|  |  |  | 
|---|
|  |  |  | import com.zy.acs.common.enums.AgvDirectionType; | 
|---|
|  |  |  | import com.zy.acs.framework.common.Cools; | 
|---|
|  |  |  | import com.zy.acs.manager.common.utils.MapDataUtils; | 
|---|
|  |  |  | import com.zy.acs.manager.core.constant.MapDataConstant; | 
|---|
|  |  |  | import com.zy.acs.manager.core.service.astart.*; | 
|---|
|  |  |  | import com.zy.acs.manager.core.service.astart.domain.DynamicNode; | 
|---|
|  |  |  | import com.zy.acs.manager.core.service.floyd.FloydNavigateService; | 
|---|
|  |  |  | import com.zy.acs.manager.manager.entity.Code; | 
|---|
|  |  |  | import com.zy.acs.manager.manager.entity.Loc; | 
|---|
|  |  |  | import com.zy.acs.manager.manager.entity.Segment; | 
|---|
|  |  |  | import com.zy.acs.manager.manager.service.ActionService; | 
|---|
|  |  |  | import com.zy.acs.manager.manager.service.CodeService; | 
|---|
|  |  |  | import com.zy.acs.manager.system.service.ConfigService; | 
|---|
|  |  |  | 
|---|
|  |  |  | @Autowired | 
|---|
|  |  |  | private ActionService actionService; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public List<String> checkoutPath(String agvNo, Code startCode, Code endCode, Boolean lock) { | 
|---|
|  |  |  | return this.checkoutPath(agvNo, startCode, endCode, lock, null, null); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 寻址 ===>> A Star | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | public synchronized List<String> checkoutPath(String agvNo, Code startCode, Code endCode | 
|---|
|  |  |  | , Boolean lock, List<String> whiteList, List<String> blackList) { | 
|---|
|  |  |  | , Boolean lock, List<String> blackList, Segment segment) { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int[] startMapIdx = mapDataDispatcher.getCodeMatrixIdx(null, startCode.getData()); | 
|---|
|  |  |  | int[] endMapIdx = mapDataDispatcher.getCodeMatrixIdx(null, endCode.getData()); | 
|---|
|  |  |  | 
|---|
|  |  |  | NavigateNode startNode = new NavigateNode(startMapIdx[0], startMapIdx[1], startCode.getData()); | 
|---|
|  |  |  | NavigateNode endNode = new NavigateNode(endMapIdx[0], endMapIdx[1], endCode.getData()); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | NavigateNode finishNode = aStarNavigateService.execute(agvNo, startNode, endNode, lock, whiteList, blackList); | 
|---|
|  |  |  | NavigateNode finishNode = aStarNavigateService.execute(agvNo, startNode, endNode, lock, blackList, segment); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (null == finishNode) { | 
|---|
|  |  |  | log.warn("{} 号AGV检索[{}] ===>> [{}]路径失败......", agvNo, startCode.getData(), endCode.getData()); | 
|---|
|  |  |  | 
|---|
|  |  |  | //            navigateNode.setParent(null); | 
|---|
|  |  |  | //        } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | return navigateNodes.stream().map(NavigateNode::getCodeData).collect(Collectors.toList()); | 
|---|
|  |  |  | List<String> navigatePath = navigateNodes.stream().map(NavigateNode::getCodeData).collect(Collectors.toList()); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // max count of steps | 
|---|
|  |  |  | if (navigatePath.size() > MapDataConstant.MAX_STEPS_SINGLE) { | 
|---|
|  |  |  | navigatePath = navigatePath.subList(0, MapDataConstant.MAX_STEPS_SINGLE); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | return navigatePath; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | double deltaX = x1 - x0; | 
|---|
|  |  |  | double deltaY = y1 - y0; | 
|---|
|  |  |  | double angle = Math.atan2(deltaX, deltaY); | 
|---|
|  |  |  | int offsetAngle = configService.getVal("mapXoffset", Integer.class); | 
|---|
|  |  |  | angle = angle + offsetAngle; | 
|---|
|  |  |  | angle = Math.toDegrees(angle); | 
|---|
|  |  |  | double angle = -Math.atan2(deltaX, deltaY); | 
|---|
|  |  |  | int angleOffsetVal = configService.getVal("mapAngleOffsetVal", Integer.class); | 
|---|
|  |  |  | angle = Math.toDegrees(angle) + angleOffsetVal; | 
|---|
|  |  |  | angle = (angle + 360) % 360; // 将角度转换为正值 | 
|---|
|  |  |  |  | 
|---|
|  |  |  | return angle; | 
|---|
|  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public void lockPath(Integer lev, List<String> pathList, String agvNo) { | 
|---|
|  |  |  | mapDataDispatcher.modifyDynamicMatrix(lev, pathList, agvNo); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public synchronized void unlockPath(String agvNo, List<String> nodeList) { | 
|---|
|  |  |  | try { | 
|---|
|  |  |  | StopWatch stopWatch = new StopWatch(); | 
|---|
|  |  |  | stopWatch.start(); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (Cools.isEmpty(agvNo, nodeList)) { | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | List<String> pathList = actionService.getPathListByAgv(agvNo).stream().distinct().collect(Collectors.toList()); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | List<String> inTrace = new ArrayList<>(); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | Set<String> outsideTrace = new HashSet<>(); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (Cools.isEmpty(pathList)) { | 
|---|
|  |  |  | outsideTrace.addAll(nodeList); | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int size = nodeList.size(); | 
|---|
|  |  |  | for (String code : pathList) { | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | Iterator<String> iterator = nodeList.iterator(); | 
|---|
|  |  |  | while (iterator.hasNext()) { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | String next = iterator.next(); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (next.equals(code)) { | 
|---|
|  |  |  | if (!inTrace.contains(next)) { | 
|---|
|  |  |  | inTrace.add(next); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | iterator.remove(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | assert inTrace.size() + nodeList.size() <= size; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (!Cools.isEmpty(nodeList)) { | 
|---|
|  |  |  | outsideTrace.addAll(nodeList); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (!Cools.isEmpty(inTrace)) { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | String last = inTrace.get(inTrace.size() - 1); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int idx = pathList.indexOf(last); | 
|---|
|  |  |  | inTrace = pathList.subList(0, idx + 1); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | List<String> resetCodeList = new ArrayList<>(); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | Integer lev = null; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | DynamicNode[][] dynamicMatrix = mapDataDispatcher.getDynamicMatrix(lev); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | for (String code : inTrace) { | 
|---|
|  |  |  | int[] node = mapDataDispatcher.getCodeMatrixIdx(lev, code); | 
|---|
|  |  |  | DynamicNode dynamicNode = dynamicMatrix[node[0]][node[1]]; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (dynamicNode.getVehicle().equals(agvNo)) { | 
|---|
|  |  |  | resetCodeList.add(code); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | for (String code : outsideTrace) { | 
|---|
|  |  |  | int[] node = mapDataDispatcher.getCodeMatrixIdx(lev, code); | 
|---|
|  |  |  | DynamicNode dynamicNode = dynamicMatrix[node[0]][node[1]]; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (dynamicNode.getVehicle().equals(agvNo)) { | 
|---|
|  |  |  | resetCodeList.add(code); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (!Cools.isEmpty(resetCodeList)) { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | mapDataDispatcher.clearDynamicMatrixByCodeList(lev, resetCodeList); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | stopWatch.stop(); | 
|---|
|  |  |  | if (stopWatch.getTime() > 50) { | 
|---|
|  |  |  | log.info("解锁路径函数花费时间为:{}毫秒......", stopWatch.getTime()); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } catch (Exception e) { | 
|---|
|  |  |  | log.error("TrafficService.unlockPath", e); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public synchronized void unlockPath(String agvNo, String codeData) { | 
|---|
|  |  |  | 
|---|
|  |  |  | return nodeList.stream().map(NavigateNode::getCodeData).distinct().collect(Collectors.toList()); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // v1 BFS ------------------------------------------------------------------------------ | 
|---|
|  |  |  | public List<NavigateNode> getWaveScopeByCode(Integer lev, String code, Double radiusLen) { | 
|---|
|  |  |  | String[][] codeMatrix = mapDataDispatcher.getCodeMatrix(lev); | 
|---|
|  |  |  | String[][] cdaMatrix = mapDataDispatcher.getCdaMatrix(lev); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int[] codeMatrixIdx = mapDataDispatcher.getCodeMatrixIdx(lev, code); | 
|---|
|  |  |  | NavigateNode originNode = new NavigateNode(codeMatrixIdx[0], codeMatrixIdx[1], code); | 
|---|
|  |  |  | 
|---|
|  |  |  | includeList.add(originNode); | 
|---|
|  |  |  | existNodes.add(originNode); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | this.spreadWaveNode(originNode, originNode, codeMatrix, radiusLen, includeList, existNodes); | 
|---|
|  |  |  | this.spreadWaveNode(originNode, originNode, codeMatrix, cdaMatrix, radiusLen, includeList, existNodes); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | return includeList; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public void spreadWaveNode(NavigateNode originNode, NavigateNode currNode | 
|---|
|  |  |  | , String[][] codeMatrix, Double radiusLen | 
|---|
|  |  |  | , String[][] codeMatrix, String[][] cdaMatrix, Double radiusLen | 
|---|
|  |  |  | , List<NavigateNode> includeList, List<NavigateNode> existNodes) { | 
|---|
|  |  |  | int x = currNode.getX(); | 
|---|
|  |  |  | int y = currNode.getY(); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | this.extendNeighborNodes(originNode, new NavigateNode(x, y + 1), codeMatrix, radiusLen, includeList, existNodes); | 
|---|
|  |  |  | this.extendNeighborNodes(originNode, new NavigateNode(x, y - 1), codeMatrix, radiusLen, includeList, existNodes); | 
|---|
|  |  |  | this.extendNeighborNodes(originNode, new NavigateNode(x - 1, y), codeMatrix, radiusLen, includeList, existNodes); | 
|---|
|  |  |  | this.extendNeighborNodes(originNode, new NavigateNode(x + 1, y), codeMatrix, radiusLen, includeList, existNodes); | 
|---|
|  |  |  | this.extendNeighborNodes(originNode, new NavigateNode(x, y + 1), codeMatrix, cdaMatrix, radiusLen, includeList, existNodes); | 
|---|
|  |  |  | this.extendNeighborNodes(originNode, new NavigateNode(x, y - 1), codeMatrix, cdaMatrix, radiusLen, includeList, existNodes); | 
|---|
|  |  |  | this.extendNeighborNodes(originNode, new NavigateNode(x - 1, y), codeMatrix, cdaMatrix, radiusLen, includeList, existNodes); | 
|---|
|  |  |  | this.extendNeighborNodes(originNode, new NavigateNode(x + 1, y), codeMatrix, cdaMatrix, radiusLen, includeList, existNodes); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public void extendNeighborNodes(NavigateNode originNode, NavigateNode nextNode | 
|---|
|  |  |  | , String[][] codeMatrix, Double radiusLen | 
|---|
|  |  |  | , String[][] codeMatrix, String[][] cdaMatrix, Double radiusLen | 
|---|
|  |  |  | , List<NavigateNode> includeList, List<NavigateNode> existNodes) { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int x = nextNode.getX(); | 
|---|
|  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (nextNodeCodeData.equals(CodeNodeType.NONE.val)) { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | this.spreadWaveNode(originNode, nextNode, codeMatrix, radiusLen, includeList, existNodes); | 
|---|
|  |  |  | this.spreadWaveNode(originNode, nextNode, codeMatrix, cdaMatrix, radiusLen, includeList, existNodes); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | Integer lev = MapDataDispatcher.MAP_DEFAULT_LEV; | 
|---|
|  |  |  | String[][] cdaMatrix = mapDataDispatcher.getCdaMatrix(lev); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //            Code o1 = codeService.selectByData(originNode.getCodeData()); | 
|---|
|  |  |  | //            Code o2 = codeService.selectByData(nextNodeCodeData); | 
|---|
|  |  |  | List<Double> o1Cda = MapDataUtils.parseCdaNode(cdaMatrix[originNode.getX()][originNode.getY()]); | 
|---|
|  |  |  | List<Double> o2Cda = MapDataUtils.parseCdaNode(cdaMatrix[nextNode.getX()][nextNode.getY()]); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  | nextNode.setCodeData(nextNodeCodeData); | 
|---|
|  |  |  | includeList.add(nextNode); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | this.spreadWaveNode(originNode, nextNode, codeMatrix, radiusLen, includeList, existNodes); | 
|---|
|  |  |  | this.spreadWaveNode(originNode, nextNode, codeMatrix, cdaMatrix, radiusLen, includeList, existNodes); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | 
|---|
|  |  |  | return o1.getX() == o2.getX() && o1.getY() == o2.getY(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // v2 BFS ------------------------------------------------------------------------------ | 
|---|
|  |  |  | public List<NavigateNode> getWaveScopeByCode0(Integer lev, String code, Double radiusLen) { | 
|---|
|  |  |  | String[][] codeMatrix = mapDataDispatcher.getCodeMatrix(lev); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int[] codeMatrixIdx = mapDataDispatcher.getCodeMatrixIdx(lev, code); | 
|---|
|  |  |  | NavigateNode originNode = new NavigateNode(codeMatrixIdx[0], codeMatrixIdx[1], code); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | List<NavigateNode> includeList = new ArrayList<>(); | 
|---|
|  |  |  | Set<NavigateNode> visited = new HashSet<>(); // Track visited nodes to avoid re-processing | 
|---|
|  |  |  | Queue<NavigateNode> queue = new LinkedList<>(); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | includeList.add(originNode); | 
|---|
|  |  |  | visited.add(originNode); | 
|---|
|  |  |  | queue.offer(originNode); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | while (!queue.isEmpty()) { | 
|---|
|  |  |  | NavigateNode currNode = queue.poll(); | 
|---|
|  |  |  | this.spreadWaveNode0(originNode, currNode, codeMatrix, radiusLen, includeList, visited, queue); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | return includeList; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public void spreadWaveNode0(NavigateNode originNode, NavigateNode currNode, | 
|---|
|  |  |  | String[][] codeMatrix, Double radiusLen, | 
|---|
|  |  |  | List<NavigateNode> includeList, Set<NavigateNode> visited, Queue<NavigateNode> queue) { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int x = currNode.getX(); | 
|---|
|  |  |  | int y = currNode.getY(); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // Expand neighbors in all four directions (up, down, left, right) | 
|---|
|  |  |  | this.extendNeighborNodes0(originNode, new NavigateNode(x, y + 1), codeMatrix, radiusLen, includeList, visited, queue); | 
|---|
|  |  |  | this.extendNeighborNodes0(originNode, new NavigateNode(x, y - 1), codeMatrix, radiusLen, includeList, visited, queue); | 
|---|
|  |  |  | this.extendNeighborNodes0(originNode, new NavigateNode(x - 1, y), codeMatrix, radiusLen, includeList, visited, queue); | 
|---|
|  |  |  | this.extendNeighborNodes0(originNode, new NavigateNode(x + 1, y), codeMatrix, radiusLen, includeList, visited, queue); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public void extendNeighborNodes0(NavigateNode originNode, NavigateNode nextNode, | 
|---|
|  |  |  | String[][] codeMatrix, Double radiusLen, | 
|---|
|  |  |  | List<NavigateNode> includeList, Set<NavigateNode> visited, Queue<NavigateNode> queue) { | 
|---|
|  |  |  | int x = nextNode.getX(); | 
|---|
|  |  |  | int y = nextNode.getY(); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // Check if the node is out of bounds | 
|---|
|  |  |  | if (x < 0 || x >= codeMatrix.length || y < 0 || y >= codeMatrix[0].length) { | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // If the node has already been visited, skip it | 
|---|
|  |  |  | if (this.isExist0(nextNode, visited)) { | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | visited.add(nextNode); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | String nextNodeCodeData = codeMatrix[x][y]; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // If it's a NONE node, we still need to check its surroundings | 
|---|
|  |  |  | if (nextNodeCodeData.equals(CodeNodeType.NONE.val)) { | 
|---|
|  |  |  | this.spreadWaveNode0(originNode, nextNode, codeMatrix, radiusLen, includeList, visited, queue); | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | Integer lev = MapDataDispatcher.MAP_DEFAULT_LEV; | 
|---|
|  |  |  | String[][] cdaMatrix = mapDataDispatcher.getCdaMatrix(lev); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // Check if the distance between nodes is within the radius length | 
|---|
|  |  |  | List<Double> o1Cda = MapDataUtils.parseCdaNode(cdaMatrix[originNode.getX()][originNode.getY()]); | 
|---|
|  |  |  | List<Double> o2Cda = MapDataUtils.parseCdaNode(cdaMatrix[nextNode.getX()][nextNode.getY()]); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // Calculate Euclidean distance between the nodes | 
|---|
|  |  |  | if (Math.pow(o1Cda.get(0) - o2Cda.get(0), 2) + Math.pow(o1Cda.get(1) - o2Cda.get(1), 2) <= Math.pow(radiusLen, 2)) { | 
|---|
|  |  |  | nextNode.setCodeData(nextNodeCodeData); | 
|---|
|  |  |  | includeList.add(nextNode); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // Add the node to the queue to expand its neighbors | 
|---|
|  |  |  | queue.offer(nextNode); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | private boolean isExist0(NavigateNode node, Set<NavigateNode> existNodes) { | 
|---|
|  |  |  | for (NavigateNode existNode : existNodes) { | 
|---|
|  |  |  | if (this.isSame(node, existNode)) { | 
|---|
|  |  |  | return true; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | return false; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public Boolean isTurnCorner(String codeData) { | 
|---|
|  |  |  | if (Cools.isEmpty(codeData)) { | 
|---|
|  |  |  | return false; | 
|---|