仿真环境相关优化

This commit is contained in:
cbs 2025-04-09 17:59:04 +08:00
parent 9b7819387e
commit f6ce6e9de6
34 changed files with 347 additions and 89 deletions

View File

@ -30,7 +30,7 @@ public class PathPlanningApiImpl implements PathPlanningApi {
public void synchronousPointToPP(PositionMapLinePathDTO relatedPathNode, String topic) { public void synchronousPointToPP(PositionMapLinePathDTO relatedPathNode, String topic) {
try { try {
mqttUtils.pub(topic, JSON.toJSONString(relatedPathNode)); mqttUtils.pub(topic, JSON.toJSONString(relatedPathNode));
log.info("同步给路径规划完成 :{}", JSON.toJSONString(relatedPathNode)); log.info("同步给路径规划完成 :{}, topic:{}", JSON.toJSONString(relatedPathNode), topic);
} catch (MqttException e) { } catch (MqttException e) {
log.info("同步点位信息给路径规划异常 :{}",e); log.info("同步点位信息给路径规划异常 :{}",e);
} }

View File

@ -213,6 +213,7 @@ public interface ErrorCodeConstants {
ErrorCode TASK_TAKE_LOCATION_HAVE_OTHER_TASK = new ErrorCode(1-002-035-108, "取货库位已经分配了其他任务"); ErrorCode TASK_TAKE_LOCATION_HAVE_OTHER_TASK = new ErrorCode(1-002-035-108, "取货库位已经分配了其他任务");
ErrorCode TASK_RELEASE_LOCATION_HAVE_OTHER_TASK = new ErrorCode(1-002-035-109, "放货库位已经分配了其他任务"); ErrorCode TASK_RELEASE_LOCATION_HAVE_OTHER_TASK = new ErrorCode(1-002-035-109, "放货库位已经分配了其他任务");
ErrorCode TASK_CREATE_FAIL = new ErrorCode(1-002-035-110, "任务创建失败:"); ErrorCode TASK_CREATE_FAIL = new ErrorCode(1-002-035-110, "任务创建失败:");
ErrorCode ROBOT_DO_TASK_FAIL = new ErrorCode(1-002-035-112, "车机反馈不能接任务");
// ========== 机器人任务明细 1-002-036-000 ========== // ========== 机器人任务明细 1-002-036-000 ==========
ErrorCode TASK_DETAIL_NOT_EXISTS = new ErrorCode(1-002-036-001, "机器人任务明细不存在"); ErrorCode TASK_DETAIL_NOT_EXISTS = new ErrorCode(1-002-036-001, "机器人任务明细不存在");
@ -231,6 +232,7 @@ public interface ErrorCodeConstants {
ErrorCode THE_LINE_LIBRARY_POINTS_ARE_NOT_LOCATED_IN_THE_SAME_AREA = new ErrorCode(1_002_038_006, "线库点位不在同一区域内"); ErrorCode THE_LINE_LIBRARY_POINTS_ARE_NOT_LOCATED_IN_THE_SAME_AREA = new ErrorCode(1_002_038_006, "线库点位不在同一区域内");
ErrorCode THERE_ARE_ALREADY_STORAGE_LOCATIONS_IN_OTHER_LINE_WAREHOUSES = new ErrorCode(1_002_038_007, "已有库位在其他线库内"); ErrorCode THERE_ARE_ALREADY_STORAGE_LOCATIONS_IN_OTHER_LINE_WAREHOUSES = new ErrorCode(1_002_038_007, "已有库位在其他线库内");
ErrorCode THERE_ARE_ALREADY_STORAGE_LOCATIONS_IN_OTHER_STORAGE_AREAS = new ErrorCode(1_002_038_008, "已有库位在其它区域内"); ErrorCode THERE_ARE_ALREADY_STORAGE_LOCATIONS_IN_OTHER_STORAGE_AREAS = new ErrorCode(1_002_038_008, "已有库位在其它区域内");
ErrorCode MAP_DOES_NOT_EXIST_AGV = new ErrorCode(1_002_038_009, "此楼层区域不存在机器人");
// ========== 机器人自动移库 1-002-039-000 ========== // ========== 机器人自动移库 1-002-039-000 ==========
ErrorCode TASK_AUTO_MOVE_NOT_EXISTS = new ErrorCode(1_002_039_001, "机器人自动移库不存在"); ErrorCode TASK_AUTO_MOVE_NOT_EXISTS = new ErrorCode(1_002_039_001, "机器人自动移库不存在");

View File

@ -1,10 +1,8 @@
package cn.iocoder.yudao.module.system.api.robot; package cn.iocoder.yudao.module.system.api.robot;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
import cn.iocoder.yudao.module.mqtt.api.common.CommonApi; import cn.iocoder.yudao.module.mqtt.api.common.CommonApi;
import cn.iocoder.yudao.module.system.api.path.vo.RobotClosePathPlantingDTO; import cn.iocoder.yudao.module.system.api.path.vo.RobotClosePathPlantingDTO;
import cn.iocoder.yudao.module.system.api.robot.dto.RobotCommandStateDTO; import cn.iocoder.yudao.module.system.api.robot.dto.RobotCommandStateDTO;
@ -12,14 +10,12 @@ import cn.iocoder.yudao.module.system.api.robot.dto.RobotCompleteTaskDTO;
import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant; import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotExecutionStateConstant; import cn.iocoder.yudao.module.system.constant.robot.RobotExecutionStateConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant; import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant;
import cn.iocoder.yudao.module.system.controller.admin.log.vo.RobotTaskDetailActionLogSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.log.RobotTaskDetailActionLogDO; import cn.iocoder.yudao.module.system.dal.dataobject.log.RobotTaskDetailActionLogDO;
import cn.iocoder.yudao.module.system.dal.dataobject.houselocation.WareHouseLocationDO; import cn.iocoder.yudao.module.system.dal.dataobject.houselocation.WareHouseLocationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.*; import cn.iocoder.yudao.module.system.dal.dataobject.robot.*;
import cn.iocoder.yudao.module.system.dal.mysql.log.RobotTaskDetailActionLogMapper; import cn.iocoder.yudao.module.system.dal.mysql.log.RobotTaskDetailActionLogMapper;
import cn.iocoder.yudao.module.system.dal.mysql.cycle.TaskCycleMapper; import cn.iocoder.yudao.module.system.dal.mysql.cycle.TaskCycleMapper;
import cn.iocoder.yudao.module.system.dal.mysql.houselocation.WareHouseLocationMapper; import cn.iocoder.yudao.module.system.dal.mysql.houselocation.WareHouseLocationMapper;
import cn.iocoder.yudao.module.system.dal.mysql.information.DeviceInformationMapper;
import cn.iocoder.yudao.module.system.dal.mysql.robot.*; import cn.iocoder.yudao.module.system.dal.mysql.robot.*;
import cn.iocoder.yudao.module.system.enums.common.ZeroOneEnum; import cn.iocoder.yudao.module.system.enums.common.ZeroOneEnum;
import cn.iocoder.yudao.module.system.enums.path.PathIsReachEnum; import cn.iocoder.yudao.module.system.enums.path.PathIsReachEnum;
@ -35,7 +31,6 @@ import cn.iocoder.yudao.module.system.service.log.RobotTaskDetailActionLogServic
import cn.iocoder.yudao.module.system.service.path.PathPlanningService; import cn.iocoder.yudao.module.system.service.path.PathPlanningService;
import cn.iocoder.yudao.module.system.service.robot.RobotInformationService; import cn.iocoder.yudao.module.system.service.robot.RobotInformationService;
import cn.iocoder.yudao.module.system.service.robot.RobotTaskDetailService; import cn.iocoder.yudao.module.system.service.robot.RobotTaskDetailService;
import cn.iocoder.yudao.module.system.service.robot.RobotTaskService;
import cn.iocoder.yudao.module.system.service.robot.RobotWarnMsgService; import cn.iocoder.yudao.module.system.service.robot.RobotWarnMsgService;
import cn.iocoder.yudao.module.system.service.wait.MoveToWaitService; import cn.iocoder.yudao.module.system.service.wait.MoveToWaitService;
import cn.iocoder.yudao.module.system.util.redis.RedisUtil; import cn.iocoder.yudao.module.system.util.redis.RedisUtil;
@ -146,9 +141,8 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
* @param mac * @param mac
* @return * @return
*/ */
public RobotTaskDetailActionLogDO setLastLogDone(String mac) { public RobotTaskDetailActionLogDO setLastLogDone(Long orderId) {
String robotNo = robotInformationService.getRobotNoByMac(mac); return taskDetailActionLogService.setPreviousTaskDoneByOrderId(orderId);
return taskDetailActionLogService.setPreviousTaskDoneByRobotNo(robotNo);
} }
/** /**
@ -156,7 +150,7 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
*/ */
private void robotTaskDoing(RobotCompleteTaskDTO robotCompleteTaskDTO, String robotDoingActionKey) { private void robotTaskDoing(RobotCompleteTaskDTO robotCompleteTaskDTO, String robotDoingActionKey) {
String robotNo = robotInformationService.getRobotNoByMac(robotCompleteTaskDTO.getMac()); String robotNo = robotInformationService.getRobotNoByMac(robotCompleteTaskDTO.getMac());
RobotTaskDetailActionLogDO lastLog = setLastLogDone(robotCompleteTaskDTO.getMac()); RobotTaskDetailActionLogDO lastLog = setLastLogDone(robotCompleteTaskDTO.getOrderId());
if (PathTaskTypeEnum.AUTO_CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())) { if (PathTaskTypeEnum.AUTO_CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())) {
chargeDoing(robotCompleteTaskDTO, robotDoingActionKey, lastLog); chargeDoing(robotCompleteTaskDTO, robotDoingActionKey, lastLog);
@ -216,7 +210,7 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
* @param robotCompleteTaskDTO * @param robotCompleteTaskDTO
*/ */
private void robotTaskDone(RobotCompleteTaskDTO robotCompleteTaskDTO) { private void robotTaskDone(RobotCompleteTaskDTO robotCompleteTaskDTO) {
setLastLogDone(robotCompleteTaskDTO.getMac()); setLastLogDone(robotCompleteTaskDTO.getOrderId());
//todo 后面考虑下充电车机目前对充电的逻辑未定义 //todo 后面考虑下充电车机目前对充电的逻辑未定义
if (PathTaskTypeEnum.MOVE.getType().equals(robotCompleteTaskDTO.getOrderType()) if (PathTaskTypeEnum.MOVE.getType().equals(robotCompleteTaskDTO.getOrderType())
|| PathTaskTypeEnum.MOVE_TO_WAIT_STOP.getType().equals(robotCompleteTaskDTO.getOrderType()) || PathTaskTypeEnum.MOVE_TO_WAIT_STOP.getType().equals(robotCompleteTaskDTO.getOrderType())
@ -228,6 +222,7 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
} else if (PathTaskTypeEnum.TAKE_RELEASE.getType().equals(robotCompleteTaskDTO.getOrderType())) { } else if (PathTaskTypeEnum.TAKE_RELEASE.getType().equals(robotCompleteTaskDTO.getOrderType())) {
RobotTaskDetailDO robotTaskDetailDO = robotTaskDetailMapper.selectById(robotCompleteTaskDTO.getOrderId()); RobotTaskDetailDO robotTaskDetailDO = robotTaskDetailMapper.selectById(robotCompleteTaskDTO.getOrderId());
if (RobotTaskStageEnum.TAKEING.getType().equals(robotTaskDetailDO.getTaskStage())) { if (RobotTaskStageEnum.TAKEING.getType().equals(robotTaskDetailDO.getTaskStage())) {
log.info("告诉路径规划任务完成 :{}, 状态: {}",robotCompleteTaskDTO.getOrderId(),PathIsReachEnum.END_WORK.getType());
pathPlanningService.updateBehavior(String.valueOf(robotCompleteTaskDTO.getOrderId()), robotTaskDetailDO.getRobotNo() pathPlanningService.updateBehavior(String.valueOf(robotCompleteTaskDTO.getOrderId()), robotTaskDetailDO.getRobotNo()
, "", PathIsReachEnum.END_WORK.getType()); , "", PathIsReachEnum.END_WORK.getType());
} else if (RobotTaskStageEnum.RELEASEING.getType().equals(robotTaskDetailDO.getTaskStage())) { } else if (RobotTaskStageEnum.RELEASEING.getType().equals(robotTaskDetailDO.getTaskStage())) {
@ -259,7 +254,7 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
.id(robotCompleteTaskDTO.getOrderId().toString()) .id(robotCompleteTaskDTO.getOrderId().toString())
.build(); .build();
commonApi.commonMethod(closePathPlanting, PathPlanningTopicConstant.KILL_TASK); commonApi.commonMethod(closePathPlanting, PathPlanningTopicConstant.KILL_TASK);
log.info("车机上报异常, 通知PP把任务取消 :{}", robotCompleteTaskDTO.getOrderId()); log.info("通知PP把任务取消 :{}", robotCompleteTaskDTO.getOrderId());
} }
/** /**

View File

@ -18,6 +18,10 @@ public class SystemApplicationRunner implements ApplicationRunner {
@Override @Override
public void run(ApplicationArguments args) { public void run(ApplicationArguments args) {
try {
toolsService.simulationPose(); toolsService.simulationPose();
} catch (Exception e) {
log.error("同步仿真的点位信息失败 :{}",e.getMessage());
}
} }
} }

View File

@ -8,8 +8,8 @@ import javax.validation.constraints.NotNull;
@Data @Data
public class WareHouseLocationVO { public class WareHouseLocationVO {
@Schema(description = "放货类型1库位、2线库、 3区域", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") @Schema(description = "放货类型1库位、2线库、 3区域、 4:点位", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@NotNull(message = "类型1库位、2线库、 3区域)不能为空") @NotNull(message = "类型1库位、2线库、 3区域、4:点位)不能为空")
private Integer type; private Integer type;
@Schema(description = "位置", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") @Schema(description = "位置", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")

View File

@ -55,8 +55,8 @@ public class PositionMapController {
@Operation(summary = "一键急停or一键恢复地图上所有AGV") @Operation(summary = "一键急停or一键恢复地图上所有AGV")
@Parameter(name = "id", description = "编号", required = true, example = "1024") @Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:position-map:emergencyStopOrRecovery')") @PreAuthorize("@ss.hasPermission('system:position-map:emergencyStopOrRecovery')")
public CommonResult<Boolean> emergencyStopOrRecovery(@RequestParam("id") Long id) { public CommonResult<Boolean> emergencyStopOrRecovery(@RequestParam("id") Long id, @RequestParam("type") Integer type) {
positionMapService.emergencyStopOrRecovery(id); positionMapService.emergencyStopOrRecovery(id,type);
return success(true); return success(true);
} }

View File

@ -150,7 +150,7 @@ public class RobotInformationController {
} }
@PostMapping("/doTaskContinue") @PostMapping("/doTaskContinue")
@Operation(summary = "继续做任务") @Operation(summary = "恢复任务")
@PreAuthorize("@ss.hasPermission('robot:information:doTaskContinue')") @PreAuthorize("@ss.hasPermission('robot:information:doTaskContinue')")
public CommonResult<Boolean> doTaskContinue(@RequestParam("robotNo") String robotNo) { public CommonResult<Boolean> doTaskContinue(@RequestParam("robotNo") String robotNo) {
informationService.doTaskContinue(robotNo); informationService.doTaskContinue(robotNo);

View File

@ -9,12 +9,12 @@ import javax.validation.constraints.NotNull;
@Data @Data
@Schema(description = "子列表") @Schema(description = "子列表")
public class RobotTaskDetailAddVO { public class RobotTaskDetailAddVO {
@Schema(description = "任务类型1取放货、2停车、 3充电、4移动、5仅取货、6仅放货、7扫描码、8检测托盘类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") @Schema(description = "任务类型1取放货、2停车、 3充电、4移动、5仅取货、6仅放货、7扫描码、8检测托盘类型、9:移动到点位", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@NotNull(message = "任务类型1取放货、2停车、 3充电、4移动、5仅取货、6仅放货、7扫描码、8检测托盘类型)不能为空") @NotNull(message = "任务类型1取放货、2停车、 3充电、4移动、5仅取货、6仅放货、7扫描码、8检测托盘类型、9:移动到点位)不能为空")
private Integer taskType; private Integer taskType;
@Schema(description = "放货类型1库位、2线库、 3区域", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") @Schema(description = "放货类型1库位、2线库、 3区域、 4:点位", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@NotNull(message = "放货类型1库位、2线库、 3区域)不能为空") @NotNull(message = "放货类型1库位、2线库、 3区域、 4:点位)不能为空")
private Integer releaseType; private Integer releaseType;
@Schema(description = "取货类型1库位、2线库、 3区域", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @Schema(description = "取货类型1库位、2线库、 3区域", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")

View File

@ -129,4 +129,11 @@ public interface RobotTaskDetailMapper extends BaseMapperX<RobotTaskDetailDO> {
* @return * @return
*/ */
String getTaskNoByDetailId(@Param("taskDetailId") Long taskDetailId); String getTaskNoByDetailId(@Param("taskDetailId") Long taskDetailId);
/**
* 查询以下点位是否存在处理中的任务
* @param itemIds
* @return
*/
List<Long> getDoIngTaskItemIdsByItemIds(@Param("itemIds") List<Long> itemIds);
} }

View File

@ -12,9 +12,10 @@ import lombok.Getter;
public enum PathTaskTypeEnum { public enum PathTaskTypeEnum {
TAKE_RELEASE("TAKE_RELEASE","取放货"), TAKE_RELEASE("TAKE_RELEASE","取放货"),
CHARGE("CHARGE","充电任务"), CHARGE("CHARGE","充电任务"),
MOVE("MOVE","移动任务"), MOVE("MOVE","移动任务"),//移动到库位
MOVE_TO_WAIT("MOVE_TO_WAIT","移动到等待点(没任务时去等待点)"), MOVE_TO_WAIT("MOVE_TO_WAIT","移动到等待点(没任务时去等待点)"),
MOVE_TO_WAIT_STOP("MOVE_TO_WAIT_STOP","停车任务"), MOVE_TO_WAIT_STOP("MOVE_TO_WAIT_STOP","停车任务"),
MOVE_TO_POINT("MOVE_TO_POINT","移动到路径点"),
TAKE("TAKE","仅取货"), TAKE("TAKE","仅取货"),
RELEASE("RELEASE","仅放货"), RELEASE("RELEASE","仅放货"),
AUTO_CHARGE("AUTO_CHARGE","自动充电"); AUTO_CHARGE("AUTO_CHARGE","自动充电");
@ -43,6 +44,8 @@ public enum PathTaskTypeEnum {
return RELEASE.getType(); return RELEASE.getType();
}else if (RobotTaskTypeEnum.PARK.getType().equals(taskType)) { }else if (RobotTaskTypeEnum.PARK.getType().equals(taskType)) {
return MOVE_TO_WAIT_STOP.getType(); return MOVE_TO_WAIT_STOP.getType();
}else if (RobotTaskTypeEnum.MOVE_TO_POINT.getType().equals(taskType)) {
return MOVE_TO_POINT.getType();
}else { }else {
return AUTO_CHARGE.getType(); return AUTO_CHARGE.getType();
} }

View File

@ -31,7 +31,7 @@ public enum PathTaskTypeToRobotEnum {
public static String taskDetailGetType(Integer taskType) { public static String taskDetailGetType(Integer taskType) {
if (RobotTaskTypeEnum.TAKE_RELEASE.getType().equals(taskType)) { if (RobotTaskTypeEnum.TAKE_RELEASE.getType().equals(taskType)) {
return PICK_UP_GOODS.getType(); return PICK_UP_GOODS.getType();
}else if (RobotTaskTypeEnum.MOVE.getType().equals(taskType)) { }else if (RobotTaskTypeEnum.MOVE.getType().equals(taskType) || RobotTaskTypeEnum.MOVE_TO_POINT.getType().equals(taskType) ) {
return MOVE.getType(); return MOVE.getType();
}else if (RobotTaskTypeEnum.TAKE.getType().equals(taskType)) { }else if (RobotTaskTypeEnum.TAKE.getType().equals(taskType)) {
return PICK_UP_GOODS.getType(); return PICK_UP_GOODS.getType();

View File

@ -16,7 +16,8 @@ public enum RobotTaskTypeEnum {
TAKE(5),//仅取货 TAKE(5),//仅取货
RELEASE(6),//仅放货 RELEASE(6),//仅放货
SCAN(7),//扫描码 SCAN(7),//扫描码
DETECTING_TRAYS(8); //检测托盘类型 DETECTING_TRAYS(8),//检测托盘类型
MOVE_TO_POINT(9); //移动到指定点位
/** /**
* 类型 * 类型
*/ */

View File

@ -10,7 +10,9 @@ public enum RobotCommandTypeEnum {
WORK_START_CHARGE("WORK_START_CHARGE","充电"), WORK_START_CHARGE("WORK_START_CHARGE","充电"),
WORD_PICK_UP_GOODS("WORD_PICK_UP_GOODS","取货"), WORD_PICK_UP_GOODS("WORD_PICK_UP_GOODS","取货"),
WORD_DROP_OFF_GOODS("WORD_DROP_OFF_GOODS","放货"), WORD_DROP_OFF_GOODS("WORD_DROP_OFF_GOODS","放货"),
MOVE_POSE("MOVE_POSE","仿真移动点位"); MOVE_POSE("MOVE_POSE","仿真移动点位"),
EMERGENCY_STOP("EMERGENCY_STOP","急停车辆"),
RECOVERY("RECOVERY","恢复车辆");
/** /**
* 类型 * 类型
*/ */

View File

@ -63,7 +63,7 @@ public interface RobotTaskDetailActionLogService {
* @param robotNo * @param robotNo
* @return * @return
*/ */
RobotTaskDetailActionLogDO setPreviousTaskDoneByRobotNo(String robotNo); RobotTaskDetailActionLogDO setPreviousTaskDoneByOrderId(Long orderId);
/** /**
* 获取车辆的最后一条任务 * 获取车辆的最后一条任务

View File

@ -98,9 +98,9 @@ public class RobotTaskDetailActionLogServiceImpl implements RobotTaskDetailActio
} }
@Override @Override
public RobotTaskDetailActionLogDO setPreviousTaskDoneByRobotNo(String robotNo) { public RobotTaskDetailActionLogDO setPreviousTaskDoneByOrderId(Long orderId) {
RobotTaskDetailActionLogDO lastLog = taskDetailActionLogMapper.selectOne(new LambdaQueryWrapperX<RobotTaskDetailActionLogDO>() RobotTaskDetailActionLogDO lastLog = taskDetailActionLogMapper.selectOne(new LambdaQueryWrapperX<RobotTaskDetailActionLogDO>()
.eq(RobotTaskDetailActionLogDO::getRobotNo, robotNo) .eq(RobotTaskDetailActionLogDO::getTaskDetailId, orderId)
.orderByDesc(RobotTaskDetailActionLogDO::getCreateTime) .orderByDesc(RobotTaskDetailActionLogDO::getCreateTime)
.last("limit 1")); .last("limit 1"));
if (ObjectUtil.isNotEmpty(lastLog) && ObjectUtil.isEmpty(lastLog.getCommandId())) { if (ObjectUtil.isNotEmpty(lastLog) && ObjectUtil.isEmpty(lastLog.getCommandId())) {

View File

@ -44,6 +44,7 @@ import cn.iocoder.yudao.module.system.util.redis.RedisUtil;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -103,6 +104,9 @@ public class PathPlanningServiceImpl implements PathPlanningService {
@Resource @Resource
private PositionMapItemService positionMapItemService; private PositionMapItemService positionMapItemService;
@Value("${zn.is_simulation:false}")
private Boolean isSimulation;
/** /**
* 同步ware_position_map_line的点位信息 * 同步ware_position_map_line的点位信息
*/ */
@ -467,6 +471,12 @@ public class PathPlanningServiceImpl implements PathPlanningService {
*/ */
@Override @Override
public void simulationRobotPoseRequest() { public void simulationRobotPoseRequest() {
if (!isSimulation) {
log.info("非仿真环境,不同步初始点位信息");
return;
}
CommonConfigDO config = configService.getConfig(CommandConfigTypeEnum.SIMULATION_CONFIG.getType().longValue()); CommonConfigDO config = configService.getConfig(CommandConfigTypeEnum.SIMULATION_CONFIG.getType().longValue());
PositionMapDO positionMap = null; PositionMapDO positionMap = null;
if (ObjectUtil.isEmpty(config) || ObjectUtil.isEmpty(config.getConfigStr())) { if (ObjectUtil.isEmpty(config) || ObjectUtil.isEmpty(config.getConfigStr())) {

View File

@ -111,4 +111,11 @@ public interface PositionMapItemService extends IService<PositionMapItemDO> {
* @return * @return
*/ */
List<PositionMapItemDO> getPositionMapItemByMapAndType(Long id, Integer type); List<PositionMapItemDO> getPositionMapItemByMapAndType(Long id, Integer type);
/**
* 批量查询
* @param pointList
* @return
*/
List<PositionMapItemDO> getPositionMapItemByIds(List<Long> pointList);
} }

View File

@ -138,4 +138,15 @@ public class PositionMapItemServiceImpl extends ServiceImpl<PositionMapItemMappe
.eq(PositionMapItemDO::getType, type)); .eq(PositionMapItemDO::getType, type));
} }
/**
* 获取使用中的点位
* @param idList
* @return
*/
@Override
public List<PositionMapItemDO> getPositionMapItemByIds(List<Long> idList) {
return positionMapItemMapper.selectList(new LambdaQueryWrapperX<PositionMapItemDO>()
.in(PositionMapItemDO::getId, idList));
}
} }

View File

@ -94,7 +94,7 @@ public interface PositionMapService extends IService<PositionMapDO> {
* *
* @param id * @param id
*/ */
void emergencyStopOrRecovery(Long id); void emergencyStopOrRecovery(Long id,Integer type);
/** /**
* 获取所有地图 * 获取所有地图

View File

@ -5,11 +5,20 @@ import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.mqtt.api.common.CommonApi;
import cn.iocoder.yudao.module.mqtt.api.task.dto.RobotSimulationPoseDTO;
import cn.iocoder.yudao.module.system.constant.robot.RobotTopicConstant;
import cn.iocoder.yudao.module.system.controller.admin.log.vo.UserOperationLogSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapSaveReqVO; import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.information.DeviceInformationDO; import cn.iocoder.yudao.module.system.dal.dataobject.information.DeviceInformationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapDO; import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapDO;
import cn.iocoder.yudao.module.system.dal.mysql.positionmap.PositionMapMapper; import cn.iocoder.yudao.module.system.dal.mysql.positionmap.PositionMapMapper;
import cn.iocoder.yudao.module.system.enums.common.ZeroOneEnum;
import cn.iocoder.yudao.module.system.enums.robot.task.RobotCommandTypeEnum;
import cn.iocoder.yudao.module.system.service.log.UserOperationLogService;
import cn.iocoder.yudao.module.system.service.robot.RobotInformationService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -56,6 +65,15 @@ public class PositionMapServiceImpl extends ServiceImpl<PositionMapMapper, Posit
@Value("${map.file.upload-path}") @Value("${map.file.upload-path}")
private String UPLOAD_DIR; private String UPLOAD_DIR;
@Resource
private RobotInformationService informationService;
@Resource
private UserOperationLogService userOperationLogService;
@Resource
private CommonApi commonApi;
@Override @Override
public Long createPositionMap(PositionMapSaveReqVO createReqVO) { public Long createPositionMap(PositionMapSaveReqVO createReqVO) {
// 插入 // 插入
@ -300,8 +318,31 @@ public class PositionMapServiceImpl extends ServiceImpl<PositionMapMapper, Posit
@Override @Override
public void emergencyStopOrRecovery(Long id) { public void emergencyStopOrRecovery(Long id, Integer type) {
// todo 先获取当前地图上的所有AGV信息 // 先获取当前地图上的所有AGV信息
PositionMapDO positionMapDO = positionMapMapper.selectById(id);
List<String> robotNos =
informationService.getRobotByFloorAndArea(String.valueOf(positionMapDO.getFloor()), positionMapDO.getArea());
if (ObjectUtil.isEmpty(robotNos)) {
throw exception(MAP_DOES_NOT_EXIST_AGV);
}
for (String robotNo : robotNos) {
String mac = informationService.getMacByRobotNo(robotNo);
RobotSimulationPoseDTO robotSimulationPose = new RobotSimulationPoseDTO();
String str = "";
if (ZeroOneEnum.ONE.getType().equals(type)) {
robotSimulationPose.setCommandType(RobotCommandTypeEnum.EMERGENCY_STOP.getType());
str = RobotCommandTypeEnum.EMERGENCY_STOP.getMsg();
} else {
robotSimulationPose.setCommandType(RobotCommandTypeEnum.RECOVERY.getType());
str = RobotCommandTypeEnum.RECOVERY.getMsg();
}
commonApi.commonMethod(robotSimulationPose, RobotTopicConstant.ROBOT_COMMAND_TOPIC + mac);
UserOperationLogSaveReqVO operationLog = UserOperationLogSaveReqVO.builder()
.operateAction(str + robotNo)
.nickName(SecurityFrameworkUtils.getLoginUserNickname()).build();
userOperationLogService.createUserOperationLog(operationLog);
}
} }
@Override @Override

View File

@ -24,6 +24,7 @@ import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDataPoseDTO;
import cn.iocoder.yudao.module.system.api.robot.vo.RobotInformationVO; import cn.iocoder.yudao.module.system.api.robot.vo.RobotInformationVO;
import cn.iocoder.yudao.module.system.constant.path.PathPlanningChcheConstant; import cn.iocoder.yudao.module.system.constant.path.PathPlanningChcheConstant;
import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant; import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotStatusCodeConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant; import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotTopicConstant; import cn.iocoder.yudao.module.system.constant.robot.RobotTopicConstant;
import cn.iocoder.yudao.module.system.controller.admin.log.vo.UserOperationLogSaveReqVO; import cn.iocoder.yudao.module.system.controller.admin.log.vo.UserOperationLogSaveReqVO;
@ -77,6 +78,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock; import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -87,7 +89,6 @@ import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
/** /**
@ -158,6 +159,9 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
@Resource @Resource
private RedissonUtils redissonUtils; private RedissonUtils redissonUtils;
@Value("${zn.is_simulation:false}")
private Boolean isSimulation;
@Override @Override
public Long createInformation(RobotInformationSaveReqVO createReqVO) { public Long createInformation(RobotInformationSaveReqVO createReqVO) {
//判断mac地址是否重复 //判断mac地址是否重复
@ -776,7 +780,7 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
} }
/** /**
* 继续做任务 * 恢复任务
* *
* @param robotNo * @param robotNo
*/ */
@ -784,13 +788,24 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void doTaskContinue(String robotNo) { public void doTaskContinue(String robotNo) {
UserOperationLogSaveReqVO operationLog = UserOperationLogSaveReqVO.builder() UserOperationLogSaveReqVO operationLog = UserOperationLogSaveReqVO.builder()
.operateAction("继续做任务 " + robotNo) .operateAction("恢复任务 " + robotNo)
.nickName(SecurityFrameworkUtils.getLoginUserNickname()).build(); .nickName(SecurityFrameworkUtils.getLoginUserNickname()).build();
userOperationLogService.createUserOperationLog(operationLog); userOperationLogService.createUserOperationLog(operationLog);
RobotTaskDetailActionLogDO actionLog = closeTask(robotNo);
if (ObjectUtil.isEmpty(actionLog) || ActionStatusEnum.DONE.getType().equals(actionLog.getActionStatus())) { CleanAgvDTO build = CleanAgvDTO.builder().robotNo(robotNo).build();
commonApi.commonMethod(build, PathPlanningTopicConstant.CLEAN_AGV);
RobotTaskDetailActionLogDO actionLog = taskDetailActionLogService.getLastTaskByRobotNo(robotNo);
if (ObjectUtil.isEmpty(actionLog)) {
throw exception(ROBOT_LAST_TASK_NO_EXISTS); throw exception(ROBOT_LAST_TASK_NO_EXISTS);
} }
String mac = getMacByRobotNo(robotNo);
robotCloseTaskDetail(actionLog.getTaskDetailId() + "", mac, actionLog.getCommandType());
if (!isSimulation && ActionStatusEnum.DONE.getType().equals(actionLog.getActionStatus())) {
throw exception(TASK_CHECK_TASK_STATUS);
}
// RobotTaskDetailActionLogDO actionLog = closeTask(robotNo);
String key = PathPlanningChcheConstant.PATH_PLANNING_TASK + actionLog.getTaskDetailId(); String key = PathPlanningChcheConstant.PATH_PLANNING_TASK + actionLog.getTaskDetailId();
Object o = redisUtil.get(key); Object o = redisUtil.get(key);
@ -798,16 +813,32 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
throw exception(ROBOT_LAST_TASK_DELETE); throw exception(ROBOT_LAST_TASK_DELETE);
} }
RobotInformationDO robotInformationDO = informationMapper.selectOne(new LambdaQueryWrapper<RobotInformationDO>()
.eq(RobotInformationDO::getRobotNo, robotNo)
.last("limit 1"));
String taskStatusKey = RobotTaskChcheConstant.ROBOT_TASK_STATUS + robotInformationDO.getMacAddress();
Object taskStatus = redisUtil.get(taskStatusKey);
if (ObjectUtil.isEmpty(taskStatus) || !RobotStatusCodeConstant.CAN_DO_TASK.equals(Boolean.parseBoolean(String.valueOf(taskStatus)))) {
log.info("车机上报不允许接任务 :{}",robotNo);
throw exception(ROBOT_DO_TASK_FAIL);
}
TaskToPathPlanningDTO pathPlanning = JSONUtil.toBean((String) o, TaskToPathPlanningDTO.class); TaskToPathPlanningDTO pathPlanning = JSONUtil.toBean((String) o, TaskToPathPlanningDTO.class);
RLock lock = redissonUtils.getLock(RobotCacheLockEnum.ROBOT_TASK_DISTRIBUTE_LOCK.getKey()); RLock lock = redissonUtils.getLock(RobotCacheLockEnum.ROBOT_TASK_DISTRIBUTE_LOCK.getKey());
String msg = "";
if (lock.tryLock()){ if (lock.tryLock()){
try { try {
resendToPP(pathPlanning,actionLog); resendToPP(pathPlanning,actionLog);
} catch (Exception e) {
log.error("下发任务给路径规划现异常 :{}",e);
msg = ObjectUtil.isNotEmpty(e.getMessage()) ? e.getMessage(): "任务下发失败"; if (PathTaskTypeEnum.CHARGE.getType().equals(pathPlanning.getOrderType())
|| PathTaskTypeEnum.AUTO_CHARGE.getType().equals(pathPlanning.getOrderType())) {
robotInformationDO.setRobotStatus(RobotStatusEnum.CHARGE.getType());
}else {
robotInformationDO.setRobotStatus(RobotStatusEnum.DOING.getType());
}
informationMapper.updateById(robotInformationDO);
} finally { } finally {
lock.unlock(); lock.unlock();
} }
@ -816,20 +847,6 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
throw exception(REDISSON_NOT_OBTAIN_LOCK); throw exception(REDISSON_NOT_OBTAIN_LOCK);
} }
if (ObjectUtil.isNotEmpty(msg)) {
throw exception0(TASK_CHECK_EXCEPTION.getCode(), msg);
}
RobotInformationDO robotInformationDO = informationMapper.selectOne(new LambdaQueryWrapper<RobotInformationDO>()
.eq(RobotInformationDO::getRobotNo, robotNo)
.last("limit 1"));
if (PathTaskTypeEnum.CHARGE.getType().equals(pathPlanning.getOrderType())
|| PathTaskTypeEnum.AUTO_CHARGE.getType().equals(pathPlanning.getOrderType())) {
robotInformationDO.setRobotStatus(RobotStatusEnum.CHARGE.getType());
}else {
robotInformationDO.setRobotStatus(RobotStatusEnum.DOING.getType());
}
informationMapper.updateById(robotInformationDO);
} }
/** /**
@ -846,6 +863,17 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
List<TaskRobotNoLimittationAreaDTO> robotNoLimitions = Arrays.asList(taskRobotNoLimittationAreaDTO); List<TaskRobotNoLimittationAreaDTO> robotNoLimitions = Arrays.asList(taskRobotNoLimittationAreaDTO);
pathPlanning.setRobotNoLimitationAreaDTOS(robotNoLimitions); pathPlanning.setRobotNoLimitationAreaDTOS(robotNoLimitions);
if (!isSimulation) {
resendToPPData(pathPlanning,actionLog,robotInformationDO);
}
List<TaskToPathPlanningDTO> pathPlanningList = new ArrayList<>();
pathPlanningList.add(pathPlanning);
log.info("任务下发给PP :{}", JSON.toJSONString(pathPlanningList));
pathPlanningApi.synchronousLineObject(pathPlanningList, PathPlanningTopicConstant.TASK_ASSIGNMENT_REQUEST);
}
private void resendToPPData(TaskToPathPlanningDTO pathPlanning, RobotTaskDetailActionLogDO actionLog, RobotInformationDO robotInformationDO) {
if (PathTaskTypeEnum.MOVE_TO_WAIT.getType().equals(actionLog.getCommandType()) if (PathTaskTypeEnum.MOVE_TO_WAIT.getType().equals(actionLog.getCommandType())
|| PathTaskTypeEnum.MOVE_TO_WAIT_STOP.getType().equals(actionLog.getCommandType())) { || PathTaskTypeEnum.MOVE_TO_WAIT_STOP.getType().equals(actionLog.getCommandType())) {
moveToWaitTask(pathPlanning, actionLog.getRobotNo()); moveToWaitTask(pathPlanning, actionLog.getRobotNo());
@ -861,11 +889,6 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
}else if (PathTaskTypeEnum.MOVE.getType().equals(actionLog.getCommandType())) { }else if (PathTaskTypeEnum.MOVE.getType().equals(actionLog.getCommandType())) {
} }
List<TaskToPathPlanningDTO> pathPlanningList = new ArrayList<>();
pathPlanningList.add(pathPlanning);
log.info("任务下发给PP :{}", JSON.toJSONString(pathPlanningList));
pathPlanningApi.synchronousLineObject(pathPlanningList, PathPlanningTopicConstant.TASK_ASSIGNMENT_REQUEST);
} }
/** /**

View File

@ -87,4 +87,11 @@ public interface RobotTaskDetailService {
* @return * @return
*/ */
String getTaskNoByDetailId(Long orderId); String getTaskNoByDetailId(Long orderId);
/**
*
* @param pointList
* @return
*/
List<Long> getDoIngTaskItemIdsByItemIds(List<Long> pointList);
} }

View File

@ -173,4 +173,9 @@ public class RobotTaskDetailServiceImpl implements RobotTaskDetailService {
public String getTaskNoByDetailId(Long taskDetailId) { public String getTaskNoByDetailId(Long taskDetailId) {
return taskDetailMapper.getTaskNoByDetailId(taskDetailId); return taskDetailMapper.getTaskNoByDetailId(taskDetailId);
} }
@Override
public List<Long> getDoIngTaskItemIdsByItemIds(List<Long> pointList) {
return taskDetailMapper.getDoIngTaskItemIdsByItemIds(pointList);
}
} }

View File

@ -19,6 +19,7 @@ import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant; import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotTopicConstant; import cn.iocoder.yudao.module.system.constant.robot.RobotTopicConstant;
import cn.iocoder.yudao.module.system.controller.admin.log.vo.UserOperationLogSaveReqVO; import cn.iocoder.yudao.module.system.controller.admin.log.vo.UserOperationLogSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapItemSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.detail.RobotTaskDetailLogResoVO; import cn.iocoder.yudao.module.system.controller.admin.robot.detail.RobotTaskDetailLogResoVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.detail.RobotTaskDetailLogVO; import cn.iocoder.yudao.module.system.controller.admin.robot.detail.RobotTaskDetailLogVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.task.TaskAssignDTO; import cn.iocoder.yudao.module.system.controller.admin.robot.task.TaskAssignDTO;
@ -29,6 +30,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.houselane.WareHouseLaneDO;
import cn.iocoder.yudao.module.system.dal.dataobject.houselocation.WareHouseLocationDO; import cn.iocoder.yudao.module.system.dal.dataobject.houselocation.WareHouseLocationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.information.DeviceInformationDO; import cn.iocoder.yudao.module.system.dal.dataobject.information.DeviceInformationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.log.RobotTaskDetailActionLogDO; import cn.iocoder.yudao.module.system.dal.dataobject.log.RobotTaskDetailActionLogDO;
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapItemDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotChargeLogDO; import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotChargeLogDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO; 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.RobotTaskDO;
@ -54,7 +56,9 @@ import cn.iocoder.yudao.module.system.enums.robot.task.RobotCommandTypeEnum;
import cn.iocoder.yudao.module.system.enums.robot.task.RobotTaskStageEnum; import cn.iocoder.yudao.module.system.enums.robot.task.RobotTaskStageEnum;
import cn.iocoder.yudao.module.system.enums.wait.WaitStatusEnum; import cn.iocoder.yudao.module.system.enums.wait.WaitStatusEnum;
import cn.iocoder.yudao.module.system.service.information.DeviceInformationService; import cn.iocoder.yudao.module.system.service.information.DeviceInformationService;
import cn.iocoder.yudao.module.system.service.log.RobotTaskDetailActionLogService;
import cn.iocoder.yudao.module.system.service.log.UserOperationLogService; import cn.iocoder.yudao.module.system.service.log.UserOperationLogService;
import cn.iocoder.yudao.module.system.service.positionmap.PositionMapItemService;
import cn.iocoder.yudao.module.system.service.wait.MoveToWaitService; import cn.iocoder.yudao.module.system.service.wait.MoveToWaitService;
import cn.iocoder.yudao.module.system.util.redis.RedisUtil; import cn.iocoder.yudao.module.system.util.redis.RedisUtil;
import cn.iocoder.yudao.module.system.util.redis.RedissonUtils; import cn.iocoder.yudao.module.system.util.redis.RedissonUtils;
@ -64,6 +68,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock; import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -163,6 +168,12 @@ public class RobotTaskServiceImpl extends ServiceImpl<RobotTaskMapper, RobotTask
@Resource @Resource
private RobotTaskDetailActionLogMapper taskDetailActionLogMapper; private RobotTaskDetailActionLogMapper taskDetailActionLogMapper;
@Resource
private PositionMapItemService positionMapItemService;
@Resource
private RobotTaskDetailActionLogService taskDetailActionLogService;
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Long createTask(RobotTaskSaveReqVO createReqVO) throws InterruptedException { public Long createTask(RobotTaskSaveReqVO createReqVO) throws InterruptedException {
@ -242,6 +253,44 @@ public class RobotTaskServiceImpl extends ServiceImpl<RobotTaskMapper, RobotTask
} }
} }
//移动点位是否为空闲/重复 处理中的任务
List<Long> pointList = new ArrayList<>();
for (RobotTaskDetailAddVO robotTaskDetail : createReqVO.getTaskDetailList()) {
if (!RobotTaskTypeEnum.MOVE_TO_POINT.getType().equals(robotTaskDetail.getTaskType())) {
continue;
}
if (pointList.contains(robotTaskDetail.getReleaseId())) {
PositionMapItemDO positionMapItem = positionMapItemService.getPositionMapItem(robotTaskDetail.getReleaseId());
throw exception0(TASK_CHECK_EXCEPTION.getCode(), "以下移动的点位重复 " + positionMapItem.getSortNum(), positionMapItem.getSortNum());
}
pointList.add(robotTaskDetail.getReleaseId());
}
if (ObjectUtil.isNotEmpty(pointList)) {
List<PositionMapItemDO> positionMapItemList = positionMapItemService.getPositionMapItemByIds(pointList);
List<Long> list = positionMapItemList.stream()
.filter(v -> ZeroOneEnum.ONE.getType().equals(v.getUseStatus()))
.map(PositionMapItemDO::getSortNum)
.collect(Collectors.toList());
if (ObjectUtil.isNotEmpty(list)) {
String join = StringUtils.join(list, ",");
throw exception0(TASK_CHECK_EXCEPTION.getCode(), "以下移动的点位非空闲 " + join, join);
}
List<Long> doingTaskItemIds = robotTaskDetailService.getDoIngTaskItemIdsByItemIds(pointList);
if (ObjectUtil.isEmpty(doingTaskItemIds)) {
return;
}
String sortNumStr = getSortNumStr(doingTaskItemIds);
throw exception0(TASK_CHECK_EXCEPTION.getCode(), "以下移动的点位存在处理中的任务 " + sortNumStr, sortNumStr);
}
}
public String getSortNumStr(List<Long> pointList) {
List<PositionMapItemDO> positionMapItemList = positionMapItemService.getPositionMapItemByIds(pointList);
List<Long> list = positionMapItemList.stream().map(PositionMapItemDO::getSortNum)
.collect(Collectors.toList());
return StringUtils.join(list, ",");
} }
/** /**
@ -474,6 +523,8 @@ public class RobotTaskServiceImpl extends ServiceImpl<RobotTaskMapper, RobotTask
Map<Long, String> deviceNoMap = new HashMap<>(); Map<Long, String> deviceNoMap = new HashMap<>();
Integer robotStatus = RobotStatusEnum.DOING.getType(); Integer robotStatus = RobotStatusEnum.DOING.getType();
//释放ware_position_map_item的使用状态
releaseMapItemUseStatus(taskAssignDTO.getRobotNo());
RobotChargeLogDO robotChargeLogs = null; RobotChargeLogDO robotChargeLogs = null;
String taskNo = ""; String taskNo = "";
@ -529,6 +580,26 @@ public class RobotTaskServiceImpl extends ServiceImpl<RobotTaskMapper, RobotTask
} }
/**
* 释放ware_position_map_item的使用状态
* @param robotNo
*/
private void releaseMapItemUseStatus(String robotNo) {
RobotTaskDetailActionLogDO actionLog = taskDetailActionLogService.getLastTaskByRobotNo(robotNo);
if (ObjectUtil.isEmpty(actionLog) || !PathTaskTypeEnum.MOVE_TO_POINT.getType().equals(actionLog.getCommandType())) {
return;
}
RobotTaskDetailDO robotTaskDetail = taskDetailMapper.selectById(actionLog.getTaskDetailId());
if (ObjectUtil.isEmpty(robotTaskDetail)) {
return;
}
PositionMapItemSaveReqVO positionMapItemSaveReq = new PositionMapItemSaveReqVO();
positionMapItemSaveReq.setId(robotTaskDetail.getReleaseId());
positionMapItemSaveReq.setUseStatus(ZeroOneEnum.ZERO.getType());
positionMapItemService.updatePositionMapItem(positionMapItemSaveReq);
}
/** /**
* 更新设备使用中 * 更新设备使用中
* *
@ -877,6 +948,9 @@ public class RobotTaskServiceImpl extends ServiceImpl<RobotTaskMapper, RobotTask
//暂无此功能 //暂无此功能
doDetectingTrays(robotTaskVo, locationIds, takeMapItemIds, releaseMapItemIds); doDetectingTrays(robotTaskVo, locationIds, takeMapItemIds, releaseMapItemIds);
break; break;
case MOVE_TO_POINT:
doMoveToPoint(robotTaskVo);
break;
default: default:
log.error("任务类型不存在 "); log.error("任务类型不存在 ");
throw exception0(TASK_CREATE_FAIL.getCode(), "任务类型不存在"); throw exception0(TASK_CREATE_FAIL.getCode(), "任务类型不存在");
@ -885,6 +959,16 @@ public class RobotTaskServiceImpl extends ServiceImpl<RobotTaskMapper, RobotTask
return locationIds; return locationIds;
} }
/**
* 移动到指定点位
*
* @param robotTaskVo
*/
private void doMoveToPoint(RobotTaskDetailAddVO robotTaskVo) {
}
/** /**
* 检测托盘类型 * 检测托盘类型
* *
@ -1049,6 +1133,7 @@ public class RobotTaskServiceImpl extends ServiceImpl<RobotTaskMapper, RobotTask
/** /**
* 校验放货库位的下一层是否没任务 * 校验放货库位的下一层是否没任务
*
* @param locationDO * @param locationDO
*/ */
private void checkToLocationNoneTask(WareHouseLocationDO locationDO) { private void checkToLocationNoneTask(WareHouseLocationDO locationDO) {
@ -1112,6 +1197,7 @@ public class RobotTaskServiceImpl extends ServiceImpl<RobotTaskMapper, RobotTask
/** /**
* 校验取货库位的上层是否存在未取的箱子 * 校验取货库位的上层是否存在未取的箱子
*
* @param locationDO * @param locationDO
*/ */
private void checkFromLocationNoneTask(WareHouseLocationDO locationDO) { private void checkFromLocationNoneTask(WareHouseLocationDO locationDO) {

View File

@ -435,6 +435,8 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService {
} else if (RobotTaskTypeEnum.PARK.getType().equals(taskDetailDO.getTaskType())) { } else if (RobotTaskTypeEnum.PARK.getType().equals(taskDetailDO.getTaskType())) {
pathPlanning.setWaitIds(waitIds); pathPlanning.setWaitIds(waitIds);
i++; i++;
} else if (RobotTaskTypeEnum.MOVE_TO_POINT.getType().equals(taskDetailDO.getTaskType())) {
moveToPoint(pathPlanning,taskDetailDO);
} }
if (ObjectUtil.isNotEmpty(robotDoTake) && ObjectUtil.isNotEmpty(taskDetailDO.getRobotNo()) if (ObjectUtil.isNotEmpty(robotDoTake) && ObjectUtil.isNotEmpty(taskDetailDO.getRobotNo())
@ -503,6 +505,17 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService {
} }
} }
/**
* 移动到路径点
* @param pathPlanning
* @param taskDetailDO
*/
private void moveToPoint(TaskToPathPlanningDTO pathPlanning, RobotTaskDetailDO taskDetailDO) {
pathPlanning.setReleaseLocationNumber(1l);
pathPlanning.setReleasePointId(taskDetailDO.getReleaseId());
pathPlanning.setReleaseGroupId("POINT_" + taskDetailDO.getReleaseId());
}
/** /**
* 获取能执行此任务的机器人 不能走的区域 * 获取能执行此任务的机器人 不能走的区域
* *
@ -609,13 +622,21 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService {
|| RobotTaskTypeEnum.MOVE.getType().equals(detail.getTaskType()) || RobotTaskTypeEnum.MOVE.getType().equals(detail.getTaskType())
|| RobotTaskTypeEnum.TAKE.getType().equals(detail.getTaskType()) || RobotTaskTypeEnum.TAKE.getType().equals(detail.getTaskType())
|| RobotTaskTypeEnum.RELEASE.getType().equals(detail.getTaskType())) { || RobotTaskTypeEnum.RELEASE.getType().equals(detail.getTaskType())) {
if (ObjectUtil.isNotEmpty(detail.getFromLaneId())) {
laneIds.add(detail.getFromLaneId()); laneIds.add(detail.getFromLaneId());
}
if (ObjectUtil.isNotEmpty(detail.getToLaneId())) {
laneIds.add(detail.getToLaneId()); laneIds.add(detail.getToLaneId());
}
if (ObjectUtil.isNotEmpty(detail.getFromMapItemId())) {
mapIds.add(detail.getFromMapItemId()); mapIds.add(detail.getFromMapItemId());
}
if (ObjectUtil.isNotEmpty(detail.getToMapItemId())) {
mapIds.add(detail.getToMapItemId()); mapIds.add(detail.getToMapItemId());
} }
} }
} }
}
//过滤处理中的, 不能分配的任务; //过滤处理中的, 不能分配的任务;
List<RobotTaskDetailDO> detailDOS = taskDetailDOS.stream() List<RobotTaskDetailDO> detailDOS = taskDetailDOS.stream()

View File

@ -30,6 +30,7 @@ import cn.iocoder.yudao.module.system.service.positionmap.PositionMapItemService
import cn.iocoder.yudao.module.system.service.positionmap.PositionMapService; import cn.iocoder.yudao.module.system.service.positionmap.PositionMapService;
import cn.iocoder.yudao.module.system.service.robot.RobotInformationService; import cn.iocoder.yudao.module.system.service.robot.RobotInformationService;
import cn.iocoder.yudao.module.system.service.robot.RobotWarnMsgService; import cn.iocoder.yudao.module.system.service.robot.RobotWarnMsgService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -216,7 +217,7 @@ public class ToolsServiceImpl implements ToolsService {
} }
List<PositionMapItemDO> itemDOList = new ArrayList<>(); List<PositionMapItemDO> itemDOList = new ArrayList<>();
List<PositionMapItemDO> items = positionMapItemService.getPositionMapItemByMapAndType(positionMap.getId(), PositionMapItemEnum.WAIT.getType()); List<PositionMapItemDO> items = positionMapItemService.getPositionMapItemByMapAndType(positionMap.getId(), PositionMapItemEnum.STOP.getType());
if (ObjectUtil.isEmpty(items) || items.size() < robots.size()) { if (ObjectUtil.isEmpty(items) || items.size() < robots.size()) {
List<PositionMapItemDO> itemPoses = positionMapItemService.getPositionMapItemByMapAndType(positionMap.getId(), PositionMapItemEnum.PATH.getType()); List<PositionMapItemDO> itemPoses = positionMapItemService.getPositionMapItemByMapAndType(positionMap.getId(), PositionMapItemEnum.PATH.getType());
itemDOList.addAll(itemPoses); itemDOList.addAll(itemPoses);
@ -224,7 +225,6 @@ public class ToolsServiceImpl implements ToolsService {
itemDOList = items; itemDOList = items;
} }
int i = 0; int i = 0;
for (RobotInformationDO robot : robots) { for (RobotInformationDO robot : robots) {
RobotSimulationPoseDataDTO poseData = new RobotSimulationPoseDataDTO(); RobotSimulationPoseDataDTO poseData = new RobotSimulationPoseDataDTO();
@ -239,7 +239,7 @@ public class ToolsServiceImpl implements ToolsService {
simulationPoseDTO.setPose2d(poseData); simulationPoseDTO.setPose2d(poseData);
simulationPoseDTO.setCommandType(RobotCommandTypeEnum.MOVE_POSE.getType()); simulationPoseDTO.setCommandType(RobotCommandTypeEnum.MOVE_POSE.getType());
commonApi.commonMethod(simulationPoseDTO, RobotTopicConstant.ROBOT_COMMAND_TOPIC + robot.getMacAddress()); commonApi.commonMethod(simulationPoseDTO, RobotTopicConstant.ROBOT_COMMAND_TOPIC + robot.getMacAddress());
log.info("仿真环境发送机器人默认点位信息"); log.info("仿真环境发送机器人默认点位信息 {}", JSON.toJSONString(poseData));
i++; i++;
} }
} }

View File

@ -191,7 +191,7 @@ zn:
robot_position_cache_time: 10 #机器人上报点位存储时间(秒) robot_position_cache_time: 10 #机器人上报点位存储时间(秒)
cycle_do_auto_move: true #存在循环的任务,是否开启自动移库. true:存在循环任务,开启自动移库; false有循环任务不自动移库 cycle_do_auto_move: true #存在循环的任务,是否开启自动移库. true:存在循环任务,开启自动移库; false有循环任务不自动移库
full_electricity: 100 #机器人充满电的电量 full_electricity: 100 #机器人充满电的电量
task_need_single: false #机器人对同一线库/点位是不是只能有一台机器人做任务 (true:一个点位/线库,只有一台机器人) task_need_single: true #机器人对同一线库/点位是不是只能有一台机器人做任务 (true:一个点位/线库,只有一台机器人)
location_number_reduce: 100000000 #库位排序的差值(下发取货任务,将库位排序减去此值,然后取绝对值) location_number_reduce: 100000000 #库位排序的差值(下发取货任务,将库位排序减去此值,然后取绝对值)
robot_doing_action: # 机器人正在做的动作 robot_doing_action: # 机器人正在做的动作
action_entity_cache_time: 172800 #机器人所有动作缓存时间 8小时 action_entity_cache_time: 172800 #机器人所有动作缓存时间 8小时

View File

@ -226,7 +226,7 @@ zn:
robot_position_cache_time: 10 #机器人上报点位存储时间(秒) robot_position_cache_time: 10 #机器人上报点位存储时间(秒)
cycle_do_auto_move: true #存在循环的任务,是否开启自动移库. true:存在循环任务,开启自动移库; false有循环任务不自动移库 cycle_do_auto_move: true #存在循环的任务,是否开启自动移库. true:存在循环任务,开启自动移库; false有循环任务不自动移库
full_electricity: 100 #机器人充满电的电量 full_electricity: 100 #机器人充满电的电量
task_need_single: false #机器人对同一线库/点位是不是只能有一台机器人做任务 (true:一个点位/线库,只有一台机器人) task_need_single: true #机器人对同一线库/点位是不是只能有一台机器人做任务 (true:一个点位/线库,只有一台机器人)
location_number_reduce: 100000000 #库位排序的差值(下发取货任务,将库位排序减去此值,然后取绝对值) location_number_reduce: 100000000 #库位排序的差值(下发取货任务,将库位排序减去此值,然后取绝对值)
robot_doing_action: # 机器人正在做的动作 robot_doing_action: # 机器人正在做的动作
action_entity_cache_time: 172800 #机器人所有动作缓存时间 8小时 action_entity_cache_time: 172800 #机器人所有动作缓存时间 8小时

View File

@ -217,7 +217,7 @@ zn:
robot_position_cache_time: 10 #机器人上报点位存储时间(秒) robot_position_cache_time: 10 #机器人上报点位存储时间(秒)
cycle_do_auto_move: true #存在循环的任务,是否开启自动移库. true:存在循环任务,开启自动移库; false有循环任务不自动移库 cycle_do_auto_move: true #存在循环的任务,是否开启自动移库. true:存在循环任务,开启自动移库; false有循环任务不自动移库
full_electricity: 100 #机器人充满电的电量 full_electricity: 100 #机器人充满电的电量
task_need_single: false #机器人对同一线库/点位是不是只能有一台机器人做任务 (true:一个点位/线库,只有一台机器人) task_need_single: true #机器人对同一线库/点位是不是只能有一台机器人做任务 (true:一个点位/线库,只有一台机器人)
location_number_reduce: 100000000 #库位排序的差值(下发取货任务,将库位排序减去此值,然后取绝对值) location_number_reduce: 100000000 #库位排序的差值(下发取货任务,将库位排序减去此值,然后取绝对值)
robot_doing_action: # 机器人正在做的动作 robot_doing_action: # 机器人正在做的动作
action_entity_cache_time: 172800 #机器人所有动作缓存时间 8小时 action_entity_cache_time: 172800 #机器人所有动作缓存时间 8小时

View File

@ -766,6 +766,16 @@
area_name like concat('%', #{locationNo}, '%') area_name like concat('%', #{locationNo}, '%')
and deleted = '0' and deleted = '0'
</when> </when>
<when test="type == 4">
select
id as id,
sort_num as locationNo
from
ware_position_map_item
where
sort_num like concat('%', #{locationNo}, '%')
and deleted = '0'
</when>
</choose> </choose>
</select> </select>

View File

@ -56,6 +56,8 @@
ware_position_map_item t1 ,ware_house_location t2 ware_position_map_item t1 ,ware_house_location t2
where t1.id = t2.map_item_id where t1.id = t2.map_item_id
and t2.id = #{locationId} and t2.id = #{locationId}
and t1.deleted = '0'
and t2.deleted = '0'
</select> </select>
<select id="getAllByMapId" resultType="cn.iocoder.yudao.module.mqtt.api.path.dto.PositionMapItemSynDTO"> <select id="getAllByMapId" resultType="cn.iocoder.yudao.module.mqtt.api.path.dto.PositionMapItemSynDTO">
@ -70,7 +72,7 @@
ware_position_map_item ware_position_map_item
where where
position_map_id = #{positionMapId} position_map_id = #{positionMapId}
and type in ('1','2') and deleted = '0'
</select> </select>
<select id="selectInWaitList" <select id="selectInWaitList"

View File

@ -291,9 +291,7 @@
<if test="updateTime != null"> <if test="updateTime != null">
and update_time = #{updateTime} and update_time = #{updateTime}
</if> </if>
<if test="deleted != null"> and deleted = '0'
and deleted = #{deleted}
</if>
<if test="toward != null"> <if test="toward != null">
and toward = #{toward} and toward = #{toward}
</if> </if>

View File

@ -264,6 +264,9 @@
FROM FROM
robot_information t1 robot_information t1
LEFT JOIN robot_model t2 ON t1.robot_model_id = t2.id LEFT JOIN robot_model t2 ON t1.robot_model_id = t2.id
where
t1.deleted = '0'
and t2.deleted = '0'
</select> </select>
<select id="getListByMapId" <select id="getListByMapId"
resultType="cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO"> resultType="cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO">

View File

@ -285,6 +285,26 @@
and t2.deleted = '0' and t2.deleted = '0'
</select> </select>
<select id="getDoIngTaskItemIdsByItemIds" resultType="java.lang.Long">
select
distinct
t2.release_id
from
robot_task t1 left join robot_task_detail t2
on t1.id = t2.robot_task_id
where
t2.release_id in
<foreach collection="itemIds" item="itemId" index="index" open="(" close=")"
separator=",">
#{itemId}
</foreach>
and t1.deleted = '0'
and t2.deleted = '0'
and t1.task_status in ('0','1')
and t2.task_status in ('0','1')
and t2.task_type = '9'
</select>
<!--通过主键修改数据--> <!--通过主键修改数据-->
<update id="updateRobotDetailById"> <update id="updateRobotDetailById">