ats进路触发逻辑修改以处理小交路折返堵车问题(西安三香湖湾);侧防满足条件修改;修改强制取消进路线路配置描述及取消进路操作逻辑;修改信号机接近区段占用、进路接近锁闭的判断逻辑。修改宁波、哈尔滨、西安三若干问题

This commit is contained in:
joylink_zhangsai 2021-05-26 13:15:27 +08:00
parent d655347512
commit 076b1ad6f8
22 changed files with 241 additions and 191 deletions

View File

@ -3,6 +3,7 @@ package club.joylink.rtss.services.runplan;
import club.joylink.rtss.constants.BusinessConsts;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.vo.client.map.MapVO;
import club.joylink.rtss.vo.client.map.RealLineConfigVO;
import club.joylink.rtss.vo.client.runplan.RunPlanTripTimeVO;
import club.joylink.rtss.vo.client.runplan.RunPlanTripVO;
import club.joylink.rtss.vo.client.runplan.user.*;
@ -32,6 +33,8 @@ public class RunPlanGenerator {
private IRunPlanUserConfigService runPlanUserConfigService;
public List<RunPlanTripVO> generatorTrips(Long userId, RunPlanInputData inputData, MapVO mapVO) {
RealLineConfigVO configVO = mapVO.getConfigVO();
String serviceFormat = String.format("%%0%sd", configVO.getFiguresOfServiceNumber());
//校验时间
checkInputTime(inputData);
RunPlanRoutingVO running1Routing = runPlanRoutingService.queryUserRoutingById(userId, mapVO.getId(), inputData.getRunningRouting1());
@ -61,7 +64,7 @@ public class RunPlanGenerator {
tripList.addAll(serviceTripList1);
LocalTime departEndTime2 = serviceTripList1.get(1).getTimeList().get(0).getArrivalTime();
inputData.setServiceNumber(String.format("%03d", startServiceNumber + 1));
inputData.setServiceNumber(String.format(serviceFormat, startServiceNumber + 1));
LinkedList<RunPlanTripVO> serviceTripList2 = generateService(inputData, mapVO, inboundRoutings, running2Routing, running1Routing, runLevelMap, parkTimeMap, reentryData);
tripList.addAll(serviceTripList2);
LocalTime departEndTime1 = serviceTripList2.get(1).getTimeList().get(0).getArrivalTime();
@ -69,32 +72,32 @@ public class RunPlanGenerator {
Routing2BoundInfo outBoundRouting2 = null;
Routing2BoundInfo outBoundRouting1 = null;
if (inputData.hasOutAndInBound()) {
outBoundRouting1 = getOutboundRouting(running1Routing, outboundRoutings,runLevelMap);
outBoundRouting2 = getOutboundRouting(running2Routing, outboundRoutings,runLevelMap);
outBoundRouting1 = getOutboundRouting(running1Routing, outboundRoutings, runLevelMap);
outBoundRouting2 = getOutboundRouting(running2Routing, outboundRoutings, runLevelMap);
if (Objects.nonNull(outBoundRouting1) && Objects.nonNull(outBoundRouting2)) {
setOutBoundTripTimes(runLevelMap, parkTimeMap, reentryData, serviceTripList1, outBoundRouting1);
setOutBoundTripTimes(runLevelMap, parkTimeMap, reentryData, serviceTripList2, outBoundRouting2);
} else if (Objects.nonNull(outBoundRouting1)) {
tripList.removeAll(serviceTripList2);
setOutBoundTripTimes(runLevelMap, parkTimeMap, reentryData, serviceTripList1, outBoundRouting1);
inputData.setServiceNumber(String.format("%03d", startServiceNumber + 2));
inputData.setServiceNumber(String.format(serviceFormat, startServiceNumber + 2));
departEndTime1 = serviceTripList1.get(2).getTimeList().get(0).getArrivalTime();
generateServices(inputData, mapVO, running1Routing, running2Routing, inboundRoutings, outBoundRouting1, runLevelMap, parkTimeMap, reentryData, tripList, initBeginTime, departEndTime1);
return tripList;
} else if (Objects.nonNull(outBoundRouting2)) {
tripList.removeAll(serviceTripList1);
setOutBoundTripTimes(runLevelMap, parkTimeMap, reentryData, serviceTripList2, outBoundRouting2);
inputData.setServiceNumber(String.format("%03d", startServiceNumber + 3));
inputData.setServiceNumber(String.format(serviceFormat, startServiceNumber + 3));
departEndTime2 = serviceTripList2.get(2).getTimeList().get(0).getArrivalTime();
generateServices(inputData, mapVO, running2Routing, running1Routing, inboundRoutings, outBoundRouting2, runLevelMap, parkTimeMap, reentryData, tripList, initBeginTime, departEndTime2);
return tripList;
}
}
//相向发车
inputData.setServiceNumber(String.format("%03d", startServiceNumber + 2));
inputData.setServiceNumber(String.format(serviceFormat, startServiceNumber + 2));
generateServices(inputData, mapVO, running1Routing, running2Routing, inboundRoutings, outBoundRouting1, runLevelMap, parkTimeMap, reentryData, tripList, initBeginTime, departEndTime1);
inputData.setServiceNumber(String.format("%03d", startServiceNumber + 3));
inputData.setServiceNumber(String.format(serviceFormat, startServiceNumber + 3));
generateServices(inputData, mapVO, running2Routing, running1Routing, inboundRoutings, outBoundRouting2, runLevelMap, parkTimeMap, reentryData, tripList, initBeginTime, departEndTime2);
} else {
@ -104,11 +107,11 @@ public class RunPlanGenerator {
//另一个交路
RunPlanRoutingVO otherLoop = running2Routing;
if (inputData.hasOutAndInBound()) {
outBoundRouting = getOutboundRouting(running1Routing, outboundRoutings,runLevelMap);
outBoundRouting = getOutboundRouting(running1Routing, outboundRoutings, runLevelMap);
outRefLoop = running1Routing;
otherLoop = running2Routing;
if (Objects.isNull(outBoundRouting)) {
outBoundRouting = getOutboundRouting(running2Routing, outboundRoutings,runLevelMap);
outBoundRouting = getOutboundRouting(running2Routing, outboundRoutings, runLevelMap);
outRefLoop = running2Routing;
otherLoop = running1Routing;
}
@ -136,13 +139,16 @@ public class RunPlanGenerator {
Map<String, Integer> runLevelMap, Map<String, Integer> parkTimeMap, Map<String, RunPlanUserConfigVO.ReentryTime> reentryData,
List<RunPlanTripVO> tripList,
LocalTime initBeginTime, LocalTime departEndTime) {
RealLineConfigVO configVO = mapVO.getConfigVO();
String serviceFormat = String.format("%%0%sd", configVO.getFiguresOfServiceNumber());
LinkedList<RunPlanTripVO> serviceTripList;
inputData.setBeginTime(initBeginTime);
LocalTime preServiceDepartTime = inputData.getBeginTime();
while (preServiceDepartTime.plusSeconds(inputData.getDepartureInterval() * 2).compareTo(Objects.nonNull(departEndTime) ? departEndTime : LocalTime.of(12, 0)) <= 0) {
inputData.setBeginTime(inputData.getBeginTime().plusSeconds(inputData.getDepartureInterval()));
serviceTripList = generateService(inputData, mapVO, inboundRoutings, running1Routing, running2Routing, runLevelMap, parkTimeMap, reentryData);
inputData.setServiceNumber(String.format("%03d", Integer.parseInt(inputData.getServiceNumber()) + 2));
inputData.setServiceNumber(String.format(serviceFormat, Integer.parseInt(inputData.getServiceNumber()) + 2));
preServiceDepartTime = serviceTripList.getFirst().getStartTime();
//构建出库车次时刻
if (inputData.hasOutAndInBound() && Objects.nonNull(outBoundRouting)) {
@ -180,10 +186,15 @@ public class RunPlanGenerator {
}
}
private LinkedList<RunPlanTripVO> generateService(RunPlanInputData inputData, MapVO mapVO, List<RunPlanRoutingVO> inboundRoutings, RunPlanRoutingVO outRefLoop, RunPlanRoutingVO otherLoop,
Map<String, Integer> runLevelMap, Map<String, Integer> parkTimeMap, Map<String, RunPlanUserConfigVO.ReentryTime> reentryData) {
private LinkedList<RunPlanTripVO> generateService(RunPlanInputData inputData, MapVO mapVO, List<RunPlanRoutingVO> inboundRoutings,
RunPlanRoutingVO outRefLoop, RunPlanRoutingVO otherLoop, Map<String, Integer> runLevelMap,
Map<String, Integer> parkTimeMap, Map<String, RunPlanUserConfigVO.ReentryTime> reentryData) {
RealLineConfigVO configVO = mapVO.getConfigVO();
LinkedList<RunPlanTripVO> serviceTripList = new LinkedList<>();
int nextTripNumber = 1;
if (configVO.getFiguresOfTripNumber() == 2 && configVO.isUp(outRefLoop.getRight())) {
nextTripNumber = 2;
}
//构建环路车次
boolean loop = false;
@ -201,10 +212,10 @@ public class RunPlanGenerator {
}
if (inputData.hasOutAndInBound()) {
Routing2BoundInfo inboundRouting = getInboundRouting(loop ? outRefLoop : otherLoop, inboundRoutings,runLevelMap);
Routing2BoundInfo inboundRouting = getInboundRouting(loop ? outRefLoop : otherLoop, inboundRoutings, runLevelMap);
if (Objects.isNull(inboundRouting)) {
serviceTripList.removeLast();
inboundRouting = getInboundRouting(!loop ? outRefLoop : otherLoop, inboundRoutings,runLevelMap);
inboundRouting = getInboundRouting(!loop ? outRefLoop : otherLoop, inboundRoutings, runLevelMap);
}
if (Objects.nonNull(inboundRouting)) {
setInBoundTripTimes(runLevelMap, parkTimeMap, reentryData, serviceTripList, inboundRouting);
@ -278,10 +289,23 @@ public class RunPlanGenerator {
private int buildServiceTrip(RunPlanInputData inputData, MapVO mapVO, RunPlanRoutingVO routing,
Map<String, Integer> runLevelMap, Map<String, Integer> parkTimeMap, Map<String, RunPlanUserConfigVO.ReentryTime> reentryData,
LinkedList<RunPlanTripVO> tripList, int tripNumber) {
RealLineConfigVO configVO = mapVO.getConfigVO();
String tripFormat;
if (configVO.getFiguresOfTripNumber() == 2) {
tripFormat = "%02d";
} else {
tripFormat = String.format("%%0%sd", configVO.getFiguresOfTripNumber() - 1);
}
RunPlanTripVO tripVO = new RunPlanTripVO(routing);
setDirectionCode(mapVO, tripVO);
tripVO.setServiceNumber(inputData.getServiceNumber());
tripVO.setTripNumber(tripVO.getDirectionCode() + String.format("%03d", tripNumber));
if (configVO.getFiguresOfTripNumber() == 2) {
tripVO.setTripNumber(String.format(tripFormat, tripNumber));
} else {
tripVO.setTripNumber(tripVO.getDirectionCode() + String.format(tripFormat, tripNumber));
}
tripVO.setIsReentry(true);
tripVO.setIsInbound(false);
tripVO.setIsOutbound(false);
@ -322,7 +346,7 @@ public class RunPlanGenerator {
}
RunPlanUserConfigVO.ReentryTime reentryTime = reentryData.get(routingSection.getStationCode());
runPlanTripTimeVO.setArrivalTime(CollectionUtils.isEmpty(tripTimeList) ?
CollectionUtils.isEmpty(tripList) ? inputData.getBeginTime().plusSeconds(reentryData.get(routing.getStartStationCode()).getTbTo()): tripList.getLast().getEndTime().plusSeconds(reentryData.get(routing.getStartStationCode()).getTbBack()-reentryData.get(routing.getStartStationCode()).getTbFrom())
CollectionUtils.isEmpty(tripList) ? inputData.getBeginTime().plusSeconds(reentryData.get(routing.getStartStationCode()).getTbTo()) : tripList.getLast().getEndTime().plusSeconds(reentryData.get(routing.getStartStationCode()).getTbBack() - reentryData.get(routing.getStartStationCode()).getTbFrom())
: tripTimeList.getLast().getDepartureTime().plusSeconds(runLevelMap.get(tripTimeList.getLast().getSectionCode() + "-" + runPlanTripTimeVO.getSectionCode())));
runPlanTripTimeVO.setDepartureTime(Objects.isNull(routing.getEndTbFront())
? runPlanTripTimeVO.getArrivalTime()
@ -386,7 +410,7 @@ public class RunPlanGenerator {
}
}
private Routing2BoundInfo getOutboundRouting(RunPlanRoutingVO runningRouting, List<RunPlanRoutingVO> outboundRoutings,Map<String, Integer> runLevelMap) {
private Routing2BoundInfo getOutboundRouting(RunPlanRoutingVO runningRouting, List<RunPlanRoutingVO> outboundRoutings, Map<String, Integer> runLevelMap) {
//找出库
RunPlanRoutingVO outboundRouting = null;
List<RunPlanRoutingSection> parkSectionCodeList = runningRouting.getParkSectionCodeList();
@ -395,7 +419,7 @@ public class RunPlanGenerator {
for (int i = runningRouting.getStartTbFront() ? 0 : 1, index = parkSectionCodeList.size() - (runningRouting.getEndTbFront() ? 1 : 2); i < index; i++) {
RunPlanRoutingSection parkSection = parkSectionCodeList.get(i);
outboundRouting = outboundRoutings.stream().filter(outRouting -> {
outboundRouting = outboundRoutings.stream().filter(outRouting -> {
RunPlanRoutingSection outSection = outRouting.getParkSectionCodeList().get(1);
return Objects.equals(parkSection.getSectionCode(), outSection.getSectionCode());
}).sorted(Comparator.comparing(routingVO -> runLevelMap.get(routingVO.getStartSectionCode() + "-" + parkSection.getSectionCode()))).findFirst().orElse(null);
@ -415,7 +439,7 @@ public class RunPlanGenerator {
// }
// }
}
if (Objects.isNull(outboundRouting)) return null;
if (Objects.isNull(outboundRouting)) return null;
return new Routing2BoundInfo(outboundRouting, r);
}

View File

@ -34,6 +34,8 @@ public class SignalOperateHandler {
@OperateHandlerMapping(type = Operation.Type.Signal_Set_Route)
public void settingRoute(Simulation simulation, String routeCode) {
Route.CheckFailMessage checkResult = this.ciApiService.routeSettingCheck(simulation, routeCode);
if (checkResult != null)
log.info(checkResult.debugStr());
BusinessExceptionAssertEnum.SIMULATION_EXCEPTION_FOR_SHOW.assertNull(checkResult, "进路排列失败,被联锁逻辑取消");
this.ciApiService.settingRoute(simulation, routeCode);
}

View File

@ -103,11 +103,12 @@ public class TrainOperateHandler {
* @param dn 目的地码可为空
* @param sn 服务号/表号可为空
* @param tn 行程号/序号/车次号可为空
* @param cn 乘务组号可为空
*/
@OperateHandlerMapping(type = Operation.Type.Train_Add_Train_Trace)
public void addTrainTrace(Simulation simulation, String sectionCode, String groupNumber,
String dn, String sn, String tn) {
this.atsTrainService.addTrainTrace(simulation, sectionCode, groupNumber, dn, sn, tn);
String dn, String sn, String tn, String cn) {
this.atsTrainService.addTrainTrace(simulation, sectionCode, groupNumber, dn, sn, tn, cn);
}
/**

View File

@ -263,11 +263,10 @@ public class AtsRouteService {
Route route = this.ciApiService.findLockedRouteByStartSignal(simulation, signalCode);
if (Objects.nonNull(route)) {
SimulationDataRepository repository = simulation.getRepository();
TrainInfo firstTrain = repository.querySignalApproachedFirstTrain(route.getStart());
if (route.getStart().isApproachOccupy() && Objects.nonNull(firstTrain) && !firstTrain.isStop()) {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
String.format("进路接近锁闭,无法取消"));
}
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(
routeService.isApproachLock(repository, route), "进路接近锁闭,无法取消");
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(
route.getStart().isGuideOpen(), "引导进路,需要人解进路");
this.ciApiService.unlockRoute(simulation, route.getCode());
}
}

View File

@ -361,6 +361,9 @@ public class AtsRouteSettingService {
}
}
}
StationPlan stationPlan = repository.queryStationPlanBetween(tripPlan.getPlanList().get(0).getStation(), current, arriveTime);
if (stationPlan != null)
return true;
}
return false;
}
@ -426,7 +429,7 @@ public class AtsRouteSettingService {
throw new SimulationException(SimulationExceptionType.System_Fault);
}
if (pathList.size() > 1) {
return false;
return true;
} else {
if (pathList.get(0).isStraight()) {
return true;

View File

@ -40,7 +40,7 @@ public class AtsStandService {
List<Stand> standList = section.getStandList();
int parkTime = -1;
for (Stand stand : standList) {
log.debug(String.format("站台[%s(%s)]列车停靠",stand.getName(), stand.getCode()));
log.debug(String.format("站台[%s(%s)]列车停靠", stand.getName(), stand.getCode()));
stand.setTrainParking(true);
if (stand.getParkingTime() > 0) {
parkTime = stand.getParkingTime();
@ -72,6 +72,7 @@ public class AtsStandService {
/**
* 获取人工设置的站间运行时间
*
* @param simulation
* @param section
* @return
@ -97,6 +98,7 @@ public class AtsStandService {
/**
* 更新剩余停站时间检查是否到达发车时间
*
* @param stand
* @return
*/
@ -113,6 +115,7 @@ public class AtsStandService {
/**
* 列车离站
*
* @param section
*/
public void trainLeaveStand(Section section) {
@ -143,58 +146,20 @@ public class AtsStandService {
MapConfig config = simulation.getRepository().getConfig();
SimulationDataRepository repository = simulation.getRepository();
List<TrainInfo> superviseTrainList = repository.getSuperviseTrainList();
if (config.isJumpSetPreviousStand()) {
// 上一个站设置
//在上一个停车站台向所有经过该跳停站台的列车发送跳停命令
List<Stand> preStandList = repository.queryPreviousStand(stand);
if (!CollectionUtils.isEmpty(preStandList)) {
for (Stand preStand : preStandList) {
for (TrainInfo train : superviseTrainList) {
if (!stand.isJumpStop(train.getGroupNumber())) {
break;
}
if (train.isParkingStand(preStand)) {
this.onboardAtpApiService.setJump(simulation, train.getGroupNumber());
break;
}
}
// 随时设置
// 查询目的地为此站台且可以到达此站台的列车
Section section = stand.getSection();
for (TrainInfo trainInfo : superviseTrainList) {
if (Objects.nonNull(trainInfo.getEstimatedArriveStandTrack()) &&
Objects.equals(section.getCode(), trainInfo.getEstimatedArriveStandTrack())) {
// 是列车预计到达站台
SectionPosition position = repository.buildSectionPositionOfTrainInfo(trainInfo);
if (CalculateService.isTargetSectionOnDirectionExist(position.getSection(), trainInfo.getRight(), section)) {
// 可以到达通知跳停
this.onboardAtpApiService.setJump(simulation, trainInfo.getGroupNumber());
}
}
} else {
// 随时设置
// 查询目的地为此站台且可以到达此站台的列车
Section section = stand.getSection();
for (TrainInfo trainInfo : superviseTrainList) {
if (Objects.nonNull(trainInfo.getEstimatedArriveStandTrack()) &&
Objects.equals(section.getCode(), trainInfo.getEstimatedArriveStandTrack())) {
// 是列车预计到达站台
SectionPosition position = repository.buildSectionPositionOfTrainInfo(trainInfo);
if (CalculateService.isTargetSectionOnDirectionExist(position.getSection(), trainInfo.getRight(), section)) {
// 可以到达通知跳停
this.onboardAtpApiService.setJump(simulation, trainInfo.getGroupNumber());
}
}
}
// List<RouteUnit> routeUnitList = repository.queryRouteUnitByEndSection(section);
// for (TrainInfo train : superviseTrainList) {
// if (!train.hasPositionAndDirection()) {
// continue;
// }
// if (stand.isJumpStop(train.getGroupNumber())) {
// Boolean right = train.getRight();
// Section headSection = repository.getByCode(train.getPhysicalSection(), Section.class);
// for (RouteUnit routeUnit : routeUnitList) {
// if (Objects.equals(routeUnit.isRight(), right) && routeUnit.containsSection(headSection)) {
// Float distance = CalculateService.calculateDistance(headSection, section, right);
// if (Objects.nonNull(distance) && distance > 0) {
// // 列车前方到站就是此站台通知跳停
// this.onboardAtpApiService.setJump(simulation, train.getGroupNumber());
// }
// break;
// }
// }
// }
// }
}
}
@ -313,7 +278,7 @@ public class AtsStandService {
public void checkAndCancelGivenTrainJump(Simulation simulation, Section section, String groupNumber) {
List<Stand> standList = section.getStandList();
standList.forEach(stand -> {
if (stand.isGivenTrainSkip(groupNumber) && !stand.isSkipAlwaysValid()) {
if (stand.isGivenTrainSkip(groupNumber) && !stand.isSkipAlwaysValid()) {
stand.removeSkipTrain(groupNumber);
}
});
@ -418,8 +383,10 @@ public class AtsStandService {
this.checkAndCancelTrainHold(simulation, stand);
}
/**根据当前操作站台取消所在方向的所有站台扣车状态*/
public void cancelHoldTrainForWholeLine(Simulation simulation, String operateStandCode,Boolean right) {
/**
* 根据当前操作站台取消所在方向的所有站台扣车状态
*/
public void cancelHoldTrainForWholeLine(Simulation simulation, String operateStandCode, Boolean right) {
Stand operateStand = simulation.getRepository().getByCode(operateStandCode, Stand.class);
List<Stand> standList = simulation.getRepository().getStandList();
boolean isRight;
@ -478,12 +445,12 @@ public class AtsStandService {
public void open(Simulation simulation, List<String> standCodes) {
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertCollectionNotEmpty(standCodes, "所选站台不能为空");
SimulationDataRepository repository = simulation.getRepository();
standCodes.forEach(code->repository.getByCode(code, Stand.class).open());
standCodes.forEach(code -> repository.getByCode(code, Stand.class).open());
}
public void close(Simulation simulation, List<String> standCodes) {
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertCollectionNotEmpty(standCodes, "所选站台不能为空");
SimulationDataRepository repository = simulation.getRepository();
standCodes.forEach(code->repository.getByCode(code, Stand.class).close());
standCodes.forEach(code -> repository.getByCode(code, Stand.class).close());
}
}

View File

@ -54,30 +54,43 @@ public class AtsTrainService {
/**
* 添加列车追踪
*
* @param simulation
* @param simulation
* @param sectionCode
* @param groupNumber
* @param dn 目的地码
* @param sn 服务号/表号
* @param tn 行程号/序号/车次号
* @param cn
*/
public void addTrainTrace(Simulation simulation, String sectionCode, String groupNumber,
String dn, String sn, String tn) {
String dn, String sn, String tn, String cn) {
SimulationDataRepository repository = simulation.getRepository();
//车组号检查
TrainInfo trainInfo = repository.findSupervisedTrainByGroup(groupNumber);
if (Objects.nonNull(trainInfo)) {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
String.format("[%s]已经存在", groupNumber));
}
//区段车辆数检查
Section section = repository.getByCode(sectionCode, Section.class);
List<TrainInfo> existList = repository.queryTrainInfosBySection(section);
if (existList.size() >= 10) {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
String.format("区段超过10辆"));
}
TrainInfo ti = new TrainInfo(groupNumber);
ti.init(section, dn, sn, tn);
//添加监控列车
TripPlan tripPlan = repository.findTripPlan(sn, tn);
TrainInfo ti;
if (tripPlan != null) {
//车次计划检查
boolean tripRepeat = repository.getTrainInfoMap().values().stream()
.anyMatch(info -> Objects.equals(info.getServiceNumber(), sn) && Objects.equals(info.getTripNumber(), tn));
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(tripRepeat, "车次计划已在运行");
ti = new TrainInfo(groupNumber, TrainType.PLAN);
} else {
ti = new TrainInfo(groupNumber, TrainType.MANUAL);
}
ti.init(section, dn, sn, tn, cn);
repository.addTrainInfo(ti);
}
@ -115,7 +128,7 @@ public class AtsTrainService {
}
Section target = repository.getByCode(sectionCode, Section.class);
if (!trainInfo.isCbtcTrack()) {
trainInfo.init(target, trainInfo.getDestinationCode(), trainInfo.getServiceNumber(), trainInfo.getTripNumber());
trainInfo.init(target, trainInfo.getDestinationCode(), trainInfo.getServiceNumber(), trainInfo.getTripNumber(), trainInfo.getCrewNumber());
}
}
@ -131,12 +144,10 @@ public class AtsTrainService {
String.format("不存在追踪的列车[%s]", groupNumber));
}
TripPlan tripPlan = repository.getTripPlan(serviceNumber, tripNumber);
// if (tripPlan.isDeparture()) {
// throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
// String.format("车次[%s|%s|%s]已经发车",
// tripPlan.getServiceNumber(), tripPlan.getTripNumber(),
// tripPlan.getDestinationCode()));
// }
setPlanTrain(simulation, repository, supervisedTrain, tripPlan);
}
private void setPlanTrain(Simulation simulation, SimulationDataRepository repository, TrainInfo supervisedTrain, TripPlan tripPlan) {
if (supervisedTrain.hasPositionAndDirection()) {
Section phySection = repository.getByCode(supervisedTrain.getPhysicalSection(), Section.class);
StationPlan nextPlan = null;
@ -149,11 +160,6 @@ public class AtsTrainService {
nextPlan = stationPlan;
break;
}
// RouteUnit routeUnit = repository.queryRouteUnit(phySection, stationPlan.getSection());
// if (Objects.nonNull(routeUnit)) {
// nextPlan = stationPlan;
// break;
// }
}
} else {
// 列车不在折返轨停车判断列车目标区段是否在计划到站的站台轨中
@ -163,28 +169,6 @@ public class AtsTrainService {
if (filterPlan.isPresent()) {
nextPlan = filterPlan.get();
}
// // 列车不在折返轨停车判断列车是否在计划到站的路径单元中
// List<StationPlan> stationPlanList = tripPlan.getPlanList();
// for (int i = 1; i < stationPlanList.size(); i++) {
// StationPlan startPlan = stationPlanList.get(i - 1);
// StationPlan endPlan = stationPlanList.get(i);
// List<RoutePath> routePaths = repository.getRoutePaths(startPlan.getSection(), endPlan.getSection());
// for (RoutePath routePath : routePaths) {
// if (routePath.containsSection(phySection)) {
// nextPlan = endPlan;
// break;
// }
// }
// if (Objects.nonNull(nextPlan)) {
// break;
// }
//// RouteUnit routeUnit = repository.getRouteUnit(startPlan.getSection(), endPlan.getSection());
//// if (routeUnit.containsSection(phySection)) {
//// nextPlan = endPlan;
//// break;
//// }
// }
}
if (Objects.isNull(nextPlan)) {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,

View File

@ -203,6 +203,12 @@ public class CiApiServiceImpl implements CiApiService {
@Override
public void unlockRoute(Simulation simulation, String routeCode) {
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
if (simulation.getRepository().getConfig().isDelayWhenCancelRouteWithAbnormalInterlock()) {
if (!routeService.isInterlocked(route)) {
routeService.humanCancel(simulation, route);
return;
}
}
this.routeService.cancelNoApproachLock(simulation, route);
}
@ -210,19 +216,10 @@ public class CiApiServiceImpl implements CiApiService {
public void forceUnlockRoute(Simulation simulation, String routeCode) {
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
SimulationDataRepository repository = simulation.getRepository();
TrainInfo firstTrain = repository.querySignalApproachedFirstTrain(route.getStart());
if (route.isApproachLock()) { // 接近锁闭总人解
if (firstTrain != null) {
if (!firstTrain.isStop()) {
this.routeService.humanCancel(simulation, route);
} else {
this.routeService.cancelNoApproachLock(simulation, route);
}
} else {
this.routeService.humanCancel(simulation, route);
}
if (routeService.isApproachLock(repository, route)) {
routeService.humanCancel(simulation, route);
} else {
this.routeService.cancelNoApproachLock(simulation, route);
unlockRoute(simulation, route.getCode());
}
}

View File

@ -3,8 +3,10 @@ package club.joylink.rtss.simulation.cbtc.CI.service;
import club.joylink.rtss.simulation.cbtc.Simulation;
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.support.TrainStopMessage;
import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
import lombok.extern.slf4j.Slf4j;
@ -568,12 +570,24 @@ public class RouteService {
SwitchElement pSwitch = flsElement.getPSwitch();
if (pSwitch != null && !pSwitch.getASwitch().isOnPosition(pSwitch.isNormal())) {
return false;
} else {
}
Signal pSignal = flsElement.getPSignal();
if (pSignal != null && !pSignal.isClose()) {
SwitchElement fpae = flsElement.getFpae();
if (fpae != null && !fpae.getASwitch().isOnPosition(fpae.isNormal())) {
if (fpae != null) {
if (fpae.getASwitch().isOnPosition(fpae.isNormal())) {
return false;
}
} else {
return false;
}
}
// else {
// SwitchElement fpae = flsElement.getFpae();
// if (fpae != null && !fpae.getASwitch().isOnPosition(fpae.isNormal())) {
// return false;
// }
// }
}
}
}
@ -932,11 +946,20 @@ public class RouteService {
} else {
SwitchElement fpae = flsElement.getFpae();
Signal pSignal = flsElement.getPSignal();
if ((pSignal != null && !pSignal.isClose()) ||
(fpae != null && !fpae.getASwitch().isOnPosition(fpae.isNormal()))) {
level1Result = false;
break;
if (pSignal != null && !pSignal.isClose()) {
if (fpae != null) {
if (fpae.getASwitch().isOnPosition(fpae.isNormal())) {
level1Result = false;
}
} else {
level1Result = false;
}
}
// if ((pSignal != null && !pSignal.isClose()) ||
// (fpae != null && !fpae.getASwitch().isOnPosition(fpae.isNormal()))) {
// level1Result = false;
// break;
// }
}
}
}
@ -1442,4 +1465,14 @@ public class RouteService {
public void setOverlap(Simulation simulation, Signal signal, RouteOverlap overlap) {
overlap.startSetting(simulation.getSystemTime());
}
public boolean isApproachLock(SimulationDataRepository repository, Route route) {
TrainInfo firstTrain = repository.querySignalApproachedFirstTrain(route.getStart());
if (route.getStart().isApproachOccupy()) { // 接近锁闭总人解
if (firstTrain == null || !firstTrain.isStop()) {
return true;
}
}
return false;
}
}

View File

@ -10,6 +10,7 @@ import club.joylink.rtss.vo.client.map.newmap.MapStationParkingTimeVO;
import club.joylink.rtss.vo.client.map.newmap.MapStationRunLevelVO;
import club.joylink.rtss.vo.client.runplan.user.RunPlanParkingTimeVO;
import club.joylink.rtss.vo.client.runplan.user.RunPlanRunlevelVO;
import org.springframework.util.CollectionUtils;
import java.util.HashMap;
import java.util.List;
@ -19,6 +20,8 @@ import java.util.stream.Collectors;
public class UserConfigDataBuilder {
public static void buildRunLevel(SimulationDataRepository repository, List<RunPlanRunlevelVO> userRunLevelList, MapVO map) {
if (CollectionUtils.isEmpty(userRunLevelList))
return;
Map<String, RunPlanRunlevelVO> voMap = userRunLevelList.stream()
.collect(Collectors.toMap(
vo -> StationRunLevel.buildKey(vo.getStartSectionCode(), vo.getEndSectionCode()),

View File

@ -1092,4 +1092,17 @@ public class SimulationDataRepository {
.filter(trainInfo -> trainInfo.getSection() != null && trainInfo.getSection().equals(section.getCode()))
.collect(Collectors.toList());
}
public StationPlan queryStationPlanBetween(Station station, LocalTime start, LocalTime end) {
for (TripPlan tripPlan : this.getAllTripPlanList()) {
if (tripPlan.getStartTime().isAfter(end) || tripPlan.getEndTime().isBefore(start))
continue;
for (StationPlan stationPlan : tripPlan.getPlanList()) {
if (stationPlan.getStation().equals(station) && start.isBefore(stationPlan.getArriveTime()) && end.isAfter(stationPlan.getArriveTime())) {
return stationPlan;
}
}
}
return null;
}
}

View File

@ -72,11 +72,6 @@ public class MapConfig {
*/
private boolean routeLikeHa1;
/**
* 备用计划车是否转人工车
*/
private boolean backupTurnManual;
/**
* 道岔区段是否单独占用对于两个相连的道岔情况
*/
@ -87,11 +82,6 @@ public class MapConfig {
*/
private boolean overlapSettingByTrigger;
/**
* 跳停是否在上一个站台前才能设置false-随时可设置
*/
private boolean jumpSetPreviousStand;
/**
* 道岔正/反操是否联动
*/
@ -108,7 +98,7 @@ public class MapConfig {
private boolean switchLossChain;
/**
* 是否强制取消进路/在接近区段占用时是否依旧强制执行取消进路
* 取消进路命令能否取消引导或接近锁闭的进路
*/
private boolean signalForceCancelRoute;
@ -182,21 +172,11 @@ public class MapConfig {
*/
private boolean needApproachLockBeforeSetGuide;
// /**
// * 站台指定列车跳停仅跳停一次
// */
// private boolean standSkipSetTrainOnlyOnce;
/**
* 封锁命令状态仅在后备模式下有效
*/
private boolean blockadeCommandOnlyValidInStandbyMode;
// /**
// * 一些命令需要初始化泰雷兹道岔封锁信号机开放引导
// */
// private boolean someCommandNeedInit;
/**
* 计轴预复位前需要车站预复位
*/
@ -215,6 +195,15 @@ public class MapConfig {
/** 共享紧急关闭效果的车站 */
private Set<String> sharingECStations;
/** 取消联锁条件不满足的进路时需要延时解锁 */
private boolean delayWhenCancelRouteWithAbnormalInterlock;
/** 车次号的位数 */
private int figuresOfTripNumber;
/** 服务号的位数 */
private int figuresOfServiceNumber;
private Set<SimulationMember.Type> needConfirmConnectMembers =
Stream.of(DISPATCHER, STATION_SUPERVISOR, MAINTAINER, ELECTRIC_DISPATCHER).collect(Collectors.toSet());
@ -259,6 +248,9 @@ public class MapConfig {
setStationPreResetBeforeAxlePreReset(configVO.isStationPreResetBeforeAxlePreReset());
setSwitchTurnOperationCanRecoverSplitFault(configVO.isSwitchTurnOperationCanRecoverSplitFault());
setHoldCommandIgnoreControlMode(configVO.isHoldCommandIgnoreControlMode());
setDelayWhenCancelRouteWithAbnormalInterlock(configVO.isDelayWhenCancelRouteWithAbnormalInterlock());
setFiguresOfTripNumber(configVO.getFiguresOfTripNumber());
setFiguresOfServiceNumber(configVO.getFiguresOfServiceNumber());
}
}

View File

@ -72,16 +72,17 @@ public class RouteFls {
if (pSwitch.isOnPosition() || (pSwitch.getASwitch().isLoss())) {
pSwitch.getASwitch().fpLock();
}
} else {
Signal pSignal = flsElement.getPSignal();
SwitchElement fpae = flsElement.getFpae();
if (pSignal != null && fpae == null) {
pSignal.fpLock();
}
if (fpae != null && (fpae.isOnPosition() || fpae.getASwitch().isLoss())) {
fpae.getASwitch().fpLock();
}
}
// else {
// Signal pSignal = flsElement.getPSignal();
// SwitchElement fpae = flsElement.getFpae();
// if (pSignal != null && fpae == null) {
// pSignal.fpLock();
// }
// if (fpae != null && (fpae.isOnPosition() || fpae.getASwitch().isLoss())) {
// fpae.getASwitch().fpLock();
// }
// }
}
}

View File

@ -859,8 +859,6 @@ public class Section extends MayOutOfOrderDevice {
}
public boolean isRouteLockOn(boolean right) {
if (noStatus)
return false;
return this.routeLock && Objects.equals(this.lockRight, right);
}

View File

@ -326,7 +326,16 @@ public class Signal extends MayOutOfOrderDevice {
}
public boolean isApproachOccupy() {
return !Objects.equals(this.approachMsg, SignalApproachMessage.ApproachMessage.NULL);
if (CollectionUtils.isEmpty(approachPathList))
return false;
for (SectionPath sectionPath : approachPathList) {
for (Section section : sectionPath.getSectionList()) {
if (section.isOccupied())
return true;
}
}
return false;
// return !Objects.equals(this.approachMsg, SignalApproachMessage.ApproachMessage.NULL);
}
public boolean containsApproachAtpSection(List<Section> atpSectionList) {

View File

@ -34,6 +34,9 @@ public class TrainStatus extends DeviceStatus {
/** 目的地码 */
private String destinationCode;
/** 乘务组号 */
private String crewNumber;
/** 计划交路类型 */
private PlanRoutingType planRoutingType;
@ -117,6 +120,7 @@ public class TrainStatus extends DeviceStatus {
if (!Objects.equals(train.getType(), TrainType.MANUAL)) {
this.destinationCode = train.getDestinationCode();
}
this.crewNumber = train.getCrewNumber();
this.sectionCode = train.getSection();
this.physicalCode = train.getPhysicalSection();
this.offsetp = train.getOffsetp();
@ -166,6 +170,11 @@ public class TrainStatus extends DeviceStatus {
status.setTripNumber(this.tripNumber);
change = true;
}
if (!Objects.equals(this.crewNumber, train.getCrewNumber())) {
this.crewNumber = train.getCrewNumber();
status.setCrewNumber(this.crewNumber);
change = true;
}
if (!Objects.equals(this.planRoutingType, train.getPlanRoutingType())) {
this.planRoutingType = train.getPlanRoutingType();
change = true;
@ -278,6 +287,7 @@ public class TrainStatus extends DeviceStatus {
statusVO.setStop(stop);
statusVO.setBackUp(backUp);
statusVO.setOrderStop(orderStop);
statusVO.setCrewNumber(crewNumber);
return statusVO;
}

View File

@ -71,6 +71,7 @@ public class TrainInfo extends MapElement {
/** 物理区段偏移量百分比 */
private float offsetp;
@Setter
private Boolean right;
private float speed;
@ -154,6 +155,12 @@ public class TrainInfo extends MapElement {
this.groupNumber = groupNumber;
}
public TrainInfo(String groupNumber, TrainType trainType) {
super(groupNumber, DeviceType.TRAIN);
this.groupNumber = groupNumber;
this.type = trainType;
}
/**
* 构造人工车的列车信息
*/
@ -230,11 +237,12 @@ public class TrainInfo extends MapElement {
this.estimatedArriveTime = nextStationPlan.getArriveTime();
}
public void init(Section section, String dn, String sn, String tn) {
public void init(Section section, String dn, String sn, String tn, String cn) {
this.section = section.getCode();
this.destinationCode = dn;
this.serviceNumber = sn;
this.tripNumber = tn;
this.crewNumber = cn;
}
public void init(TripPlan tripPlan, MapConfig config) {

View File

@ -32,6 +32,9 @@ public class TrainStatusVO extends DeviceStatusVO {
/** 目的地码 */
private String destinationCode;
/** 乘务组号 */
private String crewNumber;
/** 计划交路类型 */
@JsonInclude(JsonInclude.Include.ALWAYS)
private PlanRoutingType planRoutingType;

View File

@ -190,13 +190,11 @@ public class VRTrainRunningService {
if (!train.isCBTC() && defaultRunLevel.equals(RunLevel.CBTC)) { //如果列车不是CBTC同时线路默认级别是CBTC
train.setRunLevel(RunLevel.CBTC);
}
train.setCbtcMaMissDuration(train.getCbtcMaMissDuration() + SimulationConstants.TRAIN_RUNNING_RATE);
}
if (!train.isItcMaMiss()) { //itc级别ma未丢失
if (RunLevel.IL.equals(train.getRunLevel())) { //如果列车是IL级别
train.setRunLevel(RunLevel.ITC);
}
train.setItcMaMissDuration(train.getItcMaMissDuration() + SimulationConstants.TRAIN_RUNNING_RATE);
}
}

View File

@ -78,27 +78,19 @@ public class ATPLogicLoop {
* 检查ma接收情况并改变列车运行级别
*/
private void maCheckAndChangeRunLevel(Simulation simulation, VirtualRealityTrain train) {
// RunLevel defaultRunLevel = simulation.getRepository().getConfig().getRunMode();
RunLevel defaultRunLevel = simulation.getRepository().getConfig().getRunMode();
if (train.isCbtcMaMiss()) { //cbtc级别ma丢失
if (train.isCBTC()) { //并且列车处于CBTC级别
train.setRunLevel(RunLevel.IL);
atpService.triggerSignalEB(train);
train.setMa(null);
}
} else {
train.setCbtcMaMissDuration(train.getCbtcMaMissDuration() + SimulationConstants.ATP_LOOP_RATE);
}
if (!train.isItcMaMiss()) { //itc级别ma未丢失
train.setItcMaMissDuration(train.getItcMaMissDuration() + SimulationConstants.ATP_LOOP_RATE);
}
// else {
// if (!train.isCBTC() && defaultRunLevel.equals(RunLevel.CBTC)) { //如果列车不是CBTC同时线路默认级别是CBTC
// train.setRunLevel(RunLevel.CBTC);
// }
// train.setCbtcMaMissDuration(train.getCbtcMaMissDuration() + SimulationConstants.ATP_LOOP_RATE);
// }
//
// if (!train.isItcMaMiss()) { //itc级别ma未丢失
// if (RunLevel.IL.equals(train.getRunLevel())) { //如果列车是IL级别
// train.setRunLevel(RunLevel.ITC);
// }
// train.setItcMaMissDuration(train.getItcMaMissDuration() + SimulationConstants.ATP_LOOP_RATE);
// }
}
private void driveLogicRun(Simulation simulation, VirtualRealityTrain train) {

View File

@ -150,6 +150,15 @@ public class RealLineConfigVO {
*/
private boolean holdCommandIgnoreControlMode;
/** 取消联锁条件不满足的进路时需要延时解锁 */
private boolean delayWhenCancelRouteWithAbnormalInterlock;
/** 车次号的位数 */
private int figuresOfTripNumber = 4;
/** 服务号的位数 */
private int figuresOfServiceNumber = 3;
public static RealLineConfigVO parseJsonStr(String configData) {
if (StringUtils.hasText(configData)) {
return JsonUtils.read(configData, RealLineConfigVO.class);
@ -157,4 +166,8 @@ public class RealLineConfigVO {
return new RealLineConfigVO();
}
public boolean isUp(boolean right) {
return right == upRight;
}
}

View File

@ -79,7 +79,7 @@ public class MapCiGenerateConfig {
@ApiModelProperty("是否生成目的地码定义(泰雷兹式)")
private boolean generateDestination;
/** 共享紧急关闭效果的车站 */
/** 上下行站台共享紧急关闭效果的车站 */
private Set<String> sharingECStations = new HashSet<>();
// @ApiModelProperty(value = "是否分开生成ATP联锁和地面信号联锁")