海康/停车/任务上报

This commit is contained in:
cbs 2025-06-10 17:09:34 +08:00
parent 2a098a2e21
commit a860cdf12b
28 changed files with 445 additions and 38 deletions

View File

@ -15,5 +15,8 @@ public class PathToRobotChangeXYArgDTO {
private List<PathToRobotChangeXYArgMovePoseDTO> pose2ds;
private PathToRobotChangeXYArgPoseDTO backPose;
private PathToRobotChangeXYArgPoseDTO cargoPose;
private Double height;
private Integer level;
private Double offsetHeight;
}

View File

@ -5,6 +5,8 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@ -21,5 +23,5 @@ public class PathToRobotChangeXYDTO {
private String robotNo;
private String taskType;
private PathToRobotChangeXYDataDTO data;
private List<PathToRobotChangeXYDataDTO> data;
}

View File

@ -130,6 +130,13 @@
<artifactId>yudao-spring-boot-starter-monitor</artifactId>
</dependency>
<dependency>
<groupId>com.hikvision.ga</groupId>
<artifactId>artemis-http-client</artifactId>
<version>1.1.3</version>
</dependency>
<!-- 三方云服务相关 -->
<dependency>
<groupId>com.xingyuv</groupId>

View File

@ -53,9 +53,9 @@ public class RobotUpdatePalletHeightApiImpl implements RobotUpdatePalletHeightAp
log.info("高度反馈 :{}", message);
TenantContextHolder.setTenantId(1L);
RobotUpdatePalletHeightDTO data = JSON.parseObject(message, RobotUpdatePalletHeightDTO.class);
if (RobotCommandTypeEnum.WORD_DROP_OFF_GOODS.getType().equals(data.getCommandType())) {
if (RobotCommandTypeEnum.WORK_DROP_OFF_GOODS.getType().equals(data.getCommandType())) {
dropOffGoods(data);
} else if (RobotCommandTypeEnum.WORD_PICK_UP_GOODS.getType().equals(data.getCommandType())) {
} else if (RobotCommandTypeEnum.WORK_PICK_UP_GOODS.getType().equals(data.getCommandType())) {
pickUpGoods(data);
}
}

View File

@ -2,8 +2,13 @@ package cn.iocoder.yudao.module.system.api.robot;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.system.api.robot.vo.RobotWorkStatusDTO;
import cn.iocoder.yudao.module.system.constant.robot.RobotExecutionStateConstant;
import cn.iocoder.yudao.module.system.controller.admin.log.vo.RobotOperationLogSaveReqVO;
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.robot.CommandTypeEnum;
import cn.iocoder.yudao.module.system.service.log.RobotOperationLogService;
import cn.iocoder.yudao.module.system.service.path.PathPlanningService;
import cn.iocoder.yudao.module.system.service.robot.RobotInformationService;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
@ -24,6 +29,9 @@ public class RobotWorkStatusApiImpl implements RobotWorkStatusApi {
@Autowired
private RobotInformationService robotInformationService;
@Resource
private PathPlanningService pathPlanningService;
@Override
public void robotWorkStatus(String message) {
log.info("作业实时行为上报: {}", message);
@ -40,6 +48,19 @@ public class RobotWorkStatusApiImpl implements RobotWorkStatusApi {
.executionState(data.getExecutionState())
.build();
operationLogService.createOperationLog(createReqVO);
if ((CommandTypeEnum.WORK_PICK_UP_GOODS_MOVE_TO_CHECK.getType().equals(data.getCommandType())
|| CommandTypeEnum.WORK_DROP_OFF_GOODS_MOVE_TO_CHECK.getType().equals(data.getCommandType()))
&& RobotExecutionStateConstant.DOING.equals(Integer.valueOf(data.getExecutionState()))) {
pathPlanningService.updateBehavior(String.valueOf(data.getOrderId()), robotNo
, data.getCommandType(), PathIsReachEnum.START_WORK.getType());
}else if ((CommandTypeEnum.WORK_PICK_UP_GOODS_MOVE_TO_CHECK.getType().equals(data.getCommandType())
|| CommandTypeEnum.WORK_DROP_OFF_GOODS_MOVE_TO_CHECK.getType().equals(data.getCommandType()))
&& RobotExecutionStateConstant.DONE.equals(Integer.valueOf(data.getExecutionState()))) {
pathPlanningService.updateBehavior(String.valueOf(data.getOrderId()), robotNo
, data.getCommandType(), PathIsReachEnum.END_WORK.getType());
}
}
}

View File

@ -8,7 +8,7 @@ public class RobotUpdatePalletHeightDTO {
private String goodsHeight;
private String mac;
private String orderId;
//作业类型 WORD_PICK_UP_GOODS/WORD_DROP_OFF_GOODS
//作业类型 WORK_PICK_UP_GOODS/WORK_DROP_OFF_GOODS
private String commandType;
private String orderType;
}

View File

@ -0,0 +1,43 @@
package cn.iocoder.yudao.module.system.config.hik;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@Slf4j
@PropertySource("classpath:application-hik.yaml")
public class ArtemisApiConstant implements CommandLineRunner {
public static String camerasApi;
public static String previewUrlsApi;
public static String replayUrlApi;
public static String operateUrlApi = "/artemis/api/video/v1/ptzs/controlling";
@Value("${resource.cameras}")
public void setCamerasApi(String a) {
camerasApi = a;
}
@Value("${video.previewUrls}")
public void setPreviewUrls(String a) {
previewUrlsApi = a;
}
@Value("${video.replayUrlApi}")
public void setReplayUrlApi(String a) {
replayUrlApi = a;
}
@Override
public void run(String... args) throws Exception {
log.info("# 【ArtemisApiConstant】 camerasApi{} #", camerasApi);
log.info("# 【ArtemisApiConstant】 previewUrlsApi{} #", previewUrlsApi);
log.info("# 【ArtemisApiConstant】 replayUrlApi{} #", replayUrlApi);
}
}

View File

@ -0,0 +1,45 @@
package cn.iocoder.yudao.module.system.config.hik;
import com.hikvision.artemis.sdk.config.ArtemisConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@Slf4j
@PropertySource("classpath:application-hik.yaml")
public class ArtemisConfigConstant implements CommandLineRunner {
public static String host;
public static String appKey;
public static String appSecret;
@Value("${isc.host}")
public void setHost(String a) {
host = a;
ArtemisConfig.host = a;
}
@Value("${isc.appKey}")
public void setAppKey(String a) {
appKey = a;
ArtemisConfig.appKey = a;
}
@Value("${isc.appSecret}")
public void setAppSecret(String a) {
appSecret = a;
ArtemisConfig.appSecret = a;
}
@Override
public void run(String... args) throws Exception {
log.info("# 【ArtemisConfigConstant】 host{} #", ArtemisConfigConstant.host);
log.info("# 【ArtemisConfigConstant】 appKey{} #", ArtemisConfigConstant.appKey);
log.info("# 【ArtemisConfigConstant】 appSecret{} #", ArtemisConfigConstant.appSecret);
}
}

View File

@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.system.controller.admin.hik;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.system.service.hik.HikService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
/**
* 工厂管理-工厂列表
*
* @author qun.xu
*/
@RestController
@RequestMapping("/system/smartfactory/hik")
@Tag(name = "海康接口")
public class HikController {
@Resource
private HikService hikService;
@GetMapping("/getCameraUrl")
@Operation(summary = "视频播放->查询播放地址")
// @PreAuthorize("@ss.hasPermission('smartfactory:camera:view')")
@PermitAll
public CommonResult<String> getCameraUrl(String cameraCode) {
String url = hikService.getPreviewUrlsApi(cameraCode, 0);
return CommonResult.success(url);
}
}

View File

@ -84,7 +84,7 @@ public class DeviceInformationController {
}
@GetMapping("/list")
@Operation(summary = "获得设备信息列表")
@Operation(summary = "获得设备信息列表,3D地图也用到")
public CommonResult<List<DeviceInformationRespVO>> getList(@Valid DeviceInformationDTO dto) {
List<DeviceInformationDO> list = informationService.getList(dto);
return success(BeanUtils.toBean(list, DeviceInformationRespVO.class));

View File

@ -29,6 +29,12 @@ public class DeviceInformationPageReqVO extends PageParam {
@Schema(description = "库位坐标y轴")
private String locationY;
@Schema(description = "实际坐标x轴")
private String actualLocationX;
@Schema(description = "实际坐标Y轴")
private String actualLocationY;
@Schema(description = "宽度")
private BigDecimal locationWide;

View File

@ -34,6 +34,14 @@ public class DeviceInformationRespVO {
@ExcelProperty("库位坐标y轴")
private String locationY;
@Schema(description = "实际坐标x轴")
@ExcelProperty("实际坐标x轴")
private String actualLocationX;
@Schema(description = "实际坐标Y轴")
@ExcelProperty("实际坐标Y轴")
private String actualLocationY;
@Schema(description = "宽度")
@ExcelProperty("宽度")
private BigDecimal locationWide;

View File

@ -29,6 +29,12 @@ public class DeviceInformationSaveReqVO {
@Schema(description = "库位坐标y轴")
private String locationY;
@Schema(description = "实际坐标x轴")
private String actualLocationX;
@Schema(description = "实际坐标Y轴")
private String actualLocationY;
@Schema(description = "宽度")
private BigDecimal locationWide;

View File

@ -29,7 +29,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 车辆摄像头信息")
@RestController
@RequestMapping("/robot/camera")
@RequestMapping("/system/robot/camera")
@Validated
public class RobotCameraController {

View File

@ -50,6 +50,8 @@ public class TaskAssignDTO {
return "机器人分配到自动充电任务 ";
}if (PathTaskTypeEnum.MOVE_TO_POINT.getType().equals(orderType)) {
return "机器人分配到移动到点位任务 ";
}if (PathTaskTypeEnum.MOVE_TO_PP_POINT.getType().equals(orderType)) {
return "路径规划分配机器人移动到点位任务 ";
}
return "未知任务";
}

View File

@ -15,10 +15,11 @@ import java.util.List;
public enum PathTaskTypeEnum {
TAKE_RELEASE("TAKE_RELEASE","取放货任务"),
CHARGE("CHARGE","充电任务"),
MOVE("MOVE","移动任务"),//移动到库位
MOVE("MOVE","移动任务(移动到库位)"),
MOVE_TO_WAIT("MOVE_TO_WAIT","移动到等待点(没任务时去等待点)"),
MOVE_TO_WAIT_STOP("MOVE_TO_WAIT_STOP","停车任务"),
MOVE_TO_POINT("MOVE_TO_POINT","移动到路径点任务"),
MOVE_TO_PP_POINT("MOVE_TO_PP_POINT","移动到路径规划指定的点位"),
TAKE("TAKE","仅取货任务"),
RELEASE("RELEASE","仅放货任务"),
AUTO_CHARGE("AUTO_CHARGE","自动充电");

View File

@ -9,6 +9,8 @@ import lombok.Getter;
@Getter
@AllArgsConstructor
public enum CommandTypeEnum {
WORK_PICK_UP_GOODS_MOVE_TO_CHECK("WORK_PICK_UP_GOODS_MOVE_TO_CHECK","取货导航到检测点"),
WORK_DROP_OFF_GOODS_MOVE_TO_CHECK("WORK_DROP_OFF_GOODS_MOVE_TO_CHECK","放货导航到检测点"),
WORK_PICK_UP_GOODS("WORK_PICK_UP_GOODS","取货控叉"),
WORK_DROP_OFF_GOODS("WORK_DROP_OFF_GOODS","放货控叉"),
MOVE_POSES("MOVE_POSES","移动"),

View File

@ -9,8 +9,8 @@ public enum RobotCommandTypeEnum {
MOVE_POSES("MOVE_POSES","移动"),
SWITCH_MAP("SWITCH_MAP","切图"),
WORK_START_CHARGE("WORK_START_CHARGE","充电"),
WORD_PICK_UP_GOODS("WORD_PICK_UP_GOODS","取货"),
WORD_DROP_OFF_GOODS("WORD_DROP_OFF_GOODS","放货"),
WORK_PICK_UP_GOODS("WORK_PICK_UP_GOODS","取货"),
WORK_DROP_OFF_GOODS("WORK_DROP_OFF_GOODS","放货"),
MOVE_POSE("MOVE_POSE","仿真移动点位"),
MODE("MODE","远遥/RCS模式切换"),
EMERGENCY_STOP("EMERGENCY_STOP","急停车辆"),

View File

@ -0,0 +1,5 @@
package cn.iocoder.yudao.module.system.service.hik;
public interface HikService {
String getPreviewUrlsApi(String cameraCode, int i);
}

View File

@ -0,0 +1,52 @@
package cn.iocoder.yudao.module.system.service.hik;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.hikvision.artemis.sdk.ArtemisHttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.util.HashMap;
import java.util.Map;
@Service
@Validated
@Slf4j
public class HikServiceImpl implements HikService{
@Override
public String getPreviewUrlsApi(String cameraCode, int streamType) {
final String previewUrlsApi ="/artemis/api/video/v2/cameras/previewURLs";
Map<String, String> path = new HashMap<String, String>(1) {
{
put("https://", previewUrlsApi);
}
};
JSONObject body = new JSONObject();
body.set("cameraIndexCode", cameraCode);
body.set("streamType", streamType);
body.set("protocol", "ws");
body.set("transmode", 1);
body.set("expand", "streamform=ps");
try {
String result = ArtemisHttpUtil
.doPostStringArtemis(path, JSONUtil.toJsonStr(body), null, null, "application/json") ;
log.info("{}监控查看预览地址返回:{}", JSONUtil.toJsonStr(body), result);
if (StringUtils.isEmpty(result)) {
// throw new ServiceException("监控查看预览地址返回为空");
System.out.println("监控查看预览地址返回为空");
}
JSONObject json = JSONUtil.parseObj(result);
String url = "";
if (json.getJSONObject("data") != null) {
url = json.getJSONObject("data").getStr("url");
}
return url;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -5,10 +5,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.api.robot.vo.RobotPathStatusDTO;
import cn.iocoder.yudao.module.system.constant.device.DeviceChcheConstant;
import cn.iocoder.yudao.module.system.controller.admin.information.dto.DeviceInformationDTO;
import cn.iocoder.yudao.module.system.controller.admin.information.dto.DeviceInformationDataJsonDTO;
import cn.iocoder.yudao.module.system.controller.admin.information.dto.MapBindDeviceInfoDTO;
import cn.iocoder.yudao.module.system.controller.admin.information.dto.StatisticsInformationDTO;
import cn.iocoder.yudao.module.system.controller.admin.information.vo.DeviceInformationPageReqVO;
@ -26,7 +24,6 @@ import cn.iocoder.yudao.module.system.enums.device.DeviceAttributeEnum;
import cn.iocoder.yudao.module.system.enums.device.DeviceStatusEnum;
import cn.iocoder.yudao.module.system.enums.device.DeviceTypeEnum;
import cn.iocoder.yudao.module.system.enums.device.PictureConfigEnum;
import cn.iocoder.yudao.module.system.enums.item.PositionMapItemEnum;
import cn.iocoder.yudao.module.system.service.config.CommonConfigService;
import cn.iocoder.yudao.module.system.service.dict.DictDataService;
import cn.iocoder.yudao.module.system.service.log.UserOperationLogService;

View File

@ -37,6 +37,7 @@ import cn.iocoder.yudao.module.system.enums.config.CommandConfigTypeEnum;
import cn.iocoder.yudao.module.system.enums.item.PositionMapItemEnum;
import cn.iocoder.yudao.module.system.enums.line.DirectionEnum;
import cn.iocoder.yudao.module.system.enums.path.PathTaskTypeEnum;
import cn.iocoder.yudao.module.system.enums.path.PathTaskTypeToRobotEnum;
import cn.iocoder.yudao.module.system.enums.path.PathTypeEnum;
import cn.iocoder.yudao.module.system.enums.robot.actionlog.ActionStatusEnum;
import cn.iocoder.yudao.module.system.enums.robot.task.RobotCommandTypeEnum;
@ -50,6 +51,7 @@ import cn.iocoder.yudao.module.system.service.robot.RobotInformationService;
import cn.iocoder.yudao.module.system.service.robot.RobotModelService;
import cn.iocoder.yudao.module.system.util.redis.RedisUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@ -57,6 +59,8 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.MathContext;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
@ -78,6 +82,8 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.PATH_PLANN
@Service
public class PathPlanningServiceImpl implements PathPlanningService {
private static final double PI = Math.PI;
@Resource
private PositionMapLineMapper positionMapLineMapper;
@ -115,6 +121,9 @@ public class PathPlanningServiceImpl implements PathPlanningService {
@Value("${zn.send_robot_init_pose:false}")
private Boolean sendRobotInitPose;
@Value("${zn.synchronous_all_map_node:500}")
private Integer synchronousAllMapNodeSize;
@Resource
private PositionChangePointBindingService positionChangePointBindingService;
@ -187,13 +196,16 @@ public class PathPlanningServiceImpl implements PathPlanningService {
if (ObjectUtil.isEmpty(positionMapItemSynDTOS)) {
continue;
}
PositionMapItemPathDTO relatedPathNode = new PositionMapItemPathDTO();
relatedPathNode.setFloor(positionMapDO.getFloor());
relatedPathNode.setArea(positionMapDO.getArea());
relatedPathNode.setType(PathTypeEnum.INIT.getType());
relatedPathNode.setControl_nodes(positionMapItemSynDTOS);
commonApi.commonMethod(relatedPathNode, PathPlanningTopicConstant.SYNCHRONOUS_ALL_MAP_NODE);
List<List<PositionMapItemSynDTO>> partition = Lists.partition(positionMapItemSynDTOS, synchronousAllMapNodeSize);
for (List<PositionMapItemSynDTO> nodes : partition) {
PositionMapItemPathDTO relatedPathNode = new PositionMapItemPathDTO();
relatedPathNode.setFloor(positionMapDO.getFloor());
relatedPathNode.setArea(positionMapDO.getArea());
relatedPathNode.setType(PathTypeEnum.INIT.getType());
relatedPathNode.setControl_nodes(nodes);
commonApi.commonMethod(relatedPathNode, PathPlanningTopicConstant.SYNCHRONOUS_ALL_MAP_NODE);
}
}
log.info("同步点位信息结束");
@ -450,11 +462,12 @@ public class PathPlanningServiceImpl implements PathPlanningService {
@Override
public void sendPosedsToRobot(String message) {
PathToRobotDTO pathRobotDTO = JSON.parseObject(message, PathToRobotDTO.class);
log.info("任务类型 :{}",pathRobotDTO.getTaskType());
String mac = robotInformationService.getMacByRobotNo(pathRobotDTO.getRobotNo());
String topic = RobotTopicConstant.ROBOT_TASK_MOVE_TOPIC + mac;
if(RobotCommandTypeEnum.SWITCH_MAP.getType().equals(pathRobotDTO.getCommandType())) {
if(RobotCommandTypeEnum.SWITCH_MAP.getType().equals(pathRobotDTO.getTaskType())) {
switchMap(pathRobotDTO,topic);
} else if (RobotCommandTypeEnum.WORD_DROP_OFF_GOODS.getType().equals(pathRobotDTO.getCommandType())) {
} else if (PathTaskTypeToRobotEnum.DROP_OFF_GOODS.getType().equals(pathRobotDTO.getTaskType())) {
wordDropOffGoods(message,topic,pathRobotDTO.getRobotNo());
} else {
commonApi.commonMethodStr(message, topic);
@ -474,9 +487,36 @@ public class PathPlanningServiceImpl implements PathPlanningService {
commonApi.commonMethodStr(message, topic);
return;
}
// PathToRobotChangeXYDTO pathToRobotChangeXY = JSON.parseObject(message, PathToRobotChangeXYDTO.class);
PathToRobotChangeXYDTO pathToRobotChangeXY = JSON.parseObject(message, PathToRobotChangeXYDTO.class);
List<PathToRobotChangeXYDataDTO> data = pathToRobotChangeXY.getData();
boolean needOffset = false;
PathToRobotChangeXYArgPoseDTO cargoPose = new PathToRobotChangeXYArgPoseDTO();
for (PathToRobotChangeXYDataDTO item : data) {
if (RobotCommandTypeEnum.WORK_DROP_OFF_GOODS.getType().equals(item.getCommandType()) && ZeroOneEnum.ONE.getType().equals(item.getIsCommandEnd())) {
needOffset = true;
cargoPose = item.getArg().getCargoPose();
}
}
if (!needOffset) {
commonApi.commonMethodStr(message, topic);
return;
}
BigDecimal robotXOffset = new BigDecimal(model.getRobotXOffset());
BigDecimal robotYOffset = new BigDecimal(model.getRobotYOffset());
double sin = Math.sin(cargoPose.getYaw());
double cos = Math.cos(cargoPose.getYaw());
BigDecimal sino = new BigDecimal(String.valueOf(sin));
BigDecimal coso = new BigDecimal(String.valueOf(cos));
BigDecimal x1 = new BigDecimal(String.valueOf(cargoPose.getX()));
BigDecimal y1 = new BigDecimal(String.valueOf(cargoPose.getY()));
BigDecimal x = (coso.multiply(robotXOffset, MathContext.DECIMAL32)).subtract(sino.multiply(robotYOffset, MathContext.DECIMAL32)).add(x1);
BigDecimal y = (sino.multiply(robotXOffset, MathContext.DECIMAL32)).add(coso.multiply(robotYOffset, MathContext.DECIMAL32)).add(y1);
cargoPose.setX(x.doubleValue());
cargoPose.setY(y.doubleValue());
log.info("转换后 :{}",JSON.toJSONString(pathToRobotChangeXY));
commonApi.commonMethodStr(JSON.toJSONString(pathToRobotChangeXY), topic);
}
/**

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.system.service.robot;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
@ -45,6 +46,7 @@ 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.common.ZeroOneEnum;
import cn.iocoder.yudao.module.system.enums.device.DeviceUseStatusEnum;
import cn.iocoder.yudao.module.system.enums.item.PositionMapItemEnum;
import cn.iocoder.yudao.module.system.enums.item.UseStatusEnum;
import cn.iocoder.yudao.module.system.enums.path.PathTaskTypeEnum;
import cn.iocoder.yudao.module.system.enums.redis.RobotCacheLockEnum;
@ -166,6 +168,15 @@ public class RobotTaskServiceImpl extends ServiceImpl<RobotTaskMapper, RobotTask
@Resource
private RobotTaskDetailActionLogMapper taskDetailActionLogMapper;
@Autowired
private RobotTaskMapper robotTaskMapper;
@Autowired
private RobotTaskDetailMapper robotTaskDetailMapper;
@Value("${zn.move-no:MOVE}")
private String moveTaskNo;
@Resource
private PositionMapItemService positionMapItemService;
@ -608,7 +619,12 @@ public class RobotTaskServiceImpl extends ServiceImpl<RobotTaskMapper, RobotTask
robotInformationMapper.updateRobotListStatus(taskAssignDTO.getRobotNo(), robotStatus, taskAssignDTO.getOrderId());
RobotTaskDO robotTaskDO = setTaskDoing(taskAssignDTO.getOrderId(), taskAssignDTO.getRobotNo(), deviceNoMap, taskAssignDTO.getWaitId());
RobotTaskDO robotTaskDO = null;
if (PathTaskTypeEnum.MOVE_TO_PP_POINT.getType().equals(taskAssignDTO.getOrderType())) {
robotTaskDO = ppCreateMove(taskAssignDTO);
} else {
robotTaskDO = setTaskDoing(taskAssignDTO.getOrderId(), taskAssignDTO.getRobotNo(), deviceNoMap, taskAssignDTO.getWaitId());
}
RobotTaskDetailActionLogSaveReqVO logOne = new RobotTaskDetailActionLogSaveReqVO();
logOne.setCommandType(taskAssignDTO.getOrderType());
@ -629,6 +645,36 @@ public class RobotTaskServiceImpl extends ServiceImpl<RobotTaskMapper, RobotTask
robotWorkingHoursStatisticsService.createFreeTime(taskAssignDTO.getRobotNo());
}
private RobotTaskDO ppCreateMove(TaskAssignDTO taskAssignDTO) {
RobotTaskDO task = new RobotTaskDO();
String incrementByKey = redisUtil.getIncrementByKey(RobotCacheLockEnum.MOVE_TASK_NO.getKey());
task.setTaskNo(moveTaskNo + DateUtils.getYearMonthDay() + incrementByKey);
task.setId(IdUtil.getSnowflakeNextId());
task.setCycleNumber(0L);
task.setRemainingCycleNumber(0L);
task.setStartTime(LocalDateTime.now());
task.setTaskStatus(RobotTaskStatusEnum.DOING.getType());
PositionMapItemDO positionMapItem = positionMapItemService.getPositionMapItem(Long.valueOf(taskAssignDTO.getWaitId()));
RobotTaskDetailDO taskDetailDO = new RobotTaskDetailDO();
taskDetailDO.setId(taskAssignDTO.getOrderId());
taskDetailDO.setRobotTaskId(task.getId());
taskDetailDO.setTaskType(RobotTaskTypeEnum.MOVE_TO_POINT.getType());
taskDetailDO.setReleaseType(ReleaseTakeEnum.TO_LOCATION.getType());
taskDetailDO.setReleaseId(Long.valueOf(taskAssignDTO.getWaitId()));
taskDetailDO.setToLocationId(Long.valueOf(taskAssignDTO.getWaitId()));
taskDetailDO.setToLocationNo( positionMapItem.getSortNum() + "");
taskDetailDO.setRobotNo(taskAssignDTO.getRobotNo());
taskDetailDO.setTaskStatus(RobotTaskDetailStatusEnum.DOING.getType());
taskDetailDO.setStartTime(LocalDateTime.now());
robotTaskMapper.insert(task);
robotTaskDetailMapper.insert(taskDetailDO);
return task;
}
/**
* 释放ware_position_map_item的使用状态
*
@ -715,7 +761,7 @@ public class RobotTaskServiceImpl extends ServiceImpl<RobotTaskMapper, RobotTask
WareHouseLocationDO location = null;
if (PathTaskTypeEnum.TAKE_RELEASE.getType().equals(taskAssignDTO.getOrderType()) ||
PathTaskTypeEnum.TAKE.getType().equals(taskAssignDTO.getOrderType())) {
take.setCommandType(RobotCommandTypeEnum.WORD_PICK_UP_GOODS.getType());
take.setCommandType(RobotCommandTypeEnum.WORK_PICK_UP_GOODS.getType());
location = locationMapper.selectById(v.getFromLocationId());
build = RobotAssignTaskArgDTO.builder()
.level(Double.valueOf(location.getLocationStorey()))
@ -723,7 +769,7 @@ public class RobotTaskServiceImpl extends ServiceImpl<RobotTaskMapper, RobotTask
.build();
take.setArg(Arrays.asList(build));
} else if (PathTaskTypeEnum.RELEASE.getType().equals(taskAssignDTO.getOrderType())) {
take.setCommandType(RobotCommandTypeEnum.WORD_DROP_OFF_GOODS.getType());
take.setCommandType(RobotCommandTypeEnum.WORK_DROP_OFF_GOODS.getType());
location = locationMapper.selectById(v.getToLocationId());
build = RobotAssignTaskArgDTO.builder()
.level(Double.valueOf(location.getLocationStorey()))

View File

@ -197,14 +197,6 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService {
return;
}
robots = robots.stream()
.filter(v -> v.getRobotStatus().equals(RobotStatusEnum.STAND_BY.getType()))
.collect(Collectors.toList());
if (ObjectUtil.isEmpty(robots)) {
log.info("------没有空闲的机器人可以去等待点-----");
return;
}
List<PositionMapItemDO> positionMapItems = positionMapItemMapper.selectList(new LambdaQueryWrapperX<PositionMapItemDO>()
.eq(PositionMapItemDO::getType, PositionMapItemEnum.STOP.getType()));
@ -213,19 +205,50 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService {
return;
}
List<String> robotNos = robots.stream().map(RobotInformationDO::getRobotNo).collect(Collectors.toList());
List<String> inStopPointRobotNos = new ArrayList<>();
for (PositionMapItemDO positionMapItem : positionMapItems) {
if (UseStatusEnum.USEING.getType().equals(positionMapItem.getUseStatus()) && ObjectUtil.isNotEmpty(positionMapItem.getRobotNo())) {
inStopPointRobotNos.add(positionMapItem.getRobotNo());
}
}
List<String> robotNos = new ArrayList<>();
Map<String,Set<Long>> robotFloorAreaJsonMap = new HashMap<>();
for (RobotInformationDO robot : robots) {
if (!RobotStatusEnum.STAND_BY.getType().equals(robot.getRobotStatus())) {
continue;
}
if (ObjectUtil.isEmpty(robot.getFloorAreaJson())) {
log.info("车辆没有能行走的区域 :{}",robot.getRobotNo());
continue;
}
if (ObjectUtil.isNotEmpty(inStopPointRobotNos) && inStopPointRobotNos.contains(robot.getRobotNo())) {
log.info("车辆已经在停车点了 :{}",robot.getRobotNo());
continue;
}
robotNos.add(robot.getRobotNo());
robotFloorAreaJsonMap.put(robot.getRobotNo(),robot.getFloorAreaJson());
}
if (ObjectUtil.isEmpty(robotNos)) {
log.info("------没有空闲的机器人可以去等待点-----");
return;
}
List<PositionMapItemDO> existMapItems = positionMapItems.stream()
.filter(v -> ObjectUtil.isNotEmpty(v.getRobotNo()) && robotNos.contains(v.getRobotNo()))
.filter(v -> ObjectUtil.isNotEmpty(v.getRobotNo())
&& robotNos.contains(v.getRobotNo())
&& robotFloorAreaJsonMap.get(v.getRobotNo()).contains(v.getPositionMapId()))
.collect(Collectors.toList());
//车辆直接分配的停车点集合
List<PositionMapItemDO> robotMapItems = new ArrayList<>();
if (ObjectUtil.isNotEmpty(existMapItems)) {
for (PositionMapItemDO positionMapItem : existMapItems) {
if (ObjectUtil.isEmpty(robots)) {
if (ObjectUtil.isEmpty(robotNos)) {
break;
}
robotNos.removeIf(v -> v.equals(positionMapItem.getRobotNo()));
@ -244,7 +267,12 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService {
if (ObjectUtil.isEmpty(robotNos)) {
break;
}
positionMapItem.setRobotNo(robotNos.get(0));
String robotNo = robotNos.get(0);
if (!robotFloorAreaJsonMap.get(robotNo).contains(positionMapItem.getPositionMapId())) {
log.info("车辆不能在此停车点 :{}, 车辆编号 :{}",positionMapItem.getSortNum(), robotNo);
continue;
}
positionMapItem.setRobotNo(robotNo);
robotNos.removeIf(v -> v.equals(positionMapItem.getRobotNo()));
positionMapItem.setUseStatus(UseStatusEnum.PRE_OCCUPANCY.getType());
robotMapItems.add(positionMapItem);

View File

@ -212,3 +212,19 @@ zn:
is_simulation: false # 是否为仿真环境
send_robot_init_pose: true # 是否为发送默认的车辆所在地图和点位
restore_task_restart: false # 恢复任务是否全部重新执行 true:全部重新开始
synchronous_all_map_node: 500 # 点位信息每次发送的数据量
#海康威视的相关配置
isc:
previewUrl: https://api.znkj.ispt.com.cn
host: 111.75.51.123:10443
appKey: 24991430
appSecret: jQd4pIYZBzwW8cnuI9IN
#视频资源
resource:
cameras: /artemis/api/resource/v1/cameras
#视频能力
video:
previewUrls: /artemis/api/video/v2/cameras/previewURLs
replayUrlApi: /artemis/api/video/v2/cameras/playbackURLs

View File

@ -0,0 +1,12 @@
#海康威视的相关配置
isc:
host: hik.znkj.ispt.com.cn:10443
appKey: 24991430
appSecret: jQd4pIYZBzwW8cnuI9IN
#视频资源
resource:
cameras: /artemis/api/resource/v1/cameras
#视频能力
video:
previewUrls: /artemis/api/video/v2/cameras/previewURLs
replayUrlApi: /artemis/api/video/v2/cameras/playbackURLs

View File

@ -247,7 +247,22 @@ zn:
is_simulation: true # 是否为仿真环境
send_robot_init_pose: true # 是否为发送默认的车辆所在地图和点位
restore_task_restart: true # 恢复任务是否全部重新执行 true:全部重新开始
synchronous_all_map_node: 500 # 点位信息每次发送的数据量
logging:
file:
name: C:\system\install\log/${spring.application.name}.log
name: C:\system\install\log/${spring.application.name}.log
#海康威视的相关配置
isc:
previewUrl: https://api.znkj.ispt.com.cn
host: 111.75.51.123:10443
appKey: 24991430
appSecret: jQd4pIYZBzwW8cnuI9IN
#视频资源
resource:
cameras: /artemis/api/resource/v1/cameras
#视频能力
video:
previewUrls: /artemis/api/video/v2/cameras/previewURLs
replayUrlApi: /artemis/api/video/v2/cameras/playbackURLs

View File

@ -240,4 +240,18 @@ zn:
is_simulation: false # 是否为仿真环境
send_robot_init_pose: true # 是否为发送默认的车辆所在地图和点位
restore_task_restart: false # 恢复任务是否全部重新执行 true:全部重新开始
synchronous_all_map_node: 500 # 点位信息每次发送的数据量
#海康威视的相关配置
isc:
previewUrl: https://api.znkj.ispt.com.cn
host: 111.75.51.123:10443
appKey: 24991430
appSecret: jQd4pIYZBzwW8cnuI9IN
#视频资源
resource:
cameras: /artemis/api/resource/v1/cameras
#视频能力
video:
previewUrls: /artemis/api/video/v2/cameras/previewURLs
replayUrlApi: /artemis/api/video/v2/cameras/playbackURLs