| | |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.zy.acs.common.utils.GsonUtils; |
| | | import com.zy.acs.common.utils.RedisSupport; |
| | | import com.zy.acs.framework.common.Cools; |
| | | import com.zy.acs.framework.common.SnowflakeIdWorker; |
| | | import com.zy.acs.framework.exception.CoolException; |
| | | import com.zy.acs.manager.common.utils.MapDataUtils; |
| | | import com.zy.acs.manager.core.constant.MapDataConstant; |
| | | import com.zy.acs.manager.core.domain.BlockVehicleDto; |
| | | import com.zy.acs.manager.core.domain.TaskPosDto; |
| | | import com.zy.acs.manager.core.domain.type.BlockSeverityType; |
| | | import com.zy.acs.manager.core.service.astart.MapDataDispatcher; |
| | | import com.zy.acs.manager.core.service.astart.NavigateNode; |
| | | import com.zy.acs.manager.core.service.astart.RetreatNavigateNode; |
| | | import com.zy.acs.manager.core.service.astart.WaveNodeType; |
| | | import com.zy.acs.manager.manager.entity.*; |
| | |
| | | @Component |
| | | public class TrafficService { |
| | | |
| | | public static final Integer MIN_SLICE_PATH_LENGTH = 3; |
| | | |
| | | public static final Integer MAX_JAM_TIMEOUT = 5 * 1000; |
| | | |
| | | private final RedisSupport redis = RedisSupport.defaultRedisSupport; |
| | | |
| | | @Autowired |
| | | private AgvService agvService; |
| | | @Autowired |
| | |
| | | @Autowired |
| | | private SnowflakeIdWorker snowflakeIdWorker; |
| | | @Autowired |
| | | private ActionService actionService; |
| | | private AgvModelService agvModelService; |
| | | @Autowired |
| | | private RetreatNavigateService retreatNavigateService; |
| | | @Autowired |
| | |
| | | String agvNo = agv.getUuid(); |
| | | Date now = new Date(); |
| | | Jam jam = jamService.getJam(agv.getId(), startCode.getId(), segment.getId()); |
| | | BlockSeverityType blockSeverity = BlockSeverityType.query(null == jam ? null : jam.getDuration()); |
| | | // judge avoid of jam |
| | | List<Jam> unfinishedOriginJamByCurrAgv = jamService.getUnfinishedOriginJamByAvo(agv.getId(), startCode.getId(), segment.getId()); |
| | | List<String> blackPath = this.getBlackPathList(unfinishedOriginJamByCurrAgv); |
| | |
| | | pathList = lockPathList; |
| | | } else { |
| | | |
| | | // preview path |
| | | List<String> draftPath = new ArrayList<>(unlockPathList); |
| | | if (blockSeverity.equals(BlockSeverityType.SEVERE)) { |
| | | unlockPathList.remove(endCode.getData()); |
| | | blackPath.addAll(unlockPathList); |
| | | List<String> newUnlockPathList = mapService.checkoutPath(agvNo, startCode, endCode, false, blackPath, segment); |
| | | if (!Cools.isEmpty(newUnlockPathList)) { |
| | | draftPath = newUnlockPathList; |
| | | } |
| | | } |
| | | // 可走行路径集合计算 |
| | | List<BlockVehicleDto> blockVehicleList = this.slicePathAndReturnBlockVehicleList(lev, unlockPathList, agvNo, pathList); // jamAgvNo may was wave |
| | | List<BlockVehicleDto> blockVehicleList = this.slicePathAndReturnBlockVehicleList(lev, draftPath, agvNo, pathList); // jamAgvNo may was wave |
| | | |
| | | if (!Cools.isEmpty(pathList)) { |
| | | |
| | |
| | | assert !Cools.isEmpty(blockVehicleList); |
| | | |
| | | boolean hasUnavoidableBlocks = blockVehicleList.stream().anyMatch(blockVehicleDto -> !blockVehicleDto.isAvoidable()); |
| | | if (hasUnavoidableBlocks && pathList.size() <= MIN_SLICE_PATH_LENGTH) { |
| | | if (hasUnavoidableBlocks && pathList.size() <= MapDataConstant.MIN_SLICE_PATH_LENGTH) { |
| | | log.info("AGV[{}] waiting in place, because the path list is too short...", agvNo); |
| | | pathList.clear(); |
| | | } |
| | |
| | | Integer maxJamTimeoutFactor = null; |
| | | |
| | | // persist jam data |
| | | ArrayList<String> jamPath = new ArrayList<>(unlockPathList); |
| | | jam = this.createOrUpdateJam(agv, startCode, segment, jam, jamPath); |
| | | jam = this.createOrUpdateJam(agv, startCode, segment, jam, draftPath); |
| | | |
| | | // ? has unAvoidable block vehicles |
| | | if (blockVehicleList.stream().anyMatch(blockVehicleDto -> !blockVehicleDto.isAvoidable())) { |
| | |
| | | if (!Cools.isEmpty(jam.getAvoAgv()) |
| | | && BlockVehicleDto.customContain(blockVehicleList, agvService.getById(jam.getAvoAgv()).getUuid())) { |
| | | |
| | | maxJamTimeoutFactor = 10; |
| | | maxJamTimeoutFactor = 5; |
| | | |
| | | } else { |
| | | |
| | | // select optimal block vehicle |
| | | // String blockAgvNo = blockVehicleList.stream() |
| | | // .filter(BlockVehicleDto::isAvoidable) |
| | | // .map(BlockVehicleDto::getVehicle) |
| | | // .findFirst().orElse(null); |
| | | String blockAgvNo = this.checkoutBestSolutionOfBlocks(blockVehicleList); |
| | | if (Cools.isEmpty(blockAgvNo)) { |
| | | |
| | |
| | | } |
| | | |
| | | // notify block vehicle to avoid |
| | | if (this.notifyVehicleAvoid(blockAgvNo, blockAgvCode, jamPath, agvNo, jam)) { |
| | | if (this.notifyVehicleAvoid(blockAgvNo, blockAgvCode, draftPath, agvNo, jam)) { |
| | | if (jam.getCycleAvo() == 1) { |
| | | jam.setCycleCode(endCode.getId()); |
| | | } |
| | |
| | | |
| | | // handle jam timeout |
| | | if (null != maxJamTimeoutFactor) { |
| | | if (System.currentTimeMillis() - jam.getStartTime().getTime() > MAX_JAM_TIMEOUT * maxJamTimeoutFactor) { |
| | | if (System.currentTimeMillis() - jam.getStartTime().getTime() > MapDataConstant.MAX_JAM_TIMEOUT * maxJamTimeoutFactor) { |
| | | |
| | | if (!Cools.isEmpty(lockPathList)) { |
| | | |
| | |
| | | |
| | | private List<String> getBlackPathList(List<Jam> unfinishedOriginJamByCurrAgv) { |
| | | List<String> blackPathList = new ArrayList<>(); |
| | | Integer lev = MapDataDispatcher.MAP_DEFAULT_LEV; |
| | | if (!Cools.isEmpty(unfinishedOriginJamByCurrAgv)) { |
| | | for (Jam jam : unfinishedOriginJamByCurrAgv) { |
| | | if (!Cools.isEmpty(jam.getJamPath())) { |
| | | |
| | | List<String> list = GsonUtils.fromJsonToList(jam.getJamPath(), String.class); |
| | | |
| | | Agv jamAgv = agvService.getById(jam.getJamAgv()); |
| | | List<String> jamDynamicNodes = mapDataDispatcher.queryCodeListFromDynamicNode(lev, jamAgv.getUuid()); |
| | | // jamDynamicNodes has sorted |
| | | String firstCodeNode = jamDynamicNodes.stream().findFirst().orElse(null); |
| | | |
| | | if (!Cools.isEmpty(firstCodeNode)) { |
| | | int idx = list.indexOf(firstCodeNode); |
| | | if (idx != -1) { |
| | | list = new ArrayList<>(list.subList(idx, list.size())); |
| | | } |
| | | |
| | | // the wave of first node |
| | | Double avoidDistance = MapDataUtils.getVehicleWaveSafeDistance( |
| | | agvModelService.getById(jamAgv.getAgvModel()).getDiameter(), |
| | | MapDataConstant.MAX_DISTANCE_BETWEEN_ADJACENT_AGV_FACTOR |
| | | ); |
| | | List<String> waveCodeList = mapService.getWaveScopeByCode(lev, firstCodeNode, avoidDistance) |
| | | .stream().map(NavigateNode::getCodeData).distinct().collect(Collectors.toList()); |
| | | list.addAll(waveCodeList); |
| | | } |
| | | |
| | | blackPathList.addAll(list); |
| | | } |
| | | } |