修复国赛场景编制遇到的问题。修改延续保护中道岔的延续保护及侧防解锁逻辑;修改设计划车时的计划筛选逻辑

This commit is contained in:
joylink_zhangsai 2023-11-21 14:51:26 +08:00
parent 0faf852aa6
commit aec1a01f96
13 changed files with 3587 additions and 3357 deletions

View File

@ -1,7 +1,6 @@
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.Route;
import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo;
import lombok.extern.slf4j.Slf4j;
@ -13,11 +12,12 @@ import org.springframework.stereotype.Component;
@Slf4j
@Component
public class AtsHeadTrainRouteSelectServiceImpl extends AtsRouteSelectService {
@Override
public Route select(Simulation simulation, TrainInfo trainInfo) {
if (!trainInfo.isHeadCodeTrain()) {
return null;
}
return queryTriggerRoutes(simulation, trainInfo.getHctPath().getSections(), trainInfo, null);
@Override
public Route select(Simulation simulation, TrainInfo trainInfo) {
if (!trainInfo.isHeadCodeTrain()) {
return null;
}
return queryTriggerRoutes(simulation, trainInfo.getHctPath().getSections(), trainInfo, null);
}
}

View File

@ -11,11 +11,6 @@ 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.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
@ -23,6 +18,10 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 计划车进路选择
@ -31,207 +30,220 @@ import java.util.stream.Collectors;
@Component
public class AtsPlanTrainRouteSelectServiceImpl extends AtsRouteSelectService {
@Autowired
private AtsAlarmService atsAlarmService;
@Autowired
private AtsAlarmService atsAlarmService;
@Override
public Route select(Simulation simulation, TrainInfo trainInfo) {
if (!trainInfo.isPlanTrain()) {
return null;
}
SimulationDataRepository repository = simulation.getRepository();
TripPlan tripPlan = repository.getTripPlan(trainInfo.getServiceNumber(), trainInfo.getTripNumber());
LocalDateTime systemTime = simulation.getSystemTime();
// 根据车次计划查找可触发进路列表
@Override
public Route select(Simulation simulation, TrainInfo trainInfo) {
if (!trainInfo.isPlanTrain()) {
return null;
}
SimulationDataRepository repository = simulation.getRepository();
TripPlan tripPlan = repository.getTripPlan(trainInfo.getServiceNumber(),
trainInfo.getTripNumber());
LocalDateTime systemTime = simulation.getSystemTime();
// 根据车次计划查找可触发进路列表
// Object[] results = this.queryByStationPlan(repository, systemTime, trainInfo, tripPlan);
Route route = queryByStationPlan(simulation, systemTime, trainInfo, tripPlan);
// 根据计划筛选需触发进路
return filterRoutes(simulation, trainInfo, tripPlan, route);
}
Route route = queryByStationPlan(simulation, systemTime, trainInfo, tripPlan);
// 根据计划筛选需触发进路
return filterRoutes(simulation, trainInfo, tripPlan, route);
}
private Route queryByStationPlan(Simulation simulation, LocalDateTime systemTime, TrainInfo trainInfo, TripPlan tripPlan) {
SimulationDataRepository repository = simulation.getRepository();
//判断是否到进路触发时间
Section section = repository.getByCode(trainInfo.getPhysicalSection(), Section.class);
if (section.isTransferTrack() || section.isTurnBackTrack()) { //列车在转换轨或折返轨
List<StationPlan> planList = tripPlan.getPlanList();
for (StationPlan stationPlan : planList) {
if (!stationPlan.getStation().isDepot()) { //第一个非停车场的车站
if (stationPlan.getSection().getCode().equals(trainInfo.getPlanStandTrack())
&& !section.equals(stationPlan.getSection())) { //车站是列车的计划
if (!systemTime.toLocalTime().plusSeconds(60).isAfter(tripPlan.getStartTime())) { //当前时间不早于计划开始时间60秒
log.debug(String.format("列车[%s]未到发车时间,不触发进路", trainInfo.getGroupNumber()));
return null;
}
}
break;
}
private Route queryByStationPlan(Simulation simulation, LocalDateTime systemTime,
TrainInfo trainInfo, TripPlan tripPlan) {
SimulationDataRepository repository = simulation.getRepository();
//判断是否到进路触发时间
Section section = repository.getByCode(trainInfo.getPhysicalSection(), Section.class);
if (section.isTransferTrack() || section.isTurnBackTrack()) { //列车在转换轨或折返轨
List<StationPlan> planList = tripPlan.getPlanList();
for (StationPlan stationPlan : planList) {
if (!stationPlan.getStation().isDepot()) { //第一个非停车场的车站
if (stationPlan.getSection().getCode().equals(trainInfo.getPlanStandTrack())
&& !section.equals(stationPlan.getSection())) { //车站是列车的计划
if (!systemTime.toLocalTime().plusSeconds(60)
.isAfter(tripPlan.getStartTime())) { //当前时间不早于计划开始时间60秒
log.debug(
String.format("列车[%s]未到发车时间,不触发进路", trainInfo.getGroupNumber()));
return null;
}
}
break;
}
List<Section> targetList = tripPlan.getPlanList().stream().map(StationPlan::getSection).collect(Collectors.toList());
if (tripPlan.isBackup()) {
targetList.add(tripPlan.getEndSection());
}
if (tripPlan.isBehindTurnBack()) {
return queryTriggerRoutes(simulation, targetList, trainInfo, tripPlan.getEndSection());
} else {
return queryTriggerRoutes(simulation, targetList, trainInfo, null);
}
}
}
/**
* 先选取需要征用的进路再根据计划判断是否存在冲突的未完成计划
*/
private Route filterRoutes(Simulation simulation,
TrainInfo trainInfo, TripPlan tripPlan, Route route) {
if (route == null) {
return null;
}
SimulationDataRepository repository = simulation.getRepository();
// 先选取需要征用的进路
log.debug(String.format("列车[%s]筛选出的进路为:[%s]", trainInfo.getGroupNumber(), route.getName()));
if (route.isCheckConflict() && route.getConflictAlarm() == null) {
ConflictInfo conflictInfo = this.checkConflict(repository, trainInfo, tripPlan, route);
if (conflictInfo != null) {
Section startSection = conflictInfo.section;
StationPlan stationPlan = conflictInfo.stationPlan;
String conflictDesc = String.format("计划车(%s(%s)触发的进路[%s]与计划(%s)从节点(%s_%s)到节点(%s_%s)的计划冲突,无法选排",
tripPlan.getStNumber(), trainInfo.getGroupNumber(), route.getName(),
stationPlan.getPlan().getStNumber(),
startSection.getStation().getName(), startSection.getName(),
stationPlan.getStation().getName(), stationPlan.getSection().getName());
log.debug(String.format("构建并发送进路冲突告警"));
AtsAlarm alarm = this.atsAlarmService.buildAndSendAlarm(
simulation,
AtsAlarm.Type.Conflict_Route_Set,
"0", route.getCode(), conflictDesc);
route.setConflictAlarm(alarm);
}
}
return route;
List<Section> targetList = tripPlan.getPlanList().stream().map(StationPlan::getSection)
.collect(Collectors.toList());
if (tripPlan.isBehindTurnBack()) {
targetList.add(tripPlan.getEndSection());
}
@Getter
public static class ConflictInfo {
Section section;
StationPlan stationPlan;
public ConflictInfo(Section section, StationPlan stationPlan) {
this.section = section;
this.stationPlan = stationPlan;
}
if (tripPlan.isBehindTurnBack()) {
return queryTriggerRoutes(simulation, targetList, trainInfo, tripPlan.getEndSection());
} else {
return queryTriggerRoutes(simulation, targetList, trainInfo, null);
}
}
/**
* 检查进路是否和未完成的计划冲突
*
* @param repository
* @param trainInfo
* @param tripPlan
* @param route
* @return
*/
public ConflictInfo checkConflict(SimulationDataRepository repository, TrainInfo trainInfo,
TripPlan tripPlan, Route route) {
Section section = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class);
LocalTime arriveTime = this.queryRouteArriveTime(repository, route, trainInfo, tripPlan, section);
if (arriveTime == null) {
log.debug(String.format("计划车[%s]未找到进路[%s]下一计划到达时间", trainInfo.getGroupNumber(), route.getName()));
return null;
/**
* 先选取需要征用的进路再根据计划判断是否存在冲突的未完成计划
*/
private Route filterRoutes(Simulation simulation,
TrainInfo trainInfo, TripPlan tripPlan, Route route) {
if (route == null) {
return null;
}
SimulationDataRepository repository = simulation.getRepository();
// 先选取需要征用的进路
log.debug(
String.format("列车[%s]筛选出的进路为:[%s]", trainInfo.getGroupNumber(), route.getName()));
if (route.isCheckConflict() && route.getConflictAlarm() == null) {
ConflictInfo conflictInfo = this.checkConflict(repository, trainInfo, tripPlan, route);
if (conflictInfo != null) {
Section startSection = conflictInfo.section;
StationPlan stationPlan = conflictInfo.stationPlan;
String conflictDesc = String.format(
"计划车(%s(%s)触发的进路[%s]与计划(%s)从节点(%s_%s)到节点(%s_%s)的计划冲突,无法选排",
tripPlan.getStNumber(), trainInfo.getGroupNumber(), route.getName(),
stationPlan.getPlan().getStNumber(),
startSection.getStation().getName(), startSection.getName(),
stationPlan.getStation().getName(), stationPlan.getSection().getName());
log.debug(String.format("构建并发送进路冲突告警"));
AtsAlarm alarm = this.atsAlarmService.buildAndSendAlarm(
simulation,
AtsAlarm.Type.Conflict_Route_Set,
"0", route.getCode(), conflictDesc);
route.setConflictAlarm(alarm);
}
}
return route;
}
@Getter
public static class ConflictInfo {
Section section;
StationPlan stationPlan;
public ConflictInfo(Section section, StationPlan stationPlan) {
this.section = section;
this.stationPlan = stationPlan;
}
}
/**
* 检查进路是否和未完成的计划冲突
*
* @param repository
* @param trainInfo
* @param tripPlan
* @param route
* @return
*/
public ConflictInfo checkConflict(SimulationDataRepository repository, TrainInfo trainInfo,
TripPlan tripPlan, Route route) {
Section section = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class);
LocalTime arriveTime = this.queryRouteArriveTime(repository, route, trainInfo, tripPlan,
section);
if (arriveTime == null) {
log.debug(
String.format("计划车[%s]未找到进路[%s]下一计划到达时间", trainInfo.getGroupNumber(),
route.getName()));
return null;
}
TripPlan nextTripPlan = repository.queryNextTripPlanOf(tripPlan);
Section start = null;
StationPlan conflictStationPlan = null;
Map<String, List<TripPlan>> serviceTripsMap = repository.getServiceTripsMap();
for (List<TripPlan> planList : serviceTripsMap.values()) {
for (TripPlan plan : planList) {
if (plan.equals(tripPlan)) {
continue;
}
TripPlan nextTripPlan = repository.queryNextTripPlanOf(tripPlan);
Section start = null;
StationPlan conflictStationPlan = null;
Map<String, List<TripPlan>> serviceTripsMap = repository.getServiceTripsMap();
for (List<TripPlan> planList : serviceTripsMap.values()) {
for (TripPlan plan : planList) {
if (plan.equals(tripPlan)) {
continue;
}
if (plan.equals(nextTripPlan)) {
continue;
}
if (plan.getStartTime().isAfter(arriveTime)) {
break;
}
List<StationPlan> stationPlanList = plan.getPlanList();
TrainInfo aheadTrain = repository.queryAtsTrainInfoOfTripPlan(plan);
start = plan.getStartSection();
for (StationPlan temp : stationPlanList) {
if (temp.getArriveTime().isAfter(arriveTime)) {
break;
}
if (!temp.isFinished()) {
if (!start.equals(temp.getSection())) {
if (this.isConflict(repository, route, aheadTrain, start, temp.getSection())) {
conflictStationPlan = temp;
break;
}
}
}
if (conflictStationPlan != null) {
break;
}
start = temp.getSection();
}
if (conflictStationPlan != null) {
break;
}
}
if (conflictStationPlan != null) {
if (plan.equals(nextTripPlan)) {
continue;
}
if (plan.getStartTime().isAfter(arriveTime)) {
break;
}
List<StationPlan> stationPlanList = plan.getPlanList();
TrainInfo aheadTrain = repository.queryAtsTrainInfoOfTripPlan(plan);
start = plan.getStartSection();
for (StationPlan temp : stationPlanList) {
if (temp.getArriveTime().isAfter(arriveTime)) {
break;
}
if (!temp.isFinished()) {
if (!start.equals(temp.getSection())) {
if (this.isConflict(repository, route, aheadTrain, start, temp.getSection())) {
conflictStationPlan = temp;
break;
}
}
}
if (conflictStationPlan != null) {
break;
}
start = temp.getSection();
}
if (conflictStationPlan != null) {
log.debug(String.format("列车[%s]的进路[%s]和未完成车站计划[%s]冲突",
trainInfo.getGroupNumber(), route.getName(),
String.format("%s{%s}", conflictStationPlan.getPlan().getStNumber(), conflictStationPlan.debugStr())));
return new ConflictInfo(start, conflictStationPlan);
break;
}
return null;
}
if (conflictStationPlan != null) {
break;
}
}
if (conflictStationPlan != null) {
log.debug(String.format("列车[%s]的进路[%s]和未完成车站计划[%s]冲突",
trainInfo.getGroupNumber(), route.getName(),
String.format("%s{%s}", conflictStationPlan.getPlan().getStNumber(),
conflictStationPlan.debugStr())));
return new ConflictInfo(start, conflictStationPlan);
}
return null;
}
/**
* 查询所需办理进路所需到达的计划时间
*/
private LocalTime queryRouteArriveTime(SimulationDataRepository repository, Route route,
TrainInfo trainInfo, TripPlan tripPlan, Section nextPlanSection) {
boolean start = false;
List<StationPlan> planList = tripPlan.getPlanList();
for (int i = 0; i < planList.size(); i++) {
StationPlan stationPlan = planList.get(i);
if (stationPlan.getSection().equals(nextPlanSection)) {
start = true;
}
if (start) {
List<RoutePath> routePathList = repository.queryRoutePathsByEnd(stationPlan.getSection());
for (RoutePath routePath : routePathList) {
if (routePath.isPathRoute(route)) {
return stationPlan.getArriveTime();
}
}
if (i == planList.size() - 1) { // 最后一站,判断是否站后折返
if (tripPlan.isBehindTurnBack()) {
routePathList = repository.queryRoutePathsByStart(stationPlan.getSection());
for (RoutePath routePath : routePathList) {
if (routePath.isPathRoute(route)) {
TripPlan nextTripPlan = repository.queryNextTripPlanOf(tripPlan);
return nextTripPlan.getFirstStationPlan().getArriveTime();
}
}
} else if (!Objects.equals(tripPlan.getEndSection(), stationPlan.getSection())) {
routePathList = repository.getRoutePaths(stationPlan.getSection(), tripPlan.getEndSection());
for (RoutePath routePath : routePathList) {
if (routePath.isPathRoute(route)) {
return tripPlan.getEndTime();
}
}
}
}
}
/**
* 查询所需办理进路所需到达的计划时间
*/
private LocalTime queryRouteArriveTime(SimulationDataRepository repository, Route route,
TrainInfo trainInfo, TripPlan tripPlan, Section nextPlanSection) {
boolean start = false;
List<StationPlan> planList = tripPlan.getPlanList();
for (int i = 0; i < planList.size(); i++) {
StationPlan stationPlan = planList.get(i);
if (stationPlan.getSection().equals(nextPlanSection)) {
start = true;
}
if (start) {
List<RoutePath> routePathList = repository.queryRoutePathsByEnd(stationPlan.getSection());
for (RoutePath routePath : routePathList) {
if (routePath.isPathRoute(route)) {
return stationPlan.getArriveTime();
}
}
return null;
if (i == planList.size() - 1) { // 最后一站,判断是否站后折返
if (tripPlan.isBehindTurnBack()) {
routePathList = repository.queryRoutePathsByStart(stationPlan.getSection());
for (RoutePath routePath : routePathList) {
if (routePath.isPathRoute(route)) {
TripPlan nextTripPlan = repository.queryNextTripPlanOf(tripPlan);
return nextTripPlan.getFirstStationPlan().getArriveTime();
}
}
} else if (!Objects.equals(tripPlan.getEndSection(), stationPlan.getSection())) {
routePathList = repository.getRoutePaths(stationPlan.getSection(),
tripPlan.getEndSection());
for (RoutePath routePath : routePathList) {
if (routePath.isPathRoute(route)) {
return tripPlan.getEndTime();
}
}
}
}
}
}
return null;
}
//
// /**
// * 检查进路是否和未完成的计划冲突
@ -309,116 +321,125 @@ public class AtsPlanTrainRouteSelectServiceImpl extends AtsRouteSelectService {
// return null;
// }
private boolean isConflict(SimulationDataRepository repository, Route route,
TrainInfo aheadTrain, Section start, Section end) {
if (start.equals(end)) {
return false;
}
List<RoutePath> routePaths = repository.getRoutePaths(start, end);
boolean conflict = false;// 是否有冲突的路径列车不在此路径中时返回此状态
RoutePath routePath = this.selectRoutePath(routePaths);
if (routePath.isConflictWith(route)) {
conflict = true;
if (aheadTrain != null) {
if (routePath.containsSection(aheadTrain.getPhysicalSection())) {//前车在此计划路径中
Map<String, Route> atsTriggerRouteMap = aheadTrain.getAtsTriggerRouteMap();
if (!atsTriggerRouteMap.isEmpty()) {
for (Route triggerRoute : atsTriggerRouteMap.values()) {
if (triggerRoute.isConflictWith(route) && (triggerRoute.isSetting() || triggerRoute.isOpenMain())) {
return false;
}
}
}
if (routePath.isRight() == route.isRight()) {
if (routePath.containsSection(route.getFirstRouteSection()) &&
routePath.getSectionSort(route.getFirstRouteSection()) <= routePath.getSectionSort(aheadTrain.getPhysicalSection())) {
// 前车已经走过区段非冲突
return false;
} else if (routePath.containsSection(route.getLastRouteSection()) &&
routePath.getSectionSort(route.getLastRouteSection()) <= routePath.getSectionSort(aheadTrain.getPhysicalSection())) {
// 前车已经走过区段非冲突
return false;
}
} else if (routePath.isRight() != route.isRight()) { // 相反方向
// 列车是否已经经过敌对进路
if (routePath.containsSection(route.getLastRouteSection()) &&
routePath.getSectionSort(route.getLastRouteSection()) <= routePath.getSectionSort(aheadTrain.getPhysicalSection())) {
return false;
} else if (routePath.containsSection(route.getFirstRouteSection()) &&
routePath.getSectionSort(route.getFirstRouteSection()) <= routePath.getSectionSort(aheadTrain.getPhysicalSection())) {
return false;
}
}
}
} else {
return true;
}
}
return conflict;
private boolean isConflict(SimulationDataRepository repository, Route route,
TrainInfo aheadTrain, Section start, Section end) {
if (start.equals(end)) {
return false;
}
List<RoutePath> routePaths = repository.getRoutePaths(start, end);
boolean conflict = false;// 是否有冲突的路径列车不在此路径中时返回此状态
RoutePath routePath = this.selectRoutePath(routePaths);
if (routePath.isConflictWith(route)) {
conflict = true;
if (aheadTrain != null) {
if (routePath.containsSection(aheadTrain.getPhysicalSection())) {//前车在此计划路径中
Map<String, Route> atsTriggerRouteMap = aheadTrain.getAtsTriggerRouteMap();
if (!atsTriggerRouteMap.isEmpty()) {
for (Route triggerRoute : atsTriggerRouteMap.values()) {
if (triggerRoute.isConflictWith(route) && (triggerRoute.isSetting()
|| triggerRoute.isOpenMain())) {
return false;
}
}
}
if (routePath.isRight() == route.isRight()) {
if (routePath.containsSection(route.getFirstRouteSection()) &&
routePath.getSectionSort(route.getFirstRouteSection()) <= routePath.getSectionSort(
aheadTrain.getPhysicalSection())) {
// 前车已经走过区段非冲突
return false;
} else if (routePath.containsSection(route.getLastRouteSection()) &&
routePath.getSectionSort(route.getLastRouteSection()) <= routePath.getSectionSort(
aheadTrain.getPhysicalSection())) {
// 前车已经走过区段非冲突
return false;
}
} else if (routePath.isRight() != route.isRight()) { // 相反方向
// 列车是否已经经过敌对进路
if (routePath.containsSection(route.getLastRouteSection()) &&
routePath.getSectionSort(route.getLastRouteSection()) <= routePath.getSectionSort(
aheadTrain.getPhysicalSection())) {
return false;
} else if (routePath.containsSection(route.getFirstRouteSection()) &&
routePath.getSectionSort(route.getFirstRouteSection()) <= routePath.getSectionSort(
aheadTrain.getPhysicalSection())) {
return false;
}
}
}
} else {
return true;
}
}
return conflict;
}
private Route filter(SimulationDataRepository repository, TrainInfo trainInfo,
TripPlan tripPlan, List<Route> triggerList, boolean turnBack) {
Route route = triggerList.get(0);
if (turnBack) {
for (Route temp : triggerList) {
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;
}
}
} else if (triggerList.size() > 1) {
Section section = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class);
List<Route> routeList = new ArrayList<>();
for (Route temp : triggerList) {
if (!routeList.isEmpty() && routeList.get(0).getReverseSwitchQuantity() > temp.getReverseSwitchQuantity()) {
routeList.clear();
}
routeList.add(temp);
}
if (routeList.size() == 1) {
route = routeList.get(0);
} else {
// 不同延续保护
StationPlan nextStationPlan = tripPlan.queryNextStationPlan(section);
if (section.equals(routeList.get(0).getLastRouteSection()) && nextStationPlan != null) {
// 进路是计划站台轨根据后续计划筛选
List<RoutePath> routePaths = repository.getRoutePaths(section, nextStationPlan.getSection());
for (Route temp : routeList) {
if (routePaths.get(0).containsAllSections(temp.getOverlap().getFirstPath().getSectionList())) {
route = temp;
break;
}
}
} else {
// 取第一个延续保护道岔定位的
for (Route temp : routeList) {
List<SwitchElement> switchList = temp.getOverlap().getFirstPath().getSwitchList();
if (switchList.isEmpty()) {
log.debug(String.format("列车[%s]过滤进路异常:进路不是延续保护差异进路[%s]",
trainInfo.getGroupNumber(),
String.join(",", routeList.stream().map(Route::getName).collect(Collectors.toList()))));
}
if (switchList.get(0).isNormal()) {
route = temp;
break;
}
}
}
}
private Route filter(SimulationDataRepository repository, TrainInfo trainInfo,
TripPlan tripPlan, List<Route> triggerList, boolean turnBack) {
Route route = triggerList.get(0);
if (turnBack) {
for (Route temp : triggerList) {
List<Section> sectionList = temp.getSectionList();
boolean trainOccupy = false;
for (Section rs : sectionList) {
if (rs.isOccupied()) {
trainOccupy = true;
break;
}
}
return route;
if (trainOccupy) {
continue;
} else {
route = temp;
break;
}
}
} else if (triggerList.size() > 1) {
Section section = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class);
List<Route> routeList = new ArrayList<>();
for (Route temp : triggerList) {
if (!routeList.isEmpty()
&& routeList.get(0).getReverseSwitchQuantity() > temp.getReverseSwitchQuantity()) {
routeList.clear();
}
routeList.add(temp);
}
if (routeList.size() == 1) {
route = routeList.get(0);
} else {
// 不同延续保护
StationPlan nextStationPlan = tripPlan.queryNextStationPlan(section);
if (section.equals(routeList.get(0).getLastRouteSection()) && nextStationPlan != null) {
// 进路是计划站台轨根据后续计划筛选
List<RoutePath> routePaths = repository.getRoutePaths(section,
nextStationPlan.getSection());
for (Route temp : routeList) {
if (routePaths.get(0)
.containsAllSections(temp.getOverlap().getFirstPath().getSectionList())) {
route = temp;
break;
}
}
} else {
// 取第一个延续保护道岔定位的
for (Route temp : routeList) {
List<SwitchElement> switchList = temp.getOverlap().getFirstPath().getSwitchList();
if (switchList.isEmpty()) {
log.debug(String.format("列车[%s]过滤进路异常:进路不是延续保护差异进路[%s]",
trainInfo.getGroupNumber(),
String.join(",",
routeList.stream().map(Route::getName).collect(Collectors.toList()))));
}
if (switchList.get(0).isNormal()) {
route = temp;
break;
}
}
}
}
}
return route;
}
// /**
// * @return (List<Route>)[0] 可触发的进路(Boolean)[1]是否需要折返

View File

@ -11,300 +11,408 @@ import club.joylink.rtss.simulation.cbtc.constant.SignalAspect;
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
import club.joylink.rtss.simulation.cbtc.constant.SimulationModule;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
import club.joylink.rtss.simulation.cbtc.data.map.*;
import club.joylink.rtss.simulation.cbtc.data.map.MapConfig;
import club.joylink.rtss.simulation.cbtc.data.map.Route;
import club.joylink.rtss.simulation.cbtc.data.map.RouteFls;
import club.joylink.rtss.simulation.cbtc.data.map.RouteFls.FlsElement;
import club.joylink.rtss.simulation.cbtc.data.map.RouteOverlap;
import club.joylink.rtss.simulation.cbtc.data.map.Section;
import club.joylink.rtss.simulation.cbtc.data.map.SectionPath;
import club.joylink.rtss.simulation.cbtc.data.map.Signal;
import club.joylink.rtss.simulation.cbtc.data.map.Switch;
import club.joylink.rtss.simulation.cbtc.data.map.SwitchElement;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Objects;
import org.springframework.util.CollectionUtils;
@Slf4j
@Component
public class CiLogic {
interface JobName {
String SECTION_STOP_COUNTDOWN = "SECTION_STOP_COUNTDOWN";
}
@Autowired
private CiDeviceStatusCollector deviceStatusCollector;
@Autowired
private CiRouteService routeService;
@Autowired
private CiSignalControlService signalControlService;
@Autowired
private CiService ciService;
@Autowired
private StationDirectionService stationDirectionService;
interface JobName {
@Autowired
private AtsStationService atsStationService;
String SECTION_STOP_COUNTDOWN = "SECTION_STOP_COUNTDOWN";
}
public void runForTrainPosition(Simulation simulation) {
// 采集真实设备状态
deviceStatusCollector.collect(simulation);
}
@Autowired
private CiDeviceStatusCollector deviceStatusCollector;
@Autowired
private CiRouteService routeService;
@Autowired
private CiSignalControlService signalControlService;
@Autowired
private CiService ciService;
@Autowired
private StationDirectionService stationDirectionService;
public void run(Simulation simulation) {
// 采集真实设备状态
deviceStatusCollector.collect(simulation);
// 信号机监控控制
SimulationDataRepository repository = simulation.getRepository();
for (Signal signal : repository.getSignalList()) {
signalMonitor(simulation, signal);
}
// 联锁监控逻辑
List<Route> routeList = repository.getRouteList();
for (Route route : routeList) {
interlockMonitor(simulation, route);
}
List<RouteOverlap> routeOverlapList = repository.getRouteOverlapList();
for (RouteOverlap routeOverlap : routeOverlapList) {
overlapMonitor(simulation, routeOverlap);
}
@Autowired
private AtsStationService atsStationService;
// 区间灯点灯逻辑
if (simulation.getRepository().getConfig().isRailway()) {
// 车站站控操作模式转换
atsStationService.replyOperationMode(simulation);
// 车站
simulation.getRepository().getStationList().stream().forEach(station -> {
// 允许自律状态刷新
station.refreshAllowAutonomyStatus();
// 发辅助按钮倒计时刷新
station.getStationDirectionMap().values().stream()
.forEach(stationDirection -> {
// 判断进路状态是否发生变化
if (stationDirection.monitorRouteChangeStatus()) {
stationDirection.modifyRunStatus();
}
// 如果倒数结束弹起接发辅助按钮,超过50秒时不再自动抬起
if (!stationDirection.isAssistReadyStatus()
&& !stationDirection.assistDurationPass50(simulation.getCorrectSystemTime())
&& stationDirection.getCountDown().decrementAndGet() <= 0) {
stationDirection.setDeliverAssistStatus(false);
stationDirection.setReceiveAssistStatus(false);
stationDirection.getCountDown().set(0);
}
// 联锁数据检查
stationDirectionService.refreshSectionLightStatus(simulation, stationDirection);
});
});
}
}
public void addJobs(Simulation simulation) {
simulation.addJob(SimulationModule.CI.name(), () -> run(simulation),
SimulationConstants.CI_LOOP_RATE);
simulation.addJob(JobName.SECTION_STOP_COUNTDOWN, () -> sectionStopCountDown(simulation),
SimulationConstants.CI_LOOP_RATE);
}
/**
* 区段停稳倒计时
*/
public void sectionStopCountDown(Simulation simulation) {
for (Section section : simulation.getRepository().getHasStopCountDownSections()) {
int stopCountDown = section.getStopCountDown();
if (stopCountDown == 0) {
//股道占用且股道有占用
if (section.isOccupied()) {
if (section.getNextRunningSectionOf(false).isOccupied() || section.getNextRunningSectionOf(true).isOccupied()) {
section.readyStartStopCountDown();
}
}
} else {
if (stopCountDown == -1) {
// 股道占用股道两边没有占用股道没有进路锁闭或该进路正在正常解锁
if (section.isOccupied()) {
if ((!section.getNextRunningSectionOf(false).isOccupied()
&& !section.getNextRunningSectionOf(true).isOccupied())
&& (section.getRoute() == null || section.getRoute().isNormalUnlock())) {
section.startStopCountDown();
}
}
} else {
section.setStopCountDown(stopCountDown - SimulationConstants.CI_LOOP_RATE);
if (stopCountDown <= 0) {
section.setStopCountDown(0);
}
}
}
}
}
private void signalMonitor(Simulation simulation, Signal signal) {
signalControlService.controlLightOfSignal(simulation, signal);
//控制通过信号机的显示信号机前第一个区段被占用开红灯第二个区段被占用开黄灯否则开绿灯
if (simulation.getRepository().getConfig().isRailway()) {
railwaySignalMonitor(simulation, signal);
}
}
private void railwaySignalMonitor(Simulation simulation, Signal signal) {
if (signal.isGuideAspect() && signal.getLockedRoute() == null) { //引导总锁后开放的引导信号
if (signal.getRouteList().stream().noneMatch(Route::isAnySwitchMasterLock)) {
signalControlService.controlSignalAspect(simulation, signal, signal.getDefaultAspect());
}
}
if (signal.isPassingSignal()) {
boolean right = signal.isRight();
Section section = signal.getSection();
Section one = section.getNextSection(right);
if (one == null) {
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.G);
return;
}
if (one.isOccupied()) {
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.R);
return;
}
Section two = one.getNextSection(right);
if (two == null) {
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.G);
return;
}
if (two.isOccupied()) {
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.Y);
return;
}
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.G);
}
}
/**
* 进路监控
*
* @param simulation
* @param route
*/
public void interlockMonitor(Simulation simulation, Route route) {
MapConfig config = simulation.getRepository().getConfig();
if (route.isCiControl()) { // 进路联锁自动触发
if (!route.isLock() && !route.isSetting() && ciService.isCiRouteTrigger(simulation, route)) {
routeService.setRoute(simulation, route, route.getAspect());
}
} else if (route.isFleetMode()) { // 联锁自动进路
if (ciService.isCiRouteTrigger(simulation, route)) {
signalControlService.tryControlSignalAspectAccordingLevel(simulation, route.getStart(), route.getSettedAspect());
}
}
if (route.isSetting() || route.isLock() || route.isNormalUnlock()) { // 监控中的进路
if (route.isDelayUnlocking()) {
routeService.delayUnlocking(simulation, route, route.getDelayUnlockDevice());
}
if (route.isSetting()) {
routeService.routeSettingProcess(simulation, route);
}
if (route.isNormalUnlock()) {
ciService.interlockCheck(simulation, route); //南铁院叶老师提出列车越过始端信号机后灯座应该是红色
routeService.trainUnlockRoute(simulation, route);
}
if (route.isLock()) {
// 进路首区段列车占用进路开始解锁
Section firstLogicSection = route.getFirstLogicSection();
if (route.getStart().isGuideAspect() && firstLogicSection.getAxleCounterSection().isFaultOccupied()) {
log.debug(String.format("进路【%s(%s)】引导占用中,列车通过后请人工解锁", route.getName(), route.getCode()));
} else {
SimulationDataRepository repository = simulation.getRepository();
if (repository.isTrainHeadOccupy(firstLogicSection)) {
trainUnlockStart(simulation, route);
}
}
}
Signal start = route.getStart();
int guideRemain = start.getGuideRemain();
if (guideRemain != 0) {
guideRemain -= SimulationConstants.CI_LOOP_RATE;
if (guideRemain <= 0) { //计时结束关闭信号
start.setGuideRemain(0);
signalControlService.tryControlSignalAspectAccordingLevel(simulation,
start, start.getDefaultAspect());
} else {
start.setGuideRemain(guideRemain);
}
}
if (route.isLock() && !route.isSetting()) {
ciService.interlockCheck(simulation, route);
if (!config.isRailway()) {
if (route.isOpenMain() && !start.isSupportMainAspect()) {//与联锁显示不同关闭信号
CiLogic.log.info("进路[{}]联锁条件不满足,关闭信号", route.debugStr());
signalControlService.tryControlSignalAspectAccordingLevel(simulation,
start, start.getDefaultAspect());
} else if (start.isDefaultAspect() && !start.isForbidden() && !start.isBlockade() && start.isSupportMainAspect()) {
CiLogic.log.info("进路[{}]联锁条件满足,开放信号", route.debugStr());
signalControlService.tryControlSignalAspectAccordingLevel(simulation,
start, route.getSettedAspect());
}
} else {
if (route.isOpenMain() && !start.isSupportMainAspect()) {//与联锁显示不同关闭信号
CiLogic.log.info("进路[{}]联锁条件不满足,关闭信号", route.debugStr());
signalControlService.tryControlSignalAspectAccordingLevel(simulation,
start, start.getDefaultAspect());
start.setForcePhysical(true); //大铁线路暂时限制自动重开信号
} else if (!start.isForbidden() && !start.isBlockade() && start.isSupportMainAspect()) {
SignalAspect aspect = route.getAspectOfRailway();
if (!Objects.equals(route.getStart().getAspect(), aspect)) {
signalControlService.tryControlSignalAspectAccordingLevel(simulation, start, aspect);
}
}
}
}
// 进路延续保护办理判断
if (config.isOverlapSettingByTrigger()) {
if (route.getOverlap() != null && route.getOverlap().getSignal().isApproachSectionOccupied()) {
ciService.checkAndTrySettingOverlap(simulation, route.getOverlap());
}
} else if (route.isSettingOverlap()) {
ciService.checkAndTrySettingOverlap(simulation, route.getOverlap());
}
}
}
public void trainUnlockStart(Simulation simulation, Route route) {
route.startNormalUnlock();
CiLogic.log.info("进路[{}]因列车进入,关闭信号", route.debugStr());
signalControlService.tryControlSignalAspectAccordingLevel(simulation,
route.getStart(), route.getStart().getDefaultAspect());
}
/**
* 延续保护进路监控
*
* @param simulation
* @param overlap
*/
public void overlapMonitor(Simulation simulation, RouteOverlap overlap) {
MapConfig config = simulation.getRepository().getConfig();
if (config.isOverlapSettingByTrigger() && overlap.isTriggerSectionOccupied()) {
ciService.checkAndTrySettingOverlap(simulation, overlap);
}
if (overlap.isSetting()) {
routeService.overlapSettingProcess(simulation, overlap);
}
if (overlap.isForbidden()) {
routeService.checkAndAllowOverlap(simulation, overlap);
}
if (overlap.isLock() && !ciService.interlockCheck(simulation, overlap)) {
overlap.setLock(false);
}
if (overlap.isSectionOverlapLocked()) {
if (simulation.getRepository().isTrainParking(overlap.getSection())) {
CiLogic.log.debug("列车停稳,延续保护[{}}],触发区段[{}}]立即解锁",
overlap.getName(),
overlap.getSection().debugStr());
overlap.releaseImmediately();
return;
}
if (overlap.isReleasing()) {
overlap.releaseProgress();
} else if (!overlap.isReleasing() && simulation.getRepository().isTrainHeadOccupy(overlap.getSection())) {
// 进路首区段列车占用进路开始解锁
overlap.startReleasing();
}
}
}
public void addJobs(Simulation simulation) {
simulation.addJob(SimulationModule.CI.name(), () -> run(simulation), SimulationConstants.CI_LOOP_RATE);
simulation.addJob(JobName.SECTION_STOP_COUNTDOWN, () -> sectionStopCountDown(simulation), SimulationConstants.CI_LOOP_RATE);
}
public void addJobsForTrainPosition(Simulation simulation) {
simulation.addJob(SimulationModule.CI.name(), () -> runForTrainPosition(simulation), SimulationConstants.CI_LOOP_RATE);
public void addJobsForTrainPosition(Simulation simulation) {
simulation.addJob(SimulationModule.CI.name(), () -> runForTrainPosition(simulation),
SimulationConstants.CI_LOOP_RATE);
// simulation.addJob(JobName.SECTION_STOP_COUNTDOWN, () -> sectionStopCountDown(simulation), SimulationConstants.CI_LOOP_RATE);
}
public void runForTrainPosition(Simulation simulation) {
// 采集真实设备状态
deviceStatusCollector.collect(simulation);
}
public void run(Simulation simulation) {
// 采集真实设备状态
deviceStatusCollector.collect(simulation);
// 信号机监控控制
SimulationDataRepository repository = simulation.getRepository();
for (Signal signal : repository.getSignalList()) {
signalMonitor(simulation, signal);
}
// 联锁监控逻辑
List<Route> routeList = repository.getRouteList();
for (Route route : routeList) {
interlockMonitor(simulation, route);
}
//延续保护监控
List<RouteOverlap> routeOverlapList = repository.getRouteOverlapList();
Map<Switch, Boolean> unlockSwitchMap = new HashMap<>(); //记录不能解锁和需要延续保护解锁的道岔
for (RouteOverlap routeOverlap : routeOverlapList) {
overlapMonitor(simulation, routeOverlap, unlockSwitchMap);
}
unlockSwitchMap.forEach((aSwitch, unlock) -> {
if (unlock) {
aSwitch.overlapUnLock();
}
});
//延续保护侧防解锁
for (RouteOverlap routeOverlap : routeOverlapList) {
overlapFlsUnlock(routeOverlap);
}
// 区间灯点灯逻辑
if (simulation.getRepository().getConfig().isRailway()) {
// 车站站控操作模式转换
atsStationService.replyOperationMode(simulation);
// 车站
simulation.getRepository().getStationList().stream().forEach(station -> {
// 允许自律状态刷新
station.refreshAllowAutonomyStatus();
// 发辅助按钮倒计时刷新
station.getStationDirectionMap().values().stream()
.forEach(stationDirection -> {
// 判断进路状态是否发生变化
if (stationDirection.monitorRouteChangeStatus()) {
stationDirection.modifyRunStatus();
}
// 如果倒数结束弹起接发辅助按钮,超过50秒时不再自动抬起
if (!stationDirection.isAssistReadyStatus()
&& !stationDirection.assistDurationPass50(simulation.getCorrectSystemTime())
&& stationDirection.getCountDown().decrementAndGet() <= 0) {
stationDirection.setDeliverAssistStatus(false);
stationDirection.setReceiveAssistStatus(false);
stationDirection.getCountDown().set(0);
}
// 联锁数据检查
stationDirectionService.refreshSectionLightStatus(simulation, stationDirection);
});
});
}
}
/**
* 延续保护侧防解锁
*/
private void overlapFlsUnlock(RouteOverlap overlap) {
SectionPath sectionPath = overlap.selectPath();
if (CollectionUtils.isEmpty(sectionPath.getFlsList())) {
return;
}
for (RouteFls routeFls : sectionPath.getFlsList()) {
SwitchElement base = routeFls.getBase();
if (base == null) {
continue;
}
if (base.getASwitch().isRouteLock() || base.getASwitch().isOverlapLock()) {
continue;
}
if (CollectionUtils.isEmpty(routeFls.getLevel1List())) {
continue;
}
for (FlsElement flsElement : routeFls.getLevel1List()) {
if (flsElement.getPSwitch() == null) {
continue;
}
flsElement.getPSwitch().getASwitch().fpUnlock();
}
}
}
/**
* 区段停稳倒计时
*/
public void sectionStopCountDown(Simulation simulation) {
for (Section section : simulation.getRepository().getHasStopCountDownSections()) {
int stopCountDown = section.getStopCountDown();
if (stopCountDown == 0) {
//股道占用且股道有占用
if (section.isOccupied()) {
if (section.getNextRunningSectionOf(false).isOccupied()
|| section.getNextRunningSectionOf(true).isOccupied()) {
section.readyStartStopCountDown();
}
}
} else {
if (stopCountDown == -1) {
// 股道占用股道两边没有占用股道没有进路锁闭或该进路正在正常解锁
if (section.isOccupied()) {
if ((!section.getNextRunningSectionOf(false).isOccupied()
&& !section.getNextRunningSectionOf(true).isOccupied())
&& (section.getRoute() == null || section.getRoute().isNormalUnlock())) {
section.startStopCountDown();
}
}
} else {
section.setStopCountDown(stopCountDown - SimulationConstants.CI_LOOP_RATE);
if (stopCountDown <= 0) {
section.setStopCountDown(0);
}
}
}
}
}
private void signalMonitor(Simulation simulation, Signal signal) {
signalControlService.controlLightOfSignal(simulation, signal);
//控制通过信号机的显示信号机前第一个区段被占用开红灯第二个区段被占用开黄灯否则开绿灯
if (simulation.getRepository().getConfig().isRailway()) {
railwaySignalMonitor(simulation, signal);
}
}
private void railwaySignalMonitor(Simulation simulation, Signal signal) {
if (signal.isGuideAspect() && signal.getLockedRoute() == null) { //引导总锁后开放的引导信号
if (signal.getRouteList().stream().noneMatch(Route::isAnySwitchMasterLock)) {
signalControlService.controlSignalAspect(simulation, signal, signal.getDefaultAspect());
}
}
if (signal.isPassingSignal()) {
boolean right = signal.isRight();
Section section = signal.getSection();
Section one = section.getNextSection(right);
if (one == null) {
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.G);
return;
}
if (one.isOccupied()) {
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.R);
return;
}
Section two = one.getNextSection(right);
if (two == null) {
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.G);
return;
}
if (two.isOccupied()) {
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.Y);
return;
}
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.G);
}
}
/**
* 进路监控
*
* @param simulation
* @param route
*/
public void interlockMonitor(Simulation simulation, Route route) {
MapConfig config = simulation.getRepository().getConfig();
if (route.isCiControl()) { // 进路联锁自动触发
if (!route.isLock() && !route.isSetting() && ciService.isCiRouteTrigger(simulation, route)) {
routeService.setRoute(simulation, route, route.getAspect());
}
} else if (route.isFleetMode()) { // 联锁自动进路
if (ciService.isCiRouteTrigger(simulation, route)) {
signalControlService.tryControlSignalAspectAccordingLevel(simulation, route.getStart(),
route.getSettedAspect());
}
}
if (route.isSetting() || route.isLock() || route.isNormalUnlock()) { // 监控中的进路
if (route.isDelayUnlocking()) {
routeService.delayUnlocking(simulation, route, route.getDelayUnlockDevice());
}
if (route.isSetting()) {
routeService.routeSettingProcess(simulation, route);
}
if (route.isNormalUnlock()) {
ciService.interlockCheck(simulation, route); //南铁院叶老师提出列车越过始端信号机后灯座应该是红色
routeService.trainUnlockRoute(simulation, route);
}
if (route.isLock()) {
// 进路首区段列车占用进路开始解锁
Section firstLogicSection = route.getFirstLogicSection();
if (route.getStart().isGuideAspect() && firstLogicSection.getAxleCounterSection()
.isFaultOccupied()) {
log.debug(String.format("进路【%s(%s)】引导占用中,列车通过后请人工解锁", route.getName(),
route.getCode()));
} else {
SimulationDataRepository repository = simulation.getRepository();
if (repository.isTrainHeadOccupy(firstLogicSection)) {
trainUnlockStart(simulation, route);
}
}
}
Signal start = route.getStart();
int guideRemain = start.getGuideRemain();
if (guideRemain != 0) {
guideRemain -= SimulationConstants.CI_LOOP_RATE;
if (guideRemain <= 0) { //计时结束关闭信号
start.setGuideRemain(0);
signalControlService.tryControlSignalAspectAccordingLevel(simulation,
start, start.getDefaultAspect());
} else {
start.setGuideRemain(guideRemain);
}
}
if (route.isLock() && !route.isSetting()) {
ciService.interlockCheck(simulation, route);
if (!config.isRailway()) {
if (route.isOpenMain() && !start.isSupportMainAspect()) {//与联锁显示不同关闭信号
CiLogic.log.info("进路[{}]联锁条件不满足,关闭信号", route.debugStr());
signalControlService.tryControlSignalAspectAccordingLevel(simulation,
start, start.getDefaultAspect());
} else if (start.isDefaultAspect() && !start.isForbidden() && !start.isBlockade()
&& start.isSupportMainAspect()) {
CiLogic.log.info("进路[{}]联锁条件满足,开放信号", route.debugStr());
signalControlService.tryControlSignalAspectAccordingLevel(simulation,
start, route.getSettedAspect());
}
} else {
if (route.isOpenMain() && !start.isSupportMainAspect()) {//与联锁显示不同关闭信号
CiLogic.log.info("进路[{}]联锁条件不满足,关闭信号", route.debugStr());
signalControlService.tryControlSignalAspectAccordingLevel(simulation,
start, start.getDefaultAspect());
start.setForcePhysical(true); //大铁线路暂时限制自动重开信号
} else if (!start.isForbidden() && !start.isBlockade() && start.isSupportMainAspect()) {
SignalAspect aspect = route.getAspectOfRailway();
if (!Objects.equals(route.getStart().getAspect(), aspect)) {
signalControlService.tryControlSignalAspectAccordingLevel(simulation, start, aspect);
}
}
}
}
// 进路延续保护办理判断
if (config.isOverlapSettingByTrigger()) {
if (route.getOverlap() != null && route.getOverlap().getSignal()
.isApproachSectionOccupied()) {
ciService.checkAndTrySettingOverlap(simulation, route.getOverlap());
}
} else if (route.isSettingOverlap()) {
ciService.checkAndTrySettingOverlap(simulation, route.getOverlap());
}
}
}
public void trainUnlockStart(Simulation simulation, Route route) {
route.startNormalUnlock();
CiLogic.log.info("进路[{}]因列车进入,关闭信号", route.debugStr());
signalControlService.tryControlSignalAspectAccordingLevel(simulation,
route.getStart(), route.getStart().getDefaultAspect());
}
/**
* 延续保护进路监控
*
* @param simulation
* @param overlap
* @param unlockSwitchMap
* @return
*/
public void overlapMonitor(Simulation simulation, RouteOverlap overlap,
Map<Switch, Boolean> unlockSwitchMap) {
MapConfig config = simulation.getRepository().getConfig();
if (config.isOverlapSettingByTrigger() && overlap.isTriggerSectionOccupied()) {
ciService.checkAndTrySettingOverlap(simulation, overlap);
}
if (overlap.isSetting()) {
routeService.overlapSettingProcess(simulation, overlap);
}
if (overlap.isForbidden()) {
routeService.checkAndAllowOverlap(simulation, overlap);
}
if (overlap.isLock() && !ciService.interlockCheck(simulation, overlap)) {
overlap.setLock(false);
}
//区段锁闭完整的延续保护整体解锁逻辑
if (overlap.isSectionOverlapLocked()) {
if (simulation.getRepository().isTrainParking(overlap.getSection())) {
CiLogic.log.debug("列车停稳,延续保护[{}}],触发区段[{}}]立即解锁",
overlap.getName(),
overlap.getSection().debugStr());
overlap.releaseImmediately();
}
//延时解锁
if (overlap.isReleasing()) {
overlap.releaseProgress();
} else if (simulation.getRepository().isTrainHeadOccupy(overlap.getSection())) {
// 进路末区段列车占用进路开始延时解锁不能用区段占用作为条件非通信车占用范围太大导致延续保护太早开始延时解锁
overlap.startReleasing();
}
}
//统计需要/不能解锁的道岔
SectionPath sectionPath = overlap.selectPath();
List<Section> sections; //办理过程中锁闭的区段
if (!CollectionUtils.isEmpty(sectionPath.getLogicList())) {
sections = sectionPath.getLogicList();
} else {
sections = sectionPath.getSectionList();
}
for (Section section : sections) {
if (!section.isSwitchTrack()) {
continue;
}
if (section.isOverlapLock()) {
unlockSwitchMap.put(section.getRelSwitch(), false);
Switch linkedSwitch = section.getRelSwitch().queryLinkedSwitch();
if (sectionPath.containSwitch(linkedSwitch)) {
unlockSwitchMap.put(linkedSwitch, false);
}
} else if (section.getRelSwitch().isOverlapLock()) {
unlockSwitchMap.putIfAbsent(section.getRelSwitch(), true);
Switch linkedSwitch = section.getRelSwitch().queryLinkedSwitch();
if (sectionPath.containSwitch(linkedSwitch)) {
unlockSwitchMap.putIfAbsent(linkedSwitch, true);
}
}
}
}
/**
* 添加需要/不能延续保护解锁的道岔添加道岔后找到延续保护中对应的道岔判断是否要解除侧防并添加到Map中
*/
private void addSwitch(Map<Switch, Integer> map, Switch aSwitch, boolean unlock,
List<RouteFls> flsList) {
map.put(aSwitch, unlock ? 1 : -1);
for (RouteFls routeFls : flsList) {
if (routeFls.getBase().getASwitch().equals(aSwitch)) {
for (FlsElement element : routeFls.getLevel1List()) {
if (element.getPSwitch() != null) {
map.put(element.getPSwitch().getASwitch(), unlock ? 2 : -2);
}
}
}
}
}
}

View File

@ -613,7 +613,8 @@ public class CiRouteService {
}
Switch relSwitch = section.getRelSwitch();
relSwitch.routeUnlock(route);
relSwitch.overlapUnLock();
// relSwitch.overlapUnLock(); 仅解锁区段道岔的解锁由延续保护监控逻辑处理
section.overlapUnlocking();
// 侧防解锁
route.unlockRouteFlsOfSwitch(relSwitch);
//检查道岔的联动道岔和计轴关联道岔是否可以解锁
@ -726,7 +727,13 @@ public class CiRouteService {
sectionPath.getSwitchList(), false);
// 延续保护区段预先锁闭
if (onPos || config.isLockFirst()) {
this.checkAndLockOverlap(simulation, overlap);
this.checkAndLockOverlapSections(simulation, overlap);
}
// 延续保护道岔锁闭
if (onPos) {
for (SwitchElement switchElement : sectionPath.getSwitchList()) {
switchElement.getASwitch().overlapLock();
}
}
// 侧防办理
this.flsSetting(simulation, sectionPath.getFlsList());
@ -737,7 +744,7 @@ public class CiRouteService {
}
}
private void checkAndLockOverlap(Simulation simulation, RouteOverlap overlap) {
private void checkAndLockOverlapSections(Simulation simulation, RouteOverlap overlap) {
SectionPath sectionPath = overlap.selectPath();
boolean right = overlap.isRight();
//区段锁闭
@ -757,10 +764,6 @@ public class CiRouteService {
}
}
}
//道岔锁闭
for (SwitchElement switchElement : sectionPath.getSwitchList()) {
switchElement.getASwitch().overlapLock();
}
}
/**

View File

@ -3,282 +3,296 @@ package club.joylink.rtss.simulation.cbtc.data.map;
import club.joylink.rtss.simulation.cbtc.constant.SimulationModule;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
import java.time.LocalDateTime;
import java.util.List;
import lombok.Getter;
import lombok.Setter;
import org.springframework.util.CollectionUtils;
import java.time.LocalDateTime;
import java.util.List;
/**
* 进路延续保护
*/
@Getter
@Setter
public class RouteOverlap extends MapNamedElement {
public RouteOverlap(String code, String name) {
super(code, name, DeviceType.OVERLAP);
}
// ------------固有属性/关联关系-----------
List<SectionPath> pathList;
public RouteOverlap(String code, String name) {
super(code, name, DeviceType.OVERLAP);
}
/**
* 进路的最后子进路
*/
private Section section;
// ------------固有属性/关联关系-----------
List<SectionPath> pathList;
/**
* 延续保护方向
*/
private boolean right;
/**
* 进路的最后子进路
*/
private Section section;
/**
* 延续保护起始信号机
*/
private Signal signal;
/**
* 延续保护方向
*/
private boolean right;
/**
* 触发区段路径
*/
private List<SectionPath> triggerPathList;
/**
* 延续保护起始信号机
*/
private Signal signal;
/**
* 延时解锁时间
*/
private int delayReleaseTime;
/**
* 触发区段路径
*/
private List<SectionPath> triggerPathList;
// --------------状态属性-------------
/**
* 办理中
*/
private boolean setting;
/**
* 办理开始时间
*/
private LocalDateTime settingStartTime;
/**
* 是否锁闭
*/
private boolean lock;
/**
* 是否正在解锁
*/
private boolean releasing;
/**
* 禁止办理
*/
private boolean forbidden;
/**
* 剩余时间
*/
private int remainTime;
/**
* 延时解锁时间
*/
private int delayReleaseTime;
@Override
public void reset() {
this.setting = false;
this.settingStartTime = null;
this.lock = false;
this.releasing = false;
this.forbidden = false;
this.remainTime = 0;
}
// --------------状态属性-------------
/**
* 办理中
*/
private boolean setting;
/**
* 办理开始时间
*/
private LocalDateTime settingStartTime;
/**
* 是否锁闭
*/
private boolean lock;
/**
* 是否正在解锁
*/
private boolean releasing;
/**
* 禁止办理
*/
private boolean forbidden;
/**
* 剩余时间
*/
private int remainTime;
public void startSetting(LocalDateTime systemTime) {
this.setLock(false);
this.releasing = false;
this.settingStartTime = systemTime;
this.setting = true;
}
@Override
public void reset() {
this.setting = false;
this.settingStartTime = null;
this.lock = false;
this.releasing = false;
this.forbidden = false;
this.remainTime = 0;
}
public void settingOver() {
this.setting = false;
this.settingStartTime = null;
}
public void startSetting(LocalDateTime systemTime) {
this.setLock(false);
this.releasing = false;
this.settingStartTime = systemTime;
this.setting = true;
}
public boolean isSectionOverlapLocked() {
SectionPath sectionPath = this.selectPath();
if (!CollectionUtils.isEmpty(sectionPath.getLogicList())) {
for (Section logic : sectionPath.getLogicList()) {
if (!logic.isOverlapLockOn(this.isRight())) {
return false;
}
}
} else {
for (Section section1 : sectionPath.getSectionList()) {
if (!section1.isOverlapLockOn(this.isRight())) {
return false;
}
}
public void settingOver() {
this.setting = false;
this.settingStartTime = null;
}
public boolean isSectionOverlapLocked() {
SectionPath sectionPath = this.selectPath();
if (!CollectionUtils.isEmpty(sectionPath.getLogicList())) {
for (Section logic : sectionPath.getLogicList()) {
if (!logic.isOverlapLockOn(this.isRight())) {
return false;
}
}
} else {
for (Section section1 : sectionPath.getSectionList()) {
if (!section1.isOverlapLockOn(this.isRight())) {
return false;
}
}
}
return true;
}
/**
* 解锁开始
*/
public void startReleasing() {
this.remainTime = delayReleaseTime * 1000;
this.releasing = true;
}
public void allow() {
this.forbidden = false;
}
/**
* 立即解锁
*/
public void releaseImmediately() {
this.setting = false;
this.releasing = false;
this.forbidden = true;
this.remainTime = 0;
this.setLock(false);
SectionPath sectionPath = this.selectPath();
// 只解锁区段道岔及侧防由延续保护监控逻辑解锁
for (Section logic : sectionPath.getLogicList()) {
logic.overlapUnlocking();
}
for (Section section1 : sectionPath.getSectionList()) {
section1.overlapUnlocking();
if (section1.getLogicList() != null) {
for (Section logic : section1.getLogicList()) {
logic.overlapUnlocking();
}
}
}
// // 先解锁区段后解锁道岔
// for (Section logic : sectionPath.getLogicList()) {
// logic.overlapUnlocking();
// }
// for (Section section1 : sectionPath.getSectionList()) {
// section1.overlapUnlocking();
// if (section1.getLogicList() != null) {
// for (Section logic : section1.getLogicList()) {
// logic.overlapUnlocking();
// }
// }
// }
// List<RouteFls> flsList = sectionPath.getFlsList();
// for (SwitchElement element : sectionPath.getSwitchList()) {
// Switch aSwitch = element.getASwitch();
// aSwitch.overlapUnLock();
// unlockFlsOfSwitch(flsList, aSwitch);
// }
}
public void unlockFlsOfSwitch(List<RouteFls> flsList, Switch aSwitch) {
if (!CollectionUtils.isEmpty(flsList)) {
for (RouteFls routeFls : flsList) {
if (routeFls.getBase().getASwitch().equals(aSwitch) &&
!aSwitch.isRouteLock()) {
routeFls.unlock();
}
}
}
}
/**
* 延时解锁
*/
public void releaseProgress() {
if (this.releasing) { // 解锁中
this.remainTime -= SimulationModule.CI.getRateMs();
if (this.remainTime <= 0) {
this.releaseImmediately();
}
}
}
/**
* 包含直向路径
*
* @return
*/
public boolean hasStraightPath() {
for (SectionPath sectionPath : this.pathList) {
if (!sectionPath.containRpSwitch()) {
return true;
}
}
return false;
}
/**
* 解锁开始
*/
public void startReleasing() {
this.remainTime = delayReleaseTime * 1000;
this.releasing = true;
}
public void allow() {
this.forbidden = false;
}
/**
* 立即解锁
*/
public void releaseImmediately() {
this.setting = false;
this.releasing = false;
this.forbidden = true;
this.remainTime = 0;
this.setLock(false);
SectionPath sectionPath = this.selectPath();
// 先解锁区段后解锁道岔
for (Section logic : sectionPath.getLogicList()) {
logic.overlapUnlocking();
}
for (Section section1 : sectionPath.getSectionList()) {
section1.overlapUnlocking();
if (section1.getLogicList() != null) {
for (Section logic : section1.getLogicList()) {
logic.overlapUnlocking();
}
}
}
List<RouteFls> flsList = sectionPath.getFlsList();
for (SwitchElement element : sectionPath.getSwitchList()) {
Switch aSwitch = element.getASwitch();
aSwitch.overlapUnLock();
unlockFlsOfSwitch(flsList, aSwitch);
}
}
public void unlockFlsOfSwitch(List<RouteFls> flsList, Switch aSwitch) {
if (!CollectionUtils.isEmpty(flsList)) {
for (RouteFls routeFls : flsList) {
if (routeFls.getBase().getASwitch().equals(aSwitch) &&
!aSwitch.isRouteLock()) {
routeFls.unlock();
}
}
}
}
/**
* 延时解锁
*/
public void releaseProgress() {
if (this.releasing) { // 解锁中
this.remainTime -= SimulationModule.CI.getRateMs();
if (this.remainTime <= 0) {
this.releaseImmediately();
}
}
}
/**
* 包含直向路径
*
* @return
*/
public boolean hasStraightPath() {
for (SectionPath sectionPath : this.pathList) {
if (!sectionPath.containRpSwitch()) {
return true;
}
}
return false;
}
/**
* 包含反位道岔
*/
public boolean containRpSwitch() {
for (SectionPath sectionPath : this.pathList) {
if (sectionPath.containRpSwitch()) {
return true;
}
}
return false;
}
public boolean isOnlyOnePath() {
return !CollectionUtils.isEmpty(this.pathList) && this.pathList.size() == 1;
}
public SectionPath getFirstPath() {
if (!CollectionUtils.isEmpty(this.pathList)) {
return this.pathList.get(0);
} else {
throw new SimulationException(SimulationExceptionType.System_Fault);
}
}
public SectionPath selectPath() {
if (!CollectionUtils.isEmpty(this.pathList) && !this.isOnlyOnePath()) {
for (SectionPath sectionPath : this.pathList) {
if (!CollectionUtils.isEmpty(sectionPath.getSwitchList())) {
boolean onPosition = true;
for (SwitchElement element : sectionPath.getSwitchList()) {
if (element.getASwitch().isSectionOccupied()) {
onPosition = false;
break;
}
if (!element.isOnPosition()) {
onPosition = false;
break;
}
}
if (onPosition) {
return sectionPath;
}
} else {
return sectionPath;
}
}
}
return getFirstPath();
}
public boolean isTriggerSectionOccupied() {
// 触发区段是否占用
for (SectionPath path : this.triggerPathList) {
for (Section section1 : path.getSectionList()) {
if (section1.isOccupied()) {
return true;
}
}
}
return false;
}
public void setLock(boolean lock) {
this.signal.setOverlapLock(lock);
this.lock = lock;
}
public boolean containSection(Section section) {
return this.selectPath().containSection(section);
}
public boolean containSwitch(Switch aSwitch) {
return this.selectPath().containSwitch(aSwitch);
}
public boolean isStraight() {
if (CollectionUtils.isEmpty(pathList)) {
return true;
}
for (SectionPath path : pathList) {
for (SwitchElement se : path.getSwitchList()) {
if (!se.isNormal()) {
return false;
}
}
}
/**
* 包含反位道岔
*/
public boolean containRpSwitch() {
for (SectionPath sectionPath : this.pathList) {
if (sectionPath.containRpSwitch()) {
return true;
}
}
return false;
}
public boolean isOnlyOnePath() {
return !CollectionUtils.isEmpty(this.pathList) && this.pathList.size() == 1;
}
public SectionPath getFirstPath() {
if (!CollectionUtils.isEmpty(this.pathList)) {
return this.pathList.get(0);
} else {
throw new SimulationException(SimulationExceptionType.System_Fault);
}
}
public SectionPath selectPath() {
if (!CollectionUtils.isEmpty(this.pathList) && !this.isOnlyOnePath()) {
for (SectionPath sectionPath : this.pathList) {
if (!CollectionUtils.isEmpty(sectionPath.getSwitchList())) {
boolean onPosition = true;
for (SwitchElement element : sectionPath.getSwitchList()) {
if (element.getASwitch().isSectionOccupied()) {
onPosition = false;
break;
}
if (!element.isOnPosition()) {
onPosition = false;
break;
}
}
if (onPosition) {
return sectionPath;
}
} else {
return sectionPath;
}
}
}
return getFirstPath();
}
public boolean isTriggerSectionOccupied() {
// 触发区段是否占用
for (SectionPath path : this.triggerPathList) {
for (Section section1 : path.getSectionList()) {
if (section1.isOccupied()) {
return true;
}
}
}
return false;
}
public void setLock(boolean lock) {
this.signal.setOverlapLock(lock);
this.lock = lock;
}
public boolean containSection(Section section) {
return this.selectPath().containSection(section);
}
public boolean containSwitch(Switch aSwitch) {
return this.selectPath().containSwitch(aSwitch);
}
public boolean isStraight() {
if (CollectionUtils.isEmpty(pathList)) {
return true;
}
for (SectionPath path : pathList) {
for (SwitchElement se : path.getSwitchList()) {
if (!se.isNormal()) {
return false;
}
}
}
return true;
}
}

View File

@ -764,15 +764,6 @@ public class Section extends DelayUnlockDevice {
return this.routeLock && this.route.equals(route);
}
public void forceUnlocking() {
this.routeLock = false;
this.route = null;
this.overlapLock = false;
if (!isCross() && !CollectionUtils.isEmpty(this.logicList)) {
this.logicList.forEach(logic -> logic.forceUnlocking());
}
}
/**
* 进路延续保护(连同逻辑区段)
*/

View File

@ -546,19 +546,6 @@ public class TrainInfo extends MapElement {
}
public void updatePlanInfo(StationPlan nextStationPlan) {
// if (Objects.nonNull(nextStationPlan)) {
// this.planStandTrack = nextStationPlan.getSection().getCode();
// this.planArriveTime = nextStationPlan.getArriveTime();
// this.planLeaveTime = nextStationPlan.getLeaveTime();
// List<Stand> standList = nextStationPlan.getSection().getStandList();
// if (!CollectionUtils.isEmpty(standList)) {
// this.turnBackStrategy = standList.get(0).getTypeStrategy().name();
// }
// } else {
// this.planStandTrack = null;
// this.planArriveTime = null;
// this.planLeaveTime = null;
// }
if (Objects.nonNull(nextStationPlan)) {
updatePlanInfo(nextStationPlan.getSection(), nextStationPlan.getArriveTime(),
nextStationPlan.getLeaveTime());

View File

@ -12,103 +12,104 @@ import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
*/
public interface OnboardAtpApiService {
void updateCtcMa(Simulation simulation, MaService.Ma ma);
void updateCtcMa(Simulation simulation, MaService.Ma ma);
void updateItcMa(Simulation simulation, VirtualRealityTrain train, MaService.Ma ma);
void updateItcMa(Simulation simulation, VirtualRealityTrain train, MaService.Ma ma);
/**
* 更新CBTC移动授权
*/
void updateMA4CBTC(VirtualRealityTrain train, MovementAuthority ma);
/**
* 更新CBTC移动授权
*/
void updateMA4CBTC(VirtualRealityTrain train, MovementAuthority ma);
void updateMA4ITC(VirtualRealityTrain train, MovementAuthority ma);
void updateMA4ITC(VirtualRealityTrain train, MovementAuthority ma);
/**
* 分配新的车次计划
* @param simulation
* @param groupNumber
* @param tripPlan
*/
void updateTripPlan(Simulation simulation, String groupNumber, TripPlan tripPlan);
/**
* 分配新的车次计划
*
* @param simulation
* @param groupNumber
* @param tripPlan
*/
void updateTripPlan(Simulation simulation, String groupNumber, TripPlan tripPlan);
/**
* 发车
* @param simulation
* @param groupNumber
*/
void departure(Simulation simulation, String groupNumber);
/**
* 发车
*
* @param simulation
* @param groupNumber
*/
void departure(Simulation simulation, String groupNumber);
/**
* 更新下一站
* @param simulation
* @param groupNumber
* @param stationCode
* @param sectionCode
*/
void updateNextStation(Simulation simulation, String groupNumber, String stationCode, String sectionCode, long runningTime, boolean parking);
/**
* 更新下一计划到站信息
*
* @param simulation
* @param groupNumber
* @param planSection
* @param park
* @param runTime
* @param jump
*/
void updateNextArriveInfo(Simulation simulation, String groupNumber, Section planSection,
boolean park, int runTime, boolean jump);
/**
* 更新下一计划到站信息
* @param simulation
* @param groupNumber
* @param planSection
* @param park
* @param runTime
* @param jump
*/
void updateNextArriveInfo(Simulation simulation, String groupNumber, Section planSection, boolean park, int runTime, boolean jump);
/**
* 更新列车为头码车时设置服务号
*
* @param simulation
* @param groupNumber
* @param serviceNumber
*/
void update2HeadTrainServiceNumber(Simulation simulation, String groupNumber,
String serviceNumber, String tripNumber, String destinationCode, boolean parking);
/**
* 更新列车为头码车时设置服务号
* @param simulation
* @param groupNumber
* @param serviceNumber
*/
void update2HeadTrainServiceNumber(Simulation simulation, String groupNumber,
String serviceNumber, String tripNumber, String destinationCode, boolean parking);
/**
* 扣车
*
* @param simulation
* @param groupNumber
*/
void standHoldTrain(Simulation simulation, String groupNumber);
/**
* 扣车
* @param simulation
* @param groupNumber
*/
void standHoldTrain(Simulation simulation, String groupNumber);
/**
* 取消扣车
*
* @param simulation
* @param groupNumber
*/
void standCancelHoldTrain(Simulation simulation, String groupNumber);
/**
* 取消扣车
* @param simulation
* @param groupNumber
*/
void standCancelHoldTrain(Simulation simulation, String groupNumber);
/**
* 设置跳停
*
* @param simulation
* @param groupNumber
*/
void setJump(Simulation simulation, String groupNumber);
/**
* 设置跳停
* @param simulation
* @param groupNumber
*/
void setJump(Simulation simulation, String groupNumber);
/**
* 取消跳停
*
* @param simulation
* @param groupNumber
*/
void cancelJump(Simulation simulation, String groupNumber);
/**
* 取消跳停
* @param simulation
* @param groupNumber
*/
void cancelJump(Simulation simulation, String groupNumber);
/**
* 开始折返
*
* @param simulation
* @param groupNumber
* @param tbSectionCode
*/
void startTurnBack(Simulation simulation, String groupNumber, String tbSectionCode);
/**
* 开始折返
* @param simulation
* @param groupNumber
* @param tbSectionCode
*/
void startTurnBack(Simulation simulation, String groupNumber, String tbSectionCode);
void updateNextSection(Simulation simulation, String groupNumber, String targetCode);
void updateNextSection(Simulation simulation, String groupNumber, String targetCode);
void checkAndChangeDirection(Simulation simulation, VirtualRealityTrain train,
Section targetSection);
void checkAndChangeDirection(Simulation simulation, VirtualRealityTrain train,
Section targetSection);
void parkingInPlace(Simulation simulation, VirtualRealityTrain vrTrain, Section headSection);
void parkingInPlace(Simulation simulation, VirtualRealityTrain vrTrain, Section headSection);
void resetAtoSpeedMax(Simulation simulation, String groupNumber);
void resetAtoSpeedMax(Simulation simulation, String groupNumber);
}

View File

@ -6,252 +6,235 @@ import club.joylink.rtss.simulation.cbtc.constant.RunLevel;
import club.joylink.rtss.simulation.cbtc.data.CalculateService;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
import club.joylink.rtss.simulation.cbtc.data.map.Section;
import club.joylink.rtss.simulation.cbtc.data.map.Station;
import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan;
import club.joylink.rtss.simulation.cbtc.data.support.MovementAuthority;
import club.joylink.rtss.simulation.cbtc.data.support.RoutePath;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import club.joylink.rtss.simulation.cbtc.onboard.ATO.SpeedCurve;
import club.joylink.rtss.simulation.cbtc.onboard.ATO.service.ATOService;
import java.util.List;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Objects;
@Slf4j
@Component
public class OnboardAtpApiServiceImpl implements OnboardAtpApiService {
@Autowired
private ATPService ATPService;
@Autowired
private ATPService ATPService;
@Autowired
private ATOService ATOService;
@Autowired
private ATOService ATOService;
@Override
public void updateCtcMa(Simulation simulation, MaService.Ma ma) {
VirtualRealityTrain train = ma.getTrain();
@Override
public void updateCtcMa(Simulation simulation, MaService.Ma ma) {
VirtualRealityTrain train = ma.getTrain();
// log.debug(String.format("列车[%s]更新CTC-MA: %s", train.getGroupNumber(), ma.debugStr()));
SpeedCurve.calculateAndUpdate(simulation, train, ma);
train.setCbtcMaMissDuration(0);
}
SpeedCurve.calculateAndUpdate(simulation, train, ma);
train.setCbtcMaMissDuration(0);
}
@Override
public void updateItcMa(Simulation simulation, VirtualRealityTrain train, MaService.Ma ma) {
if (ma == null) {
return;
}
if (train.isCommunicable()) {
log.debug(String.format("列车[%s]是通信车不更新ITC-MA", train.getGroupNumber()));
}
if (!train.isCommunicable()) {
log.debug(String.format("列车[%s]更新ITC-MA: %s", train.getGroupNumber(), ma.debugStr()));
boolean update = SpeedCurve.calculateAndUpdate(simulation, train, ma);
if (train.isIL()) {
ATPService.updateRunLevel(train, RunLevel.ITC);
}
if (train.isReleased()) { // 释放状态
if (update) { // 成功更新取消释放状态的限速按ATO跑
log.debug(String.format("列车[%s]在释放状态成功更新ITC-MA取消释放以正常ATO继续运行",
train.getGroupNumber()));
} else { // 未更新EB
log.debug(String.format("列车[%s]以释放状态限速运行经过前方信号机主应答器却未更新ITC-MA导致EB",
train.getGroupNumber()));
this.ATPService.triggerSignalEB(train);
}
train.setReleased(false);
}
}
@Override
public void updateItcMa(Simulation simulation, VirtualRealityTrain train, MaService.Ma ma) {
if (ma == null) {
return;
}
@Override
public void updateMA4CBTC(VirtualRealityTrain train, MovementAuthority ma) {
if (ma == null)
return;
if (!train.isAtpOn()) {
return;
}
if (train.isCommunication()) {
this.ATPService.updateMA(train, ma);
train.setCbtcMaMissDuration(0);
}
if (train.isCommunicable()) {
log.debug(String.format("列车[%s]是通信车不更新ITC-MA", train.getGroupNumber()));
}
@Override
public void updateMA4ITC(VirtualRealityTrain train, MovementAuthority ma) {
if (ma == null)
return;
if (!train.isAtpOn()) {
return;
}
if (!train.isCommunication()) {
this.ATPService.updateMA(train, ma);
if (train.isIL()) {
train.setITCMode();
}
if (!train.isCommunicable()) {
log.debug(String.format("列车[%s]更新ITC-MA: %s", train.getGroupNumber(), ma.debugStr()));
boolean update = SpeedCurve.calculateAndUpdate(simulation, train, ma);
if (train.isIL()) {
ATPService.updateRunLevel(train, RunLevel.ITC);
}
if (train.isReleased()) { // 释放状态
if (update) { // 成功更新取消释放状态的限速按ATO跑
log.debug(String.format("列车[%s]在释放状态成功更新ITC-MA取消释放以正常ATO继续运行",
train.getGroupNumber()));
} else { // 未更新EB
log.debug(
String.format("列车[%s]以释放状态限速运行经过前方信号机主应答器却未更新ITC-MA导致EB",
train.getGroupNumber()));
this.ATPService.triggerSignalEB(train);
}
train.setReleased(false);
}
}
}
@Override
public void updateTripPlan(Simulation simulation, String groupNumber,
TripPlan tripPlan) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
String serviceNumber = tripPlan.getServiceNumber();
String tripNumber = tripPlan.getTripNumber();
String destinationCode = tripPlan.getDestinationCode();
train.setPlan(tripPlan);
log.debug(String.format("列车[%s-%s|%s|%s]更新新的车次计划[%s|%s|%s]",
train.getGroupNumber(), train.getServiceNumber(),
train.getTripNumber(), train.getDestinationCode(),
serviceNumber, tripNumber, destinationCode));
@Override
public void updateMA4CBTC(VirtualRealityTrain train, MovementAuthority ma) {
if (ma == null) {
return;
}
@Override
public void departure(Simulation simulation, String groupNumber) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
if (train.isParkingAt()) {
train.earlyDeparture();
}
if (!train.isAtpOn()) {
return;
}
if (train.isCommunication()) {
this.ATPService.updateMA(train, ma);
train.setCbtcMaMissDuration(0);
}
}
@Override
public void updateNextStation(Simulation simulation, String groupNumber,
String stationCode, String sectionCode, long runningTime, boolean parking) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
Station nextStation = repository.getByCode(stationCode, Station.class);
Section targetSection = repository.getByCode(sectionCode, Section.class);
if (Objects.equals(targetSection, train.getTarget())) {
// 已经更新忽略
return;
}
train.updateNextStationPlan(nextStation, targetSection, parking);
this.checkAndChangeDirection(simulation, train, targetSection);
//根据时间控制速度
@Override
public void updateMA4ITC(VirtualRealityTrain train, MovementAuthority ma) {
if (ma == null) {
return;
}
if (!train.isAtpOn()) {
return;
}
if (!train.isCommunication()) {
this.ATPService.updateMA(train, ma);
if (train.isIL()) {
train.setITCMode();
}
}
}
@Override
public void updateTripPlan(Simulation simulation, String groupNumber,
TripPlan tripPlan) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
String serviceNumber = tripPlan.getServiceNumber();
String tripNumber = tripPlan.getTripNumber();
String destinationCode = tripPlan.getDestinationCode();
train.setPlan(tripPlan);
log.debug(String.format("列车[%s-%s|%s|%s]更新新的车次计划[%s|%s|%s]",
train.getGroupNumber(), train.getServiceNumber(),
train.getTripNumber(), train.getDestinationCode(),
serviceNumber, tripNumber, destinationCode));
}
@Override
public void departure(Simulation simulation, String groupNumber) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
if (train.isParkingAt()) {
train.earlyDeparture();
}
}
@Override
public void updateNextArriveInfo(Simulation simulation, String groupNumber,
Section planSection, boolean park, int runTime, boolean jump) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
train.setJump(jump);
train.updateNextStationPlan(planSection.getStation(), planSection, park);
this.checkAndChangeDirection(simulation, train, planSection);
//根据时间控制速度
// runningTime -= 10; //减去开关门和延迟启动耗费的时间
Float atoMaxSpeed = CalculateService.calculateAtoSpeedMax4RunTime(repository, train, runningTime, targetSection);
if (atoMaxSpeed != null) {
train.setAtoSpeedMax(atoMaxSpeed);
}
Float atoMaxSpeed = CalculateService.calculateAtoSpeedMax4RunTime(repository, train, runTime,
planSection);
if (atoMaxSpeed != null) {
train.setAtoSpeedMax(atoMaxSpeed);
}
}
@Override
public void updateNextArriveInfo(Simulation simulation, String groupNumber,
Section planSection, boolean park, int runTime, boolean jump) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
train.setJump(jump);
train.updateNextStationPlan(planSection.getStation(), planSection, park);
this.checkAndChangeDirection(simulation, train, planSection);
//根据时间控制速度
// runningTime -= 10; //减去开关门和延迟启动耗费的时间
Float atoMaxSpeed = CalculateService.calculateAtoSpeedMax4RunTime(repository, train, runTime, planSection);
if (atoMaxSpeed != null) {
train.setAtoSpeedMax(atoMaxSpeed);
}
@Override
public void update2HeadTrainServiceNumber(Simulation simulation, String groupNumber,
String serviceNumber, String tripNumber, String destinationCode, boolean parking) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
train.setServiceNumber(serviceNumber);
train.setTripNumber(tripNumber);
train.setDestinationCode(destinationCode);
train.setNextParking(parking);
}
@Override
public void standHoldTrain(Simulation simulation, String groupNumber) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
if (!train.isTrainHold()) {
train.setHold(true);
}
}
@Override
public void update2HeadTrainServiceNumber(Simulation simulation, String groupNumber,
String serviceNumber, String tripNumber, String destinationCode, boolean parking) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
train.setServiceNumber(serviceNumber);
train.setTripNumber(tripNumber);
train.setDestinationCode(destinationCode);
train.setNextParking(parking);
@Override
public void standCancelHoldTrain(Simulation simulation, String groupNumber) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
if (!train.isTrainHold()) {
train.setHold(false);
}
}
@Override
public void standHoldTrain(Simulation simulation, String groupNumber) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
if (!train.isTrainHold()) {
train.setHold(true);
}
@Override
public void setJump(Simulation simulation, String groupNumber) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
train.setJump(true);
}
@Override
public void cancelJump(Simulation simulation, String groupNumber) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
train.setJump(false);
}
@Override
public void startTurnBack(Simulation simulation, String groupNumber, String tbSectionCode) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
Section tbSection = repository.getByCode(tbSectionCode, Section.class);
log.debug(String.format("列车[%s]准备折返", train.getGroupNumber()));
train.startTurnBack(tbSection);
this.checkAndChangeDirection(simulation, train, tbSection);
}
@Override
public void updateNextSection(Simulation simulation, String groupNumber, String targetCode) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
Section target = repository.getByCode(targetCode, Section.class);
if (Objects.equals(target, train.getTarget())) {
return;
}
@Override
public void standCancelHoldTrain(Simulation simulation, String groupNumber) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
if (!train.isTrainHold()) {
train.setHold(false);
}
}
@Override
public void setJump(Simulation simulation, String groupNumber) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
train.setJump(true);
}
@Override
public void cancelJump(Simulation simulation, String groupNumber) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
train.setJump(false);
}
@Override
public void startTurnBack(Simulation simulation, String groupNumber, String tbSectionCode) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
Section tbSection = repository.getByCode(tbSectionCode, Section.class);
log.debug(String.format("列车[%s]准备折返", train.getGroupNumber()));
train.startTurnBack(tbSection);
this.checkAndChangeDirection(simulation, train, tbSection);
}
@Override
public void updateNextSection(Simulation simulation, String groupNumber, String targetCode) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
Section target = repository.getByCode(targetCode, Section.class);
if (Objects.equals(target, train.getTarget())) {
return;
}
checkAndChangeDirection(simulation, train, target);
checkAndChangeDirection(simulation, train, target);
// train.setTarget(target);
}
}
@Override
public void checkAndChangeDirection(Simulation simulation, VirtualRealityTrain train,
Section targetSection) {
Objects.requireNonNull(targetSection);
SimulationDataRepository repository = simulation.getRepository();
boolean right = train.isRight();
Section headSection = train.getHeadPosition().getSection();
if (CalculateService.isTargetSectionOnDirectionExist(headSection, right, targetSection)) {
return;
} else if (CalculateService.isTargetSectionOnDirectionExist(headSection, !right, targetSection)) {
if (train.isAtoOn()) { //如果开启了ato
// 如果反向调头
this.ATPService.turnDirectionStart(train);
}
} else {
log.debug(String.format("列车[%s]无法到达目标轨道,根据路径判断是否调头", train.getGroupNumber()));
// 根据路径判断
if (headSection.isFunctionTrack() && targetSection.isFunctionTrack()) {
List<RoutePath> routePaths = repository.queryRoutePaths(headSection, targetSection);
if (!CollectionUtils.isEmpty(routePaths)) {
boolean pathRight = routePaths.get(0).isRight();
if (!Objects.equals(right, pathRight) && train.isAtoOn()) {
// 和计划方向不同并且开启了ATO调头
this.ATPService.turnDirectionStart(train);
}
}
}
@Override
public void checkAndChangeDirection(Simulation simulation, VirtualRealityTrain train,
Section targetSection) {
Objects.requireNonNull(targetSection);
SimulationDataRepository repository = simulation.getRepository();
boolean right = train.isRight();
Section headSection = train.getHeadPosition().getSection();
if (CalculateService.isTargetSectionOnDirectionExist(headSection, right, targetSection)) {
return;
} else if (CalculateService.isTargetSectionOnDirectionExist(headSection, !right,
targetSection)) {
if (train.isAtoOn()) { //如果开启了ato
// 如果反向调头
this.ATPService.turnDirectionStart(train);
}
} else {
log.debug(
String.format("列车[%s]无法到达目标轨道,根据路径判断是否调头", train.getGroupNumber()));
// 根据路径判断
if (headSection.isFunctionTrack() && targetSection.isFunctionTrack()) {
List<RoutePath> routePaths = repository.queryRoutePaths(headSection, targetSection);
if (!CollectionUtils.isEmpty(routePaths)) {
boolean pathRight = routePaths.get(0).isRight();
if (!Objects.equals(right, pathRight) && train.isAtoOn()) {
// 和计划方向不同并且开启了ATO调头
this.ATPService.turnDirectionStart(train);
}
}
}
// if (train.getRobotTargetPosition() != null) { //如果列车被托管
// return;
// }
// 列车目标区段无法到达根据路径单元判定
// 列车目标区段无法到达根据路径单元判定
// if (headSection.isSwitchTrack() && headSection.getParent().isTurnBackTrack()) {
// headSection = headSection.getParent();
// }
@ -278,17 +261,18 @@ public class OnboardAtpApiServiceImpl implements OnboardAtpApiService {
// this.newATPService.turnDirectionStart(train);
// }
// }
}
}
}
@Override
public void parkingInPlace(Simulation simulation, VirtualRealityTrain vrTrain, Section headSection) {
vrTrain.parkingAt(headSection);
}
@Override
public void parkingInPlace(Simulation simulation, VirtualRealityTrain vrTrain,
Section headSection) {
vrTrain.parkingAt(headSection);
}
@Override
public void resetAtoSpeedMax(Simulation simulation, String groupNumber) {
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
train.resetAtoSpeedMax();
}
@Override
public void resetAtoSpeedMax(Simulation simulation, String groupNumber) {
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
train.resetAtoSpeedMax();
}
}

View File

@ -9,7 +9,15 @@ import club.joylink.rtss.simulation.cbtc.constant.SignalAspect;
import club.joylink.rtss.simulation.cbtc.constant.SwitchIndication;
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.map.MapConfig;
import club.joylink.rtss.simulation.cbtc.data.map.Route;
import club.joylink.rtss.simulation.cbtc.data.map.RouteFls;
import club.joylink.rtss.simulation.cbtc.data.map.RouteOverlap;
import club.joylink.rtss.simulation.cbtc.data.map.Section;
import club.joylink.rtss.simulation.cbtc.data.map.SectionPath;
import club.joylink.rtss.simulation.cbtc.data.map.Signal;
import club.joylink.rtss.simulation.cbtc.data.map.Switch;
import club.joylink.rtss.simulation.cbtc.data.map.SwitchElement;
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.vr.VirtualRealitySignal;
@ -17,291 +25,306 @@ import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySwitch;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import club.joylink.rtss.simulation.cbtc.device.virtual.VRTrainRunningService;
import club.joylink.rtss.simulation.cbtc.device.virtual.VirtualRealityDeviceService;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* 设备状态修改工具有动作设备不需要动作过程可直接设置为想要的状态
* warn此工具类只在加载列车或实训生成场景使用正常仿真过程请勿使用
* 设备状态修改工具有动作设备不需要动作过程可直接设置为想要的状态 warn此工具类只在加载列车或实训生成场景使用正常仿真过程请勿使用
*/
@Slf4j
@Component
public class DeviceStatusModifyTool {
@Autowired
private VirtualRealityDeviceService virtualRealityDeviceService;
@Autowired
private CiRouteService routeService;
@Autowired
private AtsTrainLoadService atsTrainLoadService;
@Autowired
private VRTrainRunningService vrTrainRunningService;
/**
* 直接开放进路
*
* @param route
*/
public void openRouteDirect(Simulation simulation, Route route) {
// 修改进路涉及的所有道岔元素到指定位置
this.batchSetRouteSwitchPositionAndLock(route, route.getSwitchList(), true);
// 修改进路侧防到指定位置
this.batchSetRouteFlsSwitchPositionAndLock(route.getFlsList());
// 进路元素锁闭
route.getSectionList().forEach(section -> section.routeLocking(route, route.getStart().isRight()));
if (route.isSettingOverlap()) {
SectionPath overlapPath = route.selectOverlapElement();
if (Objects.nonNull(overlapPath)) {
this.batchSetRouteFlsSwitchPositionAndLock(overlapPath.getFlsList());
this.batchSetRouteSwitchPositionAndLock(route, overlapPath.getSwitchList(), false);
overlapPath.getSectionList().forEach(section -> section.overlapLocking(route.getStart().isRight()));
this.batchSetRouteFlsSwitchPositionAndLock(overlapPath.getFlsList());
route.getOverlap().setLock(true);
}
}
route.setNormalUnlock(false);
route.setLock(true);
route.setSettedAspect(route.getAspect());
simulation.getRepository().addSettingRoute(route);
this.openSignalDirectly(route.getStart(), route.getSettedAspect());
route.getStart().setLockedRoute(route);
@Autowired
private VirtualRealityDeviceService virtualRealityDeviceService;
@Autowired
private CiRouteService routeService;
@Autowired
private AtsTrainLoadService atsTrainLoadService;
@Autowired
private VRTrainRunningService vrTrainRunningService;
/**
* 直接开放进路
*
* @param route
*/
public void openRouteDirect(Simulation simulation, Route route) {
// 修改进路涉及的所有道岔元素到指定位置
this.batchSetRouteSwitchPositionAndLock(route, route.getSwitchList(), true,
route.getOverlap());
// 修改进路侧防到指定位置
this.batchSetRouteFlsSwitchPositionAndLock(route.getFlsList());
// 进路元素锁闭
route.getSectionList()
.forEach(section -> section.routeLocking(route, route.getStart().isRight()));
if (route.isSettingOverlap()) {
SectionPath overlapPath = route.selectOverlapElement();
if (Objects.nonNull(overlapPath)) {
this.batchSetRouteFlsSwitchPositionAndLock(overlapPath.getFlsList());
this.batchSetRouteSwitchPositionAndLock(route, overlapPath.getSwitchList(), false,
route.getOverlap());
overlapPath.getSectionList()
.forEach(section -> section.overlapLocking(route.getStart().isRight()));
this.batchSetRouteFlsSwitchPositionAndLock(overlapPath.getFlsList());
route.getOverlap().setLock(true);
}
}
route.setNormalUnlock(false);
route.setLock(true);
route.setSettedAspect(route.getAspect());
simulation.getRepository().addSettingRoute(route);
this.openSignalDirectly(route.getStart(), route.getSettedAspect());
route.getStart().setLockedRoute(route);
}
private void batchSetRouteFlsSwitchPositionAndLock(List<RouteFls> flsList) {
if (!CollectionUtils.isEmpty(flsList)) {
List<SwitchElement> switchElementList = new ArrayList<>();
for (RouteFls routeFls : flsList) {
for (RouteFls.FlsElement flsElement : routeFls.getLevel1List()) {
SwitchElement pSwitch = flsElement.getPSwitch();
if (pSwitch != null) {
switchElementList.add(pSwitch);
} else if (flsElement.getFpae() != null) {
switchElementList.add(flsElement.getFpae());
}
}
}
for (SwitchElement switchElement : switchElementList) {
private void batchSetRouteFlsSwitchPositionAndLock(List<RouteFls> flsList) {
if (!CollectionUtils.isEmpty(flsList)) {
List<SwitchElement> switchElementList = new ArrayList<>();
for (RouteFls routeFls : flsList) {
for (RouteFls.FlsElement flsElement : routeFls.getLevel1List()) {
SwitchElement pSwitch = flsElement.getPSwitch();
if (pSwitch != null) {
switchElementList.add(pSwitch);
} else if (flsElement.getFpae() != null) {
switchElementList.add(flsElement.getFpae());
}
}
}
for (SwitchElement switchElement : switchElementList) {
// switchElement.getASwitch().ciUse(switchElement.isNormal());
this.setSingleSwitchPositionDirectly(switchElement.getASwitch(), switchElement.isNormal());
switchElement.getASwitch().fpLock();
}
}
this.setSingleSwitchPositionDirectly(switchElement.getASwitch(), switchElement.isNormal());
switchElement.getASwitch().fpLock();
}
}
}
public void openGuideRouteDirect(Simulation simulation, Route route) {
// 修改进路涉及的所有道岔元素到指定位置
this.batchSetRouteSwitchPositionAndLock(route, route.getSwitchList(), true);
// 修改进路侧防到指定位置
this.batchSetRouteFlsSwitchPositionAndLock(route.getFlsList());
// 进路元素锁闭
route.getSectionList().forEach(section -> section.routeLocking(route, route.getStart().isRight()));
SectionPath overlapPath = route.selectOverlapElement();
if (Objects.nonNull(overlapPath)) {
this.batchSetRouteSwitchPositionAndLock(route, overlapPath.getSwitchList(), false);
this.batchSetRouteFlsSwitchPositionAndLock(overlapPath.getFlsList());
overlapPath.getSectionList().forEach(section -> section.overlapLocking(route.getStart().isRight()));
}
route.setLock(true);
this.openGuideSignalDirectly(route.getStart());
route.getStart().setLockedRoute(route);
public void openGuideRouteDirect(Simulation simulation, Route route) {
// 修改进路涉及的所有道岔元素到指定位置
this.batchSetRouteSwitchPositionAndLock(route, route.getSwitchList(), true,
route.getOverlap());
// 修改进路侧防到指定位置
this.batchSetRouteFlsSwitchPositionAndLock(route.getFlsList());
// 进路元素锁闭
route.getSectionList()
.forEach(section -> section.routeLocking(route, route.getStart().isRight()));
SectionPath overlapPath = route.selectOverlapElement();
if (Objects.nonNull(overlapPath)) {
this.batchSetRouteSwitchPositionAndLock(route, overlapPath.getSwitchList(), false,
route.getOverlap());
this.batchSetRouteFlsSwitchPositionAndLock(overlapPath.getFlsList());
overlapPath.getSectionList()
.forEach(section -> section.overlapLocking(route.getStart().isRight()));
}
route.setLock(true);
this.openGuideSignalDirectly(route.getStart());
route.getStart().setLockedRoute(route);
}
public void openGuideSignalDirectly(Signal signal) {
VirtualRealitySignal virtualSignal = signal.getVirtualSignal();
SignalAspect guideAspect = virtualSignal.getModel().getGuideAspect();
virtualSignal.control(guideAspect);
virtualSignal.finish();
signal.changeLightType(false);
signal.setAspect(guideAspect);
public void openGuideSignalDirectly(Signal signal) {
VirtualRealitySignal virtualSignal = signal.getVirtualSignal();
SignalAspect guideAspect = virtualSignal.getModel().getGuideAspect();
virtualSignal.control(guideAspect);
virtualSignal.finish();
signal.changeLightType(false);
signal.setAspect(guideAspect);
}
/**
* 直接开灯(默认逻辑点灯)
*
* @param signal
* @param aspect
*/
private void openSignalDirectly(Signal signal, SignalAspect aspect) {
VirtualRealitySignal virtualSignal = signal.getVirtualSignal();
signal.changeLightType(true);
if (virtualSignal != null) {
if (signal.isLogicLight()) {
virtualSignal.control(SignalAspect.No);
} else {
virtualSignal.control(aspect);
}
virtualSignal.finish();
}
signal.setAspect(aspect);
}
/**
* 直接开灯(默认逻辑点灯)
*
* @param signal
* @param aspect
*/
private void openSignalDirectly(Signal signal, SignalAspect aspect) {
VirtualRealitySignal virtualSignal = signal.getVirtualSignal();
signal.changeLightType(true);
if (virtualSignal != null) {
if (signal.isLogicLight()) {
virtualSignal.control(SignalAspect.No);
} else {
virtualSignal.control(aspect);
}
virtualSignal.finish();
}
signal.setAspect(aspect);
/**
* 直接关灯(默认逻辑点灯)
*
* @param signal
*/
public void closeSignalDirectly(Signal signal) {
VirtualRealitySignal virtualSignal = signal.getVirtualSignal();
signal.changeLightType(true);
SignalAspect defaultAspect = virtualSignal.getModel().getDefaultAspect();
if (signal.isLogicLight()) {
virtualSignal.control(SignalAspect.No);
} else {
virtualSignal.control(defaultAspect);
}
virtualSignal.finish();
signal.setAspect(defaultAspect);
}
/**
* 直接关灯(默认逻辑点灯)
*
* @param signal
*/
public void closeSignalDirectly(Signal signal) {
VirtualRealitySignal virtualSignal = signal.getVirtualSignal();
signal.changeLightType(true);
SignalAspect defaultAspect = virtualSignal.getModel().getDefaultAspect();
if (signal.isLogicLight()) {
virtualSignal.control(SignalAspect.No);
} else {
virtualSignal.control(defaultAspect);
}
virtualSignal.finish();
signal.setAspect(defaultAspect);
}
/**
* 批量设置进路道岔位置并锁闭
*
* @param route
* @param switchList
* @param routeLock
*/
private void batchSetRouteSwitchPositionAndLock(Route route, List<SwitchElement> switchList, boolean routeLock) {
if (!CollectionUtils.isEmpty(switchList)) {
for (SwitchElement switchElement : switchList) {
/**
* 批量设置进路道岔位置并锁闭
*
* @param route
* @param switchList
* @param routeLock
* @param overlap
*/
private void batchSetRouteSwitchPositionAndLock(Route route, List<SwitchElement> switchList,
boolean routeLock,
RouteOverlap overlap) {
if (!CollectionUtils.isEmpty(switchList)) {
for (SwitchElement switchElement : switchList) {
// if (switchElement.getASwitch().isOverlapLock() &&
// switchElement.isOnPosition()) {
// continue;
// }
// switchElement.getASwitch().ciUse(switchElement.isNormal());
this.setSingleSwitchPositionDirectly(switchElement.getASwitch(), switchElement.isNormal());
if (routeLock) {
switchElement.getASwitch().routeLock(route);
} else { // 延续保护锁闭
switchElement.getASwitch().overlapLock();
}
}
this.setSingleSwitchPositionDirectly(switchElement.getASwitch(), switchElement.isNormal());
if (routeLock) {
switchElement.getASwitch().routeLock(route);
} else { // 延续保护锁闭
switchElement.getASwitch().overlapLock();
}
}
}
}
/**
* 直接把单个道岔转到指定位置
*
* @param aSwitch
* @param normal
*/
public void setSingleSwitchPositionDirectly(Switch aSwitch, boolean normal) {
VirtualRealitySwitch virtualSwitch = aSwitch.getVirtualSwitch();
if (normal) {
virtualSwitch.control(VirtualRealitySwitch.Operation.NP);
virtualSwitch.finish();
aSwitch.setPos(SwitchIndication.N);
} else {
virtualSwitch.control(VirtualRealitySwitch.Operation.RP);
virtualSwitch.finish();
aSwitch.setPos(SwitchIndication.R);
}
/**
* 直接把单个道岔转到指定位置
*
* @param aSwitch
* @param normal
*/
public void setSingleSwitchPositionDirectly(Switch aSwitch, boolean normal) {
VirtualRealitySwitch virtualSwitch = aSwitch.getVirtualSwitch();
if (normal) {
virtualSwitch.control(VirtualRealitySwitch.Operation.NP);
virtualSwitch.finish();
aSwitch.setPos(SwitchIndication.N);
} else {
virtualSwitch.control(VirtualRealitySwitch.Operation.RP);
virtualSwitch.finish();
aSwitch.setPos(SwitchIndication.R);
}
}
/**
* 直接把道岔及其联动道岔转动到指定位置
*
* @param aSwitch
* @param normal
*/
public void setCoupleSwitchPositionDirectly(Simulation simulation, Switch aSwitch, boolean normal) {
SimulationDataRepository repository = simulation.getRepository();
this.setSingleSwitchPositionDirectly(aSwitch, normal);
Switch linkedSwitch = aSwitch.queryLinkedSwitch();
if (Objects.nonNull(linkedSwitch)) {
this.setSingleSwitchPositionDirectly(linkedSwitch, normal);
}
/**
* 直接把道岔及其联动道岔转动到指定位置
*
* @param aSwitch
* @param normal
*/
public void setCoupleSwitchPositionDirectly(Simulation simulation, Switch aSwitch,
boolean normal) {
SimulationDataRepository repository = simulation.getRepository();
this.setSingleSwitchPositionDirectly(aSwitch, normal);
Switch linkedSwitch = aSwitch.queryLinkedSwitch();
if (Objects.nonNull(linkedSwitch)) {
this.setSingleSwitchPositionDirectly(linkedSwitch, normal);
}
}
/**
* 直接根据最后一根区段解锁进路
*
* @param route
*/
public void routeUnlockByEndSection(Route route, Section tailSection) {
if (!route.isRouteSection(tailSection)) {
// 不是进路区段不解锁
return;
}
route.startNormalUnlock();
// 关闭始端信号机
openSignalDirectly(route.getStart(), route.getStart().getSignalModel().getDefaultAspect());
boolean right = route.getStart().isRight();
// 区段是顺序的(否则会有问题)
List<Section> sectionList = route.getSectionList();
for (Section section : sectionList) {
if (section.isSamePhysical(tailSection.getCode())) {
route.updateUnlockedSection(tailSection);
break;
}
// 直接解锁区段
if (section.isSwitchTrack()) { // 如果是道岔区段解锁道岔
Switch relSwitch = section.getRelSwitch();
if (tailSection.isSwitchTrack() && tailSection.getRelSwitch().equals(relSwitch)) {
route.updateUnlockedSection(tailSection);
break;
}
if (section.getParent() != null && section.getParent().isCross()) {
section.getParent().routeUnlocking(route);
}
relSwitch.routeUnlock(route);
relSwitch.overlapUnLock();
// 侧防解锁
route.unlockRouteFlsOfSwitch(relSwitch);
//检查道岔的联动道岔和计轴关联道岔是否可以解锁
for (SwitchElement switchElement : route.getSwitchList()) {
if (switchElement.getASwitch().equals(relSwitch)) {
continue;
}
Switch aSwitch = switchElement.getASwitch();
if (route.isRouteSection(aSwitch.getA())) {
continue;
}
if (relSwitch.isLinkedSwitch(aSwitch) || relSwitch.isBConnectTo(aSwitch)) {
if (!aSwitch.getA().isRouteLock()) {
aSwitch.routeUnlock(route);
aSwitch.overlapUnLock();
}
}
}
} else {
section.routeUnlocking(route);
}
}
/**
* 直接根据最后一根区段解锁进路
*
* @param route
*/
public void routeUnlockByEndSection(Route route, Section tailSection) {
if (!route.isRouteSection(tailSection)) {
// 不是进路区段不解锁
return;
}
route.startNormalUnlock();
// 关闭始端信号机
openSignalDirectly(route.getStart(), route.getStart().getSignalModel().getDefaultAspect());
boolean right = route.getStart().isRight();
// 区段是顺序的(否则会有问题)
List<Section> sectionList = route.getSectionList();
for (Section section : sectionList) {
if (section.isSamePhysical(tailSection.getCode())) {
route.updateUnlockedSection(tailSection);
break;
}
// 直接解锁区段
if (section.isSwitchTrack()) { // 如果是道岔区段解锁道岔
Switch relSwitch = section.getRelSwitch();
if (tailSection.isSwitchTrack() && tailSection.getRelSwitch().equals(relSwitch)) {
route.updateUnlockedSection(tailSection);
break;
}
if (section.getParent() != null && section.getParent().isCross()) {
section.getParent().routeUnlocking(route);
}
relSwitch.routeUnlock(route);
relSwitch.overlapUnLock();
// 侧防解锁
route.unlockRouteFlsOfSwitch(relSwitch);
//检查道岔的联动道岔和计轴关联道岔是否可以解锁
for (SwitchElement switchElement : route.getSwitchList()) {
if (switchElement.getASwitch().equals(relSwitch)) {
continue;
}
Switch aSwitch = switchElement.getASwitch();
if (route.isRouteSection(aSwitch.getA())) {
continue;
}
if (relSwitch.isLinkedSwitch(aSwitch) || relSwitch.isBConnectTo(aSwitch)) {
if (!aSwitch.getA().isRouteLock()) {
aSwitch.routeUnlock(route);
aSwitch.overlapUnLock();
}
}
}
} else {
section.routeUnlocking(route);
}
}
}
public void loadManualTrainOfGroup(Simulation simulation, String groupNumber, Section section, boolean right) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
if (!section.isPhysical()) {
section = section.getParent();
}
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotNull(section.isPhysical(), "列车需加载到物理区段上");
//重叠检测
SectionPosition headPosition = new SectionPosition(section, section.getStopPointByDirection(right));
SectionPosition tailPosition = CalculateService.calculateNextPositionByStartAndLen(headPosition, !right, train.getLen(), false);
boolean willOverlap = vrTrainRunningService.willOverlap(simulation, headPosition, tailPosition);
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(willOverlap, "列车重叠");
// 列车上线并构建ATS监控列车信息
train.initManualTrain(headPosition, right);
//设置列车预选模式驾驶模式运行级别
if (!headPosition.getSection().anyZcWorking()) {
train.initAsRM();
} else {
MapConfig config = repository.getConfig();
if (RunLevel.ITC.equals(config.getRunMode())) {
train.initAsAM_I();
} else if (RunLevel.IL.equals(config.getRunMode())) {
train.initAsRM();
}
}
TrainInfo trainInfo = TrainInfo.constructManualTrain(train);
trainInfo.tracking(train);
repository.addOnlineTrain(train);
repository.addTrainInfo(trainInfo);
public void loadManualTrainOfGroup(Simulation simulation, String groupNumber, Section section,
boolean right) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
if (!section.isPhysical()) {
section = section.getParent();
}
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotNull(section.isPhysical(),
"列车需加载到物理区段上");
//重叠检测
SectionPosition headPosition = new SectionPosition(section,
section.getStopPointByDirection(right));
SectionPosition tailPosition = CalculateService.calculateNextPositionByStartAndLen(headPosition,
!right, train.getLen(), false);
boolean willOverlap = vrTrainRunningService.willOverlap(simulation, headPosition, tailPosition);
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(willOverlap, "列车重叠");
// 列车上线并构建ATS监控列车信息
train.initManualTrain(headPosition, right);
//设置列车预选模式驾驶模式运行级别
if (!headPosition.getSection().anyZcWorking()) {
train.initAsRM();
} else {
MapConfig config = repository.getConfig();
if (RunLevel.ITC.equals(config.getRunMode())) {
train.initAsAM_I();
} else if (RunLevel.IL.equals(config.getRunMode())) {
train.initAsRM();
}
}
TrainInfo trainInfo = TrainInfo.constructManualTrain(train);
trainInfo.tracking(train);
repository.addOnlineTrain(train);
repository.addTrainInfo(trainInfo);
}
}