虚拟真实设备控制消息调整

车辆段调度角色调整
This commit is contained in:
walker-sheng 2021-09-14 17:09:15 +08:00
parent b68db75959
commit 5664917d65
35 changed files with 487 additions and 485 deletions

View File

@ -175,9 +175,11 @@ public class RoutingGenerator {
}
}
if (!finish) {
if (route.getDestination() != null) {
queryList.add(route.getDestination());
}
}
}
for (Signal next : queryList) {
queryAdjoinSections(next, rightDirectionList);
}

View File

@ -2,13 +2,11 @@ package club.joylink.rtss.simulation.cbtc.ATS.operation.service;
import club.joylink.rtss.simulation.cbtc.ATS.operation.vo.FaultParam;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.communication.vo.ControllableDevice;
import club.joylink.rtss.simulation.cbtc.communication.vo.PsdSwitch;
import club.joylink.rtss.simulation.cbtc.communication.vo.fault.DeviceFaultInfo;
import club.joylink.rtss.simulation.cbtc.data.map.MayOutOfOrderDevice;
import club.joylink.rtss.simulation.cbtc.data.map.Stand;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityScreenDoor;
import club.joylink.rtss.simulation.cbtc.event.SimulationDeviceControlEvent;
import club.joylink.rtss.simulation.cbtc.device.virtual.VirtualRealityDeviceService;
import club.joylink.rtss.simulation.cbtc.event.SimulationDeviceFaultOverEvent;
import club.joylink.rtss.simulation.cbtc.event.SimulationDeviceFaultSetEvent;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
@ -24,6 +22,8 @@ public class StandFaultService implements DeviceFaultService {
@Autowired
private ApplicationContext applicationContext;
@Autowired
private VirtualRealityDeviceService virtualRealityDeviceService;
@Override
public void setFault(Simulation simulation, MayOutOfOrderDevice device, FaultParam param) {
@ -35,15 +35,11 @@ public class StandFaultService implements DeviceFaultService {
VirtualRealityScreenDoor vrPsd = ((Stand) device).getPsd().getVirtualScreenDoor();
switch (fault) {
case PSD_CANNOT_BE_CLOSED:{
ControllableDevice ctrlMsg = new PsdSwitch(vrPsd, true);
SimulationDeviceControlEvent event = new SimulationDeviceControlEvent(this, simulation, ctrlMsg);
this.applicationContext.publishEvent(event);
this.virtualRealityDeviceService.control(simulation, vrPsd, VirtualRealityScreenDoor.Operation.K);
break;
}
case PSD_CANNOT_BE_OPENED:{
ControllableDevice ctrlMsg = new PsdSwitch(vrPsd, false);
SimulationDeviceControlEvent event = new SimulationDeviceControlEvent(this, simulation, ctrlMsg);
this.applicationContext.publishEvent(event);
this.virtualRealityDeviceService.control(simulation, vrPsd, VirtualRealityScreenDoor.Operation.G);
break;
}
}
@ -59,15 +55,11 @@ public class StandFaultService implements DeviceFaultService {
VirtualRealityScreenDoor vrPsd = ((Stand) device).getPsd().getVirtualScreenDoor();
switch (fault) {
case PSD_CANNOT_BE_CLOSED:{
ControllableDevice ctrlMsg = new PsdSwitch(vrPsd, !vrPsd.isSettingClose());
SimulationDeviceControlEvent event = new SimulationDeviceControlEvent(this, simulation, ctrlMsg);
this.applicationContext.publishEvent(event);
this.virtualRealityDeviceService.control(simulation, vrPsd, VirtualRealityScreenDoor.Operation.G);
break;
}
case PSD_CANNOT_BE_OPENED: {
ControllableDevice ctrlMsg = new PsdSwitch(vrPsd, vrPsd.isSettingOpen());
SimulationDeviceControlEvent event = new SimulationDeviceControlEvent(this, simulation, ctrlMsg);
this.applicationContext.publishEvent(event);
this.virtualRealityDeviceService.control(simulation, vrPsd, VirtualRealityScreenDoor.Operation.K);
break;
}
}

View File

@ -602,8 +602,8 @@ public class AtsTrainLoadService {
this.deviceStatusModifyTool.openRouteDirect(simulation, route);
// 进路设置为正常解锁
route.startNormalUnlock();
// 根据列车位置直接进路正常解锁
this.deviceStatusModifyTool.routeUnlockByEndSection(route, tailPosition.getSection());
// // 根据列车位置直接进路正常解锁
// this.deviceStatusModifyTool.routeUnlockByEndSection(route, tailPosition.getSection());
break;
}
}

View File

@ -3,7 +3,6 @@ package club.joylink.rtss.simulation.cbtc.ATS.service;
import club.joylink.rtss.simulation.cbtc.ATS.service.ars.AtsTriggerRouteService;
import club.joylink.rtss.simulation.cbtc.ATS.service.stage.AtsRealRunRecordService;
import club.joylink.rtss.simulation.cbtc.ATS.service.stage.AtsTrainStageHandler;
import club.joylink.rtss.simulation.cbtc.CI.CiApiService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
@ -41,8 +40,6 @@ public class AtsTrainMonitorService {
private AtsStandService atsStandService;
@Autowired
private OnboardAtpApiService onboardAtpApiService;
@Autowired
private CiApiService ciApiService;
/**
* 列车监控逻辑
@ -113,7 +110,6 @@ public class AtsTrainMonitorService {
// 停车点停车
this.trainParking(simulation, trainInfo, headSection.getStation(), headSection);
this.onboardAtpApiService.parkingInPlace(simulation, vrTrain, headSection);
this.ciApiService.handleTrainStopMessage(simulation, headSection);
}
}
}

View File

@ -1,7 +1,10 @@
package club.joylink.rtss.simulation.cbtc.CI;
import club.joylink.rtss.simulation.cbtc.Simulation;
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.Route;
import club.joylink.rtss.simulation.cbtc.data.map.Stand;
import club.joylink.rtss.simulation.cbtc.data.map.Station;
/**
* CI子系统接口
@ -255,13 +258,6 @@ public interface CiApiService {
void standHoldTrainCancelAll(Simulation simulation, String standCode);
/**
* 接收处理列车停稳信息
* @param simulation
* @param section
*/
void handleTrainStopMessage(Simulation simulation, Section section);
/**
* 办理引导
* @param simulation

View File

@ -370,11 +370,6 @@ public class CiApiServiceImpl2 implements CiApiService {
this.standService.cancelAllHoldTrain(simulation, stand);
}
@Override
public void handleTrainStopMessage(Simulation simulation, Section section) {
this.routeService.handleTrainStop(simulation, section);
}
/**
* 办理引导
*/

View File

@ -40,9 +40,12 @@ public class CiRouteService {
this.trainUnlockRoute(simulation, route);
}
}
Map<String, RouteOverlap> settingOverlapMap = repository.getSettingOverlapMap();
for (RouteOverlap overlap : settingOverlapMap.values()) {
this.overlapSettingProcess(simulation, overlap);
List<RouteOverlap> routeOverlapList = repository.getRouteOverlapList();
for (RouteOverlap routeOverlap : routeOverlapList) {
this.ciService.overlapMonitor(simulation, routeOverlap);
if (routeOverlap.isSetting()) {
this.overlapSettingProcess(simulation, routeOverlap);
}
}
}
@ -66,6 +69,11 @@ public class CiRouteService {
if (failMessage != null) {
return failMessage;
}
// 进路中道岔是否存在和监控中进路延续保护冲突
failMessage = monitorRouteOverlapConflictCheck(simulation, route);
if (failMessage != null) {
return failMessage;
}
// 进路内区段封锁/锁闭方向检查
List<Section> sectionList = route.getSectionList();
for (Section section : sectionList) {
@ -129,6 +137,23 @@ public class CiRouteService {
return failMessage;
}
private static Route.CheckFailMessage monitorRouteOverlapConflictCheck(Simulation simulation, Route route) {
SimulationDataRepository repository = simulation.getRepository();
List<Route> settingRoutes = repository.getSettingRoutes();
for (Route sr : settingRoutes) {
if (sr.isSettingOverlap() && !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(List<SwitchElement> switchList) {
if (switchList != null) {
for (SwitchElement switchElement : switchList) {
@ -449,7 +474,6 @@ public class CiRouteService {
boolean right = route.getStart().isRight();
// 区段是顺序的(否则会有问题)
boolean allUnlock = true;
boolean overlapRelock = true;
if (Objects.isNull(route.getUnlockedSection())) {
log.error(String.format("进路[%s(%s)]正常解锁异常", route.getName(), route.getCode()));
return;
@ -460,9 +484,6 @@ public class CiRouteService {
if (!Objects.equals(route.getUnlockedSection(), section)) {
continue;
}
if (route.isLastRouteSection(section)) {
overlapRelock = false;
}
Switch relSwitch = section.getRelSwitch();
if (section.isOccupied()) {
// 区段逻辑占用且有逻辑区段
@ -474,9 +495,10 @@ public class CiRouteService {
Collections.reverse(logicList);
}
for (Section logic : logicList) {
if (!logic.isOccupied()) {
if (!logic.isOccupied() && logic.isRouteLockOn(right)) {
logic.routeUnlocking(route);
} else {
logic.overlapUnlocking();
} else if(logic.isOccupied()) {
break;
}
}
@ -490,6 +512,7 @@ public class CiRouteService {
section.getParent().routeUnlocking(route);
}
relSwitch.routeUnlock();
relSwitch.overlapUnLock();
// 侧防解锁
route.unlockRouteFlsOfSwitch(relSwitch);
//检查道岔的联动道岔和计轴关联道岔是否可以解锁
@ -504,11 +527,13 @@ public class CiRouteService {
if (relSwitch.isLinkedSwitch(aSwitch) || relSwitch.isBConnectTo(aSwitch)) {
if (!aSwitch.getA().isRouteLock()) {
aSwitch.routeUnlock();
aSwitch.overlapUnLock();
}
}
}
} else {
section.routeUnlocking(route);
section.overlapUnlocking();
}
log.debug(section.debugStr() + "因正常解锁解锁");
}
@ -543,7 +568,6 @@ public class CiRouteService {
}
LocalDateTime systemTime = simulation.getSystemTime();
overlap.startSetting(systemTime);
simulation.getRepository().addSettingOverlap(overlap);
}
/**
@ -583,6 +607,8 @@ public class CiRouteService {
// 道岔是否转换到位置
if (onPos) {
this.checkAndLockOverlap(simulation, overlap);
}
if (this.ciService.interlockCheck(simulation, overlap)) {
overlap.settingFinish();
log.debug(String.format("进路延续保护[%s]办理成功", overlap.debugStr()));
}
@ -609,34 +635,6 @@ public class CiRouteService {
}
}
public void overlapUnlock(Simulation simulation, RouteOverlap overlap) {
}
/**
* 处理列车停稳
* @param simulation
* @param section
*/
public void handleTrainStop(Simulation simulation, Section section) {
// 进路最后一个区段通信车停车进路延续保护立即解锁
if (!section.isRouteLock())
return;
List<RouteOverlap> overlapList = simulation.getRepository()
.getListByType(MapElement.DeviceType.OVERLAP, RouteOverlap.class);
for (RouteOverlap routeOverlap : overlapList) {
if (routeOverlap.allSectionsOl() &&
section.isRouteLockOn(routeOverlap.isRight()) && routeOverlap.isRouteLastSection(section)) {
// 是此延续保护的解锁区段立即解锁
routeOverlap.releaseImmediately();
log.debug("收到列车停稳消息,[{}}]延续保护[{}}],触发区段[{}}]立即解锁",
routeOverlap.isRight() ? "右向" : "左向", routeOverlap.getName(),
routeOverlap.getSection().debugStr());
break;
}
}
}
public void routeReopen(Simulation simulation, Route route) {
// 检查信号开放条件,开信号
this.ciService.interlockMonitor(simulation, route);

View File

@ -4,7 +4,6 @@ import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.constant.SignalAspect;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
import club.joylink.rtss.simulation.cbtc.data.map.*;
import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -28,28 +27,63 @@ public class CiService {
if (route.isOpenMain()) {
// 进路首区段列车占用进路开始解锁
Section firstLogicSection = route.getFirstLogicSection();
if (firstLogicSection.isOccupied()) {
boolean trainOccupy = false;
SimulationDataRepository repository = simulation.getRepository();
for (TrainInfo trainInfo : repository.getSuperviseTrainList()) {
if (trainInfo.hasPositionAndDirection()) {
Section section = repository.getByCode(trainInfo.getPhysicalSection(), Section.class);
if (section.isSamePhysical(firstLogicSection.getCode())) {
trainOccupy = true;
break;
}
}
}
if (trainOccupy) {
if (repository.isTrainHeadOccupy(firstLogicSection)) {
route.startNormalUnlock();
}
}
}
if (route.isLock()) {
int level = this.checkRouteLevel(simulation, route);
route.getStart().setLevel(level);
}
if (route.isOpenMain()) {
SignalAspect aspect = this.getRouteCurrentMaxAspect(route);
if (!aspect.equals(route.getStart().getAspect())) {
this.signalControlService.tryControlSignalAspectAccordingLevel(simulation, route.getStart(), aspect);
if (!aspect.equals(route.getStart().getAspect())) {//与联锁显示不同控制显示禁止信号
this.signalControlService.tryControlSignalAspectAccordingLevel(simulation,
route.getStart(), route.getStart().getSignalModel().getDefaultAspect());
}
}
// 进路延续保护办理判断
if (route.isSettingOverlap()) {
this.checkAndTrySettingOverlap(simulation, route.getOverlap());
}
}
private void checkAndTrySettingOverlap(Simulation simulation, RouteOverlap overlap) {
if (!overlap.isSetting() && !overlap.isLock() && !overlap.isForbidden()) {
if (overlap.getSection().isRouteLock()) {
overlap.startSetting(simulation.getSystemTime());
}
}
}
public void overlapMonitor(Simulation simulation, RouteOverlap overlap) {
MapConfig config = simulation.getRepository().getConfig();
if (config.isOverlapSettingByTrigger()) {
this.checkAndTrySettingOverlap(simulation, overlap);
}
if (overlap.isForbidden()) {
if (!overlap.getSection().isOccupied()) {
overlap.allowLock();
}
}
if (overlap.isReleasing()) {
overlap.releaseProgress();
}
if (overlap.isLock()) {
if (simulation.getRepository().isTrainParking(overlap.getSection())) {
log.debug("列车停稳,延续保护[{}}],触发区段[{}}]立即解锁",
overlap.getName(),
overlap.getSection().debugStr());
overlap.releaseImmediately();
}
// 进路首区段列车占用进路开始解锁
if (!overlap.isReleasing() && simulation.getRepository().isTrainHeadOccupy(overlap.getSection())) {
overlap.startReleasing();
}
if (!this.interlockCheck(simulation, overlap)) {
overlap.setLock(false);
}
}
}
@ -60,6 +94,9 @@ public class CiService {
* @return
*/
private SignalAspect getRouteCurrentMaxAspect(Route route) {
if (route.isNormalUnlock()) {
return route.getStart().getSignalModel().getDefaultAspect();
}
return route.getStart().getMaxAspectByLevel(route.getAspect());
}
@ -73,6 +110,17 @@ public class CiService {
public boolean interlockCheck(Simulation simulation, RouteOverlap overlap) {
if (overlap != null) {
SectionPath sectionPath = overlap.selectPath();
List<Section> logicList = sectionPath.getLogicList();
if (!CollectionUtils.isEmpty(logicList)) {
for (Section section : logicList) {
if (!section.isOverlapLockOn(overlap.isRight())) {
return false;
}
if (section.isOccupied()) {
return false;
}
}
} else {
List<Section> sectionList = sectionPath.getSectionList();
for (Section section : sectionList) {
if (!section.isOverlapLockOn(overlap.isRight())) {
@ -82,6 +130,7 @@ public class CiService {
return false;
}
}
}
List<SwitchElement> switchList = sectionPath.getSwitchList();
for (SwitchElement switchElement : switchList) {
if (!switchElement.isOnPosition()) {
@ -134,17 +183,17 @@ public class CiService {
List<Section> sectionList = route.getSectionList();
for (Section section : sectionList) {
if (!section.isRouteLock()) {
log.info("进路{}连锁条件检查失败:区段{}未锁闭", route.debugStr(),
log.debug("进路{}连锁条件检查失败:区段{}未锁闭", route.debugStr(),
section.debugStr());
return level;
}
if (!section.isRouteLockOn(right)) {
log.info("进路{}连锁条件检查失败:区段{}锁闭方向错误", route.debugStr(),
log.debug("进路{}连锁条件检查失败:区段{}锁闭方向错误", route.debugStr(),
section.debugStr());
return level;
}
if (section.isNoStatus()) {
log.info("进路{}连锁条件检查失败:区段{}连锁无状态", route.debugStr(),
log.debug("进路{}连锁条件检查失败:区段{}连锁无状态", route.debugStr(),
section.debugStr());
return level;
}
@ -152,7 +201,7 @@ public class CiService {
// 道岔位置一致检查
for (SwitchElement element : route.getSwitchList()) {
if (!element.isOnPosition()) {
log.info("进路{}连锁条件检查失败:道岔{}位置{}",
log.debug("进路{}连锁条件检查失败:道岔{}位置{}",
route.debugStr(),
element.getASwitch().debugStr(), element.getASwitch().getPos());
return level;
@ -167,7 +216,7 @@ public class CiService {
for (RouteFls.FlsElement flsElement : level1List) {
SwitchElement pSwitch = flsElement.getPSwitch();
if (pSwitch != null && !pSwitch.isOnPosition()) {
log.info("进路{}连锁条件检查失败:侧防道岔{}位置不对",
log.debug("进路{}连锁条件检查失败:侧防道岔{}位置不对",
route.debugStr(), pSwitch.getASwitch().debugStr());
return level;
} else {
@ -191,14 +240,14 @@ public class CiService {
RouteOverrun overrun = route.findOverrunBySwitch(element.getASwitch());
if (overrun != null) {
if (overrun.getSection() != null && overrun.getSection().hasNctOccupy()) {
log.info("进路{}连锁条件检查失败:超限区段{}被占用",
log.debug("进路{}连锁条件检查失败:超限区段{}被占用",
route.debugStr(), overrun.getCode());
return level;
}
SwitchElement overrunSE = overrun.getSwitchElement();
if (overrunSE != null && overrunSE.isOnPosition()) {
if (overrunSE.getASwitch().getAllSections().stream().anyMatch(Section::hasNctOccupy)) {
log.info("进路{}连锁条件检查失败:超限区段{}被占用",
log.debug("进路{}连锁条件检查失败:超限区段{}被占用",
route.debugStr(), overrun.getCode());
return level;
}
@ -212,7 +261,7 @@ public class CiService {
if (!CollectionUtils.isEmpty(route.getEspList())) {
for (ESP esp : route.getEspList()) {
if (esp.isEffective()) {
log.info("进路{}连锁条件检查失败:站台紧急停车按钮{}按下", route.debugStr(),
log.debug("进路{}连锁条件检查失败:站台紧急停车按钮{}按下", route.debugStr(),
esp.debugStr());
return level;
}
@ -221,19 +270,19 @@ public class CiService {
// 区段占用检查
for (Section section : sectionList) {
if (section.isOccupied()) {
log.info("进路{}连锁条件检查:区段{}占用",
log.debug("进路{}连锁条件检查:区段{}占用",
route.debugStr(), section.debugStr());
return level;
}
if (section.getSpeedUpLimit() != -1) {
log.info("进路{}连锁条件检查:区段{}限速",
log.debug("进路{}连锁条件检查:区段{}限速",
route.debugStr(), section.debugStr());
return level;
}
if (!CollectionUtils.isEmpty(section.getLogicList())) {
for (Section logic : section.getLogicList()) {
if (logic.getSpeedUpLimit() != -1) {
log.info("进路{}连锁条件检查失败:区段{}限速",
log.debug("进路{}连锁条件检查失败:区段{}限速",
route.debugStr(), logic.debugStr());
return level;
}
@ -255,7 +304,7 @@ public class CiService {
if (!CollectionUtils.isEmpty(route.getStandHoldList())) {
for (Stand stand : route.getStandHoldList()) {
if (stand.isHoldTrain()) {
log.info("进路[{}]连锁条件检查:站台[{}({})]扣车",
log.debug("进路[{}]连锁条件检查:站台[{}({})]扣车",
route.debugStr(),
stand.getName(), stand.getCode());
return level;
@ -264,7 +313,7 @@ public class CiService {
}
// 延续保护
if (!this.interlockCheck(simulation, route.getOverlap())) {
log.info("进路[{}]连锁条件检查失败: 延续保护未锁闭", route.debugStr());
log.debug("进路[{}]连锁条件检查: 延续保护未锁闭", route.debugStr());
return level;
}
return Signal.LEVEL_Main; // 主信号级

View File

@ -1,20 +1,17 @@
package club.joylink.rtss.simulation.cbtc.CI.service;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.communication.vo.ControllableDevice;
import club.joylink.rtss.simulation.cbtc.communication.vo.PsdSwitch;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityScreenDoor;
import club.joylink.rtss.simulation.cbtc.event.SimulationDeviceControlEvent;
import club.joylink.rtss.simulation.cbtc.device.virtual.VirtualRealityDeviceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class VrPsdService {
@Autowired
private ApplicationContext applicationContext;
private VirtualRealityDeviceService virtualRealityDeviceService;
/**
* 控制室外屏蔽门开关
@ -38,10 +35,8 @@ public class VrPsdService {
break;
}
}
vrPsd.startSetting(open);
ControllableDevice ctrlMsg = new PsdSwitch(vrPsd, open);
SimulationDeviceControlEvent event = new SimulationDeviceControlEvent(this, simulation, ctrlMsg);
this.applicationContext.publishEvent(event);
this.virtualRealityDeviceService.control(simulation, vrPsd,
open ? VirtualRealityScreenDoor.Operation.K : VirtualRealityScreenDoor.Operation.G);
}
public enum CommandSource{

View File

@ -6,18 +6,11 @@ import club.joylink.rtss.simulation.cbtc.data.CalculateService;
import club.joylink.rtss.simulation.cbtc.data.map.*;
import club.joylink.rtss.simulation.cbtc.data.support.RoutePath;
import club.joylink.rtss.simulation.cbtc.data.support.RouteUnit;
import club.joylink.rtss.vo.map.*;
import club.joylink.rtss.vo.map.logic.MapAutoReentryVO;
import club.joylink.rtss.vo.map.logic.MapAutoSignalNewVO;
import club.joylink.rtss.vo.map.logic.MapDestinationCodeDefinitionVO;
import club.joylink.rtss.vo.map.logic.MapOverlapVO;
import club.joylink.rtss.vo.map.logic.MapRouteFlankProtectionNewVO;
import club.joylink.rtss.vo.map.logic.MapRouteNewVO;
import club.joylink.rtss.vo.map.logic.MapRouteOverrunVO;
import club.joylink.rtss.vo.map.logic.MapRoutingDataVO;
import club.joylink.rtss.vo.map.logic.MapSignalApproachSectionVO;
import club.joylink.rtss.vo.map.logic.MapStationParkingTimeVO;
import club.joylink.rtss.vo.map.logic.MapStationRunLevelVO;
import club.joylink.rtss.vo.map.MapCISwitchVO;
import club.joylink.rtss.vo.map.MapLogicDataNewVO;
import club.joylink.rtss.vo.map.MapRoutingSectionNewVO;
import club.joylink.rtss.vo.map.MapSectionPathVO;
import club.joylink.rtss.vo.map.logic.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
@ -298,7 +291,7 @@ public class InterlockBuilder2 {
startSignal.getRouteList().add(route);
}
Signal endSignal = (Signal) elementMap.get(mapRouteVO.getEndSignalCode());
if (Objects.isNull(endSignal)) {
if (Objects.isNull(endSignal) && station != null && !station.isDepot()) {
errMsgList.add(String.format("进路[%s(%s)]终端信号机未设置或不存在", route.getName(), route.getCode()));
} else {
route.setDestination(endSignal);

View File

@ -12,9 +12,7 @@ import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
import club.joylink.rtss.simulation.cbtc.data.map.Stand;
import club.joylink.rtss.simulation.cbtc.data.status.TrainStatus;
import club.joylink.rtss.simulation.cbtc.data.vo.TdtStatusVO;
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.VirtualRealitySwitch;
import club.joylink.rtss.simulation.cbtc.data.vr.ControllableVrDevice;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import club.joylink.rtss.simulation.cbtc.event.*;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
@ -154,24 +152,30 @@ public class Joylink3DMessageService {
*/
private List<ControllableDevice> collectTrainInitData(VirtualRealityTrain train) {
List<ControllableDevice> list = new ArrayList<>();
boolean door1Open;
if (train.getDoor1().isTurning()) {
door1Open = train.getDoor1().isCommandOpen();
} else if (train.getDoor1().isOpen()) {
door1Open = true;
} else {
door1Open = false;
if (train.getDoor1().getCommand() != null) {
list.add(new TrainDoorSwitch(train, train.getDoor1()));
}
list.add(new TrainDoorSwitch(train, train.getDoor1(), door1Open));
boolean door2Open;
if (train.getDoor2().isTurning()) {
door2Open = train.getDoor2().isCommandOpen();
} else if (train.getDoor2().isOpen()) {
door2Open = true;
} else {
door2Open = false;
if (train.getDoor2().getCommand() != null) {
list.add(new TrainDoorSwitch(train, train.getDoor2()));
}
list.add(new TrainDoorSwitch(train, train.getDoor2(), door2Open));
// boolean door1Open;
// if (train.getDoor1().isTurning()) {
// door1Open = train.getDoor1().isCommandOpen();
// } else if (train.getDoor1().isOpen()) {
// door1Open = true;
// } else {
// door1Open = false;
// }
// list.add(new TrainDoorSwitch(train, train.getDoor1(), door1Open));
// boolean door2Open;
// if (train.getDoor2().isTurning()) {
// door2Open = train.getDoor2().isCommandOpen();
// } else if (train.getDoor2().isOpen()) {
// door2Open = true;
// } else {
// door2Open = false;
// }
// list.add(new TrainDoorSwitch(train, train.getDoor2(), door2Open));
list.add(new TrainLoadDestroy(train));
return list;
}
@ -217,37 +221,40 @@ public class Joylink3DMessageService {
* @return
*/
private void collectAndSend3DInitDeviceList(Simulation simulation, Collection<String> userList) {
List<ControllableDevice> initDeviceList = new ArrayList<>();
SimulationDataRepository repository = simulation.getRepository();
// 信号机
List<VirtualRealitySignal> vrSignalList = repository.getVrListByType(MapElement.DeviceType.SIGNAL, VirtualRealitySignal.class);
vrSignalList.forEach(signal -> initDeviceList.add(new SignalLight(signal)));
// 道岔
List<VirtualRealitySwitch> vrSwitchList = repository.getVrListByType(MapElement.DeviceType.SWITCH, VirtualRealitySwitch.class);
vrSwitchList.forEach(vrSwitch -> {
boolean normal;
if (vrSwitch.isTurning()) {
normal = vrSwitch.getCommand().equals(VirtualRealitySwitch.Operation.NP);
} else if (vrSwitch.isPosN()) {
normal = true;
} else {
normal = false;
}
initDeviceList.add(new SwitchTurn(vrSwitch, normal));
});
// 屏蔽门
List<VirtualRealityScreenDoor> vrPsdList = repository.getVrListByType(MapElement.DeviceType.PSD, VirtualRealityScreenDoor.class);
vrPsdList.forEach(vrPsd -> {
boolean open;
if (vrPsd.isTurning()) {
open = vrPsd.getCommand().equals(VirtualRealityScreenDoor.Operation.K);
} else if (vrPsd.isClose()) {
open = false;
} else {
open = true;
}
initDeviceList.add(new PsdSwitch(vrPsd, open));
});
List<ControllableDevice> initDeviceList = repository.getAllControllableVrDevice().stream()
.filter(vrDevice -> vrDevice.getCommand() != null)
.map(vrDevice -> new ControllableDevice(vrDevice))
.collect(Collectors.toList());
// // 信号机
// List<VirtualRealitySignal> vrSignalList = repository.getVrListByType(MapElement.DeviceType.SIGNAL, VirtualRealitySignal.class);
// vrSignalList.forEach(signal -> initDeviceList.add(new SignalLight(signal)));
// // 道岔
// List<VirtualRealitySwitch> vrSwitchList = repository.getVrListByType(MapElement.DeviceType.SWITCH, VirtualRealitySwitch.class);
// vrSwitchList.forEach(vrSwitch -> {
// boolean normal;
// if (vrSwitch.isTurning()) {
// normal = vrSwitch.getCommand().equals(VirtualRealitySwitch.Operation.NP);
// } else if (vrSwitch.isPosN()) {
// normal = true;
// } else {
// normal = false;
// }
// initDeviceList.add(new SwitchTurn(vrSwitch, normal));
// });
// // 屏蔽门
// List<VirtualRealityScreenDoor> vrPsdList = repository.getVrListByType(MapElement.DeviceType.PSD, VirtualRealityScreenDoor.class);
// vrPsdList.forEach(vrPsd -> {
// boolean open;
// if (vrPsd.isTurning()) {
// open = vrPsd.getCommand().equals(VirtualRealityScreenDoor.Operation.K);
// } else if (vrPsd.isClose()) {
// open = false;
// } else {
// open = true;
// }
// initDeviceList.add(new PsdSwitch(vrPsd, open));
// });
// 列车
List<VirtualRealityTrain> onlineTrainList = repository.getOnlineTrainList();
onlineTrainList.forEach(train -> initDeviceList.addAll(this.collectTrainInitData(train)));
@ -272,10 +279,17 @@ public class Joylink3DMessageService {
@EventListener
public void handleDeviceControlEvent(SimulationDeviceControlEvent event) {
Simulation simulation = event.getSimulation();
ControllableDevice ctrlMsg = event.getCtrlMsg();
ControllableVrDevice device = event.getDevice();
ControllableDevice cd;
if (device instanceof VirtualRealityTrain.Door) {
VirtualRealityTrain.Door door = (VirtualRealityTrain.Door) device;
cd = new TrainDoorSwitch(door.getTrain(), door);
} else {
cd = new ControllableDevice(device);
}
SocketMessageVO message = SocketMessageFactory
.build(WebSocketMessageType.DeviceCtrl_3D,
simulation.getId(), ctrlMsg);
simulation.getId(), cd);
this.stompMessageService.sendToUser(simulation.getSimulationUserIds(), message);
}

View File

@ -1,10 +1,11 @@
package club.joylink.rtss.simulation.cbtc.communication.vo;
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
import club.joylink.rtss.simulation.cbtc.data.vr.ControllableVrDevice;
import lombok.Getter;
@Getter
public abstract class ControllableDevice {
public class ControllableDevice {
/** 设备code */
private String code;
@ -12,8 +13,16 @@ public abstract class ControllableDevice {
/** 设备类型 */
private MapElement.DeviceType type;
private String command;
protected ControllableDevice(String code, MapElement.DeviceType type) {
this.code = code;
this.type = type;
}
public ControllableDevice(ControllableVrDevice vrDevice) {
this.code = vrDevice.getCode();
this.type = vrDevice.getDeviceType();
this.command = vrDevice.getCommand().toString();
}
}

View File

@ -1,22 +1,22 @@
package club.joylink.rtss.simulation.cbtc.communication.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityScreenDoor;
import club.joylink.rtss.util.jsonSerialize.Boolean2NumSerializer;
import lombok.Getter;
/**
* 站台屏蔽门开/关门控制消息
*/
@Getter
public class PsdSwitch extends ControllableDevice {
/** true-开门 false-关门 */
@JsonSerialize(using = Boolean2NumSerializer.class)
private boolean open;
public PsdSwitch(VirtualRealityScreenDoor psd, boolean open) {
super(psd.getCode(), psd.getDeviceType());
this.open = open;
}
}
//package club.joylink.rtss.simulation.cbtc.communication.vo;
//
//import com.fasterxml.jackson.databind.annotation.JsonSerialize;
//import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityScreenDoor;
//import club.joylink.rtss.util.jsonSerialize.Boolean2NumSerializer;
//import lombok.Getter;
//
///**
// * 站台屏蔽门开/关门控制消息
// */
//@Getter
//public class PsdSwitch extends ControllableDevice {
//
// /** true-开门 false-关门 */
// @JsonSerialize(using = Boolean2NumSerializer.class)
// private boolean open;
//
// public PsdSwitch(VirtualRealityScreenDoor psd, boolean open) {
// super(psd.getCode(), psd.getDeviceType());
// this.open = open;
// }
//}

View File

@ -1,25 +1,25 @@
package club.joylink.rtss.simulation.cbtc.communication.vo;
import club.joylink.rtss.simulation.cbtc.constant.SignalAspect;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySignal;
import lombok.Getter;
/**
* 信号机点灯状态
*/
@Getter
public class SignalLight extends ControllableDevice {
/**
* 信号显示
*/
private SignalAspect aspect;
public SignalLight(VirtualRealitySignal signal) {
super(signal.getCode(), signal.getDeviceType());
if (signal.getCommand() != null) {
this.aspect = signal.getCommand();
} else {
this.aspect = signal.getAspect();
}
}
}
//package club.joylink.rtss.simulation.cbtc.communication.vo;
//
//import club.joylink.rtss.simulation.cbtc.constant.SignalAspect;
//import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySignal;
//import lombok.Getter;
//
///**
// * 信号机点灯状态
// */
//@Getter
//public class SignalLight extends ControllableDevice {
// /**
// * 信号显示
// */
// private SignalAspect aspect;
//
// public SignalLight(VirtualRealitySignal signal) {
// super(signal.getCode(), signal.getDeviceType());
// if (signal.getCommand() != null) {
// this.aspect = signal.getCommand();
// } else {
// this.aspect = signal.getAspect();
// }
// }
//}

View File

@ -1,22 +1,22 @@
package club.joylink.rtss.simulation.cbtc.communication.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySwitch;
import club.joylink.rtss.util.jsonSerialize.Boolean2NumSerializer;
import lombok.Getter;
/**
* 道岔开始转动消息
*/
@Getter
public class SwitchTurn extends ControllableDevice {
/** true-转到定位 false-转到反位 */
@JsonSerialize(using = Boolean2NumSerializer.class)
private boolean normal;
public SwitchTurn(VirtualRealitySwitch vrSwitch, boolean normal) {
super(vrSwitch.getCode(), vrSwitch.getDeviceType());
this.normal = normal;
}
}
//package club.joylink.rtss.simulation.cbtc.communication.vo;
//
//import com.fasterxml.jackson.databind.annotation.JsonSerialize;
//import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySwitch;
//import club.joylink.rtss.util.jsonSerialize.Boolean2NumSerializer;
//import lombok.Getter;
//
///**
// * 道岔开始转动消息
// */
//@Getter
//public class SwitchTurn extends ControllableDevice {
//
// /** true-转到定位 false-转到反位 */
// @JsonSerialize(using = Boolean2NumSerializer.class)
// private boolean normal;
//
// public SwitchTurn(VirtualRealitySwitch vrSwitch, boolean normal) {
// super(vrSwitch.getCode(), vrSwitch.getDeviceType());
// this.normal = normal;
// }
//}

View File

@ -1,23 +1,15 @@
package club.joylink.rtss.simulation.cbtc.communication.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import club.joylink.rtss.util.jsonSerialize.Boolean2NumSerializer;
import lombok.Getter;
@Getter
public class TrainDoorSwitch extends ControllableDevice {
private String doorCode;
private String trainCode;
/** true-开门 false-关门 */
@JsonSerialize(using = Boolean2NumSerializer.class)
private boolean open;
public TrainDoorSwitch(VirtualRealityTrain train, VirtualRealityTrain.Door door, boolean open) {
super(train.getCode(), MapElement.DeviceType.TRAIN_DOOR);
this.doorCode = door.getCode();
this.open = open;
public TrainDoorSwitch(VirtualRealityTrain train, VirtualRealityTrain.Door door) {
super(door);
this.trainCode = train.getCode();
}
}

View File

@ -182,12 +182,6 @@ public class SimulationDataRepository {
* val-办理中的和已经办理好的进路
*/
private Map<String, Route> settingRouteMap = new ConcurrentHashMap<>();
/**
* 办理的延续保护map
* key-延续保护id
* val-延续保护对象
*/
private Map<String, RouteOverlap> settingOverlapMap = new ConcurrentHashMap<>();
/**
* 使用的列车map
@ -997,10 +991,6 @@ public class SimulationDataRepository {
return this.settingRouteMap.containsKey(route.getCode());
}
public void addSettingOverlap(RouteOverlap overlap) {
this.settingOverlapMap.put(overlap.getCode(), overlap);
}
/**
* 是否有其他列车已经触发了此信号机为始端的进路
*
@ -1358,11 +1348,39 @@ public class SimulationDataRepository {
return this.runLevelMap.get(key);
}
public List<ControllableVrDevice> getAllControllableCrDevice() {
public List<ControllableVrDevice> getAllControllableVrDevice() {
List<ControllableVrDevice> controllableList = this.vrDeviceMap.values().stream()
.filter(vrDevice -> vrDevice instanceof ControllableVrDevice)
.map(vrDevice -> ((ControllableVrDevice) vrDevice))
.collect(Collectors.toList());
return controllableList;
}
public boolean isTrainHeadOccupy(Section section) {
if (section.isOccupied()) {
for (TrainInfo trainInfo : this.getSuperviseTrainList()) {
if (trainInfo.hasPositionAndDirection()) {
Section head = this.getByCode(trainInfo.getPhysicalSection(), Section.class);
if (head.isSameAxle(section.getCode())) {
return true;
}
}
}
}
return false;
}
public boolean isTrainParking(Section section) {
if (section.isOccupied()) {
for (TrainInfo trainInfo : this.getSuperviseTrainList()) {
if (trainInfo.hasPositionAndDirection() && trainInfo.isParking()) {
Section head = this.getByCode(trainInfo.getPhysicalSection(), Section.class);
if (head.isSameAxle(section.getCode())) {
return true;
}
}
}
}
return false;
}
}

View File

@ -81,6 +81,7 @@ public class Route extends MapNamedElement {
private List<Stand> standHoldList;
/** CTC模式下需要办理延续保护 */
@Deprecated
private boolean setOverlapInCtc = true;
/** 进路延续保护 */
@ -170,7 +171,7 @@ public class Route extends MapNamedElement {
* @return
*/
public boolean isOpenMain() {
return this.isLock() && this.aspect.equals(this.start.getAspect());
return this.aspect.equals(this.start.getAspect());
}
public void setAtsControl(boolean atsControl) {
@ -652,7 +653,7 @@ public class Route extends MapNamedElement {
public boolean isSettingOverlap() {
if (this.overlap != null) {
if (this.getStart().isCbtcMode()) {
if (this.getStart().isCbtcMode() && this.getDestination().isCbtcMode()) {
return this.getDestination().isCtcSetOverlap();
}
return true;
@ -664,6 +665,15 @@ public class Route extends MapNamedElement {
return this.delayUnlockDevice != null;
}
public boolean isConflictSwitch(SwitchElement switchElement) {
for (SwitchElement element : this.switchList) {
if (element.isConflict(switchElement)) {
return true;
}
}
return false;
}
/**
* 进路检查失败原因
*/

View File

@ -70,7 +70,7 @@ public class RouteOverlap extends MapNamedElement {
this.remainTime = 0;
}
public synchronized void startSetting(LocalDateTime systemTime) {
public void startSetting(LocalDateTime systemTime) {
this.setLock(false);
this.settingStartTime = systemTime;
this.requisition = false;

View File

@ -165,4 +165,12 @@ public class SectionPath {
public boolean containSwitch(Switch aSwitch) {
return this.switchList.stream().anyMatch(se -> Objects.equals(se.getASwitch(), aSwitch));
}
public Section getFirstSection() {
if (!CollectionUtils.isEmpty(this.getLogicList())) {
return this.getLogicList().get(0);
} else {
return this.getSectionList().get(0);
}
}
}

View File

@ -247,6 +247,9 @@ public class Switch extends DelayUnlockDevice {
}
public void overlapUnLock() {
this.a.overlapUnlocking();
this.b.overlapUnlocking();
this.c.overlapUnlocking();
this.overlapLock = false;
this.checkAndResetUsePosition();
}

View File

@ -40,4 +40,8 @@ public class SwitchElement {
// return this.aSwitch.isOnPosition(this.isNormal());
return this.aSwitch.getPos().equals(SwitchIndication.of(this.isNormal()));
}
public boolean isConflict(SwitchElement switchElement) {
return this.getASwitch().equals(switchElement.getASwitch()) && this.isNormal() != switchElement.isNormal();
}
}

View File

@ -0,0 +1,32 @@
package club.joylink.rtss.simulation.cbtc.data.storage.vr;
import club.joylink.rtss.simulation.cbtc.data.vr.ControllableVrDevice;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityDevice;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor
public abstract class StorageControllableVrDevice<C> extends StorageVirtualRealityDeviceStatus {
/**
* 控制指令
*/
private C command;
/**
* 剩余时间
*/
private int remain;
public StorageControllableVrDevice(VirtualRealityDevice device) {
super(device);
}
public void saveFrom(ControllableVrDevice device) {
this.command = (C) device.getCommand();
this.remain = device.getRemain();
}
public void recoverTo(ControllableVrDevice device) {
device.recover(this.command, this.remain);
}
}

View File

@ -1,10 +1,12 @@
package club.joylink.rtss.simulation.cbtc.data.storage.vr;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityDevice;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import club.joylink.rtss.util.jsonSerialize.Boolean2NumDeserializer;
import club.joylink.rtss.util.jsonSerialize.Boolean2NumSerializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -14,7 +16,7 @@ import java.util.Objects;
@Getter
@Setter
@NoArgsConstructor
public class StorageTrainDoor {
public class StorageTrainDoor extends StorageControllableVrDevice<VirtualRealityTrain.Door.Operation> {
private String code;
@JsonSerialize(using = Boolean2NumSerializer.class)
@ -25,30 +27,13 @@ public class StorageTrainDoor {
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean lock;
/** 是否开/关门过程中 */
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean turning;
/**
* 命令true-开门命令false-关门命令
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean commandOpen;
/**
* 过程剩余时间
*/
private float remainTime;
public StorageTrainDoor(VirtualRealityTrain.Door door) {
this.code = door.getCode();
this.close = door.isClose();
this.lock = door.isLock();
this.turning = door.isTurning();
this.commandOpen = door.isCommandOpen();
this.remainTime = door.getRemainTime();
if (door.isTurning()) {
this.saveFrom(door);
}
}
public void recover2Simulation(VirtualRealityTrain.Door door) {
@ -58,14 +43,13 @@ public class StorageTrainDoor {
if (Objects.nonNull(this.lock)) {
door.setLock(lock);
}
if (Objects.nonNull(this.turning)) {
door.setTurning(turning);
}
if (Objects.nonNull(this.commandOpen)) {
door.setCommandOpen(commandOpen);
}
if (Objects.nonNull(this.remainTime)) {
door.setRemainTime(remainTime);
if (this.getRemain() > 0) {
this.recoverTo(door);
}
}
@Override
public void recover2Simulation(VirtualRealityDevice vrDevice, SimulationDataRepository repository) {
}
}

View File

@ -14,7 +14,7 @@ import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class StorageVirtualRealityScreenDoor extends StorageVirtualRealityDeviceStatus {
public class StorageVirtualRealityScreenDoor extends StorageControllableVrDevice<VirtualRealityScreenDoor.Operation> {
/**
* 是否关闭
@ -41,33 +41,6 @@ public class StorageVirtualRealityScreenDoor extends StorageVirtualRealityDevice
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean interlockRelease;
/**
* 控制指令
*/
private VirtualRealityScreenDoor.Operation command;
/**
* 剩余时间
*/
private int remain;
/**
* 是否开门/关门过程
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean setting;
/**
* 开门/关门剩余时间
*/
private Float remainTime;
/**
* /关门指令true:开门指令false:关门指令
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean commandOpen;
private VirtualRealityScreenDoor.Fault fault;
public StorageVirtualRealityScreenDoor(VirtualRealityScreenDoor door) {
@ -105,8 +78,7 @@ public class StorageVirtualRealityScreenDoor extends StorageVirtualRealityDevice
}
if (door.isTurning()) {
change = true;
screenDoor.setCommand(door.getCommand());
screenDoor.setRemain(door.getRemain());
screenDoor.saveFrom(door);
}
if (door.getFault() != null) {
change = true;
@ -126,8 +98,8 @@ public class StorageVirtualRealityScreenDoor extends StorageVirtualRealityDevice
door.setOpen2End(open2End != null ? open2End : false);
door.setLock(lock != null ? lock : true);
door.setInterlockRelease(interlockRelease != null ? interlockRelease : false);
if (remain > 0) {
door.recover(this.command, this.remain);
if (this.getRemain() > 0) {
this.recoverTo(door);
}
door.setFault(fault);
}

View File

@ -11,17 +11,9 @@ import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class StorageVirtualRealitySignal extends StorageVirtualRealityDeviceStatus {
public class StorageVirtualRealitySignal extends StorageControllableVrDevice<SignalAspect> {
private SignalAspect aspect;
/**
* 控制指令
*/
private SignalAspect command;
/**
* 剩余时间
*/
private int remain;
private VirtualRealitySignal.Fault fault;
@ -38,8 +30,7 @@ public class StorageVirtualRealitySignal extends StorageVirtualRealityDeviceStat
}
if (signal.isTurning()) {
change = true;
storageSignal.setCommand(signal.getCommand());
storageSignal.setRemain(signal.getRemain());
storageSignal.saveFrom(signal);
}
if (signal.getFault() != null) {
change = true;
@ -57,8 +48,8 @@ public class StorageVirtualRealitySignal extends StorageVirtualRealityDeviceStat
if (this.aspect != null) {
signal.setAspect(this.aspect);
}
if (this.remain > 0) {
signal.recover(this.command, this.remain);
if (this.getRemain() > 0) {
this.recoverTo(signal);
}
signal.setFault(fault);
}

View File

@ -11,16 +11,8 @@ import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class StorageVirtualRealitySwitch extends StorageVirtualRealityDeviceStatus {
public class StorageVirtualRealitySwitch extends StorageControllableVrDevice<VirtualRealitySwitch.Operation> {
private SwitchIndication p;
/**
* 控制指令
*/
private VirtualRealitySwitch.Operation command;
/**
* 剩余时间
*/
private int remain;
public StorageVirtualRealitySwitch(VirtualRealitySwitch s) {
super(s);
@ -45,8 +37,7 @@ public class StorageVirtualRealitySwitch extends StorageVirtualRealityDeviceStat
}
if (s.isTurning()) {
change = true;
storageSwitch.setCommand(s.getCommand());
storageSwitch.setRemain(s.getRemain());
storageSwitch.saveFrom(s);
}
if (change) {
return storageSwitch;
@ -60,8 +51,8 @@ public class StorageVirtualRealitySwitch extends StorageVirtualRealityDeviceStat
if (this.p != null) {
s.setP(p);
}
if (this.remain > 0) {
s.recover(this.command, this.remain);
if (this.getRemain() > 0) {
this.recoverTo(s);
}
}
}

View File

@ -31,6 +31,9 @@ public class VirtualRealitySwitch extends ControllableVrDevice<VirtualRealitySwi
@Override
protected void doFinish(Operation command) {
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotNull(command);
if (Fault.SQUEEZE.equals(this.getFault())) {
return;
}
switch (command) {
case NP:
this.p = SwitchIndication.N;

View File

@ -496,8 +496,8 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
this.gear = ControlGear.Drive;
this.communication = true;
this.atpOn = true;
this.door1 = new Door("1");
this.door2 = new Door("2");
this.door1 = new Door(this, "1");
this.door2 = new Door(this, "2");
this.doorMode = DoorMode.AM;
this.doorSelection = DoorSelection.Z;
}
@ -543,8 +543,6 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
this.changeEndsRemainTime = 0;
this.atoOn = false;
this.atpOn = false;
this.door1 = new Door("1");
this.door2 = new Door("2");
this.fk = 0;
this.fb = 0;
this.tbControl = null;
@ -738,14 +736,6 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
this.ma2 = null;
}
/**
* 执行车门开/关过程
*/
public void doorTurning() {
this.door1.running();
this.door2.running();
}
public float getProtectSpeedKmPh() {
return (float) (this.atpSpeed * 3.6);
}
@ -754,14 +744,6 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
return (float) (this.atoSpeed * 3.6);
}
/**
* 车门是否正在关闭
*/
public boolean isDoorClosing() {
return (this.door1.isTurning() && !this.door1.isCommandOpen()) ||
(this.door2.isTurning() && !this.door2.isCommandOpen());
}
public SectionPosition calculateTailPosition() {
this.tailPosition = CalculateService.calculateNextPositionByStartAndLen(this.headPosition, !right, this.getLen());
return this.tailPosition;
@ -1094,29 +1076,28 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
@Getter
@Setter
public class Door {
public static class Door extends ControllableVrDevice<Door.Operation> {
/**
* 道岔支持的操作
*/
public enum Operation {
/** 开门 */
K,
/** 关门 */
G,
}
private VirtualRealityTrain train;
private String code;
private boolean close;
private boolean lock;
/**
* 是否开/关门过程中
*/
private boolean turning;
/**
* 命令true-开门命令false-关门命令
*/
private boolean commandOpen;
/**
* 过程剩余时间
*/
private float remainTime;
public Door(String code) {
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;
@ -1130,47 +1111,32 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
return this.close && this.lock;
}
public void open() {
this.commandOpen = true;
this.remainTime = 2;
this.turning = true;
}
public void close() {
this.commandOpen = false;
this.remainTime = 2;
this.turning = true;
}
public boolean isOpening() {
return this.turning && this.commandOpen;
return this.getRemain() > 0 && Operation.K.equals(this.getCommand());
}
public boolean isClosing() {
return this.turning && !this.commandOpen;
return this.getRemain() > 0 && Operation.G.equals(this.getCommand());
}
public void running() {
if (this.turning) {
if (this.lock) {
@Override
protected void doTurn() {
this.lock = false;
}
this.remainTime -= SimulationModule.VRD.getRateS();
if (this.remainTime < 0) {
this.finish();
}
}
this.close = false;
}
public void finish() {
this.turning = false;
this.remainTime = -1;
if (this.commandOpen) {
@Override
protected void doFinish(Operation command) {
switch (command) {
case K:
this.lock = false;
this.close = false;
} else {
break;
case G:
this.close = true;
}
this.lock = true;
break;
}
}
}

View File

@ -1,6 +1,6 @@
package club.joylink.rtss.simulation.cbtc.device.real.modbustcp.richor;
import club.joylink.rtss.simulation.cbtc.CI.service.StandService;
import club.joylink.rtss.simulation.cbtc.CI.device.CiStandService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.SimulationIscsDataRepository;
import club.joylink.rtss.simulation.cbtc.data.map.Stand;
@ -12,13 +12,12 @@ import club.joylink.rtss.simulation.rt.iscs.IscsStatusPublisher;
import club.joylink.rtss.vo.client.project.richor.RichorPslConfigVO;
import io.netty.buffer.ByteBuf;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class RichorPslServiceImpl implements RealDeviceService {
@Autowired
private StandService standService;
private CiStandService standService;
@Override
public boolean canHandle(RealDeviceConfig deviceConfig) {

View File

@ -30,13 +30,13 @@ public class VRDeviceLogicLoop {
// long start = System.currentTimeMillis();
// 虚拟真实道岔转动过程
SimulationDataRepository repository = simulation.getRepository();
List<ControllableVrDevice> list = repository.getAllControllableCrDevice();
List<ControllableVrDevice> list = repository.getAllControllableVrDevice();
for (ControllableVrDevice device : list) {
this.virtualRealityDeviceService.turning(simulation, device);
}
List<VirtualRealityTrain> onlineTrainList = repository.getOnlineTrainList();
onlineTrainList.forEach(train ->
this.virtualRealityDeviceService.virtualTrainDoorTurning(train));
this.virtualRealityDeviceService.virtualTrainDoorTurning(simulation, train));
// 列车占压计轴区段检查
this.updateTrainOccupySection(simulation);
}

View File

@ -1,7 +1,7 @@
package club.joylink.rtss.simulation.cbtc.device.virtual;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.communication.vo.*;
import club.joylink.rtss.simulation.cbtc.constant.SignalAspect;
import club.joylink.rtss.simulation.cbtc.constant.SimulationModule;
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
import club.joylink.rtss.simulation.cbtc.data.vr.*;
@ -41,50 +41,39 @@ public class VirtualRealityDeviceService {
/**
* 列车车门开/关过程控制
*
* @param simulation
* @param train
*/
public void virtualTrainDoorTurning(VirtualRealityTrain train) {
public void virtualTrainDoorTurning(Simulation simulation, VirtualRealityTrain train) {
if (!train.isConnectReal()) {
train.doorTurning();
this.turning(simulation, train.getDoor1());
this.turning(simulation, train.getDoor2());
}
}
public void reset(Simulation simulation) {
// todo 修改为新的事件
for (VirtualRealityDevice value : simulation.getRepository().getVrDeviceMap().values()) {
value.reset();
MapElement.DeviceType deviceType = value.getDeviceType();
switch (deviceType) {
case SWITCH:{
VirtualRealitySwitch aSwitch = (VirtualRealitySwitch) value;
ControllableDevice ctrlMsg = new SwitchTurn(aSwitch, true);
SimulationDeviceControlEvent event = new SimulationDeviceControlEvent(this, simulation, ctrlMsg);
this.applicationContext.publishEvent(event);
this.control(simulation, aSwitch, VirtualRealitySwitch.Operation.NP);
break;
}
case SIGNAL:{
ControllableDevice ctrlMsg = new SignalLight((VirtualRealitySignal) value);
SimulationDeviceControlEvent event = new SimulationDeviceControlEvent(this, simulation, ctrlMsg);
this.applicationContext.publishEvent(event);
this.control(simulation, (VirtualRealitySignal) value, SignalAspect.No);
break;
}
case PSD:{
VirtualRealityScreenDoor psd = (VirtualRealityScreenDoor) value;
ControllableDevice ctrlMsg = new PsdSwitch(psd, psd.isOpen2End());
SimulationDeviceControlEvent event = new SimulationDeviceControlEvent(this, simulation, ctrlMsg);
this.applicationContext.publishEvent(event);
this.control(simulation, psd, VirtualRealityScreenDoor.Operation.G);
break;
}
case TRAIN:{
VirtualRealityTrain train = (VirtualRealityTrain) value;
VirtualRealityTrain.Door door1 = train.getDoor1();
TrainDoorSwitch ctrlMsg = new TrainDoorSwitch(train, door1, door1.isOpen());
SimulationDeviceControlEvent event = new SimulationDeviceControlEvent(this, simulation, ctrlMsg);
this.applicationContext.publishEvent(event);
VirtualRealityTrain.Door door2 = train.getDoor2();
ctrlMsg = new TrainDoorSwitch(train, door2, door2.isOpen());
event = new SimulationDeviceControlEvent(this, simulation, ctrlMsg);
this.applicationContext.publishEvent(event);
this.control(simulation, train.getDoor1(), VirtualRealityTrain.Door.Operation.G);
this.control(simulation, train.getDoor2(), VirtualRealityTrain.Door.Operation.G);
break;
}
}

View File

@ -1,7 +1,6 @@
package club.joylink.rtss.simulation.cbtc.event;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.communication.vo.ControllableDevice;
import club.joylink.rtss.simulation.cbtc.data.vr.ControllableVrDevice;
import lombok.Getter;
@ -11,7 +10,6 @@ import lombok.Getter;
@Getter
public class SimulationDeviceControlEvent extends AbstractSimulationEvent {
private ControllableDevice ctrlMsg;
ControllableVrDevice device;
public SimulationDeviceControlEvent(Object source, Simulation simulation, ControllableVrDevice device) {
@ -19,8 +17,4 @@ public class SimulationDeviceControlEvent extends AbstractSimulationEvent {
this.device = device;
}
public SimulationDeviceControlEvent(Object source, Simulation simulation, ControllableDevice ctrlMsg) {
super(source, simulation);
this.ctrlMsg = ctrlMsg;
}
}

View File

@ -1,6 +1,7 @@
package club.joylink.rtss.simulation.cbtc.member;
import club.joylink.rtss.constants.MapPrdTypeEnum;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.SimulationManager;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
@ -43,6 +44,9 @@ public class MemberManager {
for (Station station : stationList) {
if (station.isNormal()) {
this.addRole(simulation, SimulationMember.Type.STATION_SUPERVISOR, null, station);
} else if (station.isDepot()) {
// 车辆段调度
this.addRole(simulation, SimulationMember.Type.DEPOT_DISPATCHER, station.getName()+"调度", station);
}
}
// 司机
@ -52,8 +56,8 @@ public class MemberManager {
}
// 工电调度
this.addRole(simulation, SimulationMember.Type.ELECTRIC_DISPATCHER);
// 车辆段调度
this.addRole(simulation, SimulationMember.Type.DEPOT_DISPATCHER);
// // 车辆段调度
// this.addRole(simulation, SimulationMember.Type.DEPOT_DISPATCHER);
// 车辆段信号楼
this.addRole(simulation, SimulationMember.Type.DEPOT_SIGNAL_BUILDING);
// 停车场信号楼
@ -109,6 +113,14 @@ public class MemberManager {
case DISPATCHER:{
break;
}
case DEPOT_DISPATCHER:{
if (Objects.isNull(device) ||
!Objects.equals(device.getDeviceType(), MapElement.DeviceType.STATION) ||
!((Station) device).isDepot()) {
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.exception("车辆段调度必须关联车辆段/停车场车站");
}
break;
}
case STATION_SUPERVISOR:{
if (Objects.isNull(device) ||
!Objects.equals(device.getDeviceType(), MapElement.DeviceType.STATION) ||

View File

@ -3,7 +3,6 @@ package club.joylink.rtss.simulation.cbtc.onboard.ATO.service;
import club.joylink.rtss.simulation.cbtc.ATP.ground.MaService;
import club.joylink.rtss.simulation.cbtc.CI.CiApiService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.communication.vo.TrainDoorSwitch;
import club.joylink.rtss.simulation.cbtc.constant.DriveMode;
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
import club.joylink.rtss.simulation.cbtc.data.CalculateService;
@ -13,7 +12,7 @@ import club.joylink.rtss.simulation.cbtc.data.map.Stand;
import club.joylink.rtss.simulation.cbtc.data.support.MovementAuthority;
import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import club.joylink.rtss.simulation.cbtc.event.SimulationDeviceControlEvent;
import club.joylink.rtss.simulation.cbtc.device.virtual.VirtualRealityDeviceService;
import club.joylink.rtss.simulation.cbtc.onboard.ATO.SpeedCurve;
import club.joylink.rtss.simulation.cbtc.onboard.ATP.OnboardAtpApiService;
import lombok.extern.slf4j.Slf4j;
@ -34,6 +33,8 @@ public class ATOService {
@Autowired
private ApplicationContext applicationContext;
@Autowired
private VirtualRealityDeviceService virtualRealityDeviceService;
@Autowired
private CiApiService ciApiService;
@ -414,10 +415,7 @@ public class ATOService {
if (door.isOpening() || door.isOpen()) {
return;
}
TrainDoorSwitch ctrlMsg = new TrainDoorSwitch(train, door, true);
SimulationDeviceControlEvent event = new SimulationDeviceControlEvent(this, simulation, ctrlMsg);
this.applicationContext.publishEvent(event);
door.open();
this.virtualRealityDeviceService.control(simulation, door, VirtualRealityTrain.Door.Operation.K);
log.debug(String.format("列车[%s-%s|%s|%s]开门[%s]",
train.getGroupNumber(), train.getServiceNumber(),
train.getTripNumber(), train.getDestinationCode(),
@ -428,10 +426,7 @@ public class ATOService {
if (door.isClosing() || door.isClose()) {
return;
}
TrainDoorSwitch ctrlMsg = new TrainDoorSwitch(train, door, false);
SimulationDeviceControlEvent event = new SimulationDeviceControlEvent(this, simulation, ctrlMsg);
this.applicationContext.publishEvent(event);
door.close();
this.virtualRealityDeviceService.control(simulation, door, VirtualRealityTrain.Door.Operation.G);
log.debug(String.format("列车[%s-%s|%s|%s]关门[%s]",
train.getGroupNumber(), train.getServiceNumber(),
train.getTripNumber(), train.getDestinationCode(),