小车调度
This commit is contained in:
@@ -9,30 +9,26 @@ import java.util.Map;
|
||||
|
||||
public interface RoadCacheService {
|
||||
|
||||
/**
|
||||
* 获取指定楼层的缓存
|
||||
* @param floor 楼层
|
||||
* @return
|
||||
*/
|
||||
Map<String,WcsSrgvMap> getArrByRoadSite(Integer floor);
|
||||
|
||||
int[][] updateRoadCache(int floor, List<int[]> grid ,int value);
|
||||
|
||||
List<int[]> findFullPath(int floor, int startX, int startY, int endX, int endY);
|
||||
int[][] findFullMap(int floor, int startX, int startY, int endX, int endY);
|
||||
int[][] findFullMap(int floor, int startX, int startY, int endX, int endY, DeviceSrgv srgvPlc);
|
||||
|
||||
List<int[]> findEmptyPath(int floor, int startX, int startY, int endX, int endY);
|
||||
|
||||
int[][] findEmptyMap(int floor, int startX, int startY, int endX, int endY);
|
||||
int[][] findEmptyMap(int floor, int startX, int startY, int endX, int endY, DeviceSrgv splc);
|
||||
|
||||
Map<String, String> getRoadSiteByArr(int floor);
|
||||
|
||||
int[][] getRoadCache(int floor);
|
||||
|
||||
Map<String, int[]> getArrByRoadSite(int floor);
|
||||
|
||||
List<WcsSrgvMap> getRoadDataCache(int floor);
|
||||
|
||||
|
||||
int[][] findMap(int floor);
|
||||
|
||||
int[][] findFullMap(int floor, int startX, int startY, int endX, int endY,DeviceSrgv srgvPlc,List<String> noSite);
|
||||
|
||||
Map<String, String> getSpaceDataCache();
|
||||
/**
|
||||
* 处理地图
|
||||
* @param arrByRoadSite
|
||||
* @param deviceSrgv
|
||||
* @return
|
||||
*/
|
||||
int[][] handleMap(Map<String, WcsSrgvMap> arrByRoadSite, DeviceSrgv deviceSrgv);
|
||||
/**
|
||||
* 根据x y z 获取指定位置的缓存
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @return
|
||||
*/
|
||||
WcsSrgvMap selectRoadSiteByArr(int x, int y, int z);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
package com.ruoyi.bas.srgvmap.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import com.ruoyi.bas.srgvmap.domain.WcsSrgvMap;
|
||||
import com.ruoyi.bas.srgvmap.service.IWcsSrgvMapService;
|
||||
import com.ruoyi.bas.srgvmap.service.RoadCacheService;
|
||||
import com.ruoyi.device.srgv.domain.DeviceSrgv;
|
||||
import com.ruoyi.device.srgv.service.IDeviceSrgvService;
|
||||
import com.ruoyi.queue.srgv.domain.WcsSrgvQueue;
|
||||
import com.ruoyi.queue.srgv.service.IWcsSrgvQueueService;
|
||||
import com.ruoyi.schedule.plcRead.srgv.PlcSrgvRead;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@@ -31,14 +32,76 @@ public class AgvPathProcessor {
|
||||
public void processNoSites(int[][] roadCache, int floor, List<String> noSite) {
|
||||
}
|
||||
|
||||
public void processAgvPathInfo(int[][] ints, int floor) {
|
||||
public void processAgvPathInfo(Map<String, WcsSrgvMap> maps,Integer agvId) {
|
||||
List<WcsSrgvQueue> wcsSrgvQueues = wcsSagvQueueMapper.selectWcsSrgvQueueList(new WcsSrgvQueue());
|
||||
if (CollUtil.isNotEmpty(wcsSrgvQueues)) {
|
||||
//筛选其他小车队列
|
||||
wcsSrgvQueues = wcsSrgvQueues.stream().filter(x -> x.getAgvId().equals(Convert.toStr(agvId))).collect(Collectors.toList());
|
||||
|
||||
//获取其他小车占用点位列表
|
||||
HashSet<String> siteList = new HashSet<>();
|
||||
for (WcsSrgvQueue wcsSrgvQueue : wcsSrgvQueues) {
|
||||
String[] split = wcsSrgvQueue.getPathInfo().split(",");
|
||||
siteList.addAll(Arrays.asList(split));
|
||||
}
|
||||
|
||||
//设置其他小车占用点位
|
||||
for (String site : siteList) {
|
||||
if (maps.containsKey(site)){
|
||||
maps.get(site).setValue(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void processOnlineAgvSites(int[][] ints, int floor) {
|
||||
/**
|
||||
* 更新AGV路径映射,只保留当前站点及以后的路径
|
||||
*/
|
||||
private void updateAgvPathMap(Map<String, String> agvPathMap, List<SRGVPlc> srgvPlcs) {
|
||||
for (SRGVPlc plc : srgvPlcs) {
|
||||
com.ruoyi.plc.sagv.SRGVData agvData = plc.getAgvData();
|
||||
if (agvData != null && agvData.getAgvId() != null) {
|
||||
String agvId = agvData.getAgvId();
|
||||
String currSite = agvData.getCurrSite();
|
||||
|
||||
// 如果这个agvId在agvPathMap中存在,且currSite不为空
|
||||
if (agvPathMap.containsKey(agvId) && currSite != null) {
|
||||
String pathInfo = agvPathMap.get(agvId);
|
||||
|
||||
// 处理路径信息,只保留当前站点及以后的路径
|
||||
if (pathInfo != null && !pathInfo.isEmpty()) {
|
||||
String[] pathArray = pathInfo.split(",");
|
||||
StringBuilder newPathBuilder = new StringBuilder();
|
||||
|
||||
boolean foundCurrentSite = false;
|
||||
for (String site : pathArray) {
|
||||
if (site.trim().equals(currSite.trim())) {
|
||||
foundCurrentSite = true;
|
||||
}
|
||||
|
||||
if (foundCurrentSite) {
|
||||
if (newPathBuilder.length() > 0) {
|
||||
newPathBuilder.append(",");
|
||||
}
|
||||
newPathBuilder.append(site);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果找到了当前站点,更新路径信息
|
||||
if (foundCurrentSite) {
|
||||
agvPathMap.put(agvId, newPathBuilder.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void processOfflineAgvSites(int[][] ints, int floor) {
|
||||
public void processOnlineAgvSites(Map<String, WcsSrgvMap> maps) {
|
||||
}
|
||||
|
||||
public void processOfflineAgvSites(Map<String, WcsSrgvMap> maps) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,311 +1,150 @@
|
||||
package com.ruoyi.bas.srgvmap.service.impl;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.ruoyi.bas.srgvmap.domain.WcsSrgvMap;
|
||||
import com.ruoyi.bas.srgvmap.mapper.WcsSrgvMapMapper;
|
||||
import com.ruoyi.bas.srgvmap.service.RoadCacheService;
|
||||
import com.ruoyi.device.srgv.domain.DeviceSrgv;
|
||||
import com.ruoyi.schedule.plcRead.srgv.roadUtil.PathFinder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.ruoyi.device.srgv.service.IDeviceSrgvService;
|
||||
import com.ruoyi.queue.srgv.domain.WcsSrgvQueue;
|
||||
import com.ruoyi.queue.srgv.service.IWcsSrgvQueueService;
|
||||
import com.ruoyi.schedule.plcRead.srgv.PlcSrgvRead;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class RoadCacheServiceImpl implements RoadCacheService {
|
||||
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
|
||||
@Autowired
|
||||
private WcsSrgvMapMapper wcsSrgvMapMapper;
|
||||
|
||||
@Autowired
|
||||
private CacheManager cacheManager;
|
||||
|
||||
|
||||
private IWcsSrgvQueueService wcsSrgvQueueService;
|
||||
@Autowired
|
||||
private RoadCacheService selfProxy; // 注入代理对象
|
||||
private IDeviceSrgvService deviceSrgvService;
|
||||
|
||||
|
||||
@Autowired
|
||||
private AgvPathProcessor agvPathProcessor;
|
||||
@Override
|
||||
public Map<String, WcsSrgvMap> getArrByRoadSite(Integer floor) {
|
||||
WcsSrgvMap param = new WcsSrgvMap();
|
||||
param.setZ(floor);
|
||||
List<WcsSrgvMap> wcsSrgvMaps = wcsSrgvMapMapper.selectWcsSrgvMapList(param);
|
||||
|
||||
HashMap<String, WcsSrgvMap> maps = new HashMap<>();
|
||||
for (WcsSrgvMap wcsSrgvMap : wcsSrgvMaps) {
|
||||
maps.put(wcsSrgvMap.getSiteId(), wcsSrgvMap);
|
||||
}
|
||||
return maps;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* */
|
||||
@Autowired
|
||||
@Cacheable(value = "CSpaceDataCache" ,key = "'CSpaceDataCacheKey_'")
|
||||
public Map<String,String> getSpaceDataCache() {
|
||||
log.info("从数据库获取初始化地图数据");
|
||||
@Override
|
||||
public int[][] handleMap(Map<String, WcsSrgvMap> maps, DeviceSrgv deviceSrgv) {
|
||||
|
||||
WcsSrgvMap wcsSrgvMap = new WcsSrgvMap();
|
||||
List<WcsSrgvMap> wcsSrgvMaps = wcsSrgvMapMapper.selectWcsSrgvMapList(wcsSrgvMap);
|
||||
//将集合转为map,
|
||||
Map<String, String> siteMap = new HashMap<>();
|
||||
//1.锁定其他车任务路径
|
||||
lockedOtherCarQueuePath(maps, deviceSrgv);
|
||||
//2.锁定无任务小车当前位置
|
||||
lockedOtherCarCurrSite(maps, deviceSrgv);
|
||||
//3.锁定离线小车当前位置
|
||||
lockedOfflineCarCurrSite(maps, deviceSrgv);
|
||||
|
||||
for (WcsSrgvMap srgvMap : wcsSrgvMaps) {
|
||||
String siteId = srgvMap.getSiteId();
|
||||
String warehouse = srgvMap.getWarehouse();
|
||||
if(!Objects.equals(siteId,"000")){
|
||||
siteMap.put(siteId,warehouse);
|
||||
int[][] mapsInt = new int[29][11];
|
||||
for (String site : maps.keySet()) {
|
||||
WcsSrgvMap wcsSrgvMap = maps.get(site);
|
||||
mapsInt[wcsSrgvMap.getX()][wcsSrgvMap.getY()] = wcsSrgvMap.getValue();
|
||||
}
|
||||
return mapsInt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WcsSrgvMap selectRoadSiteByArr(int x, int y, int z) {
|
||||
WcsSrgvMap param = new WcsSrgvMap();
|
||||
param.setX(x);
|
||||
param.setY(y);
|
||||
param.setZ(z);
|
||||
List<WcsSrgvMap> wcsSrgvMaps = wcsSrgvMapMapper.selectWcsSrgvMapList(param);
|
||||
if (CollUtil.isNotEmpty(wcsSrgvMaps)){
|
||||
return wcsSrgvMaps.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 锁定离线小车当前位置
|
||||
*
|
||||
* @param maps
|
||||
* @param deviceSrgv
|
||||
*/
|
||||
private void lockedOfflineCarCurrSite(Map<String, WcsSrgvMap> maps, DeviceSrgv deviceSrgv) {
|
||||
//获取所有小车状态
|
||||
List<DeviceSrgv> deviceSrgvs = deviceSrgvService.selectDeviceSrgvList(new DeviceSrgv());
|
||||
//获取其他小车离线站点
|
||||
List<DeviceSrgv> offlineSrgvList = deviceSrgvs.stream().filter(x ->
|
||||
!x.getDeviceId().equals(deviceSrgv.getDeviceId()) &&
|
||||
StrUtil.isNotEmpty(x.getOfflineSite())
|
||||
).collect(Collectors.toList());
|
||||
//锁定离线小车站点
|
||||
if (CollUtil.isNotEmpty(offlineSrgvList)) {
|
||||
for (DeviceSrgv offlineSrgv : offlineSrgvList) {
|
||||
if (maps.containsKey(offlineSrgv.getOfflineSite())) {
|
||||
maps.get(offlineSrgv.getOfflineSite()).setValue(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return siteMap;
|
||||
}
|
||||
|
||||
|
||||
@Cacheable(value = "RoadDataCache" ,key = "'RoadDataCacheKey_floor_' +#floor")
|
||||
@Override
|
||||
public List<WcsSrgvMap> getRoadDataCache(int floor) {
|
||||
log.info("从数据库获取初始化地图");
|
||||
|
||||
WcsSrgvMap wcsSrgvMap1 = new WcsSrgvMap();
|
||||
wcsSrgvMap1.setUz(floor);
|
||||
List<WcsSrgvMap> wcsSrgvMaps = wcsSrgvMapMapper.selectWcsSrgvMapList(wcsSrgvMap1);
|
||||
|
||||
return wcsSrgvMaps;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* 每层二维地图
|
||||
* */
|
||||
@Override
|
||||
@Cacheable(value = "RoadCache" ,key = "'RoadCacheKey_floor_' +#floor")
|
||||
public int[][] getRoadCache(int floor) {
|
||||
|
||||
List<WcsSrgvMap> roadDataCache = selfProxy.getRoadDataCache(floor);
|
||||
|
||||
//集合转为二维数组
|
||||
int[][] grid = new int[30][137];
|
||||
for (WcsSrgvMap roadMap : roadDataCache) {
|
||||
grid[roadMap.getX().intValue()][roadMap.getY().intValue()] = roadMap.getValue().intValue();
|
||||
/**
|
||||
* 锁定无任务小车当前位置
|
||||
*
|
||||
* @param arrByRoadSite
|
||||
* @param deviceSrgv
|
||||
*/
|
||||
private void lockedOtherCarCurrSite(Map<String, WcsSrgvMap> arrByRoadSite, DeviceSrgv deviceSrgv) {
|
||||
//锁定其他车当前位置
|
||||
for (String sRgv : PlcSrgvRead.deviceSrgvMap.keySet()) {
|
||||
if (!sRgv.equals(deviceSrgv.getDeviceId().toString())) {
|
||||
DeviceSrgv otherCar = PlcSrgvRead.deviceSrgvMap.get(sRgv);
|
||||
String currSite = otherCar.getCurrSite();
|
||||
if (arrByRoadSite.containsKey(currSite)) {
|
||||
arrByRoadSite.get(currSite).setValue(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return grid;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 每层 站点与二维数组关系
|
||||
* */
|
||||
@Override
|
||||
@CachePut(value = "SiteCache" ,key = "'SiteKey_floor_' +#floor")
|
||||
public Map<String, int[]> getArrByRoadSite(int floor) {
|
||||
List<WcsSrgvMap> roadDataCache = selfProxy.getRoadDataCache(floor);
|
||||
|
||||
//将集合转为map,key为siteId,value为x,y
|
||||
Map<String, int[]> siteMap = new HashMap<>();
|
||||
for (WcsSrgvMap map : roadDataCache) {
|
||||
siteMap.put(map.getSiteId(), new int[]{map.getX(), map.getY(),floor});
|
||||
/**
|
||||
* 锁定其他车任务路径
|
||||
*
|
||||
* @param maps
|
||||
* @param deviceSrgv
|
||||
*/
|
||||
private void lockedOtherCarQueuePath(Map<String, WcsSrgvMap> maps, DeviceSrgv deviceSrgv) {
|
||||
//查询所有小车作业
|
||||
List<WcsSrgvQueue> wcsSrgvQueues = wcsSrgvQueueService.selectWcsSrgvQueueList(new WcsSrgvQueue());
|
||||
if (CollUtil.isNotEmpty(wcsSrgvQueues)) {
|
||||
//筛选其他小车队列
|
||||
List<WcsSrgvQueue> otherCarQueue = wcsSrgvQueues.stream().filter(x -> !x.getAgvId().equals(deviceSrgv.getDeviceId().toString())).collect(Collectors.toList());
|
||||
if (CollUtil.isNotEmpty(otherCarQueue)) {
|
||||
//添加其他小车路径列表
|
||||
HashSet<String> otherCarSiteList = new HashSet<>();
|
||||
for (WcsSrgvQueue wcsSrgvQueue : otherCarQueue) {
|
||||
otherCarSiteList.addAll(Arrays.asList(wcsSrgvQueue.getPathInfo().split(",")));
|
||||
}
|
||||
//锁定其他小车路径
|
||||
if (CollUtil.isNotEmpty(otherCarSiteList)) {
|
||||
for (String siteId : otherCarSiteList) {
|
||||
if (maps.containsKey(siteId)) {
|
||||
maps.get(siteId).setValue(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return siteMap;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* */
|
||||
@Override
|
||||
@CachePut(value = "ArrCache" ,key = "'ArrKey_floor_' +#floor")
|
||||
public Map<String, String> getRoadSiteByArr(int floor) {
|
||||
List<WcsSrgvMap> roadDataCache = selfProxy.getRoadDataCache(floor);
|
||||
|
||||
//将集合转为map,key为x,y,value为siteId
|
||||
Map<String, String> siteMap = new HashMap<>();
|
||||
for (WcsSrgvMap map : roadDataCache) {
|
||||
siteMap.put(map.getX()+","+map.getY(), map.getSiteId());
|
||||
}
|
||||
|
||||
return siteMap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//更新地图
|
||||
@Override
|
||||
@CachePut(value = "RoadCache" ,key = "'RoadCacheKey_floor_' +#floor")
|
||||
public int[][] updateRoadCache(int floor, List<int[]> grid,int value) {
|
||||
|
||||
|
||||
int[][] roadCache = selfProxy.getRoadCache(floor);
|
||||
|
||||
for (int[] ints : grid) {
|
||||
roadCache[ints[0]][ints[1]] = value;
|
||||
}
|
||||
|
||||
return roadCache;
|
||||
}
|
||||
|
||||
|
||||
//获取载货路径
|
||||
@Override
|
||||
public List<int[]> findFullPath(int floor, int startX, int startY, int endX, int endY) {
|
||||
|
||||
int[][] grid = selfProxy.getRoadCache(floor);
|
||||
|
||||
//对二维数组 进行深拷贝
|
||||
int[][] roadCache = Arrays.stream(grid).map(int[]::clone).toArray(int[][]::new);
|
||||
|
||||
//剔除不允许站点
|
||||
extractInflectionPoints(roadCache,floor);
|
||||
|
||||
// 调用路径规划算法
|
||||
return PathFinder.findShortestPathFrom2To2Or1(roadCache,startX,startY,endX,endY);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int[][] findFullMap(int floor, int startX, int startY, int endX, int endY) {
|
||||
|
||||
int[][] grid = selfProxy.getRoadCache(floor);
|
||||
|
||||
//对二维数组 进行深拷贝
|
||||
int[][] roadCache = Arrays.stream(grid).map(int[]::clone).toArray(int[][]::new);
|
||||
|
||||
//剔除不允许站点
|
||||
extractInflectionPoints(roadCache,floor);
|
||||
|
||||
// 调用路径规划算法
|
||||
return roadCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[][] findFullMap(int floor, int startX, int startY, int endX, int endY,DeviceSrgv splc) {
|
||||
|
||||
int[][] grid = selfProxy.getRoadCache(floor);
|
||||
|
||||
//对二维数组 进行深拷贝
|
||||
int[][] roadCache = Arrays.stream(grid).map(int[]::clone).toArray(int[][]::new);
|
||||
|
||||
//剔除不允许站点(不包含自己)
|
||||
extractInflectionPoints(roadCache,floor,splc);
|
||||
|
||||
// 调用路径规划算法
|
||||
return roadCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[][] findFullMap(int floor, int startX, int startY, int endX, int endY,DeviceSrgv splc,List<String> noSite) {
|
||||
|
||||
int[][] grid = selfProxy.getRoadCache(floor);
|
||||
|
||||
//对二维数组 进行深拷贝
|
||||
int[][] roadCache = Arrays.stream(grid).map(int[]::clone).toArray(int[][]::new);
|
||||
|
||||
//剔除不允许站点(不包含自己)
|
||||
extractInflectionPoints(roadCache,floor,splc);
|
||||
|
||||
//将地图 roadCache 中的 所有站点noSite排除掉
|
||||
agvPathProcessor.processNoSites(roadCache,floor,noSite);
|
||||
|
||||
// 调用路径规划算法
|
||||
return roadCache;
|
||||
}
|
||||
|
||||
|
||||
//获取空载路径
|
||||
@Override
|
||||
public List<int[]> findEmptyPath(int floor, int startX, int startY, int endX, int endY) {
|
||||
|
||||
|
||||
int[][] grid = selfProxy.getRoadCache(floor);
|
||||
|
||||
//对二维数组 进行深拷贝
|
||||
int[][] roadCache = Arrays.stream(grid).map(int[]::clone).toArray(int[][]::new);
|
||||
|
||||
//剔除不允许站点
|
||||
extractInflectionPoints(roadCache,floor);
|
||||
|
||||
List<int[]> shortestPath = PathFinder.findShortestPath(grid, startX, startY, endX, endY);
|
||||
return shortestPath;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int[][] findEmptyMap(int floor, int startX, int startY, int endX, int endY, DeviceSrgv splc) {
|
||||
|
||||
|
||||
int[][] grid = selfProxy.getRoadCache(floor);
|
||||
|
||||
//对二维数组 进行深拷贝
|
||||
int[][] roadCache = Arrays.stream(grid).map(int[]::clone).toArray(int[][]::new);
|
||||
|
||||
//剔除不允许站点(不包含自己)
|
||||
extractInflectionPoints(roadCache,floor,splc);
|
||||
|
||||
|
||||
return roadCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[][] findEmptyMap(int floor, int startX, int startY, int endX, int endY) {
|
||||
|
||||
|
||||
int[][] grid = selfProxy.getRoadCache(floor);
|
||||
|
||||
//对二维数组 进行深拷贝
|
||||
int[][] roadCache = Arrays.stream(grid).map(int[]::clone).toArray(int[][]::new);
|
||||
|
||||
//剔除不允许站点
|
||||
extractInflectionPoints(roadCache,floor);
|
||||
|
||||
|
||||
return roadCache;
|
||||
}
|
||||
|
||||
/*
|
||||
* 剔除不可用站点,并返回新地图
|
||||
*
|
||||
* */
|
||||
private int[][] extractInflectionPoints(int[][] ints,int floor){
|
||||
|
||||
|
||||
//所有车锁定路径
|
||||
agvPathProcessor.processAgvPathInfo(ints,floor);
|
||||
//所有在线车当前站点
|
||||
agvPathProcessor.processOnlineAgvSites(ints,floor);
|
||||
//所有离线车站点
|
||||
agvPathProcessor.processOfflineAgvSites(ints,floor);
|
||||
|
||||
return ints;
|
||||
}
|
||||
|
||||
private int[][] extractInflectionPoints(int[][] ints, int floor, DeviceSrgv splc){
|
||||
|
||||
String agvId = String.valueOf(splc.getDeviceId());
|
||||
String currSite = splc.getCurrSite();
|
||||
//所有车锁定路径
|
||||
agvPathProcessor.processAgvPathInfo(ints,floor);
|
||||
//所有在线车当前站点
|
||||
agvPathProcessor.processOnlineAgvSites(ints,floor);
|
||||
//所有离线车站点
|
||||
agvPathProcessor.processOfflineAgvSites(ints,floor);
|
||||
|
||||
return ints;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[][] findMap(int floor) {
|
||||
int[][] grid = selfProxy.getRoadCache(floor);
|
||||
|
||||
//对二维数组 进行深拷贝
|
||||
int[][] roadCache = Arrays.stream(grid).map(int[]::clone).toArray(int[][]::new);
|
||||
|
||||
return roadCache;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ public class PathFinder {
|
||||
int[][] gCost = new int[rows][cols];
|
||||
// fCost: gCost + 启发式估计成本(从当前节点到终点)
|
||||
int[][] fCost = new int[rows][cols];
|
||||
// prev: 记录路径回溯信息
|
||||
// prev: 记录路径回溯信息,初始化为无效值
|
||||
int[][][] prev = new int[rows][cols][2];
|
||||
// closedSet: 记录已访问的节点
|
||||
boolean[][] closedSet = new boolean[rows][cols];
|
||||
@@ -137,6 +137,10 @@ public class PathFinder {
|
||||
for (int i = 0; i < rows; i++) {
|
||||
Arrays.fill(gCost[i], Integer.MAX_VALUE);
|
||||
Arrays.fill(fCost[i], Integer.MAX_VALUE);
|
||||
// 初始化 prev 数组为无效值 [-1, -1]
|
||||
for (int j = 0; j < cols; j++) {
|
||||
prev[i][j] = new int[]{-1, -1};
|
||||
}
|
||||
}
|
||||
|
||||
// 优先队列,按fCost排序
|
||||
@@ -211,8 +215,8 @@ public class PathFinder {
|
||||
path.add(new int[]{currX, currY});
|
||||
int[] p = prev[currX][currY];
|
||||
|
||||
// 检查路径有效性
|
||||
if (p[0] == 0 && p[1] == 0 && (currX != startX || currY != startY)) {
|
||||
// 检查路径有效性,使用 -1,-1 作为无效值判断
|
||||
if (p[0] == -1 && p[1] == -1 && (currX != startX || currY != startY)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -403,32 +407,13 @@ public class PathFinder {
|
||||
* - 方向变化点(水平转垂直 / 垂直转水平)
|
||||
*
|
||||
* @param path 路径坐标列表(逻辑坐标)
|
||||
* @param grid 网格数据
|
||||
* @return 拐点坐标列表(逻辑坐标)
|
||||
*/
|
||||
public static List<int[]> extractInflectionPoints2(List<int[]> path, int[][] grid) {
|
||||
public static List<int[]> extractInflectionPoints2(List<int[]> path) {
|
||||
List<int[]> inflectionPoints = new ArrayList<>();
|
||||
|
||||
// 记录类型转换点和方向变化点
|
||||
Set<String> seen = new HashSet<>();
|
||||
|
||||
// 检测类型转换点(1 ↔ 2)
|
||||
/*for (int i = 0; i < path.size() - 1; i++) {
|
||||
int[] current = path.get(i);
|
||||
int[] next = path.get(i + 1);
|
||||
int currentValue = grid[current[0]][current[1]];
|
||||
int nextValue = grid[next[0]][next[1]];
|
||||
|
||||
if ((currentValue == 1 && nextValue == 2) || (currentValue == 2 && nextValue == 1)) {
|
||||
int[] point = currentValue == 2 ? current : next;
|
||||
String key = point[0] + "," + point[1];
|
||||
if (!seen.contains(key)) {
|
||||
seen.add(key);
|
||||
inflectionPoints.add(point);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
// 检测方向变化点(连续三点的方向变化)
|
||||
for (int i = 1; i < path.size() - 1; i++) {
|
||||
int[] prev = path.get(i - 1);
|
||||
@@ -448,9 +433,7 @@ public class PathFinder {
|
||||
}
|
||||
|
||||
// 排序后返回(可选)
|
||||
return inflectionPoints; /*.stream()
|
||||
.sorted(Comparator.comparingInt(a -> a[0] * 1000 + a[1]))
|
||||
.collect(Collectors.toList());*/
|
||||
return inflectionPoints;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -5,7 +5,6 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import com.ruoyi.bas.port.domain.WcsPort;
|
||||
import com.ruoyi.bas.port.service.IWcsPortService;
|
||||
import com.ruoyi.bas.srgvmap.domain.WcsSrgvMap;
|
||||
import com.ruoyi.bas.srgvmap.service.IWcsSrgvMapService;
|
||||
@@ -75,17 +74,14 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
|
||||
if (ObjUtil.isNotNull(PlcSrgvRead.deviceSrgvMap.get(code))) {
|
||||
|
||||
DeviceSrgv deviceSrgv = PlcSrgvRead.deviceSrgvMap.get(code);
|
||||
//循环所有楼层
|
||||
for (int i = 1; i <= 8; i++) {
|
||||
sRgvTask(deviceSrgv, i);
|
||||
}
|
||||
sRgvTask(deviceSrgv);
|
||||
|
||||
createCarInQueue();
|
||||
|
||||
createCarOutQueue();
|
||||
|
||||
} else {
|
||||
log.error("堆垛机设备为空");
|
||||
log.error("小车设备为空");
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
@@ -107,15 +103,15 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
|
||||
/**
|
||||
* 四向小车任务处理
|
||||
*/
|
||||
private void sRgvTask(DeviceSrgv deviceSrgv, int floor) {
|
||||
private void sRgvTask(DeviceSrgv deviceSrgv) {
|
||||
//处理队列下发
|
||||
resQueue(deviceSrgv, floor);
|
||||
resQueue(deviceSrgv);
|
||||
|
||||
//小车完成队列
|
||||
completeCarTask(deviceSrgv, floor);
|
||||
completeCarTask(deviceSrgv);
|
||||
|
||||
//小车发送任务
|
||||
sendTask(deviceSrgv, floor);
|
||||
sendTask(deviceSrgv);
|
||||
|
||||
}
|
||||
|
||||
@@ -213,10 +209,10 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
|
||||
/**
|
||||
* 小车发送任务
|
||||
*/
|
||||
private void sendTask(DeviceSrgv deviceSrgv, int floor) {
|
||||
private void sendTask(DeviceSrgv deviceSrgv) {
|
||||
WcsSrgvQueue param = new WcsSrgvQueue();
|
||||
param.setIssued("0");
|
||||
param.setTheFloor(Convert.toStr(floor));
|
||||
param.setAgvId(deviceSrgv.getDeviceId().toString());
|
||||
List<WcsSrgvQueue> wcsSrgvQueues = wcsSagvQueueMapper.selectWcsSrgvQueueList(param);
|
||||
if (CollUtil.isEmpty(wcsSrgvQueues)) {
|
||||
return;
|
||||
@@ -232,10 +228,10 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
|
||||
//判断小车是否在起始点
|
||||
if (currSite.equals(startSite)) {
|
||||
//小车在起始点
|
||||
sendMainTask(deviceSrgv, wcsSrgvQueue, currSite, endSite, floor);
|
||||
sendMainTask(deviceSrgv, wcsSrgvQueue, currSite, endSite);
|
||||
} else {
|
||||
//小车不在起始点
|
||||
sendPointToPointTask(deviceSrgv, wcsSrgvQueue, currSite, startSite, floor);
|
||||
sendPointToPointTask(deviceSrgv, wcsSrgvQueue, currSite, startSite);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -246,51 +242,58 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
|
||||
/**
|
||||
* 小车发送点对点任务
|
||||
*/
|
||||
private void sendPointToPointTask(DeviceSrgv deviceSrgv, WcsSrgvQueue wcsSrgvQueue, String startSite, String endSite, int floor) {
|
||||
private boolean sendPointToPointTask(DeviceSrgv deviceSrgv, WcsSrgvQueue wcsSrgvQueue, String startSite, String endSite) {
|
||||
Integer floor = deviceSrgv.getCurrFloor();
|
||||
//获取当前地图
|
||||
Map<String, int[]> arrByRoadSite = roadCacheService.getArrByRoadSite(floor);
|
||||
Map<String, WcsSrgvMap> arrByRoadSite = roadCacheService.getArrByRoadSite(floor);
|
||||
|
||||
//处理地图
|
||||
int[][] emptyMap = roadCacheService.handleMap(arrByRoadSite, deviceSrgv);
|
||||
|
||||
//获取空载地图
|
||||
int[][] emptyMap = roadCacheService.findEmptyMap(floor, arrByRoadSite.get(startSite)[0], arrByRoadSite.get(startSite)[1], arrByRoadSite.get(endSite)[0], arrByRoadSite.get(endSite)[1], deviceSrgv);
|
||||
//计算最短路径
|
||||
List<int[]> shortestPath = PathFinder.findShortestPath(emptyMap, arrByRoadSite.get(startSite)[0], arrByRoadSite.get(startSite)[1], arrByRoadSite.get(endSite)[0], arrByRoadSite.get(endSite)[1]);
|
||||
List<int[]> shortestPath = PathFinder.findShortestPath(emptyMap, arrByRoadSite.get(startSite).getX(), arrByRoadSite.get(startSite).getY(), arrByRoadSite.get(endSite).getX(), arrByRoadSite.get(endSite).getY());
|
||||
|
||||
//判断是否能规划出最短路径
|
||||
if (shortestPath == null || shortestPath.isEmpty()) {
|
||||
return;
|
||||
log.error("无最短路径 taskNo:{}", wcsSrgvQueue.getTaskNo());
|
||||
return false;
|
||||
}
|
||||
|
||||
//获取拐点路径
|
||||
List<int[]> trun = PathFinder.extractInflectionPoints2(shortestPath, emptyMap);
|
||||
List<int[]> trun = PathFinder.extractInflectionPoints2(shortestPath);
|
||||
|
||||
// 路径点拼接
|
||||
StringBuilder pathBuilder = new StringBuilder();
|
||||
Map<String, String> roadSiteByArr = roadCacheService.getRoadSiteByArr(floor);
|
||||
for (int[] point : shortestPath) {
|
||||
String site = roadSiteByArr.get(point[0] + "," + point[1]);
|
||||
if (!"000".equals(site)) {
|
||||
if (!shortestPath.isEmpty()) {
|
||||
for (int[] ints : shortestPath) {
|
||||
WcsSrgvMap roadSiteByArr = roadCacheService.selectRoadSiteByArr(ints[0], ints[1], floor);
|
||||
if (roadSiteByArr == null) {
|
||||
log.error("无此站点 x y z :{},{},{}", ints[0], ints[1], floor);
|
||||
throw new RuntimeException("点位信息错误");
|
||||
}
|
||||
String site = roadSiteByArr.getSiteId();
|
||||
pathBuilder.append(site).append(",");
|
||||
}
|
||||
|
||||
}
|
||||
if (pathBuilder.length() > 0) {
|
||||
pathBuilder.setLength(pathBuilder.length() - 1); // 移除最后一个逗号
|
||||
}
|
||||
|
||||
// 拐点拼接
|
||||
StringBuilder inflectionBuilder = new StringBuilder();
|
||||
StringBuilder turnBuilder = new StringBuilder();
|
||||
if (!trun.isEmpty()) {
|
||||
for (int[] ints : trun) {
|
||||
String site = roadSiteByArr.get(ints[0] + "," + ints[1]);//获取站点
|
||||
inflectionBuilder.append(site).append(",");
|
||||
WcsSrgvMap roadSiteByArr = roadCacheService.selectRoadSiteByArr(ints[0], ints[1], floor);
|
||||
if (roadSiteByArr == null) {
|
||||
log.error("无此站点 x y z :{},{},{}", ints[0], ints[1], floor);
|
||||
throw new RuntimeException("点位信息错误");
|
||||
}
|
||||
String site = roadSiteByArr.getSiteId();
|
||||
turnBuilder.append(site).append(",");
|
||||
}
|
||||
if (inflectionBuilder.length() > 0) {
|
||||
inflectionBuilder.setLength(inflectionBuilder.length() - 1);
|
||||
if (turnBuilder.length() > 0) {
|
||||
turnBuilder.setLength(turnBuilder.length() - 1);
|
||||
}
|
||||
// 当trun长度小于6时,后面用0拼接
|
||||
if (trun.size() < 6) {
|
||||
for (int i = trun.size(); i < 6; i++) {
|
||||
inflectionBuilder.append(",0");
|
||||
turnBuilder.append(",0");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -299,7 +302,7 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
|
||||
if (!trun.isEmpty()) {
|
||||
SendData2 path = new SendData2();
|
||||
path.setAddress("4000");//地址
|
||||
path.setData(startSite + "," + endSite + "," + inflectionBuilder.toString());
|
||||
path.setData(startSite + "," + endSite + "," + turnBuilder);
|
||||
path.setType(2);
|
||||
sendDataList.add(path);
|
||||
} else {
|
||||
@@ -335,23 +338,32 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
|
||||
|
||||
//下发数据
|
||||
boolean b = sendCarTask(sendDataList, deviceSrgv);
|
||||
|
||||
if (b) {
|
||||
wcsSrgvQueue.setPathInfo(pathBuilder.toString());
|
||||
wcsSrgvQueue.setTrunPath(turnBuilder.toString());
|
||||
wcsSagvQueueMapper.updateWcsSrgvQueue(wcsSrgvQueue);
|
||||
return true;
|
||||
} else {
|
||||
log.error("小车下发失败 taskNo:{}", wcsSrgvQueue.getTaskNo());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 小车发送点对点主任务
|
||||
*/
|
||||
private void sendMainTask(DeviceSrgv deviceSrgv, WcsSrgvQueue wcsSrgvQueue, String currSite, String endSite, int floor) {
|
||||
String taskType = wcsSrgvQueue.getTaskType();
|
||||
private void sendMainTask(DeviceSrgv deviceSrgv, WcsSrgvQueue wcsSrgvQueue, String currSite, String endSite) {
|
||||
String taskType = wcsSrgvQueue.getDefault02();
|
||||
boolean sendFlag = false;
|
||||
switch (taskType) {
|
||||
case "1":
|
||||
case "4":
|
||||
// 空车任务(充电、换层、手动点到点、除尘等)
|
||||
sendFlag = sendEmptyCarTask(deviceSrgv, wcsSrgvQueue, currSite, endSite, floor);
|
||||
sendFlag = sendPointToPointTask(deviceSrgv, wcsSrgvQueue, currSite, endSite);
|
||||
break;
|
||||
case "1":
|
||||
case "2":
|
||||
// 载货任务(出库、入库、移库等)
|
||||
sendFlag = sendFullCarTask(deviceSrgv, wcsSrgvQueue, currSite, endSite, floor);
|
||||
sendFlag = sendPointToPointTask(deviceSrgv, wcsSrgvQueue, currSite, endSite);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -360,253 +372,6 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 小车发送载货任务
|
||||
*/
|
||||
private boolean sendFullCarTask(DeviceSrgv deviceSrgv, WcsSrgvQueue wcsSrgvQueue, String startSite, String endSite, int floor) {
|
||||
|
||||
//0 待机 1去向原站 2 到达原站托盘定位 3 上升至中位顶取货物 4生成去向目标站路径
|
||||
// 5去向目标站 6下降至低位放货,工作完成,将阶段设置为0. 20:执行点到点命令运行中 21:到达点到目标位置 22:小车充电中
|
||||
int workPhase = deviceSrgv.getWorkPhase();
|
||||
int status = deviceSrgv.getStatus();// 0:未知 1:待机 2:运行 3:报警
|
||||
int workMode = deviceSrgv.getWorkMode();
|
||||
|
||||
|
||||
//取货规划路径和下发,在货底下,并且待机,任务未被下发
|
||||
if ((workPhase == 0) && status == 1 && workMode == 5) {
|
||||
//查找载货路径
|
||||
Map<String, int[]> arrByRoadSite = roadCacheService.getArrByRoadSite(floor);
|
||||
//获取空载地图(剔除不包含自己的障碍)(250919,排除其他站点)
|
||||
|
||||
String noTar0 = null;
|
||||
String noTar1 = null;
|
||||
|
||||
if ("3".equals(wcsSrgvQueue.getCargo())) {
|
||||
noTar0 = getNoTar(startSite);
|
||||
noTar1 = getNoTar(endSite);
|
||||
} else if ("1".equals(wcsSrgvQueue.getCargo())) {
|
||||
noTar1 = getNoTar(endSite);
|
||||
} else if ("2".equals(wcsSrgvQueue.getCargo())) {
|
||||
noTar0 = getNoTar(startSite);
|
||||
}
|
||||
|
||||
|
||||
int[][] fullMap = null;
|
||||
if (noTar0 == null && noTar1 == null) {
|
||||
fullMap = roadCacheService.findFullMap(floor, arrByRoadSite.get(startSite)[0], arrByRoadSite.get(startSite)[1], arrByRoadSite.get(endSite)[0], arrByRoadSite.get(endSite)[1], deviceSrgv);
|
||||
} else {
|
||||
List<String> strings = new ArrayList<>();//排除站点
|
||||
if (noTar0 != null) {
|
||||
strings.add(noTar0);
|
||||
}
|
||||
if (noTar1 != null) {
|
||||
strings.add(noTar1);
|
||||
}
|
||||
|
||||
fullMap = roadCacheService.findFullMap(floor, arrByRoadSite.get(startSite)[0], arrByRoadSite.get(startSite)[1], arrByRoadSite.get(endSite)[0], arrByRoadSite.get(endSite)[1], deviceSrgv, strings);
|
||||
}
|
||||
|
||||
//计算最短路径
|
||||
List<int[]> shortestPath = PathFinder.findShortestPathFrom2To2Or1(fullMap, arrByRoadSite.get(startSite)[0], arrByRoadSite.get(startSite)[1], arrByRoadSite.get(endSite)[0], arrByRoadSite.get(endSite)[1]);
|
||||
//判断是否能规划出最短路径
|
||||
if (shortestPath == null || shortestPath.isEmpty()) {
|
||||
//空车从当前点去目标点没有可以路径,校验是否是同层其他车影响,要上次其他车避让任务
|
||||
return false;
|
||||
}
|
||||
|
||||
//获取拐点路径
|
||||
List<int[]> trun = PathFinder.extractInflectionPoints2(shortestPath, fullMap);
|
||||
|
||||
// 路径点拼接
|
||||
StringBuilder pathBuilder = new StringBuilder();
|
||||
Map<String, String> roadSiteByArr = roadCacheService.getRoadSiteByArr(Integer.parseInt(wcsSrgvQueue.getTheFloor()));
|
||||
for (int[] point : shortestPath) {
|
||||
String site = roadSiteByArr.get(point[0] + "," + point[1]);
|
||||
if (!"000".equals(site)) {
|
||||
pathBuilder.append(site).append(",");
|
||||
}
|
||||
}
|
||||
if (pathBuilder.length() > 0) {
|
||||
pathBuilder.setLength(pathBuilder.length() - 1); // 移除最后一个逗号
|
||||
}
|
||||
|
||||
// 拐点拼接
|
||||
StringBuilder inflectionBuilder = new StringBuilder();
|
||||
if (!trun.isEmpty()) {
|
||||
for (int[] ints : trun) {
|
||||
String site = roadSiteByArr.get(ints[0] + "," + ints[1]);//获取站点
|
||||
inflectionBuilder.append(site).append(",");
|
||||
}
|
||||
if (inflectionBuilder.length() > 0) {
|
||||
inflectionBuilder.setLength(inflectionBuilder.length() - 1);
|
||||
}
|
||||
// 当trun长度小于6时,后面用0拼接
|
||||
if (trun.size() < 6) {
|
||||
for (int i = trun.size(); i < 6; i++) {
|
||||
inflectionBuilder.append(",0");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<SendData2> sendDataList = new ArrayList<>();
|
||||
|
||||
|
||||
if (!trun.isEmpty()) {
|
||||
SendData2 path = new SendData2();
|
||||
path.setAddress("4000");//地址
|
||||
path.setData(startSite + "," + endSite + "," + inflectionBuilder);
|
||||
path.setType(2);
|
||||
sendDataList.add(path);
|
||||
} else {
|
||||
SendData2 path = new SendData2();
|
||||
path.setAddress("4000");//地址
|
||||
path.setData(startSite + "," + endSite);
|
||||
path.setType(2);
|
||||
sendDataList.add(path);
|
||||
}
|
||||
|
||||
|
||||
String siteId = wcsSrgvQueue.getTaskNo();//+ "," + startSite + "," + endSite;
|
||||
SendData2 site = new SendData2();
|
||||
site.setAddress("4400");
|
||||
site.setData(siteId);
|
||||
site.setType(2);
|
||||
sendDataList.add(site);
|
||||
//下发类型
|
||||
SendData2 taskType = new SendData2();
|
||||
taskType.setAddress("2200");
|
||||
taskType.setData(wcsSrgvQueue.getTaskType());
|
||||
taskType.setType(1);
|
||||
sendDataList.add(taskType);
|
||||
//下发标志转换
|
||||
SendData2 flag = new SendData2();
|
||||
flag.setAddress("2202");
|
||||
flag.setData("1");
|
||||
flag.setType(1);
|
||||
sendDataList.add(flag);
|
||||
|
||||
//boolean write = true;
|
||||
return sendCarTask(sendDataList, deviceSrgv);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* 获取特俗区域的母通道排除站点
|
||||
*
|
||||
* */
|
||||
private String getNoTar(String site) {
|
||||
|
||||
String s = site.substring(site.length() - 4);
|
||||
|
||||
String p = site.substring(0, 2);
|
||||
int pi = Integer.parseInt(p);
|
||||
|
||||
String l = site.substring(2, 4);
|
||||
int li = Integer.parseInt(l);//排
|
||||
|
||||
String tarSite = null;
|
||||
if (pi > 4 && pi < 15 && li > 30) {
|
||||
tarSite = "16" + s;
|
||||
} else {
|
||||
|
||||
}
|
||||
return tarSite;
|
||||
}
|
||||
|
||||
/**
|
||||
* 小车发送空车任务
|
||||
*/
|
||||
private boolean sendEmptyCarTask(DeviceSrgv deviceSrgv, WcsSrgvQueue wcsSrgvQueue, String startSite, String endSite, int floor) {
|
||||
//获取当前地图
|
||||
Map<String, int[]> arrByRoadSite = roadCacheService.getArrByRoadSite(floor);
|
||||
//获取空载地图
|
||||
int[][] emptyMap = roadCacheService.findEmptyMap(floor, arrByRoadSite.get(startSite)[0], arrByRoadSite.get(startSite)[1], arrByRoadSite.get(endSite)[0], arrByRoadSite.get(endSite)[1], deviceSrgv);
|
||||
//计算最短路径
|
||||
List<int[]> shortestPath = PathFinder.findShortestPath(emptyMap, arrByRoadSite.get(startSite)[0], arrByRoadSite.get(startSite)[1], arrByRoadSite.get(endSite)[0], arrByRoadSite.get(endSite)[1]);
|
||||
|
||||
//判断是否能规划出最短路径
|
||||
if (shortestPath == null || shortestPath.isEmpty()) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//获取拐点路径
|
||||
List<int[]> trun = PathFinder.extractInflectionPoints2(shortestPath, emptyMap);
|
||||
|
||||
// 路径点拼接
|
||||
StringBuilder pathBuilder = new StringBuilder();
|
||||
Map<String, String> roadSiteByArr = roadCacheService.getRoadSiteByArr(floor);
|
||||
for (int[] point : shortestPath) {
|
||||
String site = roadSiteByArr.get(point[0] + "," + point[1]);
|
||||
if (!"000".equals(site)) {
|
||||
pathBuilder.append(site).append(",");
|
||||
}
|
||||
|
||||
}
|
||||
if (pathBuilder.length() > 0) {
|
||||
pathBuilder.setLength(pathBuilder.length() - 1); // 移除最后一个逗号
|
||||
}
|
||||
|
||||
// 拐点拼接
|
||||
StringBuilder inflectionBuilder = new StringBuilder();
|
||||
if (!trun.isEmpty()) {
|
||||
for (int[] ints : trun) {
|
||||
String site = roadSiteByArr.get(ints[0] + "," + ints[1]);//获取站点
|
||||
inflectionBuilder.append(site).append(",");
|
||||
}
|
||||
if (inflectionBuilder.length() > 0) {
|
||||
inflectionBuilder.setLength(inflectionBuilder.length() - 1);
|
||||
}
|
||||
// 当trun长度小于6时,后面用0拼接
|
||||
if (trun.size() < 6) {
|
||||
for (int i = trun.size(); i < 6; i++) {
|
||||
inflectionBuilder.append(",0");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<SendData2> sendDataList = new ArrayList<>();
|
||||
if (!trun.isEmpty()) {
|
||||
SendData2 path = new SendData2();
|
||||
path.setAddress("4000");//地址
|
||||
path.setData(startSite + "," + endSite + "," + inflectionBuilder.toString());
|
||||
path.setType(2);
|
||||
sendDataList.add(path);
|
||||
} else {
|
||||
SendData2 path = new SendData2();
|
||||
path.setAddress("4000");//地址
|
||||
path.setData(startSite + "," + endSite);
|
||||
path.setType(2);
|
||||
sendDataList.add(path);
|
||||
}
|
||||
|
||||
|
||||
//任务号、原、目标数据转换
|
||||
String siteId = wcsSrgvQueue.getTaskNo();//+ "," + startSite + "," + endSite;
|
||||
SendData2 site = new SendData2();
|
||||
site.setAddress("4400");
|
||||
site.setData(siteId);
|
||||
site.setType(2);
|
||||
sendDataList.add(site);
|
||||
|
||||
//任务类型转换
|
||||
SendData2 taskType = new SendData2();
|
||||
taskType.setAddress("2200");
|
||||
taskType.setData(wcsSrgvQueue.getDefault02());
|
||||
taskType.setType(1);
|
||||
sendDataList.add(taskType);
|
||||
|
||||
//下发标志转换
|
||||
SendData2 flag = new SendData2();
|
||||
flag.setAddress("2202");
|
||||
flag.setData("1");
|
||||
flag.setType(1);
|
||||
sendDataList.add(flag);
|
||||
|
||||
return sendCarTask(sendDataList, deviceSrgv);
|
||||
}
|
||||
|
||||
/**
|
||||
* 小车发送任务
|
||||
*/
|
||||
@@ -667,37 +432,10 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理未指定目的地的任务
|
||||
*/
|
||||
private void handleUnspecifiedDestination(WcsSrgvQueue wcsSrgvQueue, String startSite, int floor, DeviceSrgv deviceSrgv) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断站点是否是同一层
|
||||
*
|
||||
* @param startSite
|
||||
* @param endSite
|
||||
* @return
|
||||
*/
|
||||
private boolean isSameFloor(String startSite, String endSite) {
|
||||
// 参数校验
|
||||
if (startSite == null || endSite == null || startSite.length() < 2 || endSite.length() < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 正确提取起始和结束站点的楼层信息
|
||||
String startFloor = startSite.substring(startSite.length() - 2);
|
||||
String endFloor = endSite.substring(endSite.length() - 2);
|
||||
|
||||
// 比较是否在同一层
|
||||
return Objects.equals(startFloor, endFloor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 小车完成队列
|
||||
*/
|
||||
private void completeCarTask(DeviceSrgv deviceSrgv, int floor) {
|
||||
private void completeCarTask(DeviceSrgv deviceSrgv) {
|
||||
//联机自动
|
||||
if (deviceSrgv.getWorkMode() == 4) {
|
||||
//22到达充电位置 23到达换层目标
|
||||
@@ -715,7 +453,7 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
|
||||
* 1、不处理终点是提升机站点的四向车
|
||||
* 2、处理终点不是提升机站点的
|
||||
* */
|
||||
boolean taskFinishFlag = finishTaskByQueue(deviceSrgv.getCurrSite(), wcsSrgvQueue, floor);
|
||||
boolean taskFinishFlag = finishTaskByQueue(deviceSrgv.getCurrSite(), wcsSrgvQueue);
|
||||
|
||||
if (taskFinishFlag) {
|
||||
String spare2 = deviceSrgv.getSpare2();
|
||||
@@ -741,10 +479,9 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
|
||||
*
|
||||
* @param currSite
|
||||
* @param wcsSrgvQueue
|
||||
* @param floor
|
||||
* @return
|
||||
*/
|
||||
private boolean finishTaskByQueue(String currSite, WcsSrgvQueue wcsSrgvQueue, int floor) {
|
||||
private boolean finishTaskByQueue(String currSite, WcsSrgvQueue wcsSrgvQueue) {
|
||||
|
||||
|
||||
//当前在放货站点
|
||||
@@ -825,14 +562,13 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
|
||||
*
|
||||
* @param deviceSrgv
|
||||
*/
|
||||
private void resQueue(DeviceSrgv deviceSrgv, int floor) {
|
||||
private void resQueue(DeviceSrgv deviceSrgv) {
|
||||
int taskNo = deviceSrgv.getTaskNo();
|
||||
String currSite = deviceSrgv.getCurrSite();
|
||||
Integer deviceId = deviceSrgv.getDeviceId();
|
||||
|
||||
if (taskNo > 999 && !"000000".equals(currSite)) {
|
||||
WcsSrgvQueue param = new WcsSrgvQueue();
|
||||
param.setTheFloor(Convert.toStr(floor));
|
||||
param.setTaskNo(Convert.toStr(taskNo));
|
||||
param.setIssued("0");
|
||||
param.setAgvId(String.valueOf(deviceId));
|
||||
|
||||
Reference in New Issue
Block a user