diff --git a/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/task/TaskLimitationAreaDTO.java b/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/task/TaskLimitationAreaDTO.java new file mode 100644 index 000000000..9ad8c6516 --- /dev/null +++ b/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/task/TaskLimitationAreaDTO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.mqtt.api.path.task; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 下发任务给PP,机器人不能行走的楼层和区域 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TaskLimitationAreaDTO { + + @Schema(description = "楼层", example = "20863") + private Integer floor; + + @Schema(description = "区域", example = "20863") + private String area; + +} diff --git a/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/task/TaskRobotNoLimittationAreaDTO.java b/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/task/TaskRobotNoLimittationAreaDTO.java new file mode 100644 index 000000000..ab15c20dd --- /dev/null +++ b/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/task/TaskRobotNoLimittationAreaDTO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.mqtt.api.path.task; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * 下发任务给PP,机器人不能行走的楼层和区域 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TaskRobotNoLimittationAreaDTO { + + @Schema(description = "机器人编号") + private String robotNo; + + @Schema(description = "机器人不能行走的楼层和区域") + private List limitationAreaList; +} diff --git a/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/task/TaskToPathPlanningDTO.java b/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/task/TaskToPathPlanningDTO.java index 1b2245473..e39f8b061 100644 --- a/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/task/TaskToPathPlanningDTO.java +++ b/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/task/TaskToPathPlanningDTO.java @@ -1,7 +1,10 @@ package cn.iocoder.yudao.module.mqtt.api.path.task; import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; import java.util.List; @@ -9,16 +12,43 @@ import java.util.List; * 发送任务给PP */ @Data +@Builder +@NoArgsConstructor +@AllArgsConstructor public class TaskToPathPlanningDTO { - @Schema(description = "robot_task_detail 的 id") - private String id; + @Schema(description = "robot_task_detail/robot_charge_log 的 id") + private Long id; - @Schema(description = "能执行此任务的机器人编号") - private List robotNoList; + @Schema(description = "任务类型(TASK:robot_task的任务、CHARGE:充电任务)") + private String type; //线库: LINE + 线库号 //普通库位: POINT + 点位号 - @Schema(description = "取的编号: 线库id+点位id") - private String takeId; + @Schema(description = "取货的组编号") + private String takeGroupId; + + @Schema(description = "取货任务, 组序号, 越大越先执行") + private Long takeLocationNumber; + + @Schema(description = "取货任务的终点id") + private Long takePointId; + + //线库: LINE + 线库号 + //普通库位: POINT + 点位号 + @Schema(description = "放货的组编号(可能为空)") + private String releaseGroupId; + + @Schema(description = "放货任务, 组序号, 越大越先执行(可能为空)") + private Long releaseLocationNumber; + + @Schema(description = "放货任务的终点id") + private Long releasePointId; + + @Schema(description = "优先级(不同的组编号时:越大越先执行, 相同组编号时:组序号越大的越先执行)") + private Long priority; + + @Schema(description = "能执行此任务的机器人编号, 和机器人不能行走的区域") + private List robotNoLimitationAreaDTOS; + } diff --git a/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/enums/path/TaskTypeEnum.java b/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/enums/path/TaskTypeEnum.java new file mode 100644 index 000000000..f8ee2a379 --- /dev/null +++ b/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/enums/path/TaskTypeEnum.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.mqtt.enums.path; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + *TaskToPathPlanningDTO的type + */ +@Getter +@AllArgsConstructor +public enum TaskTypeEnum { + TASK("TASK"), // 客户下发的任务 robot_task_detail的数据 + CHARGE("CHARGE"), // 充电 + ; + + private final String type; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/constant/path/PathPlanningTopicConstant.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/constant/path/PathPlanningTopicConstant.java index e122d643e..2c7f91ad1 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/constant/path/PathPlanningTopicConstant.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/constant/path/PathPlanningTopicConstant.java @@ -45,6 +45,10 @@ public class PathPlanningTopicConstant { */ public static String UPDATE_MAP_NODE = "UPDATE_MAP_NODE"; + /** + * 下发任务给给PP + */ + public static String SEND_TASK_TO_PP = "SEND_TASK_TO_PP"; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/path/PathPlanningController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/path/PathPlanningController.java index 46d82c249..c70e4fa44 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/path/PathPlanningController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/path/PathPlanningController.java @@ -59,7 +59,7 @@ public class PathPlanningController { return success("同步完成"); } - @PostMapping("/all/item") + @PostMapping("/item/all") @Operation(summary = "同步ware_position_map_item的点位信息") @PreAuthorize("@ss.hasPermission('robot:information:synchronousItem')") public CommonResult synchronousAllItem(@RequestBody PositionMapSaveReqVO positionMapSaveReqVO) { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotInformationPageRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotInformationPageRespVO.java index a8b69cf22..38f7bd11f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotInformationPageRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotInformationPageRespVO.java @@ -40,8 +40,8 @@ public class RobotInformationPageRespVO { @ExcelProperty("在线状态/离线状态(0:离线、1:在线)") private Integer onlineStatus = 0; - @Schema(description = "车机状态(0:空闲、1:锁定、2:异常)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - @ExcelProperty("车机状态(0:空闲、1:锁定、2:异常)") + @Schema(description = "车机状态(0:锁定、 1:空闲、、2:异常)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("车机状态(0:锁定、 1:空闲、、2:异常)") private Integer robotEssenceStatus = 0; @Schema(description = "任务状态(0:待命中、1:处理中、2:充电中)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotInformationRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotInformationRespVO.java index 1c4ae90bc..354d70d15 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotInformationRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotInformationRespVO.java @@ -70,5 +70,12 @@ public class RobotInformationRespVO { @ExcelProperty("是否自动充电(0:手动充电,1:自动充电)") private Integer chargeType; + @Schema(description = "楼层") + @ExcelProperty("楼层") + public String floor; + + @Schema(description = "区域") + @ExcelProperty("区域") + public String area; } \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailAddVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailAddVO.java index 3fde6a450..c8cc6a35d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailAddVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailAddVO.java @@ -43,9 +43,6 @@ public class RobotTaskDetailAddVO { @Schema(description = "放货线库id") private Long toLaneId; - @Schema(description = "取货库位的排序的位置,越大越优先堆放") - private Long locationNumber; - @Schema(description = "计算后的来源库位编号(前端不用传此字段)") private String fromLocationNo; @Schema(description = "计算后的来源库位id(前端不用传此字段)") @@ -63,6 +60,18 @@ public class RobotTaskDetailAddVO { @Schema(description = "优先级(前端不用传此字段)") private Long priority; + @Schema(description = "取货库位的排序") + private Long fromLocationNumber; + + @Schema(description = "放货库位的排序") + private Long toLocationNumber; + + @Schema(description = "取货库位ware_position_map的id") + private Long fromMapId; + + @Schema(description = "放货库位ware_position_map的id") + private Long toMapId; + public Long getPriority() { if (ObjectUtil.isEmpty(priority)) { priority = 0l; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailPageReqVO.java index 06c1c9684..523f08dda 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailPageReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailPageReqVO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.system.controller.admin.robot.vo; +import com.alibaba.excel.annotation.ExcelProperty; import lombok.*; import io.swagger.v3.oas.annotations.media.Schema; import cn.iocoder.yudao.framework.common.pojo.PageParam; @@ -52,9 +53,6 @@ public class RobotTaskDetailPageReqVO extends PageParam { @Schema(description = "放货线库id") private Long toLaneId; - @Schema(description = "取货库位的排序的位置,越大越优先堆放") - private Long locationNumber; - @Schema(description = "任务状态(0:未开始、1:执行中、2:已完成、3:已取消)", example = "1") private Integer taskStatus; @@ -83,4 +81,16 @@ public class RobotTaskDetailPageReqVO extends PageParam { private Integer needLock; @Schema(description = "所选车辆电量(充电模式)") private Integer electricity; + + @Schema(description = "取货库位的排序") + private Long fromLocationNumber; + + @Schema(description = "放货库位的排序") + private Long toLocationNumber; + + @Schema(description = "取货库位ware_position_map的id") + private Long fromMapId; + + @Schema(description = "放货库位ware_position_map的id") + private Long toMapId; } \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailRespVO.java index ef5e7db32..15efa78d4 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailRespVO.java @@ -86,10 +86,6 @@ public class RobotTaskDetailRespVO { @ExcelProperty("放货线库id") private Long toLaneId; - @Schema(description = "取货库位的排序的位置,越大越优先堆放") - @ExcelProperty("取货库位的排序的位置,越大越优先堆放") - private Long locationNumber; - @Schema(description = "取货层数") @ExcelProperty("取货层数") private Integer fromLocationStorey; @@ -106,4 +102,19 @@ public class RobotTaskDetailRespVO { @ExcelProperty("所选车辆电量(充电模式)") private Integer electricity; + @Schema(description = "取货库位的排序") + @ExcelProperty("取货库位的排序") + private Long fromLocationNumber; + + @Schema(description = "放货库位的排序") + @ExcelProperty("放货库位的排序") + private Long toLocationNumber; + + @Schema(description = "取货库位ware_position_map的id") + @ExcelProperty("取货库位ware_position_map的id") + private Long fromMapId; + + @Schema(description = "放货库位ware_position_map的id") + @ExcelProperty("放货库位ware_position_map的id") + private Long toMapId; } \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailSaveReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailSaveReqVO.java index 11b545391..d43a97900 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailSaveReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/vo/RobotTaskDetailSaveReqVO.java @@ -44,9 +44,6 @@ public class RobotTaskDetailSaveReqVO { @Schema(description = "放货线库id") private Long toLaneId; - @Schema(description = "取货库位的排序的位置,越大越优先堆放") - private Long locationNumber; - @Schema(description = "计算后的来源库位编号") private String fromLocationNo; @Schema(description = "计算后的来源库位id") @@ -85,4 +82,16 @@ public class RobotTaskDetailSaveReqVO { @Schema(description = "所选车辆电量(充电模式)") private Integer electricity; + @Schema(description = "取货库位的排序") + private Long fromLocationNumber; + + @Schema(description = "放货库位的排序") + private Long toLocationNumber; + + @Schema(description = "取货库位ware_position_map的id") + private Long fromMapId; + + @Schema(description = "放货库位ware_position_map的id") + private Long toMapId; + } \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/robot/RobotTaskDetailDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/robot/RobotTaskDetailDO.java index a1198dfa8..9ce9c5d76 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/robot/RobotTaskDetailDO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/robot/RobotTaskDetailDO.java @@ -68,9 +68,13 @@ public class RobotTaskDetailDO extends BaseDO { */ private Long toLaneId; /** - * 取货库位的排序的位置,越大越优先堆放 + * 取货库位的排序 */ - private Long locationNumber; + private Long fromLocationNumber; + /** + * 放货库位的排序 + */ + private Long toLocationNumber; /** * 计算后的目标库位编号 */ @@ -123,4 +127,14 @@ public class RobotTaskDetailDO extends BaseDO { * 所选车辆电量(充电模式) */ private Integer electricity; + + /** + * ware_position_map的id + */ + private Long fromMapId; + + /** + * ware_position_map的id + */ + private Long toMapId; } \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/robot/RobotTaskDetailMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/robot/RobotTaskDetailMapper.java index a772bedb4..522ef3a03 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/robot/RobotTaskDetailMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/robot/RobotTaskDetailMapper.java @@ -86,12 +86,6 @@ public interface RobotTaskDetailMapper extends BaseMapperX { void updateRobotDetailById(RobotTaskDetailDO detailDO); - /** - * 查询正在处理中的任务主表id - * @return - */ - List getDoingTaskIds(); - /** * 获取未进行的充电任务 * @return diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/information/DeviceInformationServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/information/DeviceInformationServiceImpl.java index 1eb553149..22b731a0a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/information/DeviceInformationServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/information/DeviceInformationServiceImpl.java @@ -90,6 +90,15 @@ public class DeviceInformationServiceImpl implements DeviceInformationService { public void updateInformation(DeviceInformationSaveReqVO updateReqVO) { // 校验存在 validateInformationExists(updateReqVO.getId()); + //默认图片 + if (PictureConfigEnum.DEFAULT.getType().equals(updateReqVO.getPictureConfig())) { + List deviceType = dictDataService.getDictDataListByDictType("device_type"); + DictDataDO dictDataDO = deviceType.stream() + .filter(v -> Integer.valueOf(v.getValue()).equals(updateReqVO.getDeviceType())) + .findFirst() + .orElse(new DictDataDO()); + updateReqVO.setUrl(dictDataDO.getRemark()); + } // 更新 DeviceInformationDO updateObj = BeanUtils.toBean(updateReqVO, DeviceInformationDO.class); informationMapper.updateById(updateObj); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotInformationServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotInformationServiceImpl.java index 7d0af862a..cb885e68b 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotInformationServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotInformationServiceImpl.java @@ -129,6 +129,15 @@ public class RobotInformationServiceImpl implements RobotInformationService { RobotInformationDO robotInformationDO = informationMapper.selectById(id); RobotInformationRespVO bean = BeanUtils.toBean(robotInformationDO, RobotInformationRespVO.class); setPositionMapList(bean); + String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT_SOC + bean.getMacAddress(); + Object object = redisUtil.get(pose2dKey); + RobotStatusDataPoseDTO robotStatusDataPoseDTO = JSONUtil.toBean((String) object, RobotStatusDataPoseDTO.class); + + if (ObjectUtil.isNotEmpty(object) && ObjectUtil.isNotEmpty(robotStatusDataPoseDTO)) { + bean.setElectricity(robotStatusDataPoseDTO.getBat_soc()); + bean.setFloor(robotStatusDataPoseDTO.getFloor()); + bean.setArea(robotStatusDataPoseDTO.getArea()); + } return bean; } @@ -175,7 +184,7 @@ public class RobotInformationServiceImpl implements RobotInformationService { } if (RobotStatisticsTypeEnum.DOLOCK.getType().equals(pageReqVO.getRobotStatisticsType()) - && v.getRobotEssenceStatus().equals(1)) { + && v.getRobotEssenceStatus().equals(0)) { resultList.add(v); continue; } @@ -223,7 +232,7 @@ public class RobotInformationServiceImpl implements RobotInformationService { //设置异常 String errorLevelKey = RobotTaskChcheConstant.ROBOT_ERROR_LEVEL + v.getMacAddress(); Object errorLevel = redisUtil.get(errorLevelKey); - if (ObjectUtil.isNotEmpty(errorLevel) && Integer.valueOf(errorLevel.toString()).intValue() >= 3) { + if (ObjectUtil.isNotEmpty(errorLevel)) { v.setRobotEssenceStatus(2); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotTaskServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotTaskServiceImpl.java index 078dde3c5..8e74c240a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotTaskServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotTaskServiceImpl.java @@ -313,7 +313,8 @@ public class RobotTaskServiceImpl extends ServiceImpl locationIds) { - setToLocation(robotTaskVo,getMapIdsByRobotNo(robotTaskVo.getRobotNo()),locationIds); - locationIds.add(robotTaskVo.getToLocationId()); + // todo 停车后续停到等待点 + /*setToLocation(robotTaskVo,getMapIdsByRobotNo(robotTaskVo.getRobotNo()),locationIds); + locationIds.add(robotTaskVo.getToLocationId());*/ } /** @@ -474,6 +476,8 @@ public class RobotTaskServiceImpl extends ServiceImpl detailDongIds = robotTaskDetailMapper.getDoingTaskIds(); List montageTaskIds = robotTaskMapper.getUnDoAndDoingTaskIds(MontageTaskEnum.YES.getType(), detailDongIds); @@ -200,6 +202,8 @@ public class DistributeTasksServiceImpl implements DistributeTasksService { .map(RobotTaskDO::getId) .collect(Collectors.toList()); + log.info("完成查找主任务"); + if (ObjectUtil.isEmpty(montageTaskIds) && ObjectUtil.isEmpty(singleTaskIds)) { log.info("暂无需要处理的主任务"); return pair; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/RobotTaskAutoMoveServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/RobotTaskAutoMoveServiceImpl.java index ec26f0fb3..d5d01a9df 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/RobotTaskAutoMoveServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/RobotTaskAutoMoveServiceImpl.java @@ -384,9 +384,9 @@ public class RobotTaskAutoMoveServiceImpl implements RobotTaskAutoMoveService { List locations = new ArrayList<>(); RobotTaskDetailDO robotTaskDetail = detaiMap.getValue() .stream() - .min(Comparator.comparing(RobotTaskDetailDO::getLocationNumber)).get(); - if (ObjectUtil.isNotEmpty(robotTaskDetail) && ObjectUtil.isNotEmpty(robotTaskDetail.getLocationNumber())) { - WareHouseLocationDO location = WareHouseLocationDO.builder().locationNumber(robotTaskDetail.getLocationNumber()) + .min(Comparator.comparing(RobotTaskDetailDO::getFromLocationNumber)).get(); + if (ObjectUtil.isNotEmpty(robotTaskDetail) && ObjectUtil.isNotEmpty(robotTaskDetail.getFromLocationNumber())) { + WareHouseLocationDO location = WareHouseLocationDO.builder().locationNumber(robotTaskDetail.getFromLocationNumber()) .locationUseStatus(LocationUseStatusEnum.YES.getType()) // .locationLock(LocationLockEnum.YES.getType()) .laneId(detaiMap.getKey()).build(); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/pathplanning/RobotPathPlanningServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/pathplanning/RobotPathPlanningServiceImpl.java index c18b1c35e..e9293563a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/pathplanning/RobotPathPlanningServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/pathplanning/RobotPathPlanningServiceImpl.java @@ -1,19 +1,37 @@ package cn.iocoder.yudao.module.system.service.robot.pathplanning; import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import cn.iocoder.yudao.module.mqtt.api.path.PathPlanningApi; +import cn.iocoder.yudao.module.mqtt.api.path.task.TaskLimitationAreaDTO; +import cn.iocoder.yudao.module.mqtt.api.path.task.TaskRobotNoLimittationAreaDTO; +import cn.iocoder.yudao.module.mqtt.api.path.task.TaskToPathPlanningDTO; import cn.iocoder.yudao.module.mqtt.api.task.RobotTaskApi; +import cn.iocoder.yudao.module.mqtt.api.task.dto.Pose2ds; +import cn.iocoder.yudao.module.mqtt.api.task.dto.RobotAcceptTaskDTO; +import cn.iocoder.yudao.module.mqtt.api.task.dto.RobotAcceptTaskData; +import cn.iocoder.yudao.module.mqtt.enums.path.TaskTypeEnum; +import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant; +import cn.iocoder.yudao.module.system.constant.robot.RobotTopicConstant; +import cn.iocoder.yudao.module.system.dal.dataobject.houselocation.WareHouseLocationDO; +import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapDO; import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO; +import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDO; import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDetailDO; import cn.iocoder.yudao.module.system.dal.mysql.config.CommonConfigMapper; import cn.iocoder.yudao.module.system.dal.mysql.houselocation.WareHouseLocationMapper; import cn.iocoder.yudao.module.system.dal.mysql.positionmap.PositionMapItemMapper; +import cn.iocoder.yudao.module.system.dal.mysql.positionmap.PositionMapMapper; import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotInformationMapper; import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskDetailMapper; import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskMapper; +import cn.iocoder.yudao.module.system.enums.robot.*; import cn.iocoder.yudao.module.system.service.robot.job.DistributeTasksService; import cn.iocoder.yudao.module.system.util.redis.RedisUtil; +import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -22,7 +40,11 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.List; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; @Service @Validated @@ -61,6 +83,12 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { @Value("${zn.full_electricity:100}") private String fullElectricity; + @Value("${zn.task_need_single:true}") + private Boolean taskNeedSingle; + + @Value("${zn.location_number_reduce:100000000}") + private Long locationNumberReduce; + @Resource private CommonConfigMapper configMapper; @@ -74,6 +102,12 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { @Autowired private DistributeTasksService distributeTasksService; + @Resource + private PositionMapMapper positionMapMapper; + + @Resource + private PathPlanningApi pathPlanningApi; + /** * 下发任务给PP */ @@ -81,6 +115,7 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { @Transactional(rollbackFor = Exception.class) public void sendTaskToPP() { TenantContextHolder.setTenantId(1L); + log.info("-------开始查找车子和任务------"); Pair, List> robotAndTaskDetails = distributeTasksService.getRobotAndTaskDetails(); @@ -95,47 +130,618 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { return; } - + log.info("-------查找到车子和任务------"); + distributeTasksToPP(robots, taskDetailDOS); } + @Transactional(rollbackFor = Exception.class) + public void distributeTasksToPP(List robots, List taskDetailDOS) { + //目前一个点位/线库, 只能派一辆车去做 + taskDetailDOS = getSingleTask(taskDetailDOS); + + if (ObjectUtil.isEmpty(taskDetailDOS)) { + log.info("相同的点位/线库,目前有处理中的任务, 无法派单给PP"); + return; + } + + List pathPlanningList = new ArrayList<>(); + + Set locationIds = new HashSet<>(); + Set fromLocationIds = taskDetailDOS.stream().map(RobotTaskDetailDO::getFromLocationId).collect(Collectors.toSet()); + Set toLocationIds = taskDetailDOS.stream().map(RobotTaskDetailDO::getToLocationId).collect(Collectors.toSet()); + locationIds.addAll(fromLocationIds); + locationIds.addAll(toLocationIds); + + List locations = locationMapper.selectList(new LambdaQueryWrapperX() + .in(WareHouseLocationDO::getId, locationIds)); + + List positionMapDOS = positionMapMapper.selectList(new LambdaQueryWrapperX()); + + Map locationDOMap = + locations.stream().collect(Collectors.toMap(v -> v.getId(), Function.identity())); + + for (RobotTaskDetailDO taskDetailDO : taskDetailDOS) { + + TaskToPathPlanningDTO pathPlanning = TaskToPathPlanningDTO.builder() + .id(taskDetailDO.getId()) + .type(TaskTypeEnum.TASK.getType()) + .priority(taskDetailDO.getPriority()) + .build(); + + //能执行此任务的机器人 和 不能走的区域 + List robotNoLimitationArea = getRobotNoLimitationArea(robots, positionMapDOS, + taskDetailDO.getRobotNo()); + if (ObjectUtil.isEmpty(robotNoLimitationArea)) { + log.info("此任务明细,已经指定了机器人编号, 没有对应的机器人能执行此任务 :{}, 机器人编号:{}", taskDetailDO.getId(), taskDetailDO.getRobotNo()); + continue; + } + pathPlanning.setRobotNoLimitationAreaDTOS(robotNoLimitationArea); + + //取是线库 + if (ObjectUtil.isNotEmpty(taskDetailDO.getFromLocationId()) + && ObjectUtil.isNotEmpty(taskDetailDO.getFromLaneId())) { + + pathPlanning.setTakeGroupId("LINE_" + taskDetailDO.getFromLaneId()); + pathPlanning.setTakeLocationNumber(Math.abs(locationNumberReduce - taskDetailDO.getFromLocationNumber())); + pathPlanning.setTakePointId(locationDOMap.get(taskDetailDO.getFromLocationId()).getMapItemId()); + + } else if (ObjectUtil.isNotEmpty(taskDetailDO.getFromLocationId()) + && ObjectUtil.isEmpty(taskDetailDO.getFromLaneId())) { + //取的是普通点位 + pathPlanning.setTakeGroupId("POINT_" + taskDetailDO.getFromMapId()); + pathPlanning.setTakeLocationNumber(Math.abs(locationNumberReduce - taskDetailDO.getFromLocationNumber())); + pathPlanning.setTakePointId(locationDOMap.get(taskDetailDO.getFromLocationId()).getMapItemId()); + } + + //放是线库 + if (ObjectUtil.isNotEmpty(taskDetailDO.getToLocationId()) + && ObjectUtil.isNotEmpty(taskDetailDO.getToLaneId())) { + + pathPlanning.setReleaseGroupId("LINE_" + taskDetailDO.getToLaneId()); + pathPlanning.setReleaseLocationNumber(Math.abs(locationNumberReduce - taskDetailDO.getToLocationNumber())); + pathPlanning.setReleasePointId(locationDOMap.get(taskDetailDO.getToLocationId()).getMapItemId()); + + } else if (ObjectUtil.isNotEmpty(taskDetailDO.getToLocationId()) + && ObjectUtil.isEmpty(taskDetailDO.getToLaneId())) { + //放的是普通点位 + pathPlanning.setReleaseGroupId("POINT_" + taskDetailDO.getToMapId()); + pathPlanning.setReleaseLocationNumber(Math.abs(locationNumberReduce - taskDetailDO.getToLocationNumber())); + pathPlanning.setReleasePointId(locationDOMap.get(taskDetailDO.getToLocationId()).getMapItemId()); + } + + pathPlanningList.add(pathPlanning); + } + + if (ObjectUtil.isNotEmpty(pathPlanningList)) { + pathPlanningApi.synchronousLineObject(pathPlanningList, PathPlanningTopicConstant.SEND_TASK_TO_PP); + } + } + + /** + * 设置机器人编号及不能行走的区域 + * + * @param robots + * @param positionMapDOS + */ + private List getRobotNoLimitationArea(List robots, + List positionMapDOS, + String robotNo) { + List robotNoLimitationAreaDTOS = new ArrayList<>(); + for (RobotInformationDO robot : robots) { + + if (ObjectUtil.isNotEmpty(robotNo) && !robot.getRobotNo().equals(robotNo)) { + continue; + } + + TaskRobotNoLimittationAreaDTO robotNoLimitationAreaDTO = new TaskRobotNoLimittationAreaDTO(); + List limitationAreaList = new ArrayList<>(); + robotNoLimitationAreaDTO.setRobotNo(robot.getRobotNo()); + + for (PositionMapDO v : positionMapDOS) { + if (!robot.getFloorAreaJson().contains(v.getId())) { + TaskLimitationAreaDTO taskLimitationAreaDTO = new TaskLimitationAreaDTO(v.getFloor(), v.getArea()); + limitationAreaList.add(taskLimitationAreaDTO); + } + } + + robotNoLimitationAreaDTO.setLimitationAreaList(limitationAreaList); + robotNoLimitationAreaDTOS.add(robotNoLimitationAreaDTO); + } + return robotNoLimitationAreaDTOS; + } + + /** + * 目前一个点位/线库, 只能派一辆车去做 + * + * @param taskDetailDOS + * @return + */ + private List getSingleTask(List taskDetailDOS) { + //剔除目前正在做的线库和点位 + if (!taskNeedSingle) { + return taskDetailDOS; + } + + log.info("---------处理:一个点位/线库 只派一台车 开始-------------"); + + //不能分配任务的线库id + Set laneIds = new HashSet<>(); + //不能分配任务的点位id + Set mapIds = new HashSet<>(); + List doingTaskDetails = robotTaskDetailMapper.selectList(new LambdaQueryWrapperX() + .eq(RobotTaskDetailDO::getTaskStatus, RobotTaskDetailStatusEnum.DOING.getType())); + if (ObjectUtil.isNotEmpty(doingTaskDetails)) { + for (RobotTaskDetailDO detail : doingTaskDetails) { + if (RobotTaskTypeEnum.TAKE_RELEASE.getType().equals(detail.getTaskType()) + || RobotTaskTypeEnum.MOVE.getType().equals(detail.getTaskType()) + || RobotTaskTypeEnum.TAKE.getType().equals(detail.getTaskType()) + || RobotTaskTypeEnum.RELEASE.getType().equals(detail.getTaskType())) { + laneIds.add(detail.getFromLaneId()); + laneIds.add(detail.getToLaneId()); + mapIds.add(detail.getFromMapId()); + mapIds.add(detail.getToMapId()); + } + } + } + + //过滤处理中的, 不能分配的任务; + List detailDOS = taskDetailDOS.stream() + .filter(v -> !laneIds.contains(v.getFromLaneId()) + && !laneIds.contains(v.getToLaneId()) + && !RobotTaskTypeEnum.PARK.getType().equals(v.getTaskType()) //停车在充电的任务做 + && !RobotTaskTypeEnum.CHARGE.getType().equals(v.getTaskType()) //停车在充电的任务做 + && !mapIds.contains(v.getFromMapId()) + && !mapIds.contains(v.getToMapId())) + .collect(Collectors.toList()); + + if (ObjectUtil.isEmpty(detailDOS)) { + log.info("过滤处理中的任务对应的线库id和点位id后,任务数据为空"); + return detailDOS; + } + + //取货线库 + Map fromLaneMap = detailDOS.stream() + .filter(v -> ObjectUtil.isNotEmpty(v.getFromLaneId())) + .collect(Collectors.groupingBy(RobotTaskDetailDO::getFromLaneId, + Collectors.collectingAndThen(Collectors.minBy(Comparator.comparingLong(RobotTaskDetailDO::getFromLocationNumber)), Optional::get))); + + //放货线库 + Map toLaneMap = detailDOS.stream() + .filter(v -> ObjectUtil.isNotEmpty(v.getToLaneId())) + .collect(Collectors.groupingBy(RobotTaskDetailDO::getToLaneId, + Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingLong(RobotTaskDetailDO::getToLocationNumber)), Optional::get))); + + //取货点位 + Map fromLocationMap = detailDOS.stream() + .filter(v -> ObjectUtil.isEmpty(v.getFromLaneId()) && ObjectUtil.isNotEmpty(v.getFromMapId())) + .collect(Collectors.groupingBy(RobotTaskDetailDO::getFromMapId, + Collectors.collectingAndThen(Collectors.minBy(Comparator.comparingLong(RobotTaskDetailDO::getFromLocationNumber)), Optional::get))); + + //放货点位 + Map toLocationMap = detailDOS.stream() + .filter(v -> ObjectUtil.isEmpty(v.getToLaneId()) && ObjectUtil.isNotEmpty(v.getToMapId())) + .collect(Collectors.groupingBy(RobotTaskDetailDO::getToMapId, + Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingLong(RobotTaskDetailDO::getToLocationNumber)), Optional::get))); + + //返回的数据 + List list = new ArrayList<>(); + for (RobotTaskDetailDO v : detailDOS) { + RobotTaskDetailDO fromLane = ObjectUtil.isNotEmpty(v.getFromLaneId()) ? fromLaneMap.get(v.getFromLaneId()) : null; + RobotTaskDetailDO toLane = ObjectUtil.isNotEmpty(v.getToLaneId()) ? toLaneMap.get(v.getToLaneId()) : null; + RobotTaskDetailDO fromLocation = ObjectUtil.isNotEmpty(v.getFromMapId()) ? fromLocationMap.get(v.getFromMapId()) : null; + RobotTaskDetailDO toLocation = ObjectUtil.isNotEmpty(v.getToMapId()) ? toLocationMap.get(v.getToMapId()) : null; + + //取放模式 + if (RobotTaskTypeEnum.TAKE_RELEASE.getType().equals(v.getTaskType())) { + takeReleaseSetTask(list, v, fromLane, toLane, fromLocation, toLocation); + } else if (RobotTaskTypeEnum.MOVE.getType().equals(v.getTaskType()) + || RobotTaskTypeEnum.RELEASE.getType().equals(v.getTaskType())) { + //移动和仅放货 + moveSetTask(list, v, fromLane, toLane, fromLocation, toLocation); + } else if (RobotTaskTypeEnum.TAKE.getType().equals(v.getTaskType())) { + //仅取货 + takeSetTask(list, v, fromLane, toLane, fromLocation, toLocation); + } + } + + log.info("---------处理:一个点位/线库 只派一台车 结束-------------"); + + return list; + } + /** + * 仅取货设置任务 + * + * @param list + * @param v + * @param fromLane + * @param toLane + * @param fromLocation + * @param toLocation + */ + private void takeSetTask(List list, RobotTaskDetailDO v, RobotTaskDetailDO fromLane, + RobotTaskDetailDO toLane, RobotTaskDetailDO fromLocation, RobotTaskDetailDO toLocation) { + + if (!(ObjectUtil.isNotEmpty(fromLocation) && fromLocation.getFromLocationNumber().equals(v.getFromLocationNumber()))) { + log.info("下发任务给PP--仅取货--排序不符合 :{}", v.getId()); + return; + } + + //终点是线库 + if (ObjectUtil.isNotEmpty(v.getFromLaneId()) && ObjectUtil.isNotEmpty(fromLane) + && fromLane.getFromLocationNumber().equals(v.getFromLocationNumber())) { + list.add(v); + + //终点是普通库位 + } else if (ObjectUtil.isEmpty(v.getFromLaneId())) { + list.add(v); + } + + } + + /** + * 移动设置任务 + * + * @param list + * @param v + */ + private void moveSetTask(List list, RobotTaskDetailDO v, RobotTaskDetailDO fromLane, + RobotTaskDetailDO toLane, + RobotTaskDetailDO fromLocation, RobotTaskDetailDO toLocation) { + + if (!(ObjectUtil.isNotEmpty(toLocation) && toLocation.getToLocationNumber().equals(v.getToLocationNumber()))) { + log.info("下发任务给PP--移动任务--排序不符合 :{}", v.getId()); + return; + } + + //终点是线库 + if (ObjectUtil.isNotEmpty(v.getToLaneId()) && ObjectUtil.isNotEmpty(toLane) + && toLane.getToLocationNumber().equals(v.getToLocationNumber())) { + list.add(v); + + //终点是普通库位 + } else if (ObjectUtil.isEmpty(v.getToLaneId())) { + list.add(v); + } + } + /** + * 取放,设置任务 + * + * @param list + * @param v + */ + private void takeReleaseSetTask(List list, RobotTaskDetailDO v, RobotTaskDetailDO fromLane, RobotTaskDetailDO toLane, + RobotTaskDetailDO fromLocation, RobotTaskDetailDO toLocation) { + if (!(ObjectUtil.isNotEmpty(fromLocation) && fromLocation.getFromLocationNumber().equals(v.getFromLocationNumber()) + && ObjectUtil.isNotEmpty(toLocation) && toLocation.getToLocationNumber().equals(v.getToLocationNumber()))) { + log.info("下发任务给PP--取放任务--取/放的排序不符合 :{}", v.getId()); + return; + } + //取放都是线库 + if (ObjectUtil.isNotEmpty(v.getFromLaneId()) && ObjectUtil.isNotEmpty(v.getToLaneId()) + && ObjectUtil.isNotEmpty(fromLane) + && fromLane.getFromLocationNumber().equals(v.getFromLocationNumber()) + && ObjectUtil.isNotEmpty(toLane) + && toLane.getToLocationNumber().equals(v.getToLocationNumber())) { + list.add(v); + + //取是线库,放是点位 + } else if (ObjectUtil.isNotEmpty(v.getFromLaneId()) && ObjectUtil.isEmpty(v.getToLaneId()) + && ObjectUtil.isNotEmpty(fromLane) + && fromLane.getFromLocationNumber().equals(v.getFromLocationNumber())) { + list.add(v); + + //取是点位,放是线库 + } else if (ObjectUtil.isEmpty(v.getFromLaneId()) && ObjectUtil.isNotEmpty(v.getToLaneId()) + && ObjectUtil.isNotEmpty(toLane) + && toLane.getToLocationNumber().equals(v.getToLocationNumber())) { + list.add(v); + + //取放都是点位 + } else if (ObjectUtil.isEmpty(v.getFromLaneId()) && ObjectUtil.isEmpty(v.getToLaneId())) { + list.add(v); + } + } + + public Pair getMadAddressRobotNo(RobotTaskDetailDO taskDetailDO, List robots, + WareHouseLocationDO fromLocation, WareHouseLocationDO toLocation) { + String macAddress = ""; + String robotNo = taskDetailDO.getRobotNo(); + if (ObjectUtil.isNotEmpty(robotNo)) { + macAddress = robots.stream() + .filter(v -> v.getRobotNo().equals(taskDetailDO.getRobotNo())) + .map(RobotInformationDO::getMacAddress) + .findFirst() + .orElse(""); + } else { + RobotInformationDO robotInformationDO = robots.stream() + .filter(v -> + ObjectUtil.isNotEmpty(v.getMacAddress()) + && v.getFloorAreaJson().contains(fromLocation.getMapId()) + && v.getFloorAreaJson().contains(toLocation.getMapId())) + .findFirst() + .orElse(new RobotInformationDO()); + macAddress = robotInformationDO.getMacAddress(); + robotNo = robotInformationDO.getRobotNo(); + } + Pair pair = new ImmutablePair<>(macAddress, robotNo); + return pair; + } + /** + * 取放货 + * + * @param taskDetailDO + * @param robots + * @param robotTaskDOS + */ + @Transactional(rollbackFor = Exception.class) + public void doTakeReleaseDistribute(RobotTaskDetailDO taskDetailDO, List robots, + List robotTaskDOS, Set taskIdSet, + List updateTaskDetail, Set robotNos, + Set doingLocationIds, Map locationMp, + List taskToPathPlanningDTOS) { + + WareHouseLocationDO fromLocation = locationMp.get(taskDetailDO.getFromLocationId()); + WareHouseLocationDO toLocation = locationMp.get(taskDetailDO.getToLocationId()); + + TaskToPathPlanningDTO taskToPathPlanningDTO = new TaskToPathPlanningDTO(); + + Pair pair = getMadAddressRobotNo(taskDetailDO, robots, fromLocation, toLocation); + String macAddress = pair.getLeft(); + String robotNo = pair.getRight(); + + if (ObjectUtil.isEmpty(macAddress) || ObjectUtil.isEmpty(robotNo)) { + log.info("mac地址为空 :{}, 机器人编号 :{}", macAddress, robotNo); + return; + } + + // 取货/放货 校验有没有其他库位挡住 + Boolean fromCanMove = checkCanMove(fromLocation, doingLocationIds); + if (!fromCanMove) { + return; + } + Boolean toCanMove = checkCanMove(toLocation, doingLocationIds); + if (!toCanMove) { + return; + } + + RobotAcceptTaskDTO robotTaskDO = new RobotAcceptTaskDTO(); + robotTaskDO.setOrder_id(taskDetailDO.getId().toString()); + robotTaskDO.setOrder_type("出库");//未定 + robotTaskDO.setTopic(RobotTopicConstant.ROBOT_TASK_TOPIC + macAddress); + + //1 + RobotAcceptTaskData taskOne = new RobotAcceptTaskData(); + taskOne.setSerial("1"); + taskOne.setCommand_id(taskDetailDO.getId().toString()); + taskOne.setCommand_type(CommandTypeEnum.MOVE_POSES.getType()); + + List pose2ds = new ArrayList<>(); + Pose2ds pose2 = positionMapItemMapper.selectByLocationId(taskDetailDO.getFromLocationId()); + pose2ds.add(pose2); + taskOne.setPose2ds(pose2ds); + + //2 + RobotAcceptTaskData taskTwo = new RobotAcceptTaskData(); + taskTwo.setSerial("1"); + taskTwo.setCommand_id(taskDetailDO.getId().toString()); + taskTwo.setCommand_type(CommandTypeEnum.FORK.getType()); + taskTwo.setTarget_height(initHeight); + + //3 + RobotAcceptTaskData taskThree = new RobotAcceptTaskData(); + taskThree.setSerial("2"); + taskThree.setCommand_id(taskDetailDO.getId().toString()); + taskThree.setCommand_type(CommandTypeEnum.FORK.getType()); + taskThree.setTarget_height(scanHeight); + + //4 + RobotAcceptTaskData taskFour = new RobotAcceptTaskData(); + taskFour.setSerial("3"); + taskFour.setCommand_id(taskDetailDO.getId().toString()); + taskFour.setCommand_type(CommandTypeEnum.WAIT.getType()); + taskFour.setParm(parm); + + //5 + RobotAcceptTaskData taskFive = new RobotAcceptTaskData(); + taskFive.setSerial("4"); + taskFive.setCommand_id(taskDetailDO.getId().toString()); + taskFive.setCommand_type(CommandTypeEnum.GET_PALLET_TOPIC.getType()); + + //6 + RobotAcceptTaskData taskSix = new RobotAcceptTaskData(); + taskSix.setSerial("5"); + taskSix.setCommand_id(taskDetailDO.getId().toString()); + taskSix.setCommand_type(CommandTypeEnum.FORK.getType()); + double fromLocationTotalHeight = fromLocation.getLocationTotalHeight().doubleValue(); + taskSix.setTarget_height(fromLocationTotalHeight); + + //7 + RobotAcceptTaskData taskSeven = new RobotAcceptTaskData(); + taskSeven.setSerial("6"); + taskSeven.setCommand_id(taskDetailDO.getId().toString()); + taskSeven.setCommand_type(CommandTypeEnum.MOVE_TO_PALLET_POSE.getType()); + //8 + RobotAcceptTaskData taskEigth = new RobotAcceptTaskData(); + taskEigth.setSerial("7"); + taskEigth.setCommand_id(taskDetailDO.getId().toString()); + taskEigth.setCommand_type(CommandTypeEnum.FORK.getType()); + BigDecimal b1 = new BigDecimal(Double.toString(fromLocationTotalHeight)); + BigDecimal b2 = new BigDecimal(Double.toString(liftHeight)); + taskEigth.setTarget_height(b1.add(b2).doubleValue()); + //8-2 + RobotAcceptTaskData taskEigth2 = new RobotAcceptTaskData(); + taskEigth2.setSerial("8"); + taskEigth2.setCommand_id(taskDetailDO.getId().toString()); + taskEigth2.setCommand_type(CommandTypeEnum.MOVE_POSE.getType()); + Pose2ds poseWait1 = positionMapItemMapper.selectByLocationId(100l); + taskEigth2.setPose2d(poseWait1); + + //9 + RobotAcceptTaskData taskNigth = new RobotAcceptTaskData(); + taskNigth.setSerial("9"); + taskNigth.setCommand_id(taskDetailDO.getId().toString()); + taskNigth.setCommand_type(CommandTypeEnum.MOVE_POSES.getType()); + List pose2dsNight = new ArrayList<>(); + + WareHouseLocationDO ware = WareHouseLocationDO.builder() + .laneId(-2l) + .build(); + List releaseStockList = + locationMapper.selectLocations(ware, new ArrayList<>(), new HashSet<>()); + for (WareHouseLocationDO wareHouseLocationDO : releaseStockList) { + Pose2ds pose = positionMapItemMapper.selectByLocationId(wareHouseLocationDO.getId()); + pose2dsNight.add(pose); + } + taskNigth.setPose2ds(pose2dsNight); + + //10 + RobotAcceptTaskData taskTen = new RobotAcceptTaskData(); + taskTen.setSerial("9"); + taskTen.setCommand_id(taskDetailDO.getId().toString()); + taskTen.setCommand_type(CommandTypeEnum.FORK.getType()); + taskTen.setTarget_height(moveHeight); + + //11 + RobotAcceptTaskData taskEleven = new RobotAcceptTaskData(); + taskEleven.setSerial("10"); + taskEleven.setCommand_id(taskDetailDO.getId().toString()); + taskEleven.setCommand_type(CommandTypeEnum.FORK.getType()); + + double toLocationTotalHeight = toLocation.getLocationTotalHeight().doubleValue(); + BigDecimal b3 = new BigDecimal(Double.toString(toLocationTotalHeight)); + BigDecimal b4 = new BigDecimal(Double.toString(liftHeight)); + taskEleven.setTarget_height(b3.add(b4).doubleValue()); + + //12 + RobotAcceptTaskData taskTwelve = new RobotAcceptTaskData(); + taskTwelve.setSerial("11"); + taskTwelve.setCommand_id(taskDetailDO.getId().toString()); + taskTwelve.setCommand_type(CommandTypeEnum.MOVE_POSE.getType()); + Pose2ds poseEnd = positionMapItemMapper.selectByLocationId(taskDetailDO.getToLocationId()); + taskTwelve.setPose2d(poseEnd); + + //13 + RobotAcceptTaskData taskThirteen = new RobotAcceptTaskData(); + taskThirteen.setSerial("12"); + taskThirteen.setCommand_id(taskDetailDO.getId().toString()); + taskThirteen.setCommand_type(CommandTypeEnum.FORK.getType()); + taskThirteen.setTarget_height(toLocationTotalHeight); + + //14 + RobotAcceptTaskData taskFourteen = new RobotAcceptTaskData(); + taskFourteen.setSerial("13"); + taskFourteen.setCommand_id(taskDetailDO.getId().toString()); + taskFourteen.setCommand_type(CommandTypeEnum.MOVE_POSE.getType()); + Pose2ds poseWait = positionMapItemMapper.selectByLocationId(99l); + taskFourteen.setPose2d(poseWait); + /* + Pose2ds poseWait = new Pose2ds(); + poseWait.setX(3.046); + poseWait.setY(3.219); + poseWait.setYaw(-3.141); + taskFourteen.setPose2d(poseWait);*/ + + //15 + RobotAcceptTaskData taskFifteen = new RobotAcceptTaskData(); + taskFifteen.setSerial("14"); + taskFifteen.setCommand_id(taskDetailDO.getId().toString()); + taskFifteen.setCommand_type(CommandTypeEnum.FORK.getType()); + taskFifteen.setTarget_height(initHeight); + + List data = new ArrayList<>(); + data.add(taskOne); + data.add(taskTwo); + data.add(taskThree); + data.add(taskFour); + data.add(taskFive); + data.add(taskSix); + data.add(taskSeven); + data.add(taskEigth); + data.add(taskEigth2); + data.add(taskNigth); + data.add(taskTen); + data.add(taskEleven); + data.add(taskTwelve); + data.add(taskThirteen); + data.add(taskFourteen); + data.add(taskFifteen); + robotTaskDO.setData(data); + + robotTaskDOS.add(robotTaskDO); + + final String mac = macAddress; + robots.removeIf(v -> v.getMacAddress().equals(mac)); + + taskDetailDO.setRobotNo(robotNo); + taskDetailDO.setStartTime(LocalDateTime.now()); + taskDetailDO.setTaskStatus(RobotTaskDetailStatusEnum.DOING.getType()); + updateTaskDetail.add(taskDetailDO); + + robotNos.add(robotNo); + taskIdSet.add(taskDetailDO.getRobotTaskId()); + } + /** + * 校验当前库位能否取放 + * + * @param fromLocation + * @return false : 有货,不能移动 ; true: 没货, 能移动 + */ + private Boolean checkCanMove(WareHouseLocationDO fromLocation, Set locationIds) { + Long laneId = fromLocation.getLaneId(); + if (ObjectUtil.isEmpty(laneId)) { + Set doingLocationIds = new HashSet<>(); + doingLocationIds.add(fromLocation.getId()); + List locationDOS = locationMapper.selectNeedMoveLocation(doingLocationIds); + locationDOS = locationDOS.stream() + .filter(v -> !locationIds.contains(v.getId())) + .collect(Collectors.toList()); + if (ObjectUtil.isNotEmpty(locationDOS)) { + // todo 后续记录到异常表 + log.info("普通库位--库位上有其他货物, 库位号:{} ,无法进行移动 :{}", fromLocation.getLocationNo(), locationDOS); + return false; + } + } else { + List locations = new ArrayList<>(); + WareHouseLocationDO location = WareHouseLocationDO.builder().locationNumber(fromLocation.getLocationNumber()) + .locationUseStatus(LocationUseStatusEnum.YES.getType()) + .laneId(fromLocation.getLaneId()).build(); + locations.add(location); + List wareHouseLocationDOS = locationMapper.selectLocationByList(locations); + wareHouseLocationDOS = wareHouseLocationDOS.stream() + .filter(v -> !locationIds.contains(v.getId())) + .collect(Collectors.toList()); + if (ObjectUtil.isNotEmpty(wareHouseLocationDOS)) { + // todo 后续记录到异常表 + log.info("线库-当前库位上有其他货物, 库位号:{},无法进行移动 :{}", fromLocation.getLocationNo(), wareHouseLocationDOS); + return false; + } + } - - - - - - - - - - - - - - - + locationIds.add(fromLocation.getId()); + return true; + } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/application-local.yaml b/yudao-module-system/yudao-module-system-biz/src/main/resources/application-local.yaml index 7ce727e16..009840470 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/application-local.yaml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/application-local.yaml @@ -231,3 +231,5 @@ zn: cycle_do_auto_move: true #存在循环的任务,是否开启自动移库. true:存在循环任务,开启自动移库; false:有循环任务不自动移库 full_electricity: 100 #机器人充满电的电量 robot_error_level_time: 30 #机器人异常存储时间(秒) + task_need_single: true #机器人对同一线库/点位是不是只能有一台机器人做任务 (true:一个点位/线库,只有一台机器人) + location_number_reduce: 100000000 #库位排序的差值(下发取货任务,将库位排序减去此值,然后取绝对值) diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/RobotTaskDetailMapper.xml b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/RobotTaskDetailMapper.xml index eb69a0581..d089cf89b 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/RobotTaskDetailMapper.xml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/RobotTaskDetailMapper.xml @@ -15,7 +15,10 @@ - + + + + @@ -47,7 +50,6 @@ from_location_id, from_lane_id, to_lane_id, - location_number to_location_no, to_location_id, robot_no, @@ -64,174 +66,13 @@ tenant_id, from_location_storey, to_location_storey, - priority + priority, + from_location_number, + to_location_number, + from_map_id, + to_map_id - - - - - - - - - - - insert into robot_task_detail(robot_task_id, task_type, release_type, take_type, release_id, take_id, - from_location_no, from_location_id, to_location_no, to_location_id, robot_no, - robot_action, task_status, task_stage, start_time, end_time, creator, create_time, - updater, update_time, deleted, tenant_id) - values (#{robotTaskId}, #{taskType}, #{releaseType}, #{takeType}, #{releaseId}, #{takeId}, #{fromLocationNo}, - #{fromLocationId}, #{toLocationNo}, #{toLocationId}, #{robotNo}, #{robotAction}, #{taskStatus}, - #{taskStage}, #{startTime}, #{endTime}, #{creator}, #{createTime}, #{updater}, #{updateTime}, - #{deleted}, #{tenantId}) - insert into robot_task_detail(robot_task_id, task_type, release_type, take_type, release_id, take_id, from_location_no, from_location_id, to_location_no, to_location_id, robot_no,from_location_storey, - to_location_storey,priority,from_lane_id,to_lane_id,location_number) + to_location_storey,priority,from_lane_id,to_lane_id,from_location_number,to_location_number, + from_map_id,to_map_id) values (#{entity.robotTaskId}, #{entity.taskType}, #{entity.releaseType}, #{entity.takeType}, #{entity.releaseId}, #{entity.takeId}, #{entity.fromLocationNo}, #{entity.fromLocationId}, #{entity.toLocationNo}, #{entity.toLocationId}, #{entity.robotNo}, #{entity.fromLocationStorey}, #{entity.toLocationStorey} - , #{entity.priority}, #{entity.fromLaneId}, #{entity.toLaneId}, #{entity.locationNumber}) + , #{entity.priority}, #{entity.fromLaneId}, #{entity.toLaneId}, #{entity.fromLocationNumber}, + #{entity.toLocationNumber}, #{entity.fromMapId}, #{entity.toMapId})