From fc8f17cdb4245f45a5c4bab712e1740cddc05d64 Mon Sep 17 00:00:00 2001 From: walker-sheng Date: Mon, 11 Oct 2021 16:59:33 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8C=89=E8=AE=A1=E5=88=92=E8=A1=8C=E8=BD=A6?= =?UTF-8?q?=E5=8A=9E=E7=90=86=E8=BF=9B=E8=B7=AF=E3=80=81=E8=A7=A3=E9=94=81?= =?UTF-8?q?=E8=BF=9B=E8=B7=AF=E9=80=BB=E8=BE=91=E8=B0=83=E6=95=B4=20?= =?UTF-8?q?=E8=BF=9B=E8=B7=AF=E8=B7=AF=E5=BE=84=E7=AD=9B=E9=80=89=E8=BF=9B?= =?UTF-8?q?=E8=B7=AF=E9=80=BB=E8=BE=91=E8=B0=83=E6=95=B4=20=E7=9B=B4?= =?UTF-8?q?=E6=8E=A5=E5=8A=9E=E7=90=86=E8=BF=9B=E8=B7=AF=E9=81=93=E5=B2=94?= =?UTF-8?q?=E8=BD=AC=E5=8A=A8bug=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cbtc/ATS/service/AtsTrainLoadService.java | 88 +++++++++++++++---- .../simulation/cbtc/data/plan/TripPlan.java | 38 ++++++++ .../cbtc/data/support/RoutePath.java | 54 +++++++++++- .../cbtc/tool/DeviceStatusModifyTool.java | 32 ++----- 4 files changed, 169 insertions(+), 43 deletions(-) diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/AtsTrainLoadService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/AtsTrainLoadService.java index 9d538300b..bbf3635b1 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/AtsTrainLoadService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/AtsTrainLoadService.java @@ -39,6 +39,8 @@ import org.springframework.util.CollectionUtils; import java.time.LocalDateTime; import java.time.LocalTime; import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; @Slf4j @Component @@ -400,16 +402,16 @@ public class AtsTrainLoadService { log.debug(String.format("实际加载列车数量:[%s]", loadedList.size())); // 处理加载到折返轨的重叠列车 this.handleTurnBackCollisionTrainByTripPlan(simulation, loadedList); - // 列车进路排列 - this.setTrainRouteByTripPlan(simulation, loadedList); // 重叠列车处理 this.handleCollision(simulation, loadedList); // 车次计划发车状态 this.updateTripPlanStatus(simulation); // 列车上线并构建ATS监控列车信息 - this.trainOnlineAndBuildSupervise(simulation, loadedList); - // 办理ats选择的进路 - this.setRoutesThatSelectedByAts(simulation); + List superviseList = this.trainOnlineAndBuildSupervise(simulation, loadedList); + // 列车进路排列 + this.setTrainRouteByTripPlan(simulation, loadedList, superviseList); +// // 办理ats选择的进路 +// this.setRoutesThatSelectedByAts(simulation); // 计算移动授权 // this.maService.calculateMaOfCtcTrains(simulation); // this.zcLogicLoop.run(simulation); @@ -503,7 +505,8 @@ public class AtsTrainLoadService { } } - private void trainOnlineAndBuildSupervise(Simulation simulation, List loadedList) { + private List trainOnlineAndBuildSupervise(Simulation simulation, List loadedList) { + List superviseList = new ArrayList<>(); SimulationDataRepository repository = simulation.getRepository(); for (VirtualRealityTrain train : loadedList) { // 构建监控列车信息 @@ -555,8 +558,10 @@ public class AtsTrainLoadService { } trainInfo.tracking(train); repository.addTrainInfo(trainInfo); + superviseList.add(trainInfo); } repository.addOnlineTrainList(loadedList); + return superviseList; } private boolean isOnSectionStopPoint(SectionPosition headPosition, Section section, boolean right) { @@ -646,8 +651,16 @@ public class AtsTrainLoadService { return collisionList; } - private void setTrainRouteByTripPlan(Simulation simulation, List loadedList) { + private void setTrainRouteByTripPlan(Simulation simulation, List loadedList, List superviseList) { SimulationDataRepository repository = simulation.getRepository(); + Map trainInfoMap = superviseList.stream() + .collect(Collectors.toMap(TrainInfo::getCode, Function.identity())); + // 按运行计划时间排序 + loadedList.sort((train1, train2) -> { + TripPlan tripPlan1 = repository.getTripPlan(train1.getServiceNumber(), train1.getTripNumber()); + TripPlan tripPlan2 = repository.getTripPlan(train2.getServiceNumber(), train2.getTripNumber()); + return TripPlan.compare(tripPlan1, tripPlan2); + }); for (VirtualRealityTrain train : loadedList) { Section headSection = train.getHeadPosition().getSection(); boolean right = train.isRight(); @@ -658,19 +671,58 @@ public class AtsTrainLoadService { for (int i = 1; i < viaSectionList.size(); i++) { Section start = viaSectionList.get(i - 1); Section end = viaSectionList.get(i); - // 取相邻两区段的路径单元,查询进路 - RoutePath routePath = this.selectDefaultRoutePath(repository, start, end); - Route route = routePath.queryRouteContainsSection(train.isCommunicable(), headSection, repository.getConfig()); - if (Objects.nonNull(route)) { - // 排列好进路 - this.deviceStatusModifyTool.openRouteDirect(simulation, route); - // 根据列车位置直接进路正常解锁 - this.deviceStatusModifyTool.routeUnlockByEndSection(route, tailPosition); - // 进路设置为正常解锁 - this.ciLogic.trainUnlockStart(simulation, route); - route.setUnlockedSection(tailPosition.getSection()); + TrainInfo trainInfo = trainInfoMap.get(train.getCode()); + if (trainInfo.getPlanStandTrack() == null) { break; } + if (!end.getCode().equals(trainInfo.getPlanStandTrack())) { + continue; + } + Section tailSection = tailPosition.getSection(); + // 取相邻两区段的路径单元,查询进路 + RoutePath routePath = this.selectDefaultRoutePath(repository, start, end); + if (!routePath.isPathSection(tailSection)) { + if (i - 2 >= 0) { + Section pre = viaSectionList.get(i - 2); + RoutePath preRoutePath = this.selectDefaultRoutePath(repository, pre, start); + Route route = preRoutePath.queryRouteContainsSection(train.isCommunicable(), tailSection, repository.getConfig()); + if (route != null) { + // 排列好进路 + this.deviceStatusModifyTool.openRouteDirect(simulation, route); + // 根据列车位置直接进路正常解锁 + this.deviceStatusModifyTool.routeUnlockByEndSection(route, tailSection); + } + } + } + List routeList = routePath.getRouteList(); + Set handledRouteStarts = new HashSet<>(); + for (Route route : routeList) { + if (handledRouteStarts.contains(route.getStart().getCode())) { + continue; + } + if (route.isRouteSection(tailSection) || route.isRouteSection(headSection)) { + Route selected = routePath.selectDefaultRouteOfStart(route.getStart(), train.isCommunicable(), repository.getConfig()); + if (selected != null) { + handledRouteStarts.add(route.getStart().getCode()); + // 排列好进路 + this.deviceStatusModifyTool.openRouteDirect(simulation, route); + // 根据列车位置直接进路正常解锁 + Section unlockTo = tailSection; + if (!route.isRouteSection(tailSection)) { + unlockTo = headSection; + } + this.deviceStatusModifyTool.routeUnlockByEndSection(route, unlockTo); + } + } else if (!train.isStop() && route.getStart().isApproachSection(headSection.getCode())) { + // 排列好进路 + Route aheadRoute = routePath.selectDefaultRouteOfStart(route.getStart(), train.isCommunicable(), repository.getConfig()); + if (aheadRoute != null) { + this.deviceStatusModifyTool.openRouteDirect(simulation, aheadRoute); + } + break; + } + } + break; } } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/data/plan/TripPlan.java b/src/main/java/club/joylink/rtss/simulation/cbtc/data/plan/TripPlan.java index dbb6f362b..99947c05e 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/data/plan/TripPlan.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/data/plan/TripPlan.java @@ -447,4 +447,42 @@ public class TripPlan { } } } + + /** + * 按计划时间先后顺序排序(对于同向的按到某个都达到的站的时间排序,对于不同向的默认向右在前) + * @param list + */ + public static void sort(List list) { + list.sort(TripPlan::compare); + } + + /** + * 比较车次计划先后顺序, 对于同向的按到某个都达到的站的时间排序,对于不同向的默认向右在前 + * @param plan1 + * @param plan2 + * @return + */ + public static int compare(TripPlan plan1, TripPlan plan2) { + if (plan1.isRight() != plan2.isRight()) { + if (plan2.isRight()) { + return 1; + } else { + return -1; + } + } else { + List spList1 = plan1.getPlanList(); + List spList2 = plan2.getPlanList(); + StationPlan stationPlan1 = spList1.get(spList1.size() - 1); + StationPlan stationPlan2 = plan2.queryStationPlan(stationPlan1.getStation()); + if (stationPlan2 != null) { + return stationPlan1.getArriveTime().compareTo(stationPlan2.getArriveTime()); + } + stationPlan2 = spList2.get(spList2.size() - 1); + stationPlan1 = plan1.queryStationPlan(stationPlan2.getStation()); + if (stationPlan1 != null) { + return stationPlan1.getArriveTime().compareTo(stationPlan2.getArriveTime()); + } + } + return plan1.getStartTime().compareTo(plan2.getStartTime()); + } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/data/support/RoutePath.java b/src/main/java/club/joylink/rtss/simulation/cbtc/data/support/RoutePath.java index 800f01b36..6a4031ba8 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/data/support/RoutePath.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/data/support/RoutePath.java @@ -1,7 +1,6 @@ package club.joylink.rtss.simulation.cbtc.data.support; import club.joylink.rtss.exception.BusinessExceptionAssertEnum; -import club.joylink.rtss.simulation.cbtc.constant.RunLevel; import club.joylink.rtss.simulation.cbtc.data.map.*; import lombok.Getter; import org.springframework.util.CollectionUtils; @@ -431,4 +430,57 @@ public class RoutePath { } return false; } + + /** + * 根据始端信号机选择此进路路径所需的进路(对于哈尔滨的进路,根据通信和进路是否ATP判断,其他取延续保护默认定位进路) + * @param signal + * @param communicable + * @param config + * @return + */ + public Route selectDefaultRouteOfStart(Signal signal, boolean communicable, MapConfig config) { + List triggerList = new ArrayList<>(); + for (Route route : this.routeList) { + if (config.isRouteLikeHa1()) { + if (communicable) { // 通信车找ATP进路 + if (!route.isAtp()) { + continue; + } + } else { // 非通信车找地面进路 + if (!route.isGround()) { + continue; + } + } + } + if (route.getStart().equals(signal) && !route.isTurnBack() && + !triggerList.contains(route) && route.isAtsControl()) { + if (config.isRouteLikeHa1()) { + if (communicable && route.isAtp()) { + triggerList.add(route); + } else if (!communicable && route.isGround()) { + triggerList.add(route); + } + } else { + triggerList.add(route); + } + } + } + //选择要触发的进路 + Route route = null; + if (triggerList.size() == 1) { + route = triggerList.get(0); + } else if (triggerList.size() > 1) { + // 取第一个延续保护道岔定位的 + for (Route temp : triggerList) { + List switchList = temp.getOverlap().getFirstPath().getSwitchList(); + if (switchList.get(0).isNormal()) { + route = temp; + break; + } else { + route = temp; + } + } + } + return route; + } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/tool/DeviceStatusModifyTool.java b/src/main/java/club/joylink/rtss/simulation/cbtc/tool/DeviceStatusModifyTool.java index 2d14330f6..808c7efbd 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/tool/DeviceStatusModifyTool.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/tool/DeviceStatusModifyTool.java @@ -7,7 +7,6 @@ import club.joylink.rtss.simulation.cbtc.constant.SignalAspect; import club.joylink.rtss.simulation.cbtc.constant.SwitchIndication; import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository; import club.joylink.rtss.simulation.cbtc.data.map.*; -import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition; import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySignal; import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySwitch; import club.joylink.rtss.simulation.cbtc.device.virtual.VirtualRealityDeviceService; @@ -17,7 +16,6 @@ import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Objects; @@ -183,7 +181,7 @@ public class DeviceStatusModifyTool { virtualSwitch.finish(); aSwitch.setPos(SwitchIndication.N); } else { - virtualSwitch.control(VirtualRealitySwitch.Operation.NP); + virtualSwitch.control(VirtualRealitySwitch.Operation.RP); virtualSwitch.finish(); aSwitch.setPos(SwitchIndication.R); } @@ -207,34 +205,20 @@ public class DeviceStatusModifyTool { * 直接根据最后一根区段解锁进路 * @param route */ - public void routeUnlockByEndSection(Route route, SectionPosition tailPosition) { - Section endOccupied = tailPosition.getSection(); - if (!route.isRouteSection(endOccupied)) { + public void routeUnlockByEndSection(Route route, Section tailSection) { + if (!route.isRouteSection(tailSection)) { // 不是进路区段,不解锁 return; } + route.startNormalUnlock(); + // 关闭始端信号机 + openSignalDirectly(route.getStart(), route.getStart().getSignalModel().getDefaultAspect()); boolean right = route.getStart().isRight(); // 区段是顺序的(否则会有问题) List
sectionList = route.getSectionList(); for (Section section : sectionList) { - if (section.isSamePhysical(endOccupied.getCode())) { - if (!CollectionUtils.isEmpty(section.getLogicList())) { - // 逻辑区段占用,根据逻辑区段占用位置解锁 - List
logicList = section.getLogicList(); - if (!right) { // 向左,逻辑区段列表reverse - logicList = new ArrayList<>(section.getLogicList()); - Collections.reverse(logicList); - } - Section logicSection = tailPosition.getLogicSection(); - for (Section logic : logicList) { - if (logic.equals(logicSection)) { - break; - } else { - logic.routeUnlocking(route); - logic.overlapUnlocking(); - } - } - } + if (section.isSamePhysical(tailSection.getCode())) { + route.updateUnlockedSection(tailSection); break; } // 直接解锁区段