| | |
| | | package com.zy.common.utils; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.core.common.SpringUtils; |
| | | import com.core.exception.CoolException; |
| | | import com.zy.asrs.entity.BasMap; |
| | | import com.zy.asrs.service.BasMapService; |
| | | import com.zy.common.model.NavigateNode; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.PriorityQueue; |
| | | import com.zy.core.enums.MapNodeType; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * A*算法实现类 |
| | | */ |
| | | public class NavigateSolution { |
| | | |
| | | // -1 -> 墙壁, 1 -> 起点 2 -> 终点 3-> 母轨 4->站点 |
| | | |
| | | int[][] map = {{}}; |
| | | |
| | | public NavigateSolution() { |
| | | //载入地图 |
| | | NavigateMapData mapData = new NavigateMapData(); |
| | | int[][] data = mapData.getData(); |
| | | this.map = data; |
| | | } |
| | | |
| | | public NavigateSolution(Integer mapType, Integer lev, List<int[]> whitePoints, List<int[]> shuttlePoints) { |
| | | //载入地图指定层高地图 |
| | | NavigateMapData mapData = new NavigateMapData(lev); |
| | | int[][] data = mapData.getDataFromRedis(mapType, whitePoints, shuttlePoints); |
| | | if (data == null) { |
| | | data = mapData.getData(mapType, whitePoints, shuttlePoints); |
| | | } |
| | | this.map = data; |
| | | } |
| | | |
| | | public NavigateSolution(int[][] data) { |
| | | this.map = data; |
| | | } |
| | | |
| | | // Open表用优先队列 |
| | | public PriorityQueue<NavigateNode> Open = new PriorityQueue<NavigateNode>(); |
| | | //Close表用普通的数组 |
| | | public ArrayList<NavigateNode> Close = new ArrayList<NavigateNode>(); |
| | | //Exist表用来存放已经出现过的结点。 |
| | | public ArrayList<NavigateNode> Exist = new ArrayList<NavigateNode>(); |
| | | //用来存放已经出现过的结点。 |
| | | Map<String, Integer> bestGMap = new HashMap<>(); |
| | | |
| | | public NavigateNode astarSearch(NavigateNode start, NavigateNode end) { |
| | | public List<List<NavigateNode>> getStationMap(int lev) { |
| | | BasMapService basMapService = SpringUtils.getBean(BasMapService.class); |
| | | BasMap basMap = basMapService.selectOne(new EntityWrapper<BasMap>().eq("lev", lev)); |
| | | if (basMap == null) { |
| | | throw new CoolException("地图不存在"); |
| | | } |
| | | |
| | | List<List<JSONObject>> dataList = JSON.parseObject(basMap.getData(), List.class); |
| | | |
| | | List<List<NavigateNode>> navigateNodeList = new ArrayList<>(); |
| | | for (int i = 0; i < dataList.size(); i++) { |
| | | List<JSONObject> row = dataList.get(i); |
| | | List<NavigateNode> navigateNodeRow = new ArrayList<>(); |
| | | for (int j = 0; j < row.size(); j++) { |
| | | JSONObject map = row.get(j); |
| | | NavigateNode navigateNode = new NavigateNode(i, j); |
| | | |
| | | String nodeType = map.getString("type"); |
| | | if(nodeType == null) { |
| | | navigateNode.setValue(MapNodeType.DISABLE.id); |
| | | }else if(nodeType.equals("devp") || nodeType.equals("merge")){ |
| | | navigateNode.setValue(MapNodeType.NORMAL_PATH.id); |
| | | |
| | | JSONObject valueObj = JSON.parseObject(map.getString("value")); |
| | | List<String> directionList = valueObj.getJSONArray("direction").toJavaList(String.class); |
| | | navigateNode.setDirectionList(directionList); |
| | | }else { |
| | | navigateNode.setValue(MapNodeType.DISABLE.id); |
| | | } |
| | | |
| | | navigateNode.setNodeType(nodeType); |
| | | navigateNode.setNodeValue(map.getString("value")); |
| | | navigateNodeRow.add(navigateNode); |
| | | } |
| | | navigateNodeList.add(navigateNodeRow); |
| | | } |
| | | |
| | | return navigateNodeList; |
| | | } |
| | | |
| | | public List<List<NavigateNode>> getRgvTrackMap(int lev) { |
| | | BasMapService basMapService = SpringUtils.getBean(BasMapService.class); |
| | | BasMap basMap = basMapService.selectOne(new EntityWrapper<BasMap>().eq("lev", lev)); |
| | | if (basMap == null) { |
| | | throw new CoolException("地图不存在"); |
| | | } |
| | | |
| | | List<List<JSONObject>> dataList = JSON.parseObject(basMap.getData(), List.class); |
| | | |
| | | List<List<NavigateNode>> navigateNodeList = new ArrayList<>(); |
| | | for (int i = 0; i < dataList.size(); i++) { |
| | | List<JSONObject> row = dataList.get(i); |
| | | List<NavigateNode> navigateNodeRow = new ArrayList<>(); |
| | | for (int j = 0; j < row.size(); j++) { |
| | | JSONObject map = row.get(j); |
| | | NavigateNode navigateNode = new NavigateNode(i, j); |
| | | |
| | | String nodeType = map.getString("type"); |
| | | if(nodeType == null) { |
| | | navigateNode.setValue(MapNodeType.DISABLE.id); |
| | | }else if(nodeType.equals("rgv")){ |
| | | navigateNode.setValue(MapNodeType.NORMAL_PATH.id); |
| | | JSONObject valueObj = JSON.parseObject(map.getString("value")); |
| | | |
| | | //RGV暂不控制行走方向,默认上下左右都可走 |
| | | List<String> directionList = new ArrayList<>(); |
| | | directionList.add("top"); |
| | | directionList.add("bottom"); |
| | | directionList.add("left"); |
| | | directionList.add("right"); |
| | | navigateNode.setDirectionList(directionList); |
| | | }else { |
| | | navigateNode.setValue(MapNodeType.DISABLE.id); |
| | | } |
| | | |
| | | navigateNode.setNodeType(nodeType); |
| | | navigateNode.setNodeValue(map.getString("value")); |
| | | navigateNodeRow.add(navigateNode); |
| | | } |
| | | navigateNodeList.add(navigateNodeRow); |
| | | } |
| | | |
| | | return navigateNodeList; |
| | | } |
| | | |
| | | public NavigateNode astarSearchJava(List<List<NavigateNode>> map, NavigateNode start, NavigateNode end) { |
| | | // 清理上次搜索的状态,防止复用实例导致记录残留 |
| | | this.Open.clear(); |
| | | this.Close.clear(); |
| | | this.bestGMap.clear(); |
| | | //把第一个开始的结点加入到Open表中 |
| | | this.Open.add(start); |
| | | //把出现过的结点加入到Exist表中 |
| | | this.Exist.add(start); |
| | | //主循环 |
| | | while (Open.size() > 0) { |
| | | //取优先队列顶部元素并且把这个元素从Open表中删除 |
| | | NavigateNode current_node = Open.poll(); |
| | | |
| | | if (current_node.getX() == end.getX() && current_node.getY() == end.getY()) {//找到目标结点就返回 |
| | | return current_node; |
| | | } |
| | | |
| | | //将这个结点加入到Close表中 |
| | | Close.add(current_node); |
| | | //对当前结点进行扩展,得到一个四周结点的数组 |
| | | ArrayList<NavigateNode> neighbour_node = extend_current_node(current_node); |
| | | ArrayList<NavigateNode> neighbour_node = extend_current_node(map, current_node); |
| | | //对这个结点遍历,看是否有目标结点出现 |
| | | for (NavigateNode node : neighbour_node) { |
| | | // G + H + E (对启发函数增加去拐点方案calcNodeExtraCost) |
| | | int gCost = calcNodeCost(current_node, node) * calcNodeExtraCost(current_node, node, end); |
| | | if (node.getX() == end.getX() && node.getY() == end.getY()) {//找到目标结点就返回 |
| | | //init_node操作把这个邻居结点的父节点设置为当前结点 |
| | | //并且计算出G, F, H等值 |
| | | node.init_node(current_node, end); |
| | | return node; |
| | | // 已在关闭列表中的节点不再处理,避免父链反复改写形成环 |
| | | if (Close.contains(node)) { |
| | | continue; |
| | | } |
| | | // G + H + E (对启发函数增加去拐点方案calcNodeExtraCost) |
| | | int gCost = calcNodeExtraCost(current_node, node, end); |
| | | |
| | | //(对启发函数增加去拐点方案calcNodeExtraCost) |
| | | if (is_exist(node)) { |
| | | if (gCost < node.getG()) { |
| | | node.setFather(current_node); |
| | | node.setG(gCost); |
| | | node.setF(node.getG() + node.getH()); |
| | | } |
| | | }else { |
| | | //没出现过的结点加入到Open表中并且设置父节点 |
| | | //进行计算对G, F, H 等值 |
| | | node.init_node(current_node, end); |
| | | node.setG(gCost); |
| | | node.setH(calcNodeCost(node, end)); |
| | | node.setF(node.getG() + node.getH()); |
| | | //进行计算对G, F, H 等值 |
| | | node.setG(1 + gCost); |
| | | node.init_node(current_node, end); |
| | | node.setH(calcNodeCost(node, end)); |
| | | node.setF(node.getG() + node.getH()); |
| | | |
| | | String key = node.getX() + "_" + node.getY(); |
| | | Integer recordedG = bestGMap.get(key); |
| | | // 仅当找到更小的代价时才更新与入Open,避免等价代价反复入队导致父链抖动 |
| | | if (recordedG == null || node.getG() < recordedG) { |
| | | bestGMap.put(key, node.getG()); |
| | | |
| | | Open.add(node); |
| | | Exist.add(node); |
| | | } |
| | | } |
| | | } |
| | |
| | | return null; |
| | | } |
| | | |
| | | |
| | | public ArrayList<NavigateNode> extend_current_node(NavigateNode current_node) { |
| | | public ArrayList<NavigateNode> extend_current_node(List<List<NavigateNode>> map, NavigateNode current_node) { |
| | | //获取当前结点的x, y |
| | | int x = current_node.getX(); |
| | | int y = current_node.getY(); |
| | | //如果当前结点的邻结点合法,就加入到neighbour_node |
| | | ArrayList<NavigateNode> neighbour_node = new ArrayList<NavigateNode>(); |
| | | // if (map[x][y] == 0 || map[x][y] == 3) { |
| | | // //只有子轨和母轨才能进行左右移动 |
| | | // if (is_valid(x, y + 1)) |
| | | // { |
| | | // Node node = new Node(x, y + 1); |
| | | // neighbour_node.add(node); |
| | | // } |
| | | // if (is_valid(x, y - 1)) |
| | | // { |
| | | // Node node = new Node(x, y - 1); |
| | | // neighbour_node.add(node); |
| | | // } |
| | | // } |
| | | // |
| | | // if (map[x][y] == 3) { |
| | | // //只有母轨才能进行上下移动 |
| | | // if (is_valid(x + 1, y)) |
| | | // { |
| | | // Node node = new Node(x + 1, y); |
| | | // neighbour_node.add(node); |
| | | // } |
| | | // if (is_valid(x - 1, y)) |
| | | // { |
| | | // Node node = new Node(x -1, y); |
| | | // neighbour_node.add(node); |
| | | // } |
| | | // } |
| | | if (map[x][y] == 3) { |
| | | //母轨才能进行左右移动 |
| | | if (is_valid(x, y + 1)) |
| | | { |
| | | NavigateNode node = new NavigateNode(x, y + 1); |
| | | neighbour_node.add(node); |
| | | } |
| | | if (is_valid(x, y - 1)) |
| | | { |
| | | NavigateNode node = new NavigateNode(x, y - 1); |
| | | neighbour_node.add(node); |
| | | } |
| | | |
| | | if(current_node.getValue() == MapNodeType.DISABLE.id) { |
| | | return neighbour_node; |
| | | } |
| | | |
| | | if (map[x][y] == 0 || map[x][y] == 3 || map[x][y] == 4 || map[x][y] == 5) { |
| | | //子轨和母轨、输送线、充电桩才能进行上下移动 |
| | | if (is_valid(x + 1, y)) |
| | | { |
| | | NavigateNode node = new NavigateNode(x + 1, y); |
| | | neighbour_node.add(node); |
| | | } |
| | | if (is_valid(x - 1, y)) |
| | | { |
| | | NavigateNode node = new NavigateNode(x -1, y); |
| | | neighbour_node.add(node); |
| | | List<String> directionList = current_node.getDirectionList(); |
| | | if(directionList == null || directionList.size() == 0) { |
| | | return neighbour_node; |
| | | } |
| | | |
| | | for(String direction : directionList) { |
| | | if(direction.equals("top")) { |
| | | NavigateNode node = getValidNavigateNode(map, x - 1, y); |
| | | if(node != null) { |
| | | neighbour_node.add(node); |
| | | } |
| | | }else if(direction.equals("bottom")) { |
| | | NavigateNode node = getValidNavigateNode(map, x + 1, y); |
| | | if(node != null) { |
| | | neighbour_node.add(node); |
| | | } |
| | | }else if(direction.equals("left")) { |
| | | NavigateNode node = getValidNavigateNode(map, x, y - 1); |
| | | if(node != null) { |
| | | neighbour_node.add(node); |
| | | } |
| | | }else if(direction.equals("right")) { |
| | | NavigateNode node = getValidNavigateNode(map, x, y + 1); |
| | | if(node != null) { |
| | | neighbour_node.add(node); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return neighbour_node; |
| | | } |
| | | |
| | | public boolean is_valid(int x, int y) { |
| | | // 如果结点的位置小于0,则不合法 |
| | | if (map[x][y] < 0) return false; |
| | | for (NavigateNode node : Exist) { |
| | | //如果结点出现过,不合法 |
| | | if (node.getX() == x && node.getY() == y) { |
| | | return false; |
| | | } |
| | | if (is_exist(new NavigateNode(x, y))) { |
| | | return false; |
| | | } |
| | | public NavigateNode getValidNavigateNode(List<List<NavigateNode>> map, int x, int y) { |
| | | if (x < 0 || x >= map.size() |
| | | || y < 0 || y >= map.get(0).size()) { |
| | | return null; |
| | | } |
| | | //以上情况都没有则合法 |
| | | return true; |
| | | |
| | | NavigateNode node = map.get(x).get(y); |
| | | if(node.getValue() == MapNodeType.DISABLE.id) { |
| | | return null; |
| | | } |
| | | |
| | | return node; |
| | | } |
| | | |
| | | public boolean is_exist(NavigateNode node) |
| | | { |
| | | for (NavigateNode exist_node : Exist) { |
| | | if (node.getX() == exist_node.getX() && node.getY() == exist_node.getY()) { |
| | | return true; |
| | | public NavigateNode findStationNavigateNode(List<List<NavigateNode>> map, int stationId) { |
| | | for(int x = 0; x < map.size(); x++) { |
| | | for(int y = 0; y < map.get(0).size(); y++) { |
| | | NavigateNode node = map.get(x).get(y); |
| | | if("devp".equals(node.getNodeType())) { |
| | | JSONObject valueObj = JSON.parseObject(node.getNodeValue()); |
| | | if(valueObj.getInteger("stationId") == stationId) { |
| | | return node; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return false; |
| | | return null; |
| | | } |
| | | |
| | | public NavigateNode findTrackSiteNoNavigateNode(List<List<NavigateNode>> map, int trackSiteNo) { |
| | | for(int x = 0; x < map.size(); x++) { |
| | | for(int y = 0; y < map.get(0).size(); y++) { |
| | | NavigateNode node = map.get(x).get(y); |
| | | if("rgv".equals(node.getNodeType())) { |
| | | JSONObject valueObj = JSON.parseObject(node.getNodeValue()); |
| | | if(valueObj.getInteger("trackSiteNo") == trackSiteNo) { |
| | | return node; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | //------------------A*启发函数------------------// |
| | |
| | | 拿到父节点和下一节点 |
| | | 通过判断父节点和下一节点的x数据和y数据都不相同时,则表明当前坐标是一个拐点 |
| | | */ |
| | | return 10; |
| | | return 1; |
| | | } |
| | | |
| | | //------------------A*启发函数-end------------------// |
| | | |
| | | } |
| | | } |