diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/ATP/ground/ResponderService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/ATP/ground/ResponderService.java index c05f40290..8e1430ffc 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/ATP/ground/ResponderService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/ATP/ground/ResponderService.java @@ -5,39 +5,31 @@ import club.joylink.rtss.simulation.cbtc.data.map.Responder; 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 lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; /** * 应答器信号发射 */ -@Slf4j @Component public class ResponderService { - /** - * 列车经过应答器触发电磁信号 - */ - public Responder activeExchangeData(Simulation simulation, VirtualRealityTrain train) { + public Responder viaResponder(Simulation simulation, VirtualRealityTrain train, SectionPosition headPosition, SectionPosition headPositionNew) { Map> sectionRespondersMap = simulation.getRepository().getSectionRespondersMap(); - if (CollectionUtils.isEmpty(sectionRespondersMap)) { - return null; + List
sections = List.of(headPosition.getSection(), headPositionNew.getSection()); + for (Section section : sections) { + List responders = sectionRespondersMap.get(section); + if (!CollectionUtils.isEmpty(responders)) { + for (Responder responder : responders) { + if (responder.isTrigger(headPosition, headPositionNew)) { + train.viaResponder(responder); + return responder; + } + } + } } - //电磁触发以列车头位置(车载应答器)模拟 - SectionPosition headPosition = train.getHeadPosition(); - Section section = headPosition.getSection(); - var responders = sectionRespondersMap.get(section); - if (CollectionUtils.isEmpty(responders)) return null; - Responder activeResponder = responders.stream().filter(responder -> - responder.active(headPosition, train.isRight())).findAny().orElse(null); - if (Objects.isNull(activeResponder)) return null; - log.info("列车触发应答器交换数据"); - activeResponder.exchangeData(train); - return activeResponder; + return null; } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/ATP/ground/ZCLogicLoop.java b/src/main/java/club/joylink/rtss/simulation/cbtc/ATP/ground/ZCLogicLoop.java index ddec15bea..ddcca5519 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/ATP/ground/ZCLogicLoop.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/ATP/ground/ZCLogicLoop.java @@ -60,9 +60,13 @@ public class ZCLogicLoop { } } //更新CBTC ma - if (!deviceStation.getZc().isFault()) { //如果列车头所在区段所属设备集中站zc未故障 + if (headPosition.getSection().anyZcWorking()) { this.calculateMAOfCBTC(simulation, train, trainList); } +// //更新CBTC ma +// if (!deviceStation.getZc().isFault()) { //如果列车头所在区段所属设备集中站zc未故障 +// this.calculateMAOfCBTC(simulation, train, trainList); +// } } }); } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/build/MapDeviceBuilder.java b/src/main/java/club/joylink/rtss/simulation/cbtc/build/MapDeviceBuilder.java index da6ea78b0..f9584a58b 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/build/MapDeviceBuilder.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/build/MapDeviceBuilder.java @@ -1,6 +1,7 @@ package club.joylink.rtss.simulation.cbtc.build; import club.joylink.rtss.constants.BusinessConsts; +import club.joylink.rtss.exception.BusinessExceptionAssertEnum; import club.joylink.rtss.simulation.cbtc.data.map.*; import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition; import club.joylink.rtss.simulation.cbtc.data.support.StationTurnBackStrategyOption; @@ -302,6 +303,39 @@ public class MapDeviceBuilder { } } }); + /* ZC和区段相互赋值 */ + // ZC + if (graphData.getZcList().size() == 1) { + MapZcVO mapZcVO = graphData.getZcList().get(0); + ZC zc = (ZC) elementMap.get(mapZcVO.getCode()); + physicalSectionList.forEach(section -> { + zc.addSection(section); + section.addZc(zc); + }); + } else { + graphData.getZcList().forEach(mapZcVO -> { + ZC zc = (ZC) elementMap.get(mapZcVO.getCode()); + List zcSections = mapZcVO.getManagedSectionList(); + if (CollectionUtils.isEmpty(zcSections)) + errMsgList.add(String.format("ZC[%s]无关联区段", mapZcVO.getCode())); + if (!CollectionUtils.isEmpty(zcSections)) { + for (String sectionCode : zcSections) { + Section section = (Section) elementMap.get(sectionCode); + BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotNull(section, + String.format("ZC[%s]关联的区段[%s]不存在", zc.getCode(), sectionCode)); + if (section.isPhysical()) { + section.addZc(zc); + zc.addSection(section); + } else if (section.isSwitchAxleCounterSection() || section.isCross()) { + section.getLogicList().forEach(logic -> { + logic.addZc(zc); + zc.addSection(logic); + }); + } + } + } + }); + } // 站台 List standList = graphData.getStationStandList(); standList.forEach(standVO -> { @@ -764,18 +798,19 @@ public class MapDeviceBuilder { queryAdjoinSections(section, false, leftDirectionList); log.debug(String.format("区段[%s][右向]邻接区段为[%s],[左向]邻接区段为[%s]", section.debugStr(), - String.join(",",rightDirectionList.stream().map(Section::debugStr).collect(Collectors.toList())), + String.join(",", rightDirectionList.stream().map(Section::debugStr).collect(Collectors.toList())), String.join(",", leftDirectionList.stream().map(Section::debugStr).collect(Collectors.toList())))); } return sectionDirectionSectionsMap; } private static String buildSectionDirectionKey(Section section, boolean right) { - return String.format("%s-%s", section.getCode(), right?"R":"L"); + return String.format("%s-%s", section.getCode(), right ? "R" : "L"); } /** * 查找区段临近的功能区段(站台轨、转换轨、折返轨) + * * @param section * @param right * @param rightDirectionList @@ -1126,7 +1161,7 @@ public class MapDeviceBuilder { } else if (!section.isPhysical()) { errMsgList.add(String.format("应答器[%s(%s)]关联区段[(%s)]不是物理区段", responderVO.getName(), responderVO.getCode(), responderVO.getSectionCode())); } else { - responder.setPhysicalSection(section); +// responder.setPhysicalSection(section); List responders = sectionRespondersMap.computeIfAbsent(section, k -> new ArrayList()); responders.add(responder); } @@ -1136,7 +1171,8 @@ public class MapDeviceBuilder { errMsgList.add(String.format("应答器[%s(%s)]的区段偏移量未设置或数据异常[%s]", responderVO.getName(), responderVO.getCode(), responderVO.getOffset())); } else { - responder.setSectionOffset(responderVO.getOffset()); +// responder.setSectionOffset(responderVO.getOffset()); + responder.setPosition(new SectionPosition(section, responderVO.getOffset())); } }); } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/Responder.java b/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/Responder.java index 38ac8a9cd..5d2422614 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/Responder.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/Responder.java @@ -5,8 +5,6 @@ import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain; import lombok.Getter; import lombok.Setter; -import java.util.Objects; - /** * 应答器仿真数据 */ @@ -27,15 +25,18 @@ public class Responder extends MapNamedElement { /** 所属设备集中站*/ private Station deviceStation; - /** 物理区段*/ - private Section physicalSection; - - /** 在区段上的偏移量*/ - private float sectionOffset; +// /** 物理区段*/ +// private Section physicalSection; +// +// /** 在区段上的偏移量*/ +// private float sectionOffset; /**VB关联信号机*/ private Signal signal; + /** 位置 */ + private SectionPosition position; + // ------------------LEU同步的状态--------------------- @@ -65,19 +66,26 @@ public class Responder extends MapNamedElement { return ResponderType.IB == type; } - public boolean active(SectionPosition headPosition, boolean right) { - if (Objects.equals(physicalSection, headPosition.getSection())) { - float o = right ? headPosition.getOffset() - sectionOffset : sectionOffset - headPosition.getOffset(); - if (o >= 0 && o < ACTIVE_DISTANCE) { - return true; - } - } - return false; - } +// public boolean active(SectionPosition headPosition, boolean right) { +// if (Objects.equals(physicalSection, headPosition.getSection())) { +// float o = right ? headPosition.getOffset() - sectionOffset : sectionOffset - headPosition.getOffset(); +// if (o >= 0 && o < ACTIVE_DISTANCE) { +// return true; +// } +// } +// return false; +// } public void exchangeData(VirtualRealityTrain train) { - train.passingResponder(this); + train.viaResponder(this); } + + public boolean isTrigger(SectionPosition headPosition, SectionPosition headPositionNew) { + if (this.isVB() && !signal.isNormalOpen()) + return false; + return this.position.isBetween(headPosition, headPositionNew); + } + public enum ResponderType { /** 固定应答器*/ FB, diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/Section.java b/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/Section.java index 0e6f153bb..c4e068c3f 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/Section.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/Section.java @@ -156,6 +156,11 @@ public class Section extends MayOutOfOrderDevice { */ private Float stopPointRight; + /** + * 所属zc + */ + private List zcs = new ArrayList<>(); + // ------------------状态属性--------------------- /** @@ -1014,6 +1019,20 @@ public class Section extends MayOutOfOrderDevice { return false; } + public void addZc(ZC zc) { + this.zcs.add(zc); + } + + /** + * 任意一个zc正常工作 + */ + public boolean anyZcWorking() { + if (!CollectionUtils.isEmpty(zcs)) { + return zcs.stream().anyMatch(zc -> !zc.isFault()); + } + return false; + } + public enum SectionRoadType { /** * 左行线 diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/ZC.java b/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/ZC.java index 1952aace2..f5d31d790 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/ZC.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/ZC.java @@ -1,11 +1,20 @@ package club.joylink.rtss.simulation.cbtc.data.map; +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; import java.util.Objects; /** * 区域控制器 */ +@Getter public class ZC extends MayOutOfOrderDevice { + + private List
sections = new ArrayList<>(); + public ZC(String code, String name) { super(code, name, DeviceType.ZC); } @@ -15,6 +24,10 @@ public class ZC extends MayOutOfOrderDevice { super.reset(); } + public void addSection(Section section) { + sections.add(section); + } + public enum Fault implements DeviceFault { /**ZC故障*/ FAULT{ diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/data/vr/VirtualRealityTrain.java b/src/main/java/club/joylink/rtss/simulation/cbtc/data/vr/VirtualRealityTrain.java index 36d985465..312c084f8 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/data/vr/VirtualRealityTrain.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/data/vr/VirtualRealityTrain.java @@ -463,6 +463,8 @@ public class VirtualRealityTrain extends VirtualRealityDevice { this.headPosition = null; this.robotTargetPosition = null; this.ma = null; + this.cbtcMaMissDuration = 0; + this.itcMaMissDuration = 0; this.gear = null; this.speed = 0; this.targetDistance = 0; @@ -1074,7 +1076,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice { return !lastTwoPassedResponders.isEmpty(); } - public void passingResponder(Responder responder) { + public void viaResponder(Responder responder) { if (lastTwoPassedResponders.isEmpty()) { lastTwoPassedResponders.offer(responder); return; @@ -1088,8 +1090,11 @@ public class VirtualRealityTrain extends VirtualRealityDevice { } public boolean isCommunicable() { - Station deviceStation = headPosition.getSection().getDeviceStation(); - if (VirtualRealityTrain.Fault.COMMUNICATION_ABNORMAL == fault || Station.Fault.INTERLOCK_MACHINE_FAULT == deviceStation.getFault() || deviceStation.getZc().isFault()) { + Section section = headPosition.getSection(); + Station deviceStation = section.getDeviceStation(); + if (VirtualRealityTrain.Fault.COMMUNICATION_ABNORMAL == fault + || Station.Fault.INTERLOCK_MACHINE_FAULT == deviceStation.getFault() + || !section.anyZcWorking()) { return false; } return true; diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/device/virtual/VRTrainRunningService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/device/virtual/VRTrainRunningService.java index 95b6ebcce..16177d6c4 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/device/virtual/VRTrainRunningService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/device/virtual/VRTrainRunningService.java @@ -3,6 +3,7 @@ package club.joylink.rtss.simulation.cbtc.device.virtual; import club.joylink.rtss.simulation.cbtc.ATP.ground.ResponderService; import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.constant.ControlGear; +import club.joylink.rtss.simulation.cbtc.constant.RunLevel; import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants; import club.joylink.rtss.simulation.cbtc.constant.SimulationModule; import club.joylink.rtss.simulation.cbtc.data.CalculateService; @@ -18,6 +19,7 @@ import org.springframework.stereotype.Component; import java.util.List; import java.util.Objects; +import java.util.Queue; @Component @Slf4j @@ -122,7 +124,7 @@ public class VRTrainRunningService { if (change) train.setHeadPosition(headPositionNew); //列车级别 - trainRunLevelUpgrade(simulation, train); + viaResponder(simulation, train, headPosition, headPositionNew); //计轴器计数 axleCounterCount(simulation, train, headPosition, headPositionNew); @@ -166,36 +168,23 @@ public class VRTrainRunningService { } } - - private void trainRunLevelUpgrade(Simulation simulation, VirtualRealityTrain train) { - - //有应答器 - if (simulation.getRepository().hasResponder()) { - if (train.isCBTC()) { - return; - } - Responder passingResponder = responderService.activeExchangeData(simulation, train); - if (Objects.isNull(passingResponder)) { - return; - } - if (train.isIL()) { - if (passingResponder.isVB()) { - Signal signal = passingResponder.getSignal(); - if (Objects.equals(signal.isRight(), train.isRight()) && signal.isNormalOpen() && Objects.nonNull(signal.getLockedRoute())) { - train.setITCMode(); - log.info("列车越过VB应答器从IL升级ITC"); - } - } - } - if (train.isCommunicable()) { - if (train.getLastTwoPassedResponders().size() == VirtualRealityTrain.Responders_Record) { - train.setCBTCMode(); - log.info("列车越过两个应答器从ITC升级CBTC"); - train.clearResponders(); - return; - } - } + /** + * 穿过应答器 + */ + private void viaResponder(Simulation simulation, VirtualRealityTrain train, SectionPosition headPosition, SectionPosition headPositionNew) { + if (!simulation.getRepository().hasResponder()) return; + // 列车升级 + if (!train.isIL()) + return; + Responder passingResponder = responderService.viaResponder(simulation, train, headPosition, headPositionNew); + if (passingResponder == null || !passingResponder.isVB()) + return; + Queue responders = train.getLastTwoPassedResponders(); + if (responders.size() != 2) + return; + if (responders.stream().allMatch(responder -> responder.isVB() || responder.isFB())) { + train.setITCMode(); } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/onboard/ATP/ATPLogicLoop.java b/src/main/java/club/joylink/rtss/simulation/cbtc/onboard/ATP/ATPLogicLoop.java index fbcec8419..332085b23 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/onboard/ATP/ATPLogicLoop.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/onboard/ATP/ATPLogicLoop.java @@ -78,22 +78,35 @@ public class ATPLogicLoop { atpService.triggerSignalEB(train); train.setMa(null); } - } - if (!simulation.getRepository().hasResponder()) { - //无应答器 - if (!train.isCbtcMaMiss()) { - if (!train.isCBTC() && defaultRunLevel.equals(RunLevel.CBTC)) { //如果列车不是CBTC,同时线路默认级别是CBTC - train.setCBTCMode(); - } - train.setCbtcMaMissDuration(train.getCbtcMaMissDuration() + SimulationConstants.ATP_LOOP_RATE); + } else { + train.setCbtcMaMissDuration(train.getCbtcMaMissDuration() + SimulationConstants.ATP_LOOP_RATE); + if (!train.isCBTC() && defaultRunLevel.equals(RunLevel.CBTC)) { //如果列车不是CBTC,同时线路默认级别是CBTC + train.setCBTCMode(); } - if (!train.isItcMaMiss()) { //itc级别ma未丢失 + } + if (!train.isItcMaMiss()) { + train.setItcMaMissDuration(train.getItcMaMissDuration() + SimulationConstants.ATP_LOOP_RATE); + if (!simulation.getRepository().hasResponder()) { if (RunLevel.IL.equals(train.getRunLevel())) { //如果列车是IL级别 train.setITCMode(); } - train.setItcMaMissDuration(train.getItcMaMissDuration() + SimulationConstants.ATP_LOOP_RATE); } } +// if (!simulation.getRepository().hasResponder()) { +// //无应答器 +// if (!train.isCbtcMaMiss()) { +// if (!train.isCBTC() && defaultRunLevel.equals(RunLevel.CBTC)) { //如果列车不是CBTC,同时线路默认级别是CBTC +// train.setCBTCMode(); +// } +// train.setCbtcMaMissDuration(train.getCbtcMaMissDuration() + SimulationConstants.ATP_LOOP_RATE); +// } +// if (!train.isItcMaMiss()) { //itc级别ma未丢失 +// if (RunLevel.IL.equals(train.getRunLevel())) { //如果列车是IL级别 +// train.setITCMode(); +// } +// train.setItcMaMissDuration(train.getItcMaMissDuration() + SimulationConstants.ATP_LOOP_RATE); +// } +// } } private void driveLogicRun(Simulation simulation, VirtualRealityTrain train) { diff --git a/src/main/java/club/joylink/rtss/vo/map/MapZcVO.java b/src/main/java/club/joylink/rtss/vo/map/MapZcVO.java index 4d3305c20..101c0aaa8 100644 --- a/src/main/java/club/joylink/rtss/vo/map/MapZcVO.java +++ b/src/main/java/club/joylink/rtss/vo/map/MapZcVO.java @@ -43,4 +43,9 @@ public class MapZcVO { * 管控集中站列表 */ private List concentrateStationList; + + /** + * 管理的区段列表 + */ + private List managedSectionList; }