修改列车供电状态的更新逻辑;列车重新通电之后重置ATP系统中的一些状态;TrainInfo中增加车地通信状态

This commit is contained in:
joylink_zhangsai 2023-11-24 16:40:40 +08:00
parent 29b94f0f1b
commit 787ecb5642
8 changed files with 897 additions and 801 deletions

View File

@ -862,6 +862,10 @@ public class Operation {
* 换端
*/
Special_Change_Head(new Label[]{Label.OTHER}, true),
/**
* 受电弓升降
*/
Special_Pantograph_Up_Down(new Label[]{Label.OTHER}, true),
//--------------------------- 方向杆 ---------------------------
/**
* 方向转换

View File

@ -1,6 +1,6 @@
package club.joylink.rtss.simulation.cbtc.ATS.operation.handler;
import club.joylink.rtss.simulation.cbtc.ATS.operation.Operation;
import club.joylink.rtss.simulation.cbtc.ATS.operation.Operation.Type;
import club.joylink.rtss.simulation.cbtc.ATS.operation.annotation.OperateHandler;
import club.joylink.rtss.simulation.cbtc.ATS.operation.annotation.OperateHandlerMapping;
import club.joylink.rtss.simulation.cbtc.Simulation;
@ -12,14 +12,27 @@ import org.springframework.beans.factory.annotation.Autowired;
@OperateHandler
@Slf4j
public class SpecialOperateHandler {
@Autowired
private ATPService atpService;
@OperateHandlerMapping(type = Operation.Type.Special_Change_Head)
public void changeHead(Simulation simulation, String groupNumber) {
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
if (train.isStop()) {
this.atpService.turnDirectionImmediately(train);
}
@Autowired
private ATPService atpService;
@OperateHandlerMapping(type = Type.Special_Change_Head)
public void changeHead(Simulation simulation, String groupNumber) {
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
if (train.isStop()) {
this.atpService.turnDirectionImmediately(train);
}
}
/**
* 受电弓升降
*
* @param index 受电弓的索引1-受电弓12-受电弓2
* @param up 受电弓升/
*/
@OperateHandlerMapping(type = Type.Special_Pantograph_Up_Down)
public void pantographUpOrDown(Simulation simulation, String groupNumber, int index, boolean up) {
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
train.updatePantographUp(index, up);
}
}

View File

@ -7,41 +7,47 @@ import club.joylink.rtss.simulation.cbtc.data.map.Catenary;
import club.joylink.rtss.simulation.cbtc.data.map.Section;
import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.Optional;
import java.util.Set;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
/**
* 供电
*/
@Service
public class PowerSupplyService {
public void run(Simulation simulation) {
SimulationDataRepository repository = simulation.getRepository();
Set<VirtualRealityTrain> trains = repository.getUsedTrains();
for (VirtualRealityTrain train : trains) {
SectionPosition headPosition = train.getHeadPosition();
if (headPosition == null)
continue;
Section section = headPosition.getSection();
Set<Catenary> catenaries = repository.findCatenaries(section.getCode());
if (CollectionUtils.isEmpty(catenaries)) {
train.updatePowerSupplyStatus(true);
continue;
}
Optional<Catenary> first = catenaries.stream().filter(catenary -> catenary.isWithinRange(headPosition)).findFirst();
if (first.isPresent()) {
Catenary catenary = first.get();
train.updatePowerSupplyStatus(catenary.isOn());
} else { //列车在没有接触网的地方也视为正常通电
train.updatePowerSupplyStatus(true);
}
}
}
public void addJobs(Simulation simulation) {
simulation.addJob(SimulationModule.CATENARY.name(), () -> this.run(simulation), SimulationConstants.POWER_SUPPLY_STATUS_UPDATE_RATE);
public void run(Simulation simulation) {
SimulationDataRepository repository = simulation.getRepository();
Set<VirtualRealityTrain> trains = repository.getUsedTrains();
for (VirtualRealityTrain train : trains) {
SectionPosition headPosition = train.getHeadPosition();
if (headPosition == null) {
continue;
}
if (!train.isPantographUp()) {
continue;
}
Section section = headPosition.getSection();
Set<Catenary> catenaries = repository.findCatenaries(section.getCode());
if (CollectionUtils.isEmpty(catenaries)) {
train.updatePowerSupplyStatus(true);
continue;
}
Optional<Catenary> first = catenaries.stream()
.filter(catenary -> catenary.isWithinRange(headPosition)).findFirst();
if (first.isPresent()) {
Catenary catenary = first.get();
train.updatePowerSupplyStatus(catenary.isOn());
} else { //列车在没有接触网的地方也视为正常通电
train.updatePowerSupplyStatus(true);
}
}
}
public void addJobs(Simulation simulation) {
simulation.addJob(SimulationModule.CATENARY.name(), () -> this.run(simulation),
SimulationConstants.POWER_SUPPLY_STATUS_UPDATE_RATE);
}
}

View File

@ -11,11 +11,10 @@ import club.joylink.rtss.simulation.cbtc.data.vo.TrainStatusVO;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import club.joylink.rtss.util.jsonSerialize.Boolean2NumSerializer;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.util.Objects;
import lombok.Getter;
import lombok.Setter;
import java.util.Objects;
/**
* 列车状态
*/
@ -23,359 +22,384 @@ import java.util.Objects;
@Setter
public class TrainStatus extends DeviceStatus {
/** 车组号 */
private String groupNumber;
/**
* 车组号
*/
private String groupNumber;
/** 服务号 */
private String serviceNumber;
/**
* 服务号
*/
private String serviceNumber;
/** 车次号 */
private String tripNumber;
/**
* 车次号
*/
private String tripNumber;
/** 目的地码 */
private String destinationCode;
/**
* 目的地码
*/
private String destinationCode;
/** 乘务组号 */
private String crewNumber;
/**
* 乘务组号
*/
private String crewNumber;
/** 最后一个抵达的车站 */
private String stationCode;
/**
* 最后一个抵达的车站
*/
private String stationCode;
/** 计划交路类型 */
private PlanRoutingType planRoutingType;
/**
* 计划交路类型
*/
private PlanRoutingType planRoutingType;
/**
* 列车所在区段code
*/
private String sectionCode;
/**
* 列车所在区段code
*/
private String sectionCode;
/** 物理区段code */
private String physicalCode;
/**
* 物理区段code
*/
private String physicalCode;
/** 物理区段偏移量百分比 */
private Float offsetp;
/**
* 物理区段偏移量百分比
*/
private Float offsetp;
/**
* 列车速度
*/
private float speed;
/**
* 列车速度
*/
private float speed;
/**
* 列车方向
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean right;
/**
* 列车方向
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean right;
/**
* 车门是否关闭且锁闭
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
private boolean doorCloseLock;
/**
* 车门是否关闭且锁闭
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
private boolean doorCloseLock;
/**
* 列车是否停稳
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
private boolean stop;
/**
* 列车是否停稳
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
private boolean stop;
/**
* 列车类型
*/
private TrainType type;
/**
* 列车类型
*/
private TrainType type;
/**
* 列车运行级别
*/
private RunLevel runLevel;
/**
* 列车运行级别
*/
private RunLevel runLevel;
/**
* 驾驶模式
*/
private DriveMode driveMode;
/**
* 驾驶模式
*/
private DriveMode driveMode;
/** 是否跳停 */
@JsonSerialize(using = Boolean2NumSerializer.class)
private boolean jump;
/**
* 是否跳停
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
private boolean jump;
/** 是否扣车 */
@JsonSerialize(using = Boolean2NumSerializer.class)
private boolean hold;
/**
* 是否扣车
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
private boolean hold;
/** 与计划时间差 */
private int dt;
/**
* 与计划时间差
*/
private int dt;
@JsonSerialize(using = Boolean2NumSerializer.class)
private boolean dispose;
@JsonSerialize(using = Boolean2NumSerializer.class)
private boolean dispose;
@JsonSerialize(using = Boolean2NumSerializer.class)
private boolean backUp;
@JsonSerialize(using = Boolean2NumSerializer.class)
private boolean backUp;
private boolean orderStop;
private boolean orderStop;
private String startStation;
private String startStation;
private String endStation;
private String endStation;
private int runningTime;
private int runningTime;
private int parkingRemainTime;
private int parkingRemainTime;
private String turnBackStrategy;
private String turnBackStrategy;
private String turnBackStatus;
private String turnBackStatus;
private Boolean autoTrigger;
private Boolean autoTrigger;
private VirtualRealityTrain.PreselectionMode preselectionMode;
private VirtualRealityTrain.PreselectionMode preselectionMode;
// private Float stationDiagramRatio;
public TrainStatus(TrainInfo train) {
super(train.getGroupNumber(), MapElement.DeviceType.TRAIN);
this.groupNumber = train.getGroupNumber();
this.type = train.getType();
if (Objects.equals(train.getType(), TrainType.PLAN)) {
this.serviceNumber = train.getServiceNumber();
this.tripNumber = train.getTripNumber();
this.planRoutingType = train.getPlanRoutingType();
}
if (!Objects.equals(train.getType(), TrainType.MANUAL)) {
this.destinationCode = train.getDestinationCode();
}
this.crewNumber = train.getCrewNumber();
this.stationCode = train.getStationCode();
this.sectionCode = train.getSection();
this.physicalCode = train.getPhysicalSection();
this.offsetp = train.getOffsetp();
this.speed = train.getSpeedKmPh();
this.right = train.getRight();
this.runLevel = train.getRunLevel();
this.driveMode = train.getDriveMode();
this.doorCloseLock = !train.isDoorOpen();
this.stop = train.isStop();
this.jump = train.isJump();
this.hold = train.isHold();
this.dt = train.getDt();
this.backUp = train.isBackUp();
this.orderStop = train.isOrderStop();
this.startStation = train.getStartStation();
this.endStation = train.getEndStation();
this.runningTime = train.getRunningTimeInSeconds();
this.parkingRemainTime = train.getParkingRemainTimeInSeconds();
this.turnBackStrategy = train.getTurnBackStrategy();
this.turnBackStatus = train.getTurnBackStatus();
this.autoTrigger = train.isAtsAutoTrigger();
this.preselectionMode = train.getPreselectionMode();
// this.stationDiagramRatio = train.getStationDiagramRatio();
private Boolean groundCommunicable;
// private Float stationDiagramRatio;
public TrainStatus(TrainInfo train) {
super(train.getGroupNumber(), MapElement.DeviceType.TRAIN);
this.groupNumber = train.getGroupNumber();
this.type = train.getType();
if (Objects.equals(train.getType(), TrainType.PLAN)) {
this.serviceNumber = train.getServiceNumber();
this.tripNumber = train.getTripNumber();
this.planRoutingType = train.getPlanRoutingType();
}
/**
* @param groupNumber
*/
public TrainStatus(String groupNumber) {
super(groupNumber, MapElement.DeviceType.TRAIN);
if (!Objects.equals(train.getType(), TrainType.MANUAL)) {
this.destinationCode = train.getDestinationCode();
}
this.crewNumber = train.getCrewNumber();
this.stationCode = train.getStationCode();
this.sectionCode = train.getSection();
this.physicalCode = train.getPhysicalSection();
this.offsetp = train.getOffsetp();
this.speed = train.getSpeedKmPh();
this.right = train.getRight();
this.runLevel = train.getRunLevel();
this.driveMode = train.getDriveMode();
this.doorCloseLock = !train.isDoorOpen();
this.stop = train.isStop();
this.jump = train.isJump();
this.hold = train.isHold();
this.dt = train.getDt();
this.backUp = train.isBackUp();
this.orderStop = train.isOrderStop();
this.startStation = train.getStartStation();
this.endStation = train.getEndStation();
this.runningTime = train.getRunningTimeInSeconds();
this.parkingRemainTime = train.getParkingRemainTimeInSeconds();
this.turnBackStrategy = train.getTurnBackStrategy();
this.turnBackStatus = train.getTurnBackStatus();
this.autoTrigger = train.isAtsAutoTrigger();
this.preselectionMode = train.getPreselectionMode();
this.groundCommunicable = train.isGroundCommunicable();
}
public static DeviceStatus buildDispose(String groupNumber) {
TrainStatus status = new TrainStatus(groupNumber);
status.dispose = true;
return status;
}
/**
* @param groupNumber
*/
public TrainStatus(String groupNumber) {
super(groupNumber, MapElement.DeviceType.TRAIN);
}
@Override
public boolean compareAndChange(MapElement device, DeviceStatusVO statusVO) {
TrainInfo train = (TrainInfo) device;
TrainStatusVO status = (TrainStatusVO)statusVO;
boolean change = false;
if (!Objects.equals(this.groupNumber, train.getGroupNumber())) {
this.groupNumber = train.getGroupNumber();
status.setGroupNumber(this.groupNumber);
change = true;
}
if (!Objects.equals(this.serviceNumber, train.getServiceNumber())) {
this.serviceNumber = train.getServiceNumber();
status.setServiceNumber(this.serviceNumber);
change = true;
}
if (!Objects.equals(this.tripNumber, train.getTripNumber())) {
this.tripNumber = train.getTripNumber();
status.setTripNumber(this.tripNumber);
change = true;
}
if (!Objects.equals(this.crewNumber, train.getCrewNumber())) {
this.crewNumber = train.getCrewNumber();
status.setCrewNumber(this.crewNumber);
change = true;
}
if (!Objects.equals(this.stationCode, train.getStationCode())) {
this.stationCode = train.getStationCode();
status.setStationCode(this.stationCode);
change = true;
}
if (!Objects.equals(this.planRoutingType, train.getPlanRoutingType())) {
this.planRoutingType = train.getPlanRoutingType();
change = true;
}
status.setPlanRoutingType(this.planRoutingType);
if (!Objects.equals(this.destinationCode, train.getDestinationCode())) {
this.destinationCode = train.getDestinationCode();
status.setDestinationCode(this.destinationCode);
change = true;
}
if (!Objects.equals(this.type, train.getType())) {
this.type = train.getType();
status.setType(this.type);
change = true;
}
if (!Objects.equals(this.sectionCode, train.getSection())) {
this.sectionCode = train.getSection();
status.setSectionCode(this.sectionCode);
change = true;
}
if (!Objects.equals(this.physicalCode, train.getPhysicalSection())) {
this.physicalCode = train.getPhysicalSection();
status.setPhysicalCode(this.physicalCode);
change = true;
}
if (!Objects.equals(this.offsetp, train.getOffsetp())) {
this.offsetp = train.getOffsetp();
status.setOffsetp(this.offsetp);
change = true;
}
if (!Objects.equals(this.speed, train.getSpeedKmPh())) {
this.speed = train.getSpeedKmPh();
status.setSpeed(this.speed);
change = true;
}
if (!Objects.equals(this.right, train.getRight())) {
this.right = train.getRight();
status.setRight(this.right);
change = true;
}
if (!Objects.equals(this.runLevel, train.getRunLevel())) {
this.runLevel = train.getRunLevel();
status.setRunLevel(this.runLevel);
change = true;
}
if (!Objects.equals(this.driveMode, train.getDriveMode())) {
this.driveMode = train.getDriveMode();
status.setDriveMode(this.driveMode);
change = true;
}
if (!Objects.equals(this.doorCloseLock, !train.isDoorOpen())) {
this.doorCloseLock = !train.isDoorOpen();
status.setDoorCloseLock(this.doorCloseLock);
change = true;
}
if (!Objects.equals(this.stop, train.isStop())) {
change = true;
this.stop = train.isStop();
status.setStop(this.stop);
}
if (!Objects.equals(this.jump, train.isJump())) {
this.jump = train.isJump();
status.setJump(this.jump);
change = true;
}
if (!Objects.equals(this.hold, train.isHold())) {
this.hold = train.isHold();
status.setHold(this.hold);
change = true;
}
if (!Objects.equals(this.backUp, train.isBackUp())) {
this.backUp = train.isBackUp();
status.setBackUp(this.backUp);
change = true;
}
if (!Objects.equals(this.dt, train.getDt())) {
this.dt = train.getDt();
status.setDt(this.dt);
change = true;
}
if (!Objects.equals(this.orderStop, train.isOrderStop())) {
this.orderStop = train.isOrderStop();
status.setOrderStop(this.orderStop);
change = true;
}
if (!Objects.equals(this.startStation, train.getStartStation())) {
this.startStation = train.getStartStation();
change = true;
}
status.setStartStation(this.startStation);
if (!Objects.equals(this.endStation, train.getEndStation())) {
this.endStation = train.getEndStation();
change = true;
}
status.setEndStation(this.endStation);
if (!Objects.equals(this.runningTime, train.getRunningTimeInSeconds())) {
this.runningTime = train.getRunningTimeInSeconds();
status.setRunningTime(this.runningTime);
change = true;
}
if (!Objects.equals(this.parkingRemainTime, train.getParkingRemainTimeInSeconds())) {
this.parkingRemainTime = train.getParkingRemainTimeInSeconds();
status.setParkingRemainTime(this.parkingRemainTime);
change = true;
}
if (!Objects.equals(this.turnBackStrategy, train.getTurnBackStrategy())) {
this.turnBackStrategy = train.getTurnBackStrategy();
status.setTurnBackStrategy(this.turnBackStrategy);
change = true;
}
if (!Objects.equals(this.turnBackStatus, train.getTurnBackStatus())) {
this.turnBackStatus = train.getTurnBackStatus();
status.setTurnBackStatus(this.turnBackStatus);
change = true;
}
if (!Objects.equals(this.autoTrigger, train.isAtsAutoTrigger())) {
this.autoTrigger = train.isAtsAutoTrigger();
status.setAutoTrigger(this.autoTrigger);
change = true;
}
if (!Objects.equals(this.preselectionMode, train.getPreselectionMode())) {
this.preselectionMode = train.getPreselectionMode();
status.setPreselectionMode(train.getPreselectionMode());
change = true;
}
/* if(!Objects.equals(this.stationDiagramRatio,train.getStationDiagramRatio())){
this.stationDiagramRatio = train.getStationDiagramRatio();
status.setStationDiagramRatio(train.getStationDiagramRatio());
change = true;
}*/
return change;
@Override
public boolean compareAndChange(MapElement device, DeviceStatusVO statusVO) {
TrainInfo train = (TrainInfo) device;
TrainStatusVO status = (TrainStatusVO) statusVO;
boolean change = false;
if (!Objects.equals(this.groupNumber, train.getGroupNumber())) {
this.groupNumber = train.getGroupNumber();
status.setGroupNumber(this.groupNumber);
change = true;
}
if (!Objects.equals(this.serviceNumber, train.getServiceNumber())) {
this.serviceNumber = train.getServiceNumber();
status.setServiceNumber(this.serviceNumber);
change = true;
}
if (!Objects.equals(this.tripNumber, train.getTripNumber())) {
this.tripNumber = train.getTripNumber();
status.setTripNumber(this.tripNumber);
change = true;
}
if (!Objects.equals(this.crewNumber, train.getCrewNumber())) {
this.crewNumber = train.getCrewNumber();
status.setCrewNumber(this.crewNumber);
change = true;
}
if (!Objects.equals(this.stationCode, train.getStationCode())) {
this.stationCode = train.getStationCode();
status.setStationCode(this.stationCode);
change = true;
}
if (!Objects.equals(this.planRoutingType, train.getPlanRoutingType())) {
this.planRoutingType = train.getPlanRoutingType();
change = true;
}
status.setPlanRoutingType(this.planRoutingType);
if (!Objects.equals(this.destinationCode, train.getDestinationCode())) {
this.destinationCode = train.getDestinationCode();
status.setDestinationCode(this.destinationCode);
change = true;
}
if (!Objects.equals(this.type, train.getType())) {
this.type = train.getType();
status.setType(this.type);
change = true;
}
if (!Objects.equals(this.sectionCode, train.getSection())) {
this.sectionCode = train.getSection();
status.setSectionCode(this.sectionCode);
change = true;
}
if (!Objects.equals(this.physicalCode, train.getPhysicalSection())) {
this.physicalCode = train.getPhysicalSection();
status.setPhysicalCode(this.physicalCode);
change = true;
}
if (!Objects.equals(this.offsetp, train.getOffsetp())) {
this.offsetp = train.getOffsetp();
status.setOffsetp(this.offsetp);
change = true;
}
if (!Objects.equals(this.speed, train.getSpeedKmPh())) {
this.speed = train.getSpeedKmPh();
status.setSpeed(this.speed);
change = true;
}
if (!Objects.equals(this.right, train.getRight())) {
this.right = train.getRight();
status.setRight(this.right);
change = true;
}
if (!Objects.equals(this.runLevel, train.getRunLevel())) {
this.runLevel = train.getRunLevel();
status.setRunLevel(this.runLevel);
change = true;
}
if (!Objects.equals(this.driveMode, train.getDriveMode())) {
this.driveMode = train.getDriveMode();
status.setDriveMode(this.driveMode);
change = true;
}
if (!Objects.equals(this.doorCloseLock, !train.isDoorOpen())) {
this.doorCloseLock = !train.isDoorOpen();
status.setDoorCloseLock(this.doorCloseLock);
change = true;
}
if (!Objects.equals(this.stop, train.isStop())) {
change = true;
this.stop = train.isStop();
status.setStop(this.stop);
}
if (!Objects.equals(this.jump, train.isJump())) {
this.jump = train.isJump();
status.setJump(this.jump);
change = true;
}
if (!Objects.equals(this.hold, train.isHold())) {
this.hold = train.isHold();
status.setHold(this.hold);
change = true;
}
if (!Objects.equals(this.backUp, train.isBackUp())) {
this.backUp = train.isBackUp();
status.setBackUp(this.backUp);
change = true;
}
if (!Objects.equals(this.dt, train.getDt())) {
this.dt = train.getDt();
status.setDt(this.dt);
change = true;
}
if (!Objects.equals(this.orderStop, train.isOrderStop())) {
this.orderStop = train.isOrderStop();
status.setOrderStop(this.orderStop);
change = true;
}
if (!Objects.equals(this.startStation, train.getStartStation())) {
this.startStation = train.getStartStation();
change = true;
}
status.setStartStation(this.startStation);
if (!Objects.equals(this.endStation, train.getEndStation())) {
this.endStation = train.getEndStation();
change = true;
}
status.setEndStation(this.endStation);
if (!Objects.equals(this.runningTime, train.getRunningTimeInSeconds())) {
this.runningTime = train.getRunningTimeInSeconds();
status.setRunningTime(this.runningTime);
change = true;
}
if (!Objects.equals(this.parkingRemainTime, train.getParkingRemainTimeInSeconds())) {
this.parkingRemainTime = train.getParkingRemainTimeInSeconds();
status.setParkingRemainTime(this.parkingRemainTime);
change = true;
}
if (!Objects.equals(this.turnBackStrategy, train.getTurnBackStrategy())) {
this.turnBackStrategy = train.getTurnBackStrategy();
status.setTurnBackStrategy(this.turnBackStrategy);
change = true;
}
if (!Objects.equals(this.turnBackStatus, train.getTurnBackStatus())) {
this.turnBackStatus = train.getTurnBackStatus();
status.setTurnBackStatus(this.turnBackStatus);
change = true;
}
if (!Objects.equals(this.autoTrigger, train.isAtsAutoTrigger())) {
this.autoTrigger = train.isAtsAutoTrigger();
status.setAutoTrigger(this.autoTrigger);
change = true;
}
if (!Objects.equals(this.preselectionMode, train.getPreselectionMode())) {
this.preselectionMode = train.getPreselectionMode();
status.setPreselectionMode(train.getPreselectionMode());
change = true;
}
if (!Objects.equals(this.groundCommunicable, train.isGroundCommunicable())) {
this.groundCommunicable = train.isGroundCommunicable();
status.setGroundCommunicable(this.groundCommunicable);
change = true;
}
return change;
}
@Override
public DeviceStatusVO convert2VO(MapElement device) {
return new TrainStatusVO(this);
}
@Override
public DeviceStatusVO convert2VO(MapElement device) {
return new TrainStatusVO(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TrainStatus that = (TrainStatus) o;
return Objects.equals(this.getCode(), that.getCode()) &&
Float.compare(that.speed, speed) == 0 &&
doorCloseLock == that.doorCloseLock &&
stop == that.stop &&
Objects.equals(groupNumber, that.groupNumber) &&
Objects.equals(serviceNumber, that.serviceNumber) &&
Objects.equals(tripNumber, that.tripNumber) &&
Objects.equals(destinationCode, that.destinationCode) &&
Objects.equals(sectionCode, that.sectionCode) &&
Objects.equals(right, that.right) &&
type == that.type &&
runLevel == that.runLevel &&
driveMode == that.driveMode &&
jump == that.jump &&
hold == that.hold &&
backUp == that.backUp &&
dispose == that.dispose;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TrainStatus that = (TrainStatus) o;
return Objects.equals(this.getCode(), that.getCode()) &&
Float.compare(that.speed, speed) == 0 &&
doorCloseLock == that.doorCloseLock &&
stop == that.stop &&
Objects.equals(groupNumber, that.groupNumber) &&
Objects.equals(serviceNumber, that.serviceNumber) &&
Objects.equals(tripNumber, that.tripNumber) &&
Objects.equals(destinationCode, that.destinationCode) &&
Objects.equals(sectionCode, that.sectionCode) &&
Objects.equals(right, that.right) &&
type == that.type &&
runLevel == that.runLevel &&
driveMode == that.driveMode &&
jump == that.jump &&
hold == that.hold &&
backUp == that.backUp &&
dispose == that.dispose;
}
@Override
public int hashCode() {
return Objects.hash(this.getCode(), groupNumber, serviceNumber, tripNumber, destinationCode, sectionCode, speed, right, doorCloseLock, stop, type, runLevel, driveMode, jump, hold,backUp, dispose);
}
@Override
public int hashCode() {
return Objects.hash(this.getCode(), groupNumber, serviceNumber, tripNumber, destinationCode,
sectionCode, speed, right, doorCloseLock, stop, type, runLevel, driveMode, jump, hold,
backUp, dispose);
}
}

View File

@ -319,10 +319,10 @@ public class TrainInfo extends MapElement {
private Float locationKM;
/**
* 车站之间的运行比例
* 与地面的通信是否正常
*/
// @Setter
// private Float stationDiagramRatio;
private boolean groundCommunicable = true;
public TrainInfo(String groupNumber) {
super(groupNumber, DeviceType.TRAIN);
this.groupNumber = groupNumber;
@ -345,13 +345,6 @@ public class TrainInfo extends MapElement {
info.tripNumber = StringUtils.isEmpty(train.getTripNumber()) ? "" : train.getTripNumber();
return info;
}
// public static TrainInfo constructManualTrain(VirtualRealityTrain train, TrainPosition tp) {
// TrainInfo info = constructManualTrain(train);
// info.setLocationKM(tp.getLocation());
// info.setRight(tp.isRight());
// info.setSpeed(tp.getSpeed());
// return info;
// }
private TrainInfo(VirtualRealityTrain train) {
super(train.getGroupNumber(), DeviceType.TRAIN);
@ -492,6 +485,7 @@ public class TrainInfo extends MapElement {
}
this.preselectionMode = train.getPreselectionMode();
this.beAbout2Arrival = train.isBeAbout2Arrive();
this.groundCommunicable = train.isPowerOn();
return this;
}

View File

@ -4,11 +4,12 @@ import club.joylink.rtss.simulation.cbtc.constant.DriveMode;
import club.joylink.rtss.simulation.cbtc.constant.PlanRoutingType;
import club.joylink.rtss.simulation.cbtc.constant.RunLevel;
import club.joylink.rtss.simulation.cbtc.constant.TrainType;
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
import club.joylink.rtss.simulation.cbtc.data.map.MapElement.DeviceType;
import club.joylink.rtss.simulation.cbtc.data.status.TrainStatus;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain.PreselectionMode;
import club.joylink.rtss.util.jsonSerialize.Boolean2NumSerializer;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Getter;
import lombok.NoArgsConstructor;
@ -22,161 +23,181 @@ import lombok.Setter;
@NoArgsConstructor
public class TrainStatusVO extends DeviceStatusVO {
/** 车组号 */
private String groupNumber;
/**
* 车组号
*/
private String groupNumber;
/** 服务号 */
private String serviceNumber;
/**
* 服务号
*/
private String serviceNumber;
/** 车次号 */
private String tripNumber;
/**
* 车次号
*/
private String tripNumber;
/** 目的地码 */
private String destinationCode;
/**
* 目的地码
*/
private String destinationCode;
/** 乘务组号 */
private String crewNumber;
/**
* 乘务组号
*/
private String crewNumber;
private String stationCode;
private String stationCode;
/** 计划交路类型 */
@JsonInclude(JsonInclude.Include.ALWAYS)
private PlanRoutingType planRoutingType;
/**
* 计划交路类型
*/
@JsonInclude(Include.ALWAYS)
private PlanRoutingType planRoutingType;
/**
* 列车所在区段code
*/
private String sectionCode;
/**
* 列车所在区段code
*/
private String sectionCode;
/** 物理区段code */
private String physicalCode;
/**
* 物理区段code
*/
private String physicalCode;
/** 物理区段偏移量百分比 */
private Float offsetp;
/**
* 物理区段偏移量百分比
*/
private Float offsetp;
/**
* 列车速度
*/
private Float speed;
/**
* 列车速度
*/
private Float speed;
/**
* 列车方向
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean right;
/**
* 列车方向
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean right;
/**
* 车门是否关闭且锁闭
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean doorCloseLock;
/**
* 车门是否关闭且锁闭
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean doorCloseLock;
/**
* 列车是否停稳
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean stop;
/**
* 列车是否停稳
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean stop;
/**
* 列车类型
*/
private TrainType type;
/**
* 列车类型
*/
private TrainType type;
/**
* 列车运行级别
*/
private RunLevel runLevel;
/**
* 列车运行级别
*/
private RunLevel runLevel;
/**
* 驾驶模式
*/
private DriveMode driveMode;
/**
* 驾驶模式
*/
private DriveMode driveMode;
/** 是否跳停 */
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean jump;
/**
* 是否跳停
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean jump;
/** 是否扣车 */
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean hold;
/**
* 是否扣车
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean hold;
/** 与计划时间差 */
private Integer dt;
/**
* 与计划时间差
*/
private Integer dt;
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean dispose;
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean dispose;
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean backUp;
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean backUp;
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean orderStop;
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean orderStop;
private String startStation;
private String startStation;
private String endStation;
private String endStation;
private Integer runningTime;
private Integer runningTime;
private Integer parkingRemainTime;
private Integer parkingRemainTime;
private String turnBackStrategy;
private String turnBackStrategy;
private String turnBackStatus;
private String turnBackStatus;
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean autoTrigger;
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean autoTrigger;
private VirtualRealityTrain.PreselectionMode preselectionMode;
// private Float stationDiagramRatio;
private PreselectionMode preselectionMode;
private Boolean groundCommunicable;
public TrainStatusVO(TrainInfo train) {
super(train.getGroupNumber(), MapElement.DeviceType.TRAIN);
}
public TrainStatusVO(TrainInfo train) {
super(train.getGroupNumber(), DeviceType.TRAIN);
}
public TrainStatusVO(TrainStatus train) {
super(train.getGroupNumber(), MapElement.DeviceType.TRAIN);
this.serviceNumber = train.getServiceNumber();
this.tripNumber = train.getTripNumber();
this.destinationCode = train.getDestinationCode();
this.crewNumber = train.getCrewNumber();
this.planRoutingType = train.getPlanRoutingType();
this.sectionCode = train.getSectionCode();
this.physicalCode = train.getPhysicalCode();
this.offsetp = train.getOffsetp();
this.speed = train.getSpeed();
this.right = train.getRight();
this.doorCloseLock = train.isDoorCloseLock();
this.stop = train.isStop();
this.type = train.getType();
this.runLevel = train.getRunLevel();
this.driveMode = train.getDriveMode();
this.jump = train.isJump();
this.hold = train.isHold();
this.dt = train.getDt();
this.dispose = train.isDispose();
this.backUp = train.isBackUp();
this.orderStop = train.isOrderStop();
this.startStation = train.getStartStation();
this.endStation = train.getEndStation();
this.runningTime = train.getRunningTime();
this.parkingRemainTime = train.getParkingRemainTime();
this.turnBackStrategy = train.getTurnBackStrategy();
this.turnBackStatus = train.getTurnBackStatus();
this.autoTrigger = train.getAutoTrigger();
this.preselectionMode = train.getPreselectionMode();
// this.stationDiagramRatio = train.getStationDiagramRatio();
}
public TrainStatusVO(TrainStatus train) {
super(train.getGroupNumber(), DeviceType.TRAIN);
this.serviceNumber = train.getServiceNumber();
this.tripNumber = train.getTripNumber();
this.destinationCode = train.getDestinationCode();
this.crewNumber = train.getCrewNumber();
this.planRoutingType = train.getPlanRoutingType();
this.sectionCode = train.getSectionCode();
this.physicalCode = train.getPhysicalCode();
this.offsetp = train.getOffsetp();
this.speed = train.getSpeed();
this.right = train.getRight();
this.doorCloseLock = train.isDoorCloseLock();
this.stop = train.isStop();
this.type = train.getType();
this.runLevel = train.getRunLevel();
this.driveMode = train.getDriveMode();
this.jump = train.isJump();
this.hold = train.isHold();
this.dt = train.getDt();
this.dispose = train.isDispose();
this.backUp = train.isBackUp();
this.orderStop = train.isOrderStop();
this.startStation = train.getStartStation();
this.endStation = train.getEndStation();
this.runningTime = train.getRunningTime();
this.parkingRemainTime = train.getParkingRemainTime();
this.turnBackStrategy = train.getTurnBackStrategy();
this.turnBackStatus = train.getTurnBackStatus();
this.autoTrigger = train.getAutoTrigger();
this.preselectionMode = train.getPreselectionMode();
this.groundCommunicable = train.getGroundCommunicable();
}
public TrainStatusVO(String groupNumber) {
super(groupNumber, DeviceType.TRAIN);
}
public TrainStatusVO(String groupNumber) {
super(groupNumber, MapElement.DeviceType.TRAIN);
}
public static DeviceStatusVO buildDispose(String groupNumber) {
TrainStatusVO vo = new TrainStatusVO(groupNumber);
vo.setDispose(true);
return vo;
}
public static DeviceStatusVO buildDispose(String groupNumber) {
TrainStatusVO vo = new TrainStatusVO(groupNumber);
vo.setDispose(true);
return vo;
}
}

View File

@ -1003,22 +1003,55 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
if (speed > 0) {
this.breaking = false;
}
// if (linkTrain != null) {
// linkTrain.setSpeed(speed);
// }
}
/**
* 更新供电状态
* 是否有受电弓是升起状态
*/
public boolean isPantographUp() {
return pantograph1Up || pantograph2Up;
}
public void updatePantographUp(int index, boolean up) {
switch (index) {
case 1:
pantograph1Up = up;
break;
case 2:
pantograph2Up = up;
break;
}
if (!isPantographUp()) {
this.powerOn = false;
}
}
/**
* 更新接触网供电状态 此方法应当在受电弓升起时才可调用
*
* @param on 接触网供电是否开启
* @param on 接触网是否供电
*/
public void updatePowerSupplyStatus(boolean on) {
if (!on) {
this.powerOn = false;
} else {
this.powerOn = pantograph1Up;
if (on && !this.powerOn) {
initWhenPowerUp();
}
this.powerOn = on;
}
/**
* 当列车从断电->通电时初始化列车状态
*/
private void initWhenPowerUp() {
this.preselectionMode = PreselectionMode.RM;
this.tempPreselectionMode = PreselectionMode.RM;
this.runLevel = RunLevel.IL;
this.driveMode = DriveMode.RM;
this.ma2 = null;
this.cbtcMaMissDuration = 0;
this.atoSpeed = 0;
this.atpSpeed = 0;
this.atoOn = false;
this.atpOn = true;
}
public synchronized void parkingAt(Section headSection) {

View File

@ -16,355 +16,356 @@ import club.joylink.rtss.simulation.cbtc.event.SimulationTrainIsAbout2ArriveEven
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 java.util.List;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Objects;
@Slf4j
@Component
public class ATPLogicLoop {
@Autowired
private ATPService atpService;
@Autowired
private ATPService atpService;
@Autowired
private ATOService atoService;
@Autowired
private ATOService atoService;
@Autowired
private ApplicationContext applicationContext;
@Autowired
private ApplicationContext applicationContext;
public void run(Simulation simulation) {
// ATP防护逻辑
List<VirtualRealityTrain> onlineTrain = simulation.getRepository().getOnlineTrainList();
for (VirtualRealityTrain train : onlineTrain) {
if (!train.isPowerOn()) { //如果列车断电
if (!train.isStop() && !train.isEB()) {
atpService.triggerSignalEB(train);
}
atpService.closeATO(train);
continue;
}
this.onboardLogicRun2(simulation, train);
SimulationMember member = simulation
.findMemberByRoleAndDeviceCode(SimulationMember.Type.DRIVER, train.getGroupNumber());
if (Objects.nonNull(member) && train.isAtoOn()/*&& member.isRobot()*/) {
this.driveLogicRun(simulation, train);
}
public void run(Simulation simulation) {
// ATP防护逻辑
List<VirtualRealityTrain> onlineTrain = simulation.getRepository().getOnlineTrainList();
for (VirtualRealityTrain train : onlineTrain) {
if (!train.isPowerOn()) { //如果列车断电
if (!train.isStop() && !train.isEB()) {
atpService.triggerSignalEB(train);
}
atpService.closeATO(train);
continue;
}
this.onboardLogicRun2(simulation, train);
SimulationMember member = simulation
.findMemberByRoleAndDeviceCode(SimulationMember.Type.DRIVER, train.getGroupNumber());
if (Objects.nonNull(member) && train.isAtoOn()) {
this.driveLogicRun(simulation, train);
}
}
}
private void driveLogicRun(Simulation simulation, VirtualRealityTrain train) {
if (train.isChangeEnds() && train.isStop()) {
// 列车换端中
this.atpService.changeEndsProgress(train);
return;
}
if (!train.isAtoOn()) {
// todo 机器人司机驾驶控制
}
}
private void onboardLogicRun2(Simulation simulation, VirtualRealityTrain train) {
atpService.handlePreselectionMode(simulation, train);
this.calculateSpeedCurve(simulation, train);
this.closeATOIfStatusIsIncorrect(train);
train.setAtoCanOpen(atpService.canOpenATO(train));
this.checkSpeedRelease(train);
boolean right = train.isRight();
SectionPosition headPosition = train.getHeadPosition();
Boolean beAbout2Arrive = this.updateBeAbout2Arrive(train, right, headPosition);
if (beAbout2Arrive != null && beAbout2Arrive) {
applicationContext.publishEvent(
new SimulationTrainIsAbout2ArriveEvent(this, simulation, train));
}
this.updateRunningTime(train);
if (train.isStop()) { // 列车停车
if (!train.isBreaking() && !train.isRMMode() && !train.isNRMMode()) { // 制动状态
// 施加常规制动防止倒溜
this.atoService.openBreaking(train);
}
if (train.isParkingAt()) {// 列车站台停靠
this.handleStandParkedTrain(simulation, train);
}
/* 缓解EB检查 */
if (train.isEB()) {
if (train.isRMMode() && train.isLeverNotInTractionGear()) { //停车RM模式操纵杆非牵引位
atpService.cancelSignalEB(train);
}
}
if (this.checkConditionToMove2(simulation, train)) { // 可以启动
this.atoService.closeBreaking(train);
} else {
return;
}
} else { // 列车运行
if (train.isParkingAt()) {
train.depart();
}
// 列车倒车限速
if (VirtualRealityTrain.Handwheel.REVERSE.equals(train.getGear())) {
if (train.getSpeed() > 5 / 3.6) { //5km/h从西安二操作手册得来
atpService.triggerSignalEB(train);
}
}
if (train.isAtpOn()) {
this.atpService.speedProtect(simulation, train);
speedReleaseProtect(simulation, train);
}
if (train.isEB()) {
return;
}
}
this.atoService.ato2(train);
}
private void driveLogicRun(Simulation simulation, VirtualRealityTrain train) {
if (train.isChangeEnds() && train.isStop()) {
// 列车换端中
this.atpService.changeEndsProgress(train);
return;
}
if (!train.isAtoOn()) {
// todo 机器人司机驾驶控制
}
/**
* 速度释放特殊防护
*/
private void speedReleaseProtect(Simulation simulation, VirtualRealityTrain train) {
if (train.isEB()) {
return;
}
private void onboardLogicRun2(Simulation simulation, VirtualRealityTrain train) {
atpService.handlePreselectionMode(simulation, train);
this.calculateSpeedCurve(simulation, train);
this.closeATOIfStatusIsIncorrect(train);
train.setAtoCanOpen(atpService.canOpenATO(train));
this.checkSpeedRelease(train);
boolean right = train.isRight();
if (train.isReleased()) {
if (!simulation.getRepository().hasResponder()) { // 没有应答器
// 列车处于释放中如果列车车头已经跨过信号机还没有更新ITC-MA触发EB
SectionPosition headPosition = train.getHeadPosition();
Boolean beAbout2Arrive = this.updateBeAbout2Arrive(train, right, headPosition);
if (beAbout2Arrive != null && beAbout2Arrive) {
applicationContext.publishEvent(new SimulationTrainIsAbout2ArriveEvent(this, simulation, train));
SectionPosition tailPosition = train.calculateTailPosition();
Signal signal = headPosition.getSection().getSignalOf(train.isRight());
if (signal != null) {
if (new SectionPosition(signal.getSection(), signal.getOffset()).isBetween(headPosition,
tailPosition)) {
this.atpService.triggerSignalEB(train);
}
}
this.updateRunningTime(train);
if (train.isStop()) { // 列车停车
if (!train.isBreaking() && !train.isRMMode() && !train.isNRMMode()) { // 制动状态
// 施加常规制动防止倒溜
this.atoService.openBreaking(train);
}
if (train.isParkingAt()) {// 列车站台停靠
this.handleStandParkedTrain(simulation, train);
}
/* 缓解EB检查 */
if (train.isEB()) {
if (train.isRMMode() && train.isLeverNotInTractionGear()) { //停车RM模式操纵杆非牵引位
atpService.cancelSignalEB(train);
}
// if (Project.SR_SANDBOX.name().equals(simulation.getBuildParams().getMap().getProjectCode())) {
// atpService.cancelSignalEB(train);
// atpService.openATO(train);
// }
}
if (this.checkConditionToMove2(simulation, train)) { // 可以启动
this.atoService.closeBreaking(train);
} else {
return;
}
} else { // 列车运行
if (train.isParkingAt()) {
train.depart();
}
// 列车倒车限速
if (VirtualRealityTrain.Handwheel.REVERSE.equals(train.getGear())) {
if (train.getSpeed() > 5 / 3.6) { //5km/h从西安二操作手册得来
atpService.triggerSignalEB(train);
}
}
// 判断列车是否跳站
// this.checkTrainJumpAndSend2Ats(simulation, train, headPosition, tailPosition, right);
if (train.isAtpOn()) {
this.atpService.speedProtect(simulation, train);
speedReleaseProtect(simulation, train);
}
if (train.isEB()) {
return;
}
}
// 列车ATO自动驾驶逻辑运行
// this.atoService.ATO(train);
this.atoService.ato2(train);
}
}
}
/**
* 速度释放特殊防护
*/
private void speedReleaseProtect(Simulation simulation, VirtualRealityTrain train) {
if (train.isEB())
return;
if (train.isReleased()) {
if (!simulation.getRepository().hasResponder()) { // 没有应答器
// 列车处于释放中如果列车车头已经跨过信号机还没有更新ITC-MA触发EB
SectionPosition headPosition = train.getHeadPosition();
SectionPosition tailPosition = train.calculateTailPosition();
Signal signal = headPosition.getSection().getSignalOf(train.isRight());
if (signal != null) {
if (new SectionPosition(signal.getSection(), signal.getOffset()).isBetween(headPosition, tailPosition)) {
this.atpService.triggerSignalEB(train);
}
}
}
}
/**
* 关闭ATO如果状态不正确
*/
private void closeATOIfStatusIsIncorrect(VirtualRealityTrain train) {
if (!train.isAtoOn()) {
return;
}
/**
* 关闭ATO如果状态不正确
*/
private void closeATOIfStatusIsIncorrect(VirtualRealityTrain train) {
if (!train.isAtoOn())
return;
if (train.isEB() || !train.isInTheGear(VirtualRealityTrain.Handwheel.ATO) || !train.isAMMode())
atpService.closeATO(train);
if (train.isEB() || !train.isInTheGear(VirtualRealityTrain.Handwheel.ATO)
|| !train.isAMMode()) {
atpService.closeATO(train);
}
}
/**
* 检查并提示速度释放
*/
private void checkSpeedRelease(VirtualRealityTrain train) {
if (!train.isReleased() && train.isITC() && train.needReleaseSpeed())
train.addMessage(VirtualRealityTrain.ConfirmationMessage.Confirm_Release_Speed);
/**
* 检查并提示速度释放
*/
private void checkSpeedRelease(VirtualRealityTrain train) {
if (!train.isReleased() && train.isITC() && train.needReleaseSpeed()) {
train.addMessage(VirtualRealityTrain.ConfirmationMessage.Confirm_Release_Speed);
}
}
private void calculateSpeedCurve(Simulation simulation, VirtualRealityTrain train) {
if (!train.isAtpOn())
return;
DriveMode driveMode = train.getDriveMode();
switch (driveMode) {
case RM: {
float atpSpeed = simulation.getRepository().getConfig().getRmAtpSpeed();
float atoSpeed = train.getAtpSpeed() - 5 / 3.6f;
train.setAtpSpeed(atpSpeed);
train.setAtoSpeed(atoSpeed);
break;
}
case AM:
case CM: {
MaService.Ma ma = train.getMa2();
if (ma != null) {
// EB 触发速度计算
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);
// ATO推荐速度计算
SpeedCurve atoSpeedCurve = SpeedCurve.calculateAtoStopCurveAndUpdate(train, ma);
ma.setAtoStopCurve(atoSpeedCurve);
float atoSpeed = atoSpeedCurve.getSpeedOf(atoSpeedCurve.getTotalDistance());
train.setAtpSpeed(atpSpeed);
train.setAtoSpeed(atoSpeed);
} else {
train.setAtpSpeed(0);
train.setAtoSpeed(0);
}
}
}
private void calculateSpeedCurve(Simulation simulation, VirtualRealityTrain train) {
if (!train.isAtpOn()) {
return;
}
private void updateRunningTime(VirtualRealityTrain train) {
if (train.isParkingAt()) {
train.setRunningTime(0);
DriveMode driveMode = train.getDriveMode();
switch (driveMode) {
case RM: {
float atpSpeed = simulation.getRepository().getConfig().getRmAtpSpeed();
float atoSpeed = train.getAtpSpeed() - 5 / 3.6f;
train.setAtpSpeed(atpSpeed);
train.setAtoSpeed(atoSpeed);
break;
}
case AM:
case CM: {
MaService.Ma ma = train.getMa2();
if (ma != null) {
// EB 触发速度计算
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);
// ATO推荐速度计算
SpeedCurve atoSpeedCurve = SpeedCurve.calculateAtoStopCurveAndUpdate(train, ma);
ma.setAtoStopCurve(atoSpeedCurve);
float atoSpeed = atoSpeedCurve.getSpeedOf(atoSpeedCurve.getTotalDistance());
train.setAtpSpeed(atpSpeed);
train.setAtoSpeed(atoSpeed);
} else {
train.setRunningTime(train.getRunningTime() + SimulationConstants.ATP_LOOP_RATE);
train.setAtpSpeed(0);
train.setAtoSpeed(0);
}
}
}
private void handleStandParkedTrain(Simulation simulation, VirtualRealityTrain train) {
StandParkedTrainActivity activity = train.getStandParkedTrainActivity();
switch (activity) {
case PARK: // 停靠
train.nextParkedTrainActivity();
if (train.isAtoOn()) {
atpService.closeATO(train);
}
break;
case OPEN_DOOR: // 开门
if (train.isAutoOpenDoor()) {
this.atoService.syncOpenDoor(simulation, train);
}
if (this.isAllDoorOpen(simulation, train)) {
train.nextParkedTrainActivity();
}
break;
case BOARD: // 乘客乘降
break;
case CLOSE_DOOR: // 关门
if (train.isAutoCloseDoor()) {
this.atoService.syncCloseDoor(simulation, train);
}
if (this.isAllDoorClose(simulation, train)) {
train.nextParkedTrainActivity();
}
break;
case START: // 准备出发
train.setParkSection(train.getHeadPosition().getSection());
break;
}
}
}
private boolean isAllDoorClose(Simulation simulation, VirtualRealityTrain train) {
if (!train.isAllDoorCloseAndLock()) {
return false;
private void updateRunningTime(VirtualRealityTrain train) {
if (train.isParkingAt()) {
train.setRunningTime(0);
} else {
train.setRunningTime(train.getRunningTime() + SimulationConstants.ATP_LOOP_RATE);
}
}
private void handleStandParkedTrain(Simulation simulation, VirtualRealityTrain train) {
StandParkedTrainActivity activity = train.getStandParkedTrainActivity();
switch (activity) {
case PARK: // 停靠
train.nextParkedTrainActivity();
if (train.isAtoOn()) {
atpService.closeATO(train);
}
List<Stand> standList = train.getHeadPosition().getSection().getStandList();
if (!CollectionUtils.isEmpty(standList)) {
for (Stand stand : standList) {
if (!stand.isPsdSafe()) {
break;
case OPEN_DOOR: // 开门
if (train.isAutoOpenDoor()) {
this.atoService.syncOpenDoor(simulation, train);
}
if (this.isAllDoorOpen(simulation, train)) {
train.nextParkedTrainActivity();
}
break;
case BOARD: // 乘客乘降
break;
case CLOSE_DOOR: // 关门
if (train.isAutoCloseDoor()) {
this.atoService.syncCloseDoor(simulation, train);
}
if (this.isAllDoorClose(simulation, train)) {
train.nextParkedTrainActivity();
}
break;
case START: // 准备出发
train.setParkSection(train.getHeadPosition().getSection());
break;
}
}
private boolean isAllDoorClose(Simulation simulation, VirtualRealityTrain train) {
if (!train.isAllDoorCloseAndLock()) {
return false;
}
List<Stand> standList = train.getHeadPosition().getSection().getStandList();
if (!CollectionUtils.isEmpty(standList)) {
for (Stand stand : standList) {
if (!stand.isPsdSafe()) {
// log.debug(String.format("列车[%s]所在站台[%s(%s)]屏蔽门未关闭且没有互锁解除,不能动车",
// train.getGroupNumber(), stand.getName(), stand.getCode()));
return false;
}
}
return false;
}
return true;
}
}
return true;
}
private boolean isAllDoorOpen(Simulation simulation, VirtualRealityTrain train) {
Section section = train.getHeadPosition().getSection();
if (!section.isNormalStandTrack()) {
return true;
private boolean isAllDoorOpen(Simulation simulation, VirtualRealityTrain train) {
Section section = train.getHeadPosition().getSection();
if (!section.isNormalStandTrack()) {
return true;
}
List<Stand> standList = section.getStandList();
if (!CollectionUtils.isEmpty(standList)) {
for (Stand stand : standList) {
boolean trainDoorOpen = false;
if (stand.isInside() && stand.isRight()) { // 内测右站台开1门
trainDoorOpen = train.getDoor1().isOpen();
} else if (stand.isInside() && !stand.isRight()) { // 内测左站台开2门
trainDoorOpen = train.getDoor2().isOpen();
} else if (!stand.isInside() && stand.isRight()) { //外侧右站台开2门
trainDoorOpen = train.getDoor2().isOpen();
} else {
trainDoorOpen = train.getDoor1().isOpen();
}
List<Stand> standList = section.getStandList();
if (!CollectionUtils.isEmpty(standList)) {
for (Stand stand : standList) {
boolean trainDoorOpen = false;
if (stand.isInside() && stand.isRight()) { // 内测右站台开1门
trainDoorOpen = train.getDoor1().isOpen();
} else if (stand.isInside() && !stand.isRight()) { // 内测左站台开2门
trainDoorOpen = train.getDoor2().isOpen();
} else if (!stand.isInside() && stand.isRight()) { //外侧右站台开2门
trainDoorOpen = train.getDoor2().isOpen();
} else {
trainDoorOpen = train.getDoor1().isOpen();
}
boolean psdOpen = !stand.hasDoor() || stand.isPsdOpen();
if (!psdOpen || !trainDoorOpen) {
return false;
}
}
return true;
boolean psdOpen = !stand.hasDoor() || stand.isPsdOpen();
if (!psdOpen || !trainDoorOpen) {
return false;
}
}
return true;
}
return false;
}
public boolean checkConditionToMove2(Simulation simulation, VirtualRealityTrain train) {
if (train.isParkingAt()) {
if (!train.isStandReadyStart()) { // 站台停靠未完成
return false;
}
SectionPosition headPosition = train.getHeadPosition();
Signal signal = headPosition.getSection().getSignalOf(train.isRight());
if (signal != null) {// 站台前方信号未开放
if (!signal.isMainAspect() && !(train.isRMMode() || train.isNRMMode())) {
return false;
}
if (signal.isMainAspect()) {
// 信号机开放但移动授权终点还是此信号机可能是ITC未到达此信号机主应答器
MaService.Ma ma2 = train.getMa2();
if (ma2 != null && ma2.getDevice().equals(signal) && !train.isReleased()) {
return false;
}
}
}
}
if (train.isHold() && train.isAtoOn()) {
Section section = train.getHeadPosition().getSection();
List<Stand> standList = section.getStandList();
if (!CollectionUtils.isEmpty(standList) &&
standList.stream()
.anyMatch(stand -> stand.isHoldTrain())) {
return false;
}
}
if (simulation.getRepository().getConfig().isAdjustOperationAutomatically()) {
if (train.getDelayTime() <= 0) {
train.setDelayTime(SimulationConstants.ATO_TRAIN_GET_SIGNAL_TO_START_DELAY);
return false;
}
train.setDelayTime(Math.max(train.getDelayTime() - SimulationConstants.ATP_LOOP_RATE, 0));
if (train.getDelayTime() > 0) {
return false;
}
}
return true;
}
public boolean checkConditionToMove2(Simulation simulation, VirtualRealityTrain train) {
if (train.isParkingAt()) {
if (!train.isStandReadyStart()) { // 站台停靠未完成
return false;
}
SectionPosition headPosition = train.getHeadPosition();
Signal signal = headPosition.getSection().getSignalOf(train.isRight());
if (signal != null) {// 站台前方信号未开放
if (!signal.isMainAspect() && !(train.isRMMode() || train.isNRMMode())) {
return false;
}
if (signal.isMainAspect()) {
// 信号机开放但移动授权终点还是此信号机可能是ITC未到达此信号机主应答器
MaService.Ma ma2 = train.getMa2();
if (ma2 != null && ma2.getDevice().equals(signal) && !train.isReleased()) {
return false;
}
}
}
}
if (train.isHold() && train.isAtoOn()) {
Section section = train.getHeadPosition().getSection();
List<Stand> standList = section.getStandList();
if (!CollectionUtils.isEmpty(standList) &&
standList.stream()
.anyMatch(stand -> stand.isHoldTrain())) {
return false;
}
}
if (simulation.getRepository().getConfig().isAdjustOperationAutomatically()) {
if (train.getDelayTime() <= 0) {
train.setDelayTime(SimulationConstants.ATO_TRAIN_GET_SIGNAL_TO_START_DELAY);
return false;
}
train.setDelayTime(Math.max(train.getDelayTime() - SimulationConstants.ATP_LOOP_RATE, 0));
if (train.getDelayTime() > 0) {
return false;
}
}
return true;
/**
* 更新即将到站状态
*/
private Boolean updateBeAbout2Arrive(VirtualRealityTrain train, boolean right,
SectionPosition headPosition) {
Section target = train.getTarget();
if (target != null) {
float stopPoint = target.getStopPointByDirection(right);
SectionPosition targetStopPosition = new SectionPosition(target, stopPoint);
Float distance2NextStation = CalculateService.calculateDistance(headPosition,
targetStopPosition, right, false);
//距下一站的距离小于200视为即将到站
boolean old = train.isBeAbout2Arrive();
train.setBeAbout2Arrive(distance2NextStation != null && distance2NextStation < 200);
if (!Objects.equals(old, train.isBeAbout2Arrive())) {
return train.isBeAbout2Arrive();
}
}
return null;
}
/**
* 更新即将到站状态
*/
private Boolean updateBeAbout2Arrive(VirtualRealityTrain train, boolean right, SectionPosition headPosition) {
Section target = train.getTarget();
if (target != null) {
float stopPoint = target.getStopPointByDirection(right);
SectionPosition targetStopPosition = new SectionPosition(target, stopPoint);
Float distance2NextStation = CalculateService.calculateDistance(headPosition, targetStopPosition, right, false);
//距下一站的距离小于200视为即将到站
boolean old = train.isBeAbout2Arrive();
train.setBeAbout2Arrive(distance2NextStation != null && distance2NextStation < 200);
if (!Objects.equals(old, train.isBeAbout2Arrive())) {
return train.isBeAbout2Arrive();
}
}
return null;
}
public void addJobs(Simulation simulation) {
simulation.addJob(SimulationModule.ATP.name(), () -> this.run(simulation), SimulationConstants.ATP_LOOP_RATE);
}
public void addJobs(Simulation simulation) {
simulation.addJob(SimulationModule.ATP.name(), () -> this.run(simulation),
SimulationConstants.ATP_LOOP_RATE);
}
}