diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/operation/handler/DriverOperateHandler.java b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/operation/handler/DriverOperateHandler.java index 3e6ad7012..3f119edde 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/operation/handler/DriverOperateHandler.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/operation/handler/DriverOperateHandler.java @@ -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; - /** * 司机操作处理 */ @@ -24,59 +23,63 @@ import java.util.Objects; @Slf4j public class DriverOperateHandler { - @Autowired - private ATOService ATOService; + @Autowired + private ATOService ATOService; - @Autowired - private ATPService ATPService; + @Autowired + private ATPService ATPService; - @Autowired - private SimulationRobotService simulationRobotService; + @Autowired + private SimulationRobotService simulationRobotService; - @OperateHandlerMapping(type = Operation.Type.Driver_Force_Change) - public void changeTrainForce(Simulation simulation, String groupNumber, Float percent) { - Objects.requireNonNull(percent); - VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); - if (!validate(train)) - return; - ATPService.changeTrainForce(train, percent); + @OperateHandlerMapping(type = Operation.Type.Driver_Force_Change) + public void changeTrainForce(Simulation simulation, String groupNumber, Float percent) { + Objects.requireNonNull(percent); + VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); + if (!validate(train)) { + return; + } + ATPService.changeTrainForce(train, percent); + } + + /** + * 紧急制动 + */ + @OperateHandlerMapping(type = Operation.Type.Driver_EB) + public void trainEB(Simulation simulation, String groupNumber) { + VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); + if (!validate(train)) { + return; + } + if (train.isCircuitEB()) { + this.ATPService.cancelCircuitEB(train); + } else { + this.ATPService.triggerCircuitEB(train); } + } - /** - * 紧急制动 - */ - @OperateHandlerMapping(type = Operation.Type.Driver_EB) - public void trainEB(Simulation simulation, String groupNumber) { - VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); - if (!validate(train)) - return; - if (train.isCircuitEB()) { - this.ATPService.cancelCircuitEB(train); - } else { - this.ATPService.triggerCircuitEB(train); - } - } + /** + * 修改工况手轮档位 + * + * @param simulation + * @param groupNumber + * @param gear + */ + @OperateHandlerMapping(type = Operation.Type.Driver_Gear_Change) + public void changeTrainGear(Simulation simulation, String groupNumber, + VirtualRealityTrain.Handwheel gear) { + Objects.requireNonNull(gear); + VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); + if (!validate(train)) { + return; + } + ATPService.changeGear(train, gear); + } - /** - * 修改工况手轮档位 - * - * @param simulation - * @param groupNumber - * @param gear - */ - @OperateHandlerMapping(type = Operation.Type.Driver_Gear_Change) - public void changeTrainGear(Simulation simulation, String groupNumber, VirtualRealityTrain.Handwheel gear) { - Objects.requireNonNull(gear); - VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); - if (!validate(train)) - return; - ATPService.changeGear(train, gear); - } - - // 场景旧数据反序列化需要 - @Deprecated - @OperateHandlerMapping(type = Operation.Type.Driver_Drive_Mode_Change) - public void changeTrainDriveMode(Simulation simulation, String groupNumber, DriveMode driveMode) { + // 场景旧数据反序列化需要 + @Deprecated + @OperateHandlerMapping(type = Operation.Type.Driver_Drive_Mode_Change) + public void changeTrainDriveMode(Simulation simulation, String groupNumber, DriveMode driveMode) { // VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); // switch (driveMode) { // case AM: @@ -87,182 +90,194 @@ public class DriverOperateHandler { // break; // } // } - } + } - @OperateHandlerMapping(type = Operation.Type.Driver_ATO_Open) - public void openAto(Simulation simulation, String groupNumber) { - VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); - if (!validate(train)) - return; - ATPService.openATO(train); - } + @OperateHandlerMapping(type = Operation.Type.Driver_ATO_Open) + public void openAto(Simulation simulation, String groupNumber) { + VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); + 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)) - return; - if (cutOff) { - this.ATPService.cutOffAtp(train); - } else { - this.ATPService.openAtp(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)) { + return; + } + if (cutOff) { + this.ATPService.cutOffAtp(train); + } else { + this.ATPService.openAtp(train); } + } - @OperateHandlerMapping(type = Operation.Type.Driver_Change_Head) - public void changeHead(Simulation simulation, String groupNumber) { - VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); - if (!validate(train)) - return; - if (train.isStop()) { - this.ATPService.turnDirectionImmediately(train); - } + @OperateHandlerMapping(type = Operation.Type.Driver_Change_Head) + public void changeHead(Simulation simulation, String groupNumber) { + VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); + if (!validate(train)) { + return; + } + if (train.isStop()) { + this.ATPService.turnDirectionImmediately(train); } + } - /** - * 开/关门 - * - * @param groupNumber 要开/关门的列车的车组号 - * @param right 要开/关右边的门吗 - * @param open 要开门吗 - */ - @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)) - return; - ATPService.openOrCloseDoor(simulation, train, right, open); - } + /** + * 开/关门 + * + * @param groupNumber 要开/关门的列车的车组号 + * @param right 要开/关右边的门吗 + * @param open 要开门吗 + */ + @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)) { + return; + } + ATPService.openOrCloseDoor(simulation, train, right, open); + } - /** - * 设置门模式 - * - * @param groupNumber 车组号 - */ - @OperateHandlerMapping(type = Operation.Type.Driver_Door_Mode) - public void setDriverDoorMode(Simulation simulation, String groupNumber, - VirtualRealityTrain.DoorMode doorMode) { - if (Objects.isNull(doorMode)) { - throw new SimulationException(SimulationExceptionType.Illegal_Argument, "门模式不能为空"); - } - VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); - if (!validate(train)) - return; - train.setDoorMode(doorMode); + /** + * 设置门模式 + * + * @param groupNumber 车组号 + */ + @OperateHandlerMapping(type = Operation.Type.Driver_Door_Mode) + public void setDriverDoorMode(Simulation simulation, String groupNumber, + VirtualRealityTrain.DoorMode doorMode) { + if (Objects.isNull(doorMode)) { + throw new SimulationException(SimulationExceptionType.Illegal_Argument, "门模式不能为空"); } + VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); + if (!validate(train)) { + return; + } + train.setDoorMode(doorMode); + } - /** - * 设置门选择 - * - * @param groupNumber 车组号 - */ - @OperateHandlerMapping(type = Operation.Type.Driver_Door_Selection) - public void setDriverDoorSelection(Simulation simulation, String groupNumber, - VirtualRealityTrain.DoorSelection doorSelection) { - if (Objects.isNull(doorSelection)) { - throw new SimulationException(SimulationExceptionType.Illegal_Argument, "门选择不能为空"); - } - VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); - if (!validate(train)) - return; - train.setDoorSelection(doorSelection); + /** + * 设置门选择 + * + * @param groupNumber 车组号 + */ + @OperateHandlerMapping(type = Operation.Type.Driver_Door_Selection) + public void setDriverDoorSelection(Simulation simulation, String groupNumber, + VirtualRealityTrain.DoorSelection doorSelection) { + if (Objects.isNull(doorSelection)) { + throw new SimulationException(SimulationExceptionType.Illegal_Argument, "门选择不能为空"); } + VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); + if (!validate(train)) { + return; + } + train.setDoorSelection(doorSelection); + } - /** - * 模式升 - */ - @OperateHandlerMapping(type = Operation.Type.Driver_Preselection_Mode_Up) - public void beforehandModeUp(Simulation simulation, String groupNumber) { - VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); - if (!validate(train)) - return; - ATPService.preselectionModeUp(train); - } + /** + * 模式升 + */ + @OperateHandlerMapping(type = Operation.Type.Driver_Preselection_Mode_Up) + public void beforehandModeUp(Simulation simulation, String groupNumber) { + VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); + if (!validate(train)) { + return; + } + ATPService.preselectionModeUp(train); + } - /** - * 模式降 - */ - @OperateHandlerMapping(type = Operation.Type.Driver_Preselection_Mode_Down) - public void beforehandModeDown(Simulation simulation, String groupNumber) { - VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); - if (!validate(train)) - return; - ATPService.preselectionModeDown(train); - } + /** + * 模式降 + */ + @OperateHandlerMapping(type = Operation.Type.Driver_Preselection_Mode_Down) + public void beforehandModeDown(Simulation simulation, String groupNumber) { + VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); + if (!validate(train)) { + return; + } + ATPService.preselectionModeDown(train); + } - /** - * 确认 - */ - @OperateHandlerMapping(type = Operation.Type.Driver_Confirm) - public void confirmMessage(Simulation simulation, String groupNumber) { - VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); - if (!validate(train)) - return; - ATPService.confirmMessage(train); - } + /** + * 确认 + */ + @OperateHandlerMapping(type = Operation.Type.Driver_Confirm) + public void confirmMessage(Simulation simulation, String groupNumber) { + VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); + if (!validate(train)) { + return; + } + ATPService.confirmMessage(train); + } - /** - * 接管列车 - */ - @OperateHandlerMapping(type = Operation.Type.Driver_TakeOver) - public void takeOver(Simulation simulation, String groupNumber, Boolean takeOver) { - VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); - train.setTakeOver(takeOver); - } + /** + * 接管列车 + */ + @OperateHandlerMapping(type = Operation.Type.Driver_TakeOver) + public void takeOver(Simulation simulation, String groupNumber, Boolean takeOver) { + VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); + train.setTakeOver(takeOver); + } - /** - * ATS停车 - */ - @OperateHandlerMapping(type = Operation.Type.Driver_Stop) - public void stopTrain(Simulation simulation, SimulationMember simulationMember, String groupNumber, Boolean eb) { - simulationRobotService.stopTrain(simulation, simulationMember, groupNumber, eb); - } + /** + * ATS停车 + */ + @OperateHandlerMapping(type = Operation.Type.Driver_Stop) + public void stopTrain(Simulation simulation, SimulationMember simulationMember, + String groupNumber, Boolean eb) { + simulationRobotService.stopTrain(simulation, simulationMember, groupNumber, eb); + } - /** - * ATS开关门 - */ - @OperateHandlerMapping(type = Operation.Type.Open_Or_Close_Door) - public void openOrCloseDoor(Simulation simulation, String groupNumber) { - ATPService.openOrCloseDoor(simulation, groupNumber); - } + /** + * ATS开关门 + */ + @OperateHandlerMapping(type = Operation.Type.Open_Or_Close_Door) + public void openOrCloseDoor(Simulation simulation, String groupNumber) { + ATPService.openOrCloseDoor(simulation, groupNumber); + } - /** - * 回库 - */ - @OperateHandlerMapping(type = Operation.Type.Inbound) - public void inbound(Simulation simulation,String groupNumber) { - ATPService.inbound(simulation, groupNumber); - } + /** + * 回库 + */ + @OperateHandlerMapping(type = Operation.Type.Inbound) + public void inbound(Simulation simulation, String groupNumber) { + ATPService.inbound(simulation, groupNumber); + } - /** - * ATS修改预选模式 - */ - @OperateHandlerMapping(type = Operation.Type.Change_Preselection_Mode) - public void changePreselectionMode(Simulation simulation, String groupNumber - , VirtualRealityTrain.PreselectionMode preselectionMode) { - ATPService.changePreselectionMode(simulation, groupNumber, preselectionMode); - } + /** + * ATS修改预选模式 + */ + @OperateHandlerMapping(type = Operation.Type.Change_Preselection_Mode) + public void changePreselectionMode(Simulation simulation, String groupNumber + , VirtualRealityTrain.PreselectionMode preselectionMode) { + ATPService.changePreselectionMode(simulation, groupNumber, preselectionMode); + } - /** - * ATS转NRM模式 - */ - @OperateHandlerMapping(type = Operation.Type.Apply_NRM) - public void applyNRM(Simulation simulation, String groupNumber) { - ATPService.applyNRM(simulation, groupNumber); - } + /** + * ATS转NRM模式 + */ + @OperateHandlerMapping(type = Operation.Type.Apply_NRM) + public void applyNRM(Simulation simulation, String groupNumber) { + ATPService.applyNRM(simulation, groupNumber); + } - /** - * ATS操作打开 ATO - */ - @OperateHandlerMapping(type = Operation.Type.Try_Open_Ato) - public void tryOpenAto(Simulation simulation, String groupNumber) { - ATPService.openAto(simulation, groupNumber); - } + /** + * ATS操作打开 ATO + */ + @OperateHandlerMapping(type = Operation.Type.Try_Open_Ato) + public void tryOpenAto(Simulation simulation, String groupNumber) { + VirtualRealityTrain train = simulation.getRepository() + .getVRByCode(groupNumber, VirtualRealityTrain.class); + ATPService.openATO(train); + } - /** - * 校验用户可操作的前提条件 - */ - private boolean validate(VirtualRealityTrain train) { - return train.isTakeOver(); - } + /** + * 校验用户可操作的前提条件 + */ + private boolean validate(VirtualRealityTrain train) { + return train.isTakeOver(); + } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/operation/handler/SwitchOperateHandler.java b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/operation/handler/SwitchOperateHandler.java index 01bd26cb1..32f61fb84 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/operation/handler/SwitchOperateHandler.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/operation/handler/SwitchOperateHandler.java @@ -15,341 +15,353 @@ 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 public class SwitchOperateHandler { - @Autowired - private CiApiService ciApiService; + @Autowired + private CiApiService ciApiService; - @Autowired - private AtsSectionService atsSectionService; + @Autowired + private AtsSectionService atsSectionService; - @Autowired - private GroundAtpApiService groundAtpApiService; + @Autowired + private GroundAtpApiService groundAtpApiService; - /** - * 道岔转动 - * - * @param simulation - * @param switchCode - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Turn) - public void turn(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - BusinessExceptionAssertEnum.SIMULATION_EXCEPTION_FOR_SHOW.assertTrue(!aSwitch.isLocked(), - String.format("联锁操作被取消,道岔%s被锁定", aSwitch.getName())); - SwitchIndication pos = this.ciApiService.turn(simulation, switchCode); + /** + * 道岔转动 + * + * @param simulation + * @param switchCode + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Turn) + public void turn(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + BusinessExceptionAssertEnum.SIMULATION_EXCEPTION_FOR_SHOW.assertTrue(!aSwitch.isLocked(), + String.format("联锁操作被取消,道岔%s被锁定", aSwitch.getName())); + SwitchIndication pos = this.ciApiService.turn(simulation, switchCode); - waitResult(simulation, aSwitch, pos); + waitResult(simulation, aSwitch, pos); + } + + /** + * 道岔定操 + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Normal_Position) + public void turn2Normal(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + if (!aSwitch.canTurn()) { + throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, + "道岔锁闭或占用,无法转动"); + } + if (aSwitch.isPosN()) { + throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, + "道岔已经在定位,无需转动"); + } + this.ciApiService.turn2NormalPosition(simulation, switchCode); + if (simulation.getRepository().getConfig().isSwitchNRTurnChain()) { + Switch linkedSwitch = aSwitch.queryLinkedSwitch(); + if (Objects.nonNull(linkedSwitch)) { + this.ciApiService.turn2NormalPosition(simulation, linkedSwitch.getCode()); + } + } + } + + /** + * 道岔反操 + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Reverse_Position) + public void turn2Reverse(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + if (!aSwitch.canTurn()) { + throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, + "道岔锁闭或占用,无法转动"); + } + if (aSwitch.isPosR()) { + throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, + "道岔已经在反位,无需转动"); + } + this.ciApiService.turn2ReversePosition(simulation, switchCode); + if (simulation.getRepository().getConfig().isSwitchNRTurnChain()) { + Switch linkedSwitch = aSwitch.queryLinkedSwitch(); + if (Objects.nonNull(linkedSwitch)) { + this.ciApiService.turn2ReversePosition(simulation, linkedSwitch.getCode()); + } + } + } + + /** + * 道岔单锁 + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Single_Lock) + public void singleLockSwitch(Simulation simulation, String switchCode) { + ciApiService.singleLockSwitch(simulation, switchCode); + //联动 + SimulationDataRepository repository = simulation.getRepository(); + if (repository.getConfig().isSwitchSingleLockChain()) { + Switch aSwitch = repository.getByCode(switchCode, Switch.class); + Switch linkedSwitch = aSwitch.queryLinkedSwitch(); + if (Objects.nonNull(linkedSwitch)) { + this.ciApiService.singleLockSwitch(simulation, linkedSwitch.getCode()); + } + } + } + + /** + * 道岔单解 + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Single_Unlock) + public void singleUnlockSwitch(Simulation simulation, String switchCode) { + ciApiService.singleUnlockSwitch(simulation, switchCode); + SimulationDataRepository repository = simulation.getRepository(); + if (repository.getConfig().isSwitchSingleLockChain()) { + Switch aSwitch = repository.getByCode(switchCode, Switch.class); + Switch linkedSwitch = aSwitch.queryLinkedSwitch(); + if (Objects.nonNull(linkedSwitch)) { + this.ciApiService.singleUnlockSwitch(simulation, linkedSwitch.getCode()); + } + } + } + + /** + * 道岔初始化封锁 + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Initialize_Block) + public void initializeBlock(Simulation simulation, String switchCode) { + ciApiService.initializeBlock(simulation, switchCode); + } + + /** + * 道岔封锁l + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Block) + public void blockadeSwitch(Simulation simulation, String switchCode) { + ciApiService.blockadeSwitch(simulation, switchCode); + } + + /** + * 道岔解锁l + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Unblock) + public void unblockSwitch(Simulation simulation, String switchCode) { + ciApiService.unblockSwitch(simulation, switchCode); + } + + /** + * 道岔区段封锁l + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Section_Block) + public void blockadeSwitchSection(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + ciApiService.blockadeSwitchSection(simulation, aSwitch.getCode()); + } + + /** + * 道岔区段解封l + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Section_Unblock) + public void unblockSwitchSection(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + ciApiService.unblockSwitchSection(simulation, aSwitch.getCode()); + } + + /** + * 道岔跟踪切除 + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Cut_Off) + public void cutoff(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + this.atsSectionService.cutoff(simulation, aSwitch.getA()); + } + + /** + * 道岔跟踪激活 + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Active) + public void active(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + this.atsSectionService.active(simulation, aSwitch.getA()); + } + + /** + * 确认计轴有效c + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Confirm_Axis_Valid) + public void confirmAxisValid(Simulation simulation, String switchCode) { + //ZC 系统 + log.debug("仿真[{}] : 道岔[{}]确认计轴有效", simulation.getId(), switchCode); + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + this.atsSectionService.confirmAxleValid(simulation, aSwitch.getA()); + } + + /** + * 设置临时限速/轨区设限 + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Set_Limit_Speed) + public void setLimitSpeed(Simulation simulation, String switchCode, String speedLimitValue) { + int limitSpeed; + try { + limitSpeed = Integer.parseInt(speedLimitValue); + } catch (NumberFormatException e) { + throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, + "速度值必须为数字!"); + } + this.groundAtpApiService.setSwitchLimitSpeed(simulation, switchCode, limitSpeed); + } + + + /** + * 取消临时限速/轨区消限 + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Cancel_Limit_Speed) + public void cancelLimitSpeed(Simulation simulation, String switchCode) { + this.groundAtpApiService.cancelSwitchLimitSpeed(simulation, switchCode); + } + + /** + * 道岔计轴预复位 + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Axle_Pre_Reset) + public void axlePreReset(Simulation simulation, String switchCode) { + ciApiService.switchAxlePreReset(simulation, switchCode); + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + ciApiService.axlePreReset(simulation, aSwitch.getA().getParent().getCode()); + } + + /** + * 区故解 + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Fault_Unlock) + public void switchSectionFaultUnlock(Simulation simulation, String switchCode) { + log.debug("仿真[{}] : 道岔[{}]区故解", simulation.getId(), switchCode); + ciApiService.switchSectionFaultUnlock(simulation, switchCode); + } + + /** + * 道岔钩锁 + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Hook_Lock) + public void switchHookLock(Simulation simulation, String switchCode, Boolean normal) { + SimulationDataRepository repository = simulation.getRepository(); + Switch aSwitch = repository.getByCode(switchCode, Switch.class); + if (normal) { + aSwitch.getVirtualSwitch().setP(SwitchIndication.N); + } else { + aSwitch.getVirtualSwitch().setP(SwitchIndication.R); } - /** - * 道岔定操 - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Normal_Position) - public void turn2Normal(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - if (!aSwitch.canTurn()) { - throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, - "道岔锁闭或占用,无法转动"); - } - if (aSwitch.isPosN()) { - throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, - "道岔已经在定位,无需转动"); - } - this.ciApiService.turn2NormalPosition(simulation, switchCode); - if (simulation.getRepository().getConfig().isSwitchNRTurnChain()) { - Switch linkedSwitch = aSwitch.queryLinkedSwitch(); - if (Objects.nonNull(linkedSwitch)) { - this.ciApiService.turn2NormalPosition(simulation, linkedSwitch.getCode()); - } - } - } - - /** - * 道岔反操 - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Reverse_Position) - public void turn2Reverse(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - if (!aSwitch.canTurn()) { - throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, - "道岔锁闭或占用,无法转动"); - } - if (aSwitch.isPosR()) { - throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, - "道岔已经在反位,无需转动"); - } - this.ciApiService.turn2ReversePosition(simulation, switchCode); - if (simulation.getRepository().getConfig().isSwitchNRTurnChain()) { - Switch linkedSwitch = aSwitch.queryLinkedSwitch(); - if (Objects.nonNull(linkedSwitch)) { - this.ciApiService.turn2ReversePosition(simulation, linkedSwitch.getCode()); - } - } - } - - /** - * 道岔单锁 - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Single_Lock) - public void singleLockSwitch(Simulation simulation, String switchCode) { - ciApiService.singleLockSwitch(simulation, switchCode); - //联动 - SimulationDataRepository repository = simulation.getRepository(); - if (repository.getConfig().isSwitchSingleLockChain()) { - Switch aSwitch = repository.getByCode(switchCode, Switch.class); - Switch linkedSwitch = aSwitch.queryLinkedSwitch(); - if (Objects.nonNull(linkedSwitch)) { - this.ciApiService.singleLockSwitch(simulation, linkedSwitch.getCode()); - } - } - } - - /** - * 道岔单解 - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Single_Unlock) - public void singleUnlockSwitch(Simulation simulation, String switchCode) { - ciApiService.singleUnlockSwitch(simulation, switchCode); - SimulationDataRepository repository = simulation.getRepository(); - if (repository.getConfig().isSwitchSingleLockChain()) { - Switch aSwitch = repository.getByCode(switchCode, Switch.class); - Switch linkedSwitch = aSwitch.queryLinkedSwitch(); - if (Objects.nonNull(linkedSwitch)) { - this.ciApiService.singleUnlockSwitch(simulation, linkedSwitch.getCode()); - } - } - } - - /** - * 道岔初始化封锁 - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Initialize_Block) - public void initializeBlock(Simulation simulation, String switchCode) { - ciApiService.initializeBlock(simulation, switchCode); - } - - /** - * 道岔封锁l - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Block) - public void blockadeSwitch(Simulation simulation, String switchCode) { - ciApiService.blockadeSwitch(simulation, switchCode); - } - - /** - * 道岔解锁l - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Unblock) - public void unblockSwitch(Simulation simulation, String switchCode) { - ciApiService.unblockSwitch(simulation, switchCode); - } - - /** - * 道岔区段封锁l - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Section_Block) - public void blockadeSwitchSection(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - ciApiService.blockadeSwitchSection(simulation, aSwitch.getCode()); - } - - /** - * 道岔区段解封l - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Section_Unblock) - public void unblockSwitchSection(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - ciApiService.unblockSwitchSection(simulation, aSwitch.getCode()); - } - - /** - * 道岔跟踪切除 - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Cut_Off) - public void cutoff(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - this.atsSectionService.cutoff(simulation, aSwitch.getA()); - } - - /** - * 道岔跟踪激活 - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Active) - public void active(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - this.atsSectionService.active(simulation, aSwitch.getA()); - } - - /** - * 确认计轴有效c - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Confirm_Axis_Valid) - public void confirmAxisValid(Simulation simulation, String switchCode) { - //ZC 系统 - log.debug("仿真[{}] : 道岔[{}]确认计轴有效", simulation.getId(), switchCode); - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - this.atsSectionService.confirmAxleValid(simulation, aSwitch.getA()); - } - - /** - * 设置临时限速/轨区设限 - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Set_Limit_Speed) - public void setLimitSpeed(Simulation simulation, String switchCode, String speedLimitValue) { - int limitSpeed; - try { - limitSpeed = Integer.parseInt(speedLimitValue); - } catch (NumberFormatException e) { - throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, "速度值必须为数字!"); - } - this.groundAtpApiService.setSwitchLimitSpeed(simulation, switchCode, limitSpeed); - } - - - /** - * 取消临时限速/轨区消限 - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Cancel_Limit_Speed) - public void cancelLimitSpeed(Simulation simulation, String switchCode) { - this.groundAtpApiService.cancelSwitchLimitSpeed(simulation, switchCode); - } - - /** - * 道岔计轴预复位 - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Axle_Pre_Reset) - public void axlePreReset(Simulation simulation, String switchCode) { - ciApiService.switchAxlePreReset(simulation, switchCode); - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - ciApiService.axlePreReset(simulation, aSwitch.getA().getParent().getCode()); - } - - /** - * 区故解 - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Fault_Unlock) - public void switchSectionFaultUnlock(Simulation simulation, String switchCode) { - log.debug("仿真[{}] : 道岔[{}]区故解", simulation.getId(), switchCode); - ciApiService.switchSectionFaultUnlock(simulation, switchCode); - } - - /** - * 道岔钩锁 - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Hook_Lock) - public void switchHookLock(Simulation simulation, String switchCode, Boolean normal) { - SimulationDataRepository repository = simulation.getRepository(); - Switch aSwitch = repository.getByCode(switchCode, Switch.class); + if (simulation.getRepository().getConfig().isSwitchNRTurnChain()) { + Switch linkedSwitch = aSwitch.queryLinkedSwitch(); + if (linkedSwitch != null) { if (normal) { - aSwitch.getVirtualSwitch().setP(SwitchIndication.N); + linkedSwitch.getVirtualSwitch().setP(SwitchIndication.N); } else { - aSwitch.getVirtualSwitch().setP(SwitchIndication.R); + linkedSwitch.getVirtualSwitch().setP(SwitchIndication.R); } + } + } + } - if (simulation.getRepository().getConfig().isSwitchNRTurnChain()) { - Switch linkedSwitch = aSwitch.queryLinkedSwitch(); - if (linkedSwitch != null) { - if (normal) { - linkedSwitch.getVirtualSwitch().setP(SwitchIndication.N); - } else { - linkedSwitch.getVirtualSwitch().setP(SwitchIndication.R); - } - } + /** + * 强行转岔 + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Force_Turn) + public void switchForceTurn(Simulation simulation, String switchCode, Boolean normal) { + SwitchIndication pos = ciApiService.switchForceTurn(simulation, switchCode); + + waitResult(simulation, simulation.getRepository().getByCode(switchCode, Switch.class), pos); + } + + /** + * 挤岔恢复 + */ + @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) { + ciApiService.switchCommand(simulation, switchCode, auto, reserve, normal); + } + + + /** + * 道岔分路不良 + * + * @param simulation 仿真实体 + * @param switchCode 道岔编码 + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Defective_Shunting) + public void defectiveShunting(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + List 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); + } + + /** + * 取消道岔分路不良 + * + * @param simulation 仿真实体 + * @param switchCode 道岔编码 + */ + @OperateHandlerMapping(type = Operation.Type.Switch_Cancel_Defective_Shunting) + public void cancelDefectiveShunting(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + atsSectionService.defectiveShunting(simulation, aSwitch.getA().getCode(), new ArrayList<>()); + } + + /** + * 道岔只要处于{posArr}中任意一个位置就认为操作完成 + */ + private static void waitResult(Simulation simulation, Switch aSwitch, + SwitchIndication... posArr) { + //等待转动完成 + LocalDateTime timeoutTime = simulation.getSystemTime().plusSeconds(13); + CompletableFuture future = CompletableFuture.supplyAsync(() -> { + while (true) { + for (SwitchIndication pos : posArr) { + if (Objects.equals(aSwitch.getPos(), pos)) { + return true; + } + if (simulation.getSystemTime().isAfter(timeoutTime)) { + return false; + } } - } - - /** - * 强行转岔 - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Force_Turn) - public void switchForceTurn(Simulation simulation, String switchCode, Boolean normal) { - SwitchIndication pos = ciApiService.switchForceTurn(simulation, switchCode); - - waitResult(simulation, simulation.getRepository().getByCode(switchCode, Switch.class), pos); - } - - /** - * 挤岔恢复 - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Squeeze_Recovery) - public void switchSqueezeRecovery(Simulation simulation, String switchCode) { - ciApiService.switchSqueezeRecovery(simulation, switchCode); - } - - /** - * 命令【泰雷兹】 - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Command) - public void switchCommand(Simulation simulation, String switchCode, Boolean auto, Boolean reserve, Boolean normal) { - ciApiService.switchCommand(simulation, switchCode, auto, reserve, normal); - } - - - /** - * 道岔分路不良 - * - * @param simulation 仿真实体 - * @param switchCode 道岔编码 - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Defective_Shunting) - public void defectiveShunting(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - List 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); - } - - /** - * 取消道岔分路不良 - * - * @param simulation 仿真实体 - * @param switchCode 道岔编码 - */ - @OperateHandlerMapping(type = Operation.Type.Switch_Cancel_Defective_Shunting) - public void cancelDefectiveShunting(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - atsSectionService.defectiveShunting(simulation, aSwitch.getA().getCode(), new ArrayList<>()); - } - - private static void waitResult(Simulation simulation, Switch aSwitch, SwitchIndication pos) { - //等待转动完成 - LocalDateTime timeoutTime = simulation.getSystemTime().plusSeconds(13); - CompletableFuture future = CompletableFuture.supplyAsync(() -> { - while (true) { - if (Objects.equals(aSwitch.getPos(), pos)) { - return true; - } - if (simulation.getSystemTime().isAfter(timeoutTime)) { - return false; - } - try { - Thread.sleep(100); - } catch (Exception e) { - throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception(); - } - } - }); try { - Boolean success = future.get(); - BusinessExceptionAssertEnum.OPERATION_FAIL.assertTrue(success, "道岔转动失败"); - } catch (BaseException be) { - throw be; + Thread.sleep(100); } catch (Exception e) { - throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception(e); + throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception(); } + } + }); + try { + Boolean success = future.get(); + BusinessExceptionAssertEnum.OPERATION_FAIL.assertTrue(success, "道岔转动失败"); + } catch (BaseException be) { + throw be; + } catch (Exception e) { + throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception(e); } + } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/CI/CiApiService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/CI/CiApiService.java index a199cc4f5..9fff3e960 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/CI/CiApiService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/CI/CiApiService.java @@ -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); - /** * 开站台屏蔽门 * diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/CI/CiApiServiceImpl2.java b/src/main/java/club/joylink/rtss/simulation/cbtc/CI/CiApiServiceImpl2.java index 37be41706..59535f4b6 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/CI/CiApiServiceImpl2.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/CI/CiApiServiceImpl2.java @@ -1,439 +1,439 @@ 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 - private CiSectionService sectionService; - @Autowired - private CiSignalControlService signalService; - @Autowired - private CiRouteService routeService; - @Autowired - private CiService ciService; - @Autowired - private CiStandService standService; - @Autowired - private VirtualRealityDeviceService virtualRealityDeviceService; + + @Autowired + private CiSwitchControlService switchService; + @Autowired + private CiSectionService sectionService; + @Autowired + private CiSignalControlService signalService; + @Autowired + private CiRouteService routeService; + @Autowired + private CiService ciService; + @Autowired + private CiStandService standService; + @Autowired + private VirtualRealityDeviceService virtualRealityDeviceService; - @Override - public void blockadeSection(Simulation simulation, String sectionCode) { - Section section = simulation.getRepository().getByCode(sectionCode, Section.class); - this.sectionService.blockade(section); + @Override + public void blockadeSection(Simulation simulation, String sectionCode) { + Section section = simulation.getRepository().getByCode(sectionCode, Section.class); + this.sectionService.blockade(section); + } + + @Override + public void unblockSection(Simulation simulation, String sectionCode) { + Section section = simulation.getRepository().getByCode(sectionCode, Section.class); + this.sectionService.unblock(section); + } + + @Override + public void blockadeSignal(Simulation simulation, String signalCode) { + Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class); + this.signalService.blockade(simulation, signal); + } + + @Override + public void unblockSignal(Simulation simulation, String signalCode) { + Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class); + this.signalService.unblock(signal); + } + + @Override + public void closeSignal(Simulation simulation, String signalCode) { + Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class); + this.signalService.closeRoute(simulation, signal); + } + + @Override + public void reopenSignal(Simulation simulation, String signalCode) { + // 判断信号机是否是关闭状态、进路是否锁闭、联锁关系是否满足 + Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class); + if (signal.isMainAspect()) { + throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, + "信号机已经开启,无需重开信号机"); } - - @Override - public void unblockSection(Simulation simulation, String sectionCode) { - Section section = simulation.getRepository().getByCode(sectionCode, Section.class); - this.sectionService.unblock(section); - } - - @Override - public void blockadeSignal(Simulation simulation, String signalCode) { - Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class); - this.signalService.blockade(simulation, signal); - } - - @Override - public void unblockSignal(Simulation simulation, String signalCode) { - Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class); - this.signalService.unblock(signal); - } - - @Override - public void closeSignal(Simulation simulation, String signalCode) { - Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class); - this.signalService.closeRoute(simulation, signal); - } - - @Override - public void reopenSignal(Simulation simulation, String signalCode) { - // 判断信号机是否是关闭状态、进路是否锁闭、联锁关系是否满足 - Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class); - if (signal.isMainAspect()) { - throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, - "信号机已经开启,无需重开信号机"); - } - Optional routeOptional = simulation.getRepository().getSettingRoutes().stream() - .filter(route -> route.getStart().equals(signal)).findAny(); - BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(routeOptional.isPresent(), "信号机不是已排进路的始端信号机"); + Optional routeOptional = simulation.getRepository().getSettingRoutes().stream() + .filter(route -> route.getStart().equals(signal)).findAny(); + 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(), "进路延时解锁中,不能重开"); - signal.setForbidden(false); + Route lockedRoute = signal.getLockedRoute(); + if (Objects.isNull(lockedRoute)) { + throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, + "进路未锁闭,不能重开信号机"); } + BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(!lockedRoute.isDelayUnlocking(), + "进路延时解锁中,不能重开"); + signal.setForbidden(false); + } - @Override - public SwitchIndication turn(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - 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, "道岔锁闭,不能进行转动"); - } - if (Switch.SwitchFault.SPLIT_1.equals(aSwitch.getFault())) { - Switch.SwitchFault.SPLIT_1.fix(aSwitch); - } - return pos; + @Override + public SwitchIndication turn(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + 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, + "道岔锁闭,不能进行转动"); } - - @Override - 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, "道岔锁闭,不能进行定操"); - } + if (Switch.SwitchFault.SPLIT_1.equals(aSwitch.getFault())) { + Switch.SwitchFault.SPLIT_1.fix(aSwitch); } + return pos; + } - @Override - 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, "道岔锁闭,不能进行反操"); - } + @Override + 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, + "道岔锁闭,不能进行定操"); } + } - @Override - public void singleLockSwitch(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - this.switchService.singleLock(aSwitch); + @Override + 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, + "道岔锁闭,不能进行反操"); } + } - @Override - public void singleUnlockSwitch(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - this.switchService.singleUnlock(aSwitch); + @Override + public void singleLockSwitch(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + this.switchService.singleLock(aSwitch); + } + + @Override + public void singleUnlockSwitch(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + this.switchService.singleUnlock(aSwitch); + } + + @Override + public void blockadeSwitch(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + //条件检查 + MapConfig config = simulation.getRepository().getConfig(); + if (config.isBlockadeCommandOnlyValidInStandbyMode()) { + boolean standbyMode = simulation.getRepository().getRouteList() + .stream().filter(route -> route.isRouteSwitch(aSwitch)) + .anyMatch(route -> !route.getStart().isCbtcMode()); //包含该道岔的进路是否有处于后备模式的 + if (!standbyMode) { + return; + } } - - @Override - public void blockadeSwitch(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - //条件检查 - MapConfig config = simulation.getRepository().getConfig(); - if (config.isBlockadeCommandOnlyValidInStandbyMode()) { - boolean standbyMode = simulation.getRepository().getRouteList() - .stream().filter(route -> route.isRouteSwitch(aSwitch)) - .anyMatch(route -> !route.getStart().isCbtcMode()); //包含该道岔的进路是否有处于后备模式的 - if (!standbyMode) { - return; - } - } // if (config.isSomeCommandNeedInit()) { // BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(aSwitch.isInit(), aSwitch.debugStr() + "未初始化"); // } - this.switchService.blockade(aSwitch); - } + this.switchService.blockade(aSwitch); + } - @Override - public void unblockSwitch(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - this.switchService.unblock(aSwitch); - } + @Override + public void unblockSwitch(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + this.switchService.unblock(aSwitch); + } - @Override - public void blockadeSwitchSection(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - this.switchService.blockade(aSwitch); - } + @Override + public void blockadeSwitchSection(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + this.switchService.blockade(aSwitch); + } - @Override - public void unblockSwitchSection(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - this.switchService.unblock(aSwitch); - } + @Override + public void unblockSwitchSection(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + this.switchService.unblock(aSwitch); + } - @Override - public Route.CheckFailMessage routeSettingCheck(Simulation simulation, String routeCode) { - Route route = simulation.getRepository().getByCode(routeCode, Route.class); - return this.routeService.routeSetCheck(simulation, route, false); - } + @Override + public Route.CheckFailMessage routeSettingCheck(Simulation simulation, String routeCode) { + Route route = simulation.getRepository().getByCode(routeCode, Route.class); + return this.routeService.routeSetCheck(simulation, route, false); + } - @Override - public Route.CheckFailMessage settingRoute(Simulation simulation, String routeCode) { - Route route = simulation.getRepository().getByCode(routeCode, Route.class); - //当为一般进路时直接获取信号显示,当为组合进路时信号显示获取到办理子进路时 - SignalAspect settedAspect = route.isMultiRoute() ? null : route.getAspect(); - return this.routeService.setRoute(simulation, route, settedAspect); - } + @Override + public Route.CheckFailMessage settingRoute(Simulation simulation, String routeCode) { + Route route = simulation.getRepository().getByCode(routeCode, Route.class); + //当为一般进路时直接获取信号显示,当为组合进路时信号显示获取到办理子进路时 + SignalAspect settedAspect = route.isMultiRoute() ? null : route.getAspect(); + return this.routeService.setRoute(simulation, route, settedAspect); + } - @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 (simulation.getRepository().getConfig().isDelayWhenCancelRouteWithAbnormalInterlock()) { - if (this.ciService.isRouteSwitchLost(simulation, route)) { - this.routeService.delayUnlockStart(simulation, route, route.getStart()); - return; - } - } - this.routeService.unlockRoute(simulation, route); + @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( + "转换轨进路只能通过区故解取消"); } - - @Override - public void forceUnlockRoute(Simulation simulation, String routeCode) { - Route route = simulation.getRepository().getByCode(routeCode, Route.class); - BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(route.isFleetMode(), - String.format("进路[%s]已开启自动通过进路,无法取消", route.debugStr())); - this.routeService.unlockRoute(simulation, route); + if (simulation.getRepository().getConfig().isDelayWhenCancelRouteWithAbnormalInterlock()) { + if (this.ciService.isRouteSwitchLost(simulation, route)) { + this.routeService.delayUnlockStart(simulation, route, route.getStart()); + return; + } } + this.routeService.unlockRoute(simulation, route); + } - @Override - public void humanCancel(Simulation simulation, String routeCode) { - Route route = simulation.getRepository().getByCode(routeCode, Route.class); + @Override + public void forceUnlockRoute(Simulation simulation, String routeCode) { + Route route = simulation.getRepository().getByCode(routeCode, Route.class); + BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(route.isFleetMode(), + String.format("进路[%s]已开启自动通过进路,无法取消", route.debugStr())); + this.routeService.unlockRoute(simulation, route); + } + + @Override + public void humanCancel(Simulation simulation, String routeCode) { + Route route = simulation.getRepository().getByCode(routeCode, Route.class); // if (simulation.getRepository().getConfig().isRailway()) { // BusinessExceptionAssertEnum.OPERATION_FAIL.assertTrue(route.isApproachLock(), // "进路未接近锁闭,不能人解"); // } - this.routeService.delayUnlockStart(simulation, route, route.getStart()); - } + this.routeService.delayUnlockStart(simulation, route, route.getStart()); + } - @Override - public void sectionFaultUnlock(Simulation simulation, String sectionCode) { - Section section = simulation.getRepository().getByCode(sectionCode, Section.class); - if (simulation.getRepository().getConfig().isSFUCanOnlyApplyForFaultLockSection()) { - if (!section.isFaultLock()) - return; + @Override + public void sectionFaultUnlock(Simulation simulation, String sectionCode) { + Section section = simulation.getRepository().getByCode(sectionCode, Section.class); + if (simulation.getRepository().getConfig().isSFUCanOnlyApplyForFaultLockSection()) { + if (!section.isFaultLock()) { + return; } - if (section.isCross()) { - Optional
crossLockedSectionOptional = section.getLogicList().stream().filter(Section::isLocked).findAny(); - if (crossLockedSectionOptional.isEmpty()) { - return; - } + } + if (section.isCross()) { + Optional
crossLockedSectionOptional = section.getLogicList().stream() + .filter(Section::isLocked).findAny(); + if (crossLockedSectionOptional.isEmpty()) { + return; + } // BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(crossLockedSectionOptional.isPresent(), // section.debugStr() + "未锁闭,无需解锁"); - section = crossLockedSectionOptional.get(); - } - if (!section.isLocked()) { - return; - } + section = crossLockedSectionOptional.get(); + } + if (!section.isLocked()) { + return; + } // BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(section.isLocked(), // section.debugStr() + "未锁闭,无需解锁"); - List lockedRouteList = simulation.getRepository().queryAllLockedRoute(); - Route lockedRoute = null; - if (section.isRouteLock()) { - lockedRoute = section.getRoute(); - } else if (section.isOverlapLock()) { - for (Route route : lockedRouteList) { - if (route.overlapContainSection(section)) { - lockedRoute = route; - break; - } - } + List lockedRouteList = simulation.getRepository().queryAllLockedRoute(); + Route lockedRoute = null; + if (section.isRouteLock()) { + lockedRoute = section.getRoute(); + } else if (section.isOverlapLock()) { + for (Route route : lockedRouteList) { + if (route.overlapContainSection(section)) { + lockedRoute = route; + break; } - if (lockedRoute != null && lockedRoute.isDelayUnlocking()) { - throw BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.exception("进路延时解锁中,不能区故解"); + } + } + if (lockedRoute != null && lockedRoute.isDelayUnlocking()) { + throw BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.exception( + "进路延时解锁中,不能区故解"); + } + this.routeService.sectionFaultUnlock(simulation, section, lockedRoute); + } + + @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)) { + return; + } + List lockedRouteList = simulation.getRepository().queryAllLockedRoute(); + Set lockSwitchRoutes = new HashSet<>(); + if (aSwitch.isRouteLock()) { + lockSwitchRoutes = aSwitch.getRoutes(); + } else if (aSwitch.isOverlapLock()) { + for (Route route : lockedRouteList) { + if (route.overlapContainSwitch(aSwitch)) { + lockSwitchRoutes.add(route); + break; } - this.routeService.sectionFaultUnlock(simulation, section, lockedRoute); + } + } + if (!lockSwitchRoutes.isEmpty()) { + for (Route lockedRoute : lockSwitchRoutes) { + this.routeService.switchFaultUnlock(simulation, aSwitch, lockedRoute); + } + } else { + aSwitch.faultUnlock(); + aSwitch.sectionFaultUnlock(); + } + } + + @Override + public void cancelFleetRoute(Simulation simulation, String routeCode) { + Route route = simulation.getRepository().getByCode(routeCode, Route.class); + this.routeService.cancelFleet(route); + } + + @Override + public Route findLockedRouteByStartSignal(Simulation simulation, String signalCode) { + Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class); + return signal.getLockedRoute(); + } + + @Override + 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); + } + } + + @Override + 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); + } + } + + @Override + public void standHoldTrain(Simulation simulation, String standCode, boolean center) { + Stand stand = simulation.getRepository().getByCode(standCode, Stand.class); + this.standService.holdTrain(simulation, stand, center); + } + + @Override + public void sysHoldTrain(Simulation simulation, String standCode) { + Stand stand = simulation.getRepository().getByCode(standCode, Stand.class); + this.standService.sysHoldTrain(simulation, stand); + } + + @Override + public void standHoldTrainCancel(Simulation simulation, String standCode, boolean center) { + Stand stand = simulation.getRepository().getByCode(standCode, Stand.class); + this.standService.cancelHoldTrain(simulation, stand, center); + } + + @Override + public void sysHoldTrainCancel(Simulation simulation, String standCode) { + Stand stand = simulation.getRepository().getByCode(standCode, Stand.class); + this.standService.cancelSysHoldTrain(simulation, stand); + } + + @Override + public void ibpHoldTrain(Simulation simulation, String standCode) { + Stand stand = simulation.getRepository().getByCode(standCode, Stand.class); + this.standService.ibpHoldTrain(simulation, stand); + } + + @Override + public void ibpHoldTrainCancel(Simulation simulation, String standCode) { + Stand stand = simulation.getRepository().getByCode(standCode, Stand.class); + this.standService.cancelIbpHoldTrain(simulation, stand); + } + + @Override + public void standHoldTrainCancelAll(Simulation simulation, String standCode) { + Stand stand = simulation.getRepository().getByCode(standCode, Stand.class); + this.standService.cancelAllHoldTrain(simulation, stand); + } + + /** + * 办理引导 + */ + @Override + public void setGuide(Simulation simulation, String signalCode, String routeCode) { + SimulationDataRepository repository = simulation.getRepository(); + MapConfig config = repository.getConfig(); + Signal signal; + Route route = null; + if (StringUtils.hasText(signalCode)) { + signal = repository.getByCode(signalCode, Signal.class); + } else if (StringUtils.hasText(routeCode)) { + route = repository.getByCode(routeCode, Route.class); + signal = route.getStart(); + } else { + throw BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.exception( + "signalCode和routeCode不能都为空"); } - @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)) - return; - List lockedRouteList = simulation.getRepository().queryAllLockedRoute(); - Set lockSwitchRoutes = new HashSet<>(); - if (aSwitch.isRouteLock()) { - lockSwitchRoutes = aSwitch.getRoutes(); - } else if (aSwitch.isOverlapLock()) { - for (Route route : lockedRouteList) { - if (route.overlapContainSwitch(aSwitch)) { - lockSwitchRoutes.add(route); - break; - } - } - } - if (!lockSwitchRoutes.isEmpty()) { - for (Route lockedRoute : lockSwitchRoutes) { - this.routeService.switchFaultUnlock(simulation, aSwitch, lockedRoute); - } - } else { - aSwitch.faultUnlock(); - aSwitch.sectionFaultUnlock(); - } + if (route == null && signal.getRouteList().stream().anyMatch(Route::isAnySwitchMasterLock)) { + openGuideAspect4GuideMasterLock(simulation, signal); + return; + } else { + } - @Override - public void setFleetRoute(Simulation simulation, String routeCode) { - Route route = simulation.getRepository().getByCode(routeCode, Route.class); - this.routeService.setFleet(route); + boolean firstCheck = config.isGuideNeedRouteSettingFirst(); + //条件检查 + if (firstCheck) { + List routeList = signal.getRouteList(); + 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())); + } else { + BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotNull(signal.getLockedRoute(), + String.format("信号机[%s]无已办理进路", signal.getCode())); + } } - - @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); - return signal.getLockedRoute(); - } - - @Override - public Route findRouteByStartAndEndSignal(Simulation simulation, String startSignalCode, String endSignalCode) { - Signal start = simulation.getRepository().getByCode(startSignalCode, Signal.class); - List 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) { - Stand stand = simulation.getRepository().getByCode(standCode, Stand.class); - if (Objects.nonNull(stand.getPsd())) { - standService.openScreenDoor(simulation, stand, source); - } - } - - @Override - 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); - } - } - - @Override - public void standHoldTrain(Simulation simulation, String standCode, boolean center) { - Stand stand = simulation.getRepository().getByCode(standCode, Stand.class); - this.standService.holdTrain(simulation, stand, center); - } - - @Override - public void sysHoldTrain(Simulation simulation, String standCode) { - Stand stand = simulation.getRepository().getByCode(standCode, Stand.class); - this.standService.sysHoldTrain(simulation, stand); - } - - @Override - public void standHoldTrainCancel(Simulation simulation, String standCode, boolean center) { - Stand stand = simulation.getRepository().getByCode(standCode, Stand.class); - this.standService.cancelHoldTrain(simulation, stand, center); - } - - @Override - public void sysHoldTrainCancel(Simulation simulation, String standCode) { - Stand stand = simulation.getRepository().getByCode(standCode, Stand.class); - this.standService.cancelSysHoldTrain(simulation, stand); - } - - @Override - public void ibpHoldTrain(Simulation simulation, String standCode) { - Stand stand = simulation.getRepository().getByCode(standCode, Stand.class); - this.standService.ibpHoldTrain(simulation, stand); - } - - @Override - public void ibpHoldTrainCancel(Simulation simulation, String standCode) { - Stand stand = simulation.getRepository().getByCode(standCode, Stand.class); - this.standService.cancelIbpHoldTrain(simulation, stand); - } - - @Override - public void standHoldTrainCancelAll(Simulation simulation, String standCode) { - Stand stand = simulation.getRepository().getByCode(standCode, Stand.class); - this.standService.cancelAllHoldTrain(simulation, stand); - } - - /** - * 办理引导 - */ - @Override - public void setGuide(Simulation simulation, String signalCode, String routeCode) { - SimulationDataRepository repository = simulation.getRepository(); - MapConfig config = repository.getConfig(); - Signal signal; - Route route = null; - if (StringUtils.hasText(signalCode)) { - signal = repository.getByCode(signalCode, Signal.class); - } else if (StringUtils.hasText(routeCode)) { - route = repository.getByCode(routeCode, Route.class); - signal = route.getStart(); - } else { - throw BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.exception("signalCode和routeCode不能都为空"); - } - - if (route == null && signal.getRouteList().stream().anyMatch(Route::isAnySwitchMasterLock)) { - openGuideAspect4GuideMasterLock(simulation, signal); - return; - } else { - - } - - boolean firstCheck = config.isGuideNeedRouteSettingFirst(); - //条件检查 - if (firstCheck) { - List routeList = signal.getRouteList(); - 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())); - } else { - BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotNull(signal.getLockedRoute(), String.format("信号机[%s]无已办理进路", signal.getCode())); - } - } // if (config.isSomeCommandNeedInit()) { // BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(signal.isInit(), signal.debugStr() + "未初始化"); // } @@ -441,381 +441,413 @@ public class CiApiServiceImpl2 implements CiApiService { // BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(signal.isDefaultAspect(), // String.format("信号机[%s]需处于关闭状态", signal.getCode())); // } - if (config.isNeedApproachLockBeforeSetGuide()) { - boolean signalApproachOccupied = signal.getApproachPathList() - .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()); + if (config.isNeedApproachLockBeforeSetGuide()) { + boolean signalApproachOccupied = signal.getApproachPathList() + .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()); + } else { + if (route != null) { + if (route.isLock()) { + this.signalService.tryControlSignalAspectAccordingLevel(simulation, signal, + signal.getSignalModel().getGuideAspect()); } else { - if (route != null) { - if (route.isLock()) { - 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()); - } else if (!CollectionUtils.isEmpty(signal.getRouteList())) { - List collect; - if (config.isRailway()) { // 大铁配置引导进路 - collect = signal.getRouteList().stream() - .filter(Route::isTrainRoute) - .filter(route1 -> route1.isAllSwitchIsOnPos() || route1.isAnySwitchMasterLock()) - .collect(Collectors.toList()); - BusinessExceptionAssertEnum.OPERATION_FAIL.assertCollectionNotEmpty(collect, - signal.debugStr() + "无符合条件的进路"); - } else { //如果signal锁闭进路为null,筛选最合适的进路(直线进路>分叉进路>折返进路) - collect = signal.getRouteList().stream() - .filter(r -> !r.isTurnBack() && CollectionUtils.isEmpty(r.getSwitchList())) - .collect(Collectors.toList()); - } - if (CollectionUtils.isEmpty(collect)) { - collect = signal.getRouteList().stream().filter(r -> !r.isTurnBack()).collect(Collectors.toList()); - } - if (CollectionUtils.isEmpty(collect)) { - collect = signal.getRouteList(); - } - route = collect.get(0); - this.routeService.setGuide(simulation, route); - } else { //如果信号机没有关联进路 - this.signalService.tryControlSignalAspectAccordingLevel(simulation, signal, signal.getSignalModel().getGuideAspect()); - } - } + this.routeService.setGuide(simulation, route); } - if (signal.getGuideRemain() > 0) { + } else { + if (signal.getLockedRoute() != null) { //如果有已锁闭进路 + this.signalService.tryControlSignalAspectAccordingLevel(simulation, signal, + signal.getSignalModel().getGuideAspect()); + } else if (!CollectionUtils.isEmpty(signal.getRouteList())) { + List collect; + if (config.isRailway()) { // 大铁配置引导进路 + collect = signal.getRouteList().stream() + .filter(Route::isTrainRoute) + .filter(route1 -> route1.isAllSwitchIsOnPos() || route1.isAnySwitchMasterLock()) + .collect(Collectors.toList()); + BusinessExceptionAssertEnum.OPERATION_FAIL.assertCollectionNotEmpty(collect, + signal.debugStr() + "无符合条件的进路"); + } else { //如果signal锁闭进路为null,筛选最合适的进路(直线进路>分叉进路>折返进路) + collect = signal.getRouteList().stream() + .filter(r -> !r.isTurnBack() && CollectionUtils.isEmpty(r.getSwitchList())) + .collect(Collectors.toList()); + } + if (CollectionUtils.isEmpty(collect)) { + collect = signal.getRouteList().stream().filter(r -> !r.isTurnBack()) + .collect(Collectors.toList()); + } + if (CollectionUtils.isEmpty(collect)) { + collect = signal.getRouteList(); + } + route = collect.get(0); + this.routeService.setGuide(simulation, route); + } else { //如果信号机没有关联进路 + this.signalService.tryControlSignalAspectAccordingLevel(simulation, signal, + signal.getSignalModel().getGuideAspect()); + } + } + } + if (signal.getGuideRemain() > 0) { // Route lockedRoute = signal.getLockedRoute(); // if (lockedRoute != null && lockedRoute.getFirstLogicSection().isOccupied() && signal.isGuideAspect()) { // signal.guideDelayStart(); // } - signal.setGuideRemain(0); + signal.setGuideRemain(0); + } else { + signal.guideDelayStart(); + } + } + + /** + * 在引导总锁的状态下开放引导信号。 引导总锁之后 + */ + private void openGuideAspect4GuideMasterLock(Simulation simulation, Signal signal) { + signalService.controlSignalAspect(simulation, signal, signal.getGuideAspect()); + } + + + @Override + public void setEst(Simulation simulation, ESP esp) { + esp.update(true); + } + + @Override + public void cancelEst(Simulation simulation, ESP esp) { + esp.update(false); + } + + @Override + public void restart(Simulation simulation, Station station) { + Station deviceStation; + if (station.isCentralized()) { + deviceStation = station; + } else { + deviceStation = station.getDeviceStation(); + } + deviceStation.setInterlockMachineStarting(false); + SimulationDataRepository repository = simulation.getRepository(); + repository.getSectionList().forEach(section -> section.setFaultLock(false)); //所有区段取消故障锁闭 + } + + @Override + public void release(Simulation simulation, Station station) { + for (Section section : simulation.getRepository().getSectionList()) { + Integer speedLimitBeforeFault = section.getSpeedLimitBeforeFault(); + if (speedLimitBeforeFault != null) { + section.setSpeedUpLimit(speedLimitBeforeFault); + section.setSpeedLimitBeforeFault(null); + } + } + Server server = simulation.getRepository().getByCode(Server.CODE, Server.class); + Server.Fault.ATP_FAULT.fix(server); + } + + @Override + public void powerOnUnlock(Simulation simulation, Station station) { + if (!station.isCentralized()) { + station = station.getDeviceStation(); + } + Station deviceStation = station; + boolean restartFlag = + Objects.nonNull(deviceStation.getRestartTime()) && deviceStation.getRestartTime() + .isBefore(simulation.getCorrectSystemTime().toLocalTime()); + // 是否大铁设备 + boolean hasCTCFlag = simulation.getRepository().getConfig().isRailway(); + // 大铁异常提示语 + String exceptionMsg = + hasCTCFlag ? "无效操作:车站未下电" : "无效操作或连锁机重启过8分钟需手动解锁"; + // 是否需要重启 + if (restartFlag) { + // 考试、课程上电标识 + 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
sections = simulation.getRepository().getSectionList(); + sections.stream() + .filter(section -> Objects.equals(section.getDeviceStation(), deviceStation)) + .forEach(Section::faultUnlock); + return; + } + } + throw BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.exception(exceptionMsg); + } + + @Override + public void standEC(Simulation simulation, Stand stand) { + if (stand.getEsp() == null) { + return; + } + stand.getEsp().update(true); + } + + @Override + public void cancelStandEC(Simulation simulation, Stand stand) { + 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(), + String.format("对%s强行转岔操作被联锁逻辑取消", aSwitch.getName())); + BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(!aSwitch.isLocked(), + String.format("道岔[%s]锁闭,无法转动", aSwitch.getCode())); + return this.switchService.forceTurn(simulation, aSwitch); + } + + @Override + public void axlePreReset(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(), + section.debugStr() + "不是计轴区段也不归属于任何计轴区段"); + VirtualRealitySectionAxleCounter virtualAxleCounter = axleSection.getVirtualAxleCounter(); + if (!virtualAxleCounter.isOccupy()) { + VirtualRealitySectionAxleCounter.Fault.FAULT.apply(virtualAxleCounter); + Section.AxleFault.ARB.apply(axleSection); + } + virtualAxleCounter.preReset(); + } + + @Override + public void switchAxlePreReset(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + aSwitch.setPreReset(true); + } + + @Override + public void switchSqueezeRecovery(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + Switch.SwitchFault.SQUEEZE.fix(aSwitch); + } + + @Override + 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(), + "道岔未处于人工模式"); + if (normal) { + switchService.turn2NormalPosition(simulation, aSwitch); } else { - signal.guideDelayStart(); + switchService.turn2ReversePosition(simulation, aSwitch); } + } } - - /** - * 在引导总锁的状态下开放引导信号。 - * 引导总锁之后 - */ - private void openGuideAspect4GuideMasterLock(Simulation simulation, Signal signal) { - signalService.controlSignalAspect(simulation, signal, signal.getGuideAspect()); + if (reserve != null) { + aSwitch.setDispatcherReserve(reserve); } + } + @Override + public void initializeBlock(Simulation simulation, String switchCode) { + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + aSwitch.setInit(true); + } - @Override - public void setEst(Simulation simulation, ESP esp) { - esp.update(true); + @Override + public void initializeGuide(Simulation simulation, String signalCode) { + Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class); + signal.setInit(true); + } + + @Override + public void cancelGuideInitialization(Simulation simulation, String signalCode) { + Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class); + signal.setInit(false); + } + + @Override + public void axleReset(Simulation simulation, String sectionCode) { + VirtualRealitySectionAxleCounter axle = getAxleCounterAndCheck4Reset(simulation, sectionCode); + if (!axle.isOccupy()) { + return; + } + axle.axleReset(); + } + + @Override + public void setOverlap(Simulation simulation, String signalCode, String overlapCode) { + SimulationDataRepository repository = simulation.getRepository(); + Signal signal = repository.getByCode(signalCode, Signal.class); + RouteOverlap overlap = repository.getByCode(overlapCode, RouteOverlap.class); + this.routeService.setOverlap(simulation, overlap); + } + + @Override + public void setOrCancelInterlockRelease(Simulation simulation, Stand stand, boolean release) { + standService.setOrCancelInterlockRelease(stand, release); + } + + @Override + public void switchMasterLock(Simulation simulation, String stationCode, Station.Throat throat) { + SimulationDataRepository repository = simulation.getRepository(); + Station station = repository.getByCode(stationCode, Station.class); + station.getDeviceMap().values().stream() + .filter(device -> device instanceof Switch) + .map(device -> (Switch) device) + .filter(aSwitch -> throat.equals(aSwitch.getThroat())) + .forEach(aSwitch -> { + aSwitch.setGuideMasterLock(true); + }); + switch (throat) { + case S: + station.setSGuideMasterLock(true); + break; + case X: + station.setXGuideMasterLock(true); + break; + default: + throw new IllegalStateException("Unexpected value: " + throat); } + } - @Override - public void cancelEst(Simulation simulation, ESP esp) { - esp.update(false); + @Override + public void switchMasterUnlock(Simulation simulation, String stationCode, Station.Throat throat) { + SimulationDataRepository repository = simulation.getRepository(); + Station station = repository.getByCode(stationCode, Station.class); + station.getDeviceMap().values().stream() + .filter(device -> device instanceof Switch) + .map(device -> (Switch) device) + .filter(aSwitch -> throat.equals(aSwitch.getThroat())) + .forEach(aSwitch -> aSwitch.setGuideMasterLock(false)); + switch (throat) { + case S: + station.setSGuideMasterLock(false); + break; + case X: + station.setXGuideMasterLock(false); + break; + default: + throw new IllegalStateException("Unexpected value: " + throat); } + } - @Override - public void restart(Simulation simulation, Station station) { - Station deviceStation; - if (station.isCentralized()) { - deviceStation = station; - } else { - deviceStation = station.getDeviceStation(); - } - deviceStation.setInterlockMachineStarting(false); - SimulationDataRepository repository = simulation.getRepository(); - repository.getSectionList().forEach(section -> section.setFaultLock(false)); //所有区段取消故障锁闭 + @Override + public void signalTurnOn(Simulation simulation, String signalCode) { + SimulationDataRepository repository = simulation.getRepository(); + Signal signal = repository.getByCode(signalCode, Signal.class); + BusinessExceptionAssertEnum.OPERATION_FAIL.assertNull(signal.getLockedRoute(), + "信号机有锁闭进路,禁止点灯"); + VirtualRealitySignal vrSignal = signal.getVirtualSignal(); + 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(), + "信号机有锁闭进路,禁止灭灯"); + VirtualRealitySignal vrSignal = signal.getVirtualSignal(); + BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotNull(vrSignal, + signal.debugStr() + "无实体信号机"); + virtualRealityDeviceService.control(simulation, vrSignal, SignalAspect.No); + } + + /** + * 获取计轴器并为预复位/复位操作检查设备状态 + */ + 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(), + 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() + "需处于预复位状态"); } + return virtualAxleCounter; + } - @Override - public void release(Simulation simulation, Station station) { - for (Section section : simulation.getRepository().getSectionList()) { - Integer speedLimitBeforeFault = section.getSpeedLimitBeforeFault(); - if (speedLimitBeforeFault != null) { - section.setSpeedUpLimit(speedLimitBeforeFault); - section.setSpeedLimitBeforeFault(null); - } - } - Server server = simulation.getRepository().getByCode(Server.CODE, Server.class); - Server.Fault.ATP_FAULT.fix(server); - } - - @Override - public void powerOnUnlock(Simulation simulation, Station station) { - if (!station.isCentralized()) { - station = station.getDeviceStation(); - } - Station deviceStation = station; - boolean restartFlag = Objects.nonNull(deviceStation.getRestartTime()) && deviceStation.getRestartTime().isBefore(simulation.getCorrectSystemTime().toLocalTime()); - // 是否大铁设备 - boolean hasCTCFlag = simulation.getRepository().getConfig().isRailway(); - // 大铁异常提示语 - String exceptionMsg = hasCTCFlag ? "无效操作:车站未下电" : "无效操作或连锁机重启过8分钟需手动解锁"; - // 是否需要重启 - if (restartFlag) { - // 考试、课程上电标识 - 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
sections = simulation.getRepository().getSectionList(); - sections.stream().filter(section -> Objects.equals(section.getDeviceStation(), deviceStation)).forEach(Section::faultUnlock); - return; - } - } - throw BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.exception(exceptionMsg); - } - - @Override - public void standEC(Simulation simulation, Stand stand) { - if (stand.getEsp() == null) - return; - stand.getEsp().update(true); - } - - @Override - public void cancelStandEC(Simulation simulation, Stand stand) { - 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(), - String.format("对%s强行转岔操作被联锁逻辑取消", aSwitch.getName())); - BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(!aSwitch.isLocked(), String.format("道岔[%s]锁闭,无法转动", aSwitch.getCode())); - return this.switchService.forceTurn(simulation, aSwitch); - } - - @Override - public void axlePreReset(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(), - section.debugStr() + "不是计轴区段也不归属于任何计轴区段"); - VirtualRealitySectionAxleCounter virtualAxleCounter = axleSection.getVirtualAxleCounter(); - if (!virtualAxleCounter.isOccupy()) { - VirtualRealitySectionAxleCounter.Fault.FAULT.apply(virtualAxleCounter); - Section.AxleFault.ARB.apply(axleSection); - } - virtualAxleCounter.preReset(); - } - - @Override - public void switchAxlePreReset(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - aSwitch.setPreReset(true); - } - - @Override - public void switchSqueezeRecovery(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - Switch.SwitchFault.SQUEEZE.fix(aSwitch); - } - - @Override - 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(), "道岔未处于人工模式"); - if (normal) { - switchService.turn2NormalPosition(simulation, aSwitch); - } else { - switchService.turn2ReversePosition(simulation, aSwitch); - } - } - } - if (reserve != null) { - aSwitch.setDispatcherReserve(reserve); - } - } - - @Override - public void initializeBlock(Simulation simulation, String switchCode) { - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - aSwitch.setInit(true); - } - - @Override - public void initializeGuide(Simulation simulation, String signalCode) { - Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class); - signal.setInit(true); - } - - @Override - public void cancelGuideInitialization(Simulation simulation, String signalCode) { - Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class); - signal.setInit(false); - } - - @Override - public void axleReset(Simulation simulation, String sectionCode) { - VirtualRealitySectionAxleCounter axle = getAxleCounterAndCheck4Reset(simulation, sectionCode); - if (!axle.isOccupy()) - return; - axle.axleReset(); - } - - @Override - public void setOverlap(Simulation simulation, String signalCode, String overlapCode) { - SimulationDataRepository repository = simulation.getRepository(); - Signal signal = repository.getByCode(signalCode, Signal.class); - RouteOverlap overlap = repository.getByCode(overlapCode, RouteOverlap.class); - this.routeService.setOverlap(simulation, overlap); - } - - @Override - public void setOrCancelInterlockRelease(Simulation simulation, Stand stand, boolean release) { - standService.setOrCancelInterlockRelease(stand, release); - } - - @Override - public void switchMasterLock(Simulation simulation, String stationCode, Station.Throat throat) { - SimulationDataRepository repository = simulation.getRepository(); - Station station = repository.getByCode(stationCode, Station.class); - station.getDeviceMap().values().stream() - .filter(device -> device instanceof Switch) - .map(device -> (Switch) device) - .filter(aSwitch -> throat.equals(aSwitch.getThroat())) - .forEach(aSwitch -> { - aSwitch.setGuideMasterLock(true); - }); - switch (throat) { - case S: - station.setSGuideMasterLock(true); - break; - case X: - station.setXGuideMasterLock(true); - break; - default: - throw new IllegalStateException("Unexpected value: " + throat); - } - } - - @Override - public void switchMasterUnlock(Simulation simulation, String stationCode, Station.Throat throat) { - SimulationDataRepository repository = simulation.getRepository(); - Station station = repository.getByCode(stationCode, Station.class); - station.getDeviceMap().values().stream() - .filter(device -> device instanceof Switch) - .map(device -> (Switch) device) - .filter(aSwitch -> throat.equals(aSwitch.getThroat())) - .forEach(aSwitch -> aSwitch.setGuideMasterLock(false)); - switch (throat) { - case S: - station.setSGuideMasterLock(false); - break; - case X: - station.setXGuideMasterLock(false); - break; - default: - throw new IllegalStateException("Unexpected value: " + throat); - } - } - - @Override - public void signalTurnOn(Simulation simulation, String signalCode) { - SimulationDataRepository repository = simulation.getRepository(); - Signal signal = repository.getByCode(signalCode, Signal.class); - BusinessExceptionAssertEnum.OPERATION_FAIL.assertNull(signal.getLockedRoute(), "信号机有锁闭进路,禁止点灯"); - VirtualRealitySignal vrSignal = signal.getVirtualSignal(); - 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(), "信号机有锁闭进路,禁止灭灯"); - VirtualRealitySignal vrSignal = signal.getVirtualSignal(); - BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotNull(vrSignal, signal.debugStr() + "无实体信号机"); - virtualRealityDeviceService.control(simulation, vrSignal, SignalAspect.No); - } - - /** - * 获取计轴器并为预复位/复位操作检查设备状态 - */ - 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(), - 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() + "需处于预复位状态"); - } - return virtualAxleCounter; - } - - /** - * 大铁、办理引导时获取进路列表 - * - * @param repository 仿真实体 - * @param signal 信号机 - */ - private List getCtcGuideRouteList(SimulationDataRepository repository, Signal signal) { - // 获取以信号机开头的进路集合 - List routeList = repository.getRouteList().stream() - .filter(routePojo -> routePojo.isTrainRoute() && routePojo.getStart().getCode().equals(signal.getCode())) - .collect(Collectors.toList()); - // 进路走向 - boolean isRight = routeList.stream().anyMatch(Route::isRight); - // 终端信号机类型,信号机类型匹配时停止循环 - List endTypeList = Signal.SignalType.SHUNTING2.equals(signal.getType()) ? - Arrays.asList(Signal.SignalType.RECEIVING, Signal.SignalType.DEPARTURE) : Arrays.asList(Signal.SignalType.SHUNTING2); - // 终止索引,最多循环20次,防止死循环 - int endIndex = 0; - Section nextSection = signal.getSection(); - Signal endSignal; // 终端信号机 - do { - if (nextSection.isSwitchTrack()) { // 如果是计轴区段 - nextSection = nextSection.getNextRunningSectionOf(isRight); - } else { // 下一区段 - nextSection = nextSection.getNextSection(isRight); - } - if (nextSection == null) { // 道岔不连续不能办理进路,直接返回结果 - log.error("进路不连续"); - return null; - } - // 获取信号机 - if (isRight) { - endSignal = nextSection.getSignalToLeft(); - } else { - endSignal = nextSection.getSignalToRight(); - } - endIndex++; - } while (endIndex < 20 && !(endSignal != null && endTypeList.contains(endSignal.getType()))); - - // 过滤符合条件的进路 - if (endSignal != null && endIndex < 20) { - String endSignalCode = endSignal.getCode(); - routeList = routeList.stream() - .filter(routePojo -> routePojo.getDestination().getCode().equals(endSignalCode)) - .collect(Collectors.toList()); - } else { - // 如果是超过第限制停下,获取第endIndex个元素对比 - String routeSectionCode = nextSection.getCode(); - final int sectionIndex = endIndex; - routeList = routeList.stream() - .filter(routePojo -> routePojo.getSectionList().size() >= sectionIndex - && routePojo.getSectionList().get(sectionIndex).getCode().equals(routeSectionCode)) - .collect(Collectors.toList()); - } - return routeList; + /** + * 大铁、办理引导时获取进路列表 + * + * @param repository 仿真实体 + * @param signal 信号机 + */ + private List getCtcGuideRouteList(SimulationDataRepository repository, Signal signal) { + // 获取以信号机开头的进路集合 + List routeList = repository.getRouteList().stream() + .filter(routePojo -> routePojo.isTrainRoute() && routePojo.getStart().getCode() + .equals(signal.getCode())) + .collect(Collectors.toList()); + // 进路走向 + boolean isRight = routeList.stream().anyMatch(Route::isRight); + // 终端信号机类型,信号机类型匹配时停止循环 + List endTypeList = Signal.SignalType.SHUNTING2.equals(signal.getType()) ? + Arrays.asList(Signal.SignalType.RECEIVING, Signal.SignalType.DEPARTURE) + : Arrays.asList(Signal.SignalType.SHUNTING2); + // 终止索引,最多循环20次,防止死循环 + int endIndex = 0; + Section nextSection = signal.getSection(); + Signal endSignal; // 终端信号机 + do { + if (nextSection.isSwitchTrack()) { // 如果是计轴区段 + nextSection = nextSection.getNextRunningSectionOf(isRight); + } else { // 下一区段 + nextSection = nextSection.getNextSection(isRight); + } + if (nextSection == null) { // 道岔不连续不能办理进路,直接返回结果 + log.error("进路不连续"); + return null; + } + // 获取信号机 + if (isRight) { + endSignal = nextSection.getSignalToLeft(); + } else { + endSignal = nextSection.getSignalToRight(); + } + endIndex++; + } while (endIndex < 20 && !(endSignal != null && endTypeList.contains(endSignal.getType()))); + + // 过滤符合条件的进路 + if (endSignal != null && endIndex < 20) { + String endSignalCode = endSignal.getCode(); + routeList = routeList.stream() + .filter(routePojo -> routePojo.getDestination().getCode().equals(endSignalCode)) + .collect(Collectors.toList()); + } else { + // 如果是超过第限制停下,获取第endIndex个元素对比 + String routeSectionCode = nextSection.getCode(); + final int sectionIndex = endIndex; + routeList = routeList.stream() + .filter(routePojo -> routePojo.getSectionList().size() >= sectionIndex + && routePojo.getSectionList().get(sectionIndex).getCode().equals(routeSectionCode)) + .collect(Collectors.toList()); } + return routeList; + } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/CI/device/CiRouteService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/CI/device/CiRouteService.java index acf695d5e..97285b05b 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/CI/device/CiRouteService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/CI/device/CiRouteService.java @@ -1,364 +1,391 @@ 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 - private CiSignalControlService signalControlService; - @Autowired - private CiService ciService; - /** - * 进路排列检查 - * @param guide 是引导进路? - * @return - */ - 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); - if (checkFailMessage != null) { - return checkFailMessage; - } + @Autowired + private CiSwitchControlService switchControlService; + @Autowired + private CiSignalControlService signalControlService; + @Autowired + private CiService ciService; + + /** + * 进路排列检查 + * + * @param guide 是引导进路? + * @return + */ + 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); + if (checkFailMessage != null) { + return checkFailMessage; + } + } + } else { + MapConfig config = simulation.getRepository().getConfig(); + Signal start = route.getStart(); + if (!config.isSignalBlockRouteSettable()) { + // 信号封锁,不能办理 + if (start.isBlockade()) { + return new Route.CheckFailMessage(Route.CheckFailReason.StartSignalBlockade, start); + } + } + // 进路中道岔没有被征用或锁定在相反位置 + Route.CheckFailMessage failMessage = setSwitchCheck(simulation, route.getSwitchList(), guide); + if (failMessage != null) { + return failMessage; + } + // 进路中道岔是否存在和监控中进路延续保护冲突 + failMessage = monitorRouteOverlapConflictCheck(simulation, route); + if (failMessage != null) { + return failMessage; + } + // 进路内区段封锁/锁闭方向检查||单列车进路区段占用 + List
sectionList = route.getSectionList(); + for (Section section : sectionList) { + // 封锁状态 + if (section.isBlockade()) { + return new Route.CheckFailMessage(Route.CheckFailReason.SectionBlockade, section); + } else if (!CollectionUtils.isEmpty(section.getLogicList())) { + for (Section logicSection : section.getLogicList()) { + if (logicSection.isBlockade()) { + return new Route.CheckFailMessage(Route.CheckFailReason.SectionBlockade, + logicSection); } - } else { - MapConfig config = simulation.getRepository().getConfig(); - Signal start = route.getStart(); - if (!config.isSignalBlockRouteSettable()) { - // 信号封锁,不能办理 - if (start.isBlockade()) { - return new Route.CheckFailMessage(Route.CheckFailReason.StartSignalBlockade, start); - } + } + } else if (section.getParent() != null) { + if (section.getParent().isCross() && section.getParent().isBlockade()) { + return new Route.CheckFailMessage(Route.CheckFailReason.SectionBlockade, section); + } + } + // 进路内区段锁闭方向不是此进路方向 + if ((section.isRouteLock() || section.isOverlapLock()) && + !Objects.equals(section.isLockRight(), start.isRight())) { + return new Route.CheckFailMessage(Route.CheckFailReason.SectionLockOppositeDirection, + section); + } + //单列车进路区段占用 + if (section.isOccupied() && route.isSingleTrain()) { + return new Route.CheckFailMessage(Route.CheckFailReason.SectionNotFree, section); + } + // 故障占用 + for (int i = 0; i < 3; i++) { + if (section.getParent() == null || section.isAxleCounter()) { + break; } - // 进路中道岔没有被征用或锁定在相反位置 - Route.CheckFailMessage failMessage = setSwitchCheck(simulation, route.getSwitchList(), guide); - if (failMessage != null) { - return failMessage; - } - // 进路中道岔是否存在和监控中进路延续保护冲突 - failMessage = monitorRouteOverlapConflictCheck(simulation, route); - if (failMessage != null) { - return failMessage; - } - // 进路内区段封锁/锁闭方向检查||单列车进路区段占用 - List
sectionList = route.getSectionList(); - for (Section section : sectionList) { - // 封锁状态 - if (section.isBlockade()) { - return new Route.CheckFailMessage(Route.CheckFailReason.SectionBlockade, section); - } else if (!CollectionUtils.isEmpty(section.getLogicList())) { - for (Section logicSection : section.getLogicList()) { - if (logicSection.isBlockade()) { - return new Route.CheckFailMessage(Route.CheckFailReason.SectionBlockade, logicSection); - } - } - } else if (section.getParent() != null) { - if (section.getParent().isCross() && section.getParent().isBlockade()) { - return new Route.CheckFailMessage(Route.CheckFailReason.SectionBlockade, section); - } - } - // 进路内区段锁闭方向不是此进路方向 - if ((section.isRouteLock() || section.isOverlapLock()) && - !Objects.equals(section.isLockRight(), start.isRight())) { - return new Route.CheckFailMessage(Route.CheckFailReason.SectionLockOppositeDirection, section); - } - //单列车进路区段占用 - if (section.isOccupied() && route.isSingleTrain()) { - return new Route.CheckFailMessage(Route.CheckFailReason.SectionNotFree, section); - } - // 故障占用 - for (int i = 0; i < 3; i++) { - if (section.getParent() == null || section.isAxleCounter()) - break; - section = section.getParent(); - } + section = section.getParent(); + } // if (Section.AxleFault.FAULT.equals(section.getFault())) { // return new Route.CheckFailMessage(Route.CheckFailReason.SectionFaultOccupied, section); // } - } - //敌对进路 - List conflictingRouteList = route.getConflictingRouteList(); - for (Route conflict : conflictingRouteList) { - if (conflict.isSetting() || conflict.isLock()) { - return new Route.CheckFailMessage(Route.CheckFailReason.ConflictingRouteSetting, conflict); - } - } - if (start.isCbtcMode()) { - // CBTC办理检查 + } + //敌对进路 + List conflictingRouteList = route.getConflictingRouteList(); + for (Route conflict : conflictingRouteList) { + if (conflict.isSetting() || conflict.isLock()) { + return new Route.CheckFailMessage(Route.CheckFailReason.ConflictingRouteSetting, + conflict); + } + } + if (start.isCbtcMode()) { + // CBTC办理检查 // Section firstLogicSection = route.getFirstLogicSection(); // if (firstLogicSection.isOccupied()) { // return new Route.CheckFailMessage(Route.CheckFailReason.SectionNotFree, firstLogicSection); // } - } else { - // 后备办理检查 - // 区段占用 - for (Section section : sectionList) { - if (section.isOccupied()) { - return new Route.CheckFailMessage(Route.CheckFailReason.SectionNotFree, section); - } - } - // 延续保护检查 - RouteOverlap overlap = route.getOverlap(); - if (Objects.nonNull(overlap)) { - SectionPath sectionPath = overlap.selectPath(); - failMessage = setSwitchCheck(simulation, sectionPath.getSwitchList(), guide); - } - } - return failMessage; + } else { + // 后备办理检查 + // 区段占用 + for (Section section : sectionList) { + if (section.isOccupied()) { + return new Route.CheckFailMessage(Route.CheckFailReason.SectionNotFree, section); + } } + // 延续保护检查 + RouteOverlap overlap = route.getOverlap(); + if (Objects.nonNull(overlap)) { + SectionPath sectionPath = overlap.selectPath(); + failMessage = setSwitchCheck(simulation, sectionPath.getSwitchList(), guide); + } + } + return failMessage; + } + return null; + } + + private static Route.CheckFailMessage monitorRouteOverlapConflictCheck(Simulation simulation, + Route route) { + SimulationDataRepository repository = simulation.getRepository(); + List settingRoutes = repository.getSettingRoutes(); + for (Route sr : settingRoutes) { + 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)) { + return new Route.CheckFailMessage(Route.CheckFailReason.SwitchCiUseOnOppositePosition, + switchElement.getASwitch()); + } + } + } + } + return null; + } + + private static Route.CheckFailMessage setSwitchCheck(Simulation simulation, + List switchList, boolean guide) { + if (switchList != null) { + for (SwitchElement switchElement : switchList) { + Switch aSwitch = switchElement.getASwitch(); + if (aSwitch.isBlockade()) { // 道岔封锁 + return new Route.CheckFailMessage(Route.CheckFailReason.SwitchBlockade, aSwitch); + } + if (!guide && aSwitch.isGuideMasterLock()) { + return new Route.CheckFailMessage(Route.CheckFailReason.SwitchGuideMasterLock, aSwitch); + } + if ((aSwitch.isLocked() || aSwitch.isSectionOccupied()) && + aSwitch.getPos().equals(SwitchIndication.of(!switchElement.isNormal()))) {//道岔锁闭或占用在相反位置 + return new Route.CheckFailMessage(Route.CheckFailReason.SwitchLockPositionError, aSwitch); + } + if (aSwitch.isCiUseOnOppositePosition(switchElement.isNormal())) { // 道岔征用在相反位置 + return new Route.CheckFailMessage(Route.CheckFailReason.SwitchCiUseOnOppositePosition, + aSwitch); + } + //道岔失表时,进路中的区段和道岔由远及近锁闭,直到失表的道岔处 -南铁院叶老师 + if (simulation.getRepository().getConfig().isRouteCanSetWhenSwitchFault()) { + continue; + } + // 非预先锁闭,道岔相应位置失表则不排进路 + 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())) { + return new Route.CheckFailMessage(Route.CheckFailReason.SwitchFault, aSwitch); + } + } + } + } + return null; + } + + /** + * 排列引导进路 + */ + public void setGuide(Simulation simulation, Route route) { + // 进路检查 + Route.CheckFailMessage failMessage = routeSetCheck(simulation, route, true); + if (failMessage == null) { + if (route.isLock() && !route.isFleetMode()) { + log.info("进路[{}]已经锁闭", route.debugStr()); + return; + } + // + route.setSettedAspect(route.getStart().getGuideAspect()); + // 引导进路开始办理 + LocalDateTime systemTime = simulation.getSystemTime(); + route.startGuideSetting(systemTime); + // 道岔征用 + for (SwitchElement switchElement : route.getSwitchList()) { + switchElement.getASwitch().ciUse(switchElement.isNormal()); + } + simulation.getRepository().addSettingRoute(route); + } + if (Objects.nonNull(failMessage)) { + log.info(String.format("进路[%s]排列检查失败,无法排列:%s", route.debugStr(), + failMessage.debugStr())); + } + } + + /** + * 排列进路 + * + * @param simulation + * @param route + * @return + */ + 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()) { + log.info("进路[{}]已经锁闭", route.debugStr()); return null; + } + // 设置根据进路性质开放的信号 + route.setSettedAspect(settedAspect); + // 进路开始办理 + LocalDateTime systemTime = simulation.getSystemTime(); + route.startSetting(systemTime); + // 道岔征用 + for (SwitchElement switchElement : route.getSwitchList()) { + switchElement.getASwitch().ciUse(switchElement.isNormal()); + } + if (!simulation.getRepository().getConfig().isOverlapSettingByTrigger()) { + // 延续保护进路办理 + this.ciService.checkAndTrySettingOverlap(simulation, route.getOverlap()); + } + simulation.getRepository().addSettingRoute(route); } - - private static Route.CheckFailMessage monitorRouteOverlapConflictCheck(Simulation simulation, Route route) { - SimulationDataRepository repository = simulation.getRepository(); - List settingRoutes = repository.getSettingRoutes(); - for (Route sr : settingRoutes) { - 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)) { - return new Route.CheckFailMessage(Route.CheckFailReason.SwitchCiUseOnOppositePosition, - switchElement.getASwitch()); - } - } - } - } - return null; + if (Objects.nonNull(failMessage)) { + log.info(String.format("进路[%s]排列检查失败,无法排列:%s", route.debugStr(), + failMessage.debugStr())); } + return failMessage; + } - private static Route.CheckFailMessage setSwitchCheck(Simulation simulation, List switchList, boolean guide) { - if (switchList != null) { - for (SwitchElement switchElement : switchList) { - Switch aSwitch = switchElement.getASwitch(); - if (aSwitch.isBlockade()) { // 道岔封锁 - return new Route.CheckFailMessage(Route.CheckFailReason.SwitchBlockade, aSwitch); - } - if (!guide && aSwitch.isGuideMasterLock()) { - return new Route.CheckFailMessage(Route.CheckFailReason.SwitchGuideMasterLock, aSwitch); - } - if ((aSwitch.isLocked() || aSwitch.isSectionOccupied()) && - aSwitch.getPos().equals(SwitchIndication.of(!switchElement.isNormal()))) {//道岔锁闭或占用在相反位置 - return new Route.CheckFailMessage(Route.CheckFailReason.SwitchLockPositionError, aSwitch); - } - if (aSwitch.isCiUseOnOppositePosition(switchElement.isNormal())) { // 道岔征用在相反位置 - return new Route.CheckFailMessage(Route.CheckFailReason.SwitchCiUseOnOppositePosition, aSwitch); - } - //道岔失表时,进路中的区段和道岔由远及近锁闭,直到失表的道岔处 -南铁院叶老师 - if (simulation.getRepository().getConfig().isRouteCanSetWhenSwitchFault()) { - continue; - } - // 非预先锁闭,道岔相应位置失表则不排进路 - 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())) { - return new Route.CheckFailMessage(Route.CheckFailReason.SwitchFault, aSwitch); - } - } - } + /** + * 排列进路过程控制 + * + * @param simulation + * @param route + */ + public void routeSettingProcess(Simulation simulation, Route route) { + if (route.isSetting()) { // 进路排列中 + MapConfig config = simulation.getRepository().getConfig(); + if (!config.isRouteSettingNoFail()) { + if (simulation.getSystemTime().isAfter( + route.getSettingStartTime().plusSeconds(SimulationConstants.ROUTE_SETTING_TIMEOUT))) { + log.info("进路[{}]办理超时,取消办理2", route.debugStr()); + route.settingOver(false); + return; } - return null; + } + List multiRouteAspects = route.getMultiRouteAspects(); + if (CollectionUtils.isEmpty(multiRouteAspects)) { + // 道岔位置转换 + boolean mainRouteSwitchOnPos = this.switchControlService.ensureSwitchPosCurrent(simulation, + route.getSwitchList(), route.isGuideSetting()); + // 预先锁闭 + if (mainRouteSwitchOnPos || config.isLockFirst() || config.isRouteCanSetWhenSwitchFault()) { + // 进路排列区段预先锁闭 + this.checkAndLockRouteMain(route, config.isRailway()); + } + // 侧防办理 + this.flsSetting(simulation, route.getFlsList()); + // 检查信号开放条件,开信号 + this.ciService.interlockCheck(simulation, route); + SignalAspect aspect = null; + if (route.isGuideSetting()) { + aspect = route.getSettedAspect(); + } else if (route.getStart().isBlockade()) { + aspect = route.getStart().getDefaultAspect(); + } else { + aspect = route.getSettedAspect(); + if (config.isRailway() && route.isDepartureRoute()) { + aspect = route.getAspectOfRailway(); + } + } + this.signalControlService.tryControlSignalAspectAccordingLevel(simulation, route.getStart(), + aspect); + if (config.isRailway()) { + if (route.isGuideSetting() && route.getStart().isGuideAspect() + || !route.getStart().isDefaultAspect()) { + route.settingOver(true); + } + } else if ((route.getSettedAspect().equals(route.getStart().getAspect())) || + (route.isGuideSetting() && route.getStart().isGuideAspect())) { + log.debug("进路[{}]信号开放,办理结束", route.debugStr()); + route.settingOver(true); + } + } else { + //由远及近办理进路 + for (int i = multiRouteAspects.size() - 1; i >= 0; i--) { + Route.MultiRouteAspect routeAspect = multiRouteAspects.get(i); + Route subRoute = routeAspect.getRoute(); + if (!subRoute.isLock()) { + setRoute(simulation, subRoute, routeAspect.getAspect()); + break; + } + } + //最近的一条进路已经锁闭 + if (multiRouteAspects.get(0).getRoute().isLock()) { + route.settingOver(true); + } + } } + } - /** - * 排列引导进路 - */ - public void setGuide(Simulation simulation, Route route) { - // 进路检查 - Route.CheckFailMessage failMessage = routeSetCheck(simulation, route, true); - if (failMessage == null) { - if (route.isLock() && !route.isFleetMode()) { - log.info("进路[{}]已经锁闭", route.debugStr()); - return; + private void flsSetting(Simulation simulation, List flsList) { + // 侧防道岔转换 + if (!CollectionUtils.isEmpty(flsList)) { + for (RouteFls routeFls : flsList) { + List level1List = routeFls.getLevel1List(); + for (RouteFls.FlsElement flsElement : level1List) { + SwitchElement pSwitch = flsElement.getPSwitch(); + if (pSwitch != null) { + boolean onPos = this.switchControlService.turnRouteSwitch(simulation, pSwitch); + if (onPos) { + pSwitch.getASwitch().fpLock(); } - // - route.setSettedAspect(route.getStart().getGuideAspect()); - // 引导进路开始办理 - LocalDateTime systemTime = simulation.getSystemTime(); - route.startGuideSetting(systemTime); - // 道岔征用 - for (SwitchElement switchElement : route.getSwitchList()) { - switchElement.getASwitch().ciUse(switchElement.isNormal()); - } - simulation.getRepository().addSettingRoute(route); - } - if (Objects.nonNull(failMessage)) { - log.info(String.format("进路[%s]排列检查失败,无法排列:%s", route.debugStr(), failMessage.debugStr())); + } } + } } + } - /** - * 排列进路 - * - * @param simulation - * @param route - * @return - */ - 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()) { - log.info("进路[{}]已经锁闭", route.debugStr()); - return null; - } - // 设置根据进路性质开放的信号 - route.setSettedAspect(settedAspect); - // 进路开始办理 - LocalDateTime systemTime = simulation.getSystemTime(); - route.startSetting(systemTime); - // 道岔征用 - for (SwitchElement switchElement : route.getSwitchList()) { - switchElement.getASwitch().ciUse(switchElement.isNormal()); - } - if (!simulation.getRepository().getConfig().isOverlapSettingByTrigger()) { - // 延续保护进路办理 - this.ciService.checkAndTrySettingOverlap(simulation, route.getOverlap()); - } - simulation.getRepository().addSettingRoute(route); + /** + * 检查并锁闭主进路(不包含侧防和延续保护) + * + * @param route + * @param railway + */ + private void checkAndLockRouteMain(Route route, boolean railway) { + boolean right = route.isRight(); + List
sectionList = route.getSectionList(); + List switchList = route.getSwitchList(); + for (int i = sectionList.size() - 1; i >= 0; i--) { + Section section = sectionList.get(i); + if (section.isSwitchTrack()) { + if (section.getRelSwitch().isLoss()) { + break; + } else { + section.getRelSwitch().sectionRouteLocking(route, right); } - if (Objects.nonNull(failMessage)) { - log.info(String.format("进路[%s]排列检查失败,无法排列:%s", route.debugStr(), failMessage.debugStr())); - } - return failMessage; + } else { + section.routeLocking(route, right); + } } - - /** - * 排列进路过程控制 - * - * @param simulation - * @param route - */ - public void routeSettingProcess(Simulation simulation, Route route) { - if (route.isSetting()) { // 进路排列中 - MapConfig config = simulation.getRepository().getConfig(); - if (!config.isRouteSettingNoFail()) { - if (simulation.getSystemTime().isAfter(route.getSettingStartTime().plusSeconds(SimulationConstants.ROUTE_SETTING_TIMEOUT))) { - log.info("进路[{}]办理超时,取消办理2", route.debugStr()); - route.settingOver(false); - return; - } - } - List multiRouteAspects = route.getMultiRouteAspects(); - if (CollectionUtils.isEmpty(multiRouteAspects)) { - // 道岔位置转换 - boolean mainRouteSwitchOnPos = this.switchControlService.ensureSwitchPosCurrent(simulation, route.getSwitchList(), route.isGuideSetting()); - // 预先锁闭 - if (mainRouteSwitchOnPos || config.isLockFirst() || config.isRouteCanSetWhenSwitchFault()) { - // 进路排列区段预先锁闭 - this.checkAndLockRouteMain(route, config.isRailway()); - } - // 侧防办理 - this.flsSetting(simulation, route.getFlsList()); - // 检查信号开放条件,开信号 - this.ciService.interlockCheck(simulation, route); - SignalAspect aspect = null; - if (route.isGuideSetting()) { - aspect = route.getSettedAspect(); - } else if (route.getStart().isBlockade()) { - aspect = route.getStart().getDefaultAspect(); - } else { - aspect = route.getSettedAspect(); - if (config.isRailway() && route.isDepartureRoute()) { - aspect = route.getAspectOfRailway(); - } - } - this.signalControlService.tryControlSignalAspectAccordingLevel(simulation, route.getStart(), aspect); - if (config.isRailway()) { - if (route.isGuideSetting() && route.getStart().isGuideAspect() - || !route.getStart().isDefaultAspect()) { - route.settingOver(true); - } - } else if ((route.getSettedAspect().equals(route.getStart().getAspect())) || - (route.isGuideSetting() && route.getStart().isGuideAspect())) { - log.debug("进路[{}]信号开放,办理结束", route.debugStr()); - route.settingOver(true); - } - } else { - //由远及近办理进路 - for (int i = multiRouteAspects.size() - 1; i >= 0; i--) { - Route.MultiRouteAspect routeAspect = multiRouteAspects.get(i); - Route subRoute = routeAspect.getRoute(); - if (!subRoute.isLock()) { - setRoute(simulation, subRoute,routeAspect.getAspect()); - break; - } - } - //最近的一条进路已经锁闭 - if (multiRouteAspects.get(0).getRoute().isLock()) { - route.settingOver(true); - } - } - } + for (int i = switchList.size() - 1; i >= 0; i--) { + SwitchElement switchElement = switchList.get(i); + if (switchElement.isOnPosition() || (route.isGuideSetting() && switchElement.getASwitch() + .isGuideMasterLock())) { + switchElement.getASwitch().routeLock(route); + } } - - private void flsSetting(Simulation simulation, List flsList) { - // 侧防道岔转换 - if (!CollectionUtils.isEmpty(flsList)) { - for (RouteFls routeFls : flsList) { - List level1List = routeFls.getLevel1List(); - for (RouteFls.FlsElement flsElement : level1List) { - SwitchElement pSwitch = flsElement.getPSwitch(); - if (pSwitch != null) { - boolean onPos = this.switchControlService.turnRouteSwitch(simulation, pSwitch); - if (onPos) { - pSwitch.getASwitch().fpLock(); - } - } - } - } - } - } - - /** - * 检查并锁闭主进路(不包含侧防和延续保护) - * - * @param route - * @param railway - */ - private void checkAndLockRouteMain(Route route, boolean railway) { - boolean right = route.isRight(); - List
sectionList = route.getSectionList(); - List switchList = route.getSwitchList(); - for (int i = sectionList.size() - 1; i >= 0; i--) { - Section section = sectionList.get(i); - if (section.isSwitchTrack()) { - if (section.getRelSwitch().isLoss()) { - break; - } else { - section.getRelSwitch().sectionRouteLocking(route, right); - } - } else { - section.routeLocking(route, right); - } - } - for (int i = switchList.size() - 1; i >= 0; i--) { - SwitchElement switchElement = switchList.get(i); - if (switchElement.isOnPosition() || (route.isGuideSetting() && switchElement.getASwitch().isGuideMasterLock())) { - switchElement.getASwitch().routeLock(route); - } - } - route.setLock(true); - + route.setLock(true); // for (SwitchElement switchElement : switchList) { // if (switchElement.isOnPosition() || (route.isGuideSetting() && switchElement.getASwitch().isGuideMasterLock())) { @@ -375,40 +402,40 @@ public class CiRouteService { // } // } // route.setLock(true); - } + } - /** - * 解锁进路 - * - * @param simulation - * @param route - */ - public void unlockRoute(Simulation simulation, Route route) { - // 取消自动进路 - this.cancelFleet(route); - // 关闭始端信号机 - this.signalControlService.tryControlSignalAspectAccordingLevel(simulation, - route.getStart(), route.getStart().getDefaultAspect()); - log.debug(String.format("取消进路,信号机[%s(%s)]关灯", - route.getStart().getName(), route.getStart().getCode())); - //进路解锁 - route.setLock(false); - route.setSetting(false); - route.setAtsControl(false); - // 始端信号机锁闭进路置为null - route.getStart().setLockedRoute(null); - route.getStart().setLevel(Signal.LEVEL_Close); - simulation.getRepository().removeSettingRoute(route); + /** + * 解锁进路 + * + * @param simulation + * @param route + */ + public void unlockRoute(Simulation simulation, Route route) { + // 取消自动进路 + this.cancelFleet(route); + // 关闭始端信号机 + this.signalControlService.tryControlSignalAspectAccordingLevel(simulation, + route.getStart(), route.getStart().getDefaultAspect()); + log.debug(String.format("取消进路,信号机[%s(%s)]关灯", + route.getStart().getName(), route.getStart().getCode())); + //进路解锁 + route.setLock(false); + route.setSetting(false); + route.setAtsControl(false); + // 始端信号机锁闭进路置为null + route.getStart().setLockedRoute(null); + route.getStart().setLevel(Signal.LEVEL_Close); + simulation.getRepository().removeSettingRoute(route); /* 进路办理时,锁闭区段、道岔、侧防均以遍历列表的方式,而非此处之前的,仅遍历区段,再从区段蔓延到相关的道岔和侧防。 这种差异导致了取消进路时有些道岔未解锁,故现修改解锁逻辑以消除这种差异 */ - // 进路区段解锁 - route.getSectionList().forEach(section -> section.routeUnlocking(route)); - // 进路道岔解锁 - route.getSwitchList().forEach(aSwitch -> aSwitch.getASwitch().routeUnlock(route)); - // 进路侧防解锁 - if (!CollectionUtils.isEmpty(route.getFlsList())) { - route.getFlsList().forEach(RouteFls::unlock); - } + // 进路区段解锁 + route.getSectionList().forEach(section -> section.routeUnlocking(route)); + // 进路道岔解锁 + route.getSwitchList().forEach(aSwitch -> aSwitch.getASwitch().routeUnlock(route)); + // 进路侧防解锁 + if (!CollectionUtils.isEmpty(route.getFlsList())) { + route.getFlsList().forEach(RouteFls::unlock); + } // // 进路区段取消锁闭 // List
sectionList = route.getSectionList(); // for (Section section : sectionList) { @@ -435,347 +462,312 @@ public class CiRouteService { // section.routeUnlocking(route); // } // } - // 进路延续保护解锁 - RouteOverlap overlap = route.getOverlap(); - if (Objects.nonNull(overlap)) { - overlap.releaseImmediately(); - log.debug(overlap.debugStr() + "因取消进路解锁"); - } + // 进路延续保护解锁 + RouteOverlap overlap = route.getOverlap(); + if (Objects.nonNull(overlap)) { + overlap.releaseImmediately(); + log.debug(overlap.debugStr() + "因取消进路解锁"); } + } - public void delayUnlockStart(Simulation simulation, Route route, DelayUnlockDevice device) { - device.delayUnlockStart(route,simulation.getRepository().getConfig()); - route.setDelayUnlockDevice(device); - route.setAtsControl(false); //南铁院叶老师:延时解锁开始的同时信号机应该红名(南京二号线) - this.signalControlService.tryControlSignalAspectAccordingLevel(simulation, route.getStart(), route.getStart().getDefaultAspect()); - } + public void delayUnlockStart(Simulation simulation, Route route, DelayUnlockDevice device) { + device.delayUnlockStart(route, simulation.getRepository().getConfig()); + route.setDelayUnlockDevice(device); + route.setAtsControl(false); //南铁院叶老师:延时解锁开始的同时信号机应该红名(南京二号线) + this.signalControlService.tryControlSignalAspectAccordingLevel(simulation, route.getStart(), + route.getStart().getDefaultAspect()); + } - /** - * 延时解锁进路 - * - * @param simulation - * @param route - */ - public void delayUnlocking(Simulation simulation, Route route, DelayUnlockDevice device) { - if (device.countAndCheckFinish(SimulationModule.CI.getRateMs())) { - // 延时结束,执行解锁 - if (device instanceof Signal) { - // 解锁整条进路 - this.unlockRoute(simulation, route); - } else if (device instanceof Switch) { - Switch aSwitch = (Switch) device; - this.faultUnlock(simulation, route, aSwitch); - } else if (device instanceof Section) { - ((Section) device).faultUnlock(); - } - route.setLock(false); - route.setDelayUnlockDevice(null); - } - } - - private void faultUnlock(Simulation simulation, Route route, Switch aSwitch) { - aSwitch.faultUnlock(); - aSwitch.sectionFaultUnlock(); - if (route != null) { - route.unlockRouteFlsOfSwitch(aSwitch); //进路中该道岔对应的侧防解除锁闭 - RouteOverlap overlap = route.getOverlap(); - if (overlap != null) { - for (SectionPath sectionPath : overlap.getPathList()) { - overlap.unlockFlsOfSwitch(sectionPath.getFlsList(), aSwitch); //延续保护中该道岔的侧防解除锁闭 - } - } - } - } - - /** - * 道岔区段故障解锁 - * - * @param simulation - * @param aSwitch - * @param route - */ - public void switchFaultUnlock(Simulation simulation, Switch aSwitch, Route route) { - if (route != null) { - if (route.isApproachLock() || aSwitch.isOverlapLock()) { - // 延时解锁 - this.delayUnlockStart(simulation, route, aSwitch); - return; - } else { - route.setLock(false); - } - } + /** + * 延时解锁进路 + * + * @param simulation + * @param route + */ + public void delayUnlocking(Simulation simulation, Route route, DelayUnlockDevice device) { + if (device.countAndCheckFinish(SimulationModule.CI.getRateMs())) { + // 延时结束,执行解锁 + if (device instanceof Signal) { + // 解锁整条进路 + this.unlockRoute(simulation, route); + } else if (device instanceof Switch) { + Switch aSwitch = (Switch) device; this.faultUnlock(simulation, route, aSwitch); + } else if (device instanceof Section) { + ((Section) device).faultUnlock(); + } + route.setLock(false); + route.setDelayUnlockDevice(null); } + } - /** - * 区故解 - */ - public void sectionFaultUnlock(Simulation simulation, Section section, Route route) { - if (route != null && route.isLock()) { - if (route.getStart().isApproachLock() - || section.isOverlapLock() - || route.getSectionList().stream().anyMatch(Section::isOccupied)) { - // 区段延时解锁 - this.delayUnlockStart(simulation, route, section); - return; - } else { - if (route.isOpenMain() || route.isOpenGuide()) { - this.signalControlService.tryControlSignalAspectAccordingLevel(simulation, route.getStart(), - route.getStart().getDefaultAspect()); - } - route.setLock(false); - } - } - section.faultUnlock(); - if (section.isShowLogic()) { - section.getLogicList().forEach(Section::faultUnlock); + private void faultUnlock(Simulation simulation, Route route, Switch aSwitch) { + aSwitch.faultUnlock(); + aSwitch.sectionFaultUnlock(); + if (route != null) { + route.unlockRouteFlsOfSwitch(aSwitch); //进路中该道岔对应的侧防解除锁闭 + RouteOverlap overlap = route.getOverlap(); + if (overlap != null) { + for (SectionPath sectionPath : overlap.getPathList()) { + overlap.unlockFlsOfSwitch(sectionPath.getFlsList(), aSwitch); //延续保护中该道岔的侧防解除锁闭 } + } } + } - /** - * 列车逐段解锁进路 - * - * @param simulation - * @param route - */ - public void trainUnlockRoute(Simulation simulation, Route route) { - if (!route.isNormalUnlock()) { - return; + /** + * 道岔区段故障解锁 + * + * @param simulation + * @param aSwitch + * @param route + */ + public void switchFaultUnlock(Simulation simulation, Switch aSwitch, Route route) { + if (route != null) { + if (route.isApproachLock() || aSwitch.isOverlapLock()) { + // 延时解锁 + this.delayUnlockStart(simulation, route, aSwitch); + return; + } else { + route.setLock(false); + } + } + this.faultUnlock(simulation, route, aSwitch); + } + + /** + * 区故解 + */ + public void sectionFaultUnlock(Simulation simulation, Section section, Route route) { + if (route != null && route.isLock()) { + if (route.getStart().isApproachLock() + || section.isOverlapLock() + || route.getSectionList().stream().anyMatch(Section::isOccupied)) { + // 区段延时解锁 + this.delayUnlockStart(simulation, route, section); + return; + } else { + if (route.isOpenMain() || route.isOpenGuide()) { + this.signalControlService.tryControlSignalAspectAccordingLevel(simulation, + route.getStart(), + route.getStart().getDefaultAspect()); } - if (!route.isFleetMode()) { // 连续通过进路不解锁,非连续通过进路随最后一辆车的运行而解锁 - boolean right = route.getStart().isRight(); - // 区段是顺序的(否则会有问题) - boolean allUnlock = true; - if (Objects.isNull(route.getUnlockedSection())) { - log.error(String.format("进路[%s(%s)]正常解锁异常", route.getName(), route.getCode())); - return; - } - List
sectionList = route.getSectionList(); - for (int i = 0; i < sectionList.size(); i++) { - Section section = sectionList.get(i); - if (!Objects.equals(route.getUnlockedSection(), section)) { - continue; - } - if (section.isOccupied()) { - // 区段逻辑占用,且有逻辑区段 + route.setLock(false); + } + } + section.faultUnlock(); + if (section.isShowLogic()) { + section.getLogicList().forEach(Section::faultUnlock); + } + } + + /** + * 列车逐段解锁进路 + * + * @param simulation + * @param route + */ + public void trainUnlockRoute(Simulation simulation, Route route) { + if (!route.isNormalUnlock()) { + return; + } + if (!route.isFleetMode()) { // 连续通过进路不解锁,非连续通过进路随最后一辆车的运行而解锁 + boolean right = route.getStart().isRight(); + // 区段是顺序的(否则会有问题) + boolean allUnlock = true; + if (Objects.isNull(route.getUnlockedSection())) { + log.error(String.format("进路[%s(%s)]正常解锁异常", route.getName(), route.getCode())); + return; + } + List
sectionList = route.getSectionList(); + for (int i = 0; i < sectionList.size(); i++) { + Section section = sectionList.get(i); + if (!Objects.equals(route.getUnlockedSection(), section)) { + continue; + } + if (section.isOccupied()) { + // 区段逻辑占用,且有逻辑区段 // log.warn("进路[{}]区段[{}]逐段解锁", route.debugStr(), section.debugStr()); - if (section.isOccupied() && !CollectionUtils.isEmpty(section.getLogicList())) { - // 逻辑区段占用,根据逻辑区段占用位置解锁 - List
logicList = section.getLogicList(); - if (!right) { // 向左,逻辑区段列表reverse - logicList = new ArrayList<>(section.getLogicList()); - Collections.reverse(logicList); - } - for (Section logic : logicList) { - if (!logic.isOccupied() && /*!logic.isInvalid() &&*/ logic.isRouteLockOn(right)) { - logic.routeUnlocking(route); - logic.overlapUnlocking(); - } else if (logic.isOccupied() /*|| logic.isInvalid()*/) { - break; - } - } - } - allUnlock = false; - break; - } else { // 区段不再占用 - if (section.isSwitchTrack()) { // 如果是道岔区段,解锁道岔 - if (section.getParent() != null && section.getParent().isCross()) { - section.getParent().routeUnlocking(route); - } - Switch relSwitch = section.getRelSwitch(); - relSwitch.routeUnlock(route); - relSwitch.overlapUnLock(); - // 侧防解锁 - route.unlockRouteFlsOfSwitch(relSwitch); - //检查道岔的联动道岔和计轴关联道岔是否可以解锁 - for (SwitchElement switchElement : route.getSwitchList()) { - if (switchElement.getASwitch().equals(relSwitch)) { - continue; - } - Switch aSwitch = switchElement.getASwitch(); - if (route.isRouteSection(aSwitch.getA())) { - continue; - } - if (relSwitch.isLinkedSwitch(aSwitch) || relSwitch.isBConnectTo(aSwitch)) { + if (section.isOccupied() && !CollectionUtils.isEmpty(section.getLogicList())) { + // 逻辑区段占用,根据逻辑区段占用位置解锁 + List
logicList = section.getLogicList(); + if (!right) { // 向左,逻辑区段列表reverse + logicList = new ArrayList<>(section.getLogicList()); + Collections.reverse(logicList); + } + for (Section logic : logicList) { + if (!logic.isOccupied() && /*!logic.isInvalid() &&*/ logic.isRouteLockOn(right)) { + logic.routeUnlocking(route); + logic.overlapUnlocking(); + } else if (logic.isOccupied() /*|| logic.isInvalid()*/) { + break; + } + } + } + allUnlock = false; + break; + } else { // 区段不再占用 + if (section.isSwitchTrack()) { // 如果是道岔区段,解锁道岔 + if (section.getParent() != null && section.getParent().isCross()) { + section.getParent().routeUnlocking(route); + } + Switch relSwitch = section.getRelSwitch(); + relSwitch.routeUnlock(route); + relSwitch.overlapUnLock(); + // 侧防解锁 + route.unlockRouteFlsOfSwitch(relSwitch); + //检查道岔的联动道岔和计轴关联道岔是否可以解锁 + for (SwitchElement switchElement : route.getSwitchList()) { + if (switchElement.getASwitch().equals(relSwitch)) { + continue; + } + Switch aSwitch = switchElement.getASwitch(); + if (route.isRouteSection(aSwitch.getA())) { + continue; + } + if (relSwitch.isLinkedSwitch(aSwitch) || relSwitch.isBConnectTo(aSwitch)) { // if (!aSwitch.getA().isRouteLock()) { //当两条进路锁闭同一个道岔时,一条进路解锁,道岔的A区段可能仍旧被另一条进路锁闭着,导致无法解锁,故去掉此判断 - aSwitch.routeUnlock(route); + aSwitch.routeUnlock(route); // aSwitch.overlapUnLock(); //应该不需要,暂时注掉 // } - } - } - } else { - if (!CollectionUtils.isEmpty(section.getLogicList())) { - for (Section logic : section.getLogicList()) { - if (!logic.isOccupied() && logic.isRouteLockOn(right)) { - logic.routeUnlocking(route); - logic.overlapUnlocking(); - } - } - } - section.routeUnlocking(route); - section.overlapUnlocking(); + } + } + } else { + if (!CollectionUtils.isEmpty(section.getLogicList())) { + for (Section logic : section.getLogicList()) { + if (!logic.isOccupied() && logic.isRouteLockOn(right)) { + logic.routeUnlocking(route); + logic.overlapUnlocking(); + } + } + } + section.routeUnlocking(route); + section.overlapUnlocking(); // log.warn("进路[{}]区段[{}]全部解锁", route.debugStr(), section.debugStr()); - } - log.debug(section.debugStr() + "因正常解锁解锁"); - } - if (!section.isRouteLock() && (i + 1) < sectionList.size()) { - // 区段已经解锁,更新解锁区段 - route.updateUnlockedSection(sectionList.get(i + 1)); - } else if (section.isRouteLock() && (i + 1) >= sectionList.size()) { - allUnlock = true; - } - } - Section firstRouteSection = route.getFirstRouteSection(); - if (firstRouteSection.isFree()) { - route.getStart().setReblockade(false); - } - 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(section.debugStr() + "因正常解锁解锁"); } + if (!section.isRouteLock() && (i + 1) < sectionList.size()) { + // 区段已经解锁,更新解锁区段 + route.updateUnlockedSection(sectionList.get(i + 1)); + } else if (section.isRouteLock() && (i + 1) >= sectionList.size()) { + allUnlock = true; + } + } + Section firstRouteSection = route.getFirstRouteSection(); + if (firstRouteSection.isFree()) { + route.getStart().setReblockade(false); + } + if (allUnlock) { // 进路所有区段都已经解锁,解锁完成 + route.normalUnlockOver(); + simulation.getRepository().removeSettingRoute(route); + log.debug(String.format("进路[%s(%s)-%s]解锁完毕,移除", route.getName(), route.getCode(), + route.isTurnBack() ? "Z" : "B")); + } } + } - /** - * 延续保护办理 - * - * @param simulation - * @param overlap - */ - public void setOverlap(Simulation simulation, RouteOverlap overlap) { - if (overlap.isSetting()) { - // 已经在办理了 - return; - } - LocalDateTime systemTime = simulation.getSystemTime(); - overlap.startSetting(systemTime); + /** + * 延续保护办理 + * + * @param simulation + * @param overlap + */ + public void setOverlap(Simulation simulation, RouteOverlap overlap) { + if (overlap.isSetting()) { + // 已经在办理了 + return; } + LocalDateTime systemTime = simulation.getSystemTime(); + overlap.startSetting(systemTime); + } - public void checkAndAllowOverlap(Simulation simulation, RouteOverlap overlap) { - if (!overlap.getSection().isOccupied()) { - overlap.allow(); - return; - } - SectionPath sectionPath = overlap.selectPath(); - if (simulation.getRepository().isTrainHeadOccupy(sectionPath.getFirstSection())) { - overlap.allow(); - } + public void checkAndAllowOverlap(Simulation simulation, RouteOverlap overlap) { + if (!overlap.getSection().isOccupied()) { + overlap.allow(); + return; } - - /** - * 延续保护办理过程 - * - * @param simulation - * @param overlap - */ - public void overlapSettingProcess(Simulation simulation, RouteOverlap overlap) { - if (!overlap.isSetting()) { - return; - } - if (!overlap.getSection().isRouteLock()) { - return; - } - MapConfig config = simulation.getRepository().getConfig(); - if (!config.isRouteSettingNoFail()) { - if (simulation.getSystemTime().isAfter(overlap.getSettingStartTime().plusSeconds(SimulationConstants.ROUTE_SETTING_TIMEOUT))) { - log.info(String.format("进路延续保护[%s]办理失败", overlap.debugStr())); - overlap.settingOver(); - return; - } - } - SectionPath sectionPath = overlap.selectPath(); - for (SwitchElement switchElement : sectionPath.getSwitchList()) { - if (!switchElement.getASwitch().ciUse(switchElement.isNormal())) { - return; - } - switchElement.getASwitch().overlapLock(); - } - // 延续保护位置转动 - boolean onPos = this.switchControlService.ensureSwitchPosCurrent(simulation, sectionPath.getSwitchList(), false); - // 延续保护区段预先锁闭 - if (onPos || config.isLockFirst()) { - this.checkAndLockOverlap(simulation, overlap); - } - // 侧防办理 - this.flsSetting(simulation, sectionPath.getFlsList()); - if (this.ciService.interlockCheck(simulation, overlap)) { - log.debug(String.format("进路延续保护[%s]办理成功", overlap.debugStr())); - overlap.setLock(true); - overlap.settingOver(); - } + SectionPath sectionPath = overlap.selectPath(); + if (simulation.getRepository().isTrainHeadOccupy(sectionPath.getFirstSection())) { + overlap.allow(); } + } - private void checkAndLockOverlap(Simulation simulation, RouteOverlap overlap) { - SectionPath sectionPath = overlap.selectPath(); - boolean right = overlap.isRight(); - List
logicList = sectionPath.getLogicList(); - if (!CollectionUtils.isEmpty(logicList)) { - for (Section section : logicList) { - section.overlapLocking(right); - } + /** + * 延续保护办理过程 + * + * @param simulation + * @param overlap + */ + public void overlapSettingProcess(Simulation simulation, RouteOverlap overlap) { + if (!overlap.isSetting()) { + return; + } + if (!overlap.getSection().isRouteLock()) { + return; + } + MapConfig config = simulation.getRepository().getConfig(); + if (!config.isRouteSettingNoFail()) { + if (simulation.getSystemTime().isAfter( + overlap.getSettingStartTime().plusSeconds(SimulationConstants.ROUTE_SETTING_TIMEOUT))) { + log.info(String.format("进路延续保护[%s]办理失败", overlap.debugStr())); + overlap.settingOver(); + return; + } + } + SectionPath sectionPath = overlap.selectPath(); + for (SwitchElement switchElement : sectionPath.getSwitchList()) { + if (!switchElement.getASwitch().ciUse(switchElement.isNormal())) { + return; + } + switchElement.getASwitch().overlapLock(); + } + // 延续保护位置转动 + boolean onPos = this.switchControlService.ensureSwitchPosCurrent(simulation, + sectionPath.getSwitchList(), false); + // 延续保护区段预先锁闭 + if (onPos || config.isLockFirst()) { + this.checkAndLockOverlap(simulation, overlap); + } + // 侧防办理 + this.flsSetting(simulation, sectionPath.getFlsList()); + if (this.ciService.interlockCheck(simulation, overlap)) { + log.debug(String.format("进路延续保护[%s]办理成功", overlap.debugStr())); + overlap.setLock(true); + overlap.settingOver(); + } + } + + private void checkAndLockOverlap(Simulation simulation, RouteOverlap overlap) { + SectionPath sectionPath = overlap.selectPath(); + boolean right = overlap.isRight(); + List
logicList = sectionPath.getLogicList(); + if (!CollectionUtils.isEmpty(logicList)) { + for (Section section : logicList) { + section.overlapLocking(right); + } + } else { + List
sectionList = sectionPath.getSectionList(); + for (Section section : sectionList) { + if (section.isSwitchTrack()) { + Switch relSwitch = section.getRelSwitch(); + relSwitch.sectionOverlapLocking(right); } else { - List
sectionList = sectionPath.getSectionList(); - for (Section section : sectionList) { - if (section.isSwitchTrack()) { - Switch relSwitch = section.getRelSwitch(); - relSwitch.sectionOverlapLocking(right); - } else { - section.overlapLocking(right); - } - } + section.overlapLocking(right); } + } } + } - /** - * 设置自动进路模式 - * - * @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); - } + /** + * 取消自动进路 + * + * @param route + */ + public void cancelFleet(Route route) { + if (route.isFleetMode()) { + route.setFleetMode(false); } + } - /** - * 取消自动进路 - * - * @param route - */ - public void cancelFleet(Route route) { - if (route.isFleetMode()) { - route.setFleetMode(false); - } - } - - /** - * 设置联锁自动触发 - * - * @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); - } - } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/command/CommandBO.java b/src/main/java/club/joylink/rtss/simulation/cbtc/command/CommandBO.java index 671947e92..c36964b93 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/command/CommandBO.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/command/CommandBO.java @@ -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,933 +39,975 @@ import java.util.stream.Collectors; @Getter @Setter public class CommandBO { - private CommandType commandType; - private SimulationMember fromMember; + private CommandType commandType; - private SimulationMember targetMember; + private SimulationMember fromMember; - private Map params; + private SimulationMember targetMember; - private List stepList; + private Map params; - public CommandBO(CommandType commandType, SimulationMember fromMember, SimulationMember targetMember, - Map params, List stepList) { - this.commandType = commandType; - this.fromMember = fromMember; - this.targetMember = targetMember; - this.params = params; - this.stepList = stepList; + private List stepList; + + public CommandBO(CommandType commandType, SimulationMember fromMember, + SimulationMember targetMember, + Map params, List stepList) { + this.commandType = commandType; + this.fromMember = fromMember; + this.targetMember = targetMember; + this.params = params; + this.stepList = stepList; + } + + public Step findNextUnfinishedStep() { + for (Step step : this.getStepList()) { + if (!step.isFinish()) { + return step; + } } + return null; + } - public Step findNextUnfinishedStep() { - for (Step step : this.getStepList()) { - if (!step.isFinish()) { - return step; - } - } - return null; - } + public List getStepByType(Step.StepType stepType) { + return this.stepList.stream().filter(step -> step.getType().equals(stepType)) + .collect(Collectors.toList()); + } - public List getStepByType(Step.StepType stepType) { - return this.stepList.stream().filter(step -> step.getType().equals(stepType)).collect(Collectors.toList()); - } + /** + * 指令步骤 + */ + @Getter + @Setter + public static class Step { + + private StepType type; + + private Operation.Type operationType; + + private Map operationParams; + + private SectionPosition targetPosition; /** - * 指令步骤 + * 越过该信号机驾驶模式从RM升BM */ - @Getter - @Setter - public static class Step { - private StepType type; + private Signal upgradeSignal; - private Operation.Type operationType; + /** + * 越信号机步骤要越过的信号机 + */ + private Signal crossSignal; - private Map operationParams; + /** + * 限速指令的限速值 + */ + private Float speedLimit; - private SectionPosition targetPosition; + private boolean finish; - /** - * 越过该信号机驾驶模式从RM升BM - */ - private Signal upgradeSignal; - - /** - * 越信号机步骤要越过的信号机 - */ - private Signal crossSignal; - - /** - * 限速指令的限速值 - */ - private Float speedLimit; - - private boolean finish; - - public void finish() { - this.finish = true; - } - - public String debugStr() { - return String.format("步骤[类型:%s|操作类型:%s]", type, operationType); - } - - public enum StepType { - /** - * 仿真操作 - */ - OPERATION, - /** - * 人工驾驶(目前就是RM模式驾驶) - */ - DRIVE, - /** - * RM模式升BM模式(越过同向信号机或在站台停站) - */ - RM_TO_BM, - /** - * 越信号机(红灯/引导信号) - */ - CROSS_SIGNAL, - /** - * 在终点停车 - */ - STOP_AT_TERMINAL, - /** - * 设置限速 - */ - SET_SPEED_LIMIT, - /** - * ATO模式下的换端 - */ - ATO_CHANGE_DIRECTION, - ; - } + public void finish() { + this.finish = true; } - @Getter - public enum CommandType { - /** - * 确认运行至前方站 - */ - Drive_Ahead(Collections.emptyList(), SimulationMember.Type.DRIVER) { - @Override - public List buildStepList(Simulation simulation, SimulationMember targetMember, Map params) { - VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice(); - SectionPosition headPosition = train.getHeadPosition(); - Section section = headPosition.getSection(); - boolean right = train.isRight(); + public String debugStr() { + return String.format("步骤[类型:%s|操作类型:%s]", type, operationType); + } - List stepList = new ArrayList<>(); - stepList.add(buildDriverForceChangeOperationStep(train.getGroupNumber(), 0)); - if (section.isStandTrack()) { //如果列车的车头所在区段是站台轨 - SectionPosition standStopPosition = new SectionPosition(section, section.getStopPointByDirection(right)); - if (train.isStopAtThePosition(standStopPosition)) { //列车已经停在站台停车点 - 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)); - } - stepList.add(buildDriveStep(nextStopPosition)); - } - } else { - SectionPosition nextStopPosition = train.calculateNextStandStopPosition(); - if (nextStopPosition == null && train.getTarget() != null) { - nextStopPosition = new SectionPosition(train.getTarget(), train.getTarget().getStopPointByDirection(right)); - } - BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotNull(nextStopPosition, - train.debugStr() + "找不到下一个停车点"); - stepList.add(buildDriveStep(nextStopPosition)); - } - stepList.add(buildRmToBmStep()); + public enum StepType { + /** + * 仿真操作 + */ + OPERATION, + /** + * 人工驾驶(目前就是RM模式驾驶) + */ + DRIVE, + /** + * RM模式升BM模式(越过同向信号机或在站台停站) + */ + RM_TO_BM, + /** + * 越信号机(红灯/引导信号) + */ + CROSS_SIGNAL, + /** + * 在终点停车 + */ + STOP_AT_TERMINAL, + /** + * 设置限速 + */ + SET_SPEED_LIMIT, + /** + * ATO模式下的换端 + */ + ATO_CHANGE_DIRECTION, + ; + } + } - return stepList; + @Getter + public enum CommandType { + /** + * 确认运行至前方站 + */ + Drive_Ahead(Collections.emptyList(), SimulationMember.Type.DRIVER) { + @Override + public List buildStepList(Simulation simulation, SimulationMember targetMember, + Map params) { + VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice(); + SectionPosition headPosition = train.getHeadPosition(); + Section section = headPosition.getSection(); + boolean right = train.isRight(); + + List stepList = new ArrayList<>(); + stepList.add(buildDriverForceChangeOperationStep(train.getGroupNumber(), 0)); + if (section.isStandTrack()) { //如果列车的车头所在区段是站台轨 + SectionPosition standStopPosition = new SectionPosition(section, + section.getStopPointByDirection(right)); + if (train.isStopAtThePosition(standStopPosition)) { //列车已经停在站台停车点 + 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)); } + stepList.add(buildDriveStep(nextStopPosition)); + } + } else { + SectionPosition nextStopPosition = train.calculateNextStandStopPosition(); + if (nextStopPosition == null && train.getTarget() != null) { + nextStopPosition = new SectionPosition(train.getTarget(), + train.getTarget().getStopPointByDirection(right)); + } + BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotNull(nextStopPosition, + train.debugStr() + "找不到下一个停车点"); + stepList.add(buildDriveStep(nextStopPosition)); + } + stepList.add(buildRmToBmStep()); - @Override - public Step execute(Simulation simulation, CommandBO command) { - VirtualRealityTrain train = (VirtualRealityTrain) command.getTargetMember().getDevice(); - List steps = command.getStepByType(Step.StepType.DRIVE); - Step driveStep = steps.get(0); - if (!train.isStopAtThePosition(driveStep.getTargetPosition())) { //如果列车没停到目标位置 - if (!train.isInTheGear(Handwheel.MANUAL)) { - return buildGearChangeStep(train.getGroupNumber(), Handwheel.MANUAL); - } - if (!train.isStop()) - return buildDriverForceChangeOperationStep(train.getGroupNumber(), -1); - if (!DriveMode.RM.equals(train.getDriveMode()) && !train.isNRMMode()) - return getStep4ChangePreselectionMode(train, PreselectionMode.RM); - if (train.isEB()) - return getStep4ReleaseEB(train); - return driveStep; - } else { //如果列车已经停到目标位置 + return stepList; + } + + @Override + public Step execute(Simulation simulation, CommandBO command) { + VirtualRealityTrain train = (VirtualRealityTrain) command.getTargetMember().getDevice(); + List steps = command.getStepByType(Step.StepType.DRIVE); + Step driveStep = steps.get(0); + if (!train.isStopAtThePosition(driveStep.getTargetPosition())) { //如果列车没停到目标位置 + if (!train.isInTheGear(Handwheel.MANUAL)) { + return buildGearChangeStep(train.getGroupNumber(), Handwheel.MANUAL); + } + if (!train.isStop()) { + return buildDriverForceChangeOperationStep(train.getGroupNumber(), -1); + } + if (!DriveMode.RM.equals(train.getDriveMode()) && !train.isNRMMode()) { + return getStep4ChangePreselectionMode(train, PreselectionMode.RM); + } + if (train.isEB()) { + return getStep4ReleaseEB(train); + } + return driveStep; + } else { //如果列车已经停到目标位置 // if (!DriveMode.AM.equals(train.getDriveMode())) // return getStepOfRm2BmAndOpenAto(command); - command.getTargetMember().setCommand(null); - return null; - } - } - }, - - /** - * 进路闭塞法行车 - */ - Route_Block_Drive(Collections.emptyList(), SimulationMember.Type.DRIVER) { - @Override - public List buildStepList(Simulation simulation, SimulationMember targetMember, Map params) { - return Collections.emptyList(); - } - - @Override - public Step execute(Simulation simulation, CommandBO command) { - VirtualRealityTrain train = (VirtualRealityTrain) command.getTargetMember().getDevice(); - if (train.isAMMode()) { - command.getTargetMember().setCommand(null); - } else { - getStep4ChangePreselectionMode(train, PreselectionMode.AM_C); - } - return null; - } - - }, - - /** - * 道岔钩锁 - */ - Switch_Hook_Lock(Arrays.asList(ParamName.switchCode, ParamName.normal), SimulationMember.Type.STATION_SUPERVISOR) { - @Override - public List buildStepList(Simulation simulation, SimulationMember targetMember, Map params) { - if (!SimulationMember.Type.STATION_SUPERVISOR.equals(targetMember.getType())) { - throw new SimulationException(SimulationExceptionType.Member_Is_Not_Station_Supervisor); - } - - List stepList = new ArrayList<>(); - String switchCode = (String) params.get(ParamName.switchCode.name()); - boolean normal = (boolean) params.get(ParamName.normal.name()); - stepList.add(buildSwitchHookLockOperationStep(switchCode, normal)); - - return stepList; - } - - @Override - public Step execute(Simulation simulation, CommandBO command) { - String switchCode = (String) command.getParams().get(ParamName.switchCode.name()); - Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); - boolean normal = (boolean) command.getParams().get(ParamName.normal.name()); - if (aSwitch.getVirtualSwitch().isPosN() != normal) { - List steps = command.getStepByType(Step.StepType.OPERATION); - return steps.get(0); - } else { - command.getTargetMember().setCommand(null); - } - return null; - } - }, - - /** - * 越红灯行驶 - */ - Drive_Through_The_Red_Light(Collections.emptyList(), SimulationMember.Type.DRIVER) { - @Override - public List buildStepList(Simulation simulation, SimulationMember targetMember, Map params) { - if (!SimulationMember.Type.DRIVER.equals(targetMember.getType())) { - throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver); - } - - List stepList = new ArrayList<>(); - VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice(); - stepList.add(buildDriveStep(train.calculateStopPosition4CrossTheRedLight())); - stepList.add(buildCrossSignalStep(train.getHeadPosition().getSection().getSignalOf(train.isRight()))); - stepList.add(buildRmToBmStep()); - - return stepList; - } - - @Override - public Step execute(Simulation simulation, CommandBO command) { - VirtualRealityTrain train = (VirtualRealityTrain) command.getTargetMember().getDevice(); - List steps = command.getStepByType(Step.StepType.DRIVE); - Step driveStep = steps.get(0); - boolean stopCorrectly = train.isStopAtThePosition(driveStep.getTargetPosition()); - if (stopCorrectly) { //如果列车已经停到目标位置 - driveStep.finish(); - command.getTargetMember().setCommand(null); - } else { - if (!DriveMode.RM.equals(train.getDriveMode()) && !train.isNRMMode()) { - return getStep4ChangePreselectionMode(train, PreselectionMode.RM); - } - if (train.isSignalEB()) { - return getStep4ReleaseEB(train); - } - return driveStep; - } - return null; - } - }, - - /** - * 越引导信号行驶 - */ - Drive_Through_The_Guide_Signal(Collections.emptyList(), SimulationMember.Type.DRIVER) { - @Override - public List buildStepList(Simulation simulation, SimulationMember targetMember, Map params) { - if (!SimulationMember.Type.DRIVER.equals(targetMember.getType())) { - throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver); - } - - List stepList = new ArrayList<>(); - VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice(); - stepList.add(buildDriveStep(calculateStepPosition4CrossTheGuideSignal(train))); - stepList.add(buildCrossSignalStep(train.getHeadPosition().getSection().getSignalOf(train.isRight()))); - - return stepList; - } - - @Override - public Step execute(Simulation simulation, CommandBO command) { - VirtualRealityTrain train = (VirtualRealityTrain) command.getTargetMember().getDevice(); - if (!train.isRMMode() && !train.isNRMMode()) { //既不是RM也不是NRM,切换预选模式 - return getStep4ChangePreselectionMode(train, PreselectionMode.RM); - } - if (!train.isInTheGear(Handwheel.MANUAL)) { //转手轮 - return buildGearChangeStep(train.getGroupNumber(), Handwheel.MANUAL); - } - List steps = command.getStepByType(Step.StepType.DRIVE); - Step driveStep = steps.get(0); - if (train.isStopAtThePosition(driveStep.getTargetPosition())) { //如果列车已经停到目标位置 - command.getTargetMember().setCommand(null); - } else { - return driveStep; - } - return null; - } - }, - - /** - * 开关门 - */ - Open_Or_Close_Door(Collections.emptyList(), SimulationMember.Type.DRIVER) { - @Override - public List buildStepList(Simulation simulation, SimulationMember targetMember, Map params) { - if (!SimulationMember.Type.DRIVER.equals(targetMember.getType())) { - throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver); - } - - List stepList = new ArrayList<>(); - VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice(); - List standList = train.getHeadPosition().getSection().getStandList(); - if (!CollectionUtils.isEmpty(standList) && standList.size() == 1 && standList.get(0).isSmall()) { - // 小站台停车,无需开关门 - return null; - } - if (!train.getDoorByDirection(false).isCloseAndLock()) { //列车左门没关 - stepList.add(buildDoorOnOffOperationStep(train.getGroupNumber(), false, false)); - } else if (!train.getDoorByDirection(true).isCloseAndLock()) { //列车右门没关 - stepList.add(buildDoorOnOffOperationStep(train.getGroupNumber(), true, false)); - } else { - boolean doorIsRight; - for (Stand stand : standList) { - if (stand.isInside() && stand.isRight()) { // 内测右站台,开1门 - doorIsRight = train.judgeDirection4DoorIsRight(train.getDoor1()); - } else if (stand.isInside() && !stand.isRight()) { // 内测左站台,开2门 - doorIsRight = train.judgeDirection4DoorIsRight(train.getDoor2()); - } else if (!stand.isInside() && stand.isRight()) { //外侧右站台,开2门 - doorIsRight = train.judgeDirection4DoorIsRight(train.getDoor2()); - } else { - doorIsRight = train.judgeDirection4DoorIsRight(train.getDoor1()); - } - stepList.add(buildDoorOnOffOperationStep(train.getGroupNumber(), doorIsRight, true)); - } - } - - return stepList; - } - - @Override - public Step execute(Simulation simulation, CommandBO command) { - VirtualRealityTrain train = (VirtualRealityTrain) command.getTargetMember().getDevice(); - List steps = command.getStepByType(Step.StepType.OPERATION); - Step step = steps.get(0); - VirtualRealityTrain.Door door = train.getDoorByDirection((boolean) step.getOperationParams().get("right")); - if (!Objects.equals(door.isOpen(), step.getOperationParams().get("open"))) { - return step; - } else { - command.getTargetMember().setCommand(null); - return null; - } - } - - }, - - /** - * 设置限速 - */ - Set_Speed_Limit(List.of(ParamName.speedLimit), SimulationMember.Type.DRIVER) { - @Override - public List buildStepList(Simulation simulation, SimulationMember targetMember, Map 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())); - if (speedLimit < 0) { - train.setSpeedLimit(Float.MAX_VALUE); - } else { - train.setSpeedLimit(speedLimit / 3.6f); - } - command.getTargetMember().setCommand(null); - return null; - } - }, - - /** - * 换端 - */ - Turn_Direction(List.of(), SimulationMember.Type.DRIVER) { - @Override - public List buildStepList(Simulation simulation, SimulationMember targetMember, Map 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<>(); - } - - @Override - public Step execute(Simulation simulation, CommandBO command) { - SimulationMember targetMember = command.getTargetMember(); - VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice(); - if (Objects.equals(train.isRight(), command.getParams().get(ParamName.trainRight.name()))) { - targetMember.setCommand(null); - return null; - } else { - return buildDriverChangeHeadOperateStep(train.getGroupNumber()); - } - } - }, - - /** - * 驾驶至 - */ - Drive_To(List.of(ParamName.sectionCode), SimulationMember.Type.DRIVER) { - @Override - public List buildStepList(Simulation simulation, SimulationMember targetMember, Map params) { - return List.of(); - } - - @Override - public Step execute(Simulation simulation, CommandBO command) { - SimulationMember targetMember = command.getTargetMember(); - 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())); - if (train.isStopAtThePosition(targetPosition)) { - targetMember.setCommand(null); - return null; - } else { - return buildDriveStep(targetPosition); - } - } - }, - - /** - * 回库 - */ - Inbound(List.of(), SimulationMember.Type.DRIVER) { - @Override - public List buildStepList(Simulation simulation, SimulationMember targetMember, Map params) { - return List.of(); - } - - @Override - public Step execute(Simulation simulation, CommandBO command) { - SimulationMember driver = command.getTargetMember(); - driver.setCommand(null); - VirtualRealityTrain train = (VirtualRealityTrain) driver.getDevice(); - Section headSection = train.getHeadPosition().getSection(); - if (headSection.isTransferTrack() && train.isStop()) { //列车停在折返轨 - SimulationDataRepository repository = simulation.getRepository(); - TrainInfo trainInfo = repository.getSupervisedTrainByGroup(train.getGroupNumber()); - List routePathList = repository.queryRoutePathsByEnd(headSection); - if (routePathList.get(0).isRight() == trainInfo.getRight()) { //准备回库 - trainInfo.finishPlanPrepareInbound(); - } - } - return null; - } - }, - - /** - * 修改预选模式 - */ - Change_Preselection_Mode(List.of(ParamName.preselectionMode), SimulationMember.Type.DRIVER) { - @Override - public List buildStepList(Simulation simulation, SimulationMember targetMember, Map params) { - return Collections.emptyList(); - } - - @Override - public Step execute(Simulation simulation, CommandBO command) { - SimulationMember driver = command.getTargetMember(); - VirtualRealityTrain train = (VirtualRealityTrain) driver.getDevice(); - if (!train.isAtpOn()) { - return buildDriverATPChangeOperationStep(train.getGroupNumber(), false); - } - if (train.isSignalEB()) { - return getStep4ReleaseEB(train); - } - PreselectionMode preselectionMode = - 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()) { - return getStep4OpenATO(train); - } else { - driver.setCommand(null); - } - return null; - } - }, - - /** - * 转NRM模式 - */ - Apply_NRM(List.of(), SimulationMember.Type.DRIVER) { - @Override - public List buildStepList(Simulation simulation, SimulationMember targetMember, Map params) { - return Collections.emptyList(); - } - - @Override - public Step execute(Simulation simulation, CommandBO command) { - SimulationMember driver = command.getTargetMember(); - VirtualRealityTrain train = (VirtualRealityTrain) driver.getDevice(); - if (train.isNRMMode()) { - driver.setCommand(null); - return null; - } - return buildDriverATPChangeOperationStep(train.getGroupNumber(), true); - } - }, - - /** - * 大铁、发车 - **/ - Depart_Train(List.of(), SimulationMember.Type.DRIVER) { - @Override - public List buildStepList(Simulation simulation, SimulationMember targetMember, Map params) { - VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice(); - boolean isRight = train.isRight(); // 列车运行方向 - Section section = train.getHeadPosition().getSection(); // 列车车头所在区段 - Section targetSection = getTargetSection(isRight, section); - List stepList = new ArrayList<>(); - if (targetSection != null) { - SectionPosition targetPosition = new SectionPosition(targetSection, targetSection.getStopPointByDirection(isRight)); - // 设置目标位置 - stepList.add(buildDriveStep(targetPosition)); - } - return stepList; - } - - @Override - public Step execute(Simulation simulation, CommandBO command) { - VirtualRealityTrain train = (VirtualRealityTrain) command.getTargetMember().getDevice(); - boolean isOnline = simulation.getRepository().getUsedTrainMap().containsKey(train.getGroupNumber()); - if (!isOnline) { - command.getTargetMember().setCommand(null); - return null; - } - List steps = command.getStepByType(Step.StepType.DRIVE); - Step driveStep = steps.get(0); - if (train.isStopAtThePosition(driveStep.getTargetPosition())) { //如果列车已经停到目标位置 - boolean isRight = train.isRight(); // 列车运行方向 - Section section = train.getHeadPosition().getSection(); // 列车车头所在区段 - Section targetSection = getTargetSection(isRight, section); - if (Objects.equals(section, targetSection)) { - command.getTargetMember().setCommand(null); - } else { - SectionPosition targetPosition = new SectionPosition(targetSection, targetSection.getStopPointByDirection(isRight)); - driveStep.setTargetPosition(targetPosition); - return driveStep; - } - } else { - SectionPosition sectionPosition = train.getHeadPosition(); - // 检查是否还可以向前行驶 - boolean checkResult = checkRunCondition(train.isRight(), sectionPosition.getSection()); - if (checkResult) { - return driveStep; - } else { - driveStep.setTargetPosition(sectionPosition); - command.getTargetMember().setCommand(null); - return null; - } - } - return null; - } - }, - - /** - * 大铁、停车 - */ - Parking_Train(List.of(), SimulationMember.Type.DRIVER) { - @Override - public List buildStepList(Simulation simulation, SimulationMember targetMember, Map params) { - return Collections.emptyList(); - } - - @Override - public Step execute(Simulation simulation, CommandBO command) { - SimulationMember targetMember = command.getTargetMember(); - VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice(); - boolean isOnline = simulation.getRepository().getUsedTrainMap().containsKey(train.getGroupNumber()); - if (!isOnline) { - command.getTargetMember().setCommand(null); - return null; - } - if (train.isStop()) { - targetMember.setCommand(null); - } - // 设置目标位置 - return buildDriveStep(train.getHeadPosition()); - } - }; - - public enum ParamName { - stationCode, - switchCode, - /** - * 是否是定位(道岔) - */ - normal, - /** - * 是否是右边(要开/关的车门) - */ - right, - /** - * 是否是开启(车门) - */ - open, - /** - * 限速值 - */ - speedLimit, - /** - * 车头方向 - */ - trainRight, - sectionCode, - preselectionMode, - ; + command.getTargetMember().setCommand(null); + return null; } - - private final List paramNames; - - private SimulationMember.Type memberType; - - CommandType(List paramNames, SimulationMember.Type memberType) { - this.paramNames = paramNames; - this.memberType = memberType; - } - - /** - * 构架指令步骤列表 - */ - public abstract List buildStepList(Simulation simulation, SimulationMember targetMember, Map params); - - /** - * 执行指令,返回无法直接完成的指令 - */ - public abstract Step execute(Simulation simulation, CommandBO command); - - - - /** - * 构建“开启ATO操作”步骤 - */ - public Step buildDriverAtoOpenOperationStep(String groupNumber) { - Map operationParams = new HashMap<>(); - operationParams.put("groupNumber", groupNumber); - Step step = new Step(); - step.setType(Step.StepType.OPERATION); - step.setOperationType(Operation.Type.Driver_ATO_Open); - step.setOperationParams(operationParams); - return step; - } - - /** - * 构建道岔钩锁操作步骤 - */ - public Step buildSwitchHookLockOperationStep(String switchCode, Boolean normal) { - Map operationParams = new HashMap<>(); - operationParams.put("switchCode", switchCode); - operationParams.put("normal", normal); - Step step = new Step(); - step.setType(Step.StepType.OPERATION); - step.setOperationType(Operation.Type.Switch_Hook_Lock); - step.setOperationParams(operationParams); - return step; - } - - /** - * 构建”开关车门操作“步骤 - */ - public Step buildDoorOnOffOperationStep(String groupNumber, boolean right, boolean open) { - Map operationParams = new HashMap<>(); - operationParams.put("groupNumber", groupNumber); - operationParams.put("right", right); - operationParams.put("open", open); - Step step = new Step(); - step.setType(Step.StepType.OPERATION); - step.setOperationType(Operation.Type.Driver_Door_On_Off); - step.setOperationParams(operationParams); - return step; - } - - public Step buildDriverChangeHeadOperateStep(String groupNumber) { - Map operationParams = new HashMap<>(); - operationParams.put("groupNumber", groupNumber); - Step step = new Step(); - step.setType(Step.StepType.OPERATION); - step.setOperationType(Operation.Type.Driver_Change_Head); - step.setOperationParams(operationParams); - return step; - } - - public Step buildDriverATPChangeOperationStep(String groupNumber, boolean cutOff) { - Map operationParams = new HashMap<>(); - operationParams.put("groupNumber", groupNumber); - operationParams.put("cutOff", cutOff); - Step step = new Step(); - step.setType(Step.StepType.OPERATION); - step.setOperationType(Operation.Type.Driver_ATP_Change); - step.setOperationParams(operationParams); - return step; - } - - /** - * 构建“驾驶”步骤 - */ - public Step buildDriveStep(SectionPosition targetPosition) { - Step step = new Step(); - step.setType(Step.StepType.DRIVE); - step.setTargetPosition(targetPosition); - return step; - } - - /** - * 构建“rm升bm”步骤 - */ - public Step buildRmToBmStep() { - Step step = new Step(); - step.setType(Step.StepType.RM_TO_BM); - return step; - } - - /** - * 构建“越过信号机”步骤 - */ - public Step buildCrossSignalStep(Signal signal) { - Step step = new Step(); - step.setType(Step.StepType.CROSS_SIGNAL); - step.setCrossSignal(signal); - return step; - } - - public Step getStep4OpenATO(VirtualRealityTrain train) { - String groupNumber = train.getGroupNumber(); - if (!train.isAtpOn()) { - return buildDriverATPChangeOperationStep(groupNumber, false); - } - if (!train.isInTheGear(Handwheel.ATO)) { - return buildGearChangeStep(groupNumber, Handwheel.ATO); - } - if (!train.isLeverInCoastingGear()) { - return buildDriverForceChangeOperationStep(groupNumber, 0); - } - if (!train.isAtoOn()) { - return buildDriverAtoOpenOperationStep(groupNumber); - } - return null; - } - - /** - * 计算越引导信号行驶的停车位置 - */ - public SectionPosition calculateStepPosition4CrossTheGuideSignal(VirtualRealityTrain train) { - boolean right = train.isRight(); - SectionPosition headPosition = train.getHeadPosition(); - Section section = headPosition.getSection(); - Signal trainHeadSignal = section.getSignalOf(right); - if (trainHeadSignal == null || !trainHeadSignal.isGuideAspect()) { - 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, "引导信号前方未找到停车位置"); - Signal signal = section.getSignalOf(right); - if (section.isStandTrack() || section.isTurnBackTrack()) { - sectionPosition = new SectionPosition(section, section.getStopPointByDirection(right)); - break; - } else if (signal != null && !signal.isShunting() && !signal.isMainAspect()) { //同向信号机未正常开放 - sectionPosition = new SectionPosition(section, signal.getOffset()); - break; - } - } - if (sectionPosition == null) { - throw new SimulationException(SimulationExceptionType.Invalid_Operation, "引导信号前方未找到停车位置"); - } - return sectionPosition; - } - - /** - * 从此区段向right方向获取未被占用的目标区段 - * - * @param isRight 方向 - * @param section 起始区段 - * @return 目标区段 - */ - public Section getTargetSection(boolean isRight, Section section) { - boolean loop = true; - Signal signal; - Section nextSection = section, targetSection = null; - while (loop) { - signal = isRight ? nextSection.getSignalToRight() : nextSection.getSignalToLeft(); // 方向信号机 - // 信号机未开放,直接中断 - if (signal != null && SignalAspect.R.equals(signal.getAspect())) { - targetSection = nextSection; - break; - } - // 存在锁闭进路,获取进路末端 - if (signal != null && signal.getLockedRoute() != null) { - nextSection = signal.getLockedRoute().getDestination().getSection(); - } else if (nextSection.isRouteLock()) { // 如果当前区段进路锁闭 - nextSection = nextSection.getRoute().getDestination().getSection(); - } else if (nextSection.isSwitchTrack()) { // 是邻近岔道 - nextSection = nextSection.getNextRunningSectionOf(isRight); - } else { - nextSection = nextSection.getNextSection(isRight); - } - // 存在邻近区段,赋值 - if (nextSection != null) { - targetSection = nextSection; - } - // 进路存在且不占用不出故障 - loop = nextSection != null && !nextSection.isOccupied() && !nextSection.isFaultLock(); - } - return targetSection; - } - - /** - * 大铁列车运行时,检查是否还可以向前行驶 - * - * @param isRight 方向 - * @param section 起始区段 - * @return 行驶区段 - */ - public boolean checkRunCondition(boolean isRight, Section section) { - Signal signal = isRight ? section.getSignalToRight() : section.getSignalToLeft(); // 方向信号机 - // 信号机未开放,直接中断 - if (signal != null && SignalAspect.R.equals(signal.getAspect())) { - return false; - } - return true; - } - } + } + }, /** - * 构建“改变列车牵引/制动力操作”步骤 + * 进路闭塞法行车 */ - public static Step buildDriverForceChangeOperationStep(String groupNumber, float percent) { - Map operationParams = new HashMap<>(); - operationParams.put("groupNumber", groupNumber); - operationParams.put("percent", percent); - Step step = new Step(); - step.setType(Step.StepType.OPERATION); - step.setOperationType(Operation.Type.Driver_Force_Change); - step.setOperationParams(operationParams); - return step; - } + Route_Block_Drive(Collections.emptyList(), SimulationMember.Type.DRIVER) { + @Override + public List buildStepList(Simulation simulation, SimulationMember targetMember, + Map params) { + return Collections.emptyList(); + } + + @Override + public Step execute(Simulation simulation, CommandBO command) { + VirtualRealityTrain train = (VirtualRealityTrain) command.getTargetMember().getDevice(); + if (train.isAMMode()) { + command.getTargetMember().setCommand(null); + } else { + getStep4ChangePreselectionMode(train, PreselectionMode.AM_C); + } + return null; + } + + }, /** - * 构建缓解EB的步骤 + * 道岔钩锁 */ - public static Step getStep4ReleaseEB(VirtualRealityTrain train) { - if (!train.isInTheGear(Handwheel.MANUAL)) { - return buildGearChangeStep(train.getGroupNumber(), Handwheel.MANUAL); + Switch_Hook_Lock(Arrays.asList(ParamName.switchCode, ParamName.normal), + SimulationMember.Type.STATION_SUPERVISOR) { + @Override + public List buildStepList(Simulation simulation, SimulationMember targetMember, + Map params) { + if (!SimulationMember.Type.STATION_SUPERVISOR.equals(targetMember.getType())) { + throw new SimulationException(SimulationExceptionType.Member_Is_Not_Station_Supervisor); } - if (!train.isStop() || !train.isLeverNotInTractionGear()) { - return buildDriverForceChangeOperationStep(train.getGroupNumber(), -2); + + List stepList = new ArrayList<>(); + String switchCode = (String) params.get(ParamName.switchCode.name()); + boolean normal = (boolean) params.get(ParamName.normal.name()); + stepList.add(buildSwitchHookLockOperationStep(switchCode, normal)); + + return stepList; + } + + @Override + public Step execute(Simulation simulation, CommandBO command) { + String switchCode = (String) command.getParams().get(ParamName.switchCode.name()); + Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class); + boolean normal = (boolean) command.getParams().get(ParamName.normal.name()); + if (aSwitch.getVirtualSwitch().isPosN() != normal) { + List steps = command.getStepByType(Step.StepType.OPERATION); + return steps.get(0); + } else { + command.getTargetMember().setCommand(null); } - if (!train.isRMMode()) { + return null; + } + }, + + /** + * 越红灯行驶 + */ + Drive_Through_The_Red_Light(Collections.emptyList(), SimulationMember.Type.DRIVER) { + @Override + public List buildStepList(Simulation simulation, SimulationMember targetMember, + Map params) { + if (!SimulationMember.Type.DRIVER.equals(targetMember.getType())) { + throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver); + } + + List stepList = new ArrayList<>(); + VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice(); + stepList.add(buildDriveStep(train.calculateStopPosition4CrossTheRedLight())); + stepList.add(buildCrossSignalStep( + train.getHeadPosition().getSection().getSignalOf(train.isRight()))); + stepList.add(buildRmToBmStep()); + + return stepList; + } + + @Override + public Step execute(Simulation simulation, CommandBO command) { + VirtualRealityTrain train = (VirtualRealityTrain) command.getTargetMember().getDevice(); + List steps = command.getStepByType(Step.StepType.DRIVE); + Step driveStep = steps.get(0); + boolean stopCorrectly = train.isStopAtThePosition(driveStep.getTargetPosition()); + if (stopCorrectly) { //如果列车已经停到目标位置 + driveStep.finish(); + command.getTargetMember().setCommand(null); + } else { + if (!DriveMode.RM.equals(train.getDriveMode()) && !train.isNRMMode()) { return getStep4ChangePreselectionMode(train, PreselectionMode.RM); + } + if (train.isSignalEB()) { + return getStep4ReleaseEB(train); + } + return driveStep; } return null; - } + } + }, - public static Step buildPreselectionModeUpOperationStep(String groupNumber) { - Map params = new HashMap<>(); - params.put("groupNumber", groupNumber); - Step step = new Step(); - step.setType(Step.StepType.OPERATION); - step.setOperationType(Operation.Type.Driver_Preselection_Mode_Up); - step.setOperationParams(params); - return step; - } + /** + * 越引导信号行驶 + */ + Drive_Through_The_Guide_Signal(Collections.emptyList(), SimulationMember.Type.DRIVER) { + @Override + public List buildStepList(Simulation simulation, SimulationMember targetMember, + Map params) { + if (!SimulationMember.Type.DRIVER.equals(targetMember.getType())) { + throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver); + } - public static Step buildPreselectionModeDownOperationStep(String groupNumber) { - Map params = new HashMap<>(); - params.put("groupNumber", groupNumber); - Step step = new Step(); - step.setType(Step.StepType.OPERATION); - step.setOperationType(Operation.Type.Driver_Preselection_Mode_Down); - step.setOperationParams(params); - return step; - } + List stepList = new ArrayList<>(); + VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice(); + stepList.add(buildDriveStep(calculateStepPosition4CrossTheGuideSignal(train))); + stepList.add(buildCrossSignalStep( + train.getHeadPosition().getSection().getSignalOf(train.isRight()))); - public static Step buildConfirmOperationStep(String groupNumber) { - Map params = new HashMap<>(); - params.put("groupNumber", groupNumber); - Step step = new Step(); - step.setType(Step.StepType.OPERATION); - step.setOperationType(Operation.Type.Driver_Confirm); - step.setOperationParams(params); - return step; - } + return stepList; + } - public static Step buildGearChangeStep(String groupNumber, Handwheel gear) { - Map params = new HashMap<>(); - params.put("groupNumber", groupNumber); - params.put("gear", gear); - Step step = new Step(); - step.setType(Step.StepType.OPERATION); - step.setOperationType(Operation.Type.Driver_Gear_Change); - step.setOperationParams(params); - return step; - } + @Override + public Step execute(Simulation simulation, CommandBO command) { + VirtualRealityTrain train = (VirtualRealityTrain) command.getTargetMember().getDevice(); + if (!train.isRMMode() && !train.isNRMMode()) { //既不是RM也不是NRM,切换预选模式 + return getStep4ChangePreselectionMode(train, PreselectionMode.RM); + } + if (!train.isInTheGear(Handwheel.MANUAL)) { //转手轮 + return buildGearChangeStep(train.getGroupNumber(), Handwheel.MANUAL); + } + List steps = command.getStepByType(Step.StepType.DRIVE); + Step driveStep = steps.get(0); + if (train.isStopAtThePosition(driveStep.getTargetPosition())) { //如果列车已经停到目标位置 + command.getTargetMember().setCommand(null); + } else { + return driveStep; + } + return null; + } + }, - public static Step getStep4ChangePreselectionMode(VirtualRealityTrain train, PreselectionMode preselectionMode) { - PreselectionMode trainMode = train.getPreselectionMode(); - PreselectionMode tempMode = train.getTempPreselectionMode(); - String groupNumber = train.getGroupNumber(); - if (trainMode != preselectionMode) { //预选级别不对 - if (tempMode != preselectionMode) { - if (preselectionMode.isHigherThan(tempMode)) { - return buildPreselectionModeUpOperationStep(groupNumber); - } else { - return buildPreselectionModeDownOperationStep(groupNumber); - } - } else /*if (ConfirmationMessage.Confirm_Preselection.equals(train.findFirstMessage()))*/ { - return buildConfirmOperationStep(groupNumber); + /** + * 开关门 + */ + Open_Or_Close_Door(Collections.emptyList(), SimulationMember.Type.DRIVER) { + @Override + public List buildStepList(Simulation simulation, SimulationMember targetMember, + Map params) { + if (!SimulationMember.Type.DRIVER.equals(targetMember.getType())) { + throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver); + } + + List stepList = new ArrayList<>(); + VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice(); + List standList = train.getHeadPosition().getSection().getStandList(); + if (!CollectionUtils.isEmpty(standList) && standList.size() == 1 && standList.get(0) + .isSmall()) { + // 小站台停车,无需开关门 + return null; + } + if (!train.getDoorByDirection(false).isCloseAndLock()) { //列车左门没关 + stepList.add(buildDoorOnOffOperationStep(train.getGroupNumber(), false, false)); + } else if (!train.getDoorByDirection(true).isCloseAndLock()) { //列车右门没关 + stepList.add(buildDoorOnOffOperationStep(train.getGroupNumber(), true, false)); + } else { + boolean doorIsRight; + for (Stand stand : standList) { + if (stand.isInside() && stand.isRight()) { // 内测右站台,开1门 + doorIsRight = train.judgeDirection4DoorIsRight(train.getDoor1()); + } else if (stand.isInside() && !stand.isRight()) { // 内测左站台,开2门 + doorIsRight = train.judgeDirection4DoorIsRight(train.getDoor2()); + } else if (!stand.isInside() && stand.isRight()) { //外侧右站台,开2门 + doorIsRight = train.judgeDirection4DoorIsRight(train.getDoor2()); + } else { + doorIsRight = train.judgeDirection4DoorIsRight(train.getDoor1()); } + stepList.add(buildDoorOnOffOperationStep(train.getGroupNumber(), doorIsRight, true)); + } + } + + return stepList; + } + + @Override + public Step execute(Simulation simulation, CommandBO command) { + VirtualRealityTrain train = (VirtualRealityTrain) command.getTargetMember().getDevice(); + List steps = command.getStepByType(Step.StepType.OPERATION); + Step step = steps.get(0); + VirtualRealityTrain.Door door = train.getDoorByDirection( + (boolean) step.getOperationParams().get("right")); + if (!Objects.equals(door.isOpen(), step.getOperationParams().get("open"))) { + return step; + } else { + command.getTargetMember().setCommand(null); + return null; + } + } + + }, + + /** + * 设置限速 + */ + Set_Speed_Limit(List.of(ParamName.speedLimit), SimulationMember.Type.DRIVER) { + @Override + public List buildStepList(Simulation simulation, SimulationMember targetMember, + Map 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())); + if (speedLimit < 0) { + train.setSpeedLimit(Float.MAX_VALUE); + } else { + train.setSpeedLimit(speedLimit / 3.6f); + } + command.getTargetMember().setCommand(null); + return null; + } + }, + + /** + * 换端 + */ + Turn_Direction(List.of(), SimulationMember.Type.DRIVER) { + @Override + public List buildStepList(Simulation simulation, SimulationMember targetMember, + Map 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<>(); + } + + @Override + public Step execute(Simulation simulation, CommandBO command) { + SimulationMember targetMember = command.getTargetMember(); + VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice(); + if (Objects.equals(train.isRight(), command.getParams().get(ParamName.trainRight.name()))) { + targetMember.setCommand(null); + return null; + } else { + return buildDriverChangeHeadOperateStep(train.getGroupNumber()); + } + } + }, + + /** + * 驾驶至 + */ + Drive_To(List.of(ParamName.sectionCode), SimulationMember.Type.DRIVER) { + @Override + public List buildStepList(Simulation simulation, SimulationMember targetMember, + Map params) { + return List.of(); + } + + @Override + public Step execute(Simulation simulation, CommandBO command) { + SimulationMember targetMember = command.getTargetMember(); + 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())); + if (train.isStopAtThePosition(targetPosition)) { + targetMember.setCommand(null); + return null; + } else { + return buildDriveStep(targetPosition); + } + } + }, + + /** + * 回库 + */ + Inbound(List.of(), SimulationMember.Type.DRIVER) { + @Override + public List buildStepList(Simulation simulation, SimulationMember targetMember, + Map params) { + return List.of(); + } + + @Override + public Step execute(Simulation simulation, CommandBO command) { + SimulationMember driver = command.getTargetMember(); + driver.setCommand(null); + VirtualRealityTrain train = (VirtualRealityTrain) driver.getDevice(); + Section headSection = train.getHeadPosition().getSection(); + if (headSection.isTransferTrack() && train.isStop()) { //列车停在折返轨 + SimulationDataRepository repository = simulation.getRepository(); + TrainInfo trainInfo = repository.getSupervisedTrainByGroup(train.getGroupNumber()); + List routePathList = repository.queryRoutePathsByEnd(headSection); + if (routePathList.get(0).isRight() == trainInfo.getRight()) { //准备回库 + trainInfo.finishPlanPrepareInbound(); + } } return null; + } + }, + + /** + * 修改预选模式 + */ + Change_Preselection_Mode(List.of(ParamName.preselectionMode), SimulationMember.Type.DRIVER) { + @Override + public List buildStepList(Simulation simulation, SimulationMember targetMember, + Map params) { + return Collections.emptyList(); + } + + @Override + public Step execute(Simulation simulation, CommandBO command) { + SimulationMember driver = command.getTargetMember(); + VirtualRealityTrain train = (VirtualRealityTrain) driver.getDevice(); + if (!train.isAtpOn()) { + return buildDriverATPChangeOperationStep(train.getGroupNumber(), false); + } + if (train.isSignalEB()) { + return getStep4ReleaseEB(train); + } + PreselectionMode preselectionMode = + PreselectionMode.valueOf( + (String) command.getParams().get(ParamName.preselectionMode.name())); + PreselectionMode trainMode = train.getPreselectionMode(); + if (trainMode != preselectionMode) { //预选级别不对 + return getStep4ChangePreselectionMode(train, preselectionMode); + } else if (trainMode.isNotLowerThanTheDriveMode(DriveMode.AM) && !train.isAMMode()) { + return getStep4OpenATO(train); + } else { + driver.setCommand(null); + } + return null; + } + }, + + /** + * 转NRM模式 + */ + Apply_NRM(List.of(), SimulationMember.Type.DRIVER) { + @Override + public List buildStepList(Simulation simulation, SimulationMember targetMember, + Map params) { + return Collections.emptyList(); + } + + @Override + public Step execute(Simulation simulation, CommandBO command) { + SimulationMember driver = command.getTargetMember(); + VirtualRealityTrain train = (VirtualRealityTrain) driver.getDevice(); + if (train.isNRMMode()) { + driver.setCommand(null); + return null; + } + return buildDriverATPChangeOperationStep(train.getGroupNumber(), true); + } + }, + + /** + * 大铁、发车 + **/ + Depart_Train(List.of(), SimulationMember.Type.DRIVER) { + @Override + public List buildStepList(Simulation simulation, SimulationMember targetMember, + Map params) { + VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice(); + boolean isRight = train.isRight(); // 列车运行方向 + Section section = train.getHeadPosition().getSection(); // 列车车头所在区段 + Section targetSection = getTargetSection(isRight, section); + List stepList = new ArrayList<>(); + if (targetSection != null) { + SectionPosition targetPosition = new SectionPosition(targetSection, + targetSection.getStopPointByDirection(isRight)); + // 设置目标位置 + stepList.add(buildDriveStep(targetPosition)); + } + return stepList; + } + + @Override + public Step execute(Simulation simulation, CommandBO command) { + VirtualRealityTrain train = (VirtualRealityTrain) command.getTargetMember().getDevice(); + boolean isOnline = simulation.getRepository().getUsedTrainMap() + .containsKey(train.getGroupNumber()); + if (!isOnline) { + command.getTargetMember().setCommand(null); + return null; + } + List steps = command.getStepByType(Step.StepType.DRIVE); + Step driveStep = steps.get(0); + if (train.isStopAtThePosition(driveStep.getTargetPosition())) { //如果列车已经停到目标位置 + boolean isRight = train.isRight(); // 列车运行方向 + Section section = train.getHeadPosition().getSection(); // 列车车头所在区段 + Section targetSection = getTargetSection(isRight, section); + if (Objects.equals(section, targetSection)) { + command.getTargetMember().setCommand(null); + } else { + SectionPosition targetPosition = new SectionPosition(targetSection, + targetSection.getStopPointByDirection(isRight)); + driveStep.setTargetPosition(targetPosition); + return driveStep; + } + } else { + SectionPosition sectionPosition = train.getHeadPosition(); + // 检查是否还可以向前行驶 + boolean checkResult = checkRunCondition(train.isRight(), sectionPosition.getSection()); + if (checkResult) { + return driveStep; + } else { + driveStep.setTargetPosition(sectionPosition); + command.getTargetMember().setCommand(null); + return null; + } + } + return null; + } + }, + + /** + * 大铁、停车 + */ + Parking_Train(List.of(), SimulationMember.Type.DRIVER) { + @Override + public List buildStepList(Simulation simulation, SimulationMember targetMember, + Map params) { + return Collections.emptyList(); + } + + @Override + public Step execute(Simulation simulation, CommandBO command) { + SimulationMember targetMember = command.getTargetMember(); + VirtualRealityTrain train = (VirtualRealityTrain) targetMember.getDevice(); + boolean isOnline = simulation.getRepository().getUsedTrainMap() + .containsKey(train.getGroupNumber()); + if (!isOnline) { + command.getTargetMember().setCommand(null); + return null; + } + if (train.isStop()) { + targetMember.setCommand(null); + } + // 设置目标位置 + return buildDriveStep(train.getHeadPosition()); + } + }; + + public enum ParamName { + stationCode, + switchCode, + /** + * 是否是定位(道岔) + */ + normal, + /** + * 是否是右边(要开/关的车门) + */ + right, + /** + * 是否是开启(车门) + */ + open, + /** + * 限速值 + */ + speedLimit, + /** + * 车头方向 + */ + trainRight, + sectionCode, + preselectionMode, + ; } + + private final List paramNames; + + private SimulationMember.Type memberType; + + CommandType(List paramNames, SimulationMember.Type memberType) { + this.paramNames = paramNames; + this.memberType = memberType; + } + + /** + * 构架指令步骤列表 + */ + public abstract List buildStepList(Simulation simulation, SimulationMember targetMember, + Map params); + + /** + * 执行指令,返回无法直接完成的指令 + */ + public abstract Step execute(Simulation simulation, CommandBO command); + + + /** + * 构建“开启ATO操作”步骤 + */ + public Step buildDriverAtoOpenOperationStep(String groupNumber) { + Map operationParams = new HashMap<>(); + operationParams.put("groupNumber", groupNumber); + Step step = new Step(); + step.setType(Step.StepType.OPERATION); + step.setOperationType(Operation.Type.Driver_ATO_Open); + step.setOperationParams(operationParams); + return step; + } + + /** + * 构建道岔钩锁操作步骤 + */ + public Step buildSwitchHookLockOperationStep(String switchCode, Boolean normal) { + Map operationParams = new HashMap<>(); + operationParams.put("switchCode", switchCode); + operationParams.put("normal", normal); + Step step = new Step(); + step.setType(Step.StepType.OPERATION); + step.setOperationType(Operation.Type.Switch_Hook_Lock); + step.setOperationParams(operationParams); + return step; + } + + /** + * 构建”开关车门操作“步骤 + */ + public Step buildDoorOnOffOperationStep(String groupNumber, boolean right, boolean open) { + Map operationParams = new HashMap<>(); + operationParams.put("groupNumber", groupNumber); + operationParams.put("right", right); + operationParams.put("open", open); + Step step = new Step(); + step.setType(Step.StepType.OPERATION); + step.setOperationType(Operation.Type.Driver_Door_On_Off); + step.setOperationParams(operationParams); + return step; + } + + public Step buildDriverChangeHeadOperateStep(String groupNumber) { + Map operationParams = new HashMap<>(); + operationParams.put("groupNumber", groupNumber); + Step step = new Step(); + step.setType(Step.StepType.OPERATION); + step.setOperationType(Operation.Type.Driver_Change_Head); + step.setOperationParams(operationParams); + return step; + } + + public Step buildDriverATPChangeOperationStep(String groupNumber, boolean cutOff) { + Map operationParams = new HashMap<>(); + operationParams.put("groupNumber", groupNumber); + operationParams.put("cutOff", cutOff); + Step step = new Step(); + step.setType(Step.StepType.OPERATION); + step.setOperationType(Operation.Type.Driver_ATP_Change); + step.setOperationParams(operationParams); + return step; + } + + /** + * 构建“驾驶”步骤 + */ + public Step buildDriveStep(SectionPosition targetPosition) { + Step step = new Step(); + step.setType(Step.StepType.DRIVE); + step.setTargetPosition(targetPosition); + return step; + } + + /** + * 构建“rm升bm”步骤 + */ + public Step buildRmToBmStep() { + Step step = new Step(); + step.setType(Step.StepType.RM_TO_BM); + return step; + } + + /** + * 构建“越过信号机”步骤 + */ + public Step buildCrossSignalStep(Signal signal) { + Step step = new Step(); + step.setType(Step.StepType.CROSS_SIGNAL); + step.setCrossSignal(signal); + return step; + } + + public Step getStep4OpenATO(VirtualRealityTrain train) { + String groupNumber = train.getGroupNumber(); + if (!train.isAtpOn()) { + return buildDriverATPChangeOperationStep(groupNumber, false); + } + if (!train.isInTheGear(Handwheel.ATO)) { + return buildGearChangeStep(groupNumber, Handwheel.ATO); + } + if (!train.isLeverInCoastingGear()) { + return buildDriverForceChangeOperationStep(groupNumber, 0); + } + if (!train.isAtoOn()) { + return buildDriverAtoOpenOperationStep(groupNumber); + } + return null; + } + + /** + * 计算越引导信号行驶的停车位置 + */ + public SectionPosition calculateStepPosition4CrossTheGuideSignal(VirtualRealityTrain train) { + boolean right = train.isRight(); + SectionPosition headPosition = train.getHeadPosition(); + Section section = headPosition.getSection(); + Signal trainHeadSignal = section.getSignalOf(right); + if (trainHeadSignal == null || !trainHeadSignal.isGuideAspect()) { + 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, + "引导信号前方未找到停车位置"); + Signal signal = section.getSignalOf(right); + if (section.isStandTrack() || section.isTurnBackTrack()) { + sectionPosition = new SectionPosition(section, section.getStopPointByDirection(right)); + break; + } else if (signal != null && !signal.isShunting() && !signal.isMainAspect()) { //同向信号机未正常开放 + sectionPosition = new SectionPosition(section, signal.getOffset()); + break; + } + } + if (sectionPosition == null) { + throw new SimulationException(SimulationExceptionType.Invalid_Operation, + "引导信号前方未找到停车位置"); + } + return sectionPosition; + } + + /** + * 从此区段向right方向获取未被占用的目标区段 + * + * @param isRight 方向 + * @param section 起始区段 + * @return 目标区段 + */ + public Section getTargetSection(boolean isRight, Section section) { + boolean loop = true; + Signal signal; + Section nextSection = section, targetSection = null; + while (loop) { + signal = isRight ? nextSection.getSignalToRight() : nextSection.getSignalToLeft(); // 方向信号机 + // 信号机未开放,直接中断 + if (signal != null && SignalAspect.R.equals(signal.getAspect())) { + targetSection = nextSection; + break; + } + // 存在锁闭进路,获取进路末端 + if (signal != null && signal.getLockedRoute() != null) { + nextSection = signal.getLockedRoute().getDestination().getSection(); + } else if (nextSection.isRouteLock()) { // 如果当前区段进路锁闭 + nextSection = nextSection.getRoute().getDestination().getSection(); + } else if (nextSection.isSwitchTrack()) { // 是邻近岔道 + nextSection = nextSection.getNextRunningSectionOf(isRight); + } else { + nextSection = nextSection.getNextSection(isRight); + } + // 存在邻近区段,赋值 + if (nextSection != null) { + targetSection = nextSection; + } + // 进路存在且不占用不出故障 + loop = nextSection != null && !nextSection.isOccupied() && !nextSection.isFaultLock(); + } + return targetSection; + } + + /** + * 大铁列车运行时,检查是否还可以向前行驶 + * + * @param isRight 方向 + * @param section 起始区段 + * @return 行驶区段 + */ + public boolean checkRunCondition(boolean isRight, Section section) { + Signal signal = isRight ? section.getSignalToRight() : section.getSignalToLeft(); // 方向信号机 + // 信号机未开放,直接中断 + if (signal != null && SignalAspect.R.equals(signal.getAspect())) { + return false; + } + return true; + } + } + + /** + * 构建“改变列车牵引/制动力操作”步骤 + */ + public static Step buildDriverForceChangeOperationStep(String groupNumber, float percent) { + Map operationParams = new HashMap<>(); + operationParams.put("groupNumber", groupNumber); + operationParams.put("percent", percent); + Step step = new Step(); + step.setType(Step.StepType.OPERATION); + step.setOperationType(Operation.Type.Driver_Force_Change); + step.setOperationParams(operationParams); + return step; + } + + /** + * 构建缓解EB的步骤 + */ + public static Step getStep4ReleaseEB(VirtualRealityTrain train) { + if (!train.isInTheGear(Handwheel.MANUAL)) { + return buildGearChangeStep(train.getGroupNumber(), Handwheel.MANUAL); + } + if (!train.isStop() || !train.isLeverNotInTractionGear()) { + return buildDriverForceChangeOperationStep(train.getGroupNumber(), -2); + } + if (!train.isRMMode()) { + return getStep4ChangePreselectionMode(train, PreselectionMode.RM); + } + return null; + } + + public static Step buildPreselectionModeUpOperationStep(String groupNumber) { + Map params = new HashMap<>(); + params.put("groupNumber", groupNumber); + Step step = new Step(); + step.setType(Step.StepType.OPERATION); + step.setOperationType(Operation.Type.Driver_Preselection_Mode_Up); + step.setOperationParams(params); + return step; + } + + public static Step buildPreselectionModeDownOperationStep(String groupNumber) { + Map params = new HashMap<>(); + params.put("groupNumber", groupNumber); + Step step = new Step(); + step.setType(Step.StepType.OPERATION); + step.setOperationType(Operation.Type.Driver_Preselection_Mode_Down); + step.setOperationParams(params); + return step; + } + + public static Step buildConfirmOperationStep(String groupNumber) { + Map params = new HashMap<>(); + params.put("groupNumber", groupNumber); + Step step = new Step(); + step.setType(Step.StepType.OPERATION); + step.setOperationType(Operation.Type.Driver_Confirm); + step.setOperationParams(params); + return step; + } + + public static Step buildGearChangeStep(String groupNumber, Handwheel gear) { + Map params = new HashMap<>(); + params.put("groupNumber", groupNumber); + params.put("gear", gear); + Step step = new Step(); + step.setType(Step.StepType.OPERATION); + step.setOperationType(Operation.Type.Driver_Gear_Change); + step.setOperationParams(params); + return step; + } + + public static Step getStep4ChangePreselectionMode(VirtualRealityTrain train, + PreselectionMode preselectionMode) { + PreselectionMode trainMode = train.getPreselectionMode(); + PreselectionMode tempMode = train.getTempPreselectionMode(); + String groupNumber = train.getGroupNumber(); + if (trainMode != preselectionMode) { //预选级别不对 + if (tempMode != preselectionMode) { + if (preselectionMode.isHigherThan(tempMode)) { + return buildPreselectionModeUpOperationStep(groupNumber); + } else { + return buildPreselectionModeDownOperationStep(groupNumber); + } + } else /*if (ConfirmationMessage.Confirm_Preselection.equals(train.findFirstMessage()))*/ { + return buildConfirmOperationStep(groupNumber); + } + } + return null; + } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/data/vr/VirtualRealityTrain.java b/src/main/java/club/joylink/rtss/simulation/cbtc/data/vr/VirtualRealityTrain.java index 37cf3bed9..854e0471f 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/data/vr/VirtualRealityTrain.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/data/vr/VirtualRealityTrain.java @@ -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; /** * 虚拟真实列车 @@ -32,1512 +35,1548 @@ import java.util.Objects; @Setter public class VirtualRealityTrain extends VirtualRealityDevice { - // -----------列车公共属性----------- - /** - * 紧急制动加速度(矢量) - */ - public static final float Emergency_Acceleration = -1.5f; + // -----------列车公共属性----------- + /** + * 紧急制动加速度(矢量) + */ + public static final float Emergency_Acceleration = -1.5f; - /** - * 紧急制动触发曲线计算加速度(矢量) - */ - public static final float Emergency_Trigger_Acceleration = -1.1f; + /** + * 紧急制动触发曲线计算加速度(矢量) + */ + public static final float Emergency_Trigger_Acceleration = -1.1f; - /** - * 非紧急制动状态下最大制动加速度(标量) - */ - public static final float Max_Braking_Acceleration = 0.55f; + /** + * 非紧急制动状态下最大制动加速度(标量) + */ + public static final float Max_Braking_Acceleration = 0.55f; - /** - * 舒适加速度(标量),单位m/s^2 - */ - public static final float Stable_Acceleration = 1.2f; + /** + * 舒适加速度(标量),单位m/s^2 + */ + public static final float Stable_Acceleration = 1.2f; - /** - * 系统固定阻力(矢量),单位KN - */ - public static final float System_Fixed_Resistance = -5f; + /** + * 系统固定阻力(矢量),单位KN + */ + public static final float System_Fixed_Resistance = -5f; - /** - * 允许的速度误差值(单位km/h) - */ - public static final float Speed_Error = 0.1f; + /** + * 允许的速度误差值(单位km/h) + */ + public static final float Speed_Error = 0.1f; - /** - * RM模式下ATP防护速度(单位km/h) - */ - public static final float RM_ATP_Speed = 25 / 3.6f; + /** + * RM模式下ATP防护速度(单位km/h) + */ + public static final float RM_ATP_Speed = 25 / 3.6f; - public static final int Responders_Record = 2; + public static final int Responders_Record = 2; - // -----------列车基础属性----------- - /** - * 列车长度 - */ - private float len; + // -----------列车基础属性----------- + /** + * 列车长度 + */ + private float len; - /** - * 列车质量 单位t - */ - private float mass = 230; + /** + * 列车质量 单位t + */ + private float mass = 230; - /** - * 列车前进最大速度 - */ - private float speedMax = (float) (80 / 3.6); + /** + * 列车前进最大速度 + */ + private float speedMax = (float) (80 / 3.6); - /** - * 列车倒车最大速度 - */ - private float reverseSpeedMax = (float) (36 / 3.6); + /** + * 列车倒车最大速度 + */ + private float reverseSpeedMax = (float) (36 / 3.6); - /** - * 列车ATP防护速度 - */ - private float atpSpeedMax = (float) (80 / 3.6); + /** + * 列车ATP防护速度 + */ + private float atpSpeedMax = (float) (80 / 3.6); - /** - * 车组号 - */ - private String groupNumber; + /** + * 车组号 + */ + private String groupNumber; - /** - * 最大功率(单位w) - */ - private Float maximumPower = 3583333f; + /** + * 最大功率(单位w) + */ + private Float maximumPower = 3583333f; - /** - * 所属停车场/车辆段 - */ - private Station depotStation; + /** + * 所属停车场/车辆段 + */ + private Station depotStation; - // -----------列车运行属性----------- + // -----------列车运行属性----------- - /** - * 是否没有通信设备 - */ - private boolean noCommunicateDevice; - /** - * 车载服务通讯是否正常在线 - */ - private boolean communication; - /** - * 列车运行级别 - */ - private RunLevel runLevel; + /** + * 是否没有通信设备 + */ + private boolean noCommunicateDevice; + /** + * 车载服务通讯是否正常在线 + */ + private boolean communication; + /** + * 列车运行级别 + */ + private RunLevel runLevel; - /** - * 驾驶模式 - */ - private DriveMode driveMode; + /** + * 驾驶模式 + */ + private DriveMode driveMode; - /** - * 临时预选模式 - */ - private PreselectionMode tempPreselectionMode; + /** + * 临时预选模式 + */ + private PreselectionMode tempPreselectionMode; - /** - * 预选模式 - */ - private PreselectionMode preselectionMode; + /** + * 预选模式 + */ + private PreselectionMode preselectionMode; - /** - * 服务号 - */ - private String serviceNumber; + /** + * 服务号 + */ + private String serviceNumber; - /** - * 车次号 - */ - private String tripNumber; + /** + * 车次号 + */ + private String tripNumber; - /** - * 目的地码 - */ - private String destinationCode; + /** + * 目的地码 + */ + private String destinationCode; - /** - * 下一站 - */ - private Station nextStation; + /** + * 下一站 + */ + private Station nextStation; - /** - * 即将到站 - */ - private boolean beAbout2Arrive; + /** + * 即将到站 + */ + private boolean beAbout2Arrive; - /** - * 目标达到区段 - */ - private Section target; + /** + * 目标达到区段 + */ + private Section target; - /** - * 站台停靠时间,单位ms - */ - private int parkTime; + /** + * 站台停靠时间,单位ms + */ + private int parkTime; - /** - * 停站剩余时间,单位ms - */ - private int parkRemainTime; + /** + * 停站剩余时间,单位ms + */ + private int parkRemainTime; - /** - * 最后一次停站的区段 - */ - private Section parkSection; + /** + * 最后一次停站的区段 + */ + private Section parkSection; - /** - * 发车提示 - */ - private boolean departure; + /** + * 发车提示 + */ + private boolean departure; - /** - * 制动 - */ - private boolean breaking; + /** + * 制动 + */ + private boolean breaking; - /** - * 终点站 - */ - private Station terminalStation; + /** + * 终点站 + */ + private Station terminalStation; - /** - * 车头位置 - */ - private SectionPosition headPosition; - /** - * 车尾位置 - */ - private SectionPosition tailPosition; + /** + * 车头位置 + */ + private SectionPosition headPosition; + /** + * 车尾位置 + */ + private SectionPosition tailPosition; - /** - * 是否向右行驶 - */ - private boolean right; + /** + * 是否向右行驶 + */ + private boolean right; - /** - * 移动授权 - */ - private MovementAuthority ma; - /** - * 移动授权 - */ - private MaService.Ma ma2; + /** + * 移动授权 + */ + private MovementAuthority ma; + /** + * 移动授权 + */ + private MaService.Ma ma2; - /** - * 未收到CBTC级别ma的时长,单位毫秒 - */ - private int cbtcMaMissDuration = 0; + /** + * 未收到CBTC级别ma的时长,单位毫秒 + */ + private int cbtcMaMissDuration = 0; - /** - * 工况手轮 - */ - private Handwheel gear; + /** + * 工况手轮 + */ + private Handwheel gear; - /** - * 实际运行速度(m/s) - */ - private float speed; + /** + * 实际运行速度(m/s) + */ + private float speed; - /** - * 公里标 - */ - private float locationKM; - /** - * 目标距离 - */ - private float targetDistance; + /** + * 公里标 + */ + private float locationKM; + /** + * 目标距离 + */ + private float targetDistance; - /** - * ATO最大速度 - */ - private float atoSpeedMax = this.atpSpeedMax * 0.9f; + /** + * ATO最大速度 + */ + private float atoSpeedMax = this.atpSpeedMax * 0.9f; - /** - * ATO推荐速度 - */ - private float atoSpeed; + /** + * ATO推荐速度 + */ + private float atoSpeed; - /** - * ATP防护速度 - */ - private float atpSpeed; + /** + * ATP防护速度 + */ + private float atpSpeed; - /** - * 是否紧急停车(信号) - */ - private boolean signalEB; + /** + * 是否紧急停车(信号) + */ + private boolean signalEB; - /** - * 是否紧急停车(电路) - */ - private boolean circuitEB; + /** + * 是否紧急停车(电路) + */ + private boolean circuitEB; - /** - * 站台停靠列车动作 - */ - private StandParkedTrainActivity standParkedTrainActivity; + /** + * 站台停靠列车动作 + */ + private StandParkedTrainActivity standParkedTrainActivity; - /** - * 下一计划是否停站 - */ - private boolean nextParking; + /** + * 下一计划是否停站 + */ + private boolean nextParking; - /** - * 跳站信息 - */ - private boolean jump; + /** + * 跳站信息 + */ + private boolean jump; - /** - * 是否扣车 - */ - private boolean hold; + /** + * 是否扣车 + */ + private boolean hold; - /** - * 当前扣车是否是列车扣车(联合hold使用) - */ - private boolean trainHold; + /** + * 当前扣车是否是列车扣车(联合hold使用) + */ + private boolean trainHold; - /** - * 是否自动折返中 - */ - private boolean dtro; + /** + * 是否自动折返中 + */ + private boolean dtro; - /** - * 是否换端中 - */ - private boolean changeEnds; + /** + * 是否换端中 + */ + private boolean changeEnds; - /** - * 换端剩余时间,单位ms - */ - private int changeEndsRemainTime; + /** + * 换端剩余时间,单位ms + */ + private int changeEndsRemainTime; - /** - * ATO是否开启 - */ - private boolean atoOn; + /** + * ATO是否开启 + */ + private boolean atoOn; - /** - * ATP是否可用 - */ - private boolean atpOn; + /** + * ATP是否可用 + */ + private boolean atpOn; - /** - * 进路优先排列 - */ - private boolean priorityRouteSet; + /** + * 进路优先排列 + */ + private boolean priorityRouteSet; - /** - * 门1 - */ - private Door door1; + /** + * 门1 + */ + private Door door1; - /** - * 门2 - */ - private Door door2; + /** + * 门2 + */ + private Door door2; - /** - * 门模式 - */ - private DoorMode doorMode; + /** + * 门模式 + */ + private DoorMode doorMode; - /** - * 门选 - */ - private DoorSelection doorSelection; + /** + * 门选 + */ + private DoorSelection doorSelection; - /** - * 牵引力,单位kN - * 公式 fk = 350 (0 <= v <= 36km/h) - * fk = 12900 / v (36 < v < 80km/h) - */ - private float fk; + /** + * 牵引力,单位kN 公式 fk = 350 (0 <= v <= 36km/h) fk = 12900 / v (36 < v < 80km/h) + */ + private float fk; - /** - * 制动力,单位kN - */ - private float fb; + /** + * 制动力,单位kN + */ + private float fb; - /** - * 列车牵引/制动状态 - */ - private TrainTBControl tbControl; + /** + * 列车牵引/制动状态 + */ + private TrainTBControl tbControl; // /** // * 阻力(暂时视为恒定)(矢量) // */ 没有地方用到 // private float resistance = -0.05f * mass; - /** - * 控制杆的位置(-1~1) - */ - private float leverPosition = 0; + /** + * 控制杆的位置(-1~1) + */ + private float leverPosition = 0; - private Fault fault; + private Fault fault; - /** - * 备用车 - */ - private boolean backUp; + /** + * 备用车 + */ + private boolean backUp; - /** - * 关门后的延迟发车时间(单位ms) - */ - private int delayTime = 0; + /** + * 关门后的延迟发车时间(单位ms) + */ + private int delayTime = 0; - /** - * 是否通电 - */ - private boolean powerOn = true; + /** + * 是否通电 + */ + private boolean powerOn = true; - /** - * 受电弓1是否升起 - */ - private boolean pantograph1Up = true; + /** + * 受电弓1是否升起 + */ + private boolean pantograph1Up = true; - /** - * 受电弓2是否升起 - */ - private boolean pantograph2Up = true; + /** + * 受电弓2是否升起 + */ + private boolean pantograph2Up = true; - /** - * 连挂的列车 - */ - private VirtualRealityTrain linkTrain; + /** + * 连挂的列车 + */ + private VirtualRealityTrain linkTrain; - /** - * 运行类型 - */ - private RunType runType; + /** + * 运行类型 + */ + private RunType runType; - /** - * 下令停车 - */ - private boolean orderStop; + /** + * 下令停车 + */ + private boolean orderStop; - /** - * 需要发车命令才能列车才能移动 - */ - private boolean needDepartureCommand; + /** + * 需要发车命令才能列车才能移动 + */ + private boolean needDepartureCommand; - /** - * 有定位 - */ - private boolean positioned = true; + /** + * 有定位 + */ + private boolean positioned = true; - /** - * 运行时间/ms - */ - private int runningTime; + /** + * 运行时间/ms + */ + private int runningTime; - /** - * 释放信号(在ITC级别下,列车站台停靠,前方信号机开放信号后,司机可按下释放按钮, - * 列车会以低速通过信号机,通过信号机的过程中接收主应答器的ITC移动授权,就可以在ITC-MA的防护下ATO以正常速度驾驶) - */ - private boolean released; + /** + * 释放信号(在ITC级别下,列车站台停靠,前方信号机开放信号后,司机可按下释放按钮, + * 列车会以低速通过信号机,通过信号机的过程中接收主应答器的ITC移动授权,就可以在ITC-MA的防护下ATO以正常速度驾驶) + */ + private boolean released; - /** - * 确认信息 - */ - private final LinkedHashSet confirmationMessages = new LinkedHashSet<>(); + /** + * 确认信息 + */ + private final LinkedHashSet confirmationMessages = new LinkedHashSet<>(); - /** - * ato可以开启 - */ - private boolean atoCanOpen; + /** + * ato可以开启。此状态仅用以前端显示,因为此状态更新不及时,使用起来比较麻烦 + */ + private boolean atoCanOpen; - /** - * 由用户接管列车操控任务 - */ - private boolean takeOver; + /** + * 由用户接管列车操控任务 + */ + private boolean takeOver; // private VirtualRealityAudio vrAudio; - private DriveParamVO robotDriveParam = new DriveParamVO(); + private DriveParamVO robotDriveParam = new DriveParamVO(); - /** - * 为解决地铁和大铁列车最高速度不同的问题 - * - * @param railway 是大铁线路?如果是,将最高速度改为320km/h - * @param manualTrainDefaultStop - */ - public VirtualRealityTrain(String code, String groupNumber, boolean railway, boolean manualTrainDefaultStop) { - super(code, groupNumber, DeviceType.TRAIN); - this.groupNumber = groupNumber; - this.gear = Handwheel.ATO; - this.communication = true; - this.atpOn = true; - this.door1 = new Door(this, "1"); - this.door2 = new Door(this, "2"); - this.doorMode = DoorMode.AM; - this.tempPreselectionMode = PreselectionMode.AM_C; - this.preselectionMode = PreselectionMode.AM_C; - this.doorSelection = DoorSelection.Z; - this.confirmationMessages.clear(); - if (railway) { - this.speedMax = (80 * 4) / 3.6f; - } - robotDriveParam.setDefaultStop(manualTrainDefaultStop); + /** + * 为解决地铁和大铁列车最高速度不同的问题 + * + * @param railway 是大铁线路?如果是,将最高速度改为320km/h + * @param manualTrainDefaultStop + */ + public VirtualRealityTrain(String code, String groupNumber, boolean railway, + boolean manualTrainDefaultStop) { + super(code, groupNumber, DeviceType.TRAIN); + this.groupNumber = groupNumber; + this.gear = Handwheel.ATO; + this.communication = true; + this.atpOn = true; + this.door1 = new Door(this, "1"); + this.door2 = new Door(this, "2"); + this.doorMode = DoorMode.AM; + this.tempPreselectionMode = PreselectionMode.AM_C; + this.preselectionMode = PreselectionMode.AM_C; + this.doorSelection = DoorSelection.Z; + this.confirmationMessages.clear(); + if (railway) { + this.speedMax = (80 * 4) / 3.6f; } + robotDriveParam.setDefaultStop(manualTrainDefaultStop); + } - public SectionPosition getTailPosition() { - return this.tailPosition == null ? calculateTailPosition() : this.tailPosition; - } + public SectionPosition getTailPosition() { + return this.tailPosition == null ? calculateTailPosition() : this.tailPosition; + } - public void setCommunication(boolean communication) { - if ((Fault.COMMUNICATION_ABNORMAL.equals(this.fault) || !atpOn || this.noCommunicateDevice) && communication) - return; - this.communication = communication; - } + public void setCommunication(boolean communication) { + if ((Fault.COMMUNICATION_ABNORMAL.equals(this.fault) || !atpOn || this.noCommunicateDevice) + && communication) { + return; + } + this.communication = communication; + } - public void setRunType(RunType runType) { - this.runType = runType; - if (runType != null) { - switch (runType) { - case ENERGY_CONSERVATION: - this.atoSpeedMax = this.atpSpeedMax * 0.2f * 0.9f; - break; - case MIDDLE_TWO: - this.atoSpeedMax = this.atpSpeedMax * 0.4f * 0.9f; - break; - case MIDDLE_ONE: - this.atoSpeedMax = this.atpSpeedMax * 0.6f * 0.9f; - break; - case NORMAL: - this.atoSpeedMax = this.atpSpeedMax * 0.8f * 0.9f; - break; - case ACCELERATE: - this.atoSpeedMax = this.atpSpeedMax * 0.9f; - break; - } - } + public void setRunType(RunType runType) { + this.runType = runType; + if (runType != null) { + switch (runType) { + case ENERGY_CONSERVATION: + this.atoSpeedMax = this.atpSpeedMax * 0.2f * 0.9f; + break; + case MIDDLE_TWO: + this.atoSpeedMax = this.atpSpeedMax * 0.4f * 0.9f; + break; + case MIDDLE_ONE: + this.atoSpeedMax = this.atpSpeedMax * 0.6f * 0.9f; + break; + case NORMAL: + this.atoSpeedMax = this.atpSpeedMax * 0.8f * 0.9f; + break; + case ACCELERATE: + this.atoSpeedMax = this.atpSpeedMax * 0.9f; + break; + } } + } - public void setAtoSpeedMax(float atoSpeedMax) { - if (runType != null) { - return; - } - this.atoSpeedMax = atoSpeedMax; + public void setAtoSpeedMax(float atoSpeedMax) { + if (runType != null) { + return; } + this.atoSpeedMax = atoSpeedMax; + } - public void resetAtoSpeedMax() { - this.atoSpeedMax = this.atpSpeedMax * 0.9f; - } + public void resetAtoSpeedMax() { + this.atoSpeedMax = this.atpSpeedMax * 0.9f; + } - public void setAtpOn(boolean on) { - this.atpOn = on; - if (!on) { //如果是关闭ATP,取消信号EB - this.setSignalEB(false); - this.communication = false; - this.setAtoSpeed(-1); - this.setAtpSpeed(-1); - } + public void setAtpOn(boolean on) { + this.atpOn = on; + if (!on) { //如果是关闭ATP,取消信号EB + this.setSignalEB(false); + this.communication = false; + this.setAtoSpeed(-1); + this.setAtpSpeed(-1); } + } - @Override - public void reset() { - this.noCommunicateDevice = false; - this.communication = true; - this.runLevel = null; - this.driveMode = null; - this.tempPreselectionMode = PreselectionMode.AM_C; - this.preselectionMode = null; - this.serviceNumber = null; - this.tripNumber = null; - this.destinationCode = null; - this.nextStation = null; - this.beAbout2Arrive = false; - this.target = null; - this.parkTime = 0; - this.parkRemainTime = 0; - this.parkSection = null; - this.departure = false; - this.breaking = false; - this.standParkedTrainActivity = null; - this.nextParking = false; - this.jump = false; - this.hold = false; - this.trainHold = false; - this.terminalStation = null; - this.headPosition = null; - this.ma2 = null; - this.ma = null; - this.cbtcMaMissDuration = 0; - this.gear = null; - this.speed = 0; - this.targetDistance = 0; - resetAtoSpeedMax(); - this.atoSpeed = 0; - this.atpSpeed = 0; - this.signalEB = false; - this.circuitEB = false; - this.dtro = false; - this.changeEnds = false; - this.changeEndsRemainTime = 0; - this.atoOn = false; - this.atpOn = false; - this.fk = 0; - this.fb = 0; - this.tbControl = null; - this.leverPosition = 0; - this.delayTime = 0; - this.powerOn = true; - this.pantograph1Up = true; - this.pantograph2Up = true; - this.linkTrain = null; - this.runType = null; - this.orderStop = false; - this.needDepartureCommand = false; - this.positioned = true; - this.runningTime = 0; - this.fault = null; - this.released = false; - this.doorMode = DoorMode.AM; - this.doorSelection = DoorSelection.Z; - this.confirmationMessages.clear(); - this.atoCanOpen = false; + @Override + public void reset() { + this.noCommunicateDevice = false; + this.communication = true; + this.runLevel = null; + this.driveMode = null; + this.tempPreselectionMode = PreselectionMode.AM_C; + this.preselectionMode = null; + this.serviceNumber = null; + this.tripNumber = null; + this.destinationCode = null; + this.nextStation = null; + this.beAbout2Arrive = false; + this.target = null; + this.parkTime = 0; + this.parkRemainTime = 0; + this.parkSection = null; + this.departure = false; + this.breaking = false; + this.standParkedTrainActivity = null; + this.nextParking = false; + this.jump = false; + this.hold = false; + this.trainHold = false; + this.terminalStation = null; + this.headPosition = null; + this.ma2 = null; + this.ma = null; + this.cbtcMaMissDuration = 0; + this.gear = null; + this.speed = 0; + this.targetDistance = 0; + resetAtoSpeedMax(); + this.atoSpeed = 0; + this.atpSpeed = 0; + this.signalEB = false; + this.circuitEB = false; + this.dtro = false; + this.changeEnds = false; + this.changeEndsRemainTime = 0; + this.atoOn = false; + this.atpOn = false; + this.fk = 0; + this.fb = 0; + this.tbControl = null; + this.leverPosition = 0; + this.delayTime = 0; + this.powerOn = true; + this.pantograph1Up = true; + this.pantograph2Up = true; + this.linkTrain = null; + this.runType = null; + this.orderStop = false; + this.needDepartureCommand = false; + this.positioned = true; + this.runningTime = 0; + this.fault = null; + this.released = false; + this.doorMode = DoorMode.AM; + this.doorSelection = DoorSelection.Z; + this.confirmationMessages.clear(); + this.atoCanOpen = false; - boolean defaultStop = this.robotDriveParam.isDefaultStop(); - this.robotDriveParam = new DriveParamVO(); - if (defaultStop) { - this.robotDriveParam.setDefaultStop(true); - this.robotDriveParam.setStop(true); - this.robotDriveParam.setRun(false); - } + boolean defaultStop = this.robotDriveParam.isDefaultStop(); + this.robotDriveParam = new DriveParamVO(); + if (defaultStop) { + this.robotDriveParam.setDefaultStop(true); + this.robotDriveParam.setStop(true); + this.robotDriveParam.setRun(false); } + } - public boolean isEB() { - return this.signalEB || this.circuitEB; - } + public boolean isEB() { + return this.signalEB || this.circuitEB; + } - /** - * 是否CBTC运行级列车 - * - * @return - */ - public boolean isCBTC() { - return Objects.equals(RunLevel.CBTC, this.runLevel); - } + /** + * 是否CBTC运行级列车 + * + * @return + */ + public boolean isCBTC() { + return Objects.equals(RunLevel.CBTC, this.runLevel); + } - /** - * 是否ITC运行级别 - * - * @return - */ - public boolean isITC() { - return Objects.equals(RunLevel.ITC, this.runLevel); - } + /** + * 是否ITC运行级别 + * + * @return + */ + public boolean isITC() { + return Objects.equals(RunLevel.ITC, this.runLevel); + } - public boolean isIL() { - return Objects.equals(RunLevel.IL, this.runLevel); - } + public boolean isIL() { + return Objects.equals(RunLevel.IL, this.runLevel); + } - /** - * 初始化方向和位置 - * - * @param right - * @param headPosition - */ - public void initPosition(boolean right, SectionPosition headPosition) { - Objects.requireNonNull(headPosition); - this.right = right; - this.headPosition = headPosition; - } + /** + * 初始化方向和位置 + * + * @param right + * @param headPosition + */ + public void initPosition(boolean right, SectionPosition headPosition) { + Objects.requireNonNull(headPosition); + this.right = right; + this.headPosition = headPosition; + } - /** - * 设置计划 - * - * @param plan - */ - public synchronized void setPlan(TripPlan plan) { - this.serviceNumber = plan.getServiceNumber(); - this.tripNumber = plan.getTripNumber(); - this.destinationCode = plan.getDestinationCode(); - this.terminalStation = plan.getLastStationPlan().getStation(); - this.backUp = plan.isBackup(); - } + /** + * 设置计划 + * + * @param plan + */ + public synchronized void setPlan(TripPlan plan) { + this.serviceNumber = plan.getServiceNumber(); + this.tripNumber = plan.getTripNumber(); + this.destinationCode = plan.getDestinationCode(); + this.terminalStation = plan.getLastStationPlan().getStation(); + this.backUp = plan.isBackup(); + } - public void initPlanTrain(SectionPosition headPosition, boolean right, TripPlan tripPlan) { - this.initPosition(right, headPosition); - this.setPlan(tripPlan); - init(); - } + public void initPlanTrain(SectionPosition headPosition, boolean right, TripPlan tripPlan) { + this.initPosition(right, headPosition); + this.setPlan(tripPlan); + init(); + } - /** - * 初始化人工车 - */ - public void initManualTrain(SectionPosition headPosition, boolean right) { - this.initPosition(right, headPosition); - init(); - } - public void initManualTrain(SectionPosition headPosition, boolean right, TrainPosition tp) { - this.initPosition(right, headPosition); - init(); - this.speed = tp.getSpeed(); - this.locationKM = tp.getLocation(); - this.right = tp.isRight(); - } - private void init() { - this.communication = true; - this.jump = false; - this.hold = false; - this.standParkedTrainActivity = null; - this.runLevel = RunLevel.CBTC; - this.driveMode = DriveMode.AM; - this.tempPreselectionMode = PreselectionMode.AM_C; - this.preselectionMode = PreselectionMode.AM_C; - this.speed = 0; - this.atoSpeed = 0; - this.atpSpeed = 0; - this.signalEB = false; - this.atpOn = true; - this.atoOn = true; - this.nextParking = true; - this.gear = Handwheel.ATO; - this.confirmationMessages.clear(); - this.cbtcMaMissDuration = 0; - } + /** + * 初始化人工车 + */ + public void initManualTrain(SectionPosition headPosition, boolean right) { + this.initPosition(right, headPosition); + init(); + } - public void setTarget(Section target) { - this.target = target; + public void initManualTrain(SectionPosition headPosition, boolean right, TrainPosition tp) { + this.initPosition(right, headPosition); + init(); + this.speed = tp.getSpeed(); + this.locationKM = tp.getLocation(); + this.right = tp.isRight(); + } + + private void init() { + this.communication = true; + this.jump = false; + this.hold = false; + this.standParkedTrainActivity = null; + this.runLevel = RunLevel.CBTC; + this.driveMode = DriveMode.AM; + this.tempPreselectionMode = PreselectionMode.AM_C; + this.preselectionMode = PreselectionMode.AM_C; + this.speed = 0; + this.atoSpeed = 0; + this.atpSpeed = 0; + this.signalEB = false; + this.atpOn = true; + this.atoOn = true; + this.nextParking = true; + this.gear = Handwheel.ATO; + this.confirmationMessages.clear(); + this.cbtcMaMissDuration = 0; + } + + public void setTarget(Section target) { + this.target = target; // if (this.ma2 != null) { // SpeedCurve.calculateAtoStopCurveAndUpdate(this, this.ma2); // } - } + } - public synchronized void updateNextStationPlan(Station nextStation, Section targetSection, boolean nextParking) { - this.nextStation = nextStation; + public synchronized void updateNextStationPlan(Station nextStation, Section targetSection, + boolean nextParking) { + this.nextStation = nextStation; // this.setTarget(targetSection); - this.nextParking = nextParking; + this.nextParking = nextParking; // log.info(String.format("列车[%s]更新下一站[%s] 轨道[%s], [%s]", // this.getGroupNumber(), nextStation.getName(),targetSection.getName(), // nextParking ? "停车" : "不停车")); - } + } - public void startTurnBack(Section tbSection) { + public void startTurnBack(Section tbSection) { // this.setTarget(tbSection); - this.dtro = true; - this.nextStation = null; - this.terminalStation = null; + this.dtro = true; + this.nextStation = null; + this.terminalStation = null; + } + + public boolean isAllDoorCloseAndLock() { + return this.door1.isCloseAndLock() && this.door2.isCloseAndLock(); + } + + public boolean isStop() { + return this.speed == 0; + } + + /** + * 通过操纵杆改变牵引/制动力 + */ + public void leaverUpdateTBForce(float fk, float fb) { + if (Handwheel.MANUAL.equals(this.gear) || Handwheel.REVERSE.equals(this.gear)) { + updateTBForce(fk, fb); } + } - public boolean isAllDoorCloseAndLock() { - return this.door1.isCloseAndLock() && this.door2.isCloseAndLock(); + public void updateTBForce(float fk, float fb) { + if (isEB()) { + return; + } + if (Fault.DRIVE_FAULT.equals(fault) && fk > 0) { + return; } + enforceUpdateTBForce(fk, fb); + } - public boolean isStop() { - return this.speed == 0; + /** + * 强制改变牵引制动力 + */ + public void enforceUpdateTBForce(float fk, float fb) { + if (linkTrain != null && linkTrain.isEB()) { + return; } + this.fk = Math.min(fk, getCurrentFkMax()); - /** - * 通过操纵杆改变牵引/制动力 - */ - public void leaverUpdateTBForce(float fk, float fb) { - if (Handwheel.MANUAL.equals(this.gear) || Handwheel.REVERSE.equals(this.gear)) { - updateTBForce(fk, fb); - } + this.fb = Math.min(fb, getCurrentFbMax()); + if (fk > 0) { + this.tbControl = TrainTBControl.TRACTION; + } else if (fb > 0) { + this.tbControl = TrainTBControl.BREAK; + } else { + this.tbControl = TrainTBControl.LAZY; } - - public void updateTBForce(float fk, float fb) { - if (isEB()) - return; - if (Fault.DRIVE_FAULT.equals(fault) && fk > 0) { - return; - } - enforceUpdateTBForce(fk, fb); + if (linkTrain != null) { + linkTrain.enforceUpdateTBForce(fk, fb); } + } - /** - * 强制改变牵引制动力 - */ - public void enforceUpdateTBForce(float fk, float fb) { - if (linkTrain != null && linkTrain.isEB()) { - return; - } - this.fk = Math.min(fk, getCurrentFkMax()); - - this.fb = Math.min(fb, getCurrentFbMax()); - if (fk > 0) { - this.tbControl = TrainTBControl.TRACTION; - } else if (fb > 0) { - this.tbControl = TrainTBControl.BREAK; - } else { - this.tbControl = TrainTBControl.LAZY; - } - if (linkTrain != null) { - linkTrain.enforceUpdateTBForce(fk, fb); - } - } - - public float getCurrentFbMax() { + public float getCurrentFbMax() { // float speed = this.getSpeedKmPh(); // return speed >= 45 ? 8900 / speed : 200; - return 200; //大铁列车速度上限比地铁高很多,上面的逻辑会导致大铁列车高速行驶时制动力远低于预期,从而导致停车出问题 + return 200; //大铁列车速度上限比地铁高很多,上面的逻辑会导致大铁列车高速行驶时制动力远低于预期,从而导致停车出问题 + } + + public float getCurrentFkMax() { + float speed = this.getSpeedKmPh(); + return speed >= 36 ? 12900 / speed : 350; + } + + public float getSpeedKmPh() { + return this.speed * 3.6f; + } + + public void clearMa() { + this.ma = null; + this.ma2 = null; + } + + public float getProtectSpeedKmPh() { + return (float) (this.atpSpeed * 3.6); + } + + public float getTargetSpeedKmPh() { + return (float) (this.atoSpeed * 3.6); + } + + public SectionPosition calculateTailPosition() { + this.tailPosition = CalculateService.calculateNextPositionByStartAndLen(this.headPosition, + !right, this.getLen(), true); + return this.tailPosition; + } + + public synchronized void depart() { + this.standParkedTrainActivity = null; + this.parkTime = 0; + this.parkRemainTime = 0; + this.departure = true; + } + + public void setITCMode() { + this.runLevel = RunLevel.ITC; + } + + public void changeEndsStart() { + this.changeEndsRemainTime = SimulationConstants.TRAIN_CHANGE_END_TIME * 1000; + this.changeEnds = true; + } + + public void changeEndsOver() { + this.changeEnds = false; + this.changeEndsRemainTime = 0; + } + + public float getMassKg() { + return this.getMass() * 1000; + } + + /** + * cbtc级别移动授权是否丢失 + */ + public boolean isCbtcMaMiss() { + return this.cbtcMaMissDuration > 3 * 1000; + } + + public void setCbtcMaMiss() { + this.cbtcMaMissDuration = 3 * 1000 + 1; + } + + /** + * 列车是否停在这个位置(在目标位置的偏差范围内) + */ + public boolean isStopAtThePosition(SectionPosition targetPosition) { + if (!this.isStop()) { + return false; + } + SectionPosition headPosition = this.headPosition; + boolean right = this.right; + SectionPosition max = CalculateService.calculateNextPositionByStartAndLen(targetPosition, + right, SimulationConstants.PARK_POINT_MAX_OFFSET, true); + SectionPosition min = CalculateService.calculateNextPositionByStartAndLen(targetPosition, + !right, SimulationConstants.PARK_POINT_MAX_OFFSET, true); + return headPosition.isAheadOf(min, right) && max.isAheadOf(headPosition, right); + } + + /** + * 获取列车后方的车站停车位置 + * + * @return + */ + public SectionPosition calculateBackStandStopPosition() { + SectionPosition tailPosition = this.tailPosition; + boolean right = this.right; + Section section = tailPosition.getSection(); + for (int i = 0; i < 100; i++) { + section = section.findBackRunningSectionBaseRealSwitch(right); + if (section == null) { + break; + } + if (section.isStandTrack()) { + float stopPoint = section.getStopPointByDirection(right); + return new SectionPosition(section, stopPoint); + } + } + return null; + } + + /** + * 计算列车前方下一个站台的停车位置 + */ + public SectionPosition calculateNextStandStopPosition() { + SectionPosition headPosition = this.headPosition; + boolean right = this.right; + Section section = headPosition.getSection(); + for (int i = 0; i < 100; i++) { + section = section.findNextRunningSectionBaseRealSwitch(right); + if (section == null) { + break; + } + if (section.isStandTrack()) { + float stopPoint = section.getStopPointByDirection(right); + return new SectionPosition(section, stopPoint); + } + } + return null; + } + + /** + * 计算越红灯行驶的停车位置(前方站台轨、折返轨、转换轨) + */ + public SectionPosition calculateStopPosition4CrossTheRedLight() { + boolean right = this.right; + Section section = this.headPosition.getSection(); + Signal signal = section.getSignalOf(right); + if (signal == null || !signal.isDefaultAspect()) { //没有同向信号机或信号机不处于信号关闭状态 + throw new SimulationException(SimulationExceptionType.Invalid_Operation, + "指令要求:列车车头所在区段有同向信号机并且信号关闭"); } - public float getCurrentFkMax() { - float speed = this.getSpeedKmPh(); - return speed >= 36 ? 12900 / speed : 350; - } - - public float getSpeedKmPh() { - return this.speed * 3.6f; - } - - public void clearMa() { - this.ma = null; - this.ma2 = null; - } - - public float getProtectSpeedKmPh() { - return (float) (this.atpSpeed * 3.6); - } - - public float getTargetSpeedKmPh() { - return (float) (this.atoSpeed * 3.6); - } - - public SectionPosition calculateTailPosition() { - this.tailPosition = CalculateService.calculateNextPositionByStartAndLen(this.headPosition, !right, this.getLen(), true); - return this.tailPosition; - } - - public synchronized void depart() { - this.standParkedTrainActivity = null; - this.parkTime = 0; - this.parkRemainTime = 0; - this.departure = true; - } - - public void setITCMode() { - this.runLevel = RunLevel.ITC; - } - - public void changeEndsStart() { - this.changeEndsRemainTime = SimulationConstants.TRAIN_CHANGE_END_TIME * 1000; - this.changeEnds = true; - } - - public void changeEndsOver() { - this.changeEnds = false; - this.changeEndsRemainTime = 0; - } - - public float getMassKg() { - return this.getMass() * 1000; - } - - /** - * cbtc级别移动授权是否丢失 - */ - public boolean isCbtcMaMiss() { - return this.cbtcMaMissDuration > 3 * 1000; - } - - public void setCbtcMaMiss() { - this.cbtcMaMissDuration = 3 * 1000 + 1; - } - - /** - * 列车是否停在这个位置(在目标位置的偏差范围内) - */ - public boolean isStopAtThePosition(SectionPosition targetPosition) { - if (!this.isStop()) { - return false; - } - SectionPosition headPosition = this.headPosition; - boolean right = this.right; - SectionPosition max = CalculateService.calculateNextPositionByStartAndLen(targetPosition, - right, SimulationConstants.PARK_POINT_MAX_OFFSET, true); - SectionPosition min = CalculateService.calculateNextPositionByStartAndLen(targetPosition, - !right, SimulationConstants.PARK_POINT_MAX_OFFSET, true); - return headPosition.isAheadOf(min, right) && max.isAheadOf(headPosition, right); - } - - /** - * 获取列车后方的车站停车位置 - * @return - */ - public SectionPosition calculateBackStandStopPosition(){ - SectionPosition tailPosition = this.tailPosition; - boolean right = this.right; - Section section = tailPosition.getSection(); - for (int i = 0; i < 100; i++) { - section = section.findBackRunningSectionBaseRealSwitch(right); - if (section == null) { - break; - } - if (section.isStandTrack()) { - float stopPoint = section.getStopPointByDirection(right); - return new SectionPosition(section, stopPoint); - } - } - return null; - } - /** - * 计算列车前方下一个站台的停车位置 - */ - public SectionPosition calculateNextStandStopPosition() { - SectionPosition headPosition = this.headPosition; - boolean right = this.right; - Section section = headPosition.getSection(); - for (int i = 0; i < 100; i++) { - section = section.findNextRunningSectionBaseRealSwitch(right); - if (section == null) { - break; - } - if (section.isStandTrack()) { - float stopPoint = section.getStopPointByDirection(right); - return new SectionPosition(section, stopPoint); - } - } - return null; - } - - /** - * 计算越红灯行驶的停车位置(前方站台轨、折返轨、转换轨) - */ - public SectionPosition calculateStopPosition4CrossTheRedLight() { - boolean right = this.right; - Section section = this.headPosition.getSection(); - Signal signal = section.getSignalOf(right); - if (signal == null || !signal.isDefaultAspect()) { //没有同向信号机或信号机不处于信号关闭状态 - throw new SimulationException(SimulationExceptionType.Invalid_Operation, "指令要求:列车车头所在区段有同向信号机并且信号关闭"); - } - - for (int i = 0; i < 30; i++) { - Section nextSection = section.findNextRunningSectionBaseRealSwitch(right); - if (nextSection == null) { - throw new SimulationException(SimulationExceptionType.Invalid_Operation, - String.format("信号机[%s]前方未找到站台轨或折返轨", signal.getName())); - } - section = nextSection; - if (section.isStandTrack() || section.isTurnBackTrack() || section.isTransferTrack()) { - return new SectionPosition(section, section.getStopPointByDirection(right)); - } + for (int i = 0; i < 30; i++) { + Section nextSection = section.findNextRunningSectionBaseRealSwitch(right); + if (nextSection == null) { + throw new SimulationException(SimulationExceptionType.Invalid_Operation, + String.format("信号机[%s]前方未找到站台轨或折返轨", signal.getName())); + } + section = nextSection; + if (section.isStandTrack() || section.isTurnBackTrack() || section.isTransferTrack()) { + return new SectionPosition(section, section.getStopPointByDirection(right)); + } // if (section.getSignalOf(right) != null && !section.getSignalOf(right).isNormalOpen()) { //同向信号机未正常开放 // sectionPosition = new SectionPosition(section, section.getSignalOf(right).getOffset()); // break; // } - } - throw new SimulationException(SimulationExceptionType.Invalid_Operation, - String.format("信号机[%s]前方未找到站台轨、折返轨或转换轨", signal.getName())); } + throw new SimulationException(SimulationExceptionType.Invalid_Operation, + String.format("信号机[%s]前方未找到站台轨、折返轨或转换轨", signal.getName())); + } - /** - * 计算车头到下一个正常开放的信号机的距离(找2个区段) - */ - public Float calculateDistance2NextNormalOpenSignal() { - SectionPosition headPosition = this.headPosition; - Section section = headPosition.getSection(); - boolean right = this.right; - Signal signal = section.getSignalOf(right); - if (signal != null && signal.isMainAspect()) { //如果车头区段的同向信号机正常开放 - SectionPosition signalPosition = new SectionPosition(section, signal.getOffset()); - return CalculateService.calculateDistance(headPosition, signalPosition, right, false); - } - return null; + /** + * 计算车头到下一个正常开放的信号机的距离(找2个区段) + */ + public Float calculateDistance2NextNormalOpenSignal() { + SectionPosition headPosition = this.headPosition; + Section section = headPosition.getSection(); + boolean right = this.right; + Signal signal = section.getSignalOf(right); + if (signal != null && signal.isMainAspect()) { //如果车头区段的同向信号机正常开放 + SectionPosition signalPosition = new SectionPosition(section, signal.getOffset()); + return CalculateService.calculateDistance(headPosition, signalPosition, right, false); } + return null; + } - /** - * 根据列车方向和选择的车门的方向选择车门 - * - * @param right 选择的车门的方向 - */ - public Door getDoorByDirection(Boolean right) { - boolean trainIsRight = this.right; - if (trainIsRight) { - if (right) { - return this.door2; - } else { - return this.door1; - } - } else { - if (right) { - return this.door1; - } else { - return this.door2; - } - } + /** + * 根据列车方向和选择的车门的方向选择车门 + * + * @param right 选择的车门的方向 + */ + public Door getDoorByDirection(Boolean right) { + boolean trainIsRight = this.right; + if (trainIsRight) { + if (right) { + return this.door2; + } else { + return this.door1; + } + } else { + if (right) { + return this.door1; + } else { + return this.door2; + } } + } - /** - * 判断车门方向是否是右 - */ - public boolean judgeDirection4DoorIsRight(Door door) { - if (Objects.equals(door, this.getDoorByDirection(true))) { - return true; - } else { - return false; - } + /** + * 判断车门方向是否是右 + */ + public boolean judgeDirection4DoorIsRight(Door door) { + if (Objects.equals(door, this.getDoorByDirection(true))) { + return true; + } else { + return false; } + } - public void setSpeed(float speed) { - this.speed = speed; - if (speed > 0) { - this.breaking = false; - } + public void setSpeed(float speed) { + this.speed = speed; + if (speed > 0) { + this.breaking = false; + } // if (linkTrain != null) { // linkTrain.setSpeed(speed); // } + } + + /** + * 更新供电状态 + * + * @param on 接触网供电是否开启 + */ + public void updatePowerSupplyStatus(boolean on) { + if (!on) { + this.powerOn = false; + } else { + this.powerOn = pantograph1Up; + } + } + + public synchronized void parkingAt(Section headSection) { + if (headSection.isNormalStandTrack()) { + this.standParkedTrainActivity = StandParkedTrainActivity.PARK; + } else { + this.standParkedTrainActivity = StandParkedTrainActivity.START; + } + } + + public boolean isParkingAt() { + return Objects.nonNull(this.standParkedTrainActivity); + } + + public boolean isStandReadyStart() { + return Objects.nonNull(this.standParkedTrainActivity) && StandParkedTrainActivity.START.equals( + this.standParkedTrainActivity); + } + + public boolean isStandBoarding() { + return Objects.nonNull(this.standParkedTrainActivity) && StandParkedTrainActivity.BOARD.equals( + this.standParkedTrainActivity); + } + + public synchronized void nextParkedTrainActivity() { + this.standParkedTrainActivity = this.standParkedTrainActivity.next(); + } + + public synchronized void earlyDeparture() { + if (StandParkedTrainActivity.CLOSE_DOOR.equals(this.standParkedTrainActivity) || + StandParkedTrainActivity.START.equals(this.standParkedTrainActivity)) { + return; + } + this.standParkedTrainActivity = StandParkedTrainActivity.CLOSE_DOOR; + } + + public boolean isRMMode() { + return DriveMode.RM.equals(this.driveMode); + } + + public boolean isNRMMode() { + return DriveMode.NRM.equals(this.driveMode); + } + + /** + * 设置紧急制动的功率和制动力 + */ + public void emergencyBreak() { + this.fk = 0; + this.fb = 350; + } + + public boolean isInTheStandArea() { + if (this.getHeadPosition() == null) { + return false; + } + return this.getHeadPosition().getSection().isNormalStandTrack() + || this.calculateTailPosition().getSection().isNormalStandTrack(); + } + + public Boolean isTowed() { + if (fk > 0) { + return true; + } else if (fb > 0) { + return false; + } else { + return null; + } + } + + public boolean isInTheGear(Handwheel gear) { + return gear.equals(this.gear); + } + + /** + * 在空挡? + */ + public boolean isInNeutralGear() { + return Handwheel.WASH.equals(gear) || Handwheel.DISCONNECT.equals(gear); + } + + /** + * 在AM级预选模式下 + */ + public boolean isInAMPreselectionMode() { + return preselectionMode.isNotLowerThanTheDriveMode(DriveMode.AM); + } + + public void addMessage(ConfirmationMessage message) { + confirmationMessages.add(message); + } + + public ConfirmationMessage findFirstMessage() { + Iterator iterator = confirmationMessages.iterator(); + if (iterator.hasNext()) { + return iterator.next(); + } else { + return null; + } + } + + public boolean containsMessage(ConfirmationMessage message) { + return confirmationMessages.contains(message); + } + + public boolean removeMessage(ConfirmationMessage message) { + return confirmationMessages.remove(message); + } + + /** + * 查询列车当前停站站台 + */ + public String queryParkingStandCode() { + if (!isParkingAt()) { + return null; + } else { + List standList = this.headPosition.getSection().getStandList(); + if (CollectionUtils.isEmpty(standList)) { + return null; + } else { + return standList.get(0).getCode(); + } + } + } + + /** + * 需要释放速度 + */ + public boolean needReleaseSpeed() { + return getAtoSpeed() * 3.6 < 20; + } + + /** + * 操纵杆是否在惰行位 + */ + public boolean isLeverInCoastingGear() { + return leverPosition == 0; + } + + /** + * 是否不在牵引位 + */ + public boolean isLeverNotInTractionGear() { + return leverPosition <= 0; + } + + /** + * 是否自动开门 + */ + public boolean isAutoOpenDoor() { + return isCBTC() && (DoorMode.AM.equals(doorMode) + || DoorMode.AA.equals(doorMode)); + } + + /** + * 是否自动关门 + */ + public boolean isAutoCloseDoor() { + return isCBTC() && DoorMode.AA.equals(doorMode); + } + + public void initAsAM_C() { + this.setCommunication(true); + this.setPreselectionMode(PreselectionMode.AM_C); + this.setTempPreselectionMode(this.preselectionMode); + this.setDriveMode(DriveMode.AM); + this.setRunLevel(RunLevel.CBTC); + this.setAtoOn(true); + } + + public void initAsSM_C() { + this.setCommunication(true); + this.setPreselectionMode(PreselectionMode.SM_C); + this.setTempPreselectionMode(this.preselectionMode); + this.setDriveMode(DriveMode.CM); + this.setRunLevel(RunLevel.CBTC); + this.setAtoOn(false); + this.setGear(Handwheel.MANUAL); + } + + public void initAsAM_I() { + this.setCommunication(false); + this.setPreselectionMode(PreselectionMode.AM_I); + this.setTempPreselectionMode(this.preselectionMode); + this.setDriveMode(DriveMode.AM); + this.setRunLevel(RunLevel.ITC); + this.setAtoOn(true); + } + + public void initAsSM_I() { + this.setCommunication(false); + this.setPreselectionMode(PreselectionMode.SM_I); + this.setTempPreselectionMode(this.preselectionMode); + this.setDriveMode(DriveMode.CM); + this.setRunLevel(RunLevel.ITC); + this.setAtoOn(false); + this.setGear(Handwheel.MANUAL); + } + + public void initAsRM() { + this.setCommunication(false); + this.setPreselectionMode(PreselectionMode.RM); + this.setTempPreselectionMode(this.preselectionMode); + this.setDriveMode(DriveMode.RM); + this.setRunLevel(RunLevel.IL); + this.setAtoOn(false); + this.setGear(Handwheel.MANUAL); + } + + public void initByPreselectionMode(PreselectionMode preselectionMode) { + switch (preselectionMode) { + case AM_C: + initAsAM_C(); + break; + case SM_C: + initAsSM_C(); + break; + case AM_I: + initAsAM_I(); + break; + case SM_I: + initAsSM_I(); + break; + case RM: + initAsRM(); + break; + } + } + + /** + * 获取一个非null的限速值。(计算限速时更方便) + */ + public float getSpeedLimitInMs() { + return robotDriveParam.getSpeedLimitInMs(); + } + + public void setSpeedLimit(float v) { + this.robotDriveParam.setSpeedLimit(v); + } + + public SectionPosition getRobotTargetPosition() { + return robotDriveParam.getTargetPosition(); + } + + public void setRobotTargetPosition(SectionPosition targetPosition) { + robotDriveParam.setTargetPosition(targetPosition); + } + + public boolean isRobotNeedRun() { + return robotDriveParam.needRun(); + } + + public boolean isRobotNeedStop() { + return robotDriveParam.needStop(); + } + + public boolean isRobotStopControl() { + return robotDriveParam.isStopControl(); + } + + @Getter + @Setter + public static class Door extends ControllableVrDevice { + + /** + * 道岔支持的操作 + */ + public enum Operation { + /** + * 开门 + */ + K, + /** + * 关门 + */ + G, + } + + private VirtualRealityTrain train; + private String code; + + private boolean close; + + private boolean lock; + + public Door(VirtualRealityTrain train, String code) { + super(code, code, DeviceType.TRAIN_DOOR, 2 * 1000); + this.train = train; + this.code = code; + this.close = true; + this.lock = true; + } + + public boolean isOpen() { + return !this.close; + } + + public boolean isCloseAndLock() { + return this.close && this.lock; + } + + public boolean isOpening() { + return this.getRemain() > 0 && Operation.K.equals(this.getCommand()); + } + + public boolean isClosing() { + return this.getRemain() > 0 && Operation.G.equals(this.getCommand()); + } + + @Override + protected void doTurn() { + this.lock = false; + this.close = false; + } + + @Override + protected void doFinish(Operation command) { + switch (command) { + case K: + this.lock = false; + this.close = false; + break; + case G: + this.close = true; + this.lock = true; + break; + } + } + } + + public boolean isCommunicable() { + Section section = headPosition.getSection(); + return communication && section.anyZcWorking(); + } + + public boolean isCMMode() { + return DriveMode.CM.equals(this.driveMode); + } + + public boolean isAMMode() { + return DriveMode.AM.equals(this.driveMode); + } + + public void updateDriveParam(DriveParamVO paramVO) { + paramVO.setDefaultStop(this.robotDriveParam.isDefaultStop()); + this.robotDriveParam = paramVO; + } + + public enum Fault { + /** + * 通信异常 + */ + COMMUNICATION_ABNORMAL { + @Override + public boolean apply(MapElement device) { + if (super.apply(device)) { + VirtualRealityTrain train = (VirtualRealityTrain) device; + train.setCommunication(false); + return true; + } + return false; + } + }, + + /** + * 驾驶异常 + */ + DRIVE_FAULT { + @Override + public boolean apply(MapElement device) { + if (super.apply(device)) { + VirtualRealityTrain train = (VirtualRealityTrain) device; + train.emergencyBreak(); //暂时就在这里直接处理,可能正常应该是ATP的责任 + return true; + } + return false; + } + }, + /** + * 列车脱线 + */ + OFF_LINE {}, + /** + * 突然EB + */ + SUDDEN_EB {}, + ; + + public boolean apply(MapElement device) { + VirtualRealityTrain train = (VirtualRealityTrain) device; + if (Objects.equals(this, train.getFault())) { + return false; + } + train.setFault(this); + return true; } /** - * 更新供电状态 - * - * @param on 接触网供电是否开启 + * 取消故障 */ - public void updatePowerSupplyStatus(boolean on) { - if (!on) { - this.powerOn = false; - } else { - this.powerOn = pantograph1Up; - } + public void fix(MapElement device) { + VirtualRealityTrain train = (VirtualRealityTrain) device; + train.setFault(null); + } + } + + public enum RunType { + /** + * 节能 + */ + ENERGY_CONSERVATION, + /** + * 中间的2 + */ + MIDDLE_TWO, + /** + * 中间的1 + */ + MIDDLE_ONE, + /** + * 正常 + */ + NORMAL, + /** + * 加速 + */ + ACCELERATE, + } + + public enum DoorMode { + /** + * 自动开手动关 + */ + AM, + /** + * 手动开手动关 + */ + MM, + /** + * 自动开自动关 + */ + AA, + ; + + public boolean isManual(boolean open) { + return (open && this.equals(MM)) || (!open && !this.equals(AA)); + } + } + + public enum DoorSelection { + /** + * 左 + */ + L, + /** + * 右 + */ + R, + /** + * 零位 + */ + Z, + ; + + public boolean match(boolean right) { + return (right && this.equals(R)) || (!right && this.equals(L)); + } + } + + /** + * 工况手轮 + */ + public enum Handwheel { + ATO, + MANUAL, + WASH, + DISCONNECT, + REVERSE; + } + + /** + * 预选模式 + */ + public enum PreselectionMode { + AM_C(DriveMode.AM, RunLevel.CBTC) { + @Override + public PreselectionMode findNext(boolean up) { + return up ? null : SM_C; + } + }, + SM_C(DriveMode.CM, RunLevel.CBTC) { + @Override + public PreselectionMode findNext(boolean up) { + return up ? AM_C : AM_I; + } + }, + AM_I(DriveMode.AM, RunLevel.ITC) { + @Override + public PreselectionMode findNext(boolean up) { + return up ? SM_C : SM_I; + } + }, + SM_I(DriveMode.CM, RunLevel.ITC) { + @Override + public PreselectionMode findNext(boolean up) { + return up ? AM_I : RM; + } + }, + RM(DriveMode.RM, RunLevel.IL) { + @Override + public PreselectionMode findNext(boolean up) { + return up ? SM_I : null; + } + }, + ; + /** + * 所允许的最高驾驶模式 + */ + private DriveMode driveMode; + /** + * 所允许的最高运行级别 + */ + private RunLevel runLevel; + + PreselectionMode(DriveMode driveMode, RunLevel runLevel) { + this.driveMode = driveMode; + this.runLevel = runLevel; } - public synchronized void parkingAt(Section headSection) { - if (headSection.isNormalStandTrack()) { - this.standParkedTrainActivity = StandParkedTrainActivity.PARK; - } else { - this.standParkedTrainActivity = StandParkedTrainActivity.START; - } - } + public abstract PreselectionMode findNext(boolean up); - public boolean isParkingAt() { - return Objects.nonNull(this.standParkedTrainActivity); - } - - public boolean isStandReadyStart() { - return Objects.nonNull(this.standParkedTrainActivity) && StandParkedTrainActivity.START.equals(this.standParkedTrainActivity); - } - - public boolean isStandBoarding() { - return Objects.nonNull(this.standParkedTrainActivity) && StandParkedTrainActivity.BOARD.equals(this.standParkedTrainActivity); - } - - public synchronized void nextParkedTrainActivity() { - this.standParkedTrainActivity = this.standParkedTrainActivity.next(); - } - - public synchronized void earlyDeparture() { - if (StandParkedTrainActivity.CLOSE_DOOR.equals(this.standParkedTrainActivity) || - StandParkedTrainActivity.START.equals(this.standParkedTrainActivity)) { - return; - } - this.standParkedTrainActivity = StandParkedTrainActivity.CLOSE_DOOR; - } - - public boolean isRMMode() { - return DriveMode.RM.equals(this.driveMode); - } - - public boolean isNRMMode() { - return DriveMode.NRM.equals(this.driveMode); + /** + * 该预选模式的驾驶模式不低于指定的驾驶模式 + */ + public boolean isNotLowerThanTheDriveMode(DriveMode driveMode) { + return this.driveMode.isNotLowerThan(driveMode); } /** - * 设置紧急制动的功率和制动力 + * 该预选模式的运行级别不低于指定级别 */ - public void emergencyBreak() { - this.fk = 0; - this.fb = 350; + public boolean isNotLowerThanTheRunLevel(RunLevel runLevel) { + return this.runLevel.isNotLowerThan(runLevel); } - public boolean isInTheStandArea() { - if (this.getHeadPosition() == null) - return false; - return this.getHeadPosition().getSection().isNormalStandTrack() - || this.calculateTailPosition().getSection().isNormalStandTrack(); - } - - public Boolean isTowed() { - if (fk > 0) { - return true; - } else if (fb > 0) { - return false; - } else { - return null; - } - } - - public boolean isInTheGear(Handwheel gear) { - return gear.equals(this.gear); + public boolean isMatchTheRunLevel(RunLevel runLevel) { + return this.runLevel == runLevel; } /** - * 在空挡? + * 是否比该模式级别更高 */ - public boolean isInNeutralGear() { - return Handwheel.WASH.equals(gear) || Handwheel.DISCONNECT.equals(gear); + public boolean isHigherThan(PreselectionMode mode) { + if (this.runLevel.equals(mode.runLevel)) { + return this.driveMode.isHigherThan(mode.driveMode); + } else { + return this.runLevel.isHigherThan(mode.runLevel); + } } + } - /** - * 在AM级预选模式下 - */ - public boolean isInAMPreselectionMode() { - return preselectionMode.isMatchTheDriveMode(DriveMode.AM); - } - - public void addMessage(ConfirmationMessage message) { - confirmationMessages.add(message); - } - - public ConfirmationMessage findFirstMessage() { - Iterator iterator = confirmationMessages.iterator(); - if (iterator.hasNext()) { - return iterator.next(); - } else { - return null; - } - } - - public boolean containsMessage(ConfirmationMessage message) { - return confirmationMessages.contains(message); - } - - public boolean removeMessage(ConfirmationMessage message) { - return confirmationMessages.remove(message); - } - - /** - * 查询列车当前停站站台 - */ - public String queryParkingStandCode() { - if (!isParkingAt()) { - return null; - } else { - List standList = this.headPosition.getSection().getStandList(); - if (CollectionUtils.isEmpty(standList)) { - return null; - } else { - return standList.get(0).getCode(); - } - } - } - - /** - * 需要释放速度 - */ - public boolean needReleaseSpeed() { - return getAtoSpeed() * 3.6 < 20; - } - - /** 操纵杆是否在惰行位 */ - public boolean isLeverInCoastingGear() { - return leverPosition == 0; - } - - /** 是否不在牵引位 */ - public boolean isLeverNotInTractionGear() { - return leverPosition <= 0; - } - - /** - * 是否自动开门 - */ - public boolean isAutoOpenDoor() { - return isCBTC() && (DoorMode.AM.equals(doorMode) - || DoorMode.AA.equals(doorMode)); - } - - /** - * 是否自动关门 - */ - public boolean isAutoCloseDoor() { - return isCBTC() && DoorMode.AA.equals(doorMode); - } - - public void initAsAM_C() { - this.setCommunication(true); - this.setPreselectionMode(PreselectionMode.AM_C); - this.setTempPreselectionMode(this.preselectionMode); - this.setDriveMode(DriveMode.AM); - this.setRunLevel(RunLevel.CBTC); - this.setAtoOn(true); - } - - public void initAsSM_C() { - this.setCommunication(true); - this.setPreselectionMode(PreselectionMode.SM_C); - this.setTempPreselectionMode(this.preselectionMode); - this.setDriveMode(DriveMode.CM); - this.setRunLevel(RunLevel.CBTC); - this.setAtoOn(false); - this.setGear(Handwheel.MANUAL); - } - - public void initAsAM_I() { - this.setCommunication(false); - this.setPreselectionMode(PreselectionMode.AM_I); - this.setTempPreselectionMode(this.preselectionMode); - this.setDriveMode(DriveMode.AM); - this.setRunLevel(RunLevel.ITC); - this.setAtoOn(true); - } - - public void initAsSM_I() { - this.setCommunication(false); - this.setPreselectionMode(PreselectionMode.SM_I); - this.setTempPreselectionMode(this.preselectionMode); - this.setDriveMode(DriveMode.CM); - this.setRunLevel(RunLevel.ITC); - this.setAtoOn(false); - this.setGear(Handwheel.MANUAL); - } - - public void initAsRM() { - this.setCommunication(false); - this.setPreselectionMode(PreselectionMode.RM); - this.setTempPreselectionMode(this.preselectionMode); - this.setDriveMode(DriveMode.RM); - this.setRunLevel(RunLevel.IL); - this.setAtoOn(false); - this.setGear(Handwheel.MANUAL); - } - - public void initByPreselectionMode(PreselectionMode preselectionMode) { - switch (preselectionMode) { - case AM_C: - initAsAM_C(); - break; - case SM_C: - initAsSM_C(); - break; - case AM_I: - initAsAM_I(); - break; - case SM_I: - initAsSM_I(); - break; - case RM: - initAsRM(); - break; - } - } - - /** - * 获取一个非null的限速值。(计算限速时更方便) - */ - public float getSpeedLimitInMs() { - return robotDriveParam.getSpeedLimitInMs(); - } - - public void setSpeedLimit(float v) { - this.robotDriveParam.setSpeedLimit(v); - } - - public SectionPosition getRobotTargetPosition() { - return robotDriveParam.getTargetPosition(); - } - - public void setRobotTargetPosition(SectionPosition targetPosition) { - robotDriveParam.setTargetPosition(targetPosition); - } - - public boolean isRobotNeedRun() { - return robotDriveParam.needRun(); - } - - public boolean isRobotNeedStop() { - return robotDriveParam.needStop(); - } - - public boolean isRobotStopControl() { - return robotDriveParam.isStopControl(); - } - - @Getter - @Setter - public static class Door extends ControllableVrDevice { - - /** - * 道岔支持的操作 - */ - public enum Operation { - /** 开门 */ - K, - /** 关门 */ - G, - } - - private VirtualRealityTrain train; - private String code; - - private boolean close; - - private boolean lock; - - public Door(VirtualRealityTrain train, String code) { - super(code, code, DeviceType.TRAIN_DOOR, 2 * 1000); - this.train = train; - this.code = code; - this.close = true; - this.lock = true; - } - - public boolean isOpen() { - return !this.close; - } - - public boolean isCloseAndLock() { - return this.close && this.lock; - } - - public boolean isOpening() { - return this.getRemain() > 0 && Operation.K.equals(this.getCommand()); - } - - public boolean isClosing() { - return this.getRemain() > 0 && Operation.G.equals(this.getCommand()); - } - - @Override - protected void doTurn() { - this.lock = false; - this.close = false; - } - - @Override - protected void doFinish(Operation command) { - switch (command) { - case K: - this.lock = false; - this.close = false; - break; - case G: - this.close = true; - this.lock = true; - break; - } - } - } - - public boolean isCommunicable() { - Section section = headPosition.getSection(); - return communication && section.anyZcWorking(); - } - - public boolean isCMMode() { - return DriveMode.CM.equals(this.driveMode); - } - - public boolean isAMMode() { - return DriveMode.AM.equals(this.driveMode); - } - - public void updateDriveParam(DriveParamVO paramVO) { - paramVO.setDefaultStop(this.robotDriveParam.isDefaultStop()); - this.robotDriveParam = paramVO; - } - - public enum Fault { - /** - * 通信异常 - */ - COMMUNICATION_ABNORMAL { - @Override - public boolean apply(MapElement device) { - if (super.apply(device)) { - VirtualRealityTrain train = (VirtualRealityTrain) device; - train.setCommunication(false); - return true; - } - return false; - } - }, - - /** 驾驶异常 */ - DRIVE_FAULT { - @Override - public boolean apply(MapElement device) { - if (super.apply(device)) { - VirtualRealityTrain train = (VirtualRealityTrain) device; - train.emergencyBreak(); //暂时就在这里直接处理,可能正常应该是ATP的责任 - return true; - } - return false; - } - }, - /** 列车脱线 */ - OFF_LINE {}, - /** 突然EB */ - SUDDEN_EB{},; - - public boolean apply(MapElement device) { - VirtualRealityTrain train = (VirtualRealityTrain) device; - if (Objects.equals(this, train.getFault())) { - return false; - } - train.setFault(this); - return true; - } - /** - * 取消故障 - */ - public void fix(MapElement device) { - VirtualRealityTrain train = (VirtualRealityTrain) device; - train.setFault(null); - } - } - - public enum RunType { - /** - * 节能 - */ - ENERGY_CONSERVATION, - /** - * 中间的2 - */ - MIDDLE_TWO, - /** - * 中间的1 - */ - MIDDLE_ONE, - /** - * 正常 - */ - NORMAL, - /** - * 加速 - */ - ACCELERATE, - } - - public enum DoorMode { - /** - * 自动开手动关 - */ - AM, - /** - * 手动开手动关 - */ - MM, - /** - * 自动开自动关 - */ - AA, - ; - - public boolean isManual(boolean open) { - return (open && this.equals(MM)) || (!open && !this.equals(AA)); - } - } - - public enum DoorSelection { - /** - * 左 - */ - L, - /** - * 右 - */ - R, - /** - * 零位 - */ - Z, - ; - - public boolean match(boolean right) { - return (right && this.equals(R)) || (!right && this.equals(L)); - } - } - - /** - * 工况手轮 - */ - public enum Handwheel { - ATO, - MANUAL, - WASH, - DISCONNECT, - REVERSE; - } - - /** - * 预选模式 - */ - public enum PreselectionMode { - AM_C(DriveMode.AM, RunLevel.CBTC) { - @Override - public PreselectionMode findNext(boolean up) { - return up ? null : SM_C; - } - }, - SM_C(DriveMode.CM, RunLevel.CBTC) { - @Override - public PreselectionMode findNext(boolean up) { - return up ? AM_C : AM_I; - } - }, - AM_I(DriveMode.AM, RunLevel.ITC) { - @Override - public PreselectionMode findNext(boolean up) { - return up ? SM_C : SM_I; - } - }, - SM_I(DriveMode.CM, RunLevel.ITC) { - @Override - public PreselectionMode findNext(boolean up) { - return up ? AM_I : RM; - } - }, - RM(DriveMode.RM, RunLevel.IL) { - @Override - public PreselectionMode findNext(boolean up) { - return up ? SM_I : null; - } - }, - ; - /** 所允许的最高驾驶模式 */ - private DriveMode driveMode; - /** 所允许的最高运行级别 */ - private RunLevel runLevel; - - PreselectionMode(DriveMode driveMode, RunLevel runLevel) { - this.driveMode = driveMode; - this.runLevel = runLevel; - } - - public abstract PreselectionMode findNext(boolean up); - - /** - * 该预选模式与该驾驶模式匹配(即允许升到该模式) - */ - public boolean isMatchTheDriveMode(DriveMode driveMode) { - return this.driveMode.isNotLowerThan(driveMode); - } - - /** - * 该预选模式与该运行级别匹配 - */ - public boolean isMatchTheRunLevel(RunLevel runLevel) { - return this.runLevel.isNotLowerThan(runLevel); - } - - /** - * 是否比该模式级别更高 - */ - public boolean isHigherThan(PreselectionMode mode) { - if (this.runLevel.equals(mode.runLevel)) { - return this.driveMode.isHigherThan(mode.driveMode); - } else { - return this.runLevel.isHigherThan(mode.runLevel); - } - } - } - - public enum ConfirmationMessage { - Exit_TGMT, - Confirm_Release_Speed, - Confirm_Preselection, - Confirm_Control_Level_Down, - Switch_To_RM, - } + public enum ConfirmationMessage { + Exit_TGMT, + Confirm_Release_Speed, + Confirm_Preselection, + Confirm_Control_Level_Down, + Switch_To_RM, + } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/onboard/ATP/ATPService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/onboard/ATP/ATPService.java index f10cb4ef7..273845dc1 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/onboard/ATP/ATPService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/onboard/ATP/ATPService.java @@ -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; - /** * 自动保护系统服务 */ @@ -42,497 +41,523 @@ import java.util.Objects; @Slf4j public class ATPService { - @Autowired - private ATOService ATOService; + @Autowired + private ATOService ATOService; - @Autowired - private CiApiService ciApiService; - @Autowired - private SimulationRobotService simulationRobotService; + @Autowired + private CiApiService ciApiService; + @Autowired + private SimulationRobotService simulationRobotService; - /** - * 更新列车移动授权 - * - * @param ma - */ - public void updateMA(VirtualRealityTrain train, MovementAuthority ma) { - //如果移动授权终点没改变,return - if (Objects.nonNull(train.getMa()) && train.getMa().getEnd().equals(ma.getEnd())) { - return; - } + /** + * 更新列车移动授权 + * + * @param ma + */ + public void updateMA(VirtualRealityTrain train, MovementAuthority ma) { + //如果移动授权终点没改变,return + if (Objects.nonNull(train.getMa()) && train.getMa().getEnd().equals(ma.getEnd())) { + return; + } // if (train.isEB() && !train.isStop()) { // return; // } - Float protectDistance = this.calculateProtectDistance(train, ma.getEnd()); - if (Objects.isNull(protectDistance)) { // 安全运行距离未计算出,抛弃此次ma数据 - log.warn(String.format("列车[%s-%s|%s|%s]移动授权终点为[%s],未计算出安全防护距离", - train.getGroupNumber(), - train.getServiceNumber(), train.getTripNumber(), train.getDestinationCode(), - ma.getEnd())); - return; - } + Float protectDistance = this.calculateProtectDistance(train, ma.getEnd()); + if (Objects.isNull(protectDistance)) { // 安全运行距离未计算出,抛弃此次ma数据 + log.warn(String.format("列车[%s-%s|%s|%s]移动授权终点为[%s],未计算出安全防护距离", + train.getGroupNumber(), + train.getServiceNumber(), train.getTripNumber(), train.getDestinationCode(), + ma.getEnd())); + return; + } // if (train.isEB() && train.isStop() && protectDistance > 100) { // 原来触发EB的因素消失,自动解除EB // log.info(String.format("列车[%s-%s|%s|%s]原触发EB因素消失,自动解除EB", // train.getGroupNumber(), train.getServiceNumber(), // train.getTripNumber(), train.getDestinationCode())); // this.cancelEB(train); // } - log.info(String.format("列车[%s-%s|%s|%s]更新移动授权[%s],位置[%s],安全防护距离[%s]", - train.getGroupNumber(), - train.getServiceNumber(), train.getTripNumber(), train.getDestinationCode(), - ma.getEnd(), ma.getEnd().getEndPosition().toString(), protectDistance)); - // 重新生成速度曲线 - SpeedCurve speedCurve = SpeedCurve.generateProtectSpeedCurve(protectDistance, train.getAtpSpeedMax()); //未考虑区段限速 + log.info(String.format("列车[%s-%s|%s|%s]更新移动授权[%s],位置[%s],安全防护距离[%s]", + train.getGroupNumber(), + train.getServiceNumber(), train.getTripNumber(), train.getDestinationCode(), + ma.getEnd(), ma.getEnd().getEndPosition().toString(), protectDistance)); + // 重新生成速度曲线 + SpeedCurve speedCurve = SpeedCurve.generateProtectSpeedCurve(protectDistance, + train.getAtpSpeedMax()); //未考虑区段限速 // SpeedCurve speedCurve = SpeedCurve.generateProtectSpeedCurve(train); //考虑区段限速 - log.debug(String.format("列车[%s-%s|%s|%s]重新生成防护速度曲线[%s]", - train.getGroupNumber(), - train.getServiceNumber(), train.getTripNumber(), train.getDestinationCode(), - speedCurve.toString())); - ma.setProtectSpeedCurve(speedCurve); - train.setMa(ma); - } + log.debug(String.format("列车[%s-%s|%s|%s]重新生成防护速度曲线[%s]", + train.getGroupNumber(), + train.getServiceNumber(), train.getTripNumber(), train.getDestinationCode(), + speedCurve.toString())); + ma.setProtectSpeedCurve(speedCurve); + train.setMa(ma); + } - /** - * 计算列车安全防护距离 - */ - public Float calculateProtectDistance(VirtualRealityTrain train, MovementAuthority.End end) { - SectionPosition headPosition = train.getHeadPosition(); - boolean right = train.isRight(); - SectionPosition endPosition = end.getEndPosition(); - Float distance = CalculateService.calculateDistance(headPosition, endPosition, right, false); - if (Objects.isNull(distance)) { // 正向找未找到,则反向找 - distance = CalculateService.calculateDistance(headPosition, endPosition, !right, false); - if (Objects.nonNull(distance)) { - distance = -distance; - } + /** + * 计算列车安全防护距离 + */ + public Float calculateProtectDistance(VirtualRealityTrain train, MovementAuthority.End end) { + SectionPosition headPosition = train.getHeadPosition(); + boolean right = train.isRight(); + SectionPosition endPosition = end.getEndPosition(); + Float distance = CalculateService.calculateDistance(headPosition, endPosition, right, false); + if (Objects.isNull(distance)) { // 正向找未找到,则反向找 + distance = CalculateService.calculateDistance(headPosition, endPosition, !right, false); + if (Objects.nonNull(distance)) { + distance = -distance; + } + } + return distance; + } + + /** + * 速度防护 + * + * @param simulation + * @param train + */ + public void speedProtect(Simulation simulation, VirtualRealityTrain train) { + if (train.isEB() || !train.isAtpOn() || (!train.isRMMode() && train.getMa2() == null)) { + return; + } + if (train.isReleased()) { + if (train.getSpeed() > SpeedCurve.Release_Limit_Speed / 0.9f) { + log.warn(String.format("列车[%s]释放限速超速", train.debugStr())); + this.triggerSignalEB(train); + } + return; + } + DriveMode driveMode = train.getDriveMode(); + switch (driveMode) { + case RM: + case AM: + case CM: + if (train.getSpeed() > train.getAtpSpeed()) { + log.warn(String.format( + "系统时间:[%s],列车[%s]超速EB。驾驶模式:[%s], 移动授权:[%s], 速度:[%s],防护速度:[%s]", + simulation.getCorrectSystemTime(), + train.getGroupNumber(), train.getDriveMode(), + train.getMa2() != null ? train.getMa2().debugStr() : '无', + train.getSpeed(), train.getAtpSpeed())); + triggerSignalEB(train); } - return distance; + break; } + } - /** - * 速度防护 - * - * @param simulation - * @param train - */ - public void speedProtect(Simulation simulation, VirtualRealityTrain train) { - if (train.isEB() || !train.isAtpOn() || (!train.isRMMode() && train.getMa2() == null)) { - return; - } - if (train.isReleased()) { - if (train.getSpeed() > SpeedCurve.Release_Limit_Speed / 0.9f) { - log.warn(String.format("列车[%s]释放限速超速", train.debugStr())); - this.triggerSignalEB(train); - } - return; - } - DriveMode driveMode = train.getDriveMode(); - switch (driveMode) { - case RM: - case AM: - case CM: - if (train.getSpeed() > train.getAtpSpeed()) { - log.warn(String.format("系统时间:[%s],列车[%s]超速EB。驾驶模式:[%s], 移动授权:[%s], 速度:[%s],防护速度:[%s]", - simulation.getCorrectSystemTime(), - train.getGroupNumber(), train.getDriveMode(), - train.getMa2() != null ? train.getMa2().debugStr() : '无', - train.getSpeed(), train.getAtpSpeed())); - triggerSignalEB(train); - } - break; - } + /** + * 触发信号紧急停车 + */ + public void triggerSignalEB(VirtualRealityTrain train) { + if (!train.isAtpOn()) { + return; } + train.setSignalEB(true); + log.warn("列车[{}]触发信号EB", train.getGroupNumber()); + train.emergencyBreak(); + closeATO(train); + } - /** - * 触发信号紧急停车 - */ - public void triggerSignalEB(VirtualRealityTrain train) { - if (!train.isAtpOn()) { - return; - } - train.setSignalEB(true); - log.warn("列车[{}]触发信号EB", train.getGroupNumber()); - train.emergencyBreak(); - closeATO(train); + /** + * 触发电路紧急停车 + */ + public void triggerCircuitEB(VirtualRealityTrain train) { + closeATO(train); + train.setCircuitEB(true); + train.emergencyBreak(); + } + + /** + * 取消信号EB + */ + public void cancelSignalEB(VirtualRealityTrain train) { + train.setSignalEB(false); + } + + /** + * 取消电路EB + */ + public void cancelCircuitEB(VirtualRealityTrain train) { + train.setCircuitEB(false); + } + + /** + * 切除ATP + */ + public void cutOffAtp(VirtualRealityTrain train) { + if (train.isAtoOn()) { + closeATO(train); } + train.initAsRM(); //简单粗暴 + train.setAtpOn(false); + train.setSignalEB(false); + train.setDriveMode(DriveMode.NRM); + } - /** - * 触发电路紧急停车 - */ - public void triggerCircuitEB(VirtualRealityTrain train) { - closeATO(train); - train.setCircuitEB(true); - train.emergencyBreak(); - } + /** + * 开启ATP + */ + public void openAtp(VirtualRealityTrain train) { + train.setAtpOn(true); + train.setDriveMode(DriveMode.RM); + } - /** - * 取消信号EB - */ - public void cancelSignalEB(VirtualRealityTrain train) { - train.setSignalEB(false); - } - - /** - * 取消电路EB - */ - public void cancelCircuitEB(VirtualRealityTrain train) { - train.setCircuitEB(false); - } - - /** - * 切除ATP - */ - public void cutOffAtp(VirtualRealityTrain train) { - if (train.isAtoOn()) { - closeATO(train); - } - train.initAsRM(); //简单粗暴 - train.setAtpOn(false); - train.setSignalEB(false); - train.setDriveMode(DriveMode.NRM); - } - - /** - * 开启ATP - */ - public void openAtp(VirtualRealityTrain train) { - train.setAtpOn(true); - train.setDriveMode(DriveMode.RM); - } - - /** - * 列车是否在正常站台停车点停车 - */ - public boolean isStopOnTargetPosition(VirtualRealityTrain train) { - if (train.isStop()) { - SectionPosition headPosition = train.getHeadPosition(); - Section headSection = headPosition.getSection(); - if (headSection.isNormalStandTrack() || headSection.isTransferTrack()) { - float offset = headPosition.getOffset(); - float stopPoint = headSection.getStopPointByDirection(train.isRight()); - float dlen = Math.abs(offset - stopPoint); - if (dlen < SimulationConstants.PARK_POINT_MAX_OFFSET) { - // 正常站台停车点停车 - return true; - } else { - float remain = train.isRight() ? stopPoint - offset : offset - stopPoint; - if (remain < 0) { - log.debug(String.format("列车[%s-%s|%s|%s]开过了区段[%s(%s)]停车点[%s/%s]", - train.getGroupNumber(), train.getServiceNumber(), - train.getTripNumber(), train.getDestinationCode(), - headSection.getName(), headSection.getCode(), - offset, stopPoint)); - } else { - log.debug(String.format("列车[%s-%s|%s|%s]未停到区段[%s(%s)]停车点[%s/%s]", - train.getGroupNumber(), train.getServiceNumber(), - train.getTripNumber(), train.getDestinationCode(), - headSection.getName(), headSection.getCode(), - offset, stopPoint)); - } - } - } - } - return false; - } - - public boolean isStopOnStandPoint(VirtualRealityTrain train) { - if (train.getSpeed() == 0) { - SectionPosition headPosition = train.getHeadPosition(); - Section section = headPosition.getSection(); - if (section.isStandTrack()) { - float stopPoint = section.getStopPointByDirection(train.isRight()); - float dlen = Math.abs(headPosition.getOffset() - stopPoint); - if (dlen < SimulationConstants.PARK_POINT_MAX_OFFSET) { - return true; - } - } - } - return false; - } - - /** - * 列车调头 - */ - public void turnDirectionStart(VirtualRealityTrain train) { - if (train.isDtro()) { - // 是自动折返,立刻调头 - this.turnDirectionImmediately(train); + /** + * 列车是否在正常站台停车点停车 + */ + public boolean isStopOnTargetPosition(VirtualRealityTrain train) { + if (train.isStop()) { + SectionPosition headPosition = train.getHeadPosition(); + Section headSection = headPosition.getSection(); + if (headSection.isNormalStandTrack() || headSection.isTransferTrack()) { + float offset = headPosition.getOffset(); + float stopPoint = headSection.getStopPointByDirection(train.isRight()); + float dlen = Math.abs(offset - stopPoint); + if (dlen < SimulationConstants.PARK_POINT_MAX_OFFSET) { + // 正常站台停车点停车 + return true; } else { - train.changeEndsStart(); + float remain = train.isRight() ? stopPoint - offset : offset - stopPoint; + if (remain < 0) { + log.debug(String.format("列车[%s-%s|%s|%s]开过了区段[%s(%s)]停车点[%s/%s]", + train.getGroupNumber(), train.getServiceNumber(), + train.getTripNumber(), train.getDestinationCode(), + headSection.getName(), headSection.getCode(), + offset, stopPoint)); + } else { + log.debug(String.format("列车[%s-%s|%s|%s]未停到区段[%s(%s)]停车点[%s/%s]", + train.getGroupNumber(), train.getServiceNumber(), + train.getTripNumber(), train.getDestinationCode(), + headSection.getName(), headSection.getCode(), + offset, stopPoint)); + } } + } } + return false; + } - public void turnDirectionImmediately(VirtualRealityTrain train) { - train.changeEndsOver(); + public boolean isStopOnStandPoint(VirtualRealityTrain train) { + if (train.getSpeed() == 0) { + SectionPosition headPosition = train.getHeadPosition(); + Section section = headPosition.getSection(); + if (section.isStandTrack()) { + float stopPoint = section.getStopPointByDirection(train.isRight()); + float dlen = Math.abs(headPosition.getOffset() - stopPoint); + if (dlen < SimulationConstants.PARK_POINT_MAX_OFFSET) { + return true; + } + } + } + return false; + } + + /** + * 列车调头 + */ + public void turnDirectionStart(VirtualRealityTrain train) { + if (train.isDtro()) { + // 是自动折返,立刻调头 + this.turnDirectionImmediately(train); + } else { + train.changeEndsStart(); + } + } + + public void turnDirectionImmediately(VirtualRealityTrain train) { + train.changeEndsOver(); // Section tempHeadSection = train.getHeadPosition().getSection(); // if(tempHeadSection.isSwitchTrack()) tempHeadSection = tempHeadSection.getParent(); - if (train.getSpeed() != 0 + if (train.getSpeed() != 0 // || !tempHeadSection.isTurnBackTrack() - ) { - return; - } - // 调头开始 - log.info(String.format("列车[%s-%s|%s|%s]调头", - train.getGroupNumber(), train.getServiceNumber(), - train.getTripNumber(), train.getDestinationCode())); - boolean right = train.isRight(); - SectionPosition headPosition = train.getHeadPosition(); - SectionPosition newHeadPosition; - if (this.isStopOnStandPoint(train)) { // 如果在停车点,调头后保证还在停车点 - Section section = train.getHeadPosition().getSection(); - float offset = section.getStopPointByDirection(!right); - newHeadPosition = new SectionPosition(section, offset); - } else { - newHeadPosition = CalculateService - .calculateNextPositionByStartAndLen(headPosition, !right, train.getLen(), false); - } - // 车尾变车头,车头变车尾 - train.setHeadPosition(newHeadPosition); - train.setRight(!right); - // 清除旧的移动授权 - train.setMa2(null); + ) { + return; } - - public void changeEndsProgress(VirtualRealityTrain train) { - if (train.isChangeEnds()) { - int remain = train.getChangeEndsRemainTime(); - remain -= SimulationModule.ATP.getRateMs(); - train.setChangeEndsRemainTime(remain); - if (remain <= 0) { - this.turnDirectionImmediately(train); - } - } + // 调头开始 + log.info(String.format("列车[%s-%s|%s|%s]调头", + train.getGroupNumber(), train.getServiceNumber(), + train.getTripNumber(), train.getDestinationCode())); + boolean right = train.isRight(); + SectionPosition headPosition = train.getHeadPosition(); + SectionPosition newHeadPosition; + if (this.isStopOnStandPoint(train)) { // 如果在停车点,调头后保证还在停车点 + Section section = train.getHeadPosition().getSection(); + float offset = section.getStopPointByDirection(!right); + newHeadPosition = new SectionPosition(section, offset); + } else { + newHeadPosition = CalculateService + .calculateNextPositionByStartAndLen(headPosition, !right, train.getLen(), false); } + // 车尾变车头,车头变车尾 + train.setHeadPosition(newHeadPosition); + train.setRight(!right); + // 清除旧的移动授权 + train.setMa2(null); + } - 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 standList = train.getHeadPosition().getSection().getStandList(); - VirtualRealityTrain.Door door = train.getDoorByDirection(right); - if (open) { - if (door.isCloseAndLock()) { - train.setDeparture(false); - ATOService.openTrainDoor(simulation, train, door); - } - if (train.isCommunicable()) { - for (Stand stand : standList) { - this.ciApiService.openScreenDoor(simulation, stand.getCode(), CiStandService.PsdCommandSource.SIG); - } - } - } else { - if (!door.isCloseAndLock()) { - ATOService.closeTrainDoor(simulation, train, door); - train.setDeparture(true); - } - if (train.isCommunicable()) { - for (Stand stand : standList) { - this.ciApiService.closeScreenDoor(simulation, stand.getCode(), CiStandService.PsdCommandSource.SIG); - } - } - } + public void changeEndsProgress(VirtualRealityTrain train) { + if (train.isChangeEnds()) { + int remain = train.getChangeEndsRemainTime(); + remain -= SimulationModule.ATP.getRateMs(); + train.setChangeEndsRemainTime(remain); + if (remain <= 0) { + this.turnDirectionImmediately(train); + } } + } - /** - * 改变工况手轮档位 - */ - public void changeGear(VirtualRealityTrain train, @NonNull VirtualRealityTrain.Handwheel gear) { - if (VirtualRealityTrain.Handwheel.REVERSE == gear && !train.isStop()) { - return; + 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 standList = train.getHeadPosition().getSection().getStandList(); + VirtualRealityTrain.Door door = train.getDoorByDirection(right); + if (open) { + if (door.isCloseAndLock()) { + train.setDeparture(false); + ATOService.openTrainDoor(simulation, train, door); + } + if (train.isCommunicable()) { + for (Stand stand : standList) { + this.ciApiService.openScreenDoor(simulation, stand.getCode(), + CiStandService.PsdCommandSource.SIG); } - train.setGear(gear); - if (!VirtualRealityTrain.Handwheel.ATO.equals(train.getGear())) { - closeATO(train); + } + } else { + if (!door.isCloseAndLock()) { + ATOService.closeTrainDoor(simulation, train, door); + train.setDeparture(true); + } + if (train.isCommunicable()) { + for (Stand stand : standList) { + this.ciApiService.closeScreenDoor(simulation, stand.getCode(), + CiStandService.PsdCommandSource.SIG); } + } } + } - /** - * 开启ATO - */ - public void openATO(VirtualRealityTrain train) { - if (train.isAtoCanOpen()) { - train.setAtoOn(true); - train.setDriveMode(DriveMode.AM); - } + /** + * 改变工况手轮档位 + */ + public void changeGear(VirtualRealityTrain train, @NonNull VirtualRealityTrain.Handwheel gear) { + if (VirtualRealityTrain.Handwheel.REVERSE == gear && !train.isStop()) { + return; } - - /** - * 关闭自动驾驶系统 - */ - public void closeATO(VirtualRealityTrain train) { - if (!train.isAtoOn()) { - return; - } - train.setAtoOn(false); - if (DriveMode.AM.equals(train.getDriveMode())) { - updateDriveMode(train, DriveMode.CM); - } + train.setGear(gear); + if (!VirtualRealityTrain.Handwheel.ATO.equals(train.getGear())) { + closeATO(train); } + } - /** - * 可以开启ATO? - */ - 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; + /** + * 开启ATO + */ + public void openATO(VirtualRealityTrain train) { + if (canOpenATO(train)) { + train.setAtoOn(true); + train.setDriveMode(DriveMode.AM); + } + } + + /** + * 关闭自动驾驶系统 + */ + public void closeATO(VirtualRealityTrain train) { + if (!train.isAtoOn()) { + return; + } + train.setAtoOn(false); + if (DriveMode.AM.equals(train.getDriveMode())) { + updateDriveMode(train, DriveMode.CM); + } + } + + /** + * 可以开启ATO? + */ + 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()) //非ITC、CTC运行级别 - return false; - if (!train.isAtpOn()) //列车ATP未启用 - return false; + if (!train.isITC() && !train.isCBTC()) //非ITC、CTC运行级别 + { + return false; + } + if (!train.isAtpOn()) //列车ATP未启用 + { + return false; + } // if (train.isEB()) // return false; // if (train.isITC() && !train.isReleased() // && train.containsMessage(VirtualRealityTrain.ConfirmationMessage.Confirm_Release_Speed) ) // return false; - return true; - } + return true; + } - public void preselectionModeUp(VirtualRealityTrain train) { - PreselectionMode next = train.getTempPreselectionMode().findNext(true); - if (next != null) { - train.setTempPreselectionMode(next); - train.addMessage(VirtualRealityTrain.ConfirmationMessage.Confirm_Preselection); + public void preselectionModeUp(VirtualRealityTrain train) { + PreselectionMode next = train.getTempPreselectionMode().findNext(true); + if (next != null) { + train.setTempPreselectionMode(next); + train.addMessage(VirtualRealityTrain.ConfirmationMessage.Confirm_Preselection); + } + } + + public void preselectionModeDown(VirtualRealityTrain train) { + PreselectionMode next = train.getTempPreselectionMode().findNext(false); + if (next != null) { + train.setTempPreselectionMode(next); + train.addMessage(VirtualRealityTrain.ConfirmationMessage.Confirm_Preselection); + } + } + + public void confirmMessage(VirtualRealityTrain train) { + VirtualRealityTrain.ConfirmationMessage message = train.findFirstMessage(); + if (message != null) { + handleConfirmMessage(train, message); + } + } + + public void confirmMessage(VirtualRealityTrain train, + VirtualRealityTrain.ConfirmationMessage message) { + if (train.containsMessage(message)) { + handleConfirmMessage(train, message); + } + } + + private void handleConfirmMessage(VirtualRealityTrain train, + VirtualRealityTrain.ConfirmationMessage message) { + switch (message) { + case Exit_TGMT: + break; + case Confirm_Release_Speed: + train.setReleased(true); + break; + case Confirm_Preselection: + train.setPreselectionMode(train.getTempPreselectionMode()); + break; + case Confirm_Control_Level_Down: + case Switch_To_RM: + break; + default: + throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception( + String.format("未知的消息类型:%s", message)); + } + train.removeMessage(message); + } + + public void updateRunLevel(VirtualRealityTrain train, @NonNull RunLevel runLevel) { + updateRunLevel(train, runLevel, train.getPreselectionMode()); + } + + public void updateRunLevel(VirtualRealityTrain train, @NonNull RunLevel runLevel, + PreselectionMode preselectionMode) { + if (!preselectionMode.isNotLowerThanTheRunLevel(runLevel)) { + return; + } + switch (runLevel) { + case CBTC: + case ITC: + MaService.Ma ma = train.getMa2(); + if (ma == null) { + return; + } + SpeedCurve ebTriggerCurve = ma.getEbTriggerCurve(); + float ebTriggerRemain = ma.calculateDistanceOfEbTriggerEnd(); + ma.setEbTriggerCurve(ebTriggerCurve); + float totalDistance = ebTriggerCurve.getTotalDistance(); + if (totalDistance < ebTriggerRemain) { + ebTriggerRemain = totalDistance; + } + float atpSpeed = ebTriggerCurve.getSpeedOf(ebTriggerRemain); + if (atpSpeed <= 0) { + return; + } + updateDriveMode(train, train.isAtoOn() ? DriveMode.AM : DriveMode.CM, preselectionMode); + break; + case IL: + updateDriveMode(train, DriveMode.RM, preselectionMode); + break; + default: + throw new IllegalStateException("Unexpected value: " + runLevel); + } + train.setRunLevel(runLevel); + } + + private void updateDriveMode(VirtualRealityTrain train, DriveMode driveMode) { + updateDriveMode(train, driveMode, train.getPreselectionMode()); + } + + private void updateDriveMode(VirtualRealityTrain train, DriveMode driveMode, + PreselectionMode preselectionMode) { + if (driveMode.equals(train.getDriveMode())) { + return; + } + if (preselectionMode.isNotLowerThanTheDriveMode(driveMode)) { + train.setDriveMode(driveMode); + if (!train.isAMMode()) { + closeATO(train); } } + } - public void preselectionModeDown(VirtualRealityTrain train) { - PreselectionMode next = train.getTempPreselectionMode().findNext(false); - if (next != null) { - train.setTempPreselectionMode(next); - train.addMessage(VirtualRealityTrain.ConfirmationMessage.Confirm_Preselection); - } + /** + * 开关门 + */ + public void openOrCloseDoor(Simulation simulation, String groupNumber) { + VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); + List standList = train.getHeadPosition().getSection().getStandList(); + if (!CollectionUtils.isEmpty(standList) && standList.size() == 1 && standList.get(0) + .isSmall()) { + // 小站台停车,无需开关门 + return; } - - public void confirmMessage(VirtualRealityTrain train) { - VirtualRealityTrain.ConfirmationMessage message = train.findFirstMessage(); - if (message != null) { - handleConfirmMessage(train, message); - } + boolean doorIsRight = false, open = false; + if (!train.getDoorByDirection(false).isCloseAndLock()) { //列车左门没关 + doorIsRight = false; + open = false; + } else if (!train.getDoorByDirection(true).isCloseAndLock()) { //列车右门没关 + doorIsRight = true; + open = false; + } else { + Stand stand = standList.get(0); + if (stand.isInside() && stand.isRight()) { // 内测右站台,开1门 + doorIsRight = train.judgeDirection4DoorIsRight(train.getDoor1()); + } else if (stand.isInside() && !stand.isRight()) { // 内测左站台,开2门 + doorIsRight = train.judgeDirection4DoorIsRight(train.getDoor2()); + } else if (!stand.isInside() && stand.isRight()) { //外侧右站台,开2门 + doorIsRight = train.judgeDirection4DoorIsRight(train.getDoor2()); + } else { + doorIsRight = train.judgeDirection4DoorIsRight(train.getDoor1()); + } + open = true; } - - public void confirmMessage(VirtualRealityTrain train, VirtualRealityTrain.ConfirmationMessage message) { - if (train.containsMessage(message)) { - handleConfirmMessage(train, message); - } - } - - private void handleConfirmMessage(VirtualRealityTrain train, VirtualRealityTrain.ConfirmationMessage message) { - switch (message) { - case Exit_TGMT: - break; - case Confirm_Release_Speed: - train.setReleased(true); - break; - case Confirm_Preselection: - train.setPreselectionMode(train.getTempPreselectionMode()); - break; - case Confirm_Control_Level_Down: - case Switch_To_RM: - break; - default: - throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception(String.format("未知的消息类型:%s", message)); - } - train.removeMessage(message); - } - - public void updateRunLevel(VirtualRealityTrain train, @NonNull RunLevel runLevel) { - updateRunLevel(train, runLevel, train.getPreselectionMode()); - } - - public void updateRunLevel(VirtualRealityTrain train, @NonNull RunLevel runLevel, - PreselectionMode preselectionMode) { - if (!preselectionMode.isMatchTheRunLevel(runLevel)) { - return; - } - switch (runLevel) { - case CBTC: - case ITC: - MaService.Ma ma = train.getMa2(); - if (ma == null) - return; - SpeedCurve ebTriggerCurve = ma.getEbTriggerCurve(); - float ebTriggerRemain = ma.calculateDistanceOfEbTriggerEnd(); - ma.setEbTriggerCurve(ebTriggerCurve); - float totalDistance = ebTriggerCurve.getTotalDistance(); - if (totalDistance < ebTriggerRemain) { - ebTriggerRemain = totalDistance; - } - float atpSpeed = ebTriggerCurve.getSpeedOf(ebTriggerRemain); - if (atpSpeed <= 0) { - return; - } - updateDriveMode(train, train.isAtoOn() ? DriveMode.AM : DriveMode.CM, preselectionMode); - break; - case IL: - updateDriveMode(train, DriveMode.RM, preselectionMode); - break; - default: - throw new IllegalStateException("Unexpected value: " + runLevel); - } - train.setRunLevel(runLevel); - } - - private void updateDriveMode(VirtualRealityTrain train, DriveMode driveMode) { - updateDriveMode(train, driveMode, train.getPreselectionMode()); - } - - private void updateDriveMode(VirtualRealityTrain train, DriveMode driveMode, PreselectionMode preselectionMode) { - if (driveMode.equals(train.getDriveMode())) - return; - if (preselectionMode.isMatchTheDriveMode(driveMode)) { - train.setDriveMode(driveMode); - if (!train.isAMMode()) - closeATO(train); - } - } - - /** - * 开关门 - */ - public void openOrCloseDoor(Simulation simulation, String groupNumber) { - VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); - List standList = train.getHeadPosition().getSection().getStandList(); - if (!CollectionUtils.isEmpty(standList) && standList.size() == 1 && standList.get(0).isSmall()) { - // 小站台停车,无需开关门 - return; - } - boolean doorIsRight = false, open = false; - if (!train.getDoorByDirection(false).isCloseAndLock()) { //列车左门没关 - doorIsRight = false; - open = false; - } else if (!train.getDoorByDirection(true).isCloseAndLock()) { //列车右门没关 - doorIsRight = true; - open = false; - } else { - Stand stand = standList.get(0); - if (stand.isInside() && stand.isRight()) { // 内测右站台,开1门 - doorIsRight = train.judgeDirection4DoorIsRight(train.getDoor1()); - } else if (stand.isInside() && !stand.isRight()) { // 内测左站台,开2门 - doorIsRight = train.judgeDirection4DoorIsRight(train.getDoor2()); - } else if (!stand.isInside() && stand.isRight()) { //外侧右站台,开2门 - doorIsRight = train.judgeDirection4DoorIsRight(train.getDoor2()); - } else { - doorIsRight = train.judgeDirection4DoorIsRight(train.getDoor1()); - } - open = true; - } - VirtualRealityTrain.Door door = train.getDoorByDirection(doorIsRight); - if (!Objects.equals(door.isOpen(), open)) { - // 使用更简单粗暴的方式保证门可以打开,如果不合适再改 - if (open) { - ATOService.openTrainDoor(simulation, train, door); - } else { - ATOService.closeTrainDoor(simulation, train, door); - } - simulationRobotService.usePsl2ControlPsd(simulation, train, open); + VirtualRealityTrain.Door door = train.getDoorByDirection(doorIsRight); + if (!Objects.equals(door.isOpen(), open)) { + // 使用更简单粗暴的方式保证门可以打开,如果不合适再改 + if (open) { + ATOService.openTrainDoor(simulation, train, door); + } else { + ATOService.closeTrainDoor(simulation, train, door); + } + simulationRobotService.usePsl2ControlPsd(simulation, train, open); // //修改门模式和门选以保证操作成功 // VirtualRealityTrain.DoorMode doorMode = train.getDoorMode(); // train.setDoorMode(VirtualRealityTrain.DoorMode.MM); @@ -543,193 +568,183 @@ public class ATPService { // //操作后将门模式和门选还原 // train.setDoorMode(doorMode); // train.setDoorSelection(doorSelection); - } } + } - /** - * 回库 - */ - public void inbound(Simulation simulation, String groupNumber) { - VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); - Section headSection = train.getHeadPosition().getSection(); - if (headSection.isTransferTrack() && train.isStop()) { //列车停在转换轨 - SimulationDataRepository repository = simulation.getRepository(); - TrainInfo trainInfo = repository.getSupervisedTrainByGroup(train.getGroupNumber()); - List routePathList = repository.queryRoutePathsByEnd(headSection); - if (routePathList.stream().anyMatch(routePath -> routePath.isRight() == trainInfo.getRight())) { //准备回库 - trainInfo.finishPlanPrepareInbound(); - } - } + /** + * 回库 + */ + public void inbound(Simulation simulation, String groupNumber) { + VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); + Section headSection = train.getHeadPosition().getSection(); + if (headSection.isTransferTrack() && train.isStop()) { //列车停在转换轨 + SimulationDataRepository repository = simulation.getRepository(); + TrainInfo trainInfo = repository.getSupervisedTrainByGroup(train.getGroupNumber()); + List routePathList = repository.queryRoutePathsByEnd(headSection); + if (routePathList.stream() + .anyMatch(routePath -> routePath.isRight() == trainInfo.getRight())) { //准备回库 + trainInfo.finishPlanPrepareInbound(); + } } + } - /** - * 修改预选模式 - */ - public void changePreselectionMode(Simulation simulation, String groupNumber, VirtualRealityTrain.PreselectionMode preselectionMode) { - VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); - if (preselectionMode == train.getPreselectionMode()) { - return; - } - 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); + /** + * 修改预选模式 + */ + public void changePreselectionMode(Simulation simulation, String groupNumber, + VirtualRealityTrain.PreselectionMode preselectionMode) { + VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); + if (preselectionMode == train.getPreselectionMode()) { + return; } + if (!train.isAtpOn()) { + this.openAtp(train); + } + train.setPreselectionMode(preselectionMode); + 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); + } - /** - * 转NRM模式 - */ - public void applyNRM(Simulation simulation, String groupNumber) { - VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); - // 检验条件 + /** + * 转NRM模式 + */ + public void applyNRM(Simulation simulation, String groupNumber) { + VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber); + // 检验条件 // operationVail(simulation,train); - while (!train.isNRMMode()) { - this.cutOffAtp(train); - } + while (!train.isNRMMode()) { + this.cutOffAtp(train); + } + } + + /** + * 改变列车的牵引 + */ + public void changeTrainForce(VirtualRealityTrain train, Float percent) { + // 门选不是零位,不给牵引力 + if (!train.getDoorSelection().equals(VirtualRealityTrain.DoorSelection.Z)) { + return; + } + if ((percent <= 1 && percent >= -1) || percent == -2) { + train.setLeverPosition(percent); + } + if (train.isEB()) { + return; + } + if (percent <= 1 && percent >= -1) { + if (percent > 0) { + float fk = train.getCurrentFkMax() * percent; + train.leaverUpdateTBForce(fk, 0); + } else if (percent < 0) { + float fb = train.getCurrentFbMax() * Math.abs(percent); + train.leaverUpdateTBForce(0, fb); + } else { + train.leaverUpdateTBForce(0, 0); + } + } else if (percent == -2) { + train.leaverUpdateTBForce(0, 350); + } else { + throw new SimulationException(SimulationExceptionType.Illegal_Argument, + String.format( + "数值[%s]超限,列车牵引/制动力可调整比例范围应该在[-1, 1]之间,或为快速制动-2", + percent)); + } + } + + private void operationVail(Simulation simulation, VirtualRealityTrain train) { + boolean driverRobot = simulation.getSimulationMembers().stream() + .filter(simulationMember -> simulationMember.isDriver() + && train.getCode().equals(simulationMember.getDevice().getCode())) + .anyMatch(SimulationMember::isRobot); + BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(!driverRobot, + "成员由用户扮演,操作不执行"); + } + + /** + * 处理预处理模式 + * + * @param simulation 仿真 + * @param train 列车 + */ + public void handlePreselectionMode(Simulation simulation, VirtualRealityTrain train) { + VirtualRealityTrain.PreselectionMode preselectionMode = train.getPreselectionMode(); + MapConfig config = simulation.getRepository().getConfig(); + switch (preselectionMode) { + case AM_C: + if (!train.isCBTC() && config.getRunMode().isNotLowerThan(RunLevel.CBTC)) { + train.setCommunication(true); + } + break; + case SM_C: + if (!train.isCBTC() && config.getRunMode().isNotLowerThan(RunLevel.CBTC)) { + train.setCommunication(true); + } + closeATO(train); + break; + case AM_I: + train.setCommunication(false); + break; + case SM_I: + case RM: + train.setCommunication(false); + closeATO(train); + break; + } + updateRunLevel(simulation, train, preselectionMode); + } + + /** + * 更新列车运行级别 + */ + private void updateRunLevel(Simulation simulation, VirtualRealityTrain train, + VirtualRealityTrain.PreselectionMode preselectionMode) { + //如果当前级别高于预选,降至IL + if (!preselectionMode.isNotLowerThanTheRunLevel(train.getRunLevel())) { + updateRunLevel(train, RunLevel.IL, preselectionMode); } - /** - * 改变列车的牵引 - */ - public void changeTrainForce(VirtualRealityTrain train, Float percent) { - // 门选不是零位,不给牵引力 - if (!train.getDoorSelection().equals(VirtualRealityTrain.DoorSelection.Z)) { - return; - } - if ((percent <= 1 && percent >= -1) || percent == -2) { - train.setLeverPosition(percent); - } - if (train.isEB()) { - return; - } - if (percent <= 1 && percent >= -1) { - if (percent > 0) { - float fk = train.getCurrentFkMax() * percent; - train.leaverUpdateTBForce(fk, 0); - } else if (percent < 0) { - float fb = train.getCurrentFbMax() * Math.abs(percent); - train.leaverUpdateTBForce(0, fb); - } else { - train.leaverUpdateTBForce(0, 0); - } - } else if (percent == -2) { - 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); - } - } - - private void operationVail(Simulation simulation,VirtualRealityTrain train){ - boolean driverRobot = simulation.getSimulationMembers().stream() - .filter(simulationMember -> simulationMember.isDriver() - && train.getCode().equals(simulationMember.getDevice().getCode())) - .anyMatch(SimulationMember::isRobot); - BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(!driverRobot,"成员由用户扮演,操作不执行"); - } - - /** - * 处理预处理模式 - * @param simulation 仿真 - * @param train 列车 - */ - public void handlePreselectionMode(Simulation simulation, VirtualRealityTrain train) { - VirtualRealityTrain.PreselectionMode preselectionMode = train.getPreselectionMode(); - MapConfig config = simulation.getRepository().getConfig(); - switch (preselectionMode) { - case AM_C: - if (!train.isCBTC() && config.getRunMode().isNotLowerThan(RunLevel.CBTC)) - train.setCommunication(true); - break; - case SM_C: - if (!train.isCBTC() && config.getRunMode().isNotLowerThan(RunLevel.CBTC)) - train.setCommunication(true); - closeATO(train); - break; - case AM_I: - train.setCommunication(false); - break; - case SM_I: - case RM: - train.setCommunication(false); - closeATO(train); - break; - } - updateRunLevel(simulation, train, preselectionMode); - } - - /** - * 更新列车运行级别 - */ - private void updateRunLevel(Simulation simulation, VirtualRealityTrain train, VirtualRealityTrain.PreselectionMode preselectionMode) { - //如果当前级别高于预选,降至IL - if (!preselectionMode.isMatchTheRunLevel(train.getRunLevel())) { - updateRunLevel(train, RunLevel.IL, preselectionMode); - } - - RunLevel defaultRunLevel = simulation.getRepository().getConfig().getRunMode(); - //更新移动授权丢失时长 - train.setCbtcMaMissDuration(train.getCbtcMaMissDuration() + SimulationConstants.ATP_LOOP_RATE); - //判断并控制运行级别 - if (!train.isPositioned()) { //列车定位丢失(降级) - if (train.isITC() || train.isCBTC()) { //并且是ITC/CBTC级别 - updateRunLevel(train, RunLevel.IL, preselectionMode); - triggerSignalEB(train); - } - } else { //列车有定位 - if (train.isCBTC() && train.isCbtcMaMiss()) { //CBTC列车的移动授权丢失 - updateRunLevel(train, RunLevel.IL, preselectionMode); - triggerSignalEB(train); - } else if (!train.isCBTC() && !train.isCbtcMaMiss() && defaultRunLevel.equals(RunLevel.CBTC)) { - updateRunLevel(train, RunLevel.CBTC, preselectionMode); - } - } + RunLevel defaultRunLevel = simulation.getRepository().getConfig().getRunMode(); + //更新移动授权丢失时长 + train.setCbtcMaMissDuration(train.getCbtcMaMissDuration() + SimulationConstants.ATP_LOOP_RATE); + //判断并控制运行级别 + if (!train.isPositioned()) { //列车定位丢失(降级) + if (train.isITC() || train.isCBTC()) { //并且是ITC/CBTC级别 + updateRunLevel(train, RunLevel.IL, preselectionMode); + triggerSignalEB(train); + } + } else { //列车有定位 + if (train.isCBTC() && train.isCbtcMaMiss()) { //CBTC列车的移动授权丢失 + updateRunLevel(train, RunLevel.IL, preselectionMode); + triggerSignalEB(train); + } else if (!train.isCBTC() && !train.isCbtcMaMiss() && defaultRunLevel.equals( + RunLevel.CBTC)) { + updateRunLevel(train, RunLevel.CBTC, preselectionMode); + } } + } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/robot/SimulationRobotService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/robot/SimulationRobotService.java index f86d85860..05fdd569b 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/robot/SimulationRobotService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/robot/SimulationRobotService.java @@ -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); - } + atpService.openATO(train); break; } } @@ -158,43 +172,74 @@ public class SimulationRobotService { List 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); - //机器人驾驶 - 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()); - } - doBreakMax(simulation, train); - } - } else if (train.isRobotNeedRun()) { - if ((train.isRMMode() || train.isNRMMode())) { //RM或NRM - VirtualRealityTrain linkTrain = train.getLinkTrain(); - if (linkTrain == null) { - Optional targetPositionOptional = calculateTargetPosition(simulation, - train); - targetPositionOptional.ifPresent(tp -> robotDrive(simulation, driver, train, tp)); - } else { - robotDrive(simulation, driver, train, train.getRobotTargetPosition()); - } - } else if (train.isCMMode()) { //CM - SpeedCurve speedCurve = train.getMa2().getAtoStopCurve(); - atoService.doControlBySpeedCurve(train, speedCurve, speedCurve.getTotalDistance(), train.getAtoSpeed()); - } + //机器人人工驾驶 + robotManualDrive(simulation, driver, train); + } + } + + private void robotManualDrive(Simulation simulation, SimulationMember driver, + VirtualRealityTrain train) { + if (train.isRobotNeedStop()) { + if (train.isStop()) { + train.getRobotDriveParam().setStop(false); + } else { + 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 targetPositionOptional = calculateTargetPosition(simulation, + train); + targetPositionOptional.ifPresent(tp -> robotDrive(simulation, driver, train, tp)); + } else { + 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()); + } + } + } + + /** + * 在检查通过后开启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,10 +303,12 @@ 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, - right, SimulationConstants.PARK_POINT_MAX_OFFSET, true); + SectionPosition maxStopPosition = CalculateService.calculateNextPositionByStartAndLen( + stopPosition, + right, SimulationConstants.PARK_POINT_MAX_OFFSET, true); if (maxStopPosition.isAheadOf(headPosition, right)) { //未越过最大停车点 targetPosition = stopPosition; break; @@ -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);