修改设置备用车时列车级别不正确的bug;修改机器人驾驶及ATS界面的修改预选模式操作逻辑;挤岔恢复操作增加等待

This commit is contained in:
joylink_zhangsai 2023-10-31 17:38:18 +08:00
parent 376590f5d1
commit 67175c5919
9 changed files with 5006 additions and 4844 deletions

View File

@ -12,11 +12,10 @@ import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import club.joylink.rtss.simulation.cbtc.onboard.ATO.service.ATOService;
import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPService;
import club.joylink.rtss.simulation.cbtc.robot.SimulationRobotService;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Objects;
/**
* 司机操作处理
*/
@ -37,8 +36,9 @@ public class DriverOperateHandler {
public void changeTrainForce(Simulation simulation, String groupNumber, Float percent) {
Objects.requireNonNull(percent);
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
if (!validate(train))
if (!validate(train)) {
return;
}
ATPService.changeTrainForce(train, percent);
}
@ -48,8 +48,9 @@ public class DriverOperateHandler {
@OperateHandlerMapping(type = Operation.Type.Driver_EB)
public void trainEB(Simulation simulation, String groupNumber) {
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
if (!validate(train))
if (!validate(train)) {
return;
}
if (train.isCircuitEB()) {
this.ATPService.cancelCircuitEB(train);
} else {
@ -65,11 +66,13 @@ public class DriverOperateHandler {
* @param gear
*/
@OperateHandlerMapping(type = Operation.Type.Driver_Gear_Change)
public void changeTrainGear(Simulation simulation, String groupNumber, VirtualRealityTrain.Handwheel gear) {
public void changeTrainGear(Simulation simulation, String groupNumber,
VirtualRealityTrain.Handwheel gear) {
Objects.requireNonNull(gear);
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
if (!validate(train))
if (!validate(train)) {
return;
}
ATPService.changeGear(train, gear);
}
@ -92,16 +95,18 @@ public class DriverOperateHandler {
@OperateHandlerMapping(type = Operation.Type.Driver_ATO_Open)
public void openAto(Simulation simulation, String groupNumber) {
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
if (!validate(train))
if (!validate(train)) {
return;
}
ATPService.openATO(train);
}
@OperateHandlerMapping(type = Operation.Type.Driver_ATP_Change)
public void changeAtpStatus(Simulation simulation, String groupNumber, boolean cutOff) {
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
if (!validate(train))
if (!validate(train)) {
return;
}
if (cutOff) {
this.ATPService.cutOffAtp(train);
} else {
@ -112,8 +117,9 @@ public class DriverOperateHandler {
@OperateHandlerMapping(type = Operation.Type.Driver_Change_Head)
public void changeHead(Simulation simulation, String groupNumber) {
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
if (!validate(train))
if (!validate(train)) {
return;
}
if (train.isStop()) {
this.ATPService.turnDirectionImmediately(train);
}
@ -129,8 +135,9 @@ public class DriverOperateHandler {
@OperateHandlerMapping(type = Operation.Type.Driver_Door_On_Off)
public void onOrOffDoor(Simulation simulation, String groupNumber, Boolean right, Boolean open) {
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
if (!validate(train))
if (!validate(train)) {
return;
}
ATPService.openOrCloseDoor(simulation, train, right, open);
}
@ -146,8 +153,9 @@ public class DriverOperateHandler {
throw new SimulationException(SimulationExceptionType.Illegal_Argument, "门模式不能为空");
}
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
if (!validate(train))
if (!validate(train)) {
return;
}
train.setDoorMode(doorMode);
}
@ -163,8 +171,9 @@ public class DriverOperateHandler {
throw new SimulationException(SimulationExceptionType.Illegal_Argument, "门选择不能为空");
}
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
if (!validate(train))
if (!validate(train)) {
return;
}
train.setDoorSelection(doorSelection);
}
@ -174,8 +183,9 @@ public class DriverOperateHandler {
@OperateHandlerMapping(type = Operation.Type.Driver_Preselection_Mode_Up)
public void beforehandModeUp(Simulation simulation, String groupNumber) {
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
if (!validate(train))
if (!validate(train)) {
return;
}
ATPService.preselectionModeUp(train);
}
@ -185,8 +195,9 @@ public class DriverOperateHandler {
@OperateHandlerMapping(type = Operation.Type.Driver_Preselection_Mode_Down)
public void beforehandModeDown(Simulation simulation, String groupNumber) {
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
if (!validate(train))
if (!validate(train)) {
return;
}
ATPService.preselectionModeDown(train);
}
@ -196,8 +207,9 @@ public class DriverOperateHandler {
@OperateHandlerMapping(type = Operation.Type.Driver_Confirm)
public void confirmMessage(Simulation simulation, String groupNumber) {
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
if (!validate(train))
if (!validate(train)) {
return;
}
ATPService.confirmMessage(train);
}
@ -214,7 +226,8 @@ public class DriverOperateHandler {
* ATS停车
*/
@OperateHandlerMapping(type = Operation.Type.Driver_Stop)
public void stopTrain(Simulation simulation, SimulationMember simulationMember, String groupNumber, Boolean eb) {
public void stopTrain(Simulation simulation, SimulationMember simulationMember,
String groupNumber, Boolean eb) {
simulationRobotService.stopTrain(simulation, simulationMember, groupNumber, eb);
}
@ -256,7 +269,9 @@ public class DriverOperateHandler {
*/
@OperateHandlerMapping(type = Operation.Type.Try_Open_Ato)
public void tryOpenAto(Simulation simulation, String groupNumber) {
ATPService.openAto(simulation, groupNumber);
VirtualRealityTrain train = simulation.getRepository()
.getVRByCode(groupNumber, VirtualRealityTrain.class);
ATPService.openATO(train);
}
/**

View File

@ -15,15 +15,14 @@ import club.joylink.rtss.simulation.cbtc.data.map.Section;
import club.joylink.rtss.simulation.cbtc.data.map.Switch;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@OperateHandler
@Slf4j
@ -213,7 +212,8 @@ public class SwitchOperateHandler {
try {
limitSpeed = Integer.parseInt(speedLimitValue);
} catch (NumberFormatException e) {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, "速度值必须为数字!");
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
"速度值必须为数字!");
}
this.groundAtpApiService.setSwitchLimitSpeed(simulation, switchCode, limitSpeed);
}
@ -287,13 +287,17 @@ public class SwitchOperateHandler {
@OperateHandlerMapping(type = Operation.Type.Switch_Squeeze_Recovery)
public void switchSqueezeRecovery(Simulation simulation, String switchCode) {
ciApiService.switchSqueezeRecovery(simulation, switchCode);
waitResult(simulation, simulation.getRepository().getByCode(switchCode, Switch.class),
SwitchIndication.N, SwitchIndication.R);
}
/**
* 命令泰雷兹
*/
@OperateHandlerMapping(type = Operation.Type.Switch_Command)
public void switchCommand(Simulation simulation, String switchCode, Boolean auto, Boolean reserve, Boolean normal) {
public void switchCommand(Simulation simulation, String switchCode, Boolean auto, Boolean reserve,
Boolean normal) {
ciApiService.switchCommand(simulation, switchCode, auto, reserve, normal);
}
@ -307,8 +311,10 @@ public class SwitchOperateHandler {
@OperateHandlerMapping(type = Operation.Type.Switch_Defective_Shunting)
public void defectiveShunting(Simulation simulation, String switchCode) {
Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class);
List<Section.ShuntingType> shuntingTypeList = Arrays.asList(Section.ShuntingType.SWITCH_FRONT_SHUNTING,
Section.ShuntingType.FIXED_POSITION_SHUNTING, Section.ShuntingType.REVERSE_POSITION_SHUNTING);
List<Section.ShuntingType> shuntingTypeList = Arrays.asList(
Section.ShuntingType.SWITCH_FRONT_SHUNTING,
Section.ShuntingType.FIXED_POSITION_SHUNTING,
Section.ShuntingType.REVERSE_POSITION_SHUNTING);
atsSectionService.defectiveShunting(simulation, aSwitch.getA().getCode(), shuntingTypeList);
}
@ -324,17 +330,23 @@ public class SwitchOperateHandler {
atsSectionService.defectiveShunting(simulation, aSwitch.getA().getCode(), new ArrayList<>());
}
private static void waitResult(Simulation simulation, Switch aSwitch, SwitchIndication pos) {
/**
* 道岔只要处于{posArr}中任意一个位置就认为操作完成
*/
private static void waitResult(Simulation simulation, Switch aSwitch,
SwitchIndication... posArr) {
//等待转动完成
LocalDateTime timeoutTime = simulation.getSystemTime().plusSeconds(13);
CompletableFuture<Boolean> future = CompletableFuture.supplyAsync(() -> {
while (true) {
for (SwitchIndication pos : posArr) {
if (Objects.equals(aSwitch.getPos(), pos)) {
return true;
}
if (simulation.getSystemTime().isAfter(timeoutTime)) {
return false;
}
}
try {
Thread.sleep(100);
} catch (Exception e) {

View File

@ -192,14 +192,6 @@ public interface CiApiService {
*/
void switchSectionFaultUnlock(Simulation simulation, String switchCode);
/**
* 设置自动通过进路
*
* @param simulation
* @param routeCode
*/
void setFleetRoute(Simulation simulation, String routeCode);
/**
* 取消自动通过进路
*
@ -208,22 +200,6 @@ public interface CiApiService {
*/
void cancelFleetRoute(Simulation simulation, String routeCode);
/**
* 设置进路CI自动触发
*
* @param simulation
* @param routeCode
*/
void setCIAutoTriggerRoute(Simulation simulation, String routeCode);
/**
* 取消进路CI自动触发
*
* @param simulation
* @param routeCode
*/
void cancelCIAutoTriggerRoute(Simulation simulation, String routeCode);
/**
* 根据始端信号机查询锁闭进路
*
@ -233,24 +209,6 @@ public interface CiApiService {
*/
Route findLockedRouteByStartSignal(Simulation simulation, String signalCode);
/**
* 根据始端终端信号机查询进路(根据延续保护自动筛选出一条进路)
*
* @param simulation
* @param startSignalCode
* @param endSignalCode
* @return
*/
Route findRouteByStartAndEndSignal(Simulation simulation, String startSignalCode, String endSignalCode);
/**
* 办理引导进路
*
* @param simulation
* @param routeCode
*/
void settingGuideRoute(Simulation simulation, String routeCode);
/**
* 开站台屏蔽门
*

View File

@ -1,33 +1,52 @@
package club.joylink.rtss.simulation.cbtc.CI;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.CI.device.*;
import club.joylink.rtss.simulation.cbtc.CI.device.CiRouteService;
import club.joylink.rtss.simulation.cbtc.CI.device.CiSectionService;
import club.joylink.rtss.simulation.cbtc.CI.device.CiService;
import club.joylink.rtss.simulation.cbtc.CI.device.CiSignalControlService;
import club.joylink.rtss.simulation.cbtc.CI.device.CiStandService;
import club.joylink.rtss.simulation.cbtc.CI.device.CiSwitchControlService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.constant.SignalAspect;
import club.joylink.rtss.simulation.cbtc.constant.SwitchIndication;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
import club.joylink.rtss.simulation.cbtc.data.map.*;
import club.joylink.rtss.simulation.cbtc.data.map.ESP;
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.RouteOverlap;
import club.joylink.rtss.simulation.cbtc.data.map.Section;
import club.joylink.rtss.simulation.cbtc.data.map.Server;
import club.joylink.rtss.simulation.cbtc.data.map.Signal;
import club.joylink.rtss.simulation.cbtc.data.map.Stand;
import club.joylink.rtss.simulation.cbtc.data.map.Station;
import club.joylink.rtss.simulation.cbtc.data.map.Switch;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySectionAxleCounter;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySignal;
import club.joylink.rtss.simulation.cbtc.device.virtual.VirtualRealityDeviceService;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
import java.time.LocalTime;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;
/**
* CI子系统
*/
@Slf4j
@Component
public class CiApiServiceImpl2 implements CiApiService {
@Autowired
private CiSwitchControlService switchService;
@Autowired
@ -84,14 +103,16 @@ public class CiApiServiceImpl2 implements CiApiService {
}
Optional<Route> routeOptional = simulation.getRepository().getSettingRoutes().stream()
.filter(route -> route.getStart().equals(signal)).findAny();
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(routeOptional.isPresent(), "信号机不是已排进路的始端信号机");
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(routeOptional.isPresent(),
"信号机不是已排进路的始端信号机");
// settingRoute(simulation, routeOptional.get().getCode());
Route lockedRoute = signal.getLockedRoute();
if (Objects.isNull(lockedRoute)) {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
"进路未锁闭,不能重开信号机");
}
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(!lockedRoute.isDelayUnlocking(), "进路延时解锁中,不能重开");
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(!lockedRoute.isDelayUnlocking(),
"进路延时解锁中,不能重开");
signal.setForbidden(false);
}
@ -101,7 +122,8 @@ public class CiApiServiceImpl2 implements CiApiService {
SwitchIndication pos = this.switchService.turn(simulation, aSwitch);
if (pos == null) {
log.info(String.format("道岔[%s(%s)]锁闭,不能转动", aSwitch.getName(), aSwitch.getCode()));
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, "道岔锁闭,不能进行转动");
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
"道岔锁闭,不能进行转动");
}
if (Switch.SwitchFault.SPLIT_1.equals(aSwitch.getFault())) {
Switch.SwitchFault.SPLIT_1.fix(aSwitch);
@ -113,8 +135,10 @@ public class CiApiServiceImpl2 implements CiApiService {
public void turn2NormalPosition(Simulation simulation, String switchCode) {
Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class);
if (!this.switchService.turn2NormalPosition(simulation, aSwitch)) {
log.info(String.format("道岔[%s(%s)]锁闭,不能进行定操", aSwitch.getName(), aSwitch.getCode()));
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, "道岔锁闭,不能进行定操");
log.info(
String.format("道岔[%s(%s)]锁闭,不能进行定操", aSwitch.getName(), aSwitch.getCode()));
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
"道岔锁闭,不能进行定操");
}
}
@ -122,8 +146,10 @@ public class CiApiServiceImpl2 implements CiApiService {
public void turn2ReversePosition(Simulation simulation, String switchCode) {
Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class);
if (!this.switchService.turn2ReversePosition(simulation, aSwitch)) {
log.info(String.format("道岔[%s(%s)]锁闭,不能进行反操", aSwitch.getName(), aSwitch.getCode()));
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, "道岔锁闭,不能进行反操");
log.info(
String.format("道岔[%s(%s)]锁闭,不能进行反操", aSwitch.getName(), aSwitch.getCode()));
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
"道岔锁闭,不能进行反操");
}
}
@ -194,8 +220,10 @@ public class CiApiServiceImpl2 implements CiApiService {
@Override
public void unlockRoute(Simulation simulation, String routeCode) {
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
if (route.isTransferRoute() && simulation.getRepository().getConfig().isTransferRouteCanOnlyFaultUnlock()) {
throw BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.exception("转换轨进路只能通过区故解取消");
if (route.isTransferRoute() && simulation.getRepository().getConfig()
.isTransferRouteCanOnlyFaultUnlock()) {
throw BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.exception(
"转换轨进路只能通过区故解取消");
}
if (simulation.getRepository().getConfig().isDelayWhenCancelRouteWithAbnormalInterlock()) {
if (this.ciService.isRouteSwitchLost(simulation, route)) {
@ -228,11 +256,13 @@ public class CiApiServiceImpl2 implements CiApiService {
public void sectionFaultUnlock(Simulation simulation, String sectionCode) {
Section section = simulation.getRepository().getByCode(sectionCode, Section.class);
if (simulation.getRepository().getConfig().isSFUCanOnlyApplyForFaultLockSection()) {
if (!section.isFaultLock())
if (!section.isFaultLock()) {
return;
}
}
if (section.isCross()) {
Optional<Section> crossLockedSectionOptional = section.getLogicList().stream().filter(Section::isLocked).findAny();
Optional<Section> crossLockedSectionOptional = section.getLogicList().stream()
.filter(Section::isLocked).findAny();
if (crossLockedSectionOptional.isEmpty()) {
return;
}
@ -258,7 +288,8 @@ public class CiApiServiceImpl2 implements CiApiService {
}
}
if (lockedRoute != null && lockedRoute.isDelayUnlocking()) {
throw BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.exception("进路延时解锁中,不能区故解");
throw BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.exception(
"进路延时解锁中,不能区故解");
}
this.routeService.sectionFaultUnlock(simulation, section, lockedRoute);
}
@ -266,8 +297,9 @@ public class CiApiServiceImpl2 implements CiApiService {
@Override
public void switchSectionFaultUnlock(Simulation simulation, String switchCode) {
Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class);
if (!aSwitch.isLocked() && aSwitch.getAllSections().stream().noneMatch(Section::isLocked))
if (!aSwitch.isLocked() && aSwitch.getAllSections().stream().noneMatch(Section::isLocked)) {
return;
}
List<Route> lockedRouteList = simulation.getRepository().queryAllLockedRoute();
Set<Route> lockSwitchRoutes = new HashSet<>();
if (aSwitch.isRouteLock()) {
@ -290,30 +322,12 @@ public class CiApiServiceImpl2 implements CiApiService {
}
}
@Override
public void setFleetRoute(Simulation simulation, String routeCode) {
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
this.routeService.setFleet(route);
}
@Override
public void cancelFleetRoute(Simulation simulation, String routeCode) {
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
this.routeService.cancelFleet(route);
}
@Override
public void setCIAutoTriggerRoute(Simulation simulation, String routeCode) {
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
this.routeService.setCIAutoTrigger(route);
}
@Override
public void cancelCIAutoTriggerRoute(Simulation simulation, String routeCode) {
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
this.routeService.cancelCIAutoTrigger(route);
}
@Override
public Route findLockedRouteByStartSignal(Simulation simulation, String signalCode) {
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
@ -321,27 +335,8 @@ public class CiApiServiceImpl2 implements CiApiService {
}
@Override
public Route findRouteByStartAndEndSignal(Simulation simulation, String startSignalCode, String endSignalCode) {
Signal start = simulation.getRepository().getByCode(startSignalCode, Signal.class);
List<Route> routeList = start.getRouteList();
if (!CollectionUtils.isEmpty(routeList)) {
for (Route route : routeList) {
if (Objects.equals(route.getDestination().getCode(), endSignalCode)) {
return route;
}
}
}
return null;
}
@Override
public void settingGuideRoute(Simulation simulation, String routeCode) {
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
this.routeService.setGuide(simulation, route);
}
@Override
public void openScreenDoor(Simulation simulation, String standCode, CiStandService.PsdCommandSource source) {
public void openScreenDoor(Simulation simulation, String standCode,
CiStandService.PsdCommandSource source) {
Stand stand = simulation.getRepository().getByCode(standCode, Stand.class);
if (Objects.nonNull(stand.getPsd())) {
standService.openScreenDoor(simulation, stand, source);
@ -349,7 +344,8 @@ public class CiApiServiceImpl2 implements CiApiService {
}
@Override
public void closeScreenDoor(Simulation simulation, String standCode, CiStandService.PsdCommandSource source) {
public void closeScreenDoor(Simulation simulation, String standCode,
CiStandService.PsdCommandSource source) {
Stand stand = simulation.getRepository().getByCode(standCode, Stand.class);
if (Objects.nonNull(stand.getPsd())) {
standService.closeScreenDoor(simulation, stand, source);
@ -413,7 +409,8 @@ public class CiApiServiceImpl2 implements CiApiService {
route = repository.getByCode(routeCode, Route.class);
signal = route.getStart();
} else {
throw BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.exception("signalCode和routeCode不能都为空");
throw BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.exception(
"signalCode和routeCode不能都为空");
}
if (route == null && signal.getRouteList().stream().anyMatch(Route::isAnySwitchMasterLock)) {
@ -427,11 +424,14 @@ public class CiApiServiceImpl2 implements CiApiService {
//条件检查
if (firstCheck) {
List<Route> routeList = signal.getRouteList();
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertCollectionNotEmpty(routeList, String.format("信号机[%s]非进路始端信号机", signal.getCode()));
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertCollectionNotEmpty(routeList,
String.format("信号机[%s]非进路始端信号机", signal.getCode()));
if (route != null) {
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(route.isLock(), String.format("进路[%s]未办理", route.getCode()));
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(route.isLock(),
String.format("进路[%s]未办理", route.getCode()));
} else {
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotNull(signal.getLockedRoute(), String.format("信号机[%s]无已办理进路", signal.getCode()));
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotNull(signal.getLockedRoute(),
String.format("信号机[%s]无已办理进路", signal.getCode()));
}
}
// if (config.isSomeCommandNeedInit()) {
@ -443,23 +443,27 @@ public class CiApiServiceImpl2 implements CiApiService {
// }
if (config.isNeedApproachLockBeforeSetGuide()) {
boolean signalApproachOccupied = signal.getApproachPathList()
.stream().anyMatch(sectionPath -> sectionPath.getSectionList().stream().anyMatch(Section::isOccupied));
.stream().anyMatch(
sectionPath -> sectionPath.getSectionList().stream().anyMatch(Section::isOccupied));
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(signalApproachOccupied,
String.format("对%s开放引导操作失败接近区段没有列车占用", signal.getName()));
}
//办理引导进路或开放引导信号
if (firstCheck) {
this.signalService.tryControlSignalAspectAccordingLevel(simulation, signal, signal.getSignalModel().getGuideAspect());
this.signalService.tryControlSignalAspectAccordingLevel(simulation, signal,
signal.getSignalModel().getGuideAspect());
} else {
if (route != null) {
if (route.isLock()) {
this.signalService.tryControlSignalAspectAccordingLevel(simulation, signal, signal.getSignalModel().getGuideAspect());
this.signalService.tryControlSignalAspectAccordingLevel(simulation, signal,
signal.getSignalModel().getGuideAspect());
} else {
this.routeService.setGuide(simulation, route);
}
} else {
if (signal.getLockedRoute() != null) { //如果有已锁闭进路
this.signalService.tryControlSignalAspectAccordingLevel(simulation, signal, signal.getSignalModel().getGuideAspect());
this.signalService.tryControlSignalAspectAccordingLevel(simulation, signal,
signal.getSignalModel().getGuideAspect());
} else if (!CollectionUtils.isEmpty(signal.getRouteList())) {
List<Route> collect;
if (config.isRailway()) { // 大铁配置引导进路
@ -475,7 +479,8 @@ public class CiApiServiceImpl2 implements CiApiService {
.collect(Collectors.toList());
}
if (CollectionUtils.isEmpty(collect)) {
collect = signal.getRouteList().stream().filter(r -> !r.isTurnBack()).collect(Collectors.toList());
collect = signal.getRouteList().stream().filter(r -> !r.isTurnBack())
.collect(Collectors.toList());
}
if (CollectionUtils.isEmpty(collect)) {
collect = signal.getRouteList();
@ -483,7 +488,8 @@ public class CiApiServiceImpl2 implements CiApiService {
route = collect.get(0);
this.routeService.setGuide(simulation, route);
} else { //如果信号机没有关联进路
this.signalService.tryControlSignalAspectAccordingLevel(simulation, signal, signal.getSignalModel().getGuideAspect());
this.signalService.tryControlSignalAspectAccordingLevel(simulation, signal,
signal.getSignalModel().getGuideAspect());
}
}
}
@ -499,8 +505,7 @@ public class CiApiServiceImpl2 implements CiApiService {
}
/**
* 在引导总锁的状态下开放引导信号
* 引导总锁之后
* 在引导总锁的状态下开放引导信号 引导总锁之后
*/
private void openGuideAspect4GuideMasterLock(Simulation simulation, Signal signal) {
signalService.controlSignalAspect(simulation, signal, signal.getGuideAspect());
@ -549,21 +554,28 @@ public class CiApiServiceImpl2 implements CiApiService {
station = station.getDeviceStation();
}
Station deviceStation = station;
boolean restartFlag = Objects.nonNull(deviceStation.getRestartTime()) && deviceStation.getRestartTime().isBefore(simulation.getCorrectSystemTime().toLocalTime());
boolean restartFlag =
Objects.nonNull(deviceStation.getRestartTime()) && deviceStation.getRestartTime()
.isBefore(simulation.getCorrectSystemTime().toLocalTime());
// 是否大铁设备
boolean hasCTCFlag = simulation.getRepository().getConfig().isRailway();
// 大铁异常提示语
String exceptionMsg = hasCTCFlag ? "无效操作:车站未下电" : "无效操作或连锁机重启过8分钟需手动解锁";
String exceptionMsg =
hasCTCFlag ? "无效操作:车站未下电" : "无效操作或连锁机重启过8分钟需手动解锁";
// 是否需要重启
if (restartFlag) {
// 考试课程上电标识
boolean powerOnFlag = ((Simulation.FunctionalType.LESSON.equals(simulation.getBuildParams().getFunctionalType())
|| Simulation.FunctionalType.EXAM.equals(simulation.getBuildParams().getFunctionalType()))
boolean powerOnFlag = (
(Simulation.FunctionalType.LESSON.equals(simulation.getBuildParams().getFunctionalType())
|| Simulation.FunctionalType.EXAM.equals(
simulation.getBuildParams().getFunctionalType()))
? true : deviceStation.getRestartTime().plusMinutes(8).isAfter(LocalTime.now()));
if (hasCTCFlag || powerOnFlag) {
deviceStation.setPowerUnlockButtonShow(false);
List<Section> sections = simulation.getRepository().getSectionList();
sections.stream().filter(section -> Objects.equals(section.getDeviceStation(), deviceStation)).forEach(Section::faultUnlock);
sections.stream()
.filter(section -> Objects.equals(section.getDeviceStation(), deviceStation))
.forEach(Section::faultUnlock);
return;
}
}
@ -572,24 +584,28 @@ public class CiApiServiceImpl2 implements CiApiService {
@Override
public void standEC(Simulation simulation, Stand stand) {
if (stand.getEsp() == null)
if (stand.getEsp() == null) {
return;
}
stand.getEsp().update(true);
}
@Override
public void cancelStandEC(Simulation simulation, Stand stand) {
if (stand.getEsp() == null)
if (stand.getEsp() == null) {
return;
}
stand.getEsp().update(false);
}
@Override
public SwitchIndication switchForceTurn(Simulation simulation, String switchCode) {
Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class);
BusinessExceptionAssertEnum.SIMULATION_EXCEPTION_FOR_SHOW.assertTrue(!aSwitch.isLocked() && aSwitch.isSectionOccupied(),
BusinessExceptionAssertEnum.SIMULATION_EXCEPTION_FOR_SHOW.assertTrue(
!aSwitch.isLocked() && aSwitch.isSectionOccupied(),
String.format("对%s强行转岔操作被联锁逻辑取消", aSwitch.getName()));
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(!aSwitch.isLocked(), String.format("道岔[%s]锁闭,无法转动", aSwitch.getCode()));
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(!aSwitch.isLocked(),
String.format("道岔[%s]锁闭,无法转动", aSwitch.getCode()));
return this.switchService.forceTurn(simulation, aSwitch);
}
@ -598,7 +614,8 @@ public class CiApiServiceImpl2 implements CiApiService {
Section section = simulation.getRepository().getByCode(sectionCode, Section.class);
Section axleSection = section.findAxleCounterSection();
//条件检查
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(axleSection != null && axleSection.isAxleCounter(),
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(
axleSection != null && axleSection.isAxleCounter(),
section.debugStr() + "不是计轴区段也不归属于任何计轴区段");
VirtualRealitySectionAxleCounter virtualAxleCounter = axleSection.getVirtualAxleCounter();
if (!virtualAxleCounter.isOccupy()) {
@ -621,13 +638,15 @@ public class CiApiServiceImpl2 implements CiApiService {
}
@Override
public void switchCommand(Simulation simulation, String switchCode, Boolean auto, Boolean reserve, Boolean normal) {
public void switchCommand(Simulation simulation, String switchCode, Boolean auto, Boolean reserve,
Boolean normal) {
Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class);
if (auto != null) {
aSwitch.setAuto(auto);
} else {
if (normal != null) {
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(!aSwitch.isAuto(), "道岔未处于人工模式");
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(!aSwitch.isAuto(),
"道岔未处于人工模式");
if (normal) {
switchService.turn2NormalPosition(simulation, aSwitch);
} else {
@ -661,8 +680,9 @@ public class CiApiServiceImpl2 implements CiApiService {
@Override
public void axleReset(Simulation simulation, String sectionCode) {
VirtualRealitySectionAxleCounter axle = getAxleCounterAndCheck4Reset(simulation, sectionCode);
if (!axle.isOccupy())
if (!axle.isOccupy()) {
return;
}
axle.axleReset();
}
@ -727,37 +747,47 @@ public class CiApiServiceImpl2 implements CiApiService {
public void signalTurnOn(Simulation simulation, String signalCode) {
SimulationDataRepository repository = simulation.getRepository();
Signal signal = repository.getByCode(signalCode, Signal.class);
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNull(signal.getLockedRoute(), "信号机有锁闭进路,禁止点灯");
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNull(signal.getLockedRoute(),
"信号机有锁闭进路,禁止点灯");
VirtualRealitySignal vrSignal = signal.getVirtualSignal();
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotNull(vrSignal, signal.debugStr() + "无实体信号机");
virtualRealityDeviceService.control(simulation, vrSignal, vrSignal.getModel().getDefaultAspect());
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotNull(vrSignal,
signal.debugStr() + "无实体信号机");
virtualRealityDeviceService.control(simulation, vrSignal,
vrSignal.getModel().getDefaultAspect());
}
@Override
public void signalTurnOff(Simulation simulation, String signalCode) {
SimulationDataRepository repository = simulation.getRepository();
Signal signal = repository.getByCode(signalCode, Signal.class);
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(signal.isShunting(), "调车信号机无法灭灯");
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNull(signal.getLockedRoute(), "信号机有锁闭进路,禁止灭灯");
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(signal.isShunting(),
"调车信号机无法灭灯");
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNull(signal.getLockedRoute(),
"信号机有锁闭进路,禁止灭灯");
VirtualRealitySignal vrSignal = signal.getVirtualSignal();
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotNull(vrSignal, signal.debugStr() + "无实体信号机");
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotNull(vrSignal,
signal.debugStr() + "无实体信号机");
virtualRealityDeviceService.control(simulation, vrSignal, SignalAspect.No);
}
/**
* 获取计轴器并为预复位/复位操作检查设备状态
*/
private VirtualRealitySectionAxleCounter getAxleCounterAndCheck4Reset(Simulation simulation, String sectionCode) {
private VirtualRealitySectionAxleCounter getAxleCounterAndCheck4Reset(Simulation simulation,
String sectionCode) {
Section section = simulation.getRepository().getByCode(sectionCode, Section.class);
Section axleSection = section.findAxleCounterSection();
//条件检查
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(axleSection != null && axleSection.isAxleCounter(),
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(
axleSection != null && axleSection.isAxleCounter(),
section.debugStr() + "不是计轴区段也不归属于任何计轴区段");
VirtualRealitySectionAxleCounter virtualAxleCounter = axleSection.getVirtualAxleCounter();
if (simulation.getRepository().getConfig().isStationPreResetBeforeAxlePreReset()) {
Station deviceStation = axleSection.getDeviceStation();
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotNull(deviceStation, section.debugStr() + "没有所属集中站");
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(deviceStation.isPreReset(), deviceStation.debugStr() + "需处于预复位状态");
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotNull(deviceStation,
section.debugStr() + "没有所属集中站");
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(deviceStation.isPreReset(),
deviceStation.debugStr() + "需处于预复位状态");
}
return virtualAxleCounter;
}
@ -771,13 +801,15 @@ public class CiApiServiceImpl2 implements CiApiService {
private List<Route> getCtcGuideRouteList(SimulationDataRepository repository, Signal signal) {
// 获取以信号机开头的进路集合
List<Route> routeList = repository.getRouteList().stream()
.filter(routePojo -> routePojo.isTrainRoute() && routePojo.getStart().getCode().equals(signal.getCode()))
.filter(routePojo -> routePojo.isTrainRoute() && routePojo.getStart().getCode()
.equals(signal.getCode()))
.collect(Collectors.toList());
// 进路走向
boolean isRight = routeList.stream().anyMatch(Route::isRight);
// 终端信号机类型信号机类型匹配时停止循环
List<Signal.SignalType> endTypeList = Signal.SignalType.SHUNTING2.equals(signal.getType()) ?
Arrays.asList(Signal.SignalType.RECEIVING, Signal.SignalType.DEPARTURE) : Arrays.asList(Signal.SignalType.SHUNTING2);
Arrays.asList(Signal.SignalType.RECEIVING, Signal.SignalType.DEPARTURE)
: Arrays.asList(Signal.SignalType.SHUNTING2);
// 终止索引最多循环20次防止死循环
int endIndex = 0;
Section nextSection = signal.getSection();

View File

@ -1,27 +1,35 @@
package club.joylink.rtss.simulation.cbtc.CI.device;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.Simulation;
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.constant.SwitchIndication;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
import club.joylink.rtss.simulation.cbtc.data.map.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import club.joylink.rtss.simulation.cbtc.data.map.DelayUnlockDevice;
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 java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
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;
@Slf4j
@Component
public class CiRouteService {
@Autowired
private CiSwitchControlService switchControlService;
@Autowired
@ -31,13 +39,16 @@ public class CiRouteService {
/**
* 进路排列检查
*
* @param guide 是引导进路
* @return
*/
public static Route.CheckFailMessage routeSetCheck(Simulation simulation, Route route, boolean guide) {
public static Route.CheckFailMessage routeSetCheck(Simulation simulation, Route route,
boolean guide) {
if (!CollectionUtils.isEmpty(route.getMultiRouteAspects())) {
for (Route.MultiRouteAspect multiRouteAspect : route.getMultiRouteAspects()) {
Route.CheckFailMessage checkFailMessage = routeSetCheck(simulation, multiRouteAspect.getRoute(), false);
Route.CheckFailMessage checkFailMessage = routeSetCheck(simulation,
multiRouteAspect.getRoute(), false);
if (checkFailMessage != null) {
return checkFailMessage;
}
@ -70,7 +81,8 @@ public class CiRouteService {
} else if (!CollectionUtils.isEmpty(section.getLogicList())) {
for (Section logicSection : section.getLogicList()) {
if (logicSection.isBlockade()) {
return new Route.CheckFailMessage(Route.CheckFailReason.SectionBlockade, logicSection);
return new Route.CheckFailMessage(Route.CheckFailReason.SectionBlockade,
logicSection);
}
}
} else if (section.getParent() != null) {
@ -81,7 +93,8 @@ public class CiRouteService {
// 进路内区段锁闭方向不是此进路方向
if ((section.isRouteLock() || section.isOverlapLock()) &&
!Objects.equals(section.isLockRight(), start.isRight())) {
return new Route.CheckFailMessage(Route.CheckFailReason.SectionLockOppositeDirection, section);
return new Route.CheckFailMessage(Route.CheckFailReason.SectionLockOppositeDirection,
section);
}
//单列车进路区段占用
if (section.isOccupied() && route.isSingleTrain()) {
@ -89,8 +102,9 @@ public class CiRouteService {
}
// 故障占用
for (int i = 0; i < 3; i++) {
if (section.getParent() == null || section.isAxleCounter())
if (section.getParent() == null || section.isAxleCounter()) {
break;
}
section = section.getParent();
}
// if (Section.AxleFault.FAULT.equals(section.getFault())) {
@ -101,7 +115,8 @@ public class CiRouteService {
List<Route> conflictingRouteList = route.getConflictingRouteList();
for (Route conflict : conflictingRouteList) {
if (conflict.isSetting() || conflict.isLock()) {
return new Route.CheckFailMessage(Route.CheckFailReason.ConflictingRouteSetting, conflict);
return new Route.CheckFailMessage(Route.CheckFailReason.ConflictingRouteSetting,
conflict);
}
}
if (start.isCbtcMode()) {
@ -130,11 +145,13 @@ public class CiRouteService {
return null;
}
private static Route.CheckFailMessage monitorRouteOverlapConflictCheck(Simulation simulation, Route route) {
private static Route.CheckFailMessage monitorRouteOverlapConflictCheck(Simulation simulation,
Route route) {
SimulationDataRepository repository = simulation.getRepository();
List<Route> settingRoutes = repository.getSettingRoutes();
for (Route sr : settingRoutes) {
if (sr.isSettingOverlap() && (sr.getOverlap().isSetting() || sr.getOverlap().isLock())/*&& !repository.isTrainParking(sr.getOverlap().getSection())*/) {
if (sr.isSettingOverlap() && (sr.getOverlap().isSetting() || sr.getOverlap()
.isLock())/*&& !repository.isTrainParking(sr.getOverlap().getSection())*/) {
SectionPath sectionPath = sr.getOverlap().selectPath();
for (SwitchElement switchElement : sectionPath.getSwitchList()) {
if (route.isConflictSwitch(switchElement)) {
@ -147,7 +164,8 @@ public class CiRouteService {
return null;
}
private static Route.CheckFailMessage setSwitchCheck(Simulation simulation, List<SwitchElement> switchList, boolean guide) {
private static Route.CheckFailMessage setSwitchCheck(Simulation simulation,
List<SwitchElement> switchList, boolean guide) {
if (switchList != null) {
for (SwitchElement switchElement : switchList) {
Switch aSwitch = switchElement.getASwitch();
@ -162,7 +180,8 @@ public class CiRouteService {
return new Route.CheckFailMessage(Route.CheckFailReason.SwitchLockPositionError, aSwitch);
}
if (aSwitch.isCiUseOnOppositePosition(switchElement.isNormal())) { // 道岔征用在相反位置
return new Route.CheckFailMessage(Route.CheckFailReason.SwitchCiUseOnOppositePosition, aSwitch);
return new Route.CheckFailMessage(Route.CheckFailReason.SwitchCiUseOnOppositePosition,
aSwitch);
}
//道岔失表时进路中的区段和道岔由远及近锁闭直到失表的道岔处 -南铁院叶老师
if (simulation.getRepository().getConfig().isRouteCanSetWhenSwitchFault()) {
@ -170,8 +189,10 @@ public class CiRouteService {
}
// 非预先锁闭道岔相应位置失表则不排进路
if (!simulation.getRepository().getConfig().isLockFirst() && aSwitch.isLoss()) {
if ((Switch.SwitchFault.NORMAL_SPLIT.equals(aSwitch.getFault()) && switchElement.isNormal())
|| (Switch.SwitchFault.REVERSE_SPLIT.equals(aSwitch.getFault()) && !switchElement.isNormal())) {
if ((Switch.SwitchFault.NORMAL_SPLIT.equals(aSwitch.getFault())
&& switchElement.isNormal())
|| (Switch.SwitchFault.REVERSE_SPLIT.equals(aSwitch.getFault())
&& !switchElement.isNormal())) {
return new Route.CheckFailMessage(Route.CheckFailReason.SwitchFault, aSwitch);
}
}
@ -203,7 +224,8 @@ public class CiRouteService {
simulation.getRepository().addSettingRoute(route);
}
if (Objects.nonNull(failMessage)) {
log.info(String.format("进路[%s]排列检查失败,无法排列:%s", route.debugStr(), failMessage.debugStr()));
log.info(String.format("进路[%s]排列检查失败,无法排列:%s", route.debugStr(),
failMessage.debugStr()));
}
}
@ -214,7 +236,8 @@ public class CiRouteService {
* @param route
* @return
*/
public Route.CheckFailMessage setRoute(Simulation simulation, Route route,SignalAspect settedAspect) {
public Route.CheckFailMessage setRoute(Simulation simulation, Route route,
SignalAspect settedAspect) {
Route.CheckFailMessage failMessage = routeSetCheck(simulation, route, false);
if (failMessage == null) {
if (route.isLock() && !route.isFleetMode()) {
@ -237,7 +260,8 @@ public class CiRouteService {
simulation.getRepository().addSettingRoute(route);
}
if (Objects.nonNull(failMessage)) {
log.info(String.format("进路[%s]排列检查失败,无法排列:%s", route.debugStr(), failMessage.debugStr()));
log.info(String.format("进路[%s]排列检查失败,无法排列:%s", route.debugStr(),
failMessage.debugStr()));
}
return failMessage;
}
@ -252,7 +276,8 @@ public class CiRouteService {
if (route.isSetting()) { // 进路排列中
MapConfig config = simulation.getRepository().getConfig();
if (!config.isRouteSettingNoFail()) {
if (simulation.getSystemTime().isAfter(route.getSettingStartTime().plusSeconds(SimulationConstants.ROUTE_SETTING_TIMEOUT))) {
if (simulation.getSystemTime().isAfter(
route.getSettingStartTime().plusSeconds(SimulationConstants.ROUTE_SETTING_TIMEOUT))) {
log.info("进路[{}]办理超时取消办理2", route.debugStr());
route.settingOver(false);
return;
@ -261,7 +286,8 @@ public class CiRouteService {
List<Route.MultiRouteAspect> multiRouteAspects = route.getMultiRouteAspects();
if (CollectionUtils.isEmpty(multiRouteAspects)) {
// 道岔位置转换
boolean mainRouteSwitchOnPos = this.switchControlService.ensureSwitchPosCurrent(simulation, route.getSwitchList(), route.isGuideSetting());
boolean mainRouteSwitchOnPos = this.switchControlService.ensureSwitchPosCurrent(simulation,
route.getSwitchList(), route.isGuideSetting());
// 预先锁闭
if (mainRouteSwitchOnPos || config.isLockFirst() || config.isRouteCanSetWhenSwitchFault()) {
// 进路排列区段预先锁闭
@ -282,7 +308,8 @@ public class CiRouteService {
aspect = route.getAspectOfRailway();
}
}
this.signalControlService.tryControlSignalAspectAccordingLevel(simulation, route.getStart(), aspect);
this.signalControlService.tryControlSignalAspectAccordingLevel(simulation, route.getStart(),
aspect);
if (config.isRailway()) {
if (route.isGuideSetting() && route.getStart().isGuideAspect()
|| !route.getStart().isDefaultAspect()) {
@ -353,13 +380,13 @@ public class CiRouteService {
}
for (int i = switchList.size() - 1; i >= 0; i--) {
SwitchElement switchElement = switchList.get(i);
if (switchElement.isOnPosition() || (route.isGuideSetting() && switchElement.getASwitch().isGuideMasterLock())) {
if (switchElement.isOnPosition() || (route.isGuideSetting() && switchElement.getASwitch()
.isGuideMasterLock())) {
switchElement.getASwitch().routeLock(route);
}
}
route.setLock(true);
// for (SwitchElement switchElement : switchList) {
// if (switchElement.isOnPosition() || (route.isGuideSetting() && switchElement.getASwitch().isGuideMasterLock())) {
// switchElement.getASwitch().routeLock(route);
@ -447,7 +474,8 @@ public class CiRouteService {
device.delayUnlockStart(route, simulation.getRepository().getConfig());
route.setDelayUnlockDevice(device);
route.setAtsControl(false); //南铁院叶老师延时解锁开始的同时信号机应该红名南京二号线
this.signalControlService.tryControlSignalAspectAccordingLevel(simulation, route.getStart(), route.getStart().getDefaultAspect());
this.signalControlService.tryControlSignalAspectAccordingLevel(simulation, route.getStart(),
route.getStart().getDefaultAspect());
}
/**
@ -520,7 +548,8 @@ public class CiRouteService {
return;
} else {
if (route.isOpenMain() || route.isOpenGuide()) {
this.signalControlService.tryControlSignalAspectAccordingLevel(simulation, route.getStart(),
this.signalControlService.tryControlSignalAspectAccordingLevel(simulation,
route.getStart(),
route.getStart().getDefaultAspect());
}
route.setLock(false);
@ -632,7 +661,8 @@ public class CiRouteService {
if (allUnlock) { // 进路所有区段都已经解锁解锁完成
route.normalUnlockOver();
simulation.getRepository().removeSettingRoute(route);
log.debug(String.format("进路[%s(%s)-%s]解锁完毕,移除", route.getName(), route.getCode(), route.isTurnBack() ? "Z" : "B"));
log.debug(String.format("进路[%s(%s)-%s]解锁完毕,移除", route.getName(), route.getCode(),
route.isTurnBack() ? "Z" : "B"));
}
}
}
@ -678,7 +708,8 @@ public class CiRouteService {
}
MapConfig config = simulation.getRepository().getConfig();
if (!config.isRouteSettingNoFail()) {
if (simulation.getSystemTime().isAfter(overlap.getSettingStartTime().plusSeconds(SimulationConstants.ROUTE_SETTING_TIMEOUT))) {
if (simulation.getSystemTime().isAfter(
overlap.getSettingStartTime().plusSeconds(SimulationConstants.ROUTE_SETTING_TIMEOUT))) {
log.info(String.format("进路延续保护[%s]办理失败", overlap.debugStr()));
overlap.settingOver();
return;
@ -692,7 +723,8 @@ public class CiRouteService {
switchElement.getASwitch().overlapLock();
}
// 延续保护位置转动
boolean onPos = this.switchControlService.ensureSwitchPosCurrent(simulation, sectionPath.getSwitchList(), false);
boolean onPos = this.switchControlService.ensureSwitchPosCurrent(simulation,
sectionPath.getSwitchList(), false);
// 延续保护区段预先锁闭
if (onPos || config.isLockFirst()) {
this.checkAndLockOverlap(simulation, overlap);
@ -727,21 +759,6 @@ public class CiRouteService {
}
}
/**
* 设置自动进路模式
*
* @param route
*/
public void setFleet(Route route) {
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(route.isFlt(),
"不是自动进路,不能设置自动进路");
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(route.isCiControl(),
"进路联锁自动触发,不能设置自动进路");
if (!route.isFleetMode()) {
route.setFleetMode(true);
}
}
/**
* 取消自动进路
*
@ -753,29 +770,4 @@ public class CiRouteService {
}
}
/**
* 设置联锁自动触发
*
* @param route
*/
public void setCIAutoTrigger(Route route) {
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(route.isFleetMode(),
"进路处于自动进路模式中,不能设置联锁自动触发");
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(route.isArs(),
"进路不具有该功能,无法设置为联锁自动触发");
if (!route.isCiControl()) {
route.setCiControl(true);
}
}
/**
* 取消联锁自动触发
*
* @param route
*/
public void cancelCIAutoTrigger(Route route) {
if (route.isCiControl()) {
route.setCiControl(false);
}
}
}

View File

@ -19,14 +19,19 @@ import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain.Preselectio
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.stream.Collectors;
/**
* 指令执行
*/
@ -34,6 +39,7 @@ import java.util.stream.Collectors;
@Getter
@Setter
public class CommandBO {
private CommandType commandType;
private SimulationMember fromMember;
@ -44,7 +50,8 @@ public class CommandBO {
private List<Step> stepList;
public CommandBO(CommandType commandType, SimulationMember fromMember, SimulationMember targetMember,
public CommandBO(CommandType commandType, SimulationMember fromMember,
SimulationMember targetMember,
Map<String, Object> params, List<Step> stepList) {
this.commandType = commandType;
this.fromMember = fromMember;
@ -63,7 +70,8 @@ public class CommandBO {
}
public List<Step> getStepByType(Step.StepType stepType) {
return this.stepList.stream().filter(step -> step.getType().equals(stepType)).collect(Collectors.toList());
return this.stepList.stream().filter(step -> step.getType().equals(stepType))
.collect(Collectors.toList());
}
/**
@ -72,6 +80,7 @@ public class CommandBO {
@Getter
@Setter
public static class Step {
private StepType type;
private Operation.Type operationType;
@ -145,7 +154,8 @@ public class CommandBO {
*/
Drive_Ahead(Collections.emptyList(), SimulationMember.Type.DRIVER) {
@Override
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember, Map<String, Object> params) {
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember,
Map<String, Object> params) {
VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice();
SectionPosition headPosition = train.getHeadPosition();
Section section = headPosition.getSection();
@ -154,22 +164,26 @@ public class CommandBO {
List<Step> stepList = new ArrayList<>();
stepList.add(buildDriverForceChangeOperationStep(train.getGroupNumber(), 0));
if (section.isStandTrack()) { //如果列车的车头所在区段是站台轨
SectionPosition standStopPosition = new SectionPosition(section, section.getStopPointByDirection(right));
SectionPosition standStopPosition = new SectionPosition(section,
section.getStopPointByDirection(right));
if (train.isStopAtThePosition(standStopPosition)) { //列车已经停在站台停车点
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "列车已在站台轨停车点停车");
throw new SimulationException(SimulationExceptionType.Invalid_Operation,
"列车已在站台轨停车点停车");
} else if (standStopPosition.isAheadOf(headPosition, right)) { //站台停车点在列车车头前方
stepList.add(buildDriveStep(standStopPosition));
} else {
SectionPosition nextStopPosition = train.calculateNextStandStopPosition();
if (nextStopPosition == null) {
nextStopPosition = new SectionPosition(train.getTarget(), train.getTarget().getStopPointByDirection(right));
nextStopPosition = new SectionPosition(train.getTarget(),
train.getTarget().getStopPointByDirection(right));
}
stepList.add(buildDriveStep(nextStopPosition));
}
} else {
SectionPosition nextStopPosition = train.calculateNextStandStopPosition();
if (nextStopPosition == null && train.getTarget() != null) {
nextStopPosition = new SectionPosition(train.getTarget(), train.getTarget().getStopPointByDirection(right));
nextStopPosition = new SectionPosition(train.getTarget(),
train.getTarget().getStopPointByDirection(right));
}
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotNull(nextStopPosition,
train.debugStr() + "找不到下一个停车点");
@ -189,12 +203,15 @@ public class CommandBO {
if (!train.isInTheGear(Handwheel.MANUAL)) {
return buildGearChangeStep(train.getGroupNumber(), Handwheel.MANUAL);
}
if (!train.isStop())
if (!train.isStop()) {
return buildDriverForceChangeOperationStep(train.getGroupNumber(), -1);
if (!DriveMode.RM.equals(train.getDriveMode()) && !train.isNRMMode())
}
if (!DriveMode.RM.equals(train.getDriveMode()) && !train.isNRMMode()) {
return getStep4ChangePreselectionMode(train, PreselectionMode.RM);
if (train.isEB())
}
if (train.isEB()) {
return getStep4ReleaseEB(train);
}
return driveStep;
} else { //如果列车已经停到目标位置
// if (!DriveMode.AM.equals(train.getDriveMode()))
@ -210,7 +227,8 @@ public class CommandBO {
*/
Route_Block_Drive(Collections.emptyList(), SimulationMember.Type.DRIVER) {
@Override
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember, Map<String, Object> params) {
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember,
Map<String, Object> params) {
return Collections.emptyList();
}
@ -230,9 +248,11 @@ public class CommandBO {
/**
* 道岔钩锁
*/
Switch_Hook_Lock(Arrays.asList(ParamName.switchCode, ParamName.normal), SimulationMember.Type.STATION_SUPERVISOR) {
Switch_Hook_Lock(Arrays.asList(ParamName.switchCode, ParamName.normal),
SimulationMember.Type.STATION_SUPERVISOR) {
@Override
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember, Map<String, Object> params) {
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember,
Map<String, Object> params) {
if (!SimulationMember.Type.STATION_SUPERVISOR.equals(targetMember.getType())) {
throw new SimulationException(SimulationExceptionType.Member_Is_Not_Station_Supervisor);
}
@ -265,7 +285,8 @@ public class CommandBO {
*/
Drive_Through_The_Red_Light(Collections.emptyList(), SimulationMember.Type.DRIVER) {
@Override
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember, Map<String, Object> params) {
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember,
Map<String, Object> params) {
if (!SimulationMember.Type.DRIVER.equals(targetMember.getType())) {
throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver);
}
@ -273,7 +294,8 @@ public class CommandBO {
List<Step> stepList = new ArrayList<>();
VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice();
stepList.add(buildDriveStep(train.calculateStopPosition4CrossTheRedLight()));
stepList.add(buildCrossSignalStep(train.getHeadPosition().getSection().getSignalOf(train.isRight())));
stepList.add(buildCrossSignalStep(
train.getHeadPosition().getSection().getSignalOf(train.isRight())));
stepList.add(buildRmToBmStep());
return stepList;
@ -306,7 +328,8 @@ public class CommandBO {
*/
Drive_Through_The_Guide_Signal(Collections.emptyList(), SimulationMember.Type.DRIVER) {
@Override
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember, Map<String, Object> params) {
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember,
Map<String, Object> params) {
if (!SimulationMember.Type.DRIVER.equals(targetMember.getType())) {
throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver);
}
@ -314,7 +337,8 @@ public class CommandBO {
List<Step> stepList = new ArrayList<>();
VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice();
stepList.add(buildDriveStep(calculateStepPosition4CrossTheGuideSignal(train)));
stepList.add(buildCrossSignalStep(train.getHeadPosition().getSection().getSignalOf(train.isRight())));
stepList.add(buildCrossSignalStep(
train.getHeadPosition().getSection().getSignalOf(train.isRight())));
return stepList;
}
@ -344,7 +368,8 @@ public class CommandBO {
*/
Open_Or_Close_Door(Collections.emptyList(), SimulationMember.Type.DRIVER) {
@Override
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember, Map<String, Object> params) {
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember,
Map<String, Object> params) {
if (!SimulationMember.Type.DRIVER.equals(targetMember.getType())) {
throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver);
}
@ -352,7 +377,8 @@ public class CommandBO {
List<Step> stepList = new ArrayList<>();
VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice();
List<Stand> standList = train.getHeadPosition().getSection().getStandList();
if (!CollectionUtils.isEmpty(standList) && standList.size() == 1 && standList.get(0).isSmall()) {
if (!CollectionUtils.isEmpty(standList) && standList.size() == 1 && standList.get(0)
.isSmall()) {
// 小站台停车无需开关门
return null;
}
@ -384,7 +410,8 @@ public class CommandBO {
VirtualRealityTrain train = (VirtualRealityTrain) command.getTargetMember().getDevice();
List<Step> steps = command.getStepByType(Step.StepType.OPERATION);
Step step = steps.get(0);
VirtualRealityTrain.Door door = train.getDoorByDirection((boolean) step.getOperationParams().get("right"));
VirtualRealityTrain.Door door = train.getDoorByDirection(
(boolean) step.getOperationParams().get("right"));
if (!Objects.equals(door.isOpen(), step.getOperationParams().get("open"))) {
return step;
} else {
@ -400,14 +427,16 @@ public class CommandBO {
*/
Set_Speed_Limit(List.of(ParamName.speedLimit), SimulationMember.Type.DRIVER) {
@Override
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember, Map<String, Object> params) {
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember,
Map<String, Object> params) {
return Collections.emptyList();
}
@Override
public Step execute(Simulation simulation, CommandBO command) {
VirtualRealityTrain train = (VirtualRealityTrain) command.getTargetMember().getDevice();
float speedLimit = Float.parseFloat((String) command.getParams().get(ParamName.speedLimit.name()));
float speedLimit = Float.parseFloat(
(String) command.getParams().get(ParamName.speedLimit.name()));
if (speedLimit < 0) {
train.setSpeedLimit(Float.MAX_VALUE);
} else {
@ -423,8 +452,10 @@ public class CommandBO {
*/
Turn_Direction(List.of(), SimulationMember.Type.DRIVER) {
@Override
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember, Map<String, Object> params) {
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertEquals(SimulationMember.Type.DRIVER, targetMember.getType());
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember,
Map<String, Object> params) {
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertEquals(SimulationMember.Type.DRIVER,
targetMember.getType());
VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice();
params.put(ParamName.trainRight.name(), !train.isRight());
return new ArrayList<>();
@ -448,7 +479,8 @@ public class CommandBO {
*/
Drive_To(List.of(ParamName.sectionCode), SimulationMember.Type.DRIVER) {
@Override
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember, Map<String, Object> params) {
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember,
Map<String, Object> params) {
return List.of();
}
@ -458,7 +490,8 @@ public class CommandBO {
VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice();
String sectionCode = (String) command.getParams().get(ParamName.sectionCode.name());
Section section = simulation.getRepository().getByCode(sectionCode, Section.class);
SectionPosition targetPosition = new SectionPosition(section, section.getStopPointByDirection(train.isRight()));
SectionPosition targetPosition = new SectionPosition(section,
section.getStopPointByDirection(train.isRight()));
if (train.isStopAtThePosition(targetPosition)) {
targetMember.setCommand(null);
return null;
@ -473,7 +506,8 @@ public class CommandBO {
*/
Inbound(List.of(), SimulationMember.Type.DRIVER) {
@Override
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember, Map<String, Object> params) {
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember,
Map<String, Object> params) {
return List.of();
}
@ -500,7 +534,8 @@ public class CommandBO {
*/
Change_Preselection_Mode(List.of(ParamName.preselectionMode), SimulationMember.Type.DRIVER) {
@Override
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember, Map<String, Object> params) {
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember,
Map<String, Object> params) {
return Collections.emptyList();
}
@ -515,11 +550,12 @@ public class CommandBO {
return getStep4ReleaseEB(train);
}
PreselectionMode preselectionMode =
PreselectionMode.valueOf((String) command.getParams().get(ParamName.preselectionMode.name()));
PreselectionMode.valueOf(
(String) command.getParams().get(ParamName.preselectionMode.name()));
PreselectionMode trainMode = train.getPreselectionMode();
if (trainMode != preselectionMode) { //预选级别不对
return getStep4ChangePreselectionMode(train, preselectionMode);
} else if (trainMode.isMatchTheDriveMode(DriveMode.AM) && !train.isAMMode()) {
} else if (trainMode.isNotLowerThanTheDriveMode(DriveMode.AM) && !train.isAMMode()) {
return getStep4OpenATO(train);
} else {
driver.setCommand(null);
@ -533,7 +569,8 @@ public class CommandBO {
*/
Apply_NRM(List.of(), SimulationMember.Type.DRIVER) {
@Override
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember, Map<String, Object> params) {
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember,
Map<String, Object> params) {
return Collections.emptyList();
}
@ -554,14 +591,16 @@ public class CommandBO {
**/
Depart_Train(List.of(), SimulationMember.Type.DRIVER) {
@Override
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember, Map<String, Object> params) {
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember,
Map<String, Object> params) {
VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice();
boolean isRight = train.isRight(); // 列车运行方向
Section section = train.getHeadPosition().getSection(); // 列车车头所在区段
Section targetSection = getTargetSection(isRight, section);
List<Step> stepList = new ArrayList<>();
if (targetSection != null) {
SectionPosition targetPosition = new SectionPosition(targetSection, targetSection.getStopPointByDirection(isRight));
SectionPosition targetPosition = new SectionPosition(targetSection,
targetSection.getStopPointByDirection(isRight));
// 设置目标位置
stepList.add(buildDriveStep(targetPosition));
}
@ -571,7 +610,8 @@ public class CommandBO {
@Override
public Step execute(Simulation simulation, CommandBO command) {
VirtualRealityTrain train = (VirtualRealityTrain) command.getTargetMember().getDevice();
boolean isOnline = simulation.getRepository().getUsedTrainMap().containsKey(train.getGroupNumber());
boolean isOnline = simulation.getRepository().getUsedTrainMap()
.containsKey(train.getGroupNumber());
if (!isOnline) {
command.getTargetMember().setCommand(null);
return null;
@ -585,7 +625,8 @@ public class CommandBO {
if (Objects.equals(section, targetSection)) {
command.getTargetMember().setCommand(null);
} else {
SectionPosition targetPosition = new SectionPosition(targetSection, targetSection.getStopPointByDirection(isRight));
SectionPosition targetPosition = new SectionPosition(targetSection,
targetSection.getStopPointByDirection(isRight));
driveStep.setTargetPosition(targetPosition);
return driveStep;
}
@ -610,7 +651,8 @@ public class CommandBO {
*/
Parking_Train(List.of(), SimulationMember.Type.DRIVER) {
@Override
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember, Map<String, Object> params) {
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember,
Map<String, Object> params) {
return Collections.emptyList();
}
@ -618,7 +660,8 @@ public class CommandBO {
public Step execute(Simulation simulation, CommandBO command) {
SimulationMember targetMember = command.getTargetMember();
VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice();
boolean isOnline = simulation.getRepository().getUsedTrainMap().containsKey(train.getGroupNumber());
boolean isOnline = simulation.getRepository().getUsedTrainMap()
.containsKey(train.getGroupNumber());
if (!isOnline) {
command.getTargetMember().setCommand(null);
return null;
@ -671,7 +714,8 @@ public class CommandBO {
/**
* 构架指令步骤列表
*/
public abstract List<Step> buildStepList(Simulation simulation, SimulationMember targetMember, Map<String, Object> params);
public abstract List<Step> buildStepList(Simulation simulation, SimulationMember targetMember,
Map<String, Object> params);
/**
* 执行指令返回无法直接完成的指令
@ -679,7 +723,6 @@ public class CommandBO {
public abstract Step execute(Simulation simulation, CommandBO command);
/**
* 构建开启ATO操作步骤
*/
@ -798,13 +841,15 @@ public class CommandBO {
Section section = headPosition.getSection();
Signal trainHeadSignal = section.getSignalOf(right);
if (trainHeadSignal == null || !trainHeadSignal.isGuideAspect()) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "指令要求:列车车头所在区段有同向信号机并且开放引导信号");
throw new SimulationException(SimulationExceptionType.Invalid_Operation,
"指令要求:列车车头所在区段有同向信号机并且开放引导信号");
}
SectionPosition sectionPosition = null;
for (int i = 0; i < 30; i++) {
section = section.findNextRunningSectionBaseRealSwitch(right);
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotNull(section, "引导信号前方未找到停车位置");
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotNull(section,
"引导信号前方未找到停车位置");
Signal signal = section.getSignalOf(right);
if (section.isStandTrack() || section.isTurnBackTrack()) {
sectionPosition = new SectionPosition(section, section.getStopPointByDirection(right));
@ -815,7 +860,8 @@ public class CommandBO {
}
}
if (sectionPosition == null) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "引导信号前方未找到停车位置");
throw new SimulationException(SimulationExceptionType.Invalid_Operation,
"引导信号前方未找到停车位置");
}
return sectionPosition;
}
@ -946,7 +992,8 @@ public class CommandBO {
return step;
}
public static Step getStep4ChangePreselectionMode(VirtualRealityTrain train, PreselectionMode preselectionMode) {
public static Step getStep4ChangePreselectionMode(VirtualRealityTrain train,
PreselectionMode preselectionMode) {
PreselectionMode trainMode = train.getPreselectionMode();
PreselectionMode tempMode = train.getTempPreselectionMode();
String groupNumber = train.getGroupNumber();

View File

@ -6,7 +6,11 @@ import club.joylink.rtss.simulation.cbtc.constant.RunLevel;
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
import club.joylink.rtss.simulation.cbtc.constant.TrainTBControl;
import club.joylink.rtss.simulation.cbtc.data.CalculateService;
import club.joylink.rtss.simulation.cbtc.data.map.*;
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
import club.joylink.rtss.simulation.cbtc.data.map.Section;
import club.joylink.rtss.simulation.cbtc.data.map.Signal;
import club.joylink.rtss.simulation.cbtc.data.map.Stand;
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.SectionPosition;
@ -14,15 +18,14 @@ import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
import club.joylink.rtss.vo.client.operation.DriveParamVO;
import club.joylink.rtss.vo.ws.TrainPosition;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
/**
* 虚拟真实列车
@ -351,9 +354,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
private DoorSelection doorSelection;
/**
* 牵引力,单位kN
* 公式 fk = 350 (0 <= v <= 36km/h)
* fk = 12900 / v (36 < v < 80km/h)
* 牵引力,单位kN 公式 fk = 350 (0 <= v <= 36km/h) fk = 12900 / v (36 < v < 80km/h)
*/
private float fk;
@ -446,7 +447,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
private final LinkedHashSet<ConfirmationMessage> confirmationMessages = new LinkedHashSet<>();
/**
* ato可以开启
* ato可以开启此状态仅用以前端显示因为此状态更新不及时使用起来比较麻烦
*/
private boolean atoCanOpen;
@ -465,7 +466,8 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
* @param railway 是大铁线路如果是将最高速度改为320km/h
* @param manualTrainDefaultStop
*/
public VirtualRealityTrain(String code, String groupNumber, boolean railway, boolean manualTrainDefaultStop) {
public VirtualRealityTrain(String code, String groupNumber, boolean railway,
boolean manualTrainDefaultStop) {
super(code, groupNumber, DeviceType.TRAIN);
this.groupNumber = groupNumber;
this.gear = Handwheel.ATO;
@ -489,8 +491,10 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
}
public void setCommunication(boolean communication) {
if ((Fault.COMMUNICATION_ABNORMAL.equals(this.fault) || !atpOn || this.noCommunicateDevice) && communication)
if ((Fault.COMMUNICATION_ABNORMAL.equals(this.fault) || !atpOn || this.noCommunicateDevice)
&& communication) {
return;
}
this.communication = communication;
}
@ -674,6 +678,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
this.initPosition(right, headPosition);
init();
}
public void initManualTrain(SectionPosition headPosition, boolean right, TrainPosition tp) {
this.initPosition(right, headPosition);
init();
@ -681,6 +686,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
this.locationKM = tp.getLocation();
this.right = tp.isRight();
}
private void init() {
this.communication = true;
this.jump = false;
@ -709,7 +715,8 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
// }
}
public synchronized void updateNextStationPlan(Station nextStation, Section targetSection, boolean nextParking) {
public synchronized void updateNextStationPlan(Station nextStation, Section targetSection,
boolean nextParking) {
this.nextStation = nextStation;
// this.setTarget(targetSection);
this.nextParking = nextParking;
@ -745,8 +752,9 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
}
public void updateTBForce(float fk, float fb) {
if (isEB())
if (isEB()) {
return;
}
if (Fault.DRIVE_FAULT.equals(fault) && fk > 0) {
return;
}
@ -804,7 +812,8 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
}
public SectionPosition calculateTailPosition() {
this.tailPosition = CalculateService.calculateNextPositionByStartAndLen(this.headPosition, !right, this.getLen(), true);
this.tailPosition = CalculateService.calculateNextPositionByStartAndLen(this.headPosition,
!right, this.getLen(), true);
return this.tailPosition;
}
@ -862,6 +871,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
/**
* 获取列车后方的车站停车位置
*
* @return
*/
public SectionPosition calculateBackStandStopPosition() {
@ -880,6 +890,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
}
return null;
}
/**
* 计算列车前方下一个站台的停车位置
*/
@ -908,7 +919,8 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
Section section = this.headPosition.getSection();
Signal signal = section.getSignalOf(right);
if (signal == null || !signal.isDefaultAspect()) { //没有同向信号机或信号机不处于信号关闭状态
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "指令要求:列车车头所在区段有同向信号机并且信号关闭");
throw new SimulationException(SimulationExceptionType.Invalid_Operation,
"指令要求:列车车头所在区段有同向信号机并且信号关闭");
}
for (int i = 0; i < 30; i++) {
@ -1014,11 +1026,13 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
}
public boolean isStandReadyStart() {
return Objects.nonNull(this.standParkedTrainActivity) && StandParkedTrainActivity.START.equals(this.standParkedTrainActivity);
return Objects.nonNull(this.standParkedTrainActivity) && StandParkedTrainActivity.START.equals(
this.standParkedTrainActivity);
}
public boolean isStandBoarding() {
return Objects.nonNull(this.standParkedTrainActivity) && StandParkedTrainActivity.BOARD.equals(this.standParkedTrainActivity);
return Objects.nonNull(this.standParkedTrainActivity) && StandParkedTrainActivity.BOARD.equals(
this.standParkedTrainActivity);
}
public synchronized void nextParkedTrainActivity() {
@ -1050,8 +1064,9 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
}
public boolean isInTheStandArea() {
if (this.getHeadPosition() == null)
if (this.getHeadPosition() == null) {
return false;
}
return this.getHeadPosition().getSection().isNormalStandTrack()
|| this.calculateTailPosition().getSection().isNormalStandTrack();
}
@ -1081,7 +1096,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
* 在AM级预选模式下
*/
public boolean isInAMPreselectionMode() {
return preselectionMode.isMatchTheDriveMode(DriveMode.AM);
return preselectionMode.isNotLowerThanTheDriveMode(DriveMode.AM);
}
public void addMessage(ConfirmationMessage message) {
@ -1128,12 +1143,16 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
return getAtoSpeed() * 3.6 < 20;
}
/** 操纵杆是否在惰行位 */
/**
* 操纵杆是否在惰行位
*/
public boolean isLeverInCoastingGear() {
return leverPosition == 0;
}
/** 是否不在牵引位 */
/**
* 是否不在牵引位
*/
public boolean isLeverNotInTractionGear() {
return leverPosition <= 0;
}
@ -1260,9 +1279,13 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
* 道岔支持的操作
*/
public enum Operation {
/** 开门 */
/**
* 开门
*/
K,
/** 关门 */
/**
* 关门
*/
G,
}
@ -1352,7 +1375,9 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
}
},
/** 驾驶异常 */
/**
* 驾驶异常
*/
DRIVE_FAULT {
@Override
public boolean apply(MapElement device) {
@ -1364,10 +1389,15 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
return false;
}
},
/** 列车脱线 */
/**
* 列车脱线
*/
OFF_LINE {},
/** 突然EB */
SUDDEN_EB{},;
/**
* 突然EB
*/
SUDDEN_EB {},
;
public boolean apply(MapElement device) {
VirtualRealityTrain train = (VirtualRealityTrain) device;
@ -1377,6 +1407,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
train.setFault(this);
return true;
}
/**
* 取消故障
*/
@ -1495,9 +1526,13 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
}
},
;
/** 所允许的最高驾驶模式 */
/**
* 所允许的最高驾驶模式
*/
private DriveMode driveMode;
/** 所允许的最高运行级别 */
/**
* 所允许的最高运行级别
*/
private RunLevel runLevel;
PreselectionMode(DriveMode driveMode, RunLevel runLevel) {
@ -1508,19 +1543,23 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
public abstract PreselectionMode findNext(boolean up);
/**
* 该预选模式与该驾驶模式匹配即允许升到该模式
* 该预选模式的驾驶模式不低于指定的驾驶模式
*/
public boolean isMatchTheDriveMode(DriveMode driveMode) {
public boolean isNotLowerThanTheDriveMode(DriveMode driveMode) {
return this.driveMode.isNotLowerThan(driveMode);
}
/**
* 该预选模式与该运行级别匹配
* 该预选模式的运行级别不低于指定级别
*/
public boolean isMatchTheRunLevel(RunLevel runLevel) {
public boolean isNotLowerThanTheRunLevel(RunLevel runLevel) {
return this.runLevel.isNotLowerThan(runLevel);
}
public boolean isMatchTheRunLevel(RunLevel runLevel) {
return this.runLevel == runLevel;
}
/**
* 是否比该模式级别更高
*/

View File

@ -26,15 +26,14 @@ 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.service.ATOService;
import club.joylink.rtss.simulation.cbtc.robot.SimulationRobotService;
import java.util.List;
import java.util.Objects;
import lombok.NonNull;
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;
/**
* 自动保护系统服务
*/
@ -82,7 +81,8 @@ public class ATPService {
train.getServiceNumber(), train.getTripNumber(), train.getDestinationCode(),
ma.getEnd(), ma.getEnd().getEndPosition().toString(), protectDistance));
// 重新生成速度曲线
SpeedCurve speedCurve = SpeedCurve.generateProtectSpeedCurve(protectDistance, train.getAtpSpeedMax()); //未考虑区段限速
SpeedCurve speedCurve = SpeedCurve.generateProtectSpeedCurve(protectDistance,
train.getAtpSpeedMax()); //未考虑区段限速
// SpeedCurve speedCurve = SpeedCurve.generateProtectSpeedCurve(train); //考虑区段限速
log.debug(String.format("列车[%s-%s|%s|%s]重新生成防护速度曲线[%s]",
train.getGroupNumber(),
@ -132,7 +132,8 @@ public class ATPService {
case AM:
case CM:
if (train.getSpeed() > train.getAtpSpeed()) {
log.warn(String.format("系统时间:[%s],列车[%s]超速EB。驾驶模式:[%s], 移动授权:[%s], 速度:[%s],防护速度:[%s]",
log.warn(String.format(
"系统时间:[%s],列车[%s]超速EB。驾驶模式:[%s], 移动授权:[%s], 速度:[%s],防护速度:[%s]",
simulation.getCorrectSystemTime(),
train.getGroupNumber(), train.getDriveMode(),
train.getMa2() != null ? train.getMa2().debugStr() : '无',
@ -304,10 +305,14 @@ public class ATPService {
}
}
public void openOrCloseDoor(Simulation simulation, VirtualRealityTrain train, boolean right, boolean open) {
BusinessExceptionAssertEnum.OPERATION_FAIL.assertTrue(train.getSpeed() == 0, String.format("列车[%s]未停止,不能操作车门", train.getGroupNumber()));
BusinessExceptionAssertEnum.OPERATION_FAIL.assertTrue(train.getDoorMode().isManual(open), String.format("列车[%s]门模式自动,不能操作车门", train.getGroupNumber()));
BusinessExceptionAssertEnum.OPERATION_FAIL.assertTrue(train.getDoorSelection().match(right),String.format("列车[%s]门选择与操作不匹配", train.getGroupNumber()));
public void openOrCloseDoor(Simulation simulation, VirtualRealityTrain train, boolean right,
boolean open) {
BusinessExceptionAssertEnum.OPERATION_FAIL.assertTrue(train.getSpeed() == 0,
String.format("列车[%s]未停止,不能操作车门", train.getGroupNumber()));
BusinessExceptionAssertEnum.OPERATION_FAIL.assertTrue(train.getDoorMode().isManual(open),
String.format("列车[%s]门模式自动,不能操作车门", train.getGroupNumber()));
BusinessExceptionAssertEnum.OPERATION_FAIL.assertTrue(train.getDoorSelection().match(right),
String.format("列车[%s]门选择与操作不匹配", train.getGroupNumber()));
List<Stand> standList = train.getHeadPosition().getSection().getStandList();
VirtualRealityTrain.Door door = train.getDoorByDirection(right);
if (open) {
@ -317,7 +322,8 @@ public class ATPService {
}
if (train.isCommunicable()) {
for (Stand stand : standList) {
this.ciApiService.openScreenDoor(simulation, stand.getCode(), CiStandService.PsdCommandSource.SIG);
this.ciApiService.openScreenDoor(simulation, stand.getCode(),
CiStandService.PsdCommandSource.SIG);
}
}
} else {
@ -327,7 +333,8 @@ public class ATPService {
}
if (train.isCommunicable()) {
for (Stand stand : standList) {
this.ciApiService.closeScreenDoor(simulation, stand.getCode(), CiStandService.PsdCommandSource.SIG);
this.ciApiService.closeScreenDoor(simulation, stand.getCode(),
CiStandService.PsdCommandSource.SIG);
}
}
}
@ -350,7 +357,7 @@ public class ATPService {
* 开启ATO
*/
public void openATO(VirtualRealityTrain train) {
if (train.isAtoCanOpen()) {
if (canOpenATO(train)) {
train.setAtoOn(true);
train.setDriveMode(DriveMode.AM);
}
@ -374,19 +381,29 @@ public class ATPService {
*/
public boolean canOpenATO(VirtualRealityTrain train) {
if (train.isAtoOn()) //ATO已经开启
{
return false;
}
if (!train.isInAMPreselectionMode()) //不在AM-预选模式
{
return false;
}
if (!VirtualRealityTrain.Handwheel.ATO.equals(train.getGear())) //工况手轮不在ATO位
{
return false;
}
// if (!train.isLeverInCoastingGear()) //操纵杆不在惰行位
// return false;
// if (train.getAtoSpeed() <= 0) //列车无推荐速度
// return false;
if (!train.isITC() && !train.isCBTC()) //非ITCCTC运行级别
{
return false;
}
if (!train.isAtpOn()) //列车ATP未启用
{
return false;
}
// if (train.isEB())
// return false;
// if (train.isITC() && !train.isReleased()
@ -418,13 +435,15 @@ public class ATPService {
}
}
public void confirmMessage(VirtualRealityTrain train, VirtualRealityTrain.ConfirmationMessage message) {
public void confirmMessage(VirtualRealityTrain train,
VirtualRealityTrain.ConfirmationMessage message) {
if (train.containsMessage(message)) {
handleConfirmMessage(train, message);
}
}
private void handleConfirmMessage(VirtualRealityTrain train, VirtualRealityTrain.ConfirmationMessage message) {
private void handleConfirmMessage(VirtualRealityTrain train,
VirtualRealityTrain.ConfirmationMessage message) {
switch (message) {
case Exit_TGMT:
break;
@ -438,7 +457,8 @@ public class ATPService {
case Switch_To_RM:
break;
default:
throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception(String.format("未知的消息类型:%s", message));
throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception(
String.format("未知的消息类型:%s", message));
}
train.removeMessage(message);
}
@ -449,15 +469,16 @@ public class ATPService {
public void updateRunLevel(VirtualRealityTrain train, @NonNull RunLevel runLevel,
PreselectionMode preselectionMode) {
if (!preselectionMode.isMatchTheRunLevel(runLevel)) {
if (!preselectionMode.isNotLowerThanTheRunLevel(runLevel)) {
return;
}
switch (runLevel) {
case CBTC:
case ITC:
MaService.Ma ma = train.getMa2();
if (ma == null)
if (ma == null) {
return;
}
SpeedCurve ebTriggerCurve = ma.getEbTriggerCurve();
float ebTriggerRemain = ma.calculateDistanceOfEbTriggerEnd();
ma.setEbTriggerCurve(ebTriggerCurve);
@ -484,15 +505,18 @@ public class ATPService {
updateDriveMode(train, driveMode, train.getPreselectionMode());
}
private void updateDriveMode(VirtualRealityTrain train, DriveMode driveMode, PreselectionMode preselectionMode) {
if (driveMode.equals(train.getDriveMode()))
private void updateDriveMode(VirtualRealityTrain train, DriveMode driveMode,
PreselectionMode preselectionMode) {
if (driveMode.equals(train.getDriveMode())) {
return;
if (preselectionMode.isMatchTheDriveMode(driveMode)) {
}
if (preselectionMode.isNotLowerThanTheDriveMode(driveMode)) {
train.setDriveMode(driveMode);
if (!train.isAMMode())
if (!train.isAMMode()) {
closeATO(train);
}
}
}
/**
* 开关门
@ -500,7 +524,8 @@ public class ATPService {
public void openOrCloseDoor(Simulation simulation, String groupNumber) {
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
List<Stand> standList = train.getHeadPosition().getSection().getStandList();
if (!CollectionUtils.isEmpty(standList) && standList.size() == 1 && standList.get(0).isSmall()) {
if (!CollectionUtils.isEmpty(standList) && standList.size() == 1 && standList.get(0)
.isSmall()) {
// 小站台停车无需开关门
return;
}
@ -556,7 +581,8 @@ public class ATPService {
SimulationDataRepository repository = simulation.getRepository();
TrainInfo trainInfo = repository.getSupervisedTrainByGroup(train.getGroupNumber());
List<RoutePath> routePathList = repository.queryRoutePathsByEnd(headSection);
if (routePathList.stream().anyMatch(routePath -> routePath.isRight() == trainInfo.getRight())) { //准备回库
if (routePathList.stream()
.anyMatch(routePath -> routePath.isRight() == trainInfo.getRight())) { //准备回库
trainInfo.finishPlanPrepareInbound();
}
}
@ -565,7 +591,8 @@ public class ATPService {
/**
* 修改预选模式
*/
public void changePreselectionMode(Simulation simulation, String groupNumber, VirtualRealityTrain.PreselectionMode preselectionMode) {
public void changePreselectionMode(Simulation simulation, String groupNumber,
VirtualRealityTrain.PreselectionMode preselectionMode) {
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
if (preselectionMode == train.getPreselectionMode()) {
return;
@ -573,31 +600,34 @@ public class ATPService {
if (!train.isAtpOn()) {
this.openAtp(train);
}
if ((train.isSignalEB() || preselectionMode.isMatchTheDriveMode(DriveMode.RM) )
&& !train.isInTheGear(VirtualRealityTrain.Handwheel.MANUAL)) { //确保当前在手动档位
changeGear(train, VirtualRealityTrain.Handwheel.MANUAL);
}
if (train.isSignalEB()) {
if (!train.isStop() || !train.isLeverNotInTractionGear()) {
changeTrainForce(train, -2F); // 改变列车的牵引/
}
if (!train.isRMMode()) {
train.setTempPreselectionMode(PreselectionMode.RM);
train.setPreselectionMode(PreselectionMode.RM);
}
}
// 对预选模式条件卡控
if (preselectionMode.isMatchTheDriveMode(DriveMode.AM) && !train.isAMMode()) {
if (!train.isInTheGear(VirtualRealityTrain.Handwheel.ATO)) {
changeGear(train, VirtualRealityTrain.Handwheel.ATO);
}
if (!train.isLeverInCoastingGear()) {
changeTrainForce(train, 0f); // 改变列车的牵引/
}
}
train.setTempPreselectionMode(preselectionMode);
train.setPreselectionMode(preselectionMode);
handlePreselectionMode(simulation, train);
train.setTempPreselectionMode(preselectionMode);
// 不需要下面的逻辑转了预选模式剩下的事机器人会做
// if ((train.isSignalEB() || preselectionMode.isNotLowerThanTheDriveMode(DriveMode.RM) )
// && !train.isInTheGear(VirtualRealityTrain.Handwheel.MANUAL)) { //确保当前在手动档位
// changeGear(train, VirtualRealityTrain.Handwheel.MANUAL);
// }
// if (train.isSignalEB()) {
// if (!train.isStop() || !train.isLeverNotInTractionGear()) {
// changeTrainForce(train, -2F); // 改变列车的牵引/
// }
// if (!train.isRMMode()) {
// train.setTempPreselectionMode(PreselectionMode.RM);
// train.setPreselectionMode(PreselectionMode.RM);
// }
// }
// // 对预选模式条件卡控
// if (preselectionMode.isNotLowerThanTheDriveMode(DriveMode.AM) && !train.isAMMode()) {
// if (!train.isInTheGear(VirtualRealityTrain.Handwheel.ATO)) {
// changeGear(train, VirtualRealityTrain.Handwheel.ATO);
// }
// if (!train.isLeverInCoastingGear()) {
// changeTrainForce(train, 0f); // 改变列车的牵引/
// }
// }
// train.setTempPreselectionMode(preselectionMode);
// train.setPreselectionMode(preselectionMode);
// handlePreselectionMode(simulation, train);
}
/**
@ -640,30 +670,9 @@ public class ATPService {
train.leaverUpdateTBForce(0, 350);
} else {
throw new SimulationException(SimulationExceptionType.Illegal_Argument,
String.format("数值[%s]超限,列车牵引/制动力可调整比例范围应该在[-1, 1]之间,或为快速制动-2", percent));
}
}
/**
* 打开ato
*/
public void openAto(Simulation simulation, String groupNumber) {
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
if (train.isAtoOn()) { //ATO已经开启
return;
}
if (!train.isAtpOn()) { // 列车ATP未启用
this.openAtp(train);
}
if (!VirtualRealityTrain.Handwheel.ATO.equals(train.getGear())) { //工况手轮不在ATO位
changeGear(train, VirtualRealityTrain.Handwheel.ATO);
}
if (!train.isInAMPreselectionMode()) { //不在AM-预选模式
changePreselectionMode(simulation, groupNumber, PreselectionMode.AM_C);
}
if (!train.isAtoOn()) {
train.setAtoOn(true);
train.setDriveMode(DriveMode.AM);
String.format(
"数值[%s]超限,列车牵引/制动力可调整比例范围应该在[-1, 1]之间,或为快速制动-2",
percent));
}
}
@ -672,11 +681,13 @@ public class ATPService {
.filter(simulationMember -> simulationMember.isDriver()
&& train.getCode().equals(simulationMember.getDevice().getCode()))
.anyMatch(SimulationMember::isRobot);
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(!driverRobot,"成员由用户扮演,操作不执行");
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(!driverRobot,
"成员由用户扮演,操作不执行");
}
/**
* 处理预处理模式
*
* @param simulation 仿真
* @param train 列车
*/
@ -685,12 +696,14 @@ public class ATPService {
MapConfig config = simulation.getRepository().getConfig();
switch (preselectionMode) {
case AM_C:
if (!train.isCBTC() && config.getRunMode().isNotLowerThan(RunLevel.CBTC))
if (!train.isCBTC() && config.getRunMode().isNotLowerThan(RunLevel.CBTC)) {
train.setCommunication(true);
}
break;
case SM_C:
if (!train.isCBTC() && config.getRunMode().isNotLowerThan(RunLevel.CBTC))
if (!train.isCBTC() && config.getRunMode().isNotLowerThan(RunLevel.CBTC)) {
train.setCommunication(true);
}
closeATO(train);
break;
case AM_I:
@ -708,9 +721,10 @@ public class ATPService {
/**
* 更新列车运行级别
*/
private void updateRunLevel(Simulation simulation, VirtualRealityTrain train, VirtualRealityTrain.PreselectionMode preselectionMode) {
private void updateRunLevel(Simulation simulation, VirtualRealityTrain train,
VirtualRealityTrain.PreselectionMode preselectionMode) {
//如果当前级别高于预选降至IL
if (!preselectionMode.isMatchTheRunLevel(train.getRunLevel())) {
if (!preselectionMode.isNotLowerThanTheRunLevel(train.getRunLevel())) {
updateRunLevel(train, RunLevel.IL, preselectionMode);
}
@ -727,7 +741,8 @@ public class ATPService {
if (train.isCBTC() && train.isCbtcMaMiss()) { //CBTC列车的移动授权丢失
updateRunLevel(train, RunLevel.IL, preselectionMode);
triggerSignalEB(train);
} else if (!train.isCBTC() && !train.isCbtcMaMiss() && defaultRunLevel.equals(RunLevel.CBTC)) {
} else if (!train.isCBTC() && !train.isCbtcMaMiss() && defaultRunLevel.equals(
RunLevel.CBTC)) {
updateRunLevel(train, RunLevel.CBTC, preselectionMode);
}
}

View File

@ -1,5 +1,7 @@
package club.joylink.rtss.simulation.cbtc.robot;
import static club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain.ConfirmationMessage.Confirm_Release_Speed;
import club.joylink.rtss.services.psl.IVirtualRealityPslService;
import club.joylink.rtss.simulation.cbtc.ATP.ground.MaService;
import club.joylink.rtss.simulation.cbtc.ATS.operation.AtsOperationDispatcher;
@ -10,32 +12,46 @@ 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.DriveMode;
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.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.PSD;
import club.joylink.rtss.simulation.cbtc.data.map.Section;
import club.joylink.rtss.simulation.cbtc.data.map.Signal;
import club.joylink.rtss.simulation.cbtc.data.map.Stand;
import club.joylink.rtss.simulation.cbtc.data.map.Station;
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.data.vr.StandParkedTrainActivity;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityPsl;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityScreenDoor;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySignal;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
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.service.ATOService;
import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPService;
import club.joylink.rtss.simulation.cbtc.training2.Training2;
import club.joylink.rtss.vo.client.operation.DriveParamVO;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.*;
import java.util.stream.Collectors;
import static club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain.ConfirmationMessage.Confirm_Release_Speed;
/**
* 仿真机器人逻辑循环
*/
@ -94,9 +110,7 @@ public class SimulationRobotService {
}
break;
case START:
if (train.isAtoCanOpen()) {
atpService.openATO(train);
}
break;
}
}
@ -158,30 +172,32 @@ public class SimulationRobotService {
List<SimulationMember> drivers = simulation.querySimulationMembersOfRole(
SimulationMember.Type.DRIVER);
for (SimulationMember driver : drivers) {
// if (!driver.isRobot())
// continue;
SimulationDataRepository repository = simulation.getRepository();
VirtualRealityTrain train = (VirtualRealityTrain) driver.getDevice();
if (train.isTakeOver() || !repository.isVrTrainOnline(train.getGroupNumber())) { //如果列车被接管或不在线
continue;
}
//判断是否需要转换手轮档位到ATO
robotOpenATOAfterCheck(train);
//准备发车
robotReadyForDeparture(simulation, train);
//机器人驾驶
//机器人人工驾驶
robotManualDrive(simulation, driver, train);
}
}
private void robotManualDrive(Simulation simulation, SimulationMember driver,
VirtualRealityTrain train) {
if (train.isRobotNeedStop()) {
if (train.isStop()) {
train.getRobotDriveParam().setStop(false);
} else {
if (!train.isInTheGear(VirtualRealityTrain.Handwheel.MANUAL)) { //确保当前在手动档位
CommandBO.Step step = CommandBO.buildGearChangeStep(train.getGroupNumber(),
VirtualRealityTrain.Handwheel.MANUAL);
atsOperationDispatcher.execute(simulation, driver, step.getOperationType().name(),
step.getOperationParams());
}
ensureTrainInTheGear(train, VirtualRealityTrain.Handwheel.MANUAL);
doBreakMax(simulation, train);
}
} else if (train.isRobotNeedRun()) {
if ((train.isRMMode() || train.isNRMMode())) { //RM或NRM
ensureTrainInTheGear(train, VirtualRealityTrain.Handwheel.MANUAL);
VirtualRealityTrain linkTrain = train.getLinkTrain();
if (linkTrain == null) {
Optional<SectionPosition> targetPositionOptional = calculateTargetPosition(simulation,
@ -191,11 +207,40 @@ public class SimulationRobotService {
robotDrive(simulation, driver, train, train.getRobotTargetPosition());
}
} else if (train.isCMMode()) { //CM
ensureTrainInTheGear(train, VirtualRealityTrain.Handwheel.MANUAL);
SpeedCurve speedCurve = train.getMa2().getAtoStopCurve();
atoService.doControlBySpeedCurve(train, speedCurve, speedCurve.getTotalDistance(), train.getAtoSpeed());
atoService.doControlBySpeedCurve(train, speedCurve, speedCurve.getTotalDistance(),
train.getAtoSpeed());
}
}
}
/**
* 在检查通过后开启ATO
*/
private void robotOpenATOAfterCheck(VirtualRealityTrain train) {
//停站时的情况可能比较特殊保险起见停站时不做处理
if (train.isParkingAt()) {
return;
}
//列车的预选模式支持到达AM驾驶模式并且列车的ATO推荐速度大于0
if (train.getPreselectionMode().isNotLowerThanTheDriveMode(DriveMode.AM)
&& train.getAtoSpeed() > 0) {
ensureTrainInTheGear(train, VirtualRealityTrain.Handwheel.ATO);
atpService.openATO(train);
}
}
/**
* 确保列车在指定挡
*/
private void ensureTrainInTheGear(VirtualRealityTrain train, VirtualRealityTrain.Handwheel gear) {
if (!train.isInTheGear(gear)) {
train.setGear(gear);
// CommandBO.Step step = CommandBO.buildGearChangeStep(train.getGroupNumber(), gear);
// atsOperationDispatcher.execute(simulation, driver, step.getOperationType().name(),
// step.getOperationParams()); 机器人驾驶逻辑中有很多操作都不是通过仿真操作执行的所以这里也不需要了吧
}
}
/**
@ -245,7 +290,8 @@ public class SimulationRobotService {
SignalAspect throughAspect = robotDriveParam.getThroughSignalAspect();
Section section = headPosition.getSection();
if (throughSignal != null && !Objects.equals(section, throughSignal.getSection())) { //当车头与要越过的信号机不在同一区段
if (throughSignal != null && !Objects.equals(section,
throughSignal.getSection())) { //当车头与要越过的信号机不在同一区段
throughSignal = null;
throughAspect = null;
robotDriveParam.setThrough(DriveParamVO.DRIVER_ROUTE_BLOCK);
@ -257,9 +303,11 @@ public class SimulationRobotService {
// 车头在正常的站台上
if (section.isNormalStandTrack() && !section.equals(train.getParkSection())) { //正常站台轨且未在此处停过车
// 如果计划停车区段为空或者计划停车区段中有包含当前区段
if (CollectionUtils.isEmpty(plannedParkingSections) || plannedParkingSections.contains(section)) {
if (CollectionUtils.isEmpty(plannedParkingSections) || plannedParkingSections.contains(
section)) {
SectionPosition stopPosition = section.buildStopPointPosition(right);
SectionPosition maxStopPosition = CalculateService.calculateNextPositionByStartAndLen(stopPosition,
SectionPosition maxStopPosition = CalculateService.calculateNextPositionByStartAndLen(
stopPosition,
right, SimulationConstants.PARK_POINT_MAX_OFFSET, true);
if (maxStopPosition.isAheadOf(headPosition, right)) { //未越过最大停车点
targetPosition = stopPosition;
@ -280,11 +328,14 @@ public class SimulationRobotService {
if (signal != null && !signal.isShunting()) { // 信号机不为调车信号机
VirtualRealitySignal vrSignal = signal.getVirtualSignal();
SectionPosition signalPosition = signal.getPosition();
if (vrSignal != null && (i != 0 || signalPosition.isAheadOf(headPosition, right))) { //有实体信号机且列车未越过信号机
if (vrSignal != null && (i != 0 || signalPosition.isAheadOf(headPosition,
right))) { //有实体信号机且列车未越过信号机
if (Objects.equals(vrSignal.getAspect(), signal.getDefaultAspect()) //禁止信号
|| Objects.equals(vrSignal.getAspect(), signal.getGuideAspect())) { //引导信号
if (!Objects.equals(signal, throughSignal) || !Objects.equals(vrSignal.getAspect(), throughAspect)) {
SectionPosition noPassPosition = CalculateService.calculateNextPositionByStartAndLen(signalPosition, !right, 2, true);
if (!Objects.equals(signal, throughSignal) || !Objects.equals(vrSignal.getAspect(),
throughAspect)) {
SectionPosition noPassPosition = CalculateService.calculateNextPositionByStartAndLen(
signalPosition, !right, 2, true);
if (targetPosition == null || noPassPosition.isAheadOf(targetPosition, right)) {
targetPosition = noPassPosition;
}
@ -294,7 +345,8 @@ public class SimulationRobotService {
}
if (targetPosition == null) {
if (selectedPosition != null && section.equals(selectedPosition.getSection())) { //不会有比选定位置更靠前的停车点了
if (selectedPosition != null && section.equals(
selectedPosition.getSection())) { //不会有比选定位置更靠前的停车点了
targetPosition = selectedPosition;
} else {
Section tempSection = section.findNextRunningSectionBaseRealSwitch(right);