#
Junjie
昨天 c4b6b51afdd3374735ed5f358457987eaa6e476f
src/main/java/com/zy/common/utils/ShuttleOperaUtils.java
@@ -3,9 +3,7 @@
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.SpringUtils;
import com.core.exception.CoolException;
import com.zy.asrs.entity.BasShuttle;
import com.zy.asrs.entity.DeviceConfig;
import com.zy.asrs.service.BasShuttleService;
import com.zy.asrs.service.DeviceConfigService;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.MapNode;
@@ -15,9 +13,9 @@
import com.zy.core.cache.SlaveConnection;
import com.zy.core.dispatcher.ShuttleDispatchUtils;
import com.zy.core.enums.MapNodeType;
import com.zy.core.enums.RedisKeyType;
import com.zy.core.enums.ShuttleRunDirection;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.ShuttleSlave;
import com.zy.core.model.command.ShuttleAssignCommand;
import com.zy.core.model.command.ShuttleCommand;
import com.zy.core.model.protocol.ShuttleProtocol;
@@ -37,11 +35,7 @@
public class ShuttleOperaUtils {
    @Autowired
    private BasShuttleService basShuttleService;
    @Autowired
    private NavigateUtils navigateUtils;
    @Autowired
    private NavigateMapUtils navigateMapUtils;
    @Autowired
    private NavigateMapData navigateMapData;
    @Autowired
@@ -50,25 +44,42 @@
    private ShuttleDispatchUtils shuttleDispatchUtils;
    @Autowired
    private DeviceConfigService deviceConfigService;
    @Autowired
    private RedisUtil redisUtil;
    public synchronized List<ShuttleCommand> getStartToTargetCommands(String startLocNo, String endLocNo, List<NavigationMapType> mapTypes, ShuttleAssignCommand assignCommand, ShuttleThread shuttleThread) {
        return getStartToTargetCommands(startLocNo, endLocNo, mapTypes, null, assignCommand, shuttleThread);
        return getStartToTargetCommands(startLocNo, endLocNo, mapTypes, null, assignCommand, shuttleThread, "move");
    }
    public synchronized List<ShuttleCommand> getStartToTargetCommands(String startLocNo, String endLocNo, List<NavigationMapType> mapTypes, List<int[]> whites, ShuttleAssignCommand assignCommand, ShuttleThread shuttleThread) {
    public synchronized List<ShuttleCommand> getStartToTargetCommands(String startLocNo, String endLocNo, List<NavigationMapType> mapTypes, ShuttleAssignCommand assignCommand, ShuttleThread shuttleThread, String moveType) {
        return getStartToTargetCommands(startLocNo, endLocNo, mapTypes, null, assignCommand, shuttleThread, moveType);
    }
    public synchronized List<ShuttleCommand> getStartToTargetCommands(String startLocNo, String endLocNo, List<NavigationMapType> mapTypes, List<int[]> whites, ShuttleAssignCommand assignCommand, ShuttleThread shuttleThread, String moveType) {
        ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
        if (shuttleProtocol == null) {
            return null;
        }
        Integer shuttleNo = shuttleProtocol.getShuttleNo();
        //获取小车移动速度
        Integer runSpeed = Optional.ofNullable(basShuttleService.selectOne(new EntityWrapper<BasShuttle>().eq("shuttle_no", shuttleNo)).getRunSpeed()).orElse(1000);
        Integer runSpeed = 1000;
        Object speedObj = redisUtil.get(RedisKeyType.SHUTTLE_SPEED_MAP.key);
        if (speedObj != null) {
            HashMap<Integer, Integer> shuttleSpeedMap = (HashMap<Integer, Integer>) speedObj;
            Integer speed = shuttleSpeedMap.get(shuttleNo);
            if (speed != null) {
                runSpeed = speed;
            }
        }
        long calcStartTime = System.currentTimeMillis();
        List<NavigateNode> nodeList = navigateUtils.calc(startLocNo, endLocNo, mapTypes, Utils.getShuttlePoints(shuttleNo, Utils.getLev(startLocNo)), whites);
        if (nodeList == null) {
            News.error("{} dash {} can't find navigate path!", startLocNo, endLocNo);
            shuttleThread.offerSystemMsg("{} dash {} can't find navigate path!", startLocNo, endLocNo);
            return null;
        }
        News.info("[RCS Debug] Calc path time:{}", (System.currentTimeMillis() - calcStartTime));
        List<NavigateNode> allNode = new ArrayList<>();
        List<NavigateNode> lockNode = new ArrayList<>();
@@ -78,7 +89,7 @@
            if (whites != null) {
                boolean flag = false;
                for (int[] white : whites) {
                    if(white[0] == node.getX() && white[1] == node.getY()) {
                    if (white[0] == node.getX() && white[1] == node.getY()) {
                        flag = true;
                        break;
                    }
@@ -91,96 +102,71 @@
            lockNode.add(node.clone());
        }
        long startTime = System.currentTimeMillis();
        List<ShuttleCommand> commands = new ArrayList<>();
        //获取分段路径
        List<List<NavigateNode>> data = navigateUtils.getSectionPath(nodeList);
        long endTime = System.currentTimeMillis();
        News.info("[RCS Debug] getSection path time:{}", (endTime - startTime));
        long startGetSectionCommandTime = System.currentTimeMillis();
        //将每一段路径分成command指令
        for (List<NavigateNode> nodes : data) {
        for (int i = 0; i < data.size(); i++) {
            long startGetStartAndEndPathTime = System.currentTimeMillis();
            List<NavigateNode> nodes = data.get(i);
            //开始路径
            NavigateNode startPath = nodes.get(0);
            //目标路径
            NavigateNode endPath = nodes.get(nodes.size() - 1);
            News.info("[RCS Debug] getStartAndEndPath idx:{} time:{}", i, (System.currentTimeMillis() - startGetStartAndEndPathTime));
            long startAllDistanceTime = System.currentTimeMillis();
            Integer allDistance = navigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离
            News.info("[RCS Debug] getAllDistance idx:{} time:{}", i, (System.currentTimeMillis() - startAllDistanceTime));
            long startGetPosition = System.currentTimeMillis();
            //通过xy坐标小车二维码
            String startCodeNum = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ());
            //通过xy坐标小车二维码
            String distCodeNum = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), endPath.getZ());
            News.info("[RCS Debug] xyToPosition idx:{} time:{}", i, (System.currentTimeMillis() - startGetPosition));
            long startGetMoveCommandTime = System.currentTimeMillis();
            //获取移动命令
            ShuttleCommand command = shuttleThread.getMoveCommand(assignCommand.getDeviceTaskNo(), startCodeNum, distCodeNum, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id.intValue(), runSpeed, nodes);
            News.info("[RCS Debug] getMoveCommand idx:{} time:{}", i, (System.currentTimeMillis() - startGetMoveCommandTime));
            if (i + 1 == data.size()) {
                long startGetInOutLiftTime = System.currentTimeMillis();
                if (moveType.equals("inLift")) {
                    command = shuttleThread.getMoveLiftCommand(assignCommand.getDeviceTaskNo(), startCodeNum, distCodeNum, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id.intValue(), runSpeed, nodes, true);
                }else if (moveType.equals("outLift")) {
                    command = shuttleThread.getMoveLiftCommand(assignCommand.getDeviceTaskNo(), startCodeNum, distCodeNum, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id.intValue(), runSpeed, nodes, false);
                }
                News.info("[RCS Debug] getInOutLiftTime idx:{} time:{}", i, (System.currentTimeMillis() - startGetInOutLiftTime));
            }
            command.setNodes(nodes);//将行走节点添加到每一步命令中
            commands.add(command);
        }
        News.info("[RCS Debug] getSectionCommand path time:{}", (System.currentTimeMillis() - startGetSectionCommandTime));
        assignCommand.setNodes(allNode);//当前任务所占用的节点list
        assignCommand.setMapTypes(mapTypes);
        boolean result = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(startLocNo), shuttleNo, lockNode, true);//锁定路径
        if (!result) {
            News.error("{} dash {} can't lock path!", startLocNo, endLocNo);
            shuttleThread.offerSystemMsg("{} dash {} can't lock path!", startLocNo, endLocNo);
            return null;//路径锁定失败
        //小车移动连续下发指令
        boolean shuttleMoveCommandsContinuously = false;
        Object object = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key);
        if (object != null) {
            HashMap<String, String> systemConfigMap = (HashMap<String, String>) object;
            String shuttleMoveCommandsContinuouslyConfig = systemConfigMap.get("shuttleMoveCommandsContinuously");
            if (shuttleMoveCommandsContinuouslyConfig != null && shuttleMoveCommandsContinuouslyConfig.equals("Y")) {
                shuttleMoveCommandsContinuously = true;
            }
        }
        return commands;
    }
        assignCommand.setShuttleMoveCommandsContinuously(shuttleMoveCommandsContinuously);
    public synchronized List<ShuttleCommand> shuttleInOutLiftCommand(String startLocNo, String endLocNo, List<NavigationMapType> mapTypes, ShuttleAssignCommand assignCommand, ShuttleThread shuttleThread) {
        NavigateNode startNode = NavigatePositionConvert.locNoToNode(startLocNo);
        NavigateNode endNode = NavigatePositionConvert.locNoToNode(endLocNo);
        List<NavigateNode> unlockPath = new ArrayList<>();
        unlockPath.add(startNode);
        unlockPath.add(endNode);
        ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
        if (shuttleProtocol == null) {
            return null;
        }
        Integer shuttleNo = shuttleProtocol.getShuttleNo();
        //所使用的路径进行锁定/解锁
        boolean lockResult = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(endLocNo), shuttleProtocol.getShuttleNo(), unlockPath, false);//所使用的路径进行解锁
        if (!lockResult) {
            News.error("{} dash {} can't find unlock path!", startLocNo, endLocNo);
            shuttleThread.offerSystemMsg("{} dash {} can't find unlock path!", startLocNo, endLocNo);
            return null;//解锁失败
        }
        //获取小车移动速度
        Integer runSpeed = Optional.ofNullable(basShuttleService.selectOne(new EntityWrapper<BasShuttle>().eq("shuttle_no", shuttleNo)).getRunSpeed()).orElse(1000);
        List<NavigateNode> nodeList = navigateUtils.calc(startLocNo, endLocNo, mapTypes, Utils.getShuttlePoints(shuttleNo, Utils.getLev(startLocNo)), null);
        if (nodeList == null) {
            News.error("{} dash {} can't find navigate path!", startLocNo, endLocNo);
            shuttleThread.offerSystemMsg("{} dash {} can't find navigate path!", startLocNo, endLocNo);
            return null;
        }
        List<NavigateNode> allNode = new ArrayList<>();
        for (NavigateNode node : nodeList) {
            allNode.add(node.clone());
        }
        List<ShuttleCommand> commands = new ArrayList<>();
        //获取分段路径
        List<List<NavigateNode>> data = navigateUtils.getSectionPath(nodeList);
        //将每一段路径分成command指令
        for (List<NavigateNode> nodes : data) {
            //开始路径
            NavigateNode startPath = nodes.get(0);
            //目标路径
            NavigateNode endPath = nodes.get(nodes.size() - 1);
            Integer allDistance = navigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离
            //通过xy坐标小车二维码
            String startCodeNum = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ());
            //通过xy坐标小车二维码
            String distCodeNum = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), endPath.getZ());
            //获取移动命令
            ShuttleCommand command = shuttleThread.getMoveCommand(assignCommand.getDeviceTaskNo(), startCodeNum, distCodeNum, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id.intValue(), runSpeed, nodes);
            command.setNodes(nodes);//将行走节点添加到每一步命令中
            commands.add(command);
        }
        assignCommand.setNodes(allNode);//当前任务所占用的节点list
        News.info("{}任务,{}小车,{} - {} 路径命令包计算成功,耗时:{}ms", assignCommand.getTaskNo(), shuttleProtocol.getShuttleNo(), startLocNo, endLocNo, System.currentTimeMillis() - startTime);
        return commands;
    }
@@ -208,17 +194,20 @@
        return commands;
    }
    //检测障碍物车
    public synchronized boolean checkObstacle(String locNo, List<Integer> whiteShuttles) {
    /**
     * 检测障碍物车
     * @return 0:无障碍 1:有障碍调度成功 2:有障碍调度失败
     */
    public synchronized int checkObstacle(String locNo, List<Integer> whiteShuttles, List<NavigateNode> whiteNodes) {
        int innerCircle = 0;
        int outerCircle = 3;
        Config avoidInnerCircleConfig = configService.selectOne(new EntityWrapper<Config>().eq("code", "avoidInnerCircle"));
        if(avoidInnerCircleConfig != null) {
        if (avoidInnerCircleConfig != null) {
            innerCircle = Integer.parseInt(avoidInnerCircleConfig.getValue());
        }
        Config avoidOuterCircleConfig = configService.selectOne(new EntityWrapper<Config>().eq("code", "avoidOuterCircle"));
        if(avoidOuterCircleConfig != null) {
        if (avoidOuterCircleConfig != null) {
            outerCircle = Integer.parseInt(avoidOuterCircleConfig.getValue());
        }
@@ -242,11 +231,11 @@
        List<NavigateNode> innerNodes = getInnerNodes(locNo, innerCircle, whiteShuttlePointList);
        List<Integer> nodesCar = findNodesCar(innerNodes);
        if (nodesCar.isEmpty()) {
            return false;//内圈中无车
            return 0;//内圈中无车
        }
        //获取外圈节点
        List<NavigateNode> outerNodes = getOuterNodes(locNo, outerCircle, whiteShuttlePointList, innerNodes);
        List<NavigateNode> outerNodes = getOuterNodes(locNo, outerCircle, whiteShuttlePointList, innerNodes, whiteNodes);
        //将内圈节点中障碍小车调离
        for (Integer shuttleNo : nodesCar) {
@@ -269,20 +258,21 @@
                List<NavigateNode> avoidInnerNodes = getInnerNodes(dispatchLocNo, innerCircle, new ArrayList<>());
                //计算内圈是否有小车
                List<Integer> avoidNodesCar = findNodesCar(avoidInnerNodes);
                if(!avoidNodesCar.isEmpty()) {
                   continue;
                if (!avoidNodesCar.isEmpty()) {
                    continue;
                }
                targetLocNo = dispatchLocNo;
                break;
            }
            if(targetLocNo == null) {
            if (targetLocNo == null) {
                continue;
            }
            shuttleDispatchUtils.dispatchShuttle(null, targetLocNo, shuttleNo);
            boolean dispatched = shuttleDispatchUtils.dispatchShuttle(null, targetLocNo, shuttleNo);
            return dispatched ? 1 : 2;
        }
        return true;//内圈中有车
        return 2;//内圈中有车
    }
    private HashMap<String, Integer> findCarMap() {
@@ -323,7 +313,7 @@
        return list;
    }
    private List<NavigateNode> getOuterNodes(String locNo, int outerCircle, List<int[]> whiteShuttlePointList, List<NavigateNode> innerNodes) {
    private List<NavigateNode> getOuterNodes(String locNo, int outerCircle, List<int[]> whiteShuttlePointList, List<NavigateNode> innerNodes, List<NavigateNode> whiteNodes) {
        List<NavigateNode> outerNodes = new ArrayList<>();
        List<NavigateNode> outerNodesTmp = new ArrayList<>();
        int lev = Utils.getLev(locNo);
@@ -348,13 +338,24 @@
        for (NavigateNode node : outerNodesTmp) {
            boolean flag = false;
            for (NavigateNode innerNode : innerNodes) {
                if(node.getX() == innerNode.getX() && node.getY() == innerNode.getY()) {
                if (node.getX() == innerNode.getX() && node.getY() == innerNode.getY()) {
                    flag = true;
                    break;
                }
            }
            if(flag) {
            if (flag) {
                continue;
            }
            for (NavigateNode whiteNode : whiteNodes) {
                if (node.getX() == whiteNode.getX() && node.getY() == whiteNode.getY()) {
                    flag = true;
                    break;
                }
            }
            if (flag) {
                continue;
            }
@@ -555,7 +556,7 @@
    private boolean is_valid(int[][] map, int x, int y) {
        if (x < 0 || x >= map.length
                || y < 0 || y >= map[0].length) {
                || y < 0 || y >= map[1].length) {
            return false;
        }
        // 如果结点的位置小于0,则不合法