自动化立体仓库 - WCS系统
Junjie
2023-10-16 c5c290a0da0a73371f3890a41cc66e02cd6b24a6
src/main/java/com/zy/common/utils/ShuttleDispatchUtils.java
@@ -1,12 +1,17 @@
package com.zy.common.utils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.SpringUtils;
import com.core.exception.CoolException;
import com.zy.asrs.entity.BasDevp;
import com.zy.asrs.entity.BasShuttle;
import com.zy.asrs.entity.WrkCharge;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.mapper.WrkChargeMapper;
import com.zy.asrs.mapper.WrkMastMapper;
import com.zy.asrs.service.BasDevpService;
import com.zy.asrs.service.BasShuttleService;
import com.zy.asrs.service.WrkMastService;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.NavigateNode;
@@ -24,6 +29,8 @@
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.LiftThread;
import com.zy.core.thread.NyShuttleThread;
import com.zy.system.entity.Config;
import com.zy.system.service.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -87,6 +94,7 @@
                if (wrkMast1 != null) {
                    wrkMast1.setShuttleNo(shuttleProtocol.getShuttleNo().intValue());
                    wrkMastMapper.updateById(wrkMast1);
                    return true;
                }
                break;
            }
@@ -123,29 +131,39 @@
            }
        }else {
            //同一楼层,没有空闲穿梭车,只能从其他楼层调度
            //寻找离任务最近的穿梭车
            for (NyShuttleThread shuttleThread : diffLev) {
            //寻找离任务楼层最近的穿梭车(不考虑跨楼层小车移动距离)
                //当前穿梭车库位号
                String currentLocNo = shuttleThread.getShuttleProtocol().getCurrentLocNo();
                int currentLev = Utils.getLev(currentLocNo);
                List<WrkMast> wrkMasts1 = wrkMastService.selectNoShuttleWrkByLev(currentLev);//判断当前穿梭车楼层是否有待分配车辆的任务,如果有则不分配这辆车
                if (wrkMasts1.size() > 0) {
                    //存在其他任务,跳过这辆车
                    continue;
            //获取任务
            WrkMast wrkMast1 = wrkMastMapper.selectByWorkNo(wrkNo);
            if (wrkMast1 != null) {
                String locNO=wrkMast1.getIoType()<100?wrkMast1.getLocNo():wrkMast1.getSourceLocNo();
                int lev = Utils.getLev(locNO);//目标楼层
                //检测目标楼层车数量是否小于允许的最大数量
                boolean checkDispatchMaxNum = checkDispatchMaxNum(lev);
                if (!checkDispatchMaxNum) {
                    return false;
                }
                //当前穿梭车线程到当前车子所在楼层的提升机口距离
                List<NavigateNode> currentShuttlePath = NavigateUtils.calc(currentLocNo, Utils.levToOutInStaLocNo(currentLev), NavigationMapType.NORMAL.id, Utils.getShuttlePoints(shuttleThread.getSlave().getId(), currentLev));//搜索空闲穿梭车,使用正常通道地图
                if (currentShuttlePath == null) {
                    continue;
                }
                int recentValue = 99999;//最小差值
                for (NyShuttleThread shuttleThread : diffLev) {
                    //当前穿梭车库位号
                    String currentLocNo = shuttleThread.getShuttleProtocol().getCurrentLocNo();
                    int currentLev = Utils.getLev(currentLocNo);
                    List<WrkMast> wrkMasts1 = wrkMastService.selectNoShuttleWrkByLev(currentLev);//判断当前穿梭车楼层是否有待分配车辆的任务,如果有则不分配这辆车
                    if (wrkMasts1.size() > 0) {
                        //存在其他任务,跳过这辆车
                        continue;
                    }
                Integer currentAllDistance = NavigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离
                if (currentAllDistance < recentAllDistance) {
                    //如果当前楼层的车路径更小,则更新最近穿梭车
                    recentShuttle = shuttleThread;
                    recentAllDistance = currentAllDistance;
                    //ABS(目标楼层 - 当前楼层) 得到差距,取最小差值
                    int currentValue = Math.abs(lev - currentLev);
                    if (currentValue < recentValue) {
                        //如果当前楼层的车路径更小,则更新最近穿梭车
                        recentShuttle = shuttleThread;
                        recentValue = currentValue;
                    }
                }
            }
        }
@@ -263,6 +281,67 @@
    }
    /**
     * 检测目标楼层车数量是否小于允许的最大数量
     * true: 小于最大数量  false: 大于或等于最大数量
     */
    public boolean checkDispatchMaxNum(Integer lev) {
        BasShuttleService basShuttleService = SpringUtils.getBean(BasShuttleService.class);
        ConfigService configService = SpringUtils.getBean(ConfigService.class);
        EntityWrapper<Config> wrapper = new EntityWrapper<>();
        wrapper.eq("code", "dispatchShuttleMaxNum");
        Config config = configService.selectOne(wrapper);
        if (config == null) {
            return false;
        }
        int levCount = 0;//目标楼层车辆数量
        for (ShuttleSlave shuttle : slaveProperties.getShuttle()) {
            //获取四向穿梭车线程
            NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttle.getId());
            NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
            if (shuttleProtocol == null || shuttleProtocol.getShuttleNo() == null) {
                continue;
            }
            NyShuttleProtocol.NyShuttlePointClass point = null;
            if (shuttleProtocol.getPoint() == null) {
                BasShuttle basShuttle = basShuttleService.selectById(shuttle.getId());//小车如果没有数据,从数据库取数据
                if (basShuttle == null || basShuttle.getPoint() == null) {
                    continue;
                }
                point = JSON.parseObject(basShuttle.getPoint(), NyShuttleProtocol.NyShuttlePointClass.class);
            }else {
                point = shuttleProtocol.getPoint();
            }
            if (point.getZ().equals(lev)) {
                levCount++;//目标楼层有车,数量增加
            }
        }
        //搜索是否存在前往目标楼层的小车移动工作档
        for (WrkMast wrkMast : wrkMastMapper.selectShuttleMoveWrk()) {
            if (wrkMast.getSourceLocNo() == null || wrkMast.getLocNo() == null) {
                continue;
            }
            int sourceLev = Utils.getLev(wrkMast.getSourceLocNo());//工作档源楼层
            int targetLev = Utils.getLev(wrkMast.getLocNo());//工作档目标楼层
            if (sourceLev == lev) {
                continue;//工作档楼层和目标楼层相同,跳过
            }
            if (targetLev == lev) {
                levCount++;//工作档目标楼层和实际楼层相同,数量增加
                continue;
            }
        }
        return levCount < Integer.parseInt(config.getValue());
    }
    /**
     * 获取穿梭车最近且空闲的提升机输送站点
     */
    public LiftStaProtocol getRecentLiftSta(Integer shuttleNo) {