zjj
7 天以前 e29a9f245ff4e57a40bbab1c0acc3cbc31d3ac2b
zy-asrs-wcs/src/main/java/com/zy/asrs/wcs/core/kernel/command/ShuttleCommandService.java
@@ -1,15 +1,16 @@
package com.zy.asrs.wcs.core.kernel.command;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zy.asrs.framework.common.Cools;
import com.zy.asrs.framework.exception.CoolException;
import com.zy.asrs.wcs.common.ExecuteSupport;
import com.zy.asrs.wcs.core.action.LiftAction;
import com.zy.asrs.wcs.core.action.ShuttleAction;
import com.zy.asrs.wcs.core.entity.BasShuttle;
import com.zy.asrs.wcs.core.entity.Loc;
import com.zy.asrs.wcs.core.model.NavigateNode;
import com.zy.asrs.wcs.core.model.command.ShuttleAssignCommand;
import com.zy.asrs.wcs.core.model.command.ShuttleCommand;
import com.zy.asrs.wcs.core.model.command.*;
import com.zy.asrs.wcs.core.model.enums.*;
import com.zy.asrs.wcs.core.service.BasShuttleService;
import com.zy.asrs.wcs.core.service.LocService;
@@ -18,6 +19,7 @@
import com.zy.asrs.wcs.rcs.News;
import com.zy.asrs.wcs.rcs.cache.SlaveConnection;
import com.zy.asrs.wcs.core.entity.Motion;
import com.zy.asrs.wcs.rcs.entity.Device;
import com.zy.asrs.wcs.rcs.model.enums.ShuttleProtocolStatusType;
import com.zy.asrs.wcs.rcs.model.enums.SlaveType;
import com.zy.asrs.wcs.rcs.model.protocol.LiftProtocol;
@@ -29,10 +31,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.*;
/**
 * Created by vincent on 2023/10/23
@@ -59,6 +58,10 @@
    private ShuttleAction shuttleAction;
    @Autowired
    private LiftAction liftAction;
    @Autowired
    private LiftDispatcher liftDispatcher;
    @Autowired
    private ShuttleDispatcher shuttleDispatcher;
    // 计算
    public Boolean accept(Motion motion) {
@@ -71,9 +74,19 @@
        if (null == shuttleProtocol) {
            return false;
        }
        if (!shuttleThread.isIdle()) {//设备不空闲
        Device shuttleDevice = shuttleThread.getDevice();
        if (!shuttleThread.isIdle(new ExecuteSupport() {
            @Override
            public Boolean judgement() {
                if (Objects.equals(MotionCtgType.get(motion.getMotionCtgEl()), MotionCtgType.SHUTTLE_CHARGE_OFF)) {//非关闭充电motion,需要判断设备状态
                    return false;//不需要判断状态
                }
                return true;//需要判断状态
            }
        })) {//设备不空闲
            return false;
        }
        if (motionService.count(new LambdaQueryWrapper<Motion>()
                .eq(Motion::getDeviceCtg, DeviceCtgType.SHUTTLE.val())
                .eq(Motion::getDevice, motion.getDevice())
@@ -83,7 +96,8 @@
        ShuttleAssignCommand assignCommand = new ShuttleAssignCommand();
        assignCommand.setShuttleNo(deviceNo);
        assignCommand.setTaskNo(motion.getWrkNo());
        assignCommand.setTaskNo(motion.getTaskNo());
        assignCommand.setDeviceTaskNo(shuttleThread.generateDeviceTaskNo(motion.getTaskNo(), MotionCtgType.get(motion.getMotionCtgEl())));
        assignCommand.setSourceLocNo(motion.getOrigin());
        assignCommand.setLocNo(motion.getTarget());
        assignCommand.setDeviceId(Integer.parseInt(motion.getDevice()));
@@ -99,7 +113,7 @@
                // 如果已经在当前条码则过滤
                if (String.valueOf(shuttleProtocol.getCurrentCode()).equals(locService.getOne(new LambdaQueryWrapper<Loc>()
                        .eq(Loc::getLocNo, motion.getTarget())
                        .eq(Loc::getHostId, motion.getHostId())).getCode())) {
                            .eq(Loc::getHostId, motion.getHostId())).getCode())) {
                    return true;
                }
                shuttleCommands = this.shuttleAssignCommand(motion.getOrigin(), motion.getTarget(), NavigationMapType.NORMAL.id, assignCommand, shuttleThread);
@@ -108,12 +122,12 @@
            case SHUTTLE_MOVE_LIFT_PALLET://穿梭车顶升并移动
                shuttleCommands = this.shuttleAssignCommand(motion.getOrigin(), motion.getTarget(), NavigationMapType.DFX.id, assignCommand, shuttleThread);
                shuttleTaskModeType = ShuttleTaskModeType.PAK_IN;
                shuttleCommands.add(0, shuttleThread.getLiftCommand(motion.getWrkNo(), true));
                shuttleCommands.add(0, shuttleThread.getLiftCommand(motion.getTaskNo(), true));
                break;
            case SHUTTLE_MOVE_DOWN_PALLET://穿梭车移动并托盘下降
                shuttleCommands = this.shuttleAssignCommand(motion.getOrigin(), motion.getTarget(), NavigationMapType.DFX.id, assignCommand, shuttleThread);
                shuttleTaskModeType = ShuttleTaskModeType.PAK_IN;
                shuttleCommands.add(shuttleCommands.size(), shuttleThread.getLiftCommand(motion.getWrkNo(), false));
                shuttleCommands.add(shuttleCommands.size(), shuttleThread.getLiftCommand(motion.getTaskNo(), false));
                break;
            case SHUTTLE_MOVE_FROM_LIFT://出提升机
                // 判断提升机状态
@@ -128,36 +142,30 @@
                }
                // 判断提升机是否空闲
                if (!liftThread.isIdle()) {
                if (!liftThread.isIdle(MotionCtgType.SHUTTLE_MOVE_FROM_LIFT)) {
                    return false;
                }
                if (liftProtocol.getLev() != Utils.getLev(motion.getTarget())) {//判断提升机是否达到目标层
                if (liftProtocol.getLev() != liftDispatcher.getLiftLevOffset(liftThread.getDevice().getId().intValue(), Utils.getLev(motion.getTarget()))) {//判断提升机是否达到目标层
                    return false;
                }
//                //判断提升机是否被锁定
//                if (!liftProtocol.getLock()) {
//                    //锁定提升机
//                    LiftCommand lockCommand = liftThread.getLockCommand(motion.getWrkNo(), true);//获取提升机锁定命令
//
//                    LiftAssignCommand liftAssignCommand = new LiftAssignCommand();
//                    liftAssignCommand.setLiftNo(liftThread.getStatus().getLiftNo());
//                    liftAssignCommand.setTaskNo(motion.getWrkNo());
//                    ArrayList<LiftCommand> list = new ArrayList<>();
//                    list.add(lockCommand);
//                    liftAssignCommand.setCommands(list);
//
//                    liftAction.assignWork(liftThread.getDevice(), liftAssignCommand);
//                    return false;//等待下一次轮询
                //判断提升机是否被锁定
                if (!liftThread.isLock(new ExecuteSupport() {
                    @Override
                    public Boolean judgement() {
                        return true;
                    }
                })) {
                    return false;
                }
//                //判断提升机工作号是否和当前任务相同
//                if (liftProtocol.getTaskNo().intValue() != motion.getTaskNo()) {
//                    return false;
//                }
                //判断提升机工作号是否和当前任务相同
                if (liftProtocol.getTaskNo().intValue() != motion.getWrkNo()) {
                    return false;
                }
                shuttleCommands = this.shuttleAssignCommand(motion.getOrigin(), motion.getTarget(), NavigationMapType.NORMAL.id, assignCommand, shuttleThread);
                shuttleCommands = this.shuttleInOutLiftCommand(motion.getOrigin(), motion.getTarget(), NavigationMapType.NORMAL.id, assignCommand, shuttleThread);
                shuttleTaskModeType = ShuttleTaskModeType.SHUTTLE_MOVE_LOC_NO;
                break;
            case SHUTTLE_MOVE_TO_LIFT://进提升机
@@ -171,49 +179,68 @@
                    return false;
                }
                // 判断提升机是否空闲
                if (!liftThread.isIdle()) {
                if (!liftThread.isIdle(MotionCtgType.SHUTTLE_MOVE_TO_LIFT)) {
                    return false;
                }
                if (liftProtocol.getLev() != Utils.getLev(motion.getTarget())) {//判断提升机是否达到目标层
                if (liftProtocol.getLev() != liftDispatcher.getLiftLevOffset(liftThread.getDevice().getId().intValue(), Utils.getLev(motion.getTarget()))) {//判断提升机是否达到目标层
                    return false;
                }
//                //判断提升机是否被锁定
//                if (!liftProtocol.getLiftLock()) {
//                    //锁定提升机
//                    LiftCommand lockCommand = liftThread.getLockCommand(true);//获取提升机锁定命令
//                    lockCommand.setLiftNo(liftProtocol.getLiftNo());
//                    lockCommand.setTaskNo(motion.getWrkNo().shortValue());//获取任务号
//                    liftThread.assignWork(lockCommand);
//                    return false;//等待下一次轮询
                //判断提升机是否被锁定
                if (!liftThread.isLock(new ExecuteSupport() {
                    @Override
                    public Boolean judgement() {
                        return true;//牛眼没有提升机锁,直接返回true
                    }
                })) {
                    return false;
                }
//                //判断提升机工作号是否和当前任务相同
//                if (liftProtocol.getTaskNo().intValue() != motion.getTaskNo()) {
//                    return false;
//                }
                //判断提升机工作号是否和当前任务相同
                if (liftProtocol.getTaskNo().intValue() != motion.getWrkNo()) {
                    return false;
                }
                shuttleCommands = this.shuttleAssignCommand(motion.getOrigin(), motion.getTarget(), NavigationMapType.NORMAL.id, assignCommand, shuttleThread);
                shuttleTaskModeType = ShuttleTaskModeType.SHUTTLE_MOVE_LOC_NO;
                break;
            case SHUTTLE_CHARGE_ON://充电开
                shuttleTaskModeType = ShuttleTaskModeType.CHARGE;
                shuttleCommands.add(shuttleThread.getChargeCommand(motion.getWrkNo(), true));
                shuttleCommands.add(shuttleThread.getChargeCommand(motion.getTaskNo(), true));
                assignCommand.setCharge(Boolean.TRUE);
                break;
            case SHUTTLE_CHARGE_OFF://充电关
                shuttleTaskModeType = ShuttleTaskModeType.CHARGE;
                shuttleCommands.add(shuttleThread.getChargeCommand(motion.getWrkNo(), false));
                shuttleCommands.add(shuttleThread.getChargeCommand(motion.getTaskNo(), false));
                assignCommand.setCharge(Boolean.TRUE);
                break;
            case SHUTTLE_PALLET_LIFT://托盘顶升
                shuttleTaskModeType = ShuttleTaskModeType.PALLET_LIFT;
                shuttleCommands.add(shuttleThread.getLiftCommand(motion.getWrkNo(), true));
                shuttleCommands.add(shuttleThread.getLiftCommand(motion.getTaskNo(), true));
                break;
            case SHUTTLE_PALLET_DOWN://托盘下降
                shuttleTaskModeType = ShuttleTaskModeType.PALLET_DOWN;
                shuttleCommands.add(shuttleThread.getLiftCommand(motion.getWrkNo(), false));
                shuttleCommands.add(shuttleThread.getLiftCommand(motion.getTaskNo(), false));
                break;
            case SHUTTLE_UPDATE_LOCATION://小车坐标更新
                shuttleTaskModeType = ShuttleTaskModeType.SHUTTLE_UPDATE_LOCATION;
                shuttleCommands.add(shuttleThread.getUpdateLocationCommand(motion.getTaskNo(), motion.getTarget()));
                break;
            case SHUTTLE_MOVE_STANDBY://穿梭车移动到待机位
                shuttleTaskModeType = ShuttleTaskModeType.SHUTTLE_MOVE_LOC_NO;
                //获取全部待机位
                List<String> standbyLocs = JSON.parseArray(motion.getTemp(), String.class);
                //获取可用待机位
                String shuttleFromLiftStandbyLoc = shuttleDispatcher.searchAvailableLocNo(Integer.valueOf(shuttleDevice.getDeviceNo()), shuttleDevice.getHostId(), shuttleThread.getStatus().getCurrentLocNo(), standbyLocs);
                shuttleCommands = this.shuttleAssignCommand(motion.getOrigin(), shuttleFromLiftStandbyLoc, NavigationMapType.NORMAL.id, assignCommand, shuttleThread);
                //更新动作可用待机位
                motion.setTarget(shuttleFromLiftStandbyLoc);
                motion.setUpdateTime(new Date());
                motionService.updateById(motion);
                break;
            default:
                throw new CoolException(motion.getMotionCtgEl() + "没有指定任务作业流程!!!");
@@ -229,7 +256,7 @@
        if (motion.getOrigin() != null && motion.getTarget() != null) {
            //所使用的路径进行锁定禁用
            boolean lockResult = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(motion.getTarget()), shuttleProtocol.getShuttleNo(), assignCommand.getNodes(), true);//所使用的路径进行锁定禁用
            boolean lockResult = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(motion.getTarget()), shuttleProtocol.getShuttleNo(), assignCommand.getNodesDeepCopy(), true);//所使用的路径进行锁定禁用
            if (!lockResult) {
                return false;//锁定失败
            }
@@ -247,24 +274,26 @@
            return false;
        }
        if (shuttleProtocol.getTaskNo() != 0 && shuttleProtocol.getTaskNo().intValue() != motion.getWrkNo()) {
        if (shuttleProtocol.getTaskNo() != 0 && shuttleProtocol.getTaskNo().intValue() != motion.getTaskNo()) {
            return false;
        }
        //充电任务
        if (Objects.requireNonNull(MotionCtgType.get(motion.getMotionCtgEl())).equals(MotionCtgType.SHUTTLE_CHARGE_ON)) {
            // 复位穿梭车
            shuttleProtocol.setTaskNo(0);
            shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
            shuttleProtocol.setPakMk(true);
            return true;
            if (shuttleProtocol.getHasCharge() || shuttleProtocol.getProtocolStatusType().equals(ShuttleProtocolStatusType.CHARGING_WAITING)) {
                // 复位穿梭车
                shuttleThread.setSyncTaskNo(0);
                shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
                shuttleThread.setPakMk(true);
                return true;
            }
        }
//        if (!shuttleProtocol.getProtocolStatusType().equals(ShuttleProtocolStatusType.WAITING)
//            && !shuttleProtocol.getProtocolStatusType().equals(ShuttleProtocolStatusType.CHARGING_WAITING)
//        ) {
//            return false;
//        }
        if (!shuttleProtocol.getProtocolStatusType().equals(ShuttleProtocolStatusType.WAITING)
            && !shuttleProtocol.getProtocolStatusType().equals(ShuttleProtocolStatusType.CHARGING_WAITING)
        ) {
            return false;
        }
        //判断设备是否空闲
        if (!shuttleThread.isIdle()) {
@@ -285,7 +314,67 @@
                }
                break;
            case SHUTTLE_MOVE_TO_LIFT:
                liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, Integer.parseInt(motion.getTemp()));
                if (liftThread == null) {
                    return false;
                }
                liftProtocol = liftThread.getStatus();
                if (!shuttleProtocol.getCurrentLocNo().equals(motion.getTarget())) {
                    return false;
                }
                //判断提升机是否被锁定
                if (!liftThread.isLock(new ExecuteSupport() {
                    @Override
                    public Boolean judgement() {
                        return false;
                    }
                })) {
                    return false;
                }
                //判断小车是否已到位
                if (!liftProtocol.getHasCar()) {
                    return false;
                }
//                //判断提升机工作号是否和当前任务相同
//                if (liftProtocol.getTaskNo().intValue() != motion.getTaskNo()) {
//                    return false;
//                }
                break;
            case SHUTTLE_MOVE_FROM_LIFT:
                liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, Integer.parseInt(motion.getTemp()));
                if (liftThread == null) {
                    return false;
                }
                liftProtocol = liftThread.getStatus();
                if (!shuttleProtocol.getCurrentLocNo().equals(motion.getTarget())) {
                    return false;
                }
                //判断提升机是否被锁定
                if (!liftThread.isLock(new ExecuteSupport() {
                    @Override
                    public Boolean judgement() {
                        return false;
                    }
                })) {
                    return false;
                }
                //判断小车是否已离开
                if (liftProtocol.getHasCar()) {
                    return false;
                }
//                //判断提升机工作号是否和当前任务相同
//                if (liftProtocol.getTaskNo().intValue() != motion.getTaskNo()) {
//                    return false;
//                }
                break;
            case SHUTTLE_TRANSPORT_FROM_LIFT:
            case SHUTTLE_TRANSPORT_TO_LIFT:
            case SHUTTLE_MOVE_FROM_LIFT_TO_CONVEYOR:
@@ -299,35 +388,45 @@
                    return false;
                }
//                //判断提升机是否被锁定
//                if (liftProtocol.getLiftLock()) {
//                    //解锁提升机
//                    LiftCommand lockCommand = liftThread.getLockCommand(false);//获取提升机解锁命令
//                    lockCommand.setLiftNo(liftProtocol.getLiftNo());
//                    lockCommand.setTaskNo(motion.getWrkNo().shortValue());//获取任务号
//                    liftThread.assignWork(lockCommand);
//                    return false;
//                }
                //判断提升机工作号是否和当前任务相同
                if (liftProtocol.getTaskNo().intValue() != motion.getWrkNo()) {
                //判断提升机是否被锁定
                if (liftThread.isLock(new ExecuteSupport() {
                    @Override
                    public Boolean judgement() {
                        return false;
                    }
                })) {
                    return false;
                }
//                if (liftProtocol.getTaskNo() != 0) {
//                    //清空提升机号
//                    liftThread.setTaskNo(0);
//                }
                //判断提升机工作号是否和当前任务相同
                if (liftProtocol.getTaskNo().intValue() != motion.getTaskNo()) {
                    return false;
                }
                break;
            case SHUTTLE_UPDATE_LOCATION://小车坐标更新
                break;
            case SHUTTLE_PALLET_LIFT://托盘顶升
                if (!shuttleProtocol.getHasLift()) {
                    return false;
                }
                break;
            case SHUTTLE_PALLET_DOWN://托盘下降
                if (shuttleProtocol.getHasLift()) {
                    return false;
                }
            case SHUTTLE_MOVE_STANDBY://穿梭车移动到待机位
                if (!shuttleProtocol.getCurrentLocNo().equals(motion.getTarget())) {
                    return false;
                }
                break;
            default:
                break;
        }
        // 复位穿梭车
        shuttleProtocol.setTaskNo(0);
        shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
        shuttleProtocol.setPakMk(true);
        shuttleThread.setSyncTaskNo(0);
        shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
        shuttleThread.setPakMk(true);
        return true;
    }
@@ -341,7 +440,11 @@
            News.error("{} dash {} can't find navigate path!", startLocNo, endLocNo);
            return null;
        }
        List<NavigateNode> allNode = new ArrayList<>(nodeList);
        List<NavigateNode> allNode = new ArrayList<>();
        for (NavigateNode node : nodeList) {
            allNode.add(node.clone());
        }
        List<ShuttleCommand> commands = new ArrayList<>();
        //获取分段路径
@@ -359,7 +462,64 @@
            //通过xy坐标小车二维码
            String distCodeNum = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), endPath.getZ(), hostId);
            //获取移动命令
            ShuttleCommand command = shuttleThread.getMoveCommand(assignCommand.getTaskNo(), startCodeNum, distCodeNum, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id.intValue(), runSpeed);
            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
        return commands;
    }
    public synchronized List<ShuttleCommand> shuttleInOutLiftCommand(String startLocNo, String endLocNo, Integer mapType, 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();
        //所使用的路径进行锁定/解锁
        boolean lockResult = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(endLocNo), shuttleProtocol.getShuttleNo(), unlockPath, false);//所使用的路径进行解锁
        if (!lockResult) {
            News.error("{} dash {} can't find unlock path!", startLocNo, endLocNo);
            return null;//解锁失败
        }
        //获取小车移动速度
        Integer runSpeed = Optional.ofNullable(basShuttleService.getOne(new LambdaQueryWrapper<BasShuttle>().eq(BasShuttle::getDeviceId, assignCommand.getDeviceId())).getRunSpeed()).orElse(1000);
        Long hostId = shuttleThread.getDevice().getHostId();
        List<NavigateNode> nodeList = NavigateUtils.calc(startLocNo, endLocNo, mapType, Utils.getShuttlePoints(Integer.parseInt(shuttleThread.getDevice().getDeviceNo()), Utils.getLev(startLocNo)));
        if (nodeList == null) {
            News.error("{} 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<>();
        //获取分段路径
        ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(nodeList);
        //将每一段路径分成command指令
        for (ArrayList<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(), hostId);
            //通过xy坐标小车二维码
            String distCodeNum = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), endPath.getZ(), hostId);
            //获取移动命令
            ShuttleCommand command = shuttleThread.getMoveCommand(assignCommand.getDeviceTaskNo(), startCodeNum, distCodeNum, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id.intValue(), runSpeed, nodes);
            command.setNodes(nodes);//将行走节点添加到每一步命令中
            commands.add(command);
        }