自动化立体仓库 - WCS系统
zc
2025-04-24 58eaf5e73359f7164525d9c50f6e5bf82b247e32
src/main/java/com/zy/common/utils/NavigateUtils.java
@@ -10,12 +10,16 @@
import com.zy.core.News;
import com.zy.core.enums.MapNodeType;
import com.zy.core.model.PythonSimilarityResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
/**
 * A*算法使用工具
@@ -25,11 +29,16 @@
    @Value("${pythonCalcPath}")
    private String pythonCalcPath;
    @Value("${pythonCalcSimilarity}")
    private String pythonCalcSimilarity;
    @Autowired
    private NavigateMapData navigateMapData;
    public List<NavigateNode> calc(String startPoint, String endPoint, Integer mapType, List<int[]> shuttlePoints, List<int[]> whites) {
        return calcJava(startPoint, endPoint, mapType, shuttlePoints, whites);
    }
    public List<NavigateNode> calcJava(String startPoint, String endPoint, Integer mapType, List<int[]> shuttlePoints, List<int[]> whites) {
        //通过开始编号和结束编号获取对应的xy轴坐标
        int[] startArr = NavigatePositionConvert.positionToXY(startPoint);//开始节点
        int[] endArr = NavigatePositionConvert.positionToXY(endPoint);//结束节点
@@ -42,17 +51,93 @@
        //获取当前节点计算的层高,并赋值到每一个节点中
        int lev = Utils.getLev(startPoint);
        NavigateSolution solution = new NavigateSolution(mapType, lev, whiteList, shuttlePoints);
        int[][] map = solution.map;
        //初始化开始节点
        NavigateNode start = new NavigateNode(startArr[0], startArr[1]);
        //开始节点无父节点
        start.setFather(null);
        start.setNodeValue(map[startArr[0]][startArr[1]]);
        NavigateNode end = new NavigateNode(endArr[0], endArr[1]);
        NavigateSolution solution = new NavigateSolution(mapType, lev, whiteList, shuttlePoints);
        end.setNodeValue(map[endArr[0]][endArr[1]]);
        //开始节点,不纳入禁用节点内计算
        String pathStr = solution.astarSearch(start, end, pythonCalcPath);
        NavigateNode res_node = solution.astarSearchJava(start, end);
        if (res_node == null) {
            News.error("{} dash {} can't find navigate path!", startPoint, endPoint);
            return null;
        }
        ArrayList<NavigateNode> list = new ArrayList<>();
        //渲染
        NavigateNode fatherNode = null;//当前循环上一节点,用于拐点计算
        while (res_node != null) {
            res_node.setDirection(null);
            res_node.setIsInflectionPoint(false);
            res_node.setZ(lev);//设置层高
            //寻找拐点
            HashMap<String, Object> result = searchInflectionPoint(res_node, fatherNode, res_node.getFather());//分别传入当前节点、父节点、下一节点
            //判断当前节点是否为拐点
            if (Boolean.parseBoolean(result.get("result").toString())) {
                //当前为拐点
                res_node.setIsInflectionPoint(true);
                //拐点方向
                res_node.setDirection(result.get("direction").toString());
            }
            list.add(res_node);
            fatherNode = res_node;//把当前节点保存成一个父节点
            res_node = res_node.getFather();//迭代操作
        }
        Collections.reverse(list);
        //将每个节点里面的fatherNode至为null(方便后续计算时父节点过多导致显示的节点太多)
        for (NavigateNode navigateNode : list) {
            //父节点设置为null,不影响计算结果,不影响后续操作。
            //此操作仅为后续排查处理提供视觉方便。
            navigateNode.setFather(null);
        }
        //起始节点计算方向
        String direction = calcDirection(list.get(0), list.get(1));
        NavigateNode startNode = list.get(0);
        startNode.setDirection(direction);
        //更新节点列表
        list.set(0, startNode);
        return list;
    }
    public List<NavigateNode> calcPython(String startPoint, String endPoint, Integer mapType, List<int[]> shuttlePoints, List<int[]> whites) {
        //通过开始编号和结束编号获取对应的xy轴坐标
        int[] startArr = NavigatePositionConvert.positionToXY(startPoint);//开始节点
        int[] endArr = NavigatePositionConvert.positionToXY(endPoint);//结束节点
        ArrayList<int[]> whiteList = new ArrayList<>();//设置计算节点的白名单
        whiteList.add(startArr);//将开始节点设置为白名单,以防被过滤
        if (whites != null && !whites.isEmpty()) {
            whiteList.addAll(whites);//批量添加白名单节点
        }
        //获取当前节点计算的层高,并赋值到每一个节点中
        int lev = Utils.getLev(startPoint);
        NavigateSolution solution = new NavigateSolution(mapType, lev, whiteList, shuttlePoints);
        int[][] map = solution.map;
        //初始化开始节点
        NavigateNode start = new NavigateNode(startArr[0], startArr[1]);
        start.setNodeValue(map[startArr[0]][startArr[1]]);
        //开始节点无父节点
        start.setFather(null);
        NavigateNode end = new NavigateNode(endArr[0], endArr[1]);
        end.setNodeValue(map[endArr[0]][endArr[1]]);
        //开始节点,不纳入禁用节点内计算
        String pathStr = solution.astarSearchPython(start, end, pythonCalcPath);
        if (pathStr == null) {
            News.error("{} dash {} can't find navigate path!", startPoint, endPoint);
            return null;
@@ -106,7 +191,7 @@
    }
    //判断当前节点到下一个节点是否为拐点
    public HashMap<String,Object> searchInflectionPoint(NavigateNode currentNode, NavigateNode fatherNode, NavigateNode nextNode) {
    public HashMap<String, Object> searchInflectionPoint(NavigateNode currentNode, NavigateNode fatherNode, NavigateNode nextNode) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("result", false);//是否为拐点,true:拐点,false:直线
        // 第一个点或直线点
@@ -136,7 +221,7 @@
            if (currentNode.getX() - fatherNode.getX() > 0) {
                //大于0,方向top
                direction = "top";
            }else {
            } else {
                //小于0,方向bottom
                direction = "bottom";
            }
@@ -148,7 +233,7 @@
            if (currentNode.getY() - fatherNode.getY() > 0) {
                //大于0,方向left
                direction = "left";
            }else {
            } else {
                //小于0,方向right
                direction = "right";
            }
@@ -272,8 +357,7 @@
     * 检测路径是否可用(可走)
     */
    public boolean checkPathIsAvailable(List<NavigateNode> path, Integer shuttleNo, Integer lev) {
        NavigateSolution solution = new NavigateSolution(NavigationMapType.DFX.id, lev, null, Utils.getShuttlePoints(shuttleNo, lev));//获取无白名单地图(该地图包含小车坐标)
        int[][] map = solution.map;
        int[][] map = navigateMapData.getDataFromRedis(lev, NavigationMapType.DFX.id, null, Utils.getShuttlePoints(shuttleNo, lev));
        for (NavigateNode node : path) {
            int value = map[node.getX()][node.getY()];
            if (value != MapNodeType.NORMAL_PATH.id && value != MapNodeType.MAIN_PATH.id && value != MapNodeType.CHARGE.id && value != MapNodeType.CONVEYOR_CAR_GO.id) {//母轨道3、子轨道0、充电桩5、小车可走输送站