From 6abd8254b66f35456e8294a72543db32a7e2b13d Mon Sep 17 00:00:00 2001 From: walker-sheng Date: Fri, 5 Mar 2021 16:34:54 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=BF=E7=9C=9F=E7=BB=93=E6=9E=84=E6=8A=BD?= =?UTF-8?q?=E8=B1=A1(=E4=BB=BF=E7=9C=9F=E4=B8=BB=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E8=B0=83=E6=95=B4)=20=E8=99=9A=E6=8B=9F?= =?UTF-8?q?=E7=9C=9F=E5=AE=9E=E8=AE=BE=E5=A4=87=E9=80=BB=E8=BE=91=E5=BC=80?= =?UTF-8?q?=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../joylink/rtss/simulation/Simulation.java | 57 ++++++++----- .../simulation/SimulationScheduledJob.java | 12 +-- .../simulation/rt/RtSimulationService.java | 20 +++-- .../rtss/simulation/rt/srd/SrdService.java | 80 ++++++++++++++++--- .../rtss/simulation/rt/srd/bo/SrTrack.java | 61 +++++++++++--- .../rtss/simulation/rt/srd/bo/SrTrain.java | 33 +++++++- .../rtss/simulation/rt/srd/bo/SrTurnout.java | 27 ++++--- .../rt/srd/bo/SrdRepositoryBuilder.java | 8 +- .../simulation/rt/srd/bo/TrackPosition.java | 13 +++ 9 files changed, 243 insertions(+), 68 deletions(-) diff --git a/src/main/java/club/joylink/rtss/simulation/Simulation.java b/src/main/java/club/joylink/rtss/simulation/Simulation.java index 6dff419fe..a3a5bec3b 100644 --- a/src/main/java/club/joylink/rtss/simulation/Simulation.java +++ b/src/main/java/club/joylink/rtss/simulation/Simulation.java @@ -28,12 +28,12 @@ public abstract class Simulation scheduledFuture = EXECUTOR.scheduleAtFixedRate(()->this.logic(), - this.runPeriod, this.runPeriod, TimeUnit.NANOSECONDS); - this.future = scheduledFuture; + this.systemTime = LocalDateTime.now(); } - private void updateRunPeriod(int speed) { - this.runPeriod = TimeUnit.MILLISECONDS.toNanos(SYSTEM_TIME_RATE) / speed; + public static void main(String[] args) { + Simulation simulation = new Simulation("1") { + @Override + public String debugStr() { + return null; + } + }; + simulation.addJob("b", () -> { + log.info("logic"); + }, 500); + simulation.addFixedRateJob("c", () -> { + log.warn("fixed"); + }, 1000); + simulation.updateSpeed(5); + simulation.start(); + } + private void runAsSpeed() { + if (this.future == null) { +// if (!this.future.cancel(false)) { +// log.error(String.format("仿真旧主线程无法取消")); +// } + ScheduledFuture scheduledFuture = EXECUTOR.scheduleAtFixedRate(()->this.logic(), + this.SYSTEM_TIME_RATE, this.SYSTEM_TIME_RATE, TimeUnit.MILLISECONDS); + this.future = scheduledFuture; + } + this.updateTimeUpdateSpeed(this.speed); + } + + private void updateTimeUpdateSpeed(int speed) { + this.timeAdd = TimeUnit.MILLISECONDS.toNanos(SYSTEM_TIME_RATE) * speed; } private void logic() { @@ -109,7 +124,7 @@ public abstract class Simulation TimeUnit.MILLISECONDS.toNanos(TIMEOUT)) { - log.warn(String.format("仿真任务[%s]执行耗时[%sns]超过[%sms],请检查并调优", - this.name, TimeUnit.NANOSECONDS.toMillis(used), TIMEOUT)); + if (used > TIMEOUT_NANO) { + log.warn(String.format("仿真任务[%s]执行耗时[%sns]超过[%sns],请检查并调优", + this.name, used, TIMEOUT_NANO)); } } public void updateRunPeriod(int speed) { if (this.fixed) { - this.runPeriod = TimeUnit.MILLISECONDS.toNanos(this.rate); + this.runPeriod = TimeUnit.MILLISECONDS.toNanos(this.rate) * speed; } else { - this.runPeriod = TimeUnit.MILLISECONDS.toNanos(this.rate) / speed; + this.runPeriod = TimeUnit.MILLISECONDS.toNanos(this.rate); } } diff --git a/src/main/java/club/joylink/rtss/simulation/rt/RtSimulationService.java b/src/main/java/club/joylink/rtss/simulation/rt/RtSimulationService.java index 032f4af3b..ff565df1e 100644 --- a/src/main/java/club/joylink/rtss/simulation/rt/RtSimulationService.java +++ b/src/main/java/club/joylink/rtss/simulation/rt/RtSimulationService.java @@ -1,32 +1,42 @@ package club.joylink.rtss.simulation.rt; +import club.joylink.rtss.services.MapService; import club.joylink.rtss.simulation.SimulationManager; import club.joylink.rtss.simulation.rt.srd.SrdService; import club.joylink.rtss.vo.UserVO; +import club.joylink.rtss.vo.client.map.MapVO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.Objects; + @Component public class RtSimulationService { + @Autowired + private MapService mapService; + @Autowired private SimulationManager simulationManager; @Autowired private SrdService srdService; - public RtSimulation create(UserVO userVO) { + public RtSimulation create(UserVO userVO, Long mapId) { + Objects.requireNonNull(mapId); + MapVO mapVO = this.mapService.getMapDetail(mapId); RtSimulation rtSimulation = new RtSimulation(SimulationIdGenerator.buildId()); - this.simulationManager.save(rtSimulation); - this.load(rtSimulation); + this.loadData(rtSimulation, mapVO); this.srdService.addJobs(rtSimulation); + this.simulationManager.save(rtSimulation); return rtSimulation; } /** * 加载相关数据 * @param rtSimulation + * @param mapVO */ - private void load(RtSimulation rtSimulation) { - + private void loadData(RtSimulation rtSimulation, MapVO mapVO) { + this.srdService.buildRepository(rtSimulation, mapVO); } } diff --git a/src/main/java/club/joylink/rtss/simulation/rt/srd/SrdService.java b/src/main/java/club/joylink/rtss/simulation/rt/srd/SrdService.java index baec00caf..0f72efb3b 100644 --- a/src/main/java/club/joylink/rtss/simulation/rt/srd/SrdService.java +++ b/src/main/java/club/joylink/rtss/simulation/rt/srd/SrdService.java @@ -1,10 +1,8 @@ package club.joylink.rtss.simulation.rt.srd; +import club.joylink.rtss.exception.BusinessExceptionAssertEnum; import club.joylink.rtss.simulation.rt.RtSimulation; -import club.joylink.rtss.simulation.rt.srd.bo.SrTrain; -import club.joylink.rtss.simulation.rt.srd.bo.SrdRepository; -import club.joylink.rtss.simulation.rt.srd.bo.SrdRepositoryBuilder; -import club.joylink.rtss.simulation.rt.srd.bo.TrackPosition; +import club.joylink.rtss.simulation.rt.srd.bo.*; import club.joylink.rtss.vo.client.map.MapVO; import org.springframework.stereotype.Component; @@ -28,14 +26,76 @@ public class SrdService { public void srTrainRun(SrdRepository repository) { List trainList = repository.getTrainList(); for (SrTrain srTrain : trainList) { + if (!srTrain.isUsing()) { + continue; + } TrackPosition position = srTrain.getPosition(); - if (position == null) { // 列车没有位置 - continue; + long speed = srTrain.getSpeed(); + boolean right = srTrain.isRight(); + int cv = this.calculateSpeed(srTrain); + int s = this.calculateLen(cv, TRAIN_RUN_RATE); + TrackPosition np = calculatePosition(position, s, right); + if (np.equals(position) && cv != 0) { + cv = 0; } - if (srTrain.isNeutralGear()) { // 空挡 - continue; - } - + srTrain.updatePositionAndSpeed(np, cv); } } + + private int calculateLen(int cv, int time) { + return cv * time; + } + + private int calculateSpeed(SrTrain srTrain) { + long speed = srTrain.getSpeed(); + int wa = (int) (10 + speed * 0.001 + speed * speed * 0.0000003); // 阻力所产生的反向加速度 + int pa = 0; + if (srTrain.isEb()) { + pa = SrTrain.ES_DEC; + } else { + pa = srTrain.getP() >= 0 ? srTrain.getP() * SrTrain.MAX_ACC : srTrain.getP() * SrTrain.MAX_DEC; + } + int a = pa - wa; + int cv = (int) (speed + a * TRAIN_RUN_RATE); // 当前速度 + if (cv < 0) { + cv = 0; + } + return cv; + } + + private TrackPosition calculatePosition(TrackPosition position, int s, boolean right) { + if (s == 0) { + return position; + } + SrTrack track = position.getTrack(); + int offset = position.getOffset(); + if (right) { + offset += s; + } else { + offset -= s; + } + SrTrack base = track; + while (offset < 0 || offset > base.getLen()) { + SrTrack nextTrack = base.queryNextTrack(right); + if (nextTrack == null) { + if (offset < 0) { + offset = 0; + } else { + offset = base.getLen(); + } + break; + } else { + if (right) { + BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotTrue(offset < 0); + offset -= base.getLen(); + } else { + BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotTrue(offset > base.getLen()); + offset += nextTrack.getLen(); + } + base = nextTrack; + } + } + return new TrackPosition(base, offset); + } + } diff --git a/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/SrTrack.java b/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/SrTrack.java index e1047b7be..fc0319c54 100644 --- a/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/SrTrack.java +++ b/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/SrTrack.java @@ -25,13 +25,21 @@ public class SrTrack extends SrDevice { */ SrAXC axc; /** - * 左侧轨道(可能为null) + * 左侧直向轨道(可能为null) */ - SrTrack left; + SrTrack leftTrack; + /** + * 左侧侧向轨道(非道岔的都为null) + */ + SrTrack leftFlankTrack; /** * 右侧轨道(可能为null) */ - SrTrack right; + SrTrack rightTrack; + /** + * 右侧侧向轨道(非道岔的都为null) + */ + SrTrack rightFlankTrack; /** * 关联的道岔(是道岔区段才会关联,否则为null) */ @@ -45,17 +53,52 @@ public class SrTrack extends SrDevice { this.axc = axc; } - public void setLeft(SrTrack left) { - this.left = left; - left.setRight(this); + public void setLeftTrack(SrTrack left) { + this.leftTrack = left; + left.setRightTrack(this); } - public void setRight(SrTrack right) { - this.right = right; - right.setLeft(this); + public void setLeftFlankTrack(SrTrack leftFlank) { + this.leftFlankTrack = leftFlank; + leftFlank.setRightTrack(this); + } + + public void setRightTrack(SrTrack right) { + this.rightTrack = right; + right.setLeftTrack(this); + } + + public void setRightFlankTrack(SrTrack rightFlank) { + this.rightFlankTrack = rightFlank; + rightFlank.setLeftTrack(this); } public void setTurnout(SrTurnout turnout) { this.turnout = turnout; } + + public SrTrack queryNextTrack(boolean right) { + if (this.turnout != null) { + if (this.turnout.isNormalPosition()) { + return right ? this.rightTrack : this.leftTrack; + } else if (this.turnout.isReversePosition()) { + if (right) { + if (this.rightFlankTrack != null) { + return this.rightFlankTrack; + } else { + return this.rightTrack; + } + } else { + if (this.leftFlankTrack != null) { + return this.leftFlankTrack; + } else { + return this.leftTrack; + } + } + } + } else { + return right ? this.rightTrack : this.leftTrack; + } + return null; + } } diff --git a/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/SrTrain.java b/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/SrTrain.java index 512f7edf2..9e6e71309 100644 --- a/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/SrTrain.java +++ b/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/SrTrain.java @@ -7,6 +7,10 @@ import lombok.Getter; */ @Getter public class SrTrain extends SrDevice { + /** + * 是否使用中 + */ + boolean using; /** * 列车长度,单位mm @@ -15,13 +19,29 @@ public class SrTrain extends SrDevice { /** * 列车质量,单位:吨 */ - int mass = 230; + int mass = 224; /** - * 牵引力,<0为制动 + * 最大加速度, 单位mm/s2 */ - int f; + public static final int MAX_ACC = 1600; /** - * 列车速度 + * 最大常用制动加速度, 单位mm/s2 + */ + public static final int MAX_DEC = -1200; + /** + * 紧急制动加速度, 单位mm/s2 + */ + public static final int ES_DEC = -1500; + /** + * 功率-100 <= p <= 100 + */ + int p; + /** + * 是否紧急制动 + */ + boolean eb; + /** + * 列车速度,单位mm/s */ int speed; /** @@ -48,4 +68,9 @@ public class SrTrain extends SrDevice { public boolean isNeutralGear() { return NEUTRAL == this.gear; } + + public void updatePositionAndSpeed(TrackPosition position, int v) { + this.position = position; + this.speed = v; + } } diff --git a/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/SrTurnout.java b/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/SrTurnout.java index d1ce898e2..a2aa90b8e 100644 --- a/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/SrTurnout.java +++ b/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/SrTurnout.java @@ -30,18 +30,27 @@ public class SrTurnout extends SrDevice { super(id, DeviceType.TURNOUT); } - public void setA(SrTrack a) { + public void setTracks(SrTrack a, SrTrack b, SrTrack c) { this.a = a; - a.setTurnout(this); - } - - public void setB(SrTrack b) { this.b = b; - b.setTurnout(this); + this.c = c; + if (this.a.leftTrack == null && this.a.rightTrack == null) { + throw new IllegalStateException("道岔a区段两端都没有关联的区段"); + } + if (this.a.leftTrack != null) { // a左侧存在 + this.a.setRightTrack(this.b); + this.a.setRightFlankTrack(this.c); + } else { // a右侧存在 + this.a.setLeftTrack(this.b); + this.a.setLeftFlankTrack(this.c); + } } - public void setC(SrTrack c) { - this.c = c; - c.setTurnout(this); + public boolean isNormalPosition() { + return NORMAL == this.state.get(); + } + + public boolean isReversePosition() { + return REVERSE == this.state.get(); } } diff --git a/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/SrdRepositoryBuilder.java b/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/SrdRepositoryBuilder.java index cc1d30af3..da737e772 100644 --- a/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/SrdRepositoryBuilder.java +++ b/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/SrdRepositoryBuilder.java @@ -43,13 +43,13 @@ public class SrdRepositoryBuilder { SrTrack left = trackMap.get(sectionVO.getLeftSectionCode()); BusinessExceptionAssertEnum.DATA_ERROR.assertNotNull(left, String.format("区段[%s]的左关联区段[%s]不存在", srTrack.getId(), sectionVO.getLeftSectionCode())); - srTrack.setLeft(left); + srTrack.setLeftTrack(left); } if (StringUtils.hasText(sectionVO.getRightSectionCode())) { SrTrack right = trackMap.get(sectionVO.getRightSectionCode()); BusinessExceptionAssertEnum.DATA_ERROR.assertNotNull(right, String.format("区段[%s]的右关联区段[%s]不存在", srTrack.getId(), sectionVO.getRightSectionCode())); - srTrack.setRight(right); + srTrack.setRightTrack(right); } // 构建轨道和计轴关系 SrAXC axc; @@ -91,9 +91,7 @@ public class SrdRepositoryBuilder { BusinessExceptionAssertEnum.DATA_ERROR.assertNotNull(c, String.format("道岔[%s]关联区段C[%s]不存在", switchVO.getCode(), switchVO.getSectionCCode())); SrTurnout turnout = turnoutMap.get(switchVO.getCode()); - turnout.setA(a); - turnout.setB(b); - turnout.setC(c); + turnout.setTracks(a, b, c); } } diff --git a/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/TrackPosition.java b/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/TrackPosition.java index 085912da4..087442a85 100644 --- a/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/TrackPosition.java +++ b/src/main/java/club/joylink/rtss/simulation/rt/srd/bo/TrackPosition.java @@ -3,4 +3,17 @@ package club.joylink.rtss.simulation.rt.srd.bo; public class TrackPosition { SrTrack track; int offset; + + public TrackPosition(SrTrack track, int offset) { + this.track = track; + this.offset = offset; + } + + public SrTrack getTrack() { + return track; + } + + public int getOffset() { + return offset; + } }