package com.zy.acs.manager.core.service; import com.zy.acs.framework.common.Cools; import com.zy.acs.common.utils.RedisSupport; import com.zy.acs.manager.common.domain.MockAgvDto; import com.zy.acs.manager.common.domain.MockDto; import com.zy.acs.manager.common.domain.MockStepDto; import com.zy.acs.manager.common.domain.MockVo; import com.zy.acs.manager.common.exception.BusinessException; import com.zy.acs.manager.core.domain.AgvMockDto; import com.zy.acs.manager.core.domain.TaskPosDto; import com.zy.acs.manager.core.service.astart.AStarNavigateService; import com.zy.acs.manager.core.service.astart.MapDataDispatcher; import com.zy.acs.manager.manager.entity.Agv; import com.zy.acs.manager.manager.entity.AgvDetail; import com.zy.acs.manager.manager.entity.Code; import com.zy.acs.manager.manager.entity.CodeGap; import com.zy.acs.manager.manager.service.AgvDetailService; import com.zy.acs.manager.manager.service.AgvService; import com.zy.acs.manager.manager.service.CodeGapService; import com.zy.acs.manager.manager.service.CodeService; import com.zy.acs.manager.system.service.ConfigService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; /** * Created by vincent on 2023/7/29 */ @Slf4j @Service public class MockService { private final RedisSupport redis = RedisSupport.defaultRedisSupport; @Autowired private MapService mapService; @Autowired private AgvService agvService; @Autowired private AgvDetailService agvDetailService; @Autowired private CodeService codeService; @Autowired private CodeGapService codeGapService; @Autowired private MapDataDispatcher mapDataDispatcher; @Autowired private AStarNavigateService aStarNavigateService; @Autowired private ConfigService configService; public void astarMock() { Code startCode = codeService.selectByData("00000028"); Code endCode = codeService.selectByData("00000057"); List strings = mapService.checkoutPath("1", startCode, endCode, false); List pathList = mapService.validFeasibility(startCode, endCode); System.out.println("end"); } @Transactional public List submit(List agvList, List taskList) { final String sameGroupXy = configService.getVal("sameGroupXy", String.class); List result = new ArrayList<>(); if (Cools.isEmpty(taskList)) { throw new BusinessException("请添加 MOCK 任务"); } taskList.sort((o1, o2) -> o2.getPriority() - o1.getPriority()); // 以 agv 分组 List taskDtos = new ArrayList<>(); for (MockDto task : taskList) { AgvMockDto taskDto = new AgvMockDto(task.getAgv(), task); if (AgvMockDto.has(taskDtos, taskDto)) { AgvMockDto dto = AgvMockDto.find(taskDtos, taskDto); assert dto != null; dto.getTaskList().add(task); } else { taskDtos.add(taskDto); } } // 重组当前 agv 的所有任务 for (AgvMockDto taskDto : taskDtos) { /** * key:y 坐标 + 任务类别(货架取货、站点取货、货架放货、站点放货) * val:任务id + 任务坐标 + 条码 + 任务类别 */ Map> groups = new HashMap<>(); for (MockDto mockDto : taskDto.getTaskList()) { Code startCode = codeService.selectByData(mockDto.getStart()); Code endCode = codeService.selectByData(mockDto.getEnd()); TaskPosDto.packagePosGroup(groups, null, startCode, TaskPosDto.PosType.ORI_LOC, sameGroupXy); TaskPosDto.packagePosGroup(groups, null, endCode, TaskPosDto.PosType.DEST_LOC, sameGroupXy); } // 二维数组 ( 每组的 y坐标 和 任务类别 一致) ArrayList> list = new ArrayList<>(groups.values()); // 二位数组 子数组 已经能确定 y坐标为一致。所有 get(0).xy[1] 为排序(就是一排一排任务进行排序),对 一排排任务以 y坐标 就行降序排序 list.sort((o1, o2) -> { double o1CompVal = (o1.get(0).getFirstWeight(sameGroupXy) * 100) + o1.get(0).getPosType().compOffset; double o2CompVal = (o2.get(0).getFirstWeight(sameGroupXy) * 100) + o2.get(0).getPosType().compOffset; return (int) (o1CompVal - o2CompVal); }); // 对一排任务进行 x坐标 顺序排序,防止来回走行 for (List taskPosDtoList : list) { taskPosDtoList.sort((o1, o2) -> (int) (o1.getSecondWeight(sameGroupXy) * 100 - o2.getSecondWeight(sameGroupXy) * 100)); } // 上一次的 code, 第一次为 agv 当前code String lastCodeData = this.getPosCode(agvList, taskDto.getAgvId()); if (Cools.isEmpty(lastCodeData)) { throw new BusinessException(taskDto.getAgvId() + "号 agv 不在条码定位上!"); } Code lastCode = codeService.selectByData(lastCodeData); // 走行路径集合 List stepList = new ArrayList<>(); stepList.add(new MockStepDto(lastCodeData, Boolean.FALSE)); for (List taskPosDtoList : list) { for (TaskPosDto dto : taskPosDtoList) { // 目标 code Code code = codeService.getById(dto.getCodeId()); if (!lastCode.getData().equals(code.getData())) { // 计算路径节点 List pathList = mapService.checkoutPath(taskDto.getAgvId(), lastCode, code, true); mapDataDispatcher.clearDynamicMatrixByCodeList(null, pathList); // List pathList = mapService.validFeasibility(lastCode, code); if (Cools.isEmpty(pathList)) { throw new BusinessException(lastCode.getData() + " 至 " + code.getData() + "没有路径!"); } // 第一个节点为本身, 所以从 下标1 开始 for (int i = 1; i < pathList.size(); i++) { String next = pathList.get(i); Code nextCode = codeService.selectByData(next); boolean pause = nextCode.getId().equals(dto.getCodeId()); String action = ""; if (pause) { switch (dto.getPosType()){ case ORI_LOC: case ORI_STA: action = "PICK"; break; case DEST_LOC: case DEST_STA: action = "DROP"; break; default: break; } } stepList.add(new MockStepDto(nextCode.getData(), pause, action)); lastCode = nextCode; } } } } result.add(new MockVo(taskDto.getAgvId(), stepList)); } plusData(result); for (MockVo mockVo : result) { // redis.setObject("PATH", mockVo.getAgv(), mockVo.getStepList().stream().map(MockStepDto::getCode).collect(Collectors.toList())); } return result; } private String getPosCode(List agvList, String agv) { for (MockAgvDto agvDto : agvList) { if (agv.equals(agvDto.getAgv())) { return agvDto.getPos(); } } return null; } private void plusData(List result) { for (MockVo mockVo : result) { int size = mockVo.getStepList().size(); int time = size * 500; Code lastCode = null; double totalDistance = 0; for (MockStepDto stepDto : mockVo.getStepList()) { Code code = codeService.selectByData(stepDto.getCode()); if (null != lastCode) { CodeGap gap = codeGapService.findByCodeOfBoth(code.getId(), lastCode.getId()); if (null != gap) { totalDistance += gap.getDistance(); stepDto.setDistance(gap.getDistance()); } } lastCode = code; } for (MockStepDto stepDto : mockVo.getStepList()) { if (null != stepDto.getDistance()) { double rate = stepDto.getDistance() / totalDistance; stepDto.setTime((int)(rate * time)); } } } } public List imitate() { Agv agv = agvService.selectByUuid("1"); AgvDetail agvDetail = agvDetailService.selectByAgvId(agv.getId()); MockAgvDto mockAgvDto = new MockAgvDto(); mockAgvDto.setAgv(agv.getUuid()); mockAgvDto.setPos(codeService.getById(agvDetail.getCode()).getData()); List mockAgvDtos = new ArrayList<>(); mockAgvDtos.add(mockAgvDto); List taskList = new ArrayList<>(); List codeList = codeService.list(); Random random = new Random(); List exitCodes = new ArrayList<>(); for (int i = 0; i < agv.getStage(); i++) { MockDto mockDto = new MockDto(); mockDto.setAgv(agv.getUuid()); int startIdx; do { startIdx = random.nextInt(codeList.size()); } while (exitCodes.contains(startIdx)); exitCodes.add(startIdx); Code startCode = codeList.get(startIdx); int endIdx; do { endIdx = random.nextInt(codeList.size()); } while (exitCodes.contains(endIdx)); exitCodes.add(endIdx); Code endCode = codeList.get(endIdx); mockDto.setStart(startCode.getData()); mockDto.setEnd(endCode.getData()); taskList.add(mockDto); } return this.submit(mockAgvDtos, taskList); } }