新版ATS进路选择修改

This commit is contained in:
joylink_zhangsai 2021-08-02 09:40:52 +08:00
commit 0a989ab9e2
22 changed files with 419 additions and 502 deletions

View File

@ -86,9 +86,9 @@ public class AtpSectionService {
for (VirtualRealityTrain train : onlineTrainList) { for (VirtualRealityTrain train : onlineTrainList) {
List<Section> atpSectionList = trainAtpSectionMap.get(train.getGroupNumber()); List<Section> atpSectionList = trainAtpSectionMap.get(train.getGroupNumber());
List<Section> physicalList = this.convert2PhysicalSectionList(atpSectionList); List<Section> physicalList = this.convert2PhysicalSectionList(atpSectionList);
if (train.isCBTC() && signal.containsApproachAtpSection(atpSectionList)) { //通信车在atp接近区段上 if (train.isCommunicable() && signal.containsApproachAtpSection(atpSectionList)) { //通信车在atp接近区段上
approachMsg = SignalApproachMessage.ApproachMessage.CBTC; approachMsg = SignalApproachMessage.ApproachMessage.CBTC;
} else if (!train.isCBTC() && signal.containsApproachPhysicalSection(physicalList)) { //非通信车在物理接近区段上 } else if (!train.isCommunicable() && signal.containsApproachPhysicalSection(physicalList)) { //非通信车在物理接近区段上
approachMsg = SignalApproachMessage.ApproachMessage.NCT; approachMsg = SignalApproachMessage.ApproachMessage.NCT;
nctApproachSignalMap.put(train, signal); nctApproachSignalMap.put(train, signal);
} }
@ -142,7 +142,7 @@ public class AtpSectionService {
SimulationDataRepository repository = simulation.getRepository(); SimulationDataRepository repository = simulation.getRepository();
atpSectionList = CalculateService.getAtpSections(trainHeadPosition, trainTailPosition, atpSectionList = CalculateService.getAtpSections(trainHeadPosition, trainTailPosition,
right, repository.getConfig().isSwitchSingleHandle()); right, repository.getConfig().isSwitchSingleHandle());
if (train.isCBTC()) { // cbtc通信车占用 if (train.isCommunicable()) { // 通信车占用
atpSectionList.forEach(atpSection -> atpSection.communicateTrainOccupy(right)); atpSectionList.forEach(atpSection -> atpSection.communicateTrainOccupy(right));
} else { // 非通信车 } else { // 非通信车
Set<Section> collect = atpSectionList.stream().map(section -> { //找到列车占压区段所属的物理区段 Set<Section> collect = atpSectionList.stream().map(section -> { //找到列车占压区段所属的物理区段

View File

@ -74,35 +74,13 @@ public class ZCLogicLoop {
})); }));
} }
//更新CBTC ma //更新CBTC ma
if (headPosition.getSection().anyZcWorking()) { if (train.isCommunicable()) {
this.calculateMAOfCBTC(simulation, train, trainList); this.calculateMAOfCBTC(simulation, train, trainList);
} }
// //更新CBTC ma
// if (!deviceStation.getZc().isFault()) { //如果列车头所在区段所属设备集中站zc未故障
// this.calculateMAOfCBTC(simulation, train, trainList);
// }
} }
}); });
} }
/**
* 为升级CM而强制更新ma简单处理
* @return 是否更新成功
*/
public boolean updateCbtcMa4CM(Simulation simulation, VirtualRealityTrain train) {
RunLevel defaultRunLevel = simulation.getRepository().getConfig().getRunMode();
if (RunLevel.CBTC.equals(defaultRunLevel)) {
List<VirtualRealityTrain> trainList = simulation.getRepository().getOnlineTrainList();
SectionPosition headPosition = train.getHeadPosition();
if (headPosition.getSection().anyZcWorking()) {
List<MovementAuthority.End> endList = this.findMaEnd(simulation, train, trainList);
MovementAuthority ma = this.compareAndBuildMa(train, endList);
return onboardAtpApiService.ignoreDriveModeUpdateMA4CBTC(train, ma);
}
}
return false;
}
private void calculateMAOfCBTC(Simulation simulation, VirtualRealityTrain train, private void calculateMAOfCBTC(Simulation simulation, VirtualRealityTrain train,
List<VirtualRealityTrain> trainList) { List<VirtualRealityTrain> trainList) {
// 查找移动授权终端列表 // 查找移动授权终端列表
@ -154,13 +132,8 @@ public class ZCLogicLoop {
// } // }
//非通信车占用区段 //非通信车占用区段
if (section.isNonCbtcOccupy() && !section.isInvalid()) { if (section.isNonCbtcOccupy() && !section.isInvalid()) {
VirtualRealitySectionAxleCounter axle = section.getVirtualAxleCounter(); endList.add(new MovementAuthority.End(section, MovementAuthority.EndType.NCT_OCCUPIED_SECTION));
if (axle == null && section.getParent() != null) return endList;
axle = section.getParent().getVirtualAxleCounter();
if (axle == null || axle.getLeftCount() > 1 || axle.getRightCount() > 1) { //以计轴器计数为1作为是当前列车导致区段非通信车占用的判断依据
endList.add(new MovementAuthority.End(section, MovementAuthority.EndType.NCT_OCCUPIED_SECTION));
return endList;
}
} }
//通信车占用区段 //通信车占用区段
List<Section> occupiedLogicSectionList = simulation.getRepository().queryTrainOccupyAtpSectionList(train.getGroupNumber()); List<Section> occupiedLogicSectionList = simulation.getRepository().queryTrainOccupyAtpSectionList(train.getGroupNumber());
@ -236,7 +209,7 @@ public class ZCLogicLoop {
if (trainEnd != null) if (trainEnd != null)
endList.add(trainEnd); endList.add(trainEnd);
//非通信车占用区段 //非通信车占用区段
if (temp.isNonCbtcOccupy() && !temp.isInvalid()) { if (temp.isNctOccupied() && !temp.isInvalid()) {
endList.add(new MovementAuthority.End(temp, MovementAuthority.EndType.NCT_OCCUPIED_SECTION)); endList.add(new MovementAuthority.End(temp, MovementAuthority.EndType.NCT_OCCUPIED_SECTION));
} }
//检查关闭的区段 //检查关闭的区段
@ -696,7 +669,7 @@ public class ZCLogicLoop {
if (section.isStandTrack()) { if (section.isStandTrack()) {
List<Stand> standList = section.getStandList(); List<Stand> standList = section.getStandList();
for (Stand stand : standList) { for (Stand stand : standList) {
if (!stand.isInterlockRelease() && stand.isPsdOpen()) { if (!stand.isPsdSafe()) {
return new MovementAuthority.End(stand, MovementAuthority.EndType.OPENED_PSD, section); return new MovementAuthority.End(stand, MovementAuthority.EndType.OPENED_PSD, section);
} }
if (stand.isClosed()) { if (stand.isClosed()) {

View File

@ -1,9 +1,11 @@
package club.joylink.rtss.simulation.cbtc.ATS.operation.handler; package club.joylink.rtss.simulation.cbtc.ATS.operation.handler;
import club.joylink.rtss.simulation.cbtc.ATP.ground.GroundAtpApiService;
import club.joylink.rtss.simulation.cbtc.ATP.ground.ZCLogicLoop; import club.joylink.rtss.simulation.cbtc.ATP.ground.ZCLogicLoop;
import club.joylink.rtss.simulation.cbtc.ATS.operation.Operation; import club.joylink.rtss.simulation.cbtc.ATS.operation.Operation;
import club.joylink.rtss.simulation.cbtc.ATS.operation.annotation.OperateHandler; import club.joylink.rtss.simulation.cbtc.ATS.operation.annotation.OperateHandler;
import club.joylink.rtss.simulation.cbtc.ATS.operation.annotation.OperateHandlerMapping; import club.joylink.rtss.simulation.cbtc.ATS.operation.annotation.OperateHandlerMapping;
import club.joylink.rtss.simulation.cbtc.CI.CILogicLoop;
import club.joylink.rtss.simulation.cbtc.CI.CiApiService; import club.joylink.rtss.simulation.cbtc.CI.CiApiService;
import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.constant.ControlGear; import club.joylink.rtss.simulation.cbtc.constant.ControlGear;
@ -39,6 +41,9 @@ public class DriverOperateHandler {
@Autowired @Autowired
private ZCLogicLoop zcLogicLoop; private ZCLogicLoop zcLogicLoop;
@Autowired
private GroundAtpApiService groundAtpApiService;
@OperateHandlerMapping(type = Operation.Type.Driver_Force_Change) @OperateHandlerMapping(type = Operation.Type.Driver_Force_Change)
public void changeTrainForce(Simulation simulation, String groupNumber, Float percent) { public void changeTrainForce(Simulation simulation, String groupNumber, Float percent) {
Objects.requireNonNull(percent); Objects.requireNonNull(percent);
@ -114,28 +119,12 @@ public class DriverOperateHandler {
public void changeTrainDriveMode(Simulation simulation, String groupNumber, DriveMode driveMode) { public void changeTrainDriveMode(Simulation simulation, String groupNumber, DriveMode driveMode) {
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
switch (driveMode) { switch (driveMode) {
case CM: { case AM:
if (!train.isAtpOn()) { case CM:
throw new SimulationException(SimulationExceptionType.Invalid_Operation,
String.format("列车[%s]ATP未开启无法升级CM驾驶模式", train.getGroupNumber()));
}
if (zcLogicLoop.updateCbtcMa4CM(simulation, train)) {
train.useCMMode();
}
break;
}
case RM: { case RM: {
if (!train.isAtpOn()) { train.setPreDriveMode(driveMode);
throw new SimulationException(SimulationExceptionType.Invalid_Operation,
String.format("列车[%s]ATP未开启无法升级RM驾驶模式", train.getGroupNumber()));
}
train.useRMMode();
break; break;
} }
case NRM:
ATPService.cutOffAtp(train);
// train.useNRMMode();
break;
} }
} }

View File

@ -752,8 +752,8 @@ public class AtsRouteSettingService {
++count; ++count;
Signal signal = base.getSignalOf(right); Signal signal = base.getSignalOf(right);
if (Objects.isNull(signal) || !signal.isClose() || if (Objects.isNull(signal) || !signal.isClose() ||
(!train.isCtcLevel() && signal.isVirtual())) { (!train.isCommunication() && signal.isVirtual())) {
// 指定方向信号机不存在或已经开放,或非CTC列车碰到虚拟信号机,继续往下找 // 指定方向信号机不存在或已经开放,或非通信车碰到虚拟信号机,继续往下找
base = base.getNextRunningSectionOf(right); base = base.getNextRunningSectionOf(right);
continue; continue;
} }

View File

@ -593,7 +593,7 @@ public class AtsTrainLoadService {
Section end = viaSectionList.get(i); Section end = viaSectionList.get(i);
// 取相邻两区段的路径单元查询进路 // 取相邻两区段的路径单元查询进路
RoutePath routePath = this.selectDefaultRoutePath(repository, start, end); RoutePath routePath = this.selectDefaultRoutePath(repository, start, end);
Route route = routePath.queryRouteContainsSection(train.getRunLevel(), headSection, repository.getConfig()); Route route = routePath.queryRouteContainsSection(train.isCommunicable(), headSection, repository.getConfig());
if (Objects.nonNull(route)) { if (Objects.nonNull(route)) {
// 排列好进路 // 排列好进路
this.deviceStatusModifyTool.openRouteDirect(simulation, route); this.deviceStatusModifyTool.openRouteDirect(simulation, route);

View File

@ -308,8 +308,7 @@ public class AtsTrainService {
if (!sections.get(0).equals(headSection)) { if (!sections.get(0).equals(headSection)) {
sections.add(0, headSection); sections.add(0, headSection);
} }
SectionPath headPath = new SectionPath(selectRouting.isRight(), null, sections, null); supervisedTrain.setHctPath(new SectionRunPath(sections, selectRouting.isRight()));
supervisedTrain.setHeadPath(headPath);
break; break;
default: default:
throw new SimulationException(SimulationExceptionType.System_Fault, String.format("无法识别的目的地码类型[%s]", destinationCodeDefinition.getType())); throw new SimulationException(SimulationExceptionType.System_Fault, String.format("无法识别的目的地码类型[%s]", destinationCodeDefinition.getType()));
@ -675,7 +674,7 @@ public class AtsTrainService {
} }
break; break;
case OTHER: case OTHER:
List<Section> path = train.getHeadPath().getSectionList(); List<Section> path = train.getHctPath().getSections();
if (path != null) { if (path != null) {
int index = path.indexOf(headSection); int index = path.indexOf(headSection);
if (index == -1) { if (index == -1) {

View File

@ -2,19 +2,10 @@ package club.joylink.rtss.simulation.cbtc.ATS.service.ars;
import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository; import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
import club.joylink.rtss.simulation.cbtc.data.map.DestinationCodeDefinition;
import club.joylink.rtss.simulation.cbtc.data.map.Route; import club.joylink.rtss.simulation.cbtc.data.map.Route;
import club.joylink.rtss.simulation.cbtc.data.map.Section;
import club.joylink.rtss.simulation.cbtc.data.plan.StationPlan;
import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan;
import club.joylink.rtss.simulation.cbtc.data.support.RoutePath;
import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo; import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.Comparator;
import java.util.List;
/** /**
* 头码车进路选择 * 头码车进路选择
@ -28,45 +19,6 @@ public class AtsHeadTrainRouteSelectServiceImpl extends AtsRouteSelectService {
return null; return null;
} }
SimulationDataRepository repository = simulation.getRepository(); SimulationDataRepository repository = simulation.getRepository();
// 基础检查 return queryTriggerRoutes(repository, trainInfo.getHctPath().getSections(), trainInfo, null);
Boolean right = trainInfo.getRight();
if (right == null)
return null;
DestinationCodeDefinition dcd = repository.getDestinationCodeDefinition(trainInfo.getDestinationCode());
Object[] results = queryTriggerRoutes(repository, trainInfo.getHeadPath().getSectionList(), trainInfo, null, trainInfo.getHeadPath().isRight());
return filterRoutes(repository, trainInfo, results, dcd);
}
private Route filterRoutes(SimulationDataRepository repository, TrainInfo trainInfo, Object[] results, DestinationCodeDefinition dcd) {
if (results == null)
return null;
List<Route> triggers = (List<Route>) results[0];
if (CollectionUtils.isEmpty(triggers))
return null;
Route route;
if (triggers.size() == 1) {
route = triggers.get(0);
} else {
route = triggers.stream().min(Comparator.comparingInt(Route::getReverseSwitchQuantity)).get();
}
return route;
}
private boolean isConflicting(SimulationDataRepository repository, TrainInfo trainInfo, Route route) {
if (!trainInfo.isPlanTrain())
return false;
TripPlan tripPlan = repository.getTripPlan(trainInfo.getServiceNumber(), trainInfo.getTripNumber());
Section start = repository.getByCode(trainInfo.getPhysicalSection(), Section.class);
for (StationPlan stationPlan : tripPlan.getPlanList()) {
if (!stationPlan.isFinished()) {
List<RoutePath> routePaths = repository.getRoutePaths(start, stationPlan.getSection());
RoutePath routePath = selectRoutePath(routePaths);
if (routePath.isConflictWith(route)) {
return true;
}
}
start = stationPlan.getSection();
}
return false;
} }
} }

View File

@ -8,7 +8,6 @@ import club.joylink.rtss.simulation.cbtc.data.map.*;
import club.joylink.rtss.simulation.cbtc.data.plan.StationPlan; import club.joylink.rtss.simulation.cbtc.data.plan.StationPlan;
import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan; import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan;
import club.joylink.rtss.simulation.cbtc.data.support.RoutePath; import club.joylink.rtss.simulation.cbtc.data.support.RoutePath;
import club.joylink.rtss.simulation.cbtc.data.support.StationTurnBackStrategyOption;
import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo; import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -44,13 +43,12 @@ public class AtsPlanTrainRouteSelectServiceImpl extends AtsRouteSelectService {
LocalDateTime systemTime = simulation.getSystemTime(); LocalDateTime systemTime = simulation.getSystemTime();
// 根据车次计划查找可触发进路列表 // 根据车次计划查找可触发进路列表
// Object[] results = this.queryByStationPlan(repository, systemTime, trainInfo, tripPlan); // Object[] results = this.queryByStationPlan(repository, systemTime, trainInfo, tripPlan);
Object[] results = queryByStationPlan2(repository, systemTime, trainInfo, tripPlan); Route route = queryByStationPlan(repository, systemTime, trainInfo, tripPlan);
// 根据计划筛选需触发进路 // 根据计划筛选需触发进路
Route route = filterRoutes(simulation, trainInfo, tripPlan, results); return filterRoutes(simulation, trainInfo, tripPlan, route);
return route;
} }
private Object[] queryByStationPlan2(SimulationDataRepository repository, LocalDateTime systemTime, TrainInfo trainInfo, TripPlan tripPlan) { private Route queryByStationPlan(SimulationDataRepository repository, LocalDateTime systemTime, TrainInfo trainInfo, TripPlan tripPlan) {
// 计划时间 // 计划时间
List<StationPlan> planList = tripPlan.getPlanList(); List<StationPlan> planList = tripPlan.getPlanList();
LocalTime startTime = tripPlan.getStartTime(); LocalTime startTime = tripPlan.getStartTime();
@ -66,9 +64,9 @@ public class AtsPlanTrainRouteSelectServiceImpl extends AtsRouteSelectService {
} }
List<Section> targetList = tripPlan.getPlanList().stream().map(StationPlan::getSection).collect(Collectors.toList()); List<Section> targetList = tripPlan.getPlanList().stream().map(StationPlan::getSection).collect(Collectors.toList());
if (tripPlan.isBehindTurnBack()) { if (tripPlan.isBehindTurnBack()) {
return queryTriggerRoutes(repository, targetList, trainInfo, tripPlan.getEndSection(), tripPlan.isRight()); return queryTriggerRoutes(repository, targetList, trainInfo, tripPlan.getEndSection());
} else { } else {
return queryTriggerRoutes(repository, targetList, trainInfo, null, tripPlan.isRight()); return queryTriggerRoutes(repository, targetList, trainInfo, null);
} }
} }
@ -77,25 +75,16 @@ public class AtsPlanTrainRouteSelectServiceImpl extends AtsRouteSelectService {
* @param simulation * @param simulation
* @param trainInfo * @param trainInfo
* @param tripPlan * @param tripPlan
* @param results * @param route
* @return * @return
*/ */
private Route filterRoutes(Simulation simulation, private Route filterRoutes(Simulation simulation,
TrainInfo trainInfo, TripPlan tripPlan, Object[] results) { TrainInfo trainInfo, TripPlan tripPlan, Route route) {
if (results == null) { if (route == null) {
return null;
}
List<Route> triggerList = (List<Route>) results[0];
if (CollectionUtils.isEmpty(triggerList)) {
return null; return null;
} }
SimulationDataRepository repository = simulation.getRepository(); SimulationDataRepository repository = simulation.getRepository();
// 先选取需要征用的进路 // 先选取需要征用的进路
boolean turnBack = (boolean) results[1];
Route route = this.filter(repository, trainInfo, tripPlan, triggerList, turnBack);
if (route == null) {
return null;
}
log.debug(String.format("列车[%s]筛选出的进路为:[%s]", trainInfo.getGroupNumber(), route.getName())); log.debug(String.format("列车[%s]筛选出的进路为:[%s]", trainInfo.getGroupNumber(), route.getName()));
if (route.isCheckConflict() && route.getConflictAlarm() == null) { if (route.isCheckConflict() && route.getConflictAlarm() == null) {
ConflictInfo conflictInfo = this.checkConflict(repository, trainInfo, tripPlan, route); ConflictInfo conflictInfo = this.checkConflict(repository, trainInfo, tripPlan, route);
@ -432,147 +421,147 @@ public class AtsPlanTrainRouteSelectServiceImpl extends AtsRouteSelectService {
return route; return route;
} }
/** // /**
* @return (List<Route>)[0] 可触发的进路(Boolean)[1]是否需要折返 // * @return (List<Route>)[0] 可触发的进路(Boolean)[1]是否需要折返
*/ // */
private Object[] queryByStationPlan(SimulationDataRepository repository, LocalDateTime systemTime, TrainInfo trainInfo, TripPlan tripPlan) { // private Object[] queryByStationPlan(SimulationDataRepository repository, LocalDateTime systemTime, TrainInfo trainInfo, TripPlan tripPlan) {
Route route = null; // Route route = null;
Object[] result = new Object[3]; // Object[] result = new Object[3];
result[1] = false; // result[1] = false;
result[2] = false; // result[2] = false;
List<Route> triggerList = null; // List<Route> triggerList = null;
// 获取列车上一停靠站台轨和下一计划达到轨道结合列车位置查询需要办理的进路 // // 获取列车上一停靠站台轨和下一计划达到轨道结合列车位置查询需要办理的进路
if (trainInfo.getPlanStandTrack() == null) { // 列车下一计划存在 // if (trainInfo.getPlanStandTrack() == null) { // 列车下一计划存在
return null; // return null;
} // }
// 计划时间 // // 计划时间
List<StationPlan> planList = tripPlan.getPlanList(); // List<StationPlan> planList = tripPlan.getPlanList();
LocalTime startTime = tripPlan.getStartTime(); // LocalTime startTime = tripPlan.getStartTime();
for (StationPlan stationPlan : planList) { // for (StationPlan stationPlan : planList) {
if (stationPlan.getSection().getCode().equals(trainInfo.getPlanStandTrack())) { // if (stationPlan.getSection().getCode().equals(trainInfo.getPlanStandTrack())) {
break; // break;
} // }
startTime = stationPlan.getLeaveTime(); // startTime = stationPlan.getLeaveTime();
} // }
if (!systemTime.toLocalTime().plusSeconds(50).isAfter(startTime)) { // if (!systemTime.toLocalTime().plusSeconds(50).isAfter(startTime)) {
log.debug(String.format("列车[%s]未到发车时间,不触发进路", trainInfo.getGroupNumber())); // log.debug(String.format("列车[%s]未到发车时间,不触发进路", trainInfo.getGroupNumber()));
return null; // return null;
} // }
Section planTrack = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class);//下一计划 // Section planTrack = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class);//下一计划
Section section = repository.getByCode(trainInfo.getPhysicalSection(), Section.class); // 列车所在区段 // Section section = repository.getByCode(trainInfo.getPhysicalSection(), Section.class); // 列车所在区段
if (!planTrack.isSamePhysical(section.getCode())) { // if (!planTrack.isSamePhysical(section.getCode())) {
List<RoutePath> routePathList = repository.queryRoutePathsByEnd(planTrack); // List<RoutePath> routePathList = repository.queryRoutePathsByEnd(planTrack);
routePathList = routePathList.stream() // routePathList = routePathList.stream()
.filter(routePath -> routePath.containsSection(section)) // .filter(routePath -> routePath.containsSection(section))
.collect(Collectors.toList()); // .collect(Collectors.toList());
result = this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePathList); // result = this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePathList);
} // }
if (!((boolean) result[1]) && !((boolean) result[2])) { // 不存在未开放进路,且不存在未接近的信号机 // if (!((boolean) result[1]) && !((boolean) result[2])) { // 不存在未开放进路,且不存在未接近的信号机
// 判断配置是否列车停站才触发接下来的进路 // // 判断配置是否列车停站才触发接下来的进路
MapConfig config = repository.getConfig(); // MapConfig config = repository.getConfig();
if (config.isSignalOpenAfterParking() && !trainInfo.isParking()) { // if (config.isSignalOpenAfterParking() && !trainInfo.isParking()) {
return null; // return null;
} else { // } else {
if (tripPlan.isLastPlanStationSection(planTrack)) { // if (tripPlan.isLastPlanStationSection(planTrack)) {
//是计划的终点站 // //是计划的终点站
if (tripPlan.isBehindTurnBack()) { // if (tripPlan.isBehindTurnBack()) {
// 是站后折返 // // 是站后折返
triggerList = this.queryAccordingTbStrategy(repository, trainInfo, tripPlan); // triggerList = this.queryAccordingTbStrategy(repository, trainInfo, tripPlan);
Object[] rs = {triggerList, true}; // Object[] rs = {triggerList, true};
return rs; // return rs;
} else if (!tripPlan.getEndSection().equals(tripPlan.getLastStationPlan().getSection())) { // } else if (!tripPlan.getEndSection().equals(tripPlan.getLastStationPlan().getSection())) {
// 备用车 // // 备用车
List<RoutePath> routePathList = repository.getRoutePaths(tripPlan.getLastStationPlan().getSection(), // List<RoutePath> routePathList = repository.getRoutePaths(tripPlan.getLastStationPlan().getSection(),
tripPlan.getEndSection()); // tripPlan.getEndSection());
result = this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePathList); // result = this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePathList);
} // }
} else { // } else {
StationPlan nextStationPlan = tripPlan.queryNextStationPlan(planTrack); // StationPlan nextStationPlan = tripPlan.queryNextStationPlan(planTrack);
if (nextStationPlan != null) { // if (nextStationPlan != null) {
// 下一计划车站存在 // // 下一计划车站存在
List<RoutePath> routePathList = repository.getRoutePaths(planTrack, nextStationPlan.getSection()); // List<RoutePath> routePathList = repository.getRoutePaths(planTrack, nextStationPlan.getSection());
result = this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePathList); // result = this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePathList);
} // }
} // }
} // }
} // }
triggerList = (List<Route>) result[0]; // triggerList = (List<Route>) result[0];
Object[] rs = {triggerList, false}; // Object[] rs = {triggerList, false};
return rs; // return rs;
} // }
private boolean isTriggerTurnBackRoute(SimulationDataRepository repository, TrainInfo trainInfo, TripPlan tripPlan) { // private boolean isTriggerTurnBackRoute(SimulationDataRepository repository, TrainInfo trainInfo, TripPlan tripPlan) {
Section eaStandSection = repository.getByCode(trainInfo.getEstimatedArriveStandTrack(), Section.class); // Section eaStandSection = repository.getByCode(trainInfo.getEstimatedArriveStandTrack(), Section.class);
Section arriveStandSection = repository.getByCode(trainInfo.getActualArriveStandTrack(), Section.class); // Section arriveStandSection = repository.getByCode(trainInfo.getActualArriveStandTrack(), Section.class);
if (tripPlan.isBehindTurnBack()) {// 是站后折返计划 // if (tripPlan.isBehindTurnBack()) {// 是站后折返计划
Section lastStationSection = tripPlan.getLastStationPlan().getSection(); // Section lastStationSection = tripPlan.getLastStationPlan().getSection();
if (lastStationSection.isSamePhysical(arriveStandSection.getCode())) { // if (lastStationSection.isSamePhysical(arriveStandSection.getCode())) {
// 列车达到计划终点站 // // 列车达到计划终点站
return true; // return true;
} else if (lastStationSection.isSamePhysical(eaStandSection.getCode())) { // } else if (lastStationSection.isSamePhysical(eaStandSection.getCode())) {
// 预计到达为终点站再判断是否到达折返始端信号机触发范围 // // 预计到达为终点站再判断是否到达折返始端信号机触发范围
List<RoutePath> list = repository.getRoutePaths(lastStationSection, tripPlan.getEndSection()); // List<RoutePath> list = repository.getRoutePaths(lastStationSection, tripPlan.getEndSection());
boolean right = list.get(0).isRight(); // boolean right = list.get(0).isRight();
Signal signal = lastStationSection.getSignalOf(right); // Signal signal = lastStationSection.getSignalOf(right);
//
// return true;
// }
// }
// return false;
// }
return true; // private List<Route> queryAccordingTbStrategy(SimulationDataRepository repository, TrainInfo trainInfo, TripPlan tripPlan) {
} // Section standSection = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class);
} // if (!standSection.isRouteLock()) {
return false; //
} // }
// Station station = standSection.getStation();
private List<Route> queryAccordingTbStrategy(SimulationDataRepository repository, TrainInfo trainInfo, TripPlan tripPlan) { // StationTurnBackStrategyOption strategy = station.getCurrentTurnBackStrategy();
Section standSection = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class); // Section tbSection = tripPlan.getEndSection();
if (!standSection.isRouteLock()) { // Route tbRoute = null;
// List<Section> tbSectionList = new ArrayList<>();
} // if (Objects.isNull(strategy)) {
Station station = standSection.getStation(); // tbSectionList.add(tbSection);
StationTurnBackStrategyOption strategy = station.getCurrentTurnBackStrategy(); // } else {
Section tbSection = tripPlan.getEndSection(); // switch (strategy.getType()) {
Route tbRoute = null; // // 按计划
List<Section> tbSectionList = new ArrayList<>(); // case NONE: {
if (Objects.isNull(strategy)) { // tbSectionList.add(tbSection);
tbSectionList.add(tbSection); // break;
} else { // }
switch (strategy.getType()) { // // 仅某个折返轨
// 按计划 // case ONLY: {
case NONE: { // tbSectionList.add(strategy.getSectionList().get(0));
tbSectionList.add(tbSection); // break;
break; // }
} // // 折返轨等价
// 仅某个折返轨 // case FIRST:
case ONLY: { // case EQUAL: {
tbSectionList.add(strategy.getSectionList().get(0)); // tbSectionList.addAll(strategy.getSectionList());
break; // break;
} // }
// 折返轨等价 // }
case FIRST: // }
case EQUAL: { // List<RoutePath> list = repository.getRoutePaths(standSection, tbSection);
tbSectionList.addAll(strategy.getSectionList()); // boolean right = list.get(0).isRight();
break; // Signal signal = standSection.getSignalOf(right);
} // if (!this.isApproachSignal(repository, trainInfo, signal)) {
} // return null;
} // }
List<RoutePath> list = repository.getRoutePaths(standSection, tbSection); // List<Route> routeList = signal.getRouteList();
boolean right = list.get(0).isRight(); // List<Route> tbRouteList = new ArrayList<>();
Signal signal = standSection.getSignalOf(right); // for (Route route : routeList) {
if (!this.isApproachSignal(repository, trainInfo, signal)) { // if (route.isTurnBack()) {
return null; // tbRouteList.add(route);
} // }
List<Route> routeList = signal.getRouteList(); // }
List<Route> tbRouteList = new ArrayList<>(); // if (!tbRouteList.isEmpty()) {
for (Route route : routeList) { // routeList = tbRouteList;
if (route.isTurnBack()) { // }
tbRouteList.add(route); // routeList = routeList.stream()
} // .filter(route -> !repository.hasSameStartTriggerRoute(trainInfo, route))
} // .filter(route -> route.containSameSection(tbSectionList))
if (!tbRouteList.isEmpty()) { // .collect(Collectors.toList());
routeList = tbRouteList; // return routeList;
} // }
routeList = routeList.stream()
.filter(route -> !repository.hasSameStartTriggerRoute(trainInfo, route))
.filter(route -> route.containSameSection(tbSectionList))
.collect(Collectors.toList());
return routeList;
}
} }

View File

@ -1,8 +1,10 @@
package club.joylink.rtss.simulation.cbtc.ATS.service.ars; package club.joylink.rtss.simulation.cbtc.ATS.service.ars;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository; import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
import club.joylink.rtss.simulation.cbtc.data.map.*; import club.joylink.rtss.simulation.cbtc.data.map.*;
import club.joylink.rtss.simulation.cbtc.data.plan.StationPlan;
import club.joylink.rtss.simulation.cbtc.data.support.RoutePath; import club.joylink.rtss.simulation.cbtc.data.support.RoutePath;
import club.joylink.rtss.simulation.cbtc.data.support.StationTurnBackStrategyOption; import club.joylink.rtss.simulation.cbtc.data.support.StationTurnBackStrategyOption;
import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo; import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo;
@ -23,53 +25,45 @@ public abstract class AtsRouteSelectService {
* 查询需要触发的进路 * 查询需要触发的进路
* *
* @param turnBackSection 站后折返的折返轨 * @param turnBackSection 站后折返的折返轨
* @param right 计划运行方向 * @return
*/ */
public Object[] queryTriggerRoutes(SimulationDataRepository repository, List<Section> targetList, public Route queryTriggerRoutes(SimulationDataRepository repository, List<Section> targetList,
TrainInfo trainInfo, Section turnBackSection, boolean right) { TrainInfo trainInfo, Section turnBackSection) {
if (trainInfo.getPlanStandTrack() == null) {
return null;
}
//寻找通向计划区段的进路
Section planSection = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class);
Section headSection = repository.getByCode(trainInfo.getPhysicalSection(), Section.class); Section headSection = repository.getByCode(trainInfo.getPhysicalSection(), Section.class);
Object[] result = {null, false, false}; List<RoutePath> routePaths = repository.queryRoutePathsByEndAndContainsSection(planSection, headSection);
int index = targetList.indexOf(planSection);
if (index == -1) {
return null;
}
Section nextPlanSection = null; //下一个计划区段
if (index < targetList.size() - 1) {
nextPlanSection = targetList.get(index + 1);
}
Route route = this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePaths, nextPlanSection);
if (route != null) { //有进路未触发
return route;
}
//通向计划区段的进路已全部办理根据条件尝试向下一个计划区段或站后折返轨办理进路
MapConfig config = repository.getConfig(); MapConfig config = repository.getConfig();
Section targetSection = null; if (!config.isSignalOpenAfterParking() || (headSection.equals(planSection) && trainInfo.isParking())) { //不需要停站就可以开放信号机或者已经在计划区段停站可以继续向前办理进路
Section nextTarget = null; if (nextPlanSection != null) { //计划区段路径未跑完
//选择目标区段 routePaths = repository.queryRoutePaths(planSection, nextPlanSection);
for (int i = targetList.size() - 1; i >= 0; i--) { if (!CollectionUtils.isEmpty(routePaths)) {
Section target = targetList.get(i); return this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePaths, nextPlanSection);
List<RoutePath> routePaths = repository.queryRoutePathsByEndAndContainsSection(target, headSection);
routePaths.removeIf(routePath -> routePath.isRight() != right);
if (!CollectionUtils.isEmpty(routePaths)) {
result = queryTriggerRoutesOfRoutePath(repository, trainInfo, routePaths);
targetSection = target;
if (i < targetList.size() - 1) {
nextTarget = targetList.get(i + 1);
} }
} else if (turnBackSection != null) { //站后折返
return queryTriggerRoutes4TurnBack(repository, planSection, turnBackSection, trainInfo);
} }
} }
//选择进路 return null;
boolean noRoute2Trigger = result != null && !(boolean) result[1] && !(boolean) result[2];
if (targetSection != null) {
if (!config.isSignalOpenAfterParking()) {
if (noRoute2Trigger) {
if (nextTarget != null) {
List<RoutePath> routePaths = repository.queryRoutePathsByEndAndContainsSection(nextTarget, headSection);
routePaths.removeIf(routePath -> routePath.isRight() != right);
result = this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePaths);
} else if (turnBackSection != null) {
List<Route> triggerRoutes = queryTriggerRoutes4TurnBack(repository, targetSection, turnBackSection, trainInfo);
return new Object[]{triggerRoutes, true};
}
}
} else {
if (nextTarget == null && targetSection.equals(headSection) && trainInfo.isParking()) {
List<Route> triggerRoutes = queryTriggerRoutes4TurnBack(repository, targetSection, turnBackSection, trainInfo);
return new Object[]{triggerRoutes, true};
}
}
}
return result;
} }
public List<Route> queryTriggerRoutes4TurnBack(SimulationDataRepository repository, Section standSection, Section tbSection, TrainInfo trainInfo) { public Route queryTriggerRoutes4TurnBack(SimulationDataRepository repository, Section standSection, Section tbSection, TrainInfo trainInfo) {
Station station = standSection.getStation(); Station station = standSection.getStation();
StationTurnBackStrategyOption strategy = station.getCurrentTurnBackStrategy(); StationTurnBackStrategyOption strategy = station.getCurrentTurnBackStrategy();
List<Section> tbSectionList = new ArrayList<>(); List<Section> tbSectionList = new ArrayList<>();
@ -115,7 +109,24 @@ public abstract class AtsRouteSelectService {
.filter(route -> !repository.hasSameStartTriggerRoute(trainInfo, route)) .filter(route -> !repository.hasSameStartTriggerRoute(trainInfo, route))
.filter(route -> route.containSameSection(tbSectionList)) .filter(route -> route.containSameSection(tbSectionList))
.collect(Collectors.toList()); .collect(Collectors.toList());
return routeList; Route route = null;
for (Route temp : routeList) {
List<Section> sectionList = temp.getSectionList();
boolean trainOccupy = false;
for (Section rs : sectionList) {
if (rs.isOccupied()) {
trainOccupy = true;
break;
}
}
if (trainOccupy) {
continue;
} else {
route = temp;
break;
}
}
return route;
} }
/** /**
@ -134,24 +145,11 @@ public abstract class AtsRouteSelectService {
return pathList.get(0); return pathList.get(0);
} }
public Object[] queryTriggerRoutesOfRoutePath(SimulationDataRepository repository, public Route queryTriggerRoutesOfRoutePath(SimulationDataRepository repository,
TrainInfo trainInfo, List<RoutePath> routePathList) { TrainInfo trainInfo, List<RoutePath> routePathList, Section nextPlanSection) {
Boolean right = trainInfo.getRight();
Section section = repository.getByCode(trainInfo.getPhysicalSection(), Section.class); // 列车所在区段 Section section = repository.getByCode(trainInfo.getPhysicalSection(), Section.class); // 列车所在区段
Section logicSection = repository.getByCode(trainInfo.getSection(), Section.class); Section planSection = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class); //列车计划区段
return queryTriggers(repository, trainInfo, routePathList, right, section, logicSection);
}
public Object[] queryTriggers(SimulationDataRepository repository, TrainInfo trainInfo, List<RoutePath> routePathList,
Boolean right, Section section, Section logicSection) {
Object[] result = new Object[3]; // 结果0为可触发的进路列表1为是否存在未触发的进路,2为是否存在未接近的信号机
List<Route> triggerList = new ArrayList<>(); List<Route> triggerList = new ArrayList<>();
result[0] = triggerList;
result[1] = false;
result[2] = false;
if (logicSection.isSwitchAxleCounterSection() || logicSection.isCross()) {
logicSection = section;
}
if (!routePathList.isEmpty()) { if (!routePathList.isEmpty()) {
RoutePath routePath = this.selectRoutePath(routePathList); RoutePath routePath = this.selectRoutePath(routePathList);
// 查找可以触发的进路列表 // 查找可以触发的进路列表
@ -164,7 +162,6 @@ public abstract class AtsRouteSelectService {
continue; continue;
} }
if (signal.hasCiAutoTriggerRoute() || signal.hasFleetModeRoute()) { if (signal.hasCiAutoTriggerRoute() || signal.hasFleetModeRoute()) {
result[2] = true; // 存在联锁自动触发进路或联锁自动进路
break; break;
} }
if (!ctcLevel && signal.isVirtual()) { if (!ctcLevel && signal.isVirtual()) {
@ -172,15 +169,15 @@ public abstract class AtsRouteSelectService {
} }
if (this.isApproachSignal(repository, trainInfo, signal)) { if (this.isApproachSignal(repository, trainInfo, signal)) {
// 是信号机接近区段 // 是信号机接近区段
if (signal.isNormalOpen()) { //如果信号机已经正常开放继续查询下一个 if (signal.isNormalOpen()) {
if (routePath.isPathRoute(signal.getLockedRoute())) { if (routePath.isPathRoute(signal.getLockedRoute())) {
continue; continue;
} else { } else {
result[2] = true; // 非路径进路办理 // 非路径进路办理
break; break;
} }
} else { } else {
result[1] = true; //筛选可触发的进路
for (Route route : routePath.getRouteList()) { for (Route route : routePath.getRouteList()) {
TrainInfo other = repository.querySameStartTriggerRouteTrain(trainInfo, route); TrainInfo other = repository.querySameStartTriggerRouteTrain(trainInfo, route);
if (other != null) { // 已经有在排列中的进路结束 if (other != null) { // 已经有在排列中的进路结束
@ -192,15 +189,40 @@ public abstract class AtsRouteSelectService {
triggerList.add(route); triggerList.add(route);
} }
} }
//选择要触发的进路
if (triggerList.size() == 1) {
return triggerList.get(0);
} else if (triggerList.size() > 1) {
if (planSection.equals(triggerList.get(0).getLastRouteSection()) && nextPlanSection != null) {
// 进路是计划站台轨根据后续计划筛选
List<RoutePath> routePaths = repository.getRoutePaths(planSection, nextPlanSection);
for (Route temp : triggerList) {
if (routePaths.get(0).containsAllSections(temp.getOverlap().getFirstPath().getSectionList())) {
return temp;
}
}
} else {
// 取第一个延续保护道岔定位的
for (Route temp : triggerList) {
List<SwitchElement> switchList = temp.getOverlap().getFirstPath().getSwitchList();
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertCollectionNotEmpty(switchList,
String.format("列车[%s]过滤进路异常:进路不是延续保护差异进路[%s]",
trainInfo.getGroupNumber(),
triggerList.stream().map(Route::getName).collect(Collectors.joining(","))));
if (switchList.get(0).isNormal()) {
return temp;
}
}
}
}
} }
} else { } else {
// 列车未接近此信号机 // 列车未接近此信号机
result[2] = true;
} }
break; break;
} }
} }
return result; return null;
} }
protected boolean isApproachSignal(SimulationDataRepository repository, TrainInfo trainInfo, Signal signal) { protected boolean isApproachSignal(SimulationDataRepository repository, TrainInfo trainInfo, Signal signal) {

View File

@ -6,14 +6,12 @@ import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.CalculateService; import club.joylink.rtss.simulation.cbtc.data.CalculateService;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository; import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
import club.joylink.rtss.simulation.cbtc.data.map.*; import club.joylink.rtss.simulation.cbtc.data.map.*;
import club.joylink.rtss.simulation.cbtc.data.support.RoutePath;
import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition; import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition;
import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo; import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo;
import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPService; import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPService;
import club.joylink.rtss.simulation.cbtc.onboard.ATP.OnboardAtpApiService; import club.joylink.rtss.simulation.cbtc.onboard.ATP.OnboardAtpApiService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.util.List; import java.util.List;
@ -45,7 +43,6 @@ public class AtsHeadTrainStageService implements AtsStageService {
DestinationCodeDefinition dcd = repository.findDestinationCodeDefinition(trainInfo.getDestinationCode()); DestinationCodeDefinition dcd = repository.findDestinationCodeDefinition(trainInfo.getDestinationCode());
if (dcd == null) if (dcd == null)
return; return;
SectionPosition headPosition = repository.buildHeadPositionOfTrainInfo(trainInfo);
if (Objects.equals(dcd.getSection(), parkSection)) { if (Objects.equals(dcd.getSection(), parkSection)) {
// 列车到达目的地 // 列车到达目的地
trainInfo.finishPlanPrepareInbound(); trainInfo.finishPlanPrepareInbound();
@ -64,7 +61,7 @@ public class AtsHeadTrainStageService implements AtsStageService {
if (Objects.equals(dcd.getSection(), parkSection)) { if (Objects.equals(dcd.getSection(), parkSection)) {
handleArriveDestination(simulation, trainInfo); handleArriveDestination(simulation, trainInfo);
} else { } else {
this.updateNextTarget(simulation, trainInfo); this.updatePlanSection(simulation, trainInfo);
} }
} }
@ -74,13 +71,13 @@ public class AtsHeadTrainStageService implements AtsStageService {
if (Objects.equals(dcd.getSection(), parkSection)) { if (Objects.equals(dcd.getSection(), parkSection)) {
handleArriveDestination(simulation, trainInfo); handleArriveDestination(simulation, trainInfo);
} else { } else {
this.updateNextTarget(simulation, trainInfo); this.updatePlanSection(simulation, trainInfo);
} }
} }
@Override @Override
public void handlePassStand(Simulation simulation, TrainInfo trainInfo) { public void handlePassStand(Simulation simulation, TrainInfo trainInfo) {
this.updateNextTarget(simulation, trainInfo); this.updatePlanSection(simulation, trainInfo);
} }
/** /**
@ -92,92 +89,53 @@ public class AtsHeadTrainStageService implements AtsStageService {
} }
} }
private void updateNextTarget(Simulation simulation, TrainInfo trainInfo) { private void updatePlanSection(Simulation simulation, TrainInfo trainInfo) {
boolean right = trainInfo.getRight(); if (!StringUtils.hasText(trainInfo.getPlanStandTrack()))
return;
boolean planRight = trainInfo.getHctPath().isRight();
SimulationDataRepository repository = simulation.getRepository(); SimulationDataRepository repository = simulation.getRepository();
SectionPosition headPosition = repository.buildHeadPositionOfTrainInfo(trainInfo); SectionPosition headPosition = repository.buildHeadPositionOfTrainInfo(trainInfo);
Section planSection = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class);
//如果还未到达目标轨 //如果还未到达目标轨
Section headSection = headPosition.getSection(); Section headSection = headPosition.getSection();
if (StringUtils.hasText(trainInfo.getEstimatedArriveStandTrack())) { if (!planSection.equals(headSection) && planSection.isAheadOf(repository, headSection, planRight)) {
Section target = repository.getByCode(trainInfo.getEstimatedArriveStandTrack(), Section.class); return;
if (!target.equals(headSection) && target.isAheadOf(repository, headSection, right)) {
return;
}
} }
//寻找目标区段 //寻找目标区段
Section nextTarget = queryNextTarget(simulation, headPosition.getSection(), trainInfo, right); Section nextPlanSection = queryNextPlanSection(simulation, trainInfo);
if (nextTarget == null) if (nextPlanSection == null)
return; return;
//判断调头 //判断调头
if (!nextTarget.isAheadOf(repository, headSection, right)) {//下一目标区段不在当前车头方向的前方 Boolean trainRight = trainInfo.getRight();
if (!nextPlanSection.isAheadOf(repository, headSection, trainRight)) {//下一计划区段不在当前车头方向的前方
atpService.turnDirectionImmediately(repository.getOnlineTrainBy(trainInfo.getGroupNumber())); //调头 atpService.turnDirectionImmediately(repository.getOnlineTrainBy(trainInfo.getGroupNumber())); //调头
} }
//更新计到站 //更新到站
SectionPosition stopPosition = new SectionPosition(nextTarget, nextTarget.getStopPointByDirection(right)); SectionPosition stopPosition = new SectionPosition(nextPlanSection, nextPlanSection.getStopPointByDirection(planRight));
Float distance = CalculateService.calculateDistance(headPosition, stopPosition, right); Float distance = CalculateService.calculateDistance(headPosition, stopPosition, planRight);
int runningTime; int runningTime;
if (distance != null) { if (distance != null) {
runningTime = (int) (distance / (45 / 3.6)); runningTime = (int) (distance / (45 / 3.6));
} else { } else {
runningTime = 180; runningTime = 180;
} }
trainInfo.updatePlanInfo(nextTarget, null, null); trainInfo.updatePlanInfo(nextPlanSection, null, null);
// trainInfo.updateEstimatedArriveInfo(nextTarget, simulation.getSystemTime().toLocalTime().plusSeconds(runningTime)); boolean jump = this.atsStandService.isJump(nextPlanSection, trainInfo.getGroupNumber());
boolean jump = this.atsStandService.isJump(nextTarget, trainInfo.getGroupNumber()); onboardAtpApiService.updateNextArriveInfo(simulation, trainInfo.getGroupNumber(), nextPlanSection, true, runningTime, jump);
onboardAtpApiService.updateNextArriveInfo(simulation, trainInfo.getGroupNumber(), nextTarget, true, runningTime, jump);
} }
public static Section queryNextTarget(Simulation simulation, Section headSection, TrainInfo trainInfo, Boolean right) { public static Section queryNextPlanSection(Simulation simulation, TrainInfo trainInfo) {
SimulationDataRepository repository = simulation.getRepository(); if (trainInfo.getPlanStandTrack() == null) {
List<Section> targetList = trainInfo.getHeadPath().getSectionList(); return null;
for (int i = targetList.size() - 1; i >= 0; i--) { }
Section target = targetList.get(i); SimulationDataRepository repository = simulation.getRepository();
List<RoutePath> routePaths = repository.queryRoutePathsByEndAndContainsSection(target, headSection); List<Section> targetList = trainInfo.getHctPath().getSections();
if (!CollectionUtils.isEmpty(routePaths)) { Section planSection = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class);
return target; int index = targetList.indexOf(planSection);
} if (index == -1 || index == targetList.size() - 1) {
return null;
} else {
return targetList.get(index + 1);
} }
return null;
// SimulationDataRepository repository = simulation.getRepository();
// String dc = trainInfo.getDestinationCode();
// List<Routing> routings = repository.queryRoutingByDestCode(dc);
// Section nextSection = null;
// if (!CollectionUtils.isEmpty(routings)) { //目的地码在区段上
// for (Routing routing : routings) {
// if (headSection.isTurnBackTrack()) { //是折返轨不限制方向
// nextSection = routing.queryNextSection(headSection);
// if (nextSection != null)
// break;
// for (Section s : routing.getAllSections()) {
// List<RoutePath> routePaths = repository.queryRoutePathsByEndAndContainsSection(s, headSection);
// if (!CollectionUtils.isEmpty(routePaths)) {
// if (routePaths.stream().anyMatch(routePath -> routePath.isRight() == routing.isRight())) {
// return s;
// }
// }
// }
// } else { //不是折返轨必须和列车同向
// if (routing.isRight() == right) {
// nextSection = routing.queryNextSection(headSection);
// if (nextSection != null)
// break;
// for (Section s : routing.getAllSections()) {
// List<RoutePath> routePaths = repository.queryRoutePathsByEndAndContainsSection(s, headSection);
// if (routePaths.stream().anyMatch(routePath -> routePath.isRight() == right)) {
// return s;
// }
// }
// }
// }
// }
// } else {
// DestinationCodeDefinition dcd = repository.findDestinationCodeDefinition(dc);
// if (dcd == null)
// return null;
// nextSection = AtsTrainService.findNextTarget4HeadTrain(simulation, trainInfo, repository, headSection, headSection.getStation(), dcd);
// }
// return nextSection;
} }
} }

View File

@ -280,15 +280,18 @@ public class RouteService {
// 进路内区段占用检查 // 进路内区段占用检查
List<Section> sectionList = route.getSectionList(); List<Section> sectionList = route.getSectionList();
for (Section section : sectionList) { for (Section section : sectionList) {
if (section.isOccupied() && !section.isPreReset()) { if (section.isOccupied()) {
if (section.isSwitchTrack()) { return new Route.CheckFailMessage(Route.CheckFailReason.SectionNotFree, section);
if (!section.getRelSwitch().isPreReset()) {
return new Route.CheckFailMessage(Route.CheckFailReason.SectionNotFree, section);
}
} else {
return new Route.CheckFailMessage(Route.CheckFailReason.SectionNotFree, section);
}
} }
// if (section.isOccupied() && !section.isPreReset()) {
// if (section.isSwitchTrack()) {
// if (!section.getRelSwitch().isPreReset()) {
// return new Route.CheckFailMessage(Route.CheckFailReason.SectionNotFree, section);
// }
// } else {
// return new Route.CheckFailMessage(Route.CheckFailReason.SectionNotFree, section);
// }
// }
} }
// 延续保护检查 // 延续保护检查
RouteOverlap overlap = route.getOverlap(); RouteOverlap overlap = route.getOverlap();

View File

@ -186,7 +186,7 @@ public class CommandBO {
if (!train.isStopAtThePosition(driveStep.getTargetPosition())) { //如果列车没停到目标位置 if (!train.isStopAtThePosition(driveStep.getTargetPosition())) { //如果列车没停到目标位置
if (!train.isStop()) if (!train.isStop())
return buildDriverForceChangeOperationStep(train.getGroupNumber(), -1); return buildDriverForceChangeOperationStep(train.getGroupNumber(), -1);
if (!DriveMode.RM.equals(train.getDriveMode())) if (!DriveMode.RM.equals(train.getDriveMode()) && !train.isNRMMode())
return buildDriverDriveModeChangeOperationStep(train.getGroupNumber(), DriveMode.RM); return buildDriverDriveModeChangeOperationStep(train.getGroupNumber(), DriveMode.RM);
if (train.isEB()) if (train.isEB())
return buildReleaseEBStep(train); return buildReleaseEBStep(train);
@ -305,7 +305,7 @@ public class CommandBO {
// command.getTargetMember().setCommand(null); // command.getTargetMember().setCommand(null);
// } // }
} else { } else {
if (!DriveMode.RM.equals(train.getDriveMode())) { if (!DriveMode.RM.equals(train.getDriveMode()) && !train.isNRMMode()) {
return buildDriverDriveModeChangeOperationStep(train.getGroupNumber(), DriveMode.RM); return buildDriverDriveModeChangeOperationStep(train.getGroupNumber(), DriveMode.RM);
} }
if (train.isSignalEB()) { if (train.isSignalEB()) {

View File

@ -0,0 +1,17 @@
package club.joylink.rtss.simulation.cbtc.data.map;
import lombok.Getter;
import java.util.List;
@Getter
public class SectionRunPath {
private List<Section> sections;
private boolean right;
public SectionRunPath(List<Section> sections, boolean right) {
this.sections = sections;
this.right = right;
}
}

View File

@ -38,7 +38,7 @@ public class PSDStatus extends DeviceStatus {
public PSDStatus(PSD psd) { public PSDStatus(PSD psd) {
super(psd.getCode(), psd.getDeviceType()); super(psd.getCode(), psd.getDeviceType());
this.close = psd.isClose(); this.close = psd.isCloseAndLock();
// this.lock = psd.isLock(); // this.lock = psd.isLock();
this.interlockRelease = psd.isInterlockRelease(); this.interlockRelease = psd.isInterlockRelease();
this.noStatus = psd.isNoStatus(); this.noStatus = psd.isNoStatus();
@ -49,8 +49,8 @@ public class PSDStatus extends DeviceStatus {
PSD psd = (PSD) device; PSD psd = (PSD) device;
PSDStatusVO status = (PSDStatusVO)statusVO; PSDStatusVO status = (PSDStatusVO)statusVO;
boolean change = false; boolean change = false;
if (!Objects.equals(this.close, psd.isClose())) { if (!Objects.equals(this.close, psd.isCloseAndLock())) {
this.close = psd.isClose(); this.close = psd.isCloseAndLock();
status.setClose(this.close); status.setClose(this.close);
change = true; change = true;
} }

View File

@ -253,7 +253,7 @@ public class RoutePath {
return new SectionPosition(section, offset); return new SectionPosition(section, offset);
} }
public Route queryRouteContainsSection(RunLevel runLevel, Section section, MapConfig config) { public Route queryRouteContainsSection(boolean communication, Section section, MapConfig config) {
for (Signal signal : this.signalList) { for (Signal signal : this.signalList) {
List<Route> routeList = signal.getRouteList(); List<Route> routeList = signal.getRouteList();
if (CollectionUtils.isEmpty(routeList)) { if (CollectionUtils.isEmpty(routeList)) {
@ -261,11 +261,11 @@ public class RoutePath {
} }
for (Route route : routeList) { for (Route route : routeList) {
if (config.isRouteLikeHa1()) { if (config.isRouteLikeHa1()) {
if (Objects.equals(runLevel, RunLevel.CBTC)) { // ctc级别列车找ATP进路 if (communication) { // 通信车找ATP进路
if (!route.isAtp()) { if (!route.isAtp()) {
continue; continue;
} }
} else { // CTC列车找地面进路 } else { // 通信车找地面进路
if (!route.isGround()) { if (!route.isGround()) {
continue; continue;
} }

View File

@ -206,7 +206,7 @@ public class TrainInfo extends MapElement {
* 头码车的区段路径 * 头码车的区段路径
*/ */
@Setter @Setter
private SectionPath headPath; private SectionRunPath hctPath;
/** /**
* 下令停车 * 下令停车
@ -244,29 +244,21 @@ public class TrainInfo extends MapElement {
*/ */
@Setter @Setter
private String turnBackStatus = NON; private String turnBackStatus = NON;
/** /** 无折返 */
* 无折返
*/
public static String NON = "NON"; public static String NON = "NON";
/** /** 初始化 */
* 初始化
*/
public static String INIT = "INIT"; public static String INIT = "INIT";
/** /** 开往折返轨 */
* 开往折返轨
*/
public static String TO = "TO"; public static String TO = "TO";
/** /** 到达折返轨停稳 */
* 到达折返轨停稳
*/
public static String STOP = "STOP"; public static String STOP = "STOP";
/** /** 开出折返轨 */
* 开出折返轨
*/
public static String EXIT = "EXIT"; public static String EXIT = "EXIT";
/** ATS为此列车触发的进路 */ /** ATS为此列车触发的进路 */
private Map<String, Route> atsTriggerRouteMap = new ConcurrentHashMap<>(); private Map<String, Route> atsTriggerRouteMap = new ConcurrentHashMap<>();
private boolean communication;
public TrainInfo(String groupNumber) { public TrainInfo(String groupNumber) {
super(groupNumber, DeviceType.TRAIN); super(groupNumber, DeviceType.TRAIN);
this.groupNumber = groupNumber; this.groupNumber = groupNumber;
@ -383,7 +375,7 @@ public class TrainInfo extends MapElement {
this.offsetp = headPosition.getPercent(); this.offsetp = headPosition.getPercent();
if (headPosition.getSection().isSwitchTrack()) { if (headPosition.getSection().isSwitchTrack()) {
this.section = headPosition.getSection().getParent().getCode(); this.section = headPosition.getSection().getParent().getCode();
} else if (this.isCtcLevel()) { } else if (this.isCommunication()) {
this.section = headPosition.getLogicSection().getCode(); this.section = headPosition.getLogicSection().getCode();
} else { } else {
this.section = headPosition.getSection().getCode(); this.section = headPosition.getSection().getCode();
@ -408,6 +400,7 @@ public class TrainInfo extends MapElement {
} else if (speed != 0 && this.turnBackStatus.equals(STOP)) { } else if (speed != 0 && this.turnBackStatus.equals(STOP)) {
this.turnBackStatus = EXIT; this.turnBackStatus = EXIT;
} }
this.communication = train.isCommunication();
} }
public boolean isCtcLevel() { public boolean isCtcLevel() {

View File

@ -99,7 +99,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
/** /**
* 车载服务通讯是否正常在线 * 车载服务通讯是否正常在线
*/ */
private boolean online; private boolean communication;
/** /**
* 列车运行级别 * 列车运行级别
@ -111,6 +111,11 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
*/ */
private DriveMode driveMode; private DriveMode driveMode;
/**
* 预选驾驶模式
*/
private DriveMode preDriveMode;
/** /**
* 服务号 * 服务号
*/ */
@ -400,6 +405,12 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
*/ */
private int runningTime; private int runningTime;
public void setCommunication(boolean communication) {
if (Fault.COMMUNICATION_ABNORMAL.equals(this.fault) && communication)
return;
this.communication = communication;
}
public void setRunType(RunType runType) { public void setRunType(RunType runType) {
this.runType = runType; this.runType = runType;
switch (runType) { switch (runType) {
@ -446,8 +457,10 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
@Override @Override
public void reset() { public void reset() {
this.communication = true;
this.runLevel = null; this.runLevel = null;
this.driveMode = null; this.driveMode = null;
this.preDriveMode = null;
this.serviceNumber = null; this.serviceNumber = null;
this.tripNumber = null; this.tripNumber = null;
this.destinationCode = null; this.destinationCode = null;
@ -569,11 +582,13 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
} }
private void init() { private void init() {
this.communication = true;
this.jump = false; this.jump = false;
this.hold = false; this.hold = false;
this.standParkedTrainActivity = null; this.standParkedTrainActivity = null;
this.runLevel = RunLevel.CBTC; this.runLevel = RunLevel.CBTC;
this.driveMode = DriveMode.AM; this.driveMode = DriveMode.AM;
this.preDriveMode = DriveMode.AM;
this.speed = 0; this.speed = 0;
this.atoSpeed = 0; this.atoSpeed = 0;
this.atpSpeed = 0; this.atpSpeed = 0;
@ -713,8 +728,9 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
// this.setSignalEB(false); // this.setSignalEB(false);
this.setAtoOn(false); this.setAtoOn(false);
this.setDriveMode(DriveMode.RM); this.setDriveMode(DriveMode.RM);
setCommunication(false); //断开通信
// this.lossPosition(); // this.lossPosition();
this.setCbtcMaMiss(); //通信断开 // this.setCbtcMaMiss(); //通信断开
// this.lastTwoPassedResponders.clear(); // this.lastTwoPassedResponders.clear();
// if (RunLevel.CBTC.equals(this.runLevel)) { // if (RunLevel.CBTC.equals(this.runLevel)) {
// this.setCbtcMaMiss(); // this.setCbtcMaMiss();
@ -728,7 +744,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
public void useCMMode() { public void useCMMode() {
if (!this.isAtpOn()) { if (!this.isAtpOn()) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, String.format("列车[%s]未打开ATP", this.getCode())); return;
} }
this.atoOn = false; this.atoOn = false;
this.driveMode = DriveMode.CM; this.driveMode = DriveMode.CM;
@ -736,12 +752,13 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
public void useAMMode() { public void useAMMode() {
if (!atoOn) { if (!atoOn) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, String.format("列车[%s]未打开ATO", this.getCode())); return;
} }
if (!this.isAtpOn()) { if (!this.isAtpOn()) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, String.format("列车[%s]未打开ATP", this.getCode())); return;
} }
this.driveMode = DriveMode.AM; this.driveMode = DriveMode.AM;
setCommunication(true);
} }
public void useNRMMode() { public void useNRMMode() {
@ -755,9 +772,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
return; return;
} }
this.driveMode = DriveMode.NRM; this.driveMode = DriveMode.NRM;
if (RunLevel.CBTC.equals(this.runLevel)) { setCommunication(false);
this.setCbtcMaMiss();
}
} }
public void setITCMode() { public void setITCMode() {
@ -1113,13 +1128,15 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
public boolean isCommunicable() { public boolean isCommunicable() {
Section section = headPosition.getSection(); Section section = headPosition.getSection();
Station deviceStation = section.getDeviceStation(); return communication && section.anyZcWorking();
if (VirtualRealityTrain.Fault.COMMUNICATION_ABNORMAL == fault
|| Station.Fault.INTERLOCK_MACHINE_FAULT == deviceStation.getFault() // Station deviceStation = section.getDeviceStation();
|| !section.anyZcWorking()) { // if (VirtualRealityTrain.Fault.COMMUNICATION_ABNORMAL == fault
return false; // || Station.Fault.INTERLOCK_MACHINE_FAULT == deviceStation.getFault()
} // || !section.anyZcWorking()) {
return true; // return false;
// }
// return true;
} }
public boolean isCMMode() { public boolean isCMMode() {
@ -1135,26 +1152,27 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
* 通信异常 * 通信异常
*/ */
COMMUNICATION_ABNORMAL { COMMUNICATION_ABNORMAL {
// @Override @Override
// public boolean apply(MapElement device) { public boolean apply(MapElement device) {
// VirtualRealityTrain train = (VirtualRealityTrain) device; if (super.apply(device)) {
// if (Objects.equals(this, train.getFault())) { VirtualRealityTrain train = (VirtualRealityTrain) device;
// return false; train.setCommunication(false);
// } return true;
// train.setFault(this); }
// train.lossPosition(); return false;
// return true; }
// }
}, },
/** 驾驶异常 */ /** 驾驶异常 */
DRIVE_FAULT { DRIVE_FAULT {
@Override @Override
public boolean apply(MapElement device) { public boolean apply(MapElement device) {
super.apply(device); if (super.apply(device)) {
VirtualRealityTrain train = (VirtualRealityTrain) device; VirtualRealityTrain train = (VirtualRealityTrain) device;
train.emergencyBreak(); //暂时就在这里直接处理可能正常应该是ATP的责任 train.emergencyBreak(); //暂时就在这里直接处理可能正常应该是ATP的责任
return true; return true;
}
return false;
} }
}, },

View File

@ -49,9 +49,10 @@ public class ATOService {
} }
if (Objects.nonNull(train.getMa())) { if (Objects.nonNull(train.getMa())) {
train.setAtoOn(true); train.setAtoOn(true);
if (DriveMode.CM.equals(train.getDriveMode())) { train.setPreDriveMode(DriveMode.AM);
train.useAMMode(); // if (DriveMode.CM.equals(train.getDriveMode())) {
} // train.useAMMode();
// }
} }
} }

View File

@ -3,10 +3,7 @@ package club.joylink.rtss.simulation.cbtc.onboard.ATP;
import club.joylink.rtss.simulation.cbtc.ATP.ground.GroundAtpApiService; import club.joylink.rtss.simulation.cbtc.ATP.ground.GroundAtpApiService;
import club.joylink.rtss.simulation.cbtc.ATS.AtsApiService; import club.joylink.rtss.simulation.cbtc.ATS.AtsApiService;
import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.constant.ControlGear; import club.joylink.rtss.simulation.cbtc.constant.*;
import club.joylink.rtss.simulation.cbtc.constant.RunLevel;
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
import club.joylink.rtss.simulation.cbtc.constant.SimulationModule;
import club.joylink.rtss.simulation.cbtc.data.CalculateService; import club.joylink.rtss.simulation.cbtc.data.CalculateService;
import club.joylink.rtss.simulation.cbtc.data.map.Section; import club.joylink.rtss.simulation.cbtc.data.map.Section;
import club.joylink.rtss.simulation.cbtc.data.map.Stand; import club.joylink.rtss.simulation.cbtc.data.map.Stand;
@ -109,6 +106,7 @@ public class ATPLogicLoop {
private void onboardLogicRun2(Simulation simulation, VirtualRealityTrain train) { private void onboardLogicRun2(Simulation simulation, VirtualRealityTrain train) {
this.runLevelControl(simulation, train); this.runLevelControl(simulation, train);
this.driveModeControl(simulation, train);
boolean right = train.isRight(); boolean right = train.isRight();
SectionPosition headPosition = train.getHeadPosition(); SectionPosition headPosition = train.getHeadPosition();
@ -183,6 +181,33 @@ public class ATPLogicLoop {
this.atoService.ATO(train); this.atoService.ATO(train);
} }
private void driveModeControl(Simulation simulation, VirtualRealityTrain train) {
DriveMode preDriveMode = train.getPreDriveMode();
DriveMode driveMode = train.getDriveMode();
if (preDriveMode.equals(driveMode))
return;
switch (preDriveMode) {
case AM:
train.setCommunication(true); //恢复列车通信
if (train.isCMMode() && train.isAtoOn()) {
train.useAMMode();
}
break;
case CM:
train.setCommunication(true); //恢复列车通信
if (!train.isCbtcMaMiss() || !train.isItcMaMiss()) { //CBTC或ITC的移动授权未丢失
Float distance = ATOService.calculateDistanceOfMa(train.getHeadPosition(), train.isRight(), train.getMa());
if (distance != null && distance > 0) { //移动授权的距离为正
train.useCMMode();
}
}
break;
case RM:
train.useRMMode();
break;
}
}
private void updateRunningTime(VirtualRealityTrain train) { private void updateRunningTime(VirtualRealityTrain train) {
if (train.isParkingAt()) { if (train.isParkingAt()) {
train.setRunningTime(0); train.setRunningTime(0);

View File

@ -16,11 +16,6 @@ public interface OnboardAtpApiService {
*/ */
void updateMA4CBTC(VirtualRealityTrain train, MovementAuthority ma); void updateMA4CBTC(VirtualRealityTrain train, MovementAuthority ma);
/**
* 忽略驾驶模式更新CBTC移动授权
*/
boolean ignoreDriveModeUpdateMA4CBTC(VirtualRealityTrain train, MovementAuthority ma);
void updateMA4ITC(VirtualRealityTrain train, MovementAuthority ma); void updateMA4ITC(VirtualRealityTrain train, MovementAuthority ma);
/** /**

View File

@ -37,30 +37,10 @@ public class OnboardAtpApiServiceImpl implements OnboardAtpApiService {
if (!train.isAtpOn()) { if (!train.isAtpOn()) {
return; return;
} }
if (train.getFault() == VirtualRealityTrain.Fault.COMMUNICATION_ABNORMAL) { //列车通信故障 if (train.isCommunication()) {
return;
}
if (train.isRMMode() || train.isNRMMode())
return;
if (train.isCBTC()) {
this.ATPService.updateMA(train, ma); this.ATPService.updateMA(train, ma);
train.setCbtcMaMissDuration(0);
} }
train.setCbtcMaMissDuration(0);
}
@Override
public boolean ignoreDriveModeUpdateMA4CBTC(VirtualRealityTrain train, MovementAuthority ma) {
if (ma == null)
return false;
if (!train.isAtpOn()) {
return false;
}
if (train.getFault() == VirtualRealityTrain.Fault.COMMUNICATION_ABNORMAL) { //列车通信故障
return false;
}
this.ATPService.updateMA(train, ma);
train.setCbtcMaMissDuration(0);
return true;
} }
@Override @Override
@ -70,7 +50,7 @@ public class OnboardAtpApiServiceImpl implements OnboardAtpApiService {
if (!train.isAtpOn()) { if (!train.isAtpOn()) {
return; return;
} }
if (!train.isCBTC()) { if (!train.isCommunication()) {
this.ATPService.updateMA(train, ma); this.ATPService.updateMA(train, ma);
train.setItcMaMissDuration(0); train.setItcMaMissDuration(0);
} }

View File

@ -13,4 +13,7 @@ public class DisplayVO {
private List<String> stationCodeList; private List<String> stationCodeList;
private List<String> elementList; private List<String> elementList;
/** 可切换显示的车站 */
private List<String> switchStationCodeList;
} }