|  |  | 
 |  |  | import com.alibaba.fastjson.JSONArray; | 
 |  |  | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 
 |  |  | import com.zy.asrs.framework.common.Cools; | 
 |  |  | import com.zy.asrs.framework.common.R; | 
 |  |  | import com.zy.asrs.framework.common.SnowflakeIdWorker; | 
 |  |  | import com.zy.asrs.framework.exception.CoolException; | 
 |  |  | import com.zy.asrs.wcs.core.entity.*; | 
 |  |  | import com.zy.asrs.wcs.core.kernel.AnalyzeService; | 
 |  |  | import com.zy.asrs.wcs.core.model.NavigateNode; | 
 |  |  | import com.zy.asrs.wcs.core.model.enums.DeviceCtgType; | 
 |  |  | import com.zy.asrs.wcs.core.model.enums.NavigationMapType; | 
 |  |  | import com.zy.asrs.wcs.core.model.enums.TaskStsType; | 
 |  |  | import com.zy.asrs.wcs.core.model.enums.*; | 
 |  |  | import com.zy.asrs.wcs.core.service.*; | 
 |  |  | import com.zy.asrs.wcs.rcs.News; | 
 |  |  | import com.zy.asrs.wcs.rcs.cache.SlaveConnection; | 
 |  |  | 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.ShuttleProtocol; | 
 |  |  | import com.zy.asrs.wcs.rcs.service.DeviceService; | 
 |  |  | import com.zy.asrs.wcs.rcs.thread.LiftThread; | 
 |  |  | import com.zy.asrs.wcs.rcs.thread.ShuttleThread; | 
 |  |  | import com.zy.asrs.wcs.system.entity.Dict; | 
 |  |  | import com.zy.asrs.wcs.system.service.DictService; | 
 |  |  | import org.springframework.beans.factory.annotation.Autowired; | 
 |  |  | import org.springframework.stereotype.Service; | 
 |  |  |  | 
 |  |  | 
 |  |  |     private TaskCtgService taskCtgService; | 
 |  |  |     @Autowired | 
 |  |  |     private ShuttleStandbyService shuttleStandbyService; | 
 |  |  |     @Autowired | 
 |  |  |     private DictService dictService; | 
 |  |  |  | 
 |  |  |     public synchronized ShuttleThread searchIdleShuttle(Task task) { | 
 |  |  |         String locNo = taskService.judgeInbound(task) ? task.getDestLoc() : task.getOriginLoc(); | 
 |  |  |         ShuttleThread resThread = null; | 
 |  |  |         Integer finalDistance = ShuttleDispatcher.INF; | 
 |  |  |  | 
 |  |  |         int lev = Utils.getLev(locNo); | 
 |  |  |         List<Device> list = deviceService.list(new LambdaQueryWrapper<Device>() | 
 |  |  |                 .eq(Device::getDeviceType, DeviceCtgType.SHUTTLE.val()) | 
 |  |  |                 .eq(Device::getHostId, task.getHostId()) | 
 |  |  |                 .eq(Device::getStatus, 1)); | 
 |  |  |  | 
 |  |  |         //获取同层小车 | 
 |  |  |         List<Device> currentLevDevices = new ArrayList<>(); | 
 |  |  |         //获取跨层小车 | 
 |  |  |         List<Device> diffLevDevices = new ArrayList<>(); | 
 |  |  |         for (Device device : list) { | 
 |  |  |             //获取四向穿梭车线程 | 
 |  |  |             ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue()); | 
 |  |  |             ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(); | 
 |  |  |             if (shuttleProtocol == null || shuttleProtocol.getShuttleNo() == null) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if (Utils.getLev(shuttleProtocol.getCurrentLocNo()) == lev) { | 
 |  |  |                 currentLevDevices.add(device); | 
 |  |  |             }else { | 
 |  |  |                 diffLevDevices.add(device); | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         //搜索同层 | 
 |  |  |         resThread = this.searchCurrentLevShuttle(currentLevDevices, locNo); | 
 |  |  |  | 
 |  |  |         //同层没有搜索到合适小车,跨楼层搜索 | 
 |  |  |         if(resThread == null) { | 
 |  |  |             resThread = this.searchDiffLevShuttle(diffLevDevices, locNo, task); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         return resThread; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     private synchronized ShuttleThread searchCurrentLevShuttle(List<Device> devices, String locNo) { | 
 |  |  |         ShuttleThread resThread = null; | 
 |  |  |         Integer finalDistance = ShuttleDispatcher.INF; | 
 |  |  |         for (Device device : devices) { | 
 |  |  |             if (taskService.hasBusyOutboundByShuttle(Integer.parseInt(device.getDeviceNo()))) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  | 
 |  |  |  | 
 |  |  |             if (!shuttleThread.isIdle()) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             BasShuttle basShuttle = basShuttleService.getOne(new LambdaQueryWrapper<BasShuttle>() | 
 |  |  |                     .eq(BasShuttle::getShuttleNo, device.getDeviceNo()) | 
 |  |  |                     .eq(BasShuttle::getHostId, device.getHostId())); | 
 |  |  |             if (basShuttle == null) { | 
 |  |  |                 continue;//小车基础数据不存在 | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if (!Cools.isEmpty(basShuttle.getDisableLev())) { | 
 |  |  |                 List<Integer> disableLev = JSON.parseArray(basShuttle.getDisableLev(), Integer.class); | 
 |  |  |                 //检查小车是否禁用该楼层 | 
 |  |  |                 if (disableLev.contains(Utils.getLev(locNo))) { | 
 |  |  |                     continue;//小车禁用该楼层跳过该车 | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             //检测是否存在充电任务 | 
 |  |  | 
 |  |  |                 break; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             String targetLocNo = null;//默认到提升机待机位 | 
 |  |  |             // 同楼层直接计算到目标库位 | 
 |  |  |             if (currentLev == Utils.getLev(locNo)) { | 
 |  |  |                 targetLocNo = locNo; | 
 |  |  |             }else { | 
 |  |  |                 Device recentTransferLift = Utils.getRecentTransferLift(locNo, Integer.parseInt(device.getDeviceNo())); | 
 |  |  |                 if (recentTransferLift == null) { | 
 |  |  |                     continue; | 
 |  |  |                 } | 
 |  |  |  | 
 |  |  |                 //获取小车楼层提升机待机位 | 
 |  |  |                 ShuttleStandby shuttleStandby = shuttleStandbyService.getOne(new LambdaQueryWrapper<ShuttleStandby>() | 
 |  |  |                         .eq(ShuttleStandby::getDeviceId, recentTransferLift.getId()) | 
 |  |  |                         .eq(ShuttleStandby::getDeviceLev, currentLev) | 
 |  |  |                         .eq(ShuttleStandby::getStatus, 1)); | 
 |  |  |                 targetLocNo = shuttleStandby.getDeviceLoc(); | 
 |  |  |             //当前穿梭车线程到当前车子所在楼层的目标库位距离 | 
 |  |  |             List<NavigateNode> currentShuttlePath = NavigateUtils.calc( | 
 |  |  |                     currentLocNo | 
 |  |  |                     , locNo | 
 |  |  |                     , NavigationMapType.NORMAL.id | 
 |  |  |                     , Utils.getShuttlePoints(Integer.parseInt(shuttleThread.getDevice().getDeviceNo()), currentLev) | 
 |  |  |             );//搜索空闲穿梭车,使用正常通道地图 | 
 |  |  |             if (currentShuttlePath == null) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             //当前穿梭车线程到当前车子所在楼层的提升机口距离 | 
 |  |  |             Integer currDistance = NavigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离 | 
 |  |  |  | 
 |  |  |             // 挂载任务权重 | 
 |  |  |             List<Task> tasks = taskService.selectWorkingByShuttle(Integer.valueOf(device.getDeviceNo()), null); | 
 |  |  |             if (!Cools.isEmpty(tasks)) { | 
 |  |  |                 currDistance += tasks.size() * WEIGHT; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if (currDistance < finalDistance) { | 
 |  |  |                 finalDistance = currDistance; | 
 |  |  |                 resThread = shuttleThread; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         return resThread; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     private synchronized ShuttleThread searchDiffLevShuttle(List<Device> devices, String locNo, Task task) { | 
 |  |  |         ShuttleThread resThread = null; | 
 |  |  |         Integer finalDistance = ShuttleDispatcher.INF; | 
 |  |  |  | 
 |  |  |         //检测目标楼层车数量是否小于允许的最大数量 | 
 |  |  |         boolean checkDispatchMaxNum = checkDispatchMaxNum(Utils.getLev(locNo), task.getHostId()); | 
 |  |  |  | 
 |  |  |         for (Device device : devices) { | 
 |  |  |             if (taskService.hasBusyOutboundByShuttle(Integer.parseInt(device.getDeviceNo()))) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |             //获取四向穿梭车线程 | 
 |  |  |             ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue()); | 
 |  |  |             ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(); | 
 |  |  |             if (shuttleProtocol == null || shuttleProtocol.getShuttleNo() == null) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if (!shuttleThread.isIdle()) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             BasShuttle basShuttle = basShuttleService.getOne(new LambdaQueryWrapper<BasShuttle>() | 
 |  |  |                     .eq(BasShuttle::getShuttleNo, device.getDeviceNo()) | 
 |  |  |                     .eq(BasShuttle::getHostId, device.getHostId())); | 
 |  |  |             if (basShuttle == null) { | 
 |  |  |                 continue;//小车基础数据不存在 | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if (!Cools.isEmpty(basShuttle.getDisableLev())) { | 
 |  |  |                 List<Integer> disableLev = JSON.parseArray(basShuttle.getDisableLev(), Integer.class); | 
 |  |  |                 //检查小车是否禁用该楼层 | 
 |  |  |                 if (disableLev.contains(Utils.getLev(locNo))) { | 
 |  |  |                     continue;//小车禁用该楼层跳过该车 | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             //检测是否存在充电任务 | 
 |  |  |             Task taskCharge = taskService.selectChargeWorking(Integer.valueOf(device.getDeviceNo())); | 
 |  |  |             if (taskCharge != null) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             // 有没有被其他任务调度 | 
 |  |  |             int currentLev = Utils.getLev(shuttleProtocol.getCurrentLocNo());//小车当前层高 | 
 |  |  |             String currentLocNo = shuttleProtocol.getCurrentLocNo();//小车当前库位号 | 
 |  |  |  | 
 |  |  |             if (!checkDispatchMaxNum) { | 
 |  |  |                 News.info("{}任务,{}层,已经达到当前楼层调度车辆最大值", task.getTaskNo(), Utils.getLev(locNo)); | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             //获取距离小车位置最近的空闲可换层提升机 | 
 |  |  |             LiftThread liftThread = liftDispatcher.searchIdleLift(currentLocNo, task.getHostId(), true); | 
 |  |  |             if (liftThread == null) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |             Device recentTransferLift = liftThread.getDevice(); | 
 |  |  |  | 
 |  |  |             //获取小车楼层提升机待机位 | 
 |  |  |             ShuttleStandby shuttleStandby = shuttleStandbyService.getOne(new LambdaQueryWrapper<ShuttleStandby>() | 
 |  |  |                     .eq(ShuttleStandby::getDeviceId, recentTransferLift.getId()) | 
 |  |  |                     .eq(ShuttleStandby::getDeviceLev, currentLev) | 
 |  |  |                     .eq(ShuttleStandby::getStatus, 1)); | 
 |  |  |             String targetLocNo = shuttleStandby.getDeviceLoc(); | 
 |  |  |  | 
 |  |  |             //当前穿梭车线程到当前车子所在楼层的提升机待机位距离 | 
 |  |  |             List<NavigateNode> currentShuttlePath = NavigateUtils.calc( | 
 |  |  |                     currentLocNo | 
 |  |  |                     , targetLocNo | 
 |  |  | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             // 挂载任务权重 | 
 |  |  |             List<Task> tasks = taskService.selectWorkingByShuttle(Integer.valueOf(device.getDeviceNo())); | 
 |  |  |             List<Task> tasks = taskService.selectWorkingByShuttle(Integer.valueOf(device.getDeviceNo()), null); | 
 |  |  |             if (!Cools.isEmpty(tasks)) { | 
 |  |  |                 currDistance += tasks.size() * WEIGHT; | 
 |  |  |             } | 
 |  |  | 
 |  |  |  | 
 |  |  |         //获取迁移任务类型 | 
 |  |  |         TaskCtg taskCtg = taskCtgService.getOne(new LambdaQueryWrapper<TaskCtg>() | 
 |  |  |                 .eq(TaskCtg::getFlag, "MOVE") | 
 |  |  |                 .eq(TaskCtg::getFlag, String.valueOf(TaskCtgType.MOVE)) | 
 |  |  |                 .eq(TaskCtg::getStatus, 1)); | 
 |  |  |         if (taskCtg == null) { | 
 |  |  |             return null; | 
 |  |  | 
 |  |  |  | 
 |  |  |         //获取手动任务类型 | 
 |  |  |         TaskCtg taskCtg = taskCtgService.getOne(new LambdaQueryWrapper<TaskCtg>() | 
 |  |  |                 .eq(TaskCtg::getFlag, "MANUAL") | 
 |  |  |                 .eq(TaskCtg::getFlag, String.valueOf(TaskCtgType.MANUAL)) | 
 |  |  |                 .eq(TaskCtg::getStatus, 1)); | 
 |  |  |         if (taskCtg == null) { | 
 |  |  |             return null; | 
 |  |  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 搜索避让库位,通过小车号和目标库位 | 
 |  |  |      * 搜索可用库位,通过小车号和目标库位 | 
 |  |  |      */ | 
 |  |  |     public String searchStandByLocNo(Integer shuttleNo, Long hostId, String locNo) { | 
 |  |  |     public String searchAvailableLocNo(Integer shuttleNo, Long hostId, String currentLocNo, List<String> locNos) { | 
 |  |  |         BasShuttle basShuttle = basShuttleService.getOne(new LambdaQueryWrapper<BasShuttle>() | 
 |  |  |                 .eq(BasShuttle::getShuttleNo, shuttleNo) | 
 |  |  |                 .eq(BasShuttle::getHostId, hostId)); | 
 |  |  | 
 |  |  |             throw new CoolException("小车基础数据不存在"); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         String idleLoc = basShuttle.getIdleLoc(); | 
 |  |  |         if (Cools.isEmpty(idleLoc)) { | 
 |  |  |             throw new CoolException("小车避让数据不存在"); | 
 |  |  |         if (locNos.isEmpty()) { | 
 |  |  |             throw new CoolException("当前层无避让位置"); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         int lev = Utils.getLev(locNo);//当前楼层 | 
 |  |  |         JSONArray standbyLoc = JSON.parseArray(idleLoc); | 
 |  |  |         if (lev > standbyLoc.size()) { | 
 |  |  |             throw new CoolException("避让数据异常"); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         Object object = standbyLoc.get(lev - 1); | 
 |  |  |         List<String> locs = JSON.parseArray(object.toString(), String.class); | 
 |  |  |         if (locs.isEmpty()) { | 
 |  |  |             throw new CoolException("避让数据为空"); | 
 |  |  |         } | 
 |  |  |         int lev = Utils.getLev(currentLocNo); | 
 |  |  |  | 
 |  |  |         Integer finalDistance = ShuttleDispatcher.INF; | 
 |  |  |         String recentLoc = null; | 
 |  |  |         for (String loc : locs) { | 
 |  |  |         for (String loc : locNos) { | 
 |  |  |             //当前穿梭车到避让位计算 | 
 |  |  |             List<NavigateNode> currentShuttlePath = NavigateUtils.calc( | 
 |  |  |                     locNo | 
 |  |  |                     currentLocNo | 
 |  |  |                     , loc | 
 |  |  |                     , NavigationMapType.NORMAL.id | 
 |  |  |                     , Utils.getShuttlePoints(shuttleNo, lev) | 
 |  |  | 
 |  |  |         return recentLoc; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 检测目标楼层车数量是否小于允许的最大数量 | 
 |  |  |      * true: 小于最大数量  false: 大于或等于最大数量 | 
 |  |  |      */ | 
 |  |  |     public boolean checkDispatchMaxNum(Integer lev, Long hostId) { | 
 |  |  |         Dict dict = dictService.getOne(new LambdaQueryWrapper<Dict>().eq(Dict::getFlag, "dispatchShuttleMaxNum")); | 
 |  |  |         if (dict == null) { | 
 |  |  |             return false; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         ArrayList<Integer> shuttleNos = new ArrayList<>(); | 
 |  |  |         List<Device> list = deviceService.list(new LambdaQueryWrapper<Device>() | 
 |  |  |                 .eq(Device::getDeviceType, DeviceCtgType.SHUTTLE.val()) | 
 |  |  |                 .eq(Device::getHostId, hostId) | 
 |  |  |                 .eq(Device::getStatus, 1)); | 
 |  |  |  | 
 |  |  |         for (Device device : list) { | 
 |  |  |             //获取四向穿梭车线程 | 
 |  |  |             ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue()); | 
 |  |  |             if (shuttleThread == null) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(); | 
 |  |  |             if (shuttleProtocol == null) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if (shuttleProtocol.getProtocolStatusType().equals(ShuttleProtocolStatusType.OFFLINE)) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if(!shuttleThread.isDeviceIdle()) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if(shuttleProtocol.getCurrentLocNo() == null) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if (Utils.getLev(shuttleProtocol.getCurrentLocNo()) == lev) { | 
 |  |  |                 if (shuttleProtocol.getHasCharge()) { | 
 |  |  |                     continue;//充电中 | 
 |  |  |                 } | 
 |  |  |  | 
 |  |  |                 shuttleNos.add(shuttleProtocol.getShuttleNo());//目标楼层有车,添加进list | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         //搜索是否存在前往目标楼层的小车移动工作档 | 
 |  |  |         for (Task task : taskService.list(new LambdaQueryWrapper<Task>() | 
 |  |  |                 .in(Task::getTaskSts, TaskStsType.NEW_MOVE.sts, TaskStsType.ANALYZE_MOVE.sts, TaskStsType.EXECUTE_MOVE.sts, TaskStsType.COMPLETE_MOVE.sts))) { | 
 |  |  |             if (task.getOriginLoc() == null || task.getDestLoc() == null) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             int sourceLev = Utils.getLev(task.getOriginLoc());//工作档源楼层 | 
 |  |  |             int targetLev = Utils.getLev(task.getDestLoc());//工作档目标楼层 | 
 |  |  |             if (sourceLev == targetLev) { | 
 |  |  |                 continue;//工作档楼层和目标楼层相同,跳过 | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if (targetLev == lev) { | 
 |  |  |                 //工作档目标楼层和实际楼层相同,数量增加 | 
 |  |  |                 if (!shuttleNos.contains(task.getShuttleNo())) { | 
 |  |  |                     shuttleNos.add(task.getShuttleNo()); | 
 |  |  |                 } | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         //搜索是否存在前往目标楼层的小车工作档 | 
 |  |  |         for (Task task : taskService.list(new LambdaQueryWrapper<Task>() | 
 |  |  |                 .in(Task::getTaskSts, TaskStsType.NEW_INBOUND.sts, TaskStsType.ANALYZE_INBOUND.sts, TaskStsType.EXECUTE_INBOUND.sts, TaskStsType.COMPLETE_INBOUND.sts | 
 |  |  |                         , TaskStsType.NEW_OUTBOUND.sts, TaskStsType.ANALYZE_OUTBOUND.sts, TaskStsType.EXECUTE_OUTBOUND.sts, TaskStsType.COMPLETE_OUTBOUND.sts))) { | 
 |  |  |             String locNo = taskService.judgeInbound(task) ? task.getDestLoc() : task.getOriginLoc(); | 
 |  |  |             if (Utils.getLev(locNo) != lev) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if (task.getShuttleNo() == null) { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if (!shuttleNos.contains(task.getShuttleNo())) { | 
 |  |  |                 shuttleNos.add(task.getShuttleNo()); | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         return shuttleNos.size() < Integer.parseInt(dict.getValue()); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     //分析出库路径待机库位 | 
 |  |  |     public String analyzeOutPathWaitLoc(String startLoc, String targetLoc, Device shuttleDevice) { | 
 |  |  |         //计算路径并分解成两段动作 | 
 |  |  |         List<NavigateNode> nodeList = NavigateUtils.calc(startLoc, targetLoc, NavigationMapType.DFX.id, Utils.getShuttlePoints(Integer.parseInt(shuttleDevice.getDeviceNo()), Utils.getLev(startLoc))); | 
 |  |  |         if (nodeList == null) { | 
 |  |  |             News.error("{} dash {} can't find navigate path!", startLoc, targetLoc); | 
 |  |  |             return null; | 
 |  |  |         } | 
 |  |  |         //获取分段路径 | 
 |  |  |         ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(nodeList); | 
 |  |  |         if (data.size() <= 1) { | 
 |  |  |             return startLoc;//两点之间只有一段路径,在起点位置等待 | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         //取出倒数第二段路径 | 
 |  |  |         ArrayList<NavigateNode> navigateNodes = data.get(data.size() - 2); | 
 |  |  |         NavigateNode startNode = navigateNodes.get(0); | 
 |  |  |         String lastPathStartLoc = Utils.getLocNo(startNode.getX(), startNode.getY(), startNode.getZ()); | 
 |  |  |         return lastPathStartLoc; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |  | 
 |  |  | } |