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

View File

@ -74,35 +74,13 @@ public class ZCLogicLoop {
}));
}
//更新CBTC ma
if (headPosition.getSection().anyZcWorking()) {
if (train.isCommunicable()) {
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,
List<VirtualRealityTrain> trainList) {
// 查找移动授权终端列表
@ -154,14 +132,9 @@ public class ZCLogicLoop {
// }
//非通信车占用区段
if (section.isNonCbtcOccupy() && !section.isInvalid()) {
VirtualRealitySectionAxleCounter axle = section.getVirtualAxleCounter();
if (axle == null && section.getParent() != null)
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());
Set<Section> occupiedLogicSectionSet;
@ -236,7 +209,7 @@ public class ZCLogicLoop {
if (trainEnd != null)
endList.add(trainEnd);
//非通信车占用区段
if (temp.isNonCbtcOccupy() && !temp.isInvalid()) {
if (temp.isNctOccupied() && !temp.isInvalid()) {
endList.add(new MovementAuthority.End(temp, MovementAuthority.EndType.NCT_OCCUPIED_SECTION));
}
//检查关闭的区段
@ -696,7 +669,7 @@ public class ZCLogicLoop {
if (section.isStandTrack()) {
List<Stand> standList = section.getStandList();
for (Stand stand : standList) {
if (!stand.isInterlockRelease() && stand.isPsdOpen()) {
if (!stand.isPsdSafe()) {
return new MovementAuthority.End(stand, MovementAuthority.EndType.OPENED_PSD, section);
}
if (stand.isClosed()) {

View File

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

View File

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

View File

@ -593,7 +593,7 @@ public class AtsTrainLoadService {
Section end = viaSectionList.get(i);
// 取相邻两区段的路径单元查询进路
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)) {
// 排列好进路
this.deviceStatusModifyTool.openRouteDirect(simulation, route);

View File

@ -308,8 +308,7 @@ public class AtsTrainService {
if (!sections.get(0).equals(headSection)) {
sections.add(0, headSection);
}
SectionPath headPath = new SectionPath(selectRouting.isRight(), null, sections, null);
supervisedTrain.setHeadPath(headPath);
supervisedTrain.setHctPath(new SectionRunPath(sections, selectRouting.isRight()));
break;
default:
throw new SimulationException(SimulationExceptionType.System_Fault, String.format("无法识别的目的地码类型[%s]", destinationCodeDefinition.getType()));
@ -675,7 +674,7 @@ public class AtsTrainService {
}
break;
case OTHER:
List<Section> path = train.getHeadPath().getSectionList();
List<Section> path = train.getHctPath().getSections();
if (path != null) {
int index = path.indexOf(headSection);
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.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.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 lombok.extern.slf4j.Slf4j;
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;
}
SimulationDataRepository repository = simulation.getRepository();
// 基础检查
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;
return queryTriggerRoutes(repository, trainInfo.getHctPath().getSections(), trainInfo, null);
}
}

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.TripPlan;
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 lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@ -44,13 +43,12 @@ public class AtsPlanTrainRouteSelectServiceImpl extends AtsRouteSelectService {
LocalDateTime systemTime = simulation.getSystemTime();
// 根据车次计划查找可触发进路列表
// 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 route;
return filterRoutes(simulation, trainInfo, tripPlan, 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();
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());
if (tripPlan.isBehindTurnBack()) {
return queryTriggerRoutes(repository, targetList, trainInfo, tripPlan.getEndSection(), tripPlan.isRight());
return queryTriggerRoutes(repository, targetList, trainInfo, tripPlan.getEndSection());
} 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 trainInfo
* @param tripPlan
* @param results
* @param route
* @return
*/
private Route filterRoutes(Simulation simulation,
TrainInfo trainInfo, TripPlan tripPlan, Object[] results) {
if (results == null) {
return null;
}
List<Route> triggerList = (List<Route>) results[0];
if (CollectionUtils.isEmpty(triggerList)) {
TrainInfo trainInfo, TripPlan tripPlan, Route route) {
if (route == null) {
return null;
}
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()));
if (route.isCheckConflict() && route.getConflictAlarm() == null) {
ConflictInfo conflictInfo = this.checkConflict(repository, trainInfo, tripPlan, route);
@ -432,147 +421,147 @@ public class AtsPlanTrainRouteSelectServiceImpl extends AtsRouteSelectService {
return route;
}
/**
* @return (List<Route>)[0] 可触发的进路(Boolean)[1]是否需要折返
*/
private Object[] queryByStationPlan(SimulationDataRepository repository, LocalDateTime systemTime, TrainInfo trainInfo, TripPlan tripPlan) {
Route route = null;
Object[] result = new Object[3];
result[1] = false;
result[2] = false;
List<Route> triggerList = null;
// 获取列车上一停靠站台轨和下一计划达到轨道结合列车位置查询需要办理的进路
if (trainInfo.getPlanStandTrack() == null) { // 列车下一计划存在
return null;
}
// 计划时间
List<StationPlan> planList = tripPlan.getPlanList();
LocalTime startTime = tripPlan.getStartTime();
for (StationPlan stationPlan : planList) {
if (stationPlan.getSection().getCode().equals(trainInfo.getPlanStandTrack())) {
break;
}
startTime = stationPlan.getLeaveTime();
}
if (!systemTime.toLocalTime().plusSeconds(50).isAfter(startTime)) {
log.debug(String.format("列车[%s]未到发车时间,不触发进路", trainInfo.getGroupNumber()));
return null;
}
Section planTrack = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class);//下一计划
Section section = repository.getByCode(trainInfo.getPhysicalSection(), Section.class); // 列车所在区段
if (!planTrack.isSamePhysical(section.getCode())) {
List<RoutePath> routePathList = repository.queryRoutePathsByEnd(planTrack);
routePathList = routePathList.stream()
.filter(routePath -> routePath.containsSection(section))
.collect(Collectors.toList());
result = this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePathList);
}
if (!((boolean) result[1]) && !((boolean) result[2])) { // 不存在未开放进路,且不存在未接近的信号机
// 判断配置是否列车停站才触发接下来的进路
MapConfig config = repository.getConfig();
if (config.isSignalOpenAfterParking() && !trainInfo.isParking()) {
return null;
} else {
if (tripPlan.isLastPlanStationSection(planTrack)) {
//是计划的终点站
if (tripPlan.isBehindTurnBack()) {
// 是站后折返
triggerList = this.queryAccordingTbStrategy(repository, trainInfo, tripPlan);
Object[] rs = {triggerList, true};
return rs;
} else if (!tripPlan.getEndSection().equals(tripPlan.getLastStationPlan().getSection())) {
// 备用车
List<RoutePath> routePathList = repository.getRoutePaths(tripPlan.getLastStationPlan().getSection(),
tripPlan.getEndSection());
result = this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePathList);
}
} else {
StationPlan nextStationPlan = tripPlan.queryNextStationPlan(planTrack);
if (nextStationPlan != null) {
// 下一计划车站存在
List<RoutePath> routePathList = repository.getRoutePaths(planTrack, nextStationPlan.getSection());
result = this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePathList);
}
}
}
}
triggerList = (List<Route>) result[0];
Object[] rs = {triggerList, false};
return rs;
}
// /**
// * @return (List<Route>)[0] 可触发的进路(Boolean)[1]是否需要折返
// */
// private Object[] queryByStationPlan(SimulationDataRepository repository, LocalDateTime systemTime, TrainInfo trainInfo, TripPlan tripPlan) {
// Route route = null;
// Object[] result = new Object[3];
// result[1] = false;
// result[2] = false;
// List<Route> triggerList = null;
// // 获取列车上一停靠站台轨和下一计划达到轨道结合列车位置查询需要办理的进路
// if (trainInfo.getPlanStandTrack() == null) { // 列车下一计划存在
// return null;
// }
// // 计划时间
// List<StationPlan> planList = tripPlan.getPlanList();
// LocalTime startTime = tripPlan.getStartTime();
// for (StationPlan stationPlan : planList) {
// if (stationPlan.getSection().getCode().equals(trainInfo.getPlanStandTrack())) {
// break;
// }
// startTime = stationPlan.getLeaveTime();
// }
// if (!systemTime.toLocalTime().plusSeconds(50).isAfter(startTime)) {
// log.debug(String.format("列车[%s]未到发车时间,不触发进路", trainInfo.getGroupNumber()));
// return null;
// }
// Section planTrack = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class);//下一计划
// Section section = repository.getByCode(trainInfo.getPhysicalSection(), Section.class); // 列车所在区段
// if (!planTrack.isSamePhysical(section.getCode())) {
// List<RoutePath> routePathList = repository.queryRoutePathsByEnd(planTrack);
// routePathList = routePathList.stream()
// .filter(routePath -> routePath.containsSection(section))
// .collect(Collectors.toList());
// result = this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePathList);
// }
// if (!((boolean) result[1]) && !((boolean) result[2])) { // 不存在未开放进路,且不存在未接近的信号机
// // 判断配置是否列车停站才触发接下来的进路
// MapConfig config = repository.getConfig();
// if (config.isSignalOpenAfterParking() && !trainInfo.isParking()) {
// return null;
// } else {
// if (tripPlan.isLastPlanStationSection(planTrack)) {
// //是计划的终点站
// if (tripPlan.isBehindTurnBack()) {
// // 是站后折返
// triggerList = this.queryAccordingTbStrategy(repository, trainInfo, tripPlan);
// Object[] rs = {triggerList, true};
// return rs;
// } else if (!tripPlan.getEndSection().equals(tripPlan.getLastStationPlan().getSection())) {
// // 备用车
// List<RoutePath> routePathList = repository.getRoutePaths(tripPlan.getLastStationPlan().getSection(),
// tripPlan.getEndSection());
// result = this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePathList);
// }
// } else {
// StationPlan nextStationPlan = tripPlan.queryNextStationPlan(planTrack);
// if (nextStationPlan != null) {
// // 下一计划车站存在
// List<RoutePath> routePathList = repository.getRoutePaths(planTrack, nextStationPlan.getSection());
// result = this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePathList);
// }
// }
// }
// }
// triggerList = (List<Route>) result[0];
// Object[] rs = {triggerList, false};
// return rs;
// }
private boolean isTriggerTurnBackRoute(SimulationDataRepository repository, TrainInfo trainInfo, TripPlan tripPlan) {
Section eaStandSection = repository.getByCode(trainInfo.getEstimatedArriveStandTrack(), Section.class);
Section arriveStandSection = repository.getByCode(trainInfo.getActualArriveStandTrack(), Section.class);
if (tripPlan.isBehindTurnBack()) {// 是站后折返计划
Section lastStationSection = tripPlan.getLastStationPlan().getSection();
if (lastStationSection.isSamePhysical(arriveStandSection.getCode())) {
// 列车达到计划终点站
return true;
} else if (lastStationSection.isSamePhysical(eaStandSection.getCode())) {
// 预计到达为终点站再判断是否到达折返始端信号机触发范围
List<RoutePath> list = repository.getRoutePaths(lastStationSection, tripPlan.getEndSection());
boolean right = list.get(0).isRight();
Signal signal = lastStationSection.getSignalOf(right);
// private boolean isTriggerTurnBackRoute(SimulationDataRepository repository, TrainInfo trainInfo, TripPlan tripPlan) {
// Section eaStandSection = repository.getByCode(trainInfo.getEstimatedArriveStandTrack(), Section.class);
// Section arriveStandSection = repository.getByCode(trainInfo.getActualArriveStandTrack(), Section.class);
// if (tripPlan.isBehindTurnBack()) {// 是站后折返计划
// Section lastStationSection = tripPlan.getLastStationPlan().getSection();
// if (lastStationSection.isSamePhysical(arriveStandSection.getCode())) {
// // 列车达到计划终点站
// return true;
// } else if (lastStationSection.isSamePhysical(eaStandSection.getCode())) {
// // 预计到达为终点站再判断是否到达折返始端信号机触发范围
// List<RoutePath> list = repository.getRoutePaths(lastStationSection, tripPlan.getEndSection());
// boolean right = list.get(0).isRight();
// Signal signal = lastStationSection.getSignalOf(right);
//
// return true;
// }
// }
// return false;
// }
return true;
}
}
return false;
}
private List<Route> queryAccordingTbStrategy(SimulationDataRepository repository, TrainInfo trainInfo, TripPlan tripPlan) {
Section standSection = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class);
if (!standSection.isRouteLock()) {
}
Station station = standSection.getStation();
StationTurnBackStrategyOption strategy = station.getCurrentTurnBackStrategy();
Section tbSection = tripPlan.getEndSection();
Route tbRoute = null;
List<Section> tbSectionList = new ArrayList<>();
if (Objects.isNull(strategy)) {
tbSectionList.add(tbSection);
} else {
switch (strategy.getType()) {
// 按计划
case NONE: {
tbSectionList.add(tbSection);
break;
}
// 仅某个折返轨
case ONLY: {
tbSectionList.add(strategy.getSectionList().get(0));
break;
}
// 折返轨等价
case FIRST:
case EQUAL: {
tbSectionList.addAll(strategy.getSectionList());
break;
}
}
}
List<RoutePath> list = repository.getRoutePaths(standSection, tbSection);
boolean right = list.get(0).isRight();
Signal signal = standSection.getSignalOf(right);
if (!this.isApproachSignal(repository, trainInfo, signal)) {
return null;
}
List<Route> routeList = signal.getRouteList();
List<Route> tbRouteList = new ArrayList<>();
for (Route route : routeList) {
if (route.isTurnBack()) {
tbRouteList.add(route);
}
}
if (!tbRouteList.isEmpty()) {
routeList = tbRouteList;
}
routeList = routeList.stream()
.filter(route -> !repository.hasSameStartTriggerRoute(trainInfo, route))
.filter(route -> route.containSameSection(tbSectionList))
.collect(Collectors.toList());
return routeList;
}
// private List<Route> queryAccordingTbStrategy(SimulationDataRepository repository, TrainInfo trainInfo, TripPlan tripPlan) {
// Section standSection = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class);
// if (!standSection.isRouteLock()) {
//
// }
// Station station = standSection.getStation();
// StationTurnBackStrategyOption strategy = station.getCurrentTurnBackStrategy();
// Section tbSection = tripPlan.getEndSection();
// Route tbRoute = null;
// List<Section> tbSectionList = new ArrayList<>();
// if (Objects.isNull(strategy)) {
// tbSectionList.add(tbSection);
// } else {
// switch (strategy.getType()) {
// // 按计划
// case NONE: {
// tbSectionList.add(tbSection);
// break;
// }
// // 仅某个折返轨
// case ONLY: {
// tbSectionList.add(strategy.getSectionList().get(0));
// break;
// }
// // 折返轨等价
// case FIRST:
// case EQUAL: {
// tbSectionList.addAll(strategy.getSectionList());
// break;
// }
// }
// }
// List<RoutePath> list = repository.getRoutePaths(standSection, tbSection);
// boolean right = list.get(0).isRight();
// Signal signal = standSection.getSignalOf(right);
// if (!this.isApproachSignal(repository, trainInfo, signal)) {
// return null;
// }
// List<Route> routeList = signal.getRouteList();
// List<Route> tbRouteList = new ArrayList<>();
// for (Route route : routeList) {
// if (route.isTurnBack()) {
// tbRouteList.add(route);
// }
// }
// if (!tbRouteList.isEmpty()) {
// routeList = tbRouteList;
// }
// 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;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
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.StationTurnBackStrategyOption;
import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo;
@ -23,53 +25,45 @@ public abstract class AtsRouteSelectService {
* 查询需要触发的进路
*
* @param turnBackSection 站后折返的折返轨
* @param right 计划运行方向
* @return
*/
public Object[] queryTriggerRoutes(SimulationDataRepository repository, List<Section> targetList,
TrainInfo trainInfo, Section turnBackSection, boolean right) {
public Route queryTriggerRoutes(SimulationDataRepository repository, List<Section> targetList,
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);
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();
Section targetSection = null;
Section nextTarget = null;
//选择目标区段
for (int i = targetList.size() - 1; i >= 0; i--) {
Section target = targetList.get(i);
List<RoutePath> routePaths = repository.queryRoutePathsByEndAndContainsSection(target, headSection);
routePaths.removeIf(routePath -> routePath.isRight() != right);
if (!config.isSignalOpenAfterParking() || (headSection.equals(planSection) && trainInfo.isParking())) { //不需要停站就可以开放信号机或者已经在计划区段停站可以继续向前办理进路
if (nextPlanSection != null) { //计划区段路径未跑完
routePaths = repository.queryRoutePaths(planSection, nextPlanSection);
if (!CollectionUtils.isEmpty(routePaths)) {
result = queryTriggerRoutesOfRoutePath(repository, trainInfo, routePaths);
targetSection = target;
if (i < targetList.size() - 1) {
nextTarget = targetList.get(i + 1);
return this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePaths, nextPlanSection);
}
} else if (turnBackSection != null) { //站后折返
return queryTriggerRoutes4TurnBack(repository, planSection, turnBackSection, trainInfo);
}
}
}
//选择进路
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;
return null;
}
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();
StationTurnBackStrategyOption strategy = station.getCurrentTurnBackStrategy();
List<Section> tbSectionList = new ArrayList<>();
@ -115,7 +109,24 @@ public abstract class AtsRouteSelectService {
.filter(route -> !repository.hasSameStartTriggerRoute(trainInfo, route))
.filter(route -> route.containSameSection(tbSectionList))
.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);
}
public Object[] queryTriggerRoutesOfRoutePath(SimulationDataRepository repository,
TrainInfo trainInfo, List<RoutePath> routePathList) {
Boolean right = trainInfo.getRight();
public Route queryTriggerRoutesOfRoutePath(SimulationDataRepository repository,
TrainInfo trainInfo, List<RoutePath> routePathList, Section nextPlanSection) {
Section section = repository.getByCode(trainInfo.getPhysicalSection(), Section.class); // 列车所在区段
Section logicSection = repository.getByCode(trainInfo.getSection(), 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为是否存在未接近的信号机
Section planSection = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class); //列车计划区段
List<Route> triggerList = new ArrayList<>();
result[0] = triggerList;
result[1] = false;
result[2] = false;
if (logicSection.isSwitchAxleCounterSection() || logicSection.isCross()) {
logicSection = section;
}
if (!routePathList.isEmpty()) {
RoutePath routePath = this.selectRoutePath(routePathList);
// 查找可以触发的进路列表
@ -164,7 +162,6 @@ public abstract class AtsRouteSelectService {
continue;
}
if (signal.hasCiAutoTriggerRoute() || signal.hasFleetModeRoute()) {
result[2] = true; // 存在联锁自动触发进路或联锁自动进路
break;
}
if (!ctcLevel && signal.isVirtual()) {
@ -172,15 +169,15 @@ public abstract class AtsRouteSelectService {
}
if (this.isApproachSignal(repository, trainInfo, signal)) {
// 是信号机接近区段
if (signal.isNormalOpen()) { //如果信号机已经正常开放继续查询下一个
if (signal.isNormalOpen()) {
if (routePath.isPathRoute(signal.getLockedRoute())) {
continue;
} else {
result[2] = true; // 非路径进路办理
// 非路径进路办理
break;
}
} else {
result[1] = true;
//筛选可触发的进路
for (Route route : routePath.getRouteList()) {
TrainInfo other = repository.querySameStartTriggerRouteTrain(trainInfo, route);
if (other != null) { // 已经有在排列中的进路结束
@ -192,15 +189,40 @@ public abstract class AtsRouteSelectService {
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 {
// 列车未接近此信号机
result[2] = true;
}
break;
}
}
return result;
return null;
}
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.SimulationDataRepository;
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.vo.TrainInfo;
import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPService;
import club.joylink.rtss.simulation.cbtc.onboard.ATP.OnboardAtpApiService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.List;
@ -45,7 +43,6 @@ public class AtsHeadTrainStageService implements AtsStageService {
DestinationCodeDefinition dcd = repository.findDestinationCodeDefinition(trainInfo.getDestinationCode());
if (dcd == null)
return;
SectionPosition headPosition = repository.buildHeadPositionOfTrainInfo(trainInfo);
if (Objects.equals(dcd.getSection(), parkSection)) {
// 列车到达目的地
trainInfo.finishPlanPrepareInbound();
@ -64,7 +61,7 @@ public class AtsHeadTrainStageService implements AtsStageService {
if (Objects.equals(dcd.getSection(), parkSection)) {
handleArriveDestination(simulation, trainInfo);
} else {
this.updateNextTarget(simulation, trainInfo);
this.updatePlanSection(simulation, trainInfo);
}
}
@ -74,13 +71,13 @@ public class AtsHeadTrainStageService implements AtsStageService {
if (Objects.equals(dcd.getSection(), parkSection)) {
handleArriveDestination(simulation, trainInfo);
} else {
this.updateNextTarget(simulation, trainInfo);
this.updatePlanSection(simulation, trainInfo);
}
}
@Override
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) {
boolean right = trainInfo.getRight();
private void updatePlanSection(Simulation simulation, TrainInfo trainInfo) {
if (!StringUtils.hasText(trainInfo.getPlanStandTrack()))
return;
boolean planRight = trainInfo.getHctPath().isRight();
SimulationDataRepository repository = simulation.getRepository();
SectionPosition headPosition = repository.buildHeadPositionOfTrainInfo(trainInfo);
Section planSection = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class);
//如果还未到达目标轨
Section headSection = headPosition.getSection();
if (StringUtils.hasText(trainInfo.getEstimatedArriveStandTrack())) {
Section target = repository.getByCode(trainInfo.getEstimatedArriveStandTrack(), Section.class);
if (!target.equals(headSection) && target.isAheadOf(repository, headSection, right)) {
if (!planSection.equals(headSection) && planSection.isAheadOf(repository, headSection, planRight)) {
return;
}
}
//寻找目标区段
Section nextTarget = queryNextTarget(simulation, headPosition.getSection(), trainInfo, right);
if (nextTarget == null)
Section nextPlanSection = queryNextPlanSection(simulation, trainInfo);
if (nextPlanSection == null)
return;
//判断调头
if (!nextTarget.isAheadOf(repository, headSection, right)) {//下一目标区段不在当前车头方向的前方
Boolean trainRight = trainInfo.getRight();
if (!nextPlanSection.isAheadOf(repository, headSection, trainRight)) {//下一计划区段不在当前车头方向的前方
atpService.turnDirectionImmediately(repository.getOnlineTrainBy(trainInfo.getGroupNumber())); //调头
}
//更新计到站
SectionPosition stopPosition = new SectionPosition(nextTarget, nextTarget.getStopPointByDirection(right));
Float distance = CalculateService.calculateDistance(headPosition, stopPosition, right);
//更新到站
SectionPosition stopPosition = new SectionPosition(nextPlanSection, nextPlanSection.getStopPointByDirection(planRight));
Float distance = CalculateService.calculateDistance(headPosition, stopPosition, planRight);
int runningTime;
if (distance != null) {
runningTime = (int) (distance / (45 / 3.6));
} else {
runningTime = 180;
}
trainInfo.updatePlanInfo(nextTarget, null, null);
// trainInfo.updateEstimatedArriveInfo(nextTarget, simulation.getSystemTime().toLocalTime().plusSeconds(runningTime));
boolean jump = this.atsStandService.isJump(nextTarget, trainInfo.getGroupNumber());
onboardAtpApiService.updateNextArriveInfo(simulation, trainInfo.getGroupNumber(), nextTarget, true, runningTime, jump);
trainInfo.updatePlanInfo(nextPlanSection, null, null);
boolean jump = this.atsStandService.isJump(nextPlanSection, trainInfo.getGroupNumber());
onboardAtpApiService.updateNextArriveInfo(simulation, trainInfo.getGroupNumber(), nextPlanSection, true, runningTime, jump);
}
public static Section queryNextTarget(Simulation simulation, Section headSection, TrainInfo trainInfo, Boolean right) {
SimulationDataRepository repository = simulation.getRepository();
List<Section> targetList = trainInfo.getHeadPath().getSectionList();
for (int i = targetList.size() - 1; i >= 0; i--) {
Section target = targetList.get(i);
List<RoutePath> routePaths = repository.queryRoutePathsByEndAndContainsSection(target, headSection);
if (!CollectionUtils.isEmpty(routePaths)) {
return target;
}
}
public static Section queryNextPlanSection(Simulation simulation, TrainInfo trainInfo) {
if (trainInfo.getPlanStandTrack() == null) {
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;
}
SimulationDataRepository repository = simulation.getRepository();
List<Section> targetList = trainInfo.getHctPath().getSections();
Section planSection = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class);
int index = targetList.indexOf(planSection);
if (index == -1 || index == targetList.size() - 1) {
return null;
} else {
return targetList.get(index + 1);
}
}
}

View File

@ -280,15 +280,18 @@ public class RouteService {
// 进路内区段占用检查
List<Section> sectionList = route.getSectionList();
for (Section section : sectionList) {
if (section.isOccupied() && !section.isPreReset()) {
if (section.isSwitchTrack()) {
if (!section.getRelSwitch().isPreReset()) {
if (section.isOccupied()) {
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();

View File

@ -186,7 +186,7 @@ public class CommandBO {
if (!train.isStopAtThePosition(driveStep.getTargetPosition())) { //如果列车没停到目标位置
if (!train.isStop())
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);
if (train.isEB())
return buildReleaseEBStep(train);
@ -305,7 +305,7 @@ public class CommandBO {
// command.getTargetMember().setCommand(null);
// }
} else {
if (!DriveMode.RM.equals(train.getDriveMode())) {
if (!DriveMode.RM.equals(train.getDriveMode()) && !train.isNRMMode()) {
return buildDriverDriveModeChangeOperationStep(train.getGroupNumber(), DriveMode.RM);
}
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) {
super(psd.getCode(), psd.getDeviceType());
this.close = psd.isClose();
this.close = psd.isCloseAndLock();
// this.lock = psd.isLock();
this.interlockRelease = psd.isInterlockRelease();
this.noStatus = psd.isNoStatus();
@ -49,8 +49,8 @@ public class PSDStatus extends DeviceStatus {
PSD psd = (PSD) device;
PSDStatusVO status = (PSDStatusVO)statusVO;
boolean change = false;
if (!Objects.equals(this.close, psd.isClose())) {
this.close = psd.isClose();
if (!Objects.equals(this.close, psd.isCloseAndLock())) {
this.close = psd.isCloseAndLock();
status.setClose(this.close);
change = true;
}

View File

@ -253,7 +253,7 @@ public class RoutePath {
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) {
List<Route> routeList = signal.getRouteList();
if (CollectionUtils.isEmpty(routeList)) {
@ -261,11 +261,11 @@ public class RoutePath {
}
for (Route route : routeList) {
if (config.isRouteLikeHa1()) {
if (Objects.equals(runLevel, RunLevel.CBTC)) { // ctc级别列车找ATP进路
if (communication) { // 通信车找ATP进路
if (!route.isAtp()) {
continue;
}
} else { // CTC列车找地面进路
} else { // 通信车找地面进路
if (!route.isGround()) {
continue;
}

View File

@ -206,7 +206,7 @@ public class TrainInfo extends MapElement {
* 头码车的区段路径
*/
@Setter
private SectionPath headPath;
private SectionRunPath hctPath;
/**
* 下令停车
@ -244,29 +244,21 @@ public class TrainInfo extends MapElement {
*/
@Setter
private String turnBackStatus = NON;
/**
* 无折返
*/
/** 无折返 */
public static String NON = "NON";
/**
* 初始化
*/
/** 初始化 */
public static String INIT = "INIT";
/**
* 开往折返轨
*/
/** 开往折返轨 */
public static String TO = "TO";
/**
* 到达折返轨停稳
*/
/** 到达折返轨停稳 */
public static String STOP = "STOP";
/**
* 开出折返轨
*/
/** 开出折返轨 */
public static String EXIT = "EXIT";
/** ATS为此列车触发的进路 */
private Map<String, Route> atsTriggerRouteMap = new ConcurrentHashMap<>();
private boolean communication;
public TrainInfo(String groupNumber) {
super(groupNumber, DeviceType.TRAIN);
this.groupNumber = groupNumber;
@ -383,7 +375,7 @@ public class TrainInfo extends MapElement {
this.offsetp = headPosition.getPercent();
if (headPosition.getSection().isSwitchTrack()) {
this.section = headPosition.getSection().getParent().getCode();
} else if (this.isCtcLevel()) {
} else if (this.isCommunication()) {
this.section = headPosition.getLogicSection().getCode();
} else {
this.section = headPosition.getSection().getCode();
@ -408,6 +400,7 @@ public class TrainInfo extends MapElement {
} else if (speed != 0 && this.turnBackStatus.equals(STOP)) {
this.turnBackStatus = EXIT;
}
this.communication = train.isCommunication();
}
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 preDriveMode;
/**
* 服务号
*/
@ -400,6 +405,12 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
*/
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) {
this.runType = runType;
switch (runType) {
@ -446,8 +457,10 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
@Override
public void reset() {
this.communication = true;
this.runLevel = null;
this.driveMode = null;
this.preDriveMode = null;
this.serviceNumber = null;
this.tripNumber = null;
this.destinationCode = null;
@ -569,11 +582,13 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
}
private void init() {
this.communication = true;
this.jump = false;
this.hold = false;
this.standParkedTrainActivity = null;
this.runLevel = RunLevel.CBTC;
this.driveMode = DriveMode.AM;
this.preDriveMode = DriveMode.AM;
this.speed = 0;
this.atoSpeed = 0;
this.atpSpeed = 0;
@ -713,8 +728,9 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
// this.setSignalEB(false);
this.setAtoOn(false);
this.setDriveMode(DriveMode.RM);
setCommunication(false); //断开通信
// this.lossPosition();
this.setCbtcMaMiss(); //通信断开
// this.setCbtcMaMiss(); //通信断开
// this.lastTwoPassedResponders.clear();
// if (RunLevel.CBTC.equals(this.runLevel)) {
// this.setCbtcMaMiss();
@ -728,7 +744,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
public void useCMMode() {
if (!this.isAtpOn()) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, String.format("列车[%s]未打开ATP", this.getCode()));
return;
}
this.atoOn = false;
this.driveMode = DriveMode.CM;
@ -736,12 +752,13 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
public void useAMMode() {
if (!atoOn) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, String.format("列车[%s]未打开ATO", this.getCode()));
return;
}
if (!this.isAtpOn()) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, String.format("列车[%s]未打开ATP", this.getCode()));
return;
}
this.driveMode = DriveMode.AM;
setCommunication(true);
}
public void useNRMMode() {
@ -755,9 +772,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
return;
}
this.driveMode = DriveMode.NRM;
if (RunLevel.CBTC.equals(this.runLevel)) {
this.setCbtcMaMiss();
}
setCommunication(false);
}
public void setITCMode() {
@ -1113,13 +1128,15 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
public boolean isCommunicable() {
Section section = headPosition.getSection();
Station deviceStation = section.getDeviceStation();
if (VirtualRealityTrain.Fault.COMMUNICATION_ABNORMAL == fault
|| Station.Fault.INTERLOCK_MACHINE_FAULT == deviceStation.getFault()
|| !section.anyZcWorking()) {
return false;
}
return true;
return communication && section.anyZcWorking();
// Station deviceStation = section.getDeviceStation();
// if (VirtualRealityTrain.Fault.COMMUNICATION_ABNORMAL == fault
// || Station.Fault.INTERLOCK_MACHINE_FAULT == deviceStation.getFault()
// || !section.anyZcWorking()) {
// return false;
// }
// return true;
}
public boolean isCMMode() {
@ -1135,27 +1152,28 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
* 通信异常
*/
COMMUNICATION_ABNORMAL {
// @Override
// public boolean apply(MapElement device) {
// VirtualRealityTrain train = (VirtualRealityTrain) device;
// if (Objects.equals(this, train.getFault())) {
// return false;
// }
// train.setFault(this);
// train.lossPosition();
// return true;
// }
@Override
public boolean apply(MapElement device) {
if (super.apply(device)) {
VirtualRealityTrain train = (VirtualRealityTrain) device;
train.setCommunication(false);
return true;
}
return false;
}
},
/** 驾驶异常 */
DRIVE_FAULT {
@Override
public boolean apply(MapElement device) {
super.apply(device);
if (super.apply(device)) {
VirtualRealityTrain train = (VirtualRealityTrain) device;
train.emergencyBreak(); //暂时就在这里直接处理可能正常应该是ATP的责任
return true;
}
return false;
}
},
/** 突然EB */

View File

@ -49,9 +49,10 @@ public class ATOService {
}
if (Objects.nonNull(train.getMa())) {
train.setAtoOn(true);
if (DriveMode.CM.equals(train.getDriveMode())) {
train.useAMMode();
}
train.setPreDriveMode(DriveMode.AM);
// 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.ATS.AtsApiService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.constant.ControlGear;
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.constant.*;
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.Stand;
@ -109,6 +106,7 @@ public class ATPLogicLoop {
private void onboardLogicRun2(Simulation simulation, VirtualRealityTrain train) {
this.runLevelControl(simulation, train);
this.driveModeControl(simulation, train);
boolean right = train.isRight();
SectionPosition headPosition = train.getHeadPosition();
@ -183,6 +181,33 @@ public class ATPLogicLoop {
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) {
if (train.isParkingAt()) {
train.setRunningTime(0);

View File

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

View File

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

View File

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