| | |
| | | CREATE INDEX idx_agv_action ON man_action(agv_id, action_sts); |
| | | CREATE INDEX idx_group_io_time ON man_action(group_id, io_time); |
| | | CREATE INDEX idx_priority ON man_action(priority); |
| | | CREATE INDEX idx_priority ON man_action(priority); |
| | | |
| | | CREATE INDEX idx_action_sts_uuid ON man_action_sts(uuid); |
| | | CREATE INDEX idx_action_type_uuid ON man_action_type(uuid); |
| | | CREATE INDEX idx_agv_model_type ON man_agv_model(type); |
| | | CREATE INDEX idx_bus_sts_uuid ON man_bus_sts(uuid); |
| | | CREATE INDEX idx_loc_sts_uuid ON man_loc_sts(uuid); |
| | | CREATE INDEX idx_task_sts_uuid ON man_task_sts(uuid); |
| | | CREATE INDEX idx_task_type_uuid ON man_task_type(uuid); |
| | | CREATE INDEX idx_zone_uuid ON man_zone(uuid); |
| | | CREATE INDEX idx_agv_detail_agv_id ON man_agv_detail(agv_id); |
| | |
| | | |
| | | public static final String AGV_MAP_ROUTE_HASH_FLAG = "AGV_MAP_ROUTE_HASH_FLAG"; |
| | | |
| | | public static final String AGV_MAP_ROUTE_CDA_HASH_FLAG = "AGV_MAP_ROUTE_CDA_HASH_FLAG"; |
| | | |
| | | public static final String AGV_TRAFFIC_JAM_FLAG = "AGV_TRAFFIC_JAM_FLAG"; |
| | | |
| | | public static final String MAP_FLOYD_MATRIX_HEADER_FLAG = "MAP_FLOYD_MATRIX_HEADER_FLAG"; |
| | |
| | | , MapDataConstant.MAX_DISTANCE_BETWEEN_ADJACENT_AGV_FACTOR); |
| | | List<String> avoidPathListWave = mapService.getWaveScopeByCodeList(lev, avoidPathList, avoidDistance); |
| | | |
| | | String[][] codeMatrix = mapDataDispatcher.getCodeMatrix(lev); |
| | | DynamicNode[][] dynamicMatrix = mapDataDispatcher.getDynamicMatrix(lev); |
| | | String[][] waveMatrix = mapDataDispatcher.getWaveMatrix(lev); |
| | | |
| | |
| | | |
| | | List<RetreatNavigateNode> enableNodes = new ArrayList<>(); |
| | | |
| | | ArrayList<RetreatNavigateNode> neighborNodes = this.getNeighborNodes(currentNode, existNodes); |
| | | ArrayList<RetreatNavigateNode> neighborNodes = this.getNeighborNodes(currentNode, existNodes, codeMatrix); |
| | | boolean pointOfTurn = neighborNodes.size() >= 2; |
| | | label: for (RetreatNavigateNode node : neighborNodes) { |
| | | if (node.getCodeData().equals(breakPoint)) { continue; } |
| | | Code code = codeService.selectByData(node.getCodeData()); |
| | | |
| | | int weight = 0; |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | Code code = codeService.selectByData(node.getCodeData()); |
| | | |
| | | // judge whether the node has already been marked as a retreat node? |
| | | // This is a very troublesome matter, if the node be repeatedly mark as a retreat node |
| | | List<Segment> runningSegments = segmentService.getRunningByEndCode(code.getId()); |
| | |
| | | RetreatNavigateNode currentNode = openQueue.poll(); |
| | | List<RetreatNavigateNode> enableNodes = new ArrayList<>(); |
| | | |
| | | ArrayList<RetreatNavigateNode> neighborNodes = this.getNeighborNodes(currentNode, existNodes); |
| | | ArrayList<RetreatNavigateNode> neighborNodes = this.getNeighborNodes(currentNode, existNodes, codeMatrix); |
| | | |
| | | // 第一步:获取有效转弯点 |
| | | if (null == availablePointOfTurn) { |
| | |
| | | } |
| | | |
| | | // 获取四周节点 |
| | | private ArrayList<RetreatNavigateNode> getNeighborNodes(RetreatNavigateNode currentNode, Set<RetreatNavigateNode> existNodes) { |
| | | private ArrayList<RetreatNavigateNode> getNeighborNodes(RetreatNavigateNode currentNode, Set<RetreatNavigateNode> existNodes, String[][] codeMatrix) { |
| | | |
| | | int x = currentNode.getX(); |
| | | int y = currentNode.getY(); |
| | | |
| | | ArrayList<RetreatNavigateNode> neighbourNodes = new ArrayList<>(); |
| | | |
| | | RetreatNavigateNode rightNode = extendNeighborNodes(currentNode, new RetreatNavigateNode(x, y + 1), existNodes, null, null); |
| | | if (null != rightNode) { |
| | | neighbourNodes.add(rightNode); |
| | | } |
| | | List<RetreatNavigateNode> possibleNodes = Arrays.asList( |
| | | new RetreatNavigateNode(x, y + 1), // right |
| | | new RetreatNavigateNode(x, y - 1), // left |
| | | new RetreatNavigateNode(x - 1, y), // up |
| | | new RetreatNavigateNode(x + 1, y) // down |
| | | ); |
| | | |
| | | RetreatNavigateNode leftNode = extendNeighborNodes(currentNode, new RetreatNavigateNode(x, y - 1), existNodes, null, null); |
| | | if (null != leftNode) { |
| | | neighbourNodes.add(leftNode); |
| | | } |
| | | |
| | | RetreatNavigateNode topNode = extendNeighborNodes(currentNode, new RetreatNavigateNode(x - 1, y), existNodes, null, null); |
| | | if (null != topNode) { |
| | | neighbourNodes.add(topNode); |
| | | } |
| | | |
| | | RetreatNavigateNode bottomNode = extendNeighborNodes(currentNode, new RetreatNavigateNode(x + 1, y), existNodes, null, null); |
| | | if (null != bottomNode) { |
| | | neighbourNodes.add(bottomNode); |
| | | } |
| | | possibleNodes.parallelStream() |
| | | .map(extendNode -> extendNeighborNodes(currentNode, extendNode, existNodes, null, null)) |
| | | .filter(Objects::nonNull) |
| | | .peek(node -> node.setCodeData(codeMatrix[node.getX()][node.getY()])) |
| | | .forEach(neighbourNodes::add); |
| | | |
| | | return neighbourNodes; |
| | | } |
| | |
| | | if (mapMatrix[x][y] == MapNodeType.DISABLE.val) { |
| | | |
| | | return extendNeighborNodes(currentNode, nextNode, existNodes, dx, dy); |
| | | } |
| | | |
| | | } else { |
| | | if (existNodes.contains(nextNode)) { |
| | | return null; |
| | | } |
| | | assert mapMatrix[x][y] == MapNodeType.ENABLE.val; |
| | | |
| | | // 节点是否可用 |
| | | if (mapMatrix[x][y] != MapNodeType.ENABLE.val) { |
| | | return null; |
| | | } |
| | | if (existNodes.contains(nextNode)) { |
| | | return null; |
| | | } |
| | | |
| | | String[][] codeMatrix = mapDataDispatcher.getCodeMatrix(null); |
| | | String currentNodeCodeData = codeMatrix[currentNode.getX()][currentNode.getY()]; |
| | | String nextNodeCodeData = codeMatrix[nextNode.getX()][nextNode.getY()]; |
| | | nextNode.setCodeData(nextNodeCodeData); |
| | | |
| | | // 判断通过性 |
| | | String routeKey = RouteGenerator.generateRouteKey(currentNodeCodeData, nextNodeCodeData); |
| | | Object routeVal = redis.getMap(RedisConstant.AGV_MAP_ROUTE_HASH_FLAG, routeKey); |
| | | if (routeVal == null || !(Boolean) routeVal) { |
| | | return null; |
| | | } |
| | | // 判断通过性 |
| | | String routeCdaKey = RouteGenerator.generateRouteCdaKey(new int[]{currentNode.getX(), currentNode.getY()}, new int[]{nextNode.getX(), nextNode.getY()}); |
| | | if (!mapDataDispatcher.validRouteCdaKey(routeCdaKey)) { |
| | | return null; |
| | | } |
| | | |
| | | return nextNode; |
| | |
| | | import com.zy.acs.manager.core.service.LaneService; |
| | | 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.Route; |
| | | 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; |
| | |
| | | |
| | | public static final int WEIGHT_CALC_FACTOR = 1; |
| | | |
| | | @Autowired |
| | | private CodeService codeService; |
| | | @Autowired |
| | | private RouteService routeService; |
| | | @Autowired |
| | | private MapDataDispatcher mapDataDispatcher; |
| | | @Autowired |
| | |
| | | existNodes.add(start); |
| | | |
| | | int[][] mapMatrix = mapDataDispatcher.getMapMatrix(null, null); |
| | | String[][] codeMatrix = mapDataDispatcher.getCodeMatrix(null); |
| | | DynamicNode[][] dynamicMatrix = mapDataDispatcher.getDynamicMatrix(null); |
| | | String[][] waveMatrix = mapDataDispatcher.getWaveMatrix(null); |
| | | |
| | | while (!openQueue.isEmpty()) { |
| | | // 取优先队列顶部元素并且把这个元素从Open表中删除,取F值最小的节点 |
| | | NavigateNode currentNode = openQueue.poll(); |
| | | |
| | | ArrayList<NavigateNode> neighbourNodes = this.getNeighborNodes(currentNode, mapMatrix, existNodes); |
| | | for (NavigateNode node : neighbourNodes) { |
| | | node.setCodeData(codeMatrix[node.getX()][node.getY()]); |
| | | boolean isEndNode = node.getX() == end.getX() && node.getY() == end.getY(); |
| | | |
| | | int weight = 0; |
| | |
| | | |
| | | // 获取四周节点 |
| | | private ArrayList<NavigateNode> getNeighborNodes(NavigateNode currentNode, int[][] mapMatrix, Set<NavigateNode> existNodes) { |
| | | //获取当前结点的x, y |
| | | int x = currentNode.getX(); |
| | | int y = currentNode.getY(); |
| | | //如果当前结点的邻结点合法,就加入到neighbour_node |
| | | |
| | | ArrayList<NavigateNode> neighbourNodes = new ArrayList<>(); |
| | | |
| | | NavigateNode rightNode = extendNeighborNodes(currentNode, new NavigateNode(x, y + 1), mapMatrix, existNodes, null, null); |
| | | if (null != rightNode) { |
| | | neighbourNodes.add(rightNode); |
| | | } |
| | | 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 |
| | | ); |
| | | |
| | | NavigateNode leftNode = extendNeighborNodes(currentNode, new NavigateNode(x, y - 1), mapMatrix, existNodes, null, null); |
| | | if (null != leftNode) { |
| | | neighbourNodes.add(leftNode); |
| | | } |
| | | |
| | | NavigateNode topNode = extendNeighborNodes(currentNode, new NavigateNode(x - 1, y), mapMatrix, existNodes, null, null); |
| | | if (null != topNode) { |
| | | neighbourNodes.add(topNode); |
| | | } |
| | | |
| | | NavigateNode bottomNode = extendNeighborNodes(currentNode, new NavigateNode(x + 1, y), mapMatrix, existNodes, null, null); |
| | | if (null != bottomNode) { |
| | | neighbourNodes.add(bottomNode); |
| | | } |
| | | possibleNodes.parallelStream() |
| | | .map(extendNode -> extendNeighborNodes(currentNode, extendNode, mapMatrix, existNodes, null, null)) |
| | | .filter(Objects::nonNull) |
| | | .forEach(neighbourNodes::add); |
| | | |
| | | return neighbourNodes; |
| | | } |
| | | |
| | | private NavigateNode extendNeighborNodes(NavigateNode currentNode, NavigateNode extendNode, int[][] mapMatrix, Set<NavigateNode> existNodes, Integer dx, Integer dy) { |
| | | NavigateNode nextNode = null; |
| | | NavigateNode nextNode; |
| | | |
| | | if (null == dx || null == dy) { |
| | | dx = extendNode.getX() - currentNode.getX(); |
| | |
| | | if (mapMatrix[x][y] == MapNodeType.DISABLE.val) { |
| | | |
| | | return extendNeighborNodes(currentNode, nextNode, mapMatrix, existNodes, dx, dy); |
| | | |
| | | } else { |
| | | |
| | | if (existNodes.contains(nextNode)) { |
| | | 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); |
| | | |
| | | // 判断通过性 |
| | | String routeKey = RouteGenerator.generateRouteKey(currentNodeCodeData, nextNodeCodeData); |
| | | Object routeVal = redis.getMap(RedisConstant.AGV_MAP_ROUTE_HASH_FLAG, routeKey); |
| | | if (routeVal == null || !(Boolean) routeVal) { |
| | | return null; |
| | | } |
| | | |
| | | return nextNode; |
| | | } |
| | | |
| | | assert mapMatrix[x][y] == MapNodeType.ENABLE.val; |
| | | |
| | | if (existNodes.contains(nextNode)) { |
| | | return null; |
| | | } |
| | | |
| | | // 判断通过性 |
| | | String routeCdaKey = RouteGenerator.generateRouteCdaKey(new int[]{currentNode.getX(), currentNode.getY()}, new int[]{nextNode.getX(), nextNode.getY()}); |
| | | if (!mapDataDispatcher.validRouteCdaKey(routeCdaKey)) { |
| | | return null; |
| | | } |
| | | |
| | | return nextNode; |
| | | } |
| | | |
| | | //------------------A*启发函数------------------// |
| | |
| | | |
| | | private String[][] cdaMatrix; |
| | | |
| | | public Map<String, Boolean> routeCdaMap = new HashMap<>(); |
| | | |
| | | private final CodeService codeService; |
| | | |
| | | private final RouteService routeService; |
| | |
| | | return mapMatrix; |
| | | } |
| | | |
| | | public boolean validRouteCdaKey(String routeCdaKey) { |
| | | if (Cools.isEmpty(routeCdaKey)) { |
| | | return false; |
| | | } |
| | | Boolean result = this.routeCdaMap.get(routeCdaKey); |
| | | if (null == result) { |
| | | return false; |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | public synchronized void initRouteMap(Integer lev) { |
| | | log.info("There is initializing Route Map......"); |
| | | lev = Optional.ofNullable(lev).orElse(MAP_DEFAULT_LEV); |
| | | Set<String> routeKeys = redis.getMapKeys(RedisConstant.AGV_MAP_ROUTE_HASH_FLAG); |
| | | Set<String> routeCdaKeys = redis.getMapKeys(RedisConstant.AGV_MAP_ROUTE_CDA_HASH_FLAG); |
| | | |
| | | List<Route> routeList = routeService.list(new LambdaQueryWrapper<Route>().eq(Route::getStatus, StatusType.ENABLE.val)); |
| | | if (routeKeys.size() == routeList.size()) { |
| | | if (routeKeys.size() == routeList.size() && routeKeys.size() == routeCdaKeys.size()) { |
| | | for (String routeCdaKey : routeCdaKeys) { |
| | | this.routeCdaMap.put(routeCdaKey, Boolean.TRUE); |
| | | } |
| | | return; |
| | | } |
| | | for (Route route : routeList) { |
| | | Code startCode = codeService.getById(route.getStartCode()); |
| | | int[] startCodeIdx = getCodeMatrixIdx(lev, startCode.getData()); |
| | | Code endCode = codeService.getById(route.getEndCode()); |
| | | int[] codeMatrixIdx = getCodeMatrixIdx(lev, endCode.getData()); |
| | | |
| | | String routeKey = RouteGenerator.generateRouteKey(startCode.getData(), endCode.getData()); |
| | | if (Cools.isEmpty(routeKey)) { |
| | | continue; |
| | | } |
| | | redis.setMap(RedisConstant.AGV_MAP_ROUTE_HASH_FLAG, routeKey, Boolean.TRUE); |
| | | |
| | | String routeCdaKey = RouteGenerator.generateRouteCdaKey(startCodeIdx, codeMatrixIdx); |
| | | if (Cools.isEmpty(routeCdaKey)) { |
| | | continue; |
| | | } |
| | | redis.setMap(RedisConstant.AGV_MAP_ROUTE_CDA_HASH_FLAG, routeCdaKey, Boolean.TRUE); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | public static String generateRouteCdaKey(int[] code0Cda, int[] code1Cda) { |
| | | if (Cools.isEmpty(code0Cda, code1Cda)) { |
| | | return null; |
| | | } |
| | | if (code0Cda[0] < code1Cda[0] || (code0Cda[0] == code1Cda[0] && code0Cda[1] < code1Cda[1])) { |
| | | return code0Cda[0] + "," + code0Cda[1] + "-" + code1Cda[0] + "," + code1Cda[1]; |
| | | } else { |
| | | return code1Cda[0] + "," + code1Cda[1] + "-" + code0Cda[0] + "," + code0Cda[1]; |
| | | } |
| | | } |
| | | |
| | | public List<String> generateRoutes(String[][] codeMatrix) { |
| | | List<String> list = new ArrayList<>(); |
| | | |