zhang
12 小时以前 70930071a49190f414c8d8bc9c9e9795a4096739
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/TrafficService.java
@@ -9,6 +9,7 @@
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.PathDto;
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;
@@ -26,6 +27,7 @@
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import com.zy.acs.common.utils.News;
import java.util.ArrayList;
import java.util.Arrays;
@@ -71,6 +73,10 @@
    private JamService jamService;
    @Autowired
    private AvoidWaveCalculator avoidWaveCalculator;
    @Autowired
    private TaskService taskService;
    @Autowired
    private FuncStaService funcStaService;
    @Transactional
    public synchronized void trigger(Segment segment) {
@@ -92,13 +98,83 @@
            Travel travel = travelService.getById(segment.getTravelId());
            Agv agv = agvService.getById(travel.getAgvId());
            AgvDetail agvDetail = agvDetailService.selectByAgvId(travel.getAgvId());
            long endNode = segment.getEndNode();
            // valid ----------------------------------------------------
            if (!agvService.judgeEnable(agv.getId())) {
                return;
            }
            // resolve deadlock
//            if (configService.getVal("unlockSwitch", Boolean.class)) {
//
//                boolean preSegIsStandbyDeadLock = false;
//                Segment previousSeg = segmentService.getPreviousStepOfFinish(segment.getTravelId(), segment.getSerial(), MapDataConstant.RESOLVE_DEADLOCK);
//                preSegIsStandbyDeadLock = previousSeg != null;
//                if (preSegIsStandbyDeadLock && !jamService.isAvoidSeg(segment.getId())) {
//                    if (0 < segmentService.count(new LambdaQueryWrapper<Segment>()
//                            .in(Segment::getState, SegmentStateType.WAITING.toString(), SegmentStateType.RUNNING.toString())
//                            .eq(Segment::getMemo, MapDataConstant.RESOLVE_DEADLOCK))) {
//                        return;
//                    }
//                }
//
//                Jam jam = jamService.getJam(agv.getId(), agvDetail.getRecentCode(), segment.getId());
//                if (!preSegIsStandbyDeadLock && (null != jam && null != jam.getDuration() && jam.getDuration() > (BlockSeverityType.SEVERE.duration - MapDataConstant.MAX_JAM_TIMEOUT)
//                        || DateUtils.diffToMilliseconds(segment.getUpdateTime(), now)  > (BlockSeverityType.SEVERE.duration - MapDataConstant.MAX_JAM_TIMEOUT))
//                        && (Cools.isEmpty(segment.getMemo()) || !segment.getMemo().equals(MapDataConstant.RESOLVE_DEADLOCK))) {
//
//                    Task task = taskService.getById(segment.getTaskId());
//                    if (task.getTaskSts().equals(TaskStsType.PROGRESS.val())
//                            && DateUtils.diffToMilliseconds(task.getUpdateTime(), now) > MapDataConstant.DEADLOCK_TASK_TIMEOUT) {
//
//                        Code endCode = null;
//                        List<FuncSta> idleFunStaList = funcStaService.findInIdleStatus(FuncStaType.STANDBY, segment.getAgvId());
//                        if (!Cools.isEmpty(idleFunStaList)) {
//                            idleFunStaList = idleFunStaList.stream().filter(funcSta -> {
//                                return 0 == segmentService.count(new LambdaQueryWrapper<Segment>()
//                                                .eq(Segment::getEndNode, funcSta.getCode())
//                                                .in(Segment::getState, SegmentStateType.WAITING.toString(), SegmentStateType.RUNNING.toString())
//                                                .eq(Segment::getMemo, MapDataConstant.RESOLVE_DEADLOCK)
//                                );
//                            }).collect(Collectors.toList());
//                            FuncSta funcSta = funcStaService.checkoutFurthestFunSta(agvDetailService.getCurrentCode(segment.getAgvId()).getId(), idleFunStaList);
//                            if (null != funcSta) {
//                                endCode = codeService.getCacheById(funcSta.getCode());
//                            }
//                        }
//                        if (null == endCode) {
//                            News.warn("AGV[{}] failed to search destination,there hadn't any idle funSta,TaskTypeType:{}", segment.getAgvId(), FuncStaType.STANDBY);
//                            return;
//                        }
//
//                        segment.setState(SegmentStateType.INIT.toString());
//                        segment.setUpdateTime(now);
//                        if (!segmentService.updateById(segment)) {
//                            News.error("Segment [{}] failed to update !!!", segment.getGroupId() + " - " + segment.getSerial());
//                            return;
//                        }
//
//                        // new move seg
//                        Segment insertSeg = new Segment();
//                        insertSeg.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
//                        insertSeg.setTravelId(segment.getTravelId());
//                        insertSeg.setAgvId(segment.getAgvId());
//                        insertSeg.setTaskId(segment.getTaskId());
//                        insertSeg.setSerial(segment.getSerial() - 1);
//                        insertSeg.setEndNode(endCode.getId());
//                        insertSeg.setPosType(TaskPosDto.PosType.MOVE.toString());
//                        insertSeg.setState(SegmentStateType.WAITING.toString());
//                        insertSeg.setMemo(MapDataConstant.RESOLVE_DEADLOCK);
//                        if (!segmentService.save(insertSeg)) {
//                            News.error("Segment [{}] failed to save !!!", segment.getTravelId() + " - " + segment.getSerial());
//                            return;
//                        }
//                        return;
//                    }
//                }
//            }
            if (!Cools.isEmpty(segmentService.getByAgvAndState(agv.getId(), SegmentStateType.RUNNING.toString()))) {
                return;
            }
@@ -106,7 +182,7 @@
            if (!Cools.isEmpty(waitingSegList)) {
                for (Segment waitingSeg : waitingSegList) {
                    if (!waitingSeg.getId().equals(segment.getId())) {
//                        log.error("AGV[{}] 任务异常,服务器错误!!!", agv.getUuid());
//                        News.error("AGV[{}] 任务异常,服务器错误!!!", agv.getUuid());
                        return;
                    }
                }
@@ -127,15 +203,15 @@
            //        ArrayList<List<TaskPosDto>> list = JSON.parseObject(travel.getTaskContent(), new TypeReference<ArrayList<List<TaskPosDto>>>() {});
            // * sync wave scope
            if (!avoidWaveCalculator.calcWaveScope()) {
                log.error("failed to calculate avoid wave matrix ...");
            if (!avoidWaveCalculator.calcWaveScope(agvModelService.getByAgvId(agv.getId()))) {
                News.error("failed to calculate avoid wave matrix ...");
                return;
            }
            // checkout path
            Code startCode = codeService.getCacheById(agvDetail.getRecentCode());
            Code startCode = agvDetailService.getCurrentCode(travel.getAgvId());
            Code endCode = codeService.getCacheById(endNode);
            long startTime = System.currentTimeMillis();
//            long startTime = System.currentTimeMillis();
            List<String> pathList = this.checkoutPath(agv, startCode, endCode, segment);
//            System.out.println("checkoutPath: " + (System.currentTimeMillis() - startTime));
            if (Cools.isEmpty(pathList)) {
@@ -158,7 +234,7 @@
                segment.setState(SegmentStateType.INIT.toString());
                segment.setUpdateTime(now);
                if (!segmentService.updateById(segment)) {
                    log.error("Segment [{}] failed to update !!!", segment.getGroupId() + " - " + segment.getSerial());
                    News.error("Segment [{}] failed to update !!!", segment.getGroupId() + " - " + segment.getSerial());
                }
                segmentList.clear();
@@ -173,7 +249,7 @@
                insertSeg.setPosType(TaskPosDto.PosType.MOVE.toString());
                insertSeg.setState(SegmentStateType.WAITING.toString());
                if (!segmentService.save(insertSeg)) {
                    log.error("Segment [{}] failed to save !!!", segment.getTravelId() + " - " + segment.getSerial());
                    News.error("Segment [{}] failed to save !!!", insertSeg.getTravelId() + " - " + insertSeg.getSerial());
                }
                segmentList.add(insertSeg);
@@ -190,8 +266,11 @@
                        interrupt = true;
                    } else {
                        if (nextStep.getEndNode() == endNode) {
                            segmentList.add(nextStep);
                            // remove sta action seg
                            if (!nextStep.getPosType().equals(TaskPosDto.PosType.ORI_STA.toString())
                                    && !nextStep.getPosType().equals(TaskPosDto.PosType.DEST_STA.toString())) {
                                segmentList.add(nextStep);
                            }
                        } else {
                            interrupt = true;
                        }
@@ -200,16 +279,17 @@
                }
            }
            mapService.lockPath(null, pathList, agv.getUuid());
            startTime = System.currentTimeMillis();
            mainService.generateAction(segment.getAgvId(), segmentList, pathList, now);
//            startTime = System.currentTimeMillis();
            List<PathDto> pathDtoList = mainService.generateAction(segment.getAgvId(), segmentList, pathList, now);
//            System.out.println("generateAction: " + (System.currentTimeMillis() - startTime));
            mapService.lockPath(null, pathDtoList, agv.getUuid());
        } catch (Exception e) {
            log.error("TrafficService.trigger", e);
            News.error("TrafficService.trigger", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new RuntimeException("trigger method caught an exception", e);
        }
    }
@@ -221,7 +301,7 @@
        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);
        List<String> blackPath = this.getBlackPathList(agvNo, unfinishedOriginJamByCurrAgv);
        // 结果集
        List<String> pathList = new ArrayList<>();
@@ -258,7 +338,7 @@
                    boolean hasUnavoidableBlocks = blockVehicleList.stream().anyMatch(blockVehicleDto -> !blockVehicleDto.isAvoidable());
                    if (hasUnavoidableBlocks && pathList.size() <= MapDataConstant.MIN_SLICE_PATH_LENGTH) {
                        log.info("AGV[{}] waiting in place, because the path list is too short...", agvNo);
//                        News.info("AGV[{}] waiting in place, because the path list is too short...", agvNo);
                        pathList.clear();
                    }
@@ -266,7 +346,7 @@
                            blockVehicleDto -> null != jamService.getCycleJam(agv.getId(), segment.getId(), blockVehicleDto.getVehicle())
                    );
                    if (hasCycleJam) {
                        log.info("AGV[{}] waiting in place, because has cycle jam...", agvNo);
                        News.info("AGV[{}] waiting in place, because has cycle jam...", agvNo);
                        pathList.clear();
                    }
                }
@@ -275,7 +355,7 @@
            } else {
                if (Cools.isEmpty(blockVehicleList)) {
                    log.warn("AGV[{}] can't reach to code: {}, because there is too many vehicle in the lane...", agvNo, endCode.getData());
                    News.warn("AGV[{}] can't reach to code: {}, because there is too many vehicle in the lane...", agvNo, endCode.getData());
                } else {
                    assert !Cools.isEmpty(blockVehicleList);
@@ -365,14 +445,14 @@
                                pathList = lockPathList;
                            } else {
                                log.error("{}号车辆检索[{}] ===>> [{}]路径失败,原因:{}"
                                News.error("{}号车辆检索[{}] ===>> [{}]路径失败,原因:{}"
                                        , agvNo, startCode.getData(), endCode.getData(), "路径阻塞超时");
                            }
                        } else {
                            log.warn("{}号车辆正在等待交通堵塞,阻塞车辆:【{}】"
                                    , agvNo
                                    , blockVehicleList.stream().map(BlockVehicleDto::getVehicle).collect(Collectors.toList()).toString()
                            );
//                            News.warn("{}号车辆正在等待交通堵塞,阻塞车辆:【{}】"
//                                    , agvNo
//                                    , blockVehicleList.stream().map(BlockVehicleDto::getVehicle).collect(Collectors.toList()).toString()
//                            );
                        }
                    }
@@ -405,23 +485,24 @@
                            previousJam.setState(JamStateType.DEPRECATED.toString());
                            previousJam.setUpdateTime(now);
                            if (!jamService.updateById(previousJam)) {
                                log.error("Jam[{}] failed to update!!!", previousJam.getUuid());
                                News.error("Jam[{}] failed to update!!!", previousJam.getUuid());
                            }
                        }
                    }
                } else {
                    log.error("Jam[{}] failed to update!!!", jam.getUuid());
                    News.error("Jam[{}] failed to update!!!", jam.getUuid());
                }
            }
            // deal expired jam
            for (Jam expiredJam : jamService.list(new LambdaQueryWrapper<Jam>()
                    .eq(Jam::getJamAgv, agv.getId())
                    .ne(Jam::getCycleAvo, 1)
                    .eq(Jam::getState, JamStateType.RUNNING.toString()))) {
                expiredJam.setEndTime(now);
                expiredJam.setUpdateTime(now);
                expiredJam.setState(JamStateType.DEPRECATED.toString());
                if (!jamService.updateById(expiredJam)) {
                    log.error("Jam[{}] failed to update!!!", expiredJam.getUuid());
                    News.error("Jam[{}] failed to update!!!", expiredJam.getUuid());
                }
            }
@@ -472,7 +553,7 @@
    private boolean notifyVehicleAvoid(String agvNo, String agvPosCode, List<String> avoidPathList, String sponsor, Jam jam) {
        Long agvId = agvService.getAgvId(agvNo);
        if (!Cools.isEmpty(segmentService.getByAgvAndState(agvId, SegmentStateType.RUNNING.toString()))) {
            log.warn("{}号车辆避让失败,存在进行中任务!!!", agvNo);
            News.warn("{}号车辆避让失败,存在进行中任务!!!", agvNo);
            return false;
        }
@@ -482,7 +563,7 @@
        assert avoidPathList.size() >= 2;
        RetreatNavigateNode finalNode = retreatNavigateService.execute(agvNo, startNode, avoidPathList, sponsor, jam);
        if (null == finalNode) {
            log.warn("{}号车辆避让失败,检索避让点失败!!!", agvNo);
            News.warn("{}号车辆避让失败,检索避让点失败!!!", agvNo);
            return false;
        }
@@ -493,7 +574,7 @@
        if (!Cools.isEmpty(waitingSegList)) {
            if (waitingSegList.size() > 1) {
                log.error("避让通知失败,{}号车辆存在多个等待中的Segment!!!", agvNo);
                News.error("避让通知失败,{}号车辆存在多个等待中的Segment!!!", agvNo);
                return false;
            }
            // revert
@@ -502,7 +583,7 @@
                seg.setState(SegmentStateType.INIT.toString());
                seg.setUpdateTime(now);
                if (!segmentService.updateById(seg)) {
                    log.error("Segment [{}] 更新失败 !!!", seg.getTravelId() + " - " + seg.getSerial());
                    News.error("Segment [{}] 更新失败 !!!", seg.getTravelId() + " - " + seg.getSerial());
                }
            }
            Segment segment = waitingSegList.get(0);
@@ -517,7 +598,7 @@
            insertSeg.setPosType(TaskPosDto.PosType.MOVE.toString());
            insertSeg.setState(SegmentStateType.WAITING.toString());
            if (!segmentService.save(insertSeg)) {
                log.error("Segment [{}] 保存失败 !!!", segment.getTravelId() + " - " + segment.getSerial());
                News.error("Segment [{}] 保存失败 !!!", segment.getTravelId() + " - " + segment.getSerial());
                return false;
            } else {
                jam.setAvoSeg(insertSeg.getId());
@@ -543,13 +624,13 @@
            jam.setStartTime(new Date());
            jam.setState(JamStateType.RUNNING.toString());
            if (!jamService.save(jam)) {
                log.error("AGV[{}] failed to save jam", agv.getUuid());
                News.error("AGV[{}] failed to save jam", agv.getUuid());
                throw new CoolException("failed to save jam");
            }
        } else {
            jam.setDuration(System.currentTimeMillis() - jam.getStartTime().getTime());
            if (!jamService.updateById(jam)) {
                log.error("AGV[{}] failed to update jam", agv.getUuid());
                News.error("AGV[{}] failed to update jam", agv.getUuid());
            }
        }
        return jam;
@@ -559,7 +640,7 @@
        originJam.setUpdateTime(new Date());
        originJam.setState(JamStateType.FINISH.toString());
        if (!jamService.updateById(originJam)) {
            log.error("Jam[{}] failed to update", originJam.getUuid());
            News.error("Jam[{}] failed to update", originJam.getUuid());
            return originJam;
        } else {
            return this.createOrUpdateJam(
@@ -572,43 +653,47 @@
        }
    }
    private List<String> getBlackPathList(List<Jam> unfinishedOriginJamByCurrAgv) {
    private List<String> getBlackPathList(String agvNo, 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())) {
        if (Cools.isEmpty(unfinishedOriginJamByCurrAgv)) {
            return blackPathList;
        }
                    List<String> list = GsonUtils.fromJsonToList(jam.getJamPath(), String.class);
        AgvModel agvModel = agvModelService.getByAgvNo(agvNo);
        double bufferRadius = MapDataUtils.buildFootprint(agvModel).maxExtent();
                    Agv jamAgv = agvService.getById(jam.getJamAgv());
                    List<String> jamDynamicNodes = mapService.queryCodeListFromDynamicNode(lev, jamAgv.getUuid());
                    // jamDynamicNodes has sorted
                    String firstCodeNode = jamDynamicNodes.stream().findFirst().orElse(null);
        for (Jam jam : unfinishedOriginJamByCurrAgv) {
            if (!Cools.isEmpty(jam.getJamPath())) {
                    if (!Cools.isEmpty(firstCodeNode)) {
                        int idx = list.indexOf(firstCodeNode);
                        if (idx != -1) {
                            list = new ArrayList<>(list.subList(idx, list.size()));
                List<String> list = GsonUtils.fromJsonToList(jam.getJamPath(), String.class);
                            // 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);
                        } else {
                            // 如果被阻塞车辆已经不在原来的阻塞路径中,考虑避让车走行时不需要把之前的阻塞路径加入黑名单
                            list = new ArrayList<>();
                        }
                String jamAgvNo = agvService.getAgvNo(jam.getJamAgv());
                List<String> jamDynamicNodes = mapService.queryCodeListFromDynamicNode(lev, jamAgvNo);
                // 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
                        AgvModel jamAgvModel = agvModelService.getByAgvNo(jamAgvNo);
                        Double avoidDistance = MapDataUtils.buildFootprint(jamAgvModel).maxExtent() + bufferRadius;
                        List<String> waveCodeList = mapService.getWaveScopeByCode(lev, firstCodeNode, avoidDistance)
                                .stream().map(NavigateNode::getCodeData).distinct().collect(Collectors.toList());
                        list.addAll(waveCodeList);
                    } else {
                        // 如果被阻塞车辆已经不在原来的阻塞路径中,考虑避让车走行时不需要把之前的阻塞路径加入黑名单
                        list = new ArrayList<>();
                    }
                    blackPathList.addAll(list);
                }
                blackPathList.addAll(list);
            }
        }
        return blackPathList.stream().distinct().collect(Collectors.toList());
    }
@@ -618,10 +703,18 @@
            if (!blockVehicleDto.isAvoidable()) {
                continue;
            }
            Long agvId = agvService.getAgvId(blockVehicleDto.getVehicle());
            // 当前vehicle正在进行避让作业
            if (!Cools.isEmpty(jamService.getUnfinishedAvoSegByAvo(blockVehicleDto.getVehicle(), null))) {
            if (!Cools.isEmpty(jamService.getUnfinishedAvoSegByAvo(agvId, null))) {
                continue;
            }
            // 当前vehicle正在进行滚筒输送线等待
            if (travelService.hasRollerWaiting(agvId)) {
                continue;
            }
//            if (segmentService.isRollerWaiting(agvId)) {
//                continue;
//            }
            return blockVehicleDto.getVehicle();
        }
        return null;
@@ -651,7 +744,7 @@
            return false;
        }
        if (jamList.size() > 1) {
            log.error("AvoSeg[id = {}] seg data has exception, result in two jams", avoSeg);
            News.error("AvoSeg[id = {}] seg data has exception, result in two jams", avoSeg);
        }
        Jam jam = jamList.get(0);
        if (jam.getState().equals(JamStateType.DEPRECATED.toString())) {
@@ -664,4 +757,4 @@
        return false;
    }
}
}