自动化立体仓库 - WCS系统
Junjie
2023-03-27 749ab7303f266992bdd603fbe64fc36b56855739
四向穿梭车手动模式
13个文件已修改
338 ■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/ShuttleController.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/param/ShuttleOperatorParam.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/NavigateMapData.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/NavigateSolution.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/NavigateUtils.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/ShuttleTaskModeType.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/ShuttleAssignCommand.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/ShuttleCommand.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/ShuttleProtocol.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/ShuttleThread.java 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/index.html 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/shuttle.html 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/ShuttleController.java
@@ -6,13 +6,9 @@
import com.core.common.Cools;
import com.core.common.R;
import com.core.exception.CoolException;
import com.zy.asrs.domain.enums.CrnStatusType;
import com.zy.asrs.domain.param.ShuttleOperatorParam;
import com.zy.asrs.domain.param.SteModeParam;
import com.zy.asrs.domain.param.SteOperatorParam;
import com.zy.asrs.domain.vo.*;
import com.zy.asrs.entity.BasShuttle;
import com.zy.asrs.entity.BasSte;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.service.BasShuttleService;
import com.zy.asrs.service.WrkMastService;
@@ -21,16 +17,12 @@
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.*;
import com.zy.core.model.ShuttleSlave;
import com.zy.core.model.SteSlave;
import com.zy.core.model.Task;
import com.zy.core.model.command.ShuttleAssignCommand;
import com.zy.core.model.command.ShuttleCommand;
import com.zy.core.model.command.SteCommand;
import com.zy.core.model.protocol.ShuttleProtocol;
import com.zy.core.model.protocol.SteProtocol;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.properties.SystemProperties;
import com.zy.core.thread.ShuttleThread;
import com.zy.core.thread.SteThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -38,6 +30,7 @@
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
/**
 * 四向穿梭车接口
@@ -77,9 +70,6 @@
            if (!Cools.isEmpty(shuttleProtocol.getBusyStatus())) {
                vo.setStatus(shuttleProtocol.getBusyStatusType().desc); //  状态
            }
            vo.setRow(shuttleProtocol.getRow());
            vo.setBay(shuttleProtocol.getBay());
            vo.setLev(shuttleProtocol.getLev());
            vo.setBatteryPower(shuttleProtocol.getBatteryPower() + "%");
            vo.setSpeed(shuttleProtocol.getCurrentMoveServoSpeed());
            if (!Cools.isEmpty(shuttleProtocol.getErrorCode())) {
@@ -127,6 +117,12 @@
            vo.setPakMk(shuttleProtocol.getPakMk().toString());    // 作业标记
        }
        return R.ok().add(list);
    }
    @PostMapping("/latest/data/shuttle")
    @ManagerAuth(memo = "四向穿梭车实时数据")
    public R shuttleLatestData(){
        return R.ok();
    }
    @PostMapping("/output/shuttle")
@@ -226,7 +222,7 @@
//            }
//        }
        ShuttleCommand shuttleCommand = new ShuttleCommand();
        shuttleCommand.setTaskNo(vo.getWorkNo());
        shuttleCommand.setTaskNo(vo.getWorkNo().shortValue());
        if (MessageQueue.offer(SlaveType.Shuttle, vo.getShuttleNo(), new Task(2, shuttleCommand))) {
        } else {
            throw new CoolException("命令下发失败");
@@ -265,23 +261,16 @@
                if (shuttleProtocol == null) {
                    throw new CoolException("四向穿梭车不在线");
                }
                ShuttleTaskModeType shuttleTaskModeType = ShuttleTaskModeType.get(param.getShuttleTaskMode());
                ShuttleCommand shuttleCommand = new ShuttleCommand();
                shuttleCommand.setShuttleNo(shuttleSlave.getId()); // 四向穿梭车编号
//                if (param.getShuttleTaskMode() == 16) {
//                    steCommand.setComplete(true);
//                } else if (param.getSteTaskMode() == 99) {
//                    steCommand.setControlMode((short) 1);
//                } else if (param.getSteTaskMode() == 100) {
//                    steCommand.setControlMode((short) 0);
//                } else {
//                    if (steTaskModeType == null) {
//                        throw new CoolException("任务类型错误");
//                    }
//                    steCommand.setTaskNo(param.getTaskNo()); // 工作号
//                    steCommand.setTaskMode(steTaskModeType);
//                }
                if (MessageQueue.offer(SlaveType.Shuttle, shuttleSlave.getId(), new Task(2, shuttleCommand))) {
                ShuttleAssignCommand command = new ShuttleAssignCommand();
                command.setShuttleNo(shuttleSlave.getId().shortValue()); // 四向穿梭车编号
                command.setTaskMode(shuttleTaskModeType.id.shortValue());
                command.setSourceLocNo(param.getSourceLocNo());
                command.setDistLocNo(param.getDistLocNo());
                command.setTaskNo((short) 9999);
                if (MessageQueue.offer(SlaveType.Shuttle, shuttleSlave.getId(), new Task(3, command))) {
                    return R.ok();
                } else {
                    throw new CoolException("命令下发失败");
src/main/java/com/zy/asrs/domain/param/ShuttleOperatorParam.java
@@ -14,13 +14,10 @@
    // 任务号
    private Integer taskNo = 0;
    // 目标库位-排
    private Short row;
    // 启动库位
    private String sourceLocNo;
    // 目标库位-列
    private Short bay;
    // 目标库位-层
    private Short lev;
    // 目标库位
    private String distLocNo;
}
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -635,7 +635,7 @@
                    //任务号
                    assignCommand.setTaskNo(wrkSts.getWrkNo().shortValue());
                    //入出库模式
                    assignCommand.setTaskMode(0);
                    assignCommand.setTaskMode((short) 0);
                    //源库位
                    assignCommand.setSourceLocNo(wrkSts.getSourceLocNo());
                    //目标库位
src/main/java/com/zy/common/utils/NavigateMapData.java
@@ -2,6 +2,7 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zy.core.enums.ShuttleTaskModeType;
import java.io.*;
import java.util.ArrayList;
@@ -12,15 +13,17 @@
public class NavigateMapData {
    public int[][] getData() {
        return getData("in");
        return getData(ShuttleTaskModeType.PAK_IN.id);
    }
    public int[][] getData(String mapType) {
    public int[][] getData(Integer mapType) {
        try {
            String mapFilename = "";
            if (mapType.equals("in")) {
            if (mapType == ShuttleTaskModeType.PAK_IN.id) {
                //入库地图
                mapFilename = "mapIn.json";
            }else {
                //出库地图
                mapFilename = "mapOut.json";
            }
src/main/java/com/zy/common/utils/NavigateSolution.java
@@ -21,7 +21,7 @@
        this.map = data;
    }
    public NavigateSolution(String mapType) {
    public NavigateSolution(Integer mapType) {
        //载入地图
        NavigateMapData mapData = new NavigateMapData();
        int[][] data = mapData.getData(mapType);
src/main/java/com/zy/common/utils/NavigateUtils.java
@@ -1,6 +1,7 @@
package com.zy.common.utils;
import com.zy.common.model.NavigateNode;
import com.zy.core.enums.ShuttleTaskModeType;
import java.util.*;
@@ -9,7 +10,7 @@
 */
public class NavigateUtils {
    public static List<NavigateNode> calc(String startPoint, String endPoint, String mapType) {
    public static List<NavigateNode> calc(String startPoint, String endPoint, Integer mapType) {
        //通过开始编号和结束编号获取对应的xy轴坐标
        int[] startArr = NavigatePositionConvert.positionToXY(startPoint);//开始节点
        int[] endArr = NavigatePositionConvert.positionToXY(endPoint);//结束节点
@@ -150,7 +151,7 @@
    public static void main(String[] args) {
        //计算路径
        List<NavigateNode> calc = calc("1000901", "0201801", "out");
        List<NavigateNode> calc = calc("1000901", "0201801", ShuttleTaskModeType.PAK_OUT.id);
        System.out.println(calc);
        System.out.println("------------------------");
//        List<NavigateNode> calc = calc("0501401", "0201801", "out");
src/main/java/com/zy/core/enums/ShuttleTaskModeType.java
@@ -3,6 +3,14 @@
public enum ShuttleTaskModeType {
    INIT(0, "初始"),    // 初始
    PAK_IN(1, "入库"),
    PAK_OUT(2, "出库"),
    PALLET_LIFT(3, "托盘顶升"),
    PALLET_DOWN(4, "托盘下降"),
    MOVE_LEFT(5, "左移"),
    MOVE_RIGHT(6, "右移"),
    MOVE_TOP(7, "前移"),
    MOVE_BOTTOM(8, "后移"),
    ;
    public Integer id;
src/main/java/com/zy/core/model/command/ShuttleAssignCommand.java
@@ -17,10 +17,16 @@
    /**
     * 作业类型
     * 0: 入库
     * 1: 出库
     * 1: 入库
     * 2: 出库
     * 3: 托盘顶升
     * 4: 托盘下降
     * 5: 左移
     * 6: 右移
     * 7: 前移
     * 8: 后移
     */
    private Integer taskMode = 0;
    private Short taskMode = 0;
    /**
     * 源库位
src/main/java/com/zy/core/model/command/ShuttleCommand.java
@@ -11,22 +11,17 @@
    /**
     * 四向穿梭车号
     */
    private Integer shuttleNo = 0;
    private Short shuttleNo = 0;
    /**
     * 任务号
     */
    private Integer taskNo = 0;
    private Short taskNo = 0;
    /**
     * 作业类型
     */
    private Short taskMode = 0;
    /**
     * 任务确认 false:未确认 true:已确认
     */
    private Boolean complete = Boolean.FALSE;
    /**
     * 控制指令字
src/main/java/com/zy/core/model/protocol/ShuttleProtocol.java
@@ -32,21 +32,6 @@
    private String locNo;
    /**
     * 排
     */
    private Short row;
    /**
     * 列
     */
    private Short bay;
    /**
     * 层
     */
    private Short lev;
    /**
     * 小车忙状态位
     * 1: 忙
     * 0: 空闲
src/main/java/com/zy/core/thread/ShuttleThread.java
@@ -66,10 +66,10 @@
                    case 1:
                        readStatus();
                        break;
//                    // 写入数据
//                    case 2:
//                        write((ShuttleCommand) task.getData());
//                        break;
                    // 写入数据
                    case 2:
                        write((ShuttleCommand) task.getData());
                        break;
                    //下发任务
                    case 3:
                        assignWork((ShuttleAssignCommand) task.getData());
@@ -189,46 +189,77 @@
            return false;
        }
        command.setShuttleNo(slave.getId());
        command.setShuttleNo(slave.getId().shortValue());
        // 开始任务
        short[] array = new short[17];
        //控制指令字
        array[0] = command.getCommandWord();
        //启始二维编号
        array[1] = command.getStartCodeNum();
        //中间二维编号
        array[2] = command.getMiddleCodeNum();
        //目标二维编号
        array[3] = command.getDistCodeNum();
        if (command.getStartCodeNum() != null) {
            //启始二维编号
            array[1] = command.getStartCodeNum();
        }
        //起点到目标点的距离长度,先将int转为byte数组,再将byte数组转成两个short,分别占用4和5空间
        short[] startToDistDistances = CommonUtils.intToShorts(command.getStartToDistDistance());
        array[4] = startToDistDistances[0];
        array[5] = startToDistDistances[1];
        if (command.getMiddleCodeNum() != null) {
            //中间二维编号
            array[2] = command.getMiddleCodeNum();
        }
        //中间点到目标点的距离长度,先将int转为byte数组,再将byte数组转成两个short,分别占用4和5空间
        short[] middleToDistDistances = CommonUtils.intToShorts(command.getMiddleToDistDistance());
        array[6] = middleToDistDistances[0];
        array[7] = middleToDistDistances[1];
        if (command.getDistCodeNum() != null) {
            //目标二维编号
            array[3] = command.getDistCodeNum();
        }
        //小车运行方向
        array[8] = command.getRunDirection();
        //托盘顶升
        array[9] = command.getPalletLift();
        if (command.getStartToDistDistance() != null) {
            //起点到目标点的距离长度,先将int转为byte数组,再将byte数组转成两个short,分别占用4和5空间
            short[] startToDistDistances = CommonUtils.intToShorts(command.getStartToDistDistance());
            array[4] = startToDistDistances[0];
            array[5] = startToDistDistances[1];
        }
        //小车强制移动距离,先将int转为byte数组,再将byte数组转成两个short,分别占用4和5空间
        short[] forceMoveDistances = CommonUtils.intToShorts(command.getForceMoveDistance());
        array[10] = forceMoveDistances[0];
        array[11] = forceMoveDistances[1];
        if (command.getMiddleToDistDistance() != null) {
            //中间点到目标点的距离长度,先将int转为byte数组,再将byte数组转成两个short,分别占用4和5空间
            short[] middleToDistDistances = CommonUtils.intToShorts(command.getMiddleToDistDistance());
            array[6] = middleToDistDistances[0];
            array[7] = middleToDistDistances[1];
        }
        //充电开关
        array[12] = command.getChargeSwitch();
        //小车IO控制
        array[13] = command.getIOControl();
        //小车运行速度
        array[14] = command.getRunSpeed();
        //小车雷达备用
        array[15] = command.getRadarTmp();
        if (command.getRunDirection() != null) {
            //小车运行方向
            array[8] = command.getRunDirection();
        }
        if (command.getPalletLift() != null) {
            //托盘顶升
            array[9] = command.getPalletLift();
        }
        if (command.getForceMoveDistance() != null) {
            //小车强制移动距离,先将int转为byte数组,再将byte数组转成两个short,分别占用4和5空间
            short[] forceMoveDistances = CommonUtils.intToShorts(command.getForceMoveDistance());
            array[10] = forceMoveDistances[0];
            array[11] = forceMoveDistances[1];
        }
        if (command.getChargeSwitch() != null) {
            //充电开关
            array[12] = command.getChargeSwitch();
        }
        if (command.getIOControl() != null) {
            //小车IO控制
            array[13] = command.getIOControl();
        }
        if (command.getRunSpeed() != null) {
            //小车运行速度
            array[14] = command.getRunSpeed();
        }
        if (command.getRadarTmp() != null) {
            //小车雷达备用
            array[15] = command.getRadarTmp();
        }
        //指令结束位
        array[16] = command.getCommandEnd();
@@ -255,23 +286,50 @@
    //分配任务
    private void assignWork(ShuttleAssignCommand assignCommand) {
        //计算路径
        List<NavigateNode> calc = NavigateUtils.calc(assignCommand.getSourceLocNo(), assignCommand.getDistLocNo(), "in");
        //获取分段路径
        ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(calc);
        //将此map存入redis中
        HashMap<String, Object> map = new HashMap<>();
        //命令执行步序
        map.put("commandStep", 0);
        //路径数据
        map.put("path", data);
        //工作号
        map.put("wrk_no", assignCommand.getTaskNo());
        //任务数据保存到redis
        redisUtil.set("wrk_no_" + assignCommand.getTaskNo(), JSON.toJSONString(map));
        ShuttleCommand command = new ShuttleCommand();
        switch (assignCommand.getTaskMode()) {
            case 1:
            case 2:
                //计算路径
                List<NavigateNode> calc = NavigateUtils.calc(assignCommand.getSourceLocNo(), assignCommand.getDistLocNo(), assignCommand.getTaskMode().intValue());
                if (calc != null) {
                    //获取分段路径
                    ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(calc);
                    //将此map存入redis中
                    HashMap<String, Object> map = new HashMap<>();
                    //命令执行步序
                    map.put("commandStep", 0);
                    //路径数据
                    map.put("path", data);
                    //工作号
                    map.put("wrk_no", assignCommand.getTaskNo());
                    //任务数据保存到redis
                    redisUtil.set("wrk_no_" + assignCommand.getTaskNo(), JSON.toJSONString(map));
                    shuttleProtocol.setTaskNo(assignCommand.getTaskNo());
        //执行下发任务
        executeWork(assignCommand.getTaskNo());
                    //执行下发任务
                    executeWork(assignCommand.getTaskNo());
                }
                break;
            case 3:
            case 4:
                command.setCommandWord((short) 2);
                command.setPalletLift(assignCommand.getTaskMode() == 3 ? (short)1 : (short)2);
                command.setCommandEnd((short) 1);
                write(command);
                break;
            case 5:
            case 6:
            case 7:
            case 8:
                command.setCommandWord((short) 3);
                command.setForceMoveDistance(1000);
                command.setRunDirection((short) (assignCommand.getTaskMode() - 4));
                command.setCommandEnd((short) 1);
                write(command);
                break;
        }
    }
    //执行下发的指令
src/main/webapp/views/index.html
@@ -20,7 +20,7 @@
        <ul class="cl-effect-4">
            <li><a id="console" onclick="nav(this.id)" class="nav-select" href="#">主控图</a></li>
            <li><a id="pipeline" onclick="nav(this.id)" class="nav-unselect" href="#">输送设备</a></li>
            <li><a id="crn" onclick="nav(this.id)" class="nav-unselect" href="#">堆垛机</a></li>
<!--            <li><a id="crn" onclick="nav(this.id)" class="nav-unselect" href="#">堆垛机</a></li>-->
<!--            <li><a id="ste" onclick="nav(this.id)" class="nav-unselect" href="#">穿梭车</a></li>-->
            <li><a id="shuttle" onclick="nav(this.id)" class="nav-unselect" href="#">四向穿梭车</a></li>
        </ul>
src/main/webapp/views/shuttle.html
@@ -95,49 +95,17 @@
                <!-- 设备任务操作 -->
                <div class="task-operator">
                    <div style="display: flex;">
                        <div class="task-operator" style="height: auto;width: auto;">
                        <div class="task-operator" style="height: auto;width: 100%;">
                            <div class="operator-item" style="height: auto">
                                <span class="select-title">源站/源库位</span>
                                <span class="select-title">源库位/目标库位</span>
                                <div class="select-container" style="height: auto">
                                    <div class="select-container-item">
                                        <span>站</span>
                                        <label><input id="sourceStaNo" type="number" name="points" min="0" /></label>
                                        <span>源库位</span>
                                        <label><input id="sourceLocNo" type="text" name="sourceLocNo" /></label>
                                    </div>
                                    <div class="select-container-item">
                                        <span>排</span>
                                        <label><input id="sourceRow" type="number" name="points" min="1" style="background-color: #a9eeff" value="1" /></label>
                                    </div>
                                    <div class="select-container-item">
                                        <span>列</span>
                                        <label><input id="sourceBay" type="number" name="points" min="0" style="background-color: #a9eeff" value="0" /></label>
                                    </div>
                                    <div class="select-container-item">
                                        <span>层</span>
                                        <label><input id="sourceLev" type="number" name="points" min="1" style="background-color: #a9eeff" value="1" /></label>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="task-operator" style="height: auto;width: auto;">
                            <div class="operator-item" style="height: auto">
                                <span class="select-title">源站/源库位</span>
                                <div class="select-container" style="height: auto">
                                    <div class="select-container-item">
                                        <span>站</span>
                                        <label><input id="distStaNo" type="number" name="points" min="0" /></label>
                                    </div>
                                    <div class="select-container-item">
                                        <span>排</span>
                                        <label><input id="distRow" type="number" name="points" min="1" style="background-color: #a9eeff" value="1" /></label>
                                    </div>
                                    <div class="select-container-item">
                                        <span>列</span>
                                        <label><input id="distBay" type="number" name="points" min="0" style="background-color: #a9eeff" value="0" /></label>
                                    </div>
                                    <div class="select-container-item">
                                        <span>层</span>
                                        <label><input id="distLev" type="number" name="points" min="1" style="background-color: #a9eeff" value="1" /></label>
                                        <span>目标库位</span>
                                        <label><input id="distLocNo" type="text" name="distLocNo" /></label>
                                    </div>
                                </div>
                            </div>
@@ -147,14 +115,14 @@
                    <fieldset style="height: auto;padding-bottom: 20px;">
                        <legend>手动操作</legend>
                        <div class="button-group">
                            <button class="item" onclick="shuttleOperator(4)">托盘顶升</button>
                            <button class="item" onclick="shuttleOperator(4)">托盘放下</button>
                            <button class="item" onclick="shuttleOperator(1)">入库</button>
                            <button class="item" onclick="shuttleOperator(2)">出库</button>
                            <button class="item" onclick="shuttleOperator(3)">托盘顶升</button>
                            <button class="item" onclick="shuttleOperator(4)">托盘下降</button>
                            <button class="item" onclick="shuttleOperator(5)">左移</button>
                            <button class="item" onclick="shuttleOperator(6)">右移</button>
                            <button class="item" onclick="shuttleOperator(7)">前移</button>
                            <button class="item" onclick="shuttleOperator(8)">后移</button>
                            <button class="item" onclick="shuttleOperator(9)">强制移动</button>
                            <button class="item" onclick="shuttleOperator(16)">任务完成</button>
                        </div>
                    </fieldset>
                </div>
@@ -696,7 +664,9 @@
    function shuttleOperator(shuttleTaskMode) {
        http.post(baseUrl+"/shuttle/operator/shuttle", {
            shuttleNo: $('input[name="shuttleSelect"]:checked').val(),
            shuttleTaskMode: shuttleTaskMode
            shuttleTaskMode: shuttleTaskMode,
            sourceLocNo: $("#sourceLocNo").val(),
            distLocNo: $("#distLocNo").val()
        }, function (res) {
            layer.msg(res.msg, {icon: 1});
        });