package com.zy.acs.manager.core.service.astart; import com.zy.acs.framework.common.Cools; import com.zy.acs.manager.common.utils.MapDataUtils; import com.zy.acs.manager.core.domain.Lane; import com.zy.acs.manager.core.service.LaneService; import com.zy.acs.manager.core.service.astart.domain.DynamicNode; import com.zy.acs.manager.manager.entity.Route; import com.zy.acs.manager.manager.service.AgvService; import com.zy.acs.manager.manager.service.CodeService; import com.zy.acs.manager.manager.service.RouteService; import com.zy.acs.manager.system.service.ConfigService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; import java.util.PriorityQueue; /** * Created by vincent on 6/12/2024 */ @Service public class AStarNavigateService { public static final boolean OPEN_TURN_COST_WEIGHT = Boolean.FALSE; @Autowired private CodeService codeService; @Autowired private RouteService routeService; @Autowired private MapDataDispatcher mapDataDispatcher; @Autowired private AgvService agvService; @Autowired private LaneService laneService; @Autowired private ConfigService configService; public synchronized NavigateNode execute(String agvNo, NavigateNode start, NavigateNode end , Boolean lock, List blackList) { if (start.getX() == end.getX() && start.getY() == end.getY()) { return end; } Integer maxAgvCountInLane = configService.getVal("maxAgvCountInLane", Integer.class); PriorityQueue openQueue = new PriorityQueue<>(); ArrayList existNodes = new ArrayList<>(); openQueue.add(start); existNodes.add(start); int[][] mapMatrix = mapDataDispatcher.getMapMatrix(null, null); DynamicNode[][] dynamicMatrix = mapDataDispatcher.getDynamicMatrix(null); String[][] waveMatrix = mapDataDispatcher.getWaveMatrix(null); // List included = new ArrayList<>(); // if (!Cools.isEmpty(whiteList)) { // included.addAll(whiteList); // } // included.add(agvNo); // List vehicleDtoList = agvService.getVehicleDtoList(included); while (openQueue.size() > 0) { // 取优先队列顶部元素并且把这个元素从Open表中删除,取F值最小的节点 NavigateNode currentNode = openQueue.poll(); // 对当前结点进行扩展,得到一个四周结点的数组 ArrayList neighbourNodes = this.getNeighborNodes(currentNode, mapMatrix, existNodes); // 对这个结点遍历,看是否有目标结点出现 label: for (NavigateNode node : neighbourNodes) { // 节点存在其他车辆 // for (VehicleDto vehicleDto : vehicleDtoList) { // if (node.getCodeData().equals(vehicleDto.getPosCode())) { // if (!Cools.isEmpty(blackList) && blackList.contains(vehicleDto.getVehicle())) { // continue label; // } // if (lock) { // continue label; // } // } // } // 节点被占用 DynamicNode dynamicNode = dynamicMatrix[node.getX()][node.getY()]; String vehicle = dynamicNode.getVehicle(); assert !vehicle.equals(DynamicNodeType.BLOCK.val); if (!vehicle.equals(DynamicNodeType.ACCESS.val)) { if (!vehicle.equals(agvNo)) { if (!Cools.isEmpty(blackList) && blackList.contains(vehicle)) { continue; } if (lock) { continue; } } } // 避障波 String waveNode = waveMatrix[node.getX()][node.getY()]; assert !waveNode.equals(WaveNodeType.DISABLE.val); if (!waveNode.equals(WaveNodeType.ENABLE.val)) { List waveNodeList = MapDataUtils.parseWaveNode(waveNode); List otherWaveList = MapDataUtils.hasOtherWave(waveNodeList, agvNo); if (!Cools.isEmpty(otherWaveList)) { if (!Cools.isEmpty(blackList) && 0 < Cools.getIntersection(otherWaveList, blackList).size()) { continue; } if (lock) { continue; } } } // 单巷道车辆容载数量 Lane lane = laneService.search(node.getCodeData()); if (null != lane) { int otherVehicleCount = 0; List laneCodes = lane.getCodes(); for (String laneCodeData : laneCodes) { int[] laneCodeMatrixIdx = mapDataDispatcher.getCodeMatrixIdx(null, laneCodeData); // scan dynamicMatrix or WaveMatrix DynamicNode laneDynamicNode = dynamicMatrix[laneCodeMatrixIdx[0]][laneCodeMatrixIdx[1]]; String laneVehicle = laneDynamicNode.getVehicle(); assert !laneVehicle.equals(DynamicNodeType.BLOCK.val); if (!laneVehicle.equals(DynamicNodeType.ACCESS.val)) { if (!laneVehicle.equals(agvNo)) { otherVehicleCount++; } } } if (otherVehicleCount + 1 > maxAgvCountInLane) { if (lock) { continue; } } } //找到目标结点就返回 if (node.getX() == end.getX() && node.getY() == end.getY()) { //并且计算出G, F, H等值 node.initNode(currentNode, end); return node; } // G + H + T (对启发函数增加去拐点方案calcNodeTurnCost) int gCost = calcNodeCost(currentNode, node) * (OPEN_TURN_COST_WEIGHT ? calcNodeTurnCost(currentNode, node, end) : 1); //进行计算对 G, F, H 等值 node.setLastDistance(gCost); node.initNode(currentNode, end); node.setH(calcNodeCost(node, end)); node.setF(node.getG() + node.getH()); openQueue.add(node); existNodes.add(node); } } //如果遍历完所有出现的结点都没有找到最终的结点,返回null return null; } // 获取四周节点 private ArrayList getNeighborNodes(NavigateNode currentNode, int[][] mapMatrix, List existNodes) { //获取当前结点的x, y int x = currentNode.getX(); int y = currentNode.getY(); //如果当前结点的邻结点合法,就加入到neighbour_node ArrayList neighbourNodes = new ArrayList<>(); NavigateNode rightNode = extendNeighborNodes(currentNode, new NavigateNode(x, y + 1), mapMatrix, existNodes, null, null); if (is_valid(currentNode, rightNode, mapMatrix, existNodes)) { neighbourNodes.add(rightNode); } NavigateNode leftNode = extendNeighborNodes(currentNode, new NavigateNode(x, y - 1), mapMatrix, existNodes, null, null); if (is_valid(currentNode, leftNode, mapMatrix, existNodes)) { neighbourNodes.add(leftNode); } NavigateNode topNode = extendNeighborNodes(currentNode, new NavigateNode(x - 1, y), mapMatrix, existNodes, null, null); if (is_valid(currentNode, topNode, mapMatrix, existNodes)) { neighbourNodes.add(topNode); } NavigateNode bottomNode = extendNeighborNodes(currentNode, new NavigateNode(x + 1, y), mapMatrix, existNodes, null, null); if (is_valid(currentNode, bottomNode, mapMatrix, existNodes)) { neighbourNodes.add(bottomNode); } return neighbourNodes; } private NavigateNode extendNeighborNodes(NavigateNode currentNode, NavigateNode extendNode, int[][] mapMatrix, List existNodes, Integer dx, Integer dy) { NavigateNode nextNode = null; if (null == dx || null == dy) { dx = extendNode.getX() - currentNode.getX(); dy = extendNode.getY() - currentNode.getY(); nextNode = extendNode; } else { nextNode = new NavigateNode(extendNode.getX() + dx, extendNode.getY() + dy); } int x = nextNode.getX(); int y = nextNode.getY(); // 数组越界 if (x < 0 || x >= mapMatrix.length || y < 0 || y >= mapMatrix[0].length) { return null; } if (mapMatrix[x][y] == MapNodeType.DISABLE.val) { return extendNeighborNodes(currentNode, nextNode, mapMatrix, existNodes, dx, dy); } else { if (isExist(nextNode, existNodes)) { return null; } // 节点是否可用 if (mapMatrix[x][y] != MapNodeType.ENABLE.val) { return null; } String[][] codeMatrix = mapDataDispatcher.getCodeMatrix(null); String currentNodeCodeData = codeMatrix[currentNode.getX()][currentNode.getY()]; String nextNodeCodeData = codeMatrix[nextNode.getX()][nextNode.getY()]; nextNode.setCodeData(nextNodeCodeData); // 判断通过性 Route route = routeService.findByCodeOfBoth( codeService.selectByData(currentNodeCodeData).getId(), codeService.selectByData(nextNodeCodeData).getId() ); if (null == route) { return null; } return nextNode; } } private boolean is_valid(NavigateNode currentNode, NavigateNode node, int[][] mapMatrix, List existNodes) { if (null == node) { return false; } // int x = node.getX(); // int y = node.getY(); // if (x < 0 || x >= mapMatrix.length // || y < 0 || y >= mapMatrix[0].length) { // return false; // } // // // 如果结点的位置小于0,则不合法 // if (mapMatrix[x][y] < 0) return false; // // if (is_exist(node, existNodes)) { // return false; // } // // // 判断通过性 // String[][] codeMatrix = mapDataDispatcher.getCodeMatrix(null); // String currentNodeCodeData = codeMatrix[currentNode.getX()][currentNode.getY()]; // String nextNodeCodeData = codeMatrix[node.getX()][node.getY()]; // node.setCodeData(nextNodeCodeData); // // Route route = routeService.findByCodeOfBoth( // codeService.selectByData(currentNodeCodeData).getId(), // codeService.selectByData(nextNodeCodeData).getId() // ); // if (null == route) { // return false; // } return true; } // private boolean is_exist(NavigateNode node, List existNodes) { // for (NavigateNode exist_node : existNodes) { // if (node.getX() == exist_node.getX() && node.getY() == exist_node.getY()) { // return true; // } // } // return false; // } private boolean isExist(NavigateNode node, List existNodes) { for (NavigateNode existNode : existNodes) { if (this.isSame(node, existNode)) { return true; } } return false; } private boolean isSame(NavigateNode o1, NavigateNode o2) { if (Cools.isEmpty(o1, o2)) { return false; } return o1.getX() == o2.getX() && o1.getY() == o2.getY(); } //------------------A*启发函数------------------// //计算通过现在的结点的位置和最终结点的位置计算H值(曼哈顿法:坐标分别取差值相加) private int calcNodeCost(NavigateNode node1, NavigateNode node2) { return Math.abs(node2.getX() - node1.getX()) + Math.abs(node2.getY() - node1.getY()); } //去除拐点算法,给直线增加优先级 private int calcNodeTurnCost(NavigateNode currNode, NavigateNode nextNode, NavigateNode endNode) { // 第一个点或直线点 if (currNode.getParent() == null || nextNode.getX() == currNode.getParent().getX() || nextNode.getY() == currNode.getParent().getY() ) { return 1; } // 拐向终点的点 if (nextNode.getX() == endNode.getX() || nextNode.getY() == endNode.getY()) { return 2; } // 普通拐点 /* 拐点判断逻辑 拿到父节点和下一节点 通过判断父节点和下一节点的x数据和y数据都不相同时,则表明当前坐标是一个拐点 */ return 3; } }