增加大铁列车自动驾驶逻辑;将大铁不需要的仿真任务去除

This commit is contained in:
joylink_zhangsai 2022-07-21 17:46:47 +08:00
parent 8dcba7a311
commit afbb57d1a8
8 changed files with 154 additions and 83 deletions

View File

@ -5,6 +5,8 @@ import club.joylink.rtss.simulation.cbtc.ATS.operation.vo.RegulationParam;
import club.joylink.rtss.simulation.cbtc.ATS.service.ars.AtsTriggerRouteService; import club.joylink.rtss.simulation.cbtc.ATS.service.ars.AtsTriggerRouteService;
import club.joylink.rtss.simulation.cbtc.ATS.service.stage.AtsRealRunRecordService; import club.joylink.rtss.simulation.cbtc.ATS.service.stage.AtsRealRunRecordService;
import club.joylink.rtss.simulation.cbtc.ATS.service.stage.AtsTrainStageHandler; import club.joylink.rtss.simulation.cbtc.ATS.service.stage.AtsTrainStageHandler;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcRepository;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcStationRunPlanLog;
import club.joylink.rtss.simulation.cbtc.ISCS.OnBoardPisService; import club.joylink.rtss.simulation.cbtc.ISCS.OnBoardPisService;
import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants; import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
@ -24,6 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.time.Duration;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.List; import java.util.List;
@ -212,36 +215,57 @@ public class AtsTrainMonitorService {
*/ */
private int getParkTimeOf(Simulation simulation, TrainInfo train, Section standTrack) { private int getParkTimeOf(Simulation simulation, TrainInfo train, Section standTrack) {
int parkTime = 0; int parkTime = 0;
LocalDateTime systemTime = simulation.getSystemTime(); if (!simulation.getRepository().getConfig().isRailway()) { //地铁线路
SimulationDataRepository repository = simulation.getRepository(); LocalDateTime systemTime = simulation.getSystemTime();
if (train.isPlanTrain()) { // 计划车 SimulationDataRepository repository = simulation.getRepository();
TripPlan tripPlan = repository.getTripPlan(train.getServiceNumber(), train.getTripNumber()); if (train.isPlanTrain()) { // 计划车
StationPlan stationPlan = tripPlan.queryStationPlan(standTrack); TripPlan tripPlan = repository.getTripPlan(train.getServiceNumber(), train.getTripNumber());
if (stationPlan != null) { StationPlan stationPlan = tripPlan.queryStationPlan(standTrack);
if (standTrack.isNormalStandTrack() && tripPlan.isFirstPlan(stationPlan)) { // 折返第一站 if (stationPlan != null) {
parkTime = this.getFirstStationPlanParkTime(stationPlan, systemTime); if (standTrack.isNormalStandTrack() && tripPlan.isFirstPlan(stationPlan)) { // 折返第一站
} else if (standTrack.isNormalStandTrack() && tripPlan.isLastPlan(stationPlan) && parkTime = this.getFirstStationPlanParkTime(stationPlan, systemTime);
tripPlan.isFrontTurnBack()) { // 站前折返终点站 } else if (standTrack.isNormalStandTrack() && tripPlan.isLastPlan(stationPlan) &&
TripPlan nextPlan = repository.queryNextTripPlanOf(tripPlan); tripPlan.isFrontTurnBack()) { // 站前折返终点站
StationPlan firstStationPlan = nextPlan.getFirstStationPlan(); TripPlan nextPlan = repository.queryNextTripPlanOf(tripPlan);
parkTime = this.getFirstStationPlanParkTime(firstStationPlan, systemTime); StationPlan firstStationPlan = nextPlan.getFirstStationPlan();
} else { parkTime = this.getFirstStationPlanParkTime(firstStationPlan, systemTime);
parkTime = stationPlan.getParkTime(); } else {
parkTime = stationPlan.getParkTime();
}
} else if (standTrack.isNormalStandTrack()) {
stationPlan = tripPlan.queryStationPlan(standTrack.getStation());
if (stationPlan != null) { // 未停靠在计划的站台轨
parkTime = stationPlan.getParkTime();
}
} }
} else if (standTrack.isNormalStandTrack()) { } else { // 头码车或人工车按默认停站时间
stationPlan = tripPlan.queryStationPlan(standTrack.getStation()); StationParkTime stationParkTime = repository.queryStandParkTime(standTrack);
if (stationPlan != null) { // 未停靠在计划的站台轨 if (stationParkTime != null) {
parkTime = stationPlan.getParkTime(); parkTime = stationParkTime.getParkTime();
} else { // 没有数据默认30s
parkTime = 30;
} }
} }
} else { // 头码车或人工车按默认停站时间 } else { //大铁线路
StationParkTime stationParkTime = repository.queryStandParkTime(standTrack); Station station = standTrack.getStation();
if (stationParkTime != null) { if (station != null) {
parkTime = stationParkTime.getParkTime(); CtcRepository ctcRepository = simulation.getCtcRepository();
} else { // 没有数据默认30s CtcStationRunPlanLog runPlan = ctcRepository.findRunPlan(station.getCode(), train.getTripNumber());
parkTime = 30; CtcStationRunPlanLog.RunPlanItem departRunPlan = runPlan.getDepartRunPlan();
if (departRunPlan != null) { //有发车计划
CtcStationRunPlanLog.RunPlanItem arriveRunPlan = runPlan.getArriveRunPlan();
if (arriveRunPlan != null) { //有接车计划用计划停站时间
parkTime = (int) Duration.between(arriveRunPlan.getPlanTime(), departRunPlan.getPlanTime()).toSeconds();
} else { //无接车计划停到计划发车时间
LocalDateTime correctSystemTime = simulation.getCorrectSystemTime();
parkTime = (int) Duration.between(correctSystemTime, departRunPlan.getPlanTime()).toSeconds();
}
} else { //无发车计划固定停站1分钟吧
parkTime = 60;
}
} }
} }
parkTime = Math.max(parkTime, 0);
return parkTime; return parkTime;
} }

View File

@ -356,6 +356,12 @@ public class CtcRepository {
.findFirst().orElse(null); .findFirst().orElse(null);
} }
public Collection<CtcStationRunPlanLog> findRunPlans(String tripNumber) {
return this.allRunPlanList.stream()
.filter(plan -> Objects.equals(tripNumber, plan.getTripNumber()))
.collect(Collectors.toList());
}
public RouteSequence.Line getRouteSequenceLine(String stationCode, String tripNumber, boolean departure) { public RouteSequence.Line getRouteSequenceLine(String stationCode, String tripNumber, boolean departure) {
RouteSequence routeSequence = routeSequenceMap.get(stationCode); RouteSequence routeSequence = routeSequenceMap.get(stationCode);
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotNull(routeSequence); BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotNull(routeSequence);

View File

@ -67,11 +67,11 @@ public class CtcDispatchCommandService {
private void dispatchCommandParamValid(RailDispatchCommandVO vo) { private void dispatchCommandParamValid(RailDispatchCommandVO vo) {
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertHasText(vo.getTitle(), "命令标题不能为空"); BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertHasText(vo.getTitle(), "命令标题不能为空");
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(vo.getTitle().length() < 20, "命令标题最大长度20"); BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(vo.getTitle().length() <= 20, "命令标题最大长度20");
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertHasText(vo.getContent(), "命令正文不能为空"); BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertHasText(vo.getContent(), "命令正文不能为空");
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(vo.getContent().length() < 200, "命令正文最大长度200"); BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(vo.getContent().length() <= 200, "命令正文最大长度200");
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertHasText(vo.getNumber(), "命令号不能为空"); BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertHasText(vo.getNumber(), "命令号不能为空");
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(vo.getNumber().length() < 10, "命令号最大长度10"); BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(vo.getNumber().length() <= 10, "命令号最大长度10");
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertHasText(vo.getSenderName(), "发令人不能为空"); BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertHasText(vo.getSenderName(), "发令人不能为空");
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertCollectionNotEmpty(vo.getReceiverIds(), "收令人不能为空"); BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertCollectionNotEmpty(vo.getReceiverIds(), "收令人不能为空");
} }

View File

@ -179,28 +179,26 @@ public class SimulationLifeCycleServiceImpl implements SimulationLifeCycleServic
} }
private void addJobs(Simulation simulation) { private void addJobs(Simulation simulation) {
atsLogicLoop.addJobs(simulation); if (simulation.getRepository().getConfig().isRailway()) {
ctcLogicLoop.addJobs(simulation);
} else {
depotService.addJobs(simulation);
trainTargetUpdateService.addJobs(simulation);
iVirtualRealityIbpService.addJobs(simulation);
powerSupplyService.addJobs(simulation);
iVirtualRealityPslService.addJobs(simulation);
iscsMessageCollectAndDispatcher.addJob(simulation);
iscsLogicLoop.addJob(simulation);
}
atpLogicLoop.addJobs(simulation); atpLogicLoop.addJobs(simulation);
depotService.addJobs(simulation); atsLogicLoop.addJobs(simulation);
trainTargetUpdateService.addJobs(simulation);
vrTrainRunningService.addJobs(simulation); vrTrainRunningService.addJobs(simulation);
ciLogic.addJobs(simulation); ciLogic.addJobs(simulation);
vrDeviceLogicLoop.addJobs(simulation); vrDeviceLogicLoop.addJobs(simulation);
// zcLogicLoop.addJobs(simulation);
atsMessageCollectAndDispatcher.addJobs(simulation); atsMessageCollectAndDispatcher.addJobs(simulation);
joylink3DMessageService.addJobs(simulation); joylink3DMessageService.addJobs(simulation);
faultGenerator.addJobs(simulation); faultGenerator.addJobs(simulation);
iVirtualRealityIbpService.addJobs(simulation);
powerSupplyService.addJobs(simulation);
robotLogicLoop.addJobs(simulation); robotLogicLoop.addJobs(simulation);
iVirtualRealityPslService.addJobs(simulation);
iscsMessageCollectAndDispatcher.addJob(simulation);
iscsLogicLoop.addJob(simulation);
//////////////////////////////////////////////
// simulationRealDeviceConnectManager.addJobs(simulation);
if (simulation.getRepository().getConfig().isRailway()) {
ctcLogicLoop.addJobs(simulation);
}
} }
@Override @Override

View File

@ -179,6 +179,11 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
*/ */
private int parkRemainTime; private int parkRemainTime;
/**
* 最后一次停站的区段
*/
private Section parkSection;
/** /**
* 发车提示 * 发车提示
*/ */
@ -538,6 +543,8 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
this.beAbout2Arrive = false; this.beAbout2Arrive = false;
this.target = null; this.target = null;
this.parkTime = 0; this.parkTime = 0;
this.parkRemainTime = 0;
this.parkSection = null;
this.departure = false; this.departure = false;
this.breaking = false; this.breaking = false;
this.standParkedTrainActivity = null; this.standParkedTrainActivity = null;
@ -780,15 +787,6 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
return this.tailPosition; return this.tailPosition;
} }
/**
* @param parkTime 单位s
*/
public synchronized void park(int parkTime) {
int ms = parkTime * 1000;
this.parkTime = ms;
this.parkRemainTime = ms;
}
public synchronized void depart() { public synchronized void depart() {
this.standParkedTrainActivity = null; this.standParkedTrainActivity = null;
this.parkTime = 0; this.parkTime = 0;
@ -968,6 +966,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
} else { } else {
this.standParkedTrainActivity = StandParkedTrainActivity.START; this.standParkedTrainActivity = StandParkedTrainActivity.START;
} }
this.parkSection = headSection;
} }
public boolean isParkingAt() { public boolean isParkingAt() {

View File

@ -31,14 +31,6 @@ public interface OnboardAtpApiService {
*/ */
void updateTripPlan(Simulation simulation, String groupNumber, TripPlan tripPlan); void updateTripPlan(Simulation simulation, String groupNumber, TripPlan tripPlan);
/**
* 更新站台停靠时间
* @param simulation
* @param groupNumber
* @param parkTime 停站时间单位s
*/
void updateStationParkTime(Simulation simulation, String groupNumber, int parkTime);
/** /**
* 发车 * 发车
* @param simulation * @param simulation

View File

@ -110,21 +110,6 @@ public class OnboardAtpApiServiceImpl implements OnboardAtpApiService {
serviceNumber, tripNumber, destinationCode)); serviceNumber, tripNumber, destinationCode));
} }
@Override
public void updateStationParkTime(Simulation simulation,
String groupNumber,
int parkTime) {
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = repository.getVRByCode(groupNumber, VirtualRealityTrain.class);
train.park(parkTime);
log.debug(String.format("列车[%s]停站时间[%s s]",
train.getGroupNumber(), parkTime));
// if (parkTime > 0) {
// // 开屏蔽门
// this.ATOService.syncOpenDoor(simulation, train);
// }
}
@Override @Override
public void departure(Simulation simulation, String groupNumber) { public void departure(Simulation simulation, String groupNumber) {
SimulationDataRepository repository = simulation.getRepository(); SimulationDataRepository repository = simulation.getRepository();

View File

@ -4,6 +4,8 @@ import club.joylink.rtss.services.psl.IVirtualRealityPslService;
import club.joylink.rtss.simulation.cbtc.ATP.ground.MaService; import club.joylink.rtss.simulation.cbtc.ATP.ground.MaService;
import club.joylink.rtss.simulation.cbtc.ATS.operation.handler.DriverOperateHandler; import club.joylink.rtss.simulation.cbtc.ATS.operation.handler.DriverOperateHandler;
import club.joylink.rtss.simulation.cbtc.ATS.service.AtsStationService; import club.joylink.rtss.simulation.cbtc.ATS.service.AtsStationService;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcRepository;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcStationRunPlanLog;
import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.command.CommandBO; import club.joylink.rtss.simulation.cbtc.command.CommandBO;
import club.joylink.rtss.simulation.cbtc.constant.SignalAspect; import club.joylink.rtss.simulation.cbtc.constant.SignalAspect;
@ -14,6 +16,7 @@ import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
import club.joylink.rtss.simulation.cbtc.data.map.*; import club.joylink.rtss.simulation.cbtc.data.map.*;
import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition; import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition;
import club.joylink.rtss.simulation.cbtc.data.vo.ControlTransferReplyVO; import club.joylink.rtss.simulation.cbtc.data.vo.ControlTransferReplyVO;
import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo;
import club.joylink.rtss.simulation.cbtc.data.vr.*; import club.joylink.rtss.simulation.cbtc.data.vr.*;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember; import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import club.joylink.rtss.simulation.cbtc.onboard.ATO.SpeedCurve; import club.joylink.rtss.simulation.cbtc.onboard.ATO.SpeedCurve;
@ -23,10 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.util.Collections; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain.ConfirmationMessage.Confirm_Release_Speed; import static club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain.ConfirmationMessage.Confirm_Release_Speed;
@ -64,7 +64,10 @@ public class RobotLogicLoop {
robotStationControlAutoTransfer(simulation); robotStationControlAutoTransfer(simulation);
} }
private void robotOpenATO(Simulation simulation, VirtualRealityTrain train) { /**
* 机器人准备发车
*/
private void robotReadyForDeparture(Simulation simulation, VirtualRealityTrain train) {
StandParkedTrainActivity activity = train.getStandParkedTrainActivity(); StandParkedTrainActivity activity = train.getStandParkedTrainActivity();
if (activity != null) { if (activity != null) {
switch (activity) { switch (activity) {
@ -142,6 +145,7 @@ public class RobotLogicLoop {
*/ */
private void robotDriverLogicLoop(Simulation simulation) { private void robotDriverLogicLoop(Simulation simulation) {
List<SimulationMember> drivers = simulation.querySimulationMembersOfRole(SimulationMember.Type.DRIVER); List<SimulationMember> drivers = simulation.querySimulationMembersOfRole(SimulationMember.Type.DRIVER);
boolean railway = simulation.getRepository().getConfig().isRailway();
for (SimulationMember driver : drivers) { for (SimulationMember driver : drivers) {
if (!driver.isRobot()) if (!driver.isRobot())
continue; continue;
@ -150,15 +154,78 @@ public class RobotLogicLoop {
if (!repository.isVrTrainOnline(train.getGroupNumber())) { //如果列车不在线 if (!repository.isVrTrainOnline(train.getGroupNumber())) { //如果列车不在线
continue; continue;
} }
robotOpenATO(simulation, train); //准备发车
robotDrive(simulation, driver, train); robotReadyForDeparture(simulation, train);
//机器人驾驶
if (train.getRobotTargetPosition() != null) {
robotDriveByCommand(simulation, driver, train);
} else if (railway) {
railRobotDrive(simulation, train);
}
} }
} }
/** /**
* 机器人驾驶 * 大铁机器人自动驾驶
* 在确认列车自身状态正确的情况下车门是关闭状态等如果是没有计划的车次则只看信号如果是有计划的车次还需要看计划
*/ */
private void robotDrive(Simulation simulation, SimulationMember driver, VirtualRealityTrain train) { private void railRobotDrive(Simulation simulation, VirtualRealityTrain train) {
if (!train.getDoor1().isCloseAndLock() || !train.getDoor2().isCloseAndLock())
return;
SimulationDataRepository repository = simulation.getRepository();
boolean right = train.isRight();
SectionPosition headPosition = train.getHeadPosition();
Section nextSection = headPosition.getSection();
TrainInfo trainInfo = repository.getSupervisedTrainByGroup(train.getGroupNumber());
CtcRepository ctcRepository = simulation.getCtcRepository();
Collection<CtcStationRunPlanLog> runPlans = ctcRepository.findRunPlans(trainInfo.getTripNumber());
Set<Section> tracks = new HashSet<>();
for (CtcStationRunPlanLog runPlan : runPlans) {
CtcStationRunPlanLog.RunPlanItem arriveRunPlan = runPlan.getArriveRunPlan();
if (arriveRunPlan != null)
tracks.add(arriveRunPlan.getTrackSection());
CtcStationRunPlanLog.RunPlanItem departRunPlan = runPlan.getDepartRunPlan();
if (departRunPlan != null)
tracks.add(departRunPlan.getTrackSection());
}
SectionPosition targetPosition = null;
for (int i = 0; i < 10; i++) {
if (tracks.contains(nextSection) && !nextSection.equals(train.getParkSection())) { //这个判断感觉迟早要出问题
targetPosition = nextSection.buildStopPointPosition(right); //站台轨停车点
break;
}
Signal signal = nextSection.getSignalOf(right);
if (signal != null && !signal.isShunting()) { //有同向非通过信号机
SectionPosition signalPosition = signal.getPosition();
VirtualRealitySignal vrSignal = signal.getVirtualSignal();
if (vrSignal != null && !headPosition.isAheadOf(signalPosition, right)) { //有物理信号机并且车头没有越过信号机
if (!SignalAspect.G.equals(vrSignal.getAspect())
&& !SignalAspect.Y.equals(vrSignal.getAspect())
&& !SignalAspect.YY.equals(vrSignal.getAspect())) { //大铁线路暂时默认绿灯和黄/双黄灯是正常通行信号
targetPosition = CalculateService.calculateNextPositionByStartAndLen(signalPosition, !right, 5, true); //信号机前5m处
break;
}
}
}
Section next = nextSection.getNextRunningSectionOf(right);
if (next == null) {
targetPosition = new SectionPosition(nextSection, right ? nextSection.getLen() - 10 : 10); //轨道尽头10m处
break;
}
nextSection = next;
}
if (targetPosition == null && nextSection != null) {
targetPosition = new SectionPosition(nextSection, right ? 0 : nextSection.getMaxOffset());
}
if (targetPosition != null)
robotDrive(simulation, train, targetPosition);
}
/**
* 机器人根据指令驾驶列车
*/
private void robotDriveByCommand(Simulation simulation, SimulationMember driver, VirtualRealityTrain train) {
SectionPosition targetPosition = train.getRobotTargetPosition(); SectionPosition targetPosition = train.getRobotTargetPosition();
if (targetPosition == null) if (targetPosition == null)
return; return;