|  |  |  | 
|---|
|  |  |  | package com.zy.acs.manager.core.service.astart; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import com.zy.acs.common.constant.RedisConstant; | 
|---|
|  |  |  | import com.zy.acs.common.utils.GsonUtils; | 
|---|
|  |  |  | import com.zy.acs.common.utils.RedisSupport; | 
|---|
|  |  |  | 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.AStarNavigateNode; | 
|---|
|  |  |  | import com.zy.acs.manager.core.service.astart.domain.DynamicNode; | 
|---|
|  |  |  | import com.zy.acs.manager.core.utils.RouteGenerator; | 
|---|
|  |  |  | import com.zy.acs.manager.manager.entity.Segment; | 
|---|
|  |  |  | 
|---|
|  |  |  | @Autowired | 
|---|
|  |  |  | private ConfigService configService; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public synchronized NavigateNode execute(String agvNo, NavigateNode start, NavigateNode end | 
|---|
|  |  |  | public synchronized AStarNavigateNode execute(String agvNo, AStarNavigateNode start, AStarNavigateNode end | 
|---|
|  |  |  | , Boolean lock, List<String> blackList, Segment segment) { | 
|---|
|  |  |  | if (start.getX() == end.getX() && start.getY() == end.getY()) { | 
|---|
|  |  |  | return end; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | Integer maxAgvCountInLane = configService.getVal("maxAgvCountInLane", Integer.class); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | PriorityQueue<NavigateNode> openQueue = new PriorityQueue<>(); | 
|---|
|  |  |  | Set<NavigateNode> existNodes = new HashSet<>(); | 
|---|
|  |  |  | PriorityQueue<AStarNavigateNode> openQueue = new PriorityQueue<>(); | 
|---|
|  |  |  | Set<AStarNavigateNode> existNodes = new HashSet<>(); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | openQueue.add(start); | 
|---|
|  |  |  | existNodes.add(start); | 
|---|
|  |  |  | 
|---|
|  |  |  | String[][] waveMatrix = mapDataDispatcher.getWaveMatrix(null); | 
|---|
|  |  |  | while (!openQueue.isEmpty()) { | 
|---|
|  |  |  | // 取优先队列顶部元素并且把这个元素从Open表中删除,取F值最小的节点 | 
|---|
|  |  |  | NavigateNode currentNode = openQueue.poll(); | 
|---|
|  |  |  | AStarNavigateNode currentNode = openQueue.poll(); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | List<NavigateNode> neighbourNodes = this.getNeighborNodes(currentNode, mapMatrix, existNodes); | 
|---|
|  |  |  | for (NavigateNode node : neighbourNodes) { | 
|---|
|  |  |  | // 终点 | 
|---|
|  |  |  | if (currentNode.getX() == end.getX() && currentNode.getY() == end.getY()) { | 
|---|
|  |  |  | return currentNode; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | List<AStarNavigateNode> neighbourNodes = this.getNeighborNodes(currentNode, mapMatrix, existNodes); | 
|---|
|  |  |  | for (AStarNavigateNode node : neighbourNodes) { | 
|---|
|  |  |  | node.setCodeData(codeMatrix[node.getX()][node.getY()]); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | boolean isEndNode = node.getX() == end.getX() && node.getY() == end.getY(); | 
|---|
|  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //找到目标结点就返回 | 
|---|
|  |  |  | if (isEndNode) { | 
|---|
|  |  |  | //并且计算出G, F, H等值 | 
|---|
|  |  |  | node.initNode(currentNode, end); | 
|---|
|  |  |  | return node; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // G + H + T (对启发函数增加去拐点方案calcNodeTurnCost) | 
|---|
|  |  |  | int gCost = calcNodeCost(currentNode, node); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (OPEN_TURN_COST_WEIGHT) { | 
|---|
|  |  |  | gCost += calcNodeTurnCost(currentNode, node, end); | 
|---|
|  |  |  | if (this.isTurning(currentNode, node)) { | 
|---|
|  |  |  | weight += WEIGHT_CALC_FACTOR; | 
|---|
|  |  |  | node.setTurnCount(currentNode.getTurnCount() + 1); | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | // 方向没变 | 
|---|
|  |  |  | node.setTurnCount(currentNode.getTurnCount()); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //进行计算对 G, F, H 等值 | 
|---|
|  |  |  | node.setWeight(weight); | 
|---|
|  |  |  | node.setLastDistance(gCost); | 
|---|
|  |  |  | node.setLastDistance(calcNodeCost(currentNode, node)); | 
|---|
|  |  |  | node.initNode(currentNode, end); | 
|---|
|  |  |  | node.setH(calcNodeCost(node, end)); | 
|---|
|  |  |  | node.setF(node.getG() + node.getH()); | 
|---|
|  |  |  | 
|---|
|  |  |  | existNodes.add(node); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | //如果遍历完所有出现的结点都没有找到最终的结点,返回null | 
|---|
|  |  |  |  | 
|---|
|  |  |  | return null; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // 获取四周节点 | 
|---|
|  |  |  | private List<NavigateNode> getNeighborNodes(NavigateNode currentNode, int[][] mapMatrix, Set<NavigateNode> existNodes) { | 
|---|
|  |  |  | private List<AStarNavigateNode> getNeighborNodes(AStarNavigateNode currentNode, int[][] mapMatrix, Set<AStarNavigateNode> existNodes) { | 
|---|
|  |  |  | int x = currentNode.getX(); | 
|---|
|  |  |  | int y = currentNode.getY(); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | List<NavigateNode> neighbourNodes = new CopyOnWriteArrayList<>(); | 
|---|
|  |  |  | List<AStarNavigateNode> neighbourNodes = new CopyOnWriteArrayList<>(); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | List<NavigateNode> possibleNodes = Arrays.asList( | 
|---|
|  |  |  | new NavigateNode(x, y + 1), // right | 
|---|
|  |  |  | new NavigateNode(x, y - 1), // left | 
|---|
|  |  |  | new NavigateNode(x - 1, y), // up | 
|---|
|  |  |  | new NavigateNode(x + 1, y)  // down | 
|---|
|  |  |  | List<AStarNavigateNode> possibleNodes = Arrays.asList( | 
|---|
|  |  |  | new AStarNavigateNode(x, y + 1), // right | 
|---|
|  |  |  | new AStarNavigateNode(x, y - 1), // left | 
|---|
|  |  |  | new AStarNavigateNode(x - 1, y), // up | 
|---|
|  |  |  | new AStarNavigateNode(x + 1, y)  // down | 
|---|
|  |  |  | ); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | possibleNodes.parallelStream() | 
|---|
|  |  |  | 
|---|
|  |  |  | return neighbourNodes; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | private NavigateNode extendNeighborNodes(NavigateNode currentNode, NavigateNode extendNode, int[][] mapMatrix, Set<NavigateNode> existNodes, Integer dx, Integer dy) { | 
|---|
|  |  |  | NavigateNode nextNode; | 
|---|
|  |  |  | private AStarNavigateNode extendNeighborNodes(AStarNavigateNode currentNode, AStarNavigateNode extendNode, int[][] mapMatrix, Set<AStarNavigateNode> existNodes, Integer dx, Integer dy) { | 
|---|
|  |  |  | AStarNavigateNode nextNode; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 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); | 
|---|
|  |  |  | nextNode = new AStarNavigateNode(extendNode.getX() + dx, extendNode.getY() + dy); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | int x = nextNode.getX(); | 
|---|
|  |  |  | 
|---|
|  |  |  | //------------------A*启发函数------------------// | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //计算通过现在的结点的位置和最终结点的位置计算H值(曼哈顿法:坐标分别取差值相加) | 
|---|
|  |  |  | private int calcNodeCost(NavigateNode node1, NavigateNode node2) { | 
|---|
|  |  |  | private int calcNodeCost(AStarNavigateNode node1, AStarNavigateNode 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 0; | 
|---|
|  |  |  | // 转弯判断:只允许“垂直或水平”运动 | 
|---|
|  |  |  | private boolean isTurning(AStarNavigateNode currNode, AStarNavigateNode nextNode) { | 
|---|
|  |  |  | // 第一个点 | 
|---|
|  |  |  | if (currNode.getParent() == null) { | 
|---|
|  |  |  | return false; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | AStarNavigateNode parent = currNode.getParent(); | 
|---|
|  |  |  | // 如果下一点(nextNode)与 parent 在同一行或同一列 => 没有转弯 | 
|---|
|  |  |  | // 注意,这实际上等同于“(curr->next) 的方向 == (parent->curr) 的方向”。 | 
|---|
|  |  |  | boolean sameRowOrCol = | 
|---|
|  |  |  | (nextNode.getX() == parent.getX()) | 
|---|
|  |  |  | || (nextNode.getY() == parent.getY()); | 
|---|
|  |  |  | return !sameRowOrCol; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // 拐向终点的点 | 
|---|
|  |  |  | if (nextNode.getX() == endNode.getX() || nextNode.getY() == endNode.getY()) { | 
|---|
|  |  |  | return 1; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // 普通拐点 | 
|---|
|  |  |  | return 1; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | // 转弯判断:如果这两个向量相同(例如都等于 (0,1)),说明方向相同;否则说明转弯。 | 
|---|
|  |  |  | //    private boolean isTurning(AStarNavigateNode currNode, AStarNavigateNode nextNode) { | 
|---|
|  |  |  | //        // 如果 currNode 没有父节点,说明是起点,不算转弯 | 
|---|
|  |  |  | //        if (currNode.getParent() == null) { | 
|---|
|  |  |  | //            return false; | 
|---|
|  |  |  | //        } | 
|---|
|  |  |  | //        // 取出坐标 | 
|---|
|  |  |  | //        AStarNavigateNode parent = currNode.getParent(); | 
|---|
|  |  |  | //        int px = currNode.getX() - parent.getX();  // parent -> curr 的x偏移 | 
|---|
|  |  |  | //        int py = currNode.getY() - parent.getY();  // parent -> curr 的y偏移 | 
|---|
|  |  |  | // | 
|---|
|  |  |  | //        int nx = nextNode.getX() - currNode.getX(); // curr -> next 的x偏移 | 
|---|
|  |  |  | //        int ny = nextNode.getY() - currNode.getY(); // curr -> next 的y偏移 | 
|---|
|  |  |  | // | 
|---|
|  |  |  | //        // 如果 (px, py) 与 (nx, ny) 不一样,就说明转弯 | 
|---|
|  |  |  | //        return (px != nx) || (py != ny); | 
|---|
|  |  |  | //    } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|