Browse Source

进路计算

zhanghaijun 2 years ago
parent
commit
9fba73a1ab

+ 32 - 20
pom.xml

@@ -30,7 +30,6 @@
     <modules>
         <module>train-common</module>
         <module>train-server</module>
-        <module>train-demo</module>
     </modules>
 
     <!-- 依赖声明 -->
@@ -136,6 +135,19 @@
                     <useDefaultDelimiters>false</useDefaultDelimiters>
                 </configuration>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.11.0</version>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                    <compilerArgs>
+                        <compilerArg>-parameters</compilerArg>
+                    </compilerArgs>
+                </configuration>
+            </plugin>
+
         </plugins>
         <pluginManagement>
             <plugins>
@@ -193,25 +205,25 @@
                         </execution>
                     </executions>
                 </plugin>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-assembly-plugin</artifactId>
-                        <version>3.3.0</version>
-                        <configuration>
-                            <appendAssemblyId>false</appendAssemblyId>
-                            <descriptors>
-                                <descriptor>src/assembly/assembly.xml</descriptor>
-                            </descriptors>
-                            <outputDirectory>target</outputDirectory>
-                        </configuration>
-                        <executions>
-                            <execution>
-                                <phase>package</phase>
-                                <goals>
-                                    <goal>single</goal>
-                                </goals>
-                            </execution>
-                        </executions>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-assembly-plugin</artifactId>
+                    <version>3.3.0</version>
+                    <configuration>
+                        <appendAssemblyId>false</appendAssemblyId>
+                        <descriptors>
+                            <descriptor>src/assembly/assembly.xml</descriptor>
+                        </descriptors>
+                        <outputDirectory>target</outputDirectory>
+                    </configuration>
+                    <executions>
+                        <execution>
+                            <phase>package</phase>
+                            <goals>
+                                <goal>single</goal>
+                            </goals>
+                        </execution>
+                    </executions>
                 </plugin>
             </plugins>
         </pluginManagement>

+ 3 - 2
train-common/train-common-websocket/src/main/java/top/haijunit/websocket/utils/WebSocketUtils.java

@@ -30,7 +30,9 @@ public class WebSocketUtils {
     }
 
     public static void sendMessage(String message) {
-        WebSocketSessionHolder.getSessionsAll().forEach(item -> sendMessage(item, message));
+        for (String item : WebSocketSessionHolder.getSessionsAll()) {
+            sendMessage(item, message);
+        }
     }
 
     public static void sendMessage(WebSocketSession session, String message) {
@@ -43,7 +45,6 @@ public class WebSocketUtils {
         } else {
             try {
                 session.sendMessage(message);
-                log.info("[websocket] sessionId: {},message:{}", session.getId(), message);
             } catch (IOException e) {
                 log.error("[websocket] session({}) 发送消息({}) 异常", session, message, e);
             }

+ 2 - 0
train-server/src/main/java/top/haijunit/train/TrainServerMain.java

@@ -3,12 +3,14 @@ package top.haijunit.train;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
+import org.springframework.scheduling.annotation.EnableScheduling;
 
 /**
  * @author zhang
  * @date 2023/11/22 22:50
  * @description 启动类
  */
+@EnableScheduling
 @SpringBootApplication
 public class TrainServerMain {
     public static void main(String[] args) {

+ 4 - 4
train-server/src/main/java/top/haijunit/train/domain/constant/RouteStatusEnum.java

@@ -10,15 +10,15 @@ import java.util.Objects;
 /**
  * @author zhang
  * @date 2023/11/20 23:33
- * @description 进路状态 占用(红光带)、出清/空闲(灰光带)、锁闭(白光带)
+ * @description 进路状态
  */
 @Getter
 @AllArgsConstructor
 public enum RouteStatusEnum {
 
-    OCCUPY(1, "占用"),
-    IDLE(2, "出清"),
-    LOCK(3, "锁闭");
+    OCCUPY(1, "占用(红光带)"),
+    IDLE(2, "出清/空闲(灰光带)"),
+    LOCK(3, "锁闭(白光带)");
 
     @JsonValue
     private final Integer code;

+ 1 - 1
train-server/src/main/java/top/haijunit/train/domain/constant/SwitchStateConverter.java

@@ -14,7 +14,7 @@ import java.util.Optional;
 public class SwitchStateConverter implements AttributeConverter<SwitchStateEnum, Integer> {
     @Override
     public Integer convertToDatabaseColumn(SwitchStateEnum state) {
-        return Optional.of(state).map(SwitchStateEnum::getCode).orElse(SwitchStateEnum.Forward.getCode());
+        return Optional.of(state).map(SwitchStateEnum::getCode).orElse(SwitchStateEnum.LOCATE.getCode());
     }
 
     @Override

+ 3 - 1
train-server/src/main/java/top/haijunit/train/domain/constant/SwitchStateEnum.java

@@ -16,7 +16,9 @@ import java.util.Objects;
 @AllArgsConstructor
 public enum SwitchStateEnum {
 
-    Forward(1, "正向"), reverse(1, "侧向");
+    LOCATE(1, "定位"),
+    REVERSE(2, "反位"),
+    MISSING(3, "失标");
 
     @JsonValue
     private final Integer code;

+ 24 - 0
train-server/src/main/java/top/haijunit/train/domain/constant/TrainConstant.java

@@ -0,0 +1,24 @@
+package top.haijunit.train.domain.constant;
+
+import java.math.BigDecimal;
+
+/**
+ * @author zhanghaijun
+ * @date 2023/11/28 06:27
+ * @description 列车行驶常量
+ */
+public interface TrainConstant {
+
+    // 全线列车限速默认为80km/h
+    BigDecimal SPEED_LIMIT = new BigDecimal(80);
+    // 列车加速度固定为0.8 m/s2
+    BigDecimal ACCELERATION_LIMIT = new BigDecimal("0.8");
+    // 制动减速度固定为-0.6 m/s2
+    BigDecimal DECELERATION_LIMIT = new BigDecimal("-0.6");
+    // 惰行减速度固定为-0.05 m/s2
+    BigDecimal SLOW_DOWN_LIMIT = new BigDecimal("-0.05");
+    // 列车停站时间统一为30s
+    BigDecimal STOP_TIME_SECOND = new BigDecimal(30);
+    // 道岔转换要维持3S
+    BigDecimal SWITCH_CHANGE_TIME_SECOND = new BigDecimal(3);
+}

+ 2 - 2
train-server/src/main/java/top/haijunit/train/domain/entity/RouteEntity.java

@@ -70,7 +70,7 @@ public class RouteEntity implements Serializable {
         if (StrUtil.isBlank(this.getSwitchState())) {
             return new ArrayList<>();
         }
-        return StrUtil.split(this.getSwitchState(), "-").stream().map(item -> SwitchStateEnum.getByCode(Convert.toInt(item, SwitchStateEnum.Forward.getCode()))).collect(Collectors.toCollection(ArrayList::new));
+        return StrUtil.split(this.getSwitchState(), "-").stream().map(item -> SwitchStateEnum.getByCode(Convert.toInt(item, SwitchStateEnum.LOCATE.getCode()))).collect(Collectors.toCollection(ArrayList::new));
     }
 
     public Map<Long, SwitchStateEnum> getSwitchMap() {
@@ -78,7 +78,7 @@ public class RouteEntity implements Serializable {
         ArrayList<SwitchStateEnum> switchStateList = this.getSwitchStateList();
         Map<Long, SwitchStateEnum> map = new HashMap<>();
         for (int i = 0; i < switchList.size(); i++) {
-            map.put(switchList.get(i), Optional.of(CollUtil.get(switchStateList, i)).orElse(SwitchStateEnum.Forward));
+            map.put(switchList.get(i), Optional.of(CollUtil.get(switchStateList, i)).orElse(SwitchStateEnum.LOCATE));
         }
         return map;
     }

+ 3 - 0
train-server/src/main/java/top/haijunit/train/domain/entity/SelectionEntity.java

@@ -6,6 +6,7 @@ import jakarta.persistence.GenerationType;
 import jakarta.persistence.Id;
 import lombok.Data;
 import top.haijunit.train.domain.constant.DirectionEnum;
+import top.haijunit.train.domain.constant.RouteStatusEnum;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
@@ -38,4 +39,6 @@ public class SelectionEntity implements Serializable {
     private Boolean zfState;
     // 所属车站编号
     private Long stationId;
+    // 区段状态
+    private RouteStatusEnum status;
 }

+ 11 - 4
train-server/src/main/java/top/haijunit/train/domain/entity/SwitchEntity.java

@@ -1,13 +1,13 @@
 package top.haijunit.train.domain.entity;
 
-import jakarta.persistence.Entity;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.GenerationType;
-import jakarta.persistence.Id;
+import jakarta.persistence.*;
 import lombok.Data;
+import top.haijunit.train.domain.constant.SwitchStateEnum;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
+import java.time.LocalTime;
+import java.time.temporal.ChronoUnit;
 
 /**
  * @author zhang
@@ -38,4 +38,11 @@ public class SwitchEntity implements Serializable {
     private Long switchTie;
     // 所属车站编号
     private Long stationId;
+
+    // 道岔状态的更新时间,默认为一小时前
+    @Transient
+    private LocalTime updateStateTime = LocalTime.now().minusHours(1);
+    // 道岔的状态
+    @Transient
+    private SwitchStateEnum state = SwitchStateEnum.REVERSE;
 }

+ 2 - 0
train-server/src/main/java/top/haijunit/train/listener/ReportTimeHandle.java

@@ -1,5 +1,6 @@
 package top.haijunit.train.listener;
 
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
@@ -13,6 +14,7 @@ import top.haijunit.train.socket.TrainWebSocketUtils;
  * @date 2023/11/27 17:50
  * @description 上报数据得定时器
  */
+@Slf4j
 @Component
 public class ReportTimeHandle {
 

+ 50 - 14
train-server/src/main/java/top/haijunit/train/simulation/TrainComputerService.java

@@ -4,10 +4,14 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import top.haijunit.train.domain.constant.RouteStatusEnum;
+import top.haijunit.train.domain.constant.SignalStateEnum;
+import top.haijunit.train.domain.constant.SwitchStateEnum;
 import top.haijunit.train.domain.entity.RouteEntity;
 import top.haijunit.train.domain.repository.RouteRepository;
 
 import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.List;
 
 /**
  * @author zhanghaijun
@@ -21,22 +25,54 @@ public class TrainComputerService {
 
     private final RouteRepository routeRepository;
 
-
-    public void run(TrainItem train) {
-        for (RouteEntity route : routeRepository.findAll()) {
-            BigDecimal nextPrePosition = train.getKilometer().add(new BigDecimal(100));
-            if (!route.isTrigger(train.getKilometer(), nextPrePosition)) {
-                continue;
-            }
-            if (!route.getRouteStatus().equals(RouteStatusEnum.IDLE)) {
-                continue;
+    public void routeCompute() {
+        Collection<TrainItem> trainItems = TrainSimulationHolder.getTrainItem();
+        List<RouteEntity> routeList = routeRepository.findAll();
+        // 1、数据库初始化,所以进路状态都是空闲状态
+        // 2、遍历所有车辆,车辆是否占用此进路,占用则改变状态为占用
+        // 3、遍历所有车辆,判断是否在MA范围内,标识状态为锁定
+        // 4、遍历所有车辆,判断是否需要触发进路,触发则改变状态为锁定
+        for (RouteEntity route : routeList) {
+            for (TrainItem train : trainItems) {
+                // TODO 假设向前走100米
+                BigDecimal nextPrePosition = train.getKilometer().add(new BigDecimal(100));
+                if (!route.isTrigger(train.getKilometer(), nextPrePosition)) {
+                    continue;
+                }
+                // a)检查进路当前是否为出清/空闲状态,否则返回触发失败;
+                if (!route.getRouteStatus().equals(RouteStatusEnum.IDLE)) {
+                    continue;
+                }
+                if (!route.getSwitchList().isEmpty()) {
+                    // b)检查进路中道岔状态是否与进路要求的状态一致
+                    if (!route.getSwitchStateList().stream().allMatch(switchState -> switchState.equals(SwitchStateEnum.REVERSE))) {
+                        // 切换道岔状态
+                        continue;
+                    }
+                }
+                // c)出清(如果包括道岔,道岔已就位),将进路至于锁闭状态
+                RouteEntity nextRoute = nextRoute(route.getId());
+                if (null == nextRoute) {
+                    continue;
+                }
+                nextRoute.setRouteStatus(RouteStatusEnum.LOCK);
+                // d)将进路的信号状态置为红色
+                nextRoute.setSignalState(String.valueOf(SignalStateEnum.RED_YELLOW.getCode()));
             }
-            if (!route.getSwitchList().isEmpty()) {
-                // TODO 出清且包含到拆
-            } else {
-                // TODO 出清且不包括到道岔
-                route.setRouteStatus(RouteStatusEnum.OCCUPY);
+        }
+    }
+
+    private RouteEntity nextRoute(Long id) {
+        List<RouteEntity> routeList = routeRepository.findAll();
+        for (int i = 0; i < routeList.size(); i++) {
+            if (routeList.get(i).getId().equals(id)) {
+                if (i == routeList.size() - 1) {
+                    return routeList.get(0);
+                } else {
+                    return routeList.get(i + 1);
+                }
             }
         }
+        return null;
     }
 }

+ 4 - 3
train-server/src/main/resources/db/changelog/db-server-train.xml

@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <databaseChangeLog
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
-        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+    xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">
 
     <changeSet id="db_signal" author="zhanghaijun" failOnError="false" runOnChange="true">
         <createTable tableName="db_signal" schemaName="${schema.name}" remarks="信号灯">
@@ -111,6 +111,7 @@
             <column name="direction" type="${number.type}" defaultValueNumeric="1" remarks="上下行"/>
             <column name="zf_state" type="boolean" defaultValueBoolean="false" remarks="折返标志"/>
             <column name="station_id" type="${autoing.type}" defaultValueNumeric="0" remarks="所属车站编号"/>
+            <column name="status" type="${number.type}" defaultValueNumeric="2" remarks="状态"/>
         </createTable>
     </changeSet>
     <changeSet id="load-selection-data" author="zhanghaijun" failOnError="false" runOnChange="true">

+ 38 - 38
train-server/src/main/resources/db/changelog/db_selection.txt

@@ -1,41 +1,41 @@
-id,name,start_kilometer,selection_length,pre_id,next_id,direction,zf_state,station_id
-103001,T0101,0,150,-1,103002,1,1,104001
-103002,T0103-1,150,50,103001,103003,1,0,104001
-103003,T0103-2,200,200,103002,103004,1,0,104001
-103004,T0103-3,400,50,103003,103005,1,0,104001
-103005,T0105,450,145.63,103004,103006,1,0,104001
-103006,T0107,595.63,3000,103005,103007,1,0,104001
-103007,T0203,3595.63,145.63,103006,103008,1,0,104002
-103008,T0205,3741.26,3000,103007,103009,1,0,104002
-103009,T0301,6741.26,145.63,103008,103010,1,0,104003
-103010,T0303-1,6886.89,50,103009,103011,1,0,104003
-103011,T0303-2,6936.89,200,103010,103012,1,0,104003
-103012,T0303-3,7136.89,50,103011,103013,1,0,104003
-103013,T0305,7186.89,150,103012,-1,1,1,104003
-
-103014,T0102,0,150,-1,103015,2,1,104001
-103015,T0104-1,150,50,103014,103016,2,0,104001
-103016,T0104-2,200,200,103015,103017,2,0,104001
-103017,T0104-3,400,50,103016,103018,2,0,104001
-103018,T0106,450,145.63,103017,103019,2,0,104001
-103019,T0108,595.63,3000,103018,103020,2,0,104001
-103020,T0202,3595.63,145.63,103019,103021,2,0,104002
-103021,T0204,3741.26,3000,103020,103022,2,0,104002
-103022,T0302,6741.26,145.63,103021,103023,2,0,104003
-103023,T0304-1,6886.89,50,103022,103024,2,0,104003
-103024,T0304-2,6936.89,200,103023,103025,2,0,104003
-103025,T0304-3,7136.89,50,103024,103026,2,0,104003
-103026,T0306,7186.89,150,103025,-1,2,1,104003
-
-103027,T0109,200,141.42,103002,103028,2,0,104001
-103028,T0110,300,141.42,103027,103017,2,0,104001
-103029,T0112,200,141.42,103015,103030,1,0,104001
-103030,T0111,300,141.42,103029,103004,1,0,104001
-
-103031,T0307,6936.89,141.42,103010,103032,2,0,104003
-103032,T0308,7036.89,141.42,103031,103025,2,0,104003
-103033,T0310,6936.89,141.42,103023,103034,1,0,104003
-103034,T0309,7036.89,141.42,103033,103012,1,0,104003
+id,name,start_kilometer,selection_length,pre_id,next_id,direction,zf_state,status,station_id
+103001,T0101,0,150,-1,103002,1,1,2,104001
+103002,T0103-1,150,50,103001,103003,1,0,2,104001
+103003,T0103-2,200,200,103002,103004,1,0,2,104001
+103004,T0103-3,400,50,103003,103005,1,0,2,104001
+103005,T0105,450,145.63,103004,103006,1,0,2,104001
+103006,T0107,595.63,3000,103005,103007,1,0,2,104001
+103007,T0203,3595.63,145.63,103006,103008,1,0,2,104002
+103008,T0205,3741.26,3000,103007,103009,1,0,2,104002
+103009,T0301,6741.26,145.63,103008,103010,1,0,2,104003
+103010,T0303-1,6886.89,50,103009,103011,1,0,2,104003
+103011,T0303-2,6936.89,200,103010,103012,1,0,2,104003
+103012,T0303-3,7136.89,50,103011,103013,1,0,2,104003
+103013,T0305,7186.89,150,103012,-1,1,1,2,104003
+
+103014,T0102,0,150,-1,103015,2,1,2,104001
+103015,T0104-1,150,50,103014,103016,2,0,2,104001
+103016,T0104-2,200,200,103015,103017,2,0,2,104001
+103017,T0104-3,400,50,103016,103018,2,0,2,104001
+103018,T0106,450,145.63,103017,103019,2,0,2,104001
+103019,T0108,595.63,3000,103018,103020,2,0,2,104001
+103020,T0202,3595.63,145.63,103019,103021,2,0,2,104002
+103021,T0204,3741.26,3000,103020,103022,2,0,2,104002
+103022,T0302,6741.26,145.63,103021,103023,2,0,2,104003
+103023,T0304-1,6886.89,50,103022,103024,2,0,2,104003
+103024,T0304-2,6936.89,200,103023,103025,2,0,2,104003
+103025,T0304-3,7136.89,50,103024,103026,2,0,2,104003
+103026,T0306,7186.89,150,103025,-1,2,1,2,104003
+
+103027,T0109,200,141.42,103002,103028,2,0,2,104001
+103028,T0110,300,141.42,103027,103017,2,0,2,104001
+103029,T0112,200,141.42,103015,103030,1,0,2,104001
+103030,T0111,300,141.42,103029,103004,1,0,2,104001
+
+103031,T0307,6936.89,141.42,103010,103032,2,0,2,104003
+103032,T0308,7036.89,141.42,103031,103025,2,0,2,104003
+103033,T0310,6936.89,141.42,103023,103034,1,0,2,104003
+103034,T0309,7036.89,141.42,103033,103012,1,0,2,104003
 
 
 

+ 12 - 11
train-web/src/pages/train/index.vue

@@ -19,10 +19,9 @@ storeTrain.updateSignal();
 storeTrain.updateSelection();
 storeTrain.updateSwitch();
 
-console.log(storeSocket.getTrainList);
-watch(() => storeSocket.trainList, (newValue, oldValue) => {
-  console.log('Data changed:', oldValue, '->', newValue);
-});
+// watch(() => storeSocket.trainList, (newValue, oldValue) => {
+//   console.log('Data changed:', oldValue, '->', newValue);
+// });
 
 onMounted(() => {
   const canvas: HTMLCanvasElement | undefined = canvasRef.value;
@@ -54,13 +53,15 @@ onMounted(() => {
   // 绘制道岔
   drawTrack.drawSwitchList(storeTrain.getSwitchList);
 
-  let trainList = storeSocket.trainList;
-  for (let i = 0; i < trainList.length; i++) {
-    const item: TrainItem = trainList[i];
-    // 绘制列车
-    const drawTrain = new DrewTrain(ctx);
-    drawTrain.draw(Number(item.kilometer), item.direction == 1);
-  }
+  setTimeout(() => {
+    let trainList = storeSocket.trainList;
+    for (let i = 0; i < trainList.length; i++) {
+      const item: TrainItem = trainList[i];
+      // 绘制列车
+      const drawTrain = new DrewTrain(ctx);
+      drawTrain.draw(Number(item.kilometer), item.direction == 1);
+    }
+  }, 1000);
   // // 绘制列车
   // const drawTrain = new DrewTrain(ctx);
   // drawTrain.draw(453, 100);