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

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.stage.AtsRealRunRecordService;
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.Simulation;
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.util.CollectionUtils;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
@ -212,36 +215,57 @@ public class AtsTrainMonitorService {
*/
private int getParkTimeOf(Simulation simulation, TrainInfo train, Section standTrack) {
int parkTime = 0;
LocalDateTime systemTime = simulation.getSystemTime();
SimulationDataRepository repository = simulation.getRepository();
if (train.isPlanTrain()) { // 计划车
TripPlan tripPlan = repository.getTripPlan(train.getServiceNumber(), train.getTripNumber());
StationPlan stationPlan = tripPlan.queryStationPlan(standTrack);
if (stationPlan != null) {
if (standTrack.isNormalStandTrack() && tripPlan.isFirstPlan(stationPlan)) { // 折返第一站
parkTime = this.getFirstStationPlanParkTime(stationPlan, systemTime);
} else if (standTrack.isNormalStandTrack() && tripPlan.isLastPlan(stationPlan) &&
tripPlan.isFrontTurnBack()) { // 站前折返终点站
TripPlan nextPlan = repository.queryNextTripPlanOf(tripPlan);
StationPlan firstStationPlan = nextPlan.getFirstStationPlan();
parkTime = this.getFirstStationPlanParkTime(firstStationPlan, systemTime);
} else {
parkTime = stationPlan.getParkTime();
if (!simulation.getRepository().getConfig().isRailway()) { //地铁线路
LocalDateTime systemTime = simulation.getSystemTime();
SimulationDataRepository repository = simulation.getRepository();
if (train.isPlanTrain()) { // 计划车
TripPlan tripPlan = repository.getTripPlan(train.getServiceNumber(), train.getTripNumber());
StationPlan stationPlan = tripPlan.queryStationPlan(standTrack);
if (stationPlan != null) {
if (standTrack.isNormalStandTrack() && tripPlan.isFirstPlan(stationPlan)) { // 折返第一站
parkTime = this.getFirstStationPlanParkTime(stationPlan, systemTime);
} else if (standTrack.isNormalStandTrack() && tripPlan.isLastPlan(stationPlan) &&
tripPlan.isFrontTurnBack()) { // 站前折返终点站
TripPlan nextPlan = repository.queryNextTripPlanOf(tripPlan);
StationPlan firstStationPlan = nextPlan.getFirstStationPlan();
parkTime = this.getFirstStationPlanParkTime(firstStationPlan, systemTime);
} else {
parkTime = stationPlan.getParkTime();
}
} else if (standTrack.isNormalStandTrack()) {
stationPlan = tripPlan.queryStationPlan(standTrack.getStation());
if (stationPlan != null) { // 未停靠在计划的站台轨
parkTime = stationPlan.getParkTime();
}
}
} else if (standTrack.isNormalStandTrack()) {
stationPlan = tripPlan.queryStationPlan(standTrack.getStation());
if (stationPlan != null) { // 未停靠在计划的站台轨
parkTime = stationPlan.getParkTime();
} else { // 头码车或人工车按默认停站时间
StationParkTime stationParkTime = repository.queryStandParkTime(standTrack);
if (stationParkTime != null) {
parkTime = stationParkTime.getParkTime();
} else { // 没有数据默认30s
parkTime = 30;
}
}
} else { // 头码车或人工车按默认停站时间
StationParkTime stationParkTime = repository.queryStandParkTime(standTrack);
if (stationParkTime != null) {
parkTime = stationParkTime.getParkTime();
} else { // 没有数据默认30s
parkTime = 30;
} else { //大铁线路
Station station = standTrack.getStation();
if (station != null) {
CtcRepository ctcRepository = simulation.getCtcRepository();
CtcStationRunPlanLog runPlan = ctcRepository.findRunPlan(station.getCode(), train.getTripNumber());
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;
}

View File

@ -356,6 +356,12 @@ public class CtcRepository {
.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) {
RouteSequence routeSequence = routeSequenceMap.get(stationCode);
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotNull(routeSequence);

View File

@ -67,11 +67,11 @@ public class CtcDispatchCommandService {
private void dispatchCommandParamValid(RailDispatchCommandVO vo) {
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.assertTrue(vo.getContent().length() < 200, "命令正文最大长度200");
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(vo.getContent().length() <= 200, "命令正文最大长度200");
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.assertCollectionNotEmpty(vo.getReceiverIds(), "收令人不能为空");
}

View File

@ -179,28 +179,26 @@ public class SimulationLifeCycleServiceImpl implements SimulationLifeCycleServic
}
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);
depotService.addJobs(simulation);
trainTargetUpdateService.addJobs(simulation);
atsLogicLoop.addJobs(simulation);
vrTrainRunningService.addJobs(simulation);
ciLogic.addJobs(simulation);
vrDeviceLogicLoop.addJobs(simulation);
// zcLogicLoop.addJobs(simulation);
atsMessageCollectAndDispatcher.addJobs(simulation);
joylink3DMessageService.addJobs(simulation);
faultGenerator.addJobs(simulation);
iVirtualRealityIbpService.addJobs(simulation);
powerSupplyService.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

View File

@ -179,6 +179,11 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
*/
private int parkRemainTime;
/**
* 最后一次停站的区段
*/
private Section parkSection;
/**
* 发车提示
*/
@ -538,6 +543,8 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
this.beAbout2Arrive = false;
this.target = null;
this.parkTime = 0;
this.parkRemainTime = 0;
this.parkSection = null;
this.departure = false;
this.breaking = false;
this.standParkedTrainActivity = null;
@ -780,15 +787,6 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
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() {
this.standParkedTrainActivity = null;
this.parkTime = 0;
@ -968,6 +966,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
} else {
this.standParkedTrainActivity = StandParkedTrainActivity.START;
}
this.parkSection = headSection;
}
public boolean isParkingAt() {

View File

@ -31,14 +31,6 @@ public interface OnboardAtpApiService {
*/
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

View File

@ -110,21 +110,6 @@ public class OnboardAtpApiServiceImpl implements OnboardAtpApiService {
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
public void departure(Simulation simulation, String groupNumber) {
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.ATS.operation.handler.DriverOperateHandler;
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.command.CommandBO;
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.support.SectionPosition;
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.member.SimulationMember;
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.util.CollectionUtils;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.*;
import java.util.stream.Collectors;
import static club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain.ConfirmationMessage.Confirm_Release_Speed;
@ -64,7 +64,10 @@ public class RobotLogicLoop {
robotStationControlAutoTransfer(simulation);
}
private void robotOpenATO(Simulation simulation, VirtualRealityTrain train) {
/**
* 机器人准备发车
*/
private void robotReadyForDeparture(Simulation simulation, VirtualRealityTrain train) {
StandParkedTrainActivity activity = train.getStandParkedTrainActivity();
if (activity != null) {
switch (activity) {
@ -142,6 +145,7 @@ public class RobotLogicLoop {
*/
private void robotDriverLogicLoop(Simulation simulation) {
List<SimulationMember> drivers = simulation.querySimulationMembersOfRole(SimulationMember.Type.DRIVER);
boolean railway = simulation.getRepository().getConfig().isRailway();
for (SimulationMember driver : drivers) {
if (!driver.isRobot())
continue;
@ -150,15 +154,78 @@ public class RobotLogicLoop {
if (!repository.isVrTrainOnline(train.getGroupNumber())) { //如果列车不在线
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();
if (targetPosition == null)
return;