|  |  | 
 |  |  | package com.zy.acs.manager.core.service.astart; | 
 |  |  |  | 
 |  |  | 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.VehicleDto; | 
 |  |  | 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.CodeGapService; | 
 |  |  | import com.zy.acs.manager.manager.entity.Segment; | 
 |  |  | import com.zy.acs.manager.manager.service.CodeService; | 
 |  |  | import com.zy.acs.manager.manager.service.JamService; | 
 |  |  | 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; | 
 |  |  | import java.util.*; | 
 |  |  |  | 
 |  |  | /** | 
 |  |  |  * Created by vincent on 6/12/2024 | 
 |  |  | 
 |  |  | @Service | 
 |  |  | public class AStarNavigateService { | 
 |  |  |  | 
 |  |  |     private final RedisSupport redis = RedisSupport.defaultRedisSupport; | 
 |  |  |  | 
 |  |  |     public static final boolean OPEN_TURN_COST_WEIGHT = Boolean.FALSE; | 
 |  |  |  | 
 |  |  |     public static final int WEIGHT_CALC_FACTOR = 1; | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private CodeService codeService; | 
 |  |  |     @Autowired | 
 |  |  |     private CodeGapService codeGapService; | 
 |  |  |     @Autowired | 
 |  |  |     private RouteService routeService; | 
 |  |  |     @Autowired | 
 |  |  |     private MapDataDispatcher mapDataDispatcher; | 
 |  |  |     @Autowired | 
 |  |  |     private AgvService agvService; | 
 |  |  |  | 
 |  |  |     public static final boolean OPEN_TURN_COST_WEIGHT = Boolean.FALSE; | 
 |  |  |     private JamService jamService; | 
 |  |  |     @Autowired | 
 |  |  |     private LaneService laneService; | 
 |  |  |     @Autowired | 
 |  |  |     private ConfigService configService; | 
 |  |  |  | 
 |  |  |     public synchronized NavigateNode execute(String agvNo, NavigateNode start, NavigateNode end | 
 |  |  |             , Boolean lock, List<String> whiteList, List<String> blackList) { | 
 |  |  |             , 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<>(); | 
 |  |  |         ArrayList<NavigateNode> existNodes = new ArrayList<>(); | 
 |  |  | 
 |  |  |         DynamicNode[][] dynamicMatrix = mapDataDispatcher.getDynamicMatrix(null); | 
 |  |  |         String[][] waveMatrix = mapDataDispatcher.getWaveMatrix(null); | 
 |  |  |  | 
 |  |  |         List<String> included = new ArrayList<>(); | 
 |  |  | //        if (!Cools.isEmpty(whiteList)) { | 
 |  |  | //            included.addAll(whiteList); | 
 |  |  | //        } | 
 |  |  |         included.add(agvNo); | 
 |  |  |         List<VehicleDto> vehicleDtoList = agvService.getVehicleDtoList(included); | 
 |  |  |  | 
 |  |  |         while (openQueue.size() > 0) { | 
 |  |  |             // 取优先队列顶部元素并且把这个元素从Open表中删除,取F值最小的节点 | 
 |  |  |             NavigateNode currentNode = openQueue.poll(); | 
 |  |  |             // 对当前结点进行扩展,得到一个四周结点的数组 | 
 |  |  |             ArrayList<NavigateNode> 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; | 
 |  |  |                         } | 
 |  |  |             ArrayList<NavigateNode> neighbourNodes = this.getNeighborNodes(currentNode, mapMatrix, existNodes); | 
 |  |  |             for (NavigateNode node : neighbourNodes) { | 
 |  |  |                 boolean isEndNode = node.getX() == end.getX() && node.getY() == end.getY(); | 
 |  |  |  | 
 |  |  |                 int weight = 0; | 
 |  |  |  | 
 |  |  |                 if (!Cools.isEmpty(blackList) && blackList.contains(node.getCodeData())) { | 
 |  |  |                     continue; | 
 |  |  |                 } | 
 |  |  |                 // 特殊情况,当blackList有且只有一个元素且为startNode时 | 
 |  |  |                 // 说明blackList已经知道当前导航起始点和目标点为相邻节点 | 
 |  |  |                 // 但是当前blackList的任务是不让系统走相邻的最短路径,所以才会有下面的判断和continue | 
 |  |  |                 if (blackList.size() == 1 && blackList.get(0).equals(start.getCodeData())) { | 
 |  |  |                     if (isEndNode && currentNode.getCodeData().equals(start.getCodeData())) { | 
 |  |  |                         continue; | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |  | 
 |  |  | 
 |  |  |                 if (!vehicle.equals(DynamicNodeType.ACCESS.val)) { | 
 |  |  |                     if (!vehicle.equals(agvNo)) { | 
 |  |  |  | 
 |  |  |                         if (!Cools.isEmpty(blackList) && blackList.contains(vehicle)) { | 
 |  |  |                             continue; | 
 |  |  |                         // vehicle已经为当前segment做过了避让,且避让任务已完成,则权重值增加 | 
 |  |  |                         if (null != segment) { | 
 |  |  |                             if (!Cools.isEmpty(jamService.getJamFromSegmentByAvo(segment, vehicle))) { | 
 |  |  |                                 weight += WEIGHT_CALC_FACTOR; | 
 |  |  |                             } | 
 |  |  |                         } | 
 |  |  |  | 
 |  |  |                         if (lock) { | 
 |  |  |                             continue; | 
 |  |  |                         } | 
 |  |  | 
 |  |  |                     List<String> otherWaveList = MapDataUtils.hasOtherWave(waveNodeList, agvNo); | 
 |  |  |  | 
 |  |  |                     if (!Cools.isEmpty(otherWaveList)) { | 
 |  |  |                         if (!Cools.isEmpty(blackList) && !Cools.isEmpty(MapDataUtils.hasIntersection(otherWaveList, blackList))) { | 
 |  |  |                             continue; | 
 |  |  |                         } | 
 |  |  |  | 
 |  |  |                         if (lock) { | 
 |  |  |                             continue; | 
 |  |  | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |  | 
 |  |  |                 // 单巷道车辆容载数量 | 
 |  |  |                 Lane lane = laneService.search(node.getCodeData()); | 
 |  |  |                 if (null != lane) { | 
 |  |  |                     Set<String> lanVehicleSet = new HashSet<>(); | 
 |  |  |  | 
 |  |  |                     List<String> 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)) { | 
 |  |  |                                 lanVehicleSet.add(laneVehicle); | 
 |  |  | //                                redis.setObject(RedisConstant.AGV_TO_STANDBY_FLAG, laneVehicle, true, 30); | 
 |  |  |                             } | 
 |  |  |                         } | 
 |  |  |                     } | 
 |  |  |  | 
 |  |  |                     if (lanVehicleSet.size() + 1 > maxAgvCountInLane) { | 
 |  |  |                         continue; | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |                 //找到目标结点就返回 | 
 |  |  |                 if (node.getX() == end.getX() && node.getY() == end.getY()) { | 
 |  |  |                 if (isEndNode) { | 
 |  |  |                     //并且计算出G, F, H等值 | 
 |  |  |                     node.initNode(currentNode, end); | 
 |  |  |                     return node; | 
 |  |  | 
 |  |  |                 int gCost = calcNodeCost(currentNode, node) * (OPEN_TURN_COST_WEIGHT ? calcNodeTurnCost(currentNode, node, end) : 1); | 
 |  |  |  | 
 |  |  |                 //进行计算对 G, F, H 等值 | 
 |  |  |                 node.setWeight(weight); | 
 |  |  |                 node.setLastDistance(gCost); | 
 |  |  |                 node.initNode(currentNode, end); | 
 |  |  |                 node.setH(calcNodeCost(node, end)); | 
 |  |  | 
 |  |  |  | 
 |  |  |     //计算通过现在的结点的位置和最终结点的位置计算H值(曼哈顿法:坐标分别取差值相加) | 
 |  |  |     private int calcNodeCost(NavigateNode node1, NavigateNode node2) { | 
 |  |  | //        Code code1 = codeService.selectByData(node1.getCodeData()); | 
 |  |  | //        Code code2 = codeService.selectByData(node2.getCodeData()); | 
 |  |  | //        return (int) (Math.abs(code2.getX() - code1.getX()) + Math.abs(code2.getY() - code1.getY())); | 
 |  |  |  | 
 |  |  |         return Math.abs(node2.getX() - node1.getX()) + Math.abs(node2.getY() - node1.getY()); | 
 |  |  |     } |