docs: design wcs dispatch traffic demo
This commit is contained in:
@@ -0,0 +1,258 @@
|
||||
# WCS 中心调度与交通管制 Demo 设计
|
||||
|
||||
## 1. 背景与目标
|
||||
|
||||
本设计依据 `01-P0-A现有链路稳固实施计划.md`,在 `FT546-WCS` 优化工作树根目录新增独立的 `javaTest` Maven 项目,用纯 Java 内存模型模拟 WCS 中心调度与交通管制。
|
||||
|
||||
Demo 的目标是:
|
||||
|
||||
1. 建立一个可运行的调度中心,模拟每周期任务准入、车辆分配、路径规划、交通管制、任务下发和完成。
|
||||
2. 用真实 JUnit 5 测试覆盖关键调度规则,确保测试数量大于 0。
|
||||
3. 固化当前 LEGACY 链路的重要语义,为后续从 `BaseSRgvThread` 提取可测试边界提供参考。
|
||||
4. 输出可读的控制台事件,使开发人员能观察每个周期的决策原因和状态变化。
|
||||
|
||||
## 2. 范围与约束
|
||||
|
||||
### 2.1 范围内
|
||||
|
||||
- 独立 Maven 项目 `javaTest`。
|
||||
- Java 8 源码兼容。
|
||||
- JUnit 5 自动测试。
|
||||
- 内存车辆快照、业务任务、调度队列、地图和事件记录。
|
||||
- 每周期一次任务准入。
|
||||
- 确定性车辆选择。
|
||||
- 网格最短路径、路径占用和通道占用。
|
||||
- 避让任务生成。
|
||||
- 模拟协议下发与队列状态流转。
|
||||
- 命令行 Demo 场景。
|
||||
|
||||
### 2.2 范围外
|
||||
|
||||
- 不修改生产 `BaseSRgvThread`、`PlcSrgvRead` 或数据库表。
|
||||
- 不连接 SQL Server、PLC、WMS 或 Spring 容器。
|
||||
- 不发送真实 PLC 指令。
|
||||
- 不建立生产中央路权服务,不写交通运行表。
|
||||
- 不启用 SHADOW 或 ACTIVE 模式。
|
||||
- 不使用 `default02` 至 `default08` 保存新增交通状态。
|
||||
- 不猜测 PLC 寄存器偏移或载货字段布局。
|
||||
|
||||
Demo 中的“调度中心”只协调内存任务、车辆与路径,不改变 P0-A 的 LEGACY 生产控制边界。
|
||||
|
||||
## 3. 方案选择
|
||||
|
||||
采用独立 Maven 项目,而不是加入现有 Reactor 或直接放入 `ruoyi-admin/src/test`。
|
||||
|
||||
理由:
|
||||
|
||||
- 可独立运行,不污染生产 Reactor 和依赖关系。
|
||||
- 不需要 Spring、MyBatis、HslCommunication 或数据库。
|
||||
- 能强制使用 JUnit 5 和现代 Surefire,避免现有工程“构建成功但测试数为 0”的假阳性。
|
||||
- 后续可把验证成熟的纯领域服务迁移到生产模块。
|
||||
|
||||
## 4. 目录结构
|
||||
|
||||
```text
|
||||
javaTest/
|
||||
├── pom.xml
|
||||
├── README.md
|
||||
└── src/
|
||||
├── main/java/com/ft546/wcs/demo/
|
||||
│ ├── DemoApplication.java
|
||||
│ ├── center/
|
||||
│ ├── model/
|
||||
│ ├── repository/
|
||||
│ ├── traffic/
|
||||
│ └── simulation/
|
||||
└── test/java/com/ft546/wcs/demo/
|
||||
```
|
||||
|
||||
包边界如下:
|
||||
|
||||
- `model`:不可变输入快照和明确的状态枚举。
|
||||
- `center`:调度周期、任务准入和车辆选择。
|
||||
- `traffic`:路径规划、资源占用与避让决策。
|
||||
- `repository`:内存任务、队列和历史。
|
||||
- `simulation`:场景构造、周期推进和事件输出。
|
||||
|
||||
## 5. 核心模型
|
||||
|
||||
### 5.1 车辆快照
|
||||
|
||||
`VehicleSnapshot` 至少包含:
|
||||
|
||||
- `vehicleId`
|
||||
- `floor`
|
||||
- `currentSite`
|
||||
- `workMode`
|
||||
- `status`
|
||||
- `battery`
|
||||
- `connected`
|
||||
- `allowSend`
|
||||
- `cargo`
|
||||
|
||||
快照不可变。车辆只有同时满足在线、自动模式 `workMode=5`、空闲 `status=1`、允许下发且电量大于 30 时才具备普通任务资格。
|
||||
|
||||
### 5.2 业务任务
|
||||
|
||||
`DispatchTask` 包含:
|
||||
|
||||
- `taskId`
|
||||
- `type`
|
||||
- `sourceSite`
|
||||
- `targetSite`
|
||||
- `floor`
|
||||
- `priority`
|
||||
- `state`
|
||||
|
||||
Demo 支持入库、出库和移库的统一调度输入,但不模拟真实 WMS 回调。
|
||||
|
||||
### 5.3 调度队列
|
||||
|
||||
`DispatchQueueEntry` 使用明确字段表达:
|
||||
|
||||
- `taskId`
|
||||
- `vehicleId`
|
||||
- `queueType`
|
||||
- `startSite`
|
||||
- `endSite`
|
||||
- `priority`
|
||||
- `issued`
|
||||
- `executionStatus`
|
||||
- `path`
|
||||
|
||||
状态语义与旧链路保持一致:
|
||||
|
||||
- 新建:`issued=0`、`executionStatus=1`
|
||||
- 下发成功:`issued=1`、`executionStatus=3`
|
||||
- 完成:`executionStatus=4`,随后归档并从活动队列删除
|
||||
|
||||
避让任务使用 `queueType=AVOIDANCE` 和优先级 9,不把新增交通状态塞入旧扩展字段。
|
||||
|
||||
## 6. 调度中心
|
||||
|
||||
`LegacyDispatchCenter.runCycle()` 是每个模拟周期的唯一入口,固定顺序为:
|
||||
|
||||
1. 冻结当轮车辆快照,并按 `vehicleId` 排序。
|
||||
2. 调用一次 `QueueAdmissionService.createPendingQueues()`。
|
||||
3. 对未分配业务任务调用 `VehicleAssignmentService.select()`。
|
||||
4. 对每辆车处理已有队列。
|
||||
5. 调用 `TrafficController.plan()` 获得路径、等待或避让决策。
|
||||
6. 通过 `SimulatedProtocolAdapter` 模拟指令下发。
|
||||
7. 根据车辆位置推进队列完成和历史归档。
|
||||
|
||||
无论车辆数是多少,每周期业务准入只能调用一次。
|
||||
|
||||
## 7. 确定性车辆选择
|
||||
|
||||
车辆选择采用稳定比较顺序:
|
||||
|
||||
1. 不符合资格的车辆排除,并记录排除原因。
|
||||
2. 同楼层优先。
|
||||
3. 绝对楼层差更小者优先。
|
||||
4. 保留旧链路的 Y 距离优先、X 距离次优语义。
|
||||
5. 全部相同时,`vehicleId` 字典序更小者优先。
|
||||
|
||||
站点编码必须能解析为坐标。编码无效时返回 `REJECT_INVALID_SITE`,不得按坐标 0 静默参与比较。
|
||||
|
||||
`VehicleAssignmentDecision` 必须包含被选车辆和可读的选择理由;没有可用车辆时返回明确的 HOLD 决策。
|
||||
|
||||
## 8. 交通管制
|
||||
|
||||
### 8.1 地图与路径
|
||||
|
||||
`GridMap` 保存可通行点及站点坐标。`GridPathPlanner` 使用确定性最短路径算法,只允许通过可通行节点。
|
||||
|
||||
每次规划前,`TrafficController` 从当前内存状态构建占用视图:
|
||||
|
||||
- 锁定其他车辆队列中从其当前位置开始的剩余路径。
|
||||
- 锁定离线车辆当前位置。
|
||||
- 锁定场景中声明不可用的提升机或障碍点。
|
||||
|
||||
占用视图只存在于当前模拟周期,不写数据库。
|
||||
|
||||
### 8.2 通道与路径冲突
|
||||
|
||||
如果目标通道存在同层阻挡车辆:
|
||||
|
||||
- 阻挡车辆没有活动队列时,为其生成高优先级避让任务。
|
||||
- 当前业务任务返回 `HOLD_CHANNEL_BLOCKED`。
|
||||
- 避让任务完成并删除后,下一周期重新规划。
|
||||
|
||||
如果路径被其他车辆占用但存在替代路线,则规划绕行;没有替代路线时返回 `HOLD_NO_PATH`。
|
||||
|
||||
同一阻挡车辆在已有避让队列时不得重复创建避让任务。
|
||||
|
||||
## 9. 协议模拟与状态流转
|
||||
|
||||
`SimulatedProtocolAdapter` 只记录命令,不进行 I/O。它支持成功和可注入失败两种结果:
|
||||
|
||||
- 成功时,队列更新为 `issued=1`、`executionStatus=3`。
|
||||
- 失败时,队列保持未下发状态,并记录 `HOLD_PROTOCOL_FAILURE` 及失败原因。
|
||||
- 同一队列已成功下发后不得重复发送。
|
||||
|
||||
模拟器把车辆移动到路径下一站。到达目标站后:
|
||||
|
||||
- 普通任务归档业务历史并删除活动队列。
|
||||
- 避让任务只归档避让事件并删除活动队列。
|
||||
- 删除队列后,其路径占用在下一周期自然释放。
|
||||
|
||||
## 10. 错误处理
|
||||
|
||||
Demo 使用决策结果表达预期异常,不使用空值表示失败:
|
||||
|
||||
- `HOLD_NO_ELIGIBLE_VEHICLE`
|
||||
- `REJECT_INVALID_SITE`
|
||||
- `HOLD_NO_PATH`
|
||||
- `HOLD_CHANNEL_BLOCKED`
|
||||
- `HOLD_PROTOCOL_FAILURE`
|
||||
|
||||
构造时拒绝重复任务号、重复车辆号和缺失地图站点。不可恢复的模型错误抛出 `IllegalArgumentException`;调度等待条件作为正常决策返回。
|
||||
|
||||
## 11. 模拟场景
|
||||
|
||||
`DemoApplication` 至少运行以下场景:
|
||||
|
||||
1. 三辆车、一个业务任务:证明每周期只准入一次,并稳定选出车辆。
|
||||
2. 同层与跨层车辆竞争:证明同层、楼层差、Y/X 距离和车辆编号裁决。
|
||||
3. 其他车辆剩余路径占用:证明绕行或等待。
|
||||
4. 同通道阻挡:生成优先级 9 的避让任务,当前车等待。
|
||||
5. 避让完成:删除避让队列,下一周期原任务重新规划并下发。
|
||||
6. 无可达路径:返回 `HOLD_NO_PATH`,不抛异常。
|
||||
7. 协议失败后重试:第一次保持未下发,下一周期成功进入执行中。
|
||||
8. 到达目标:队列完成、归档并释放路径。
|
||||
|
||||
控制台按周期输出任务、车辆、选车原因、路径、HOLD 原因、队列状态和历史结果。
|
||||
|
||||
## 12. 自动测试
|
||||
|
||||
JUnit 5 测试至少覆盖:
|
||||
|
||||
- `LegacyDispatchCenterTest`:三车每周期只准入一次、稳定处理顺序。
|
||||
- `VehicleAssignmentServiceTest`:资格过滤、同层优先、楼层差、Y/X 距离、稳定裁决和无效站点。
|
||||
- `TrafficControllerTest`:路径锁、离线点、绕行、无路、通道阻挡、避让去重和释放。
|
||||
- `QueueLifecycleTest`:新建、下发、失败重试、完成归档和幂等。
|
||||
- `DemoScenarioTest`:端到端运行关键场景并验证真实事件结果。
|
||||
|
||||
验证命令:
|
||||
|
||||
```bash
|
||||
cd javaTest
|
||||
mvn test
|
||||
mvn exec:java
|
||||
```
|
||||
|
||||
验收时必须从 Surefire 报告确认测试数量大于 0、失败数为 0、错误数为 0;不能只依据 Maven 退出码。
|
||||
|
||||
## 13. 验收标准
|
||||
|
||||
满足以下条件才认为 Demo 完成:
|
||||
|
||||
1. 工作树根目录存在独立 `javaTest` Maven 项目。
|
||||
2. 源码编译目标为 Java 8。
|
||||
3. 调度中心真实执行每周期一次准入和逐车处理。
|
||||
4. 确定性选车规则及理由可测试。
|
||||
5. 交通管制能处理路径锁、通道阻挡、避让任务和占用释放。
|
||||
6. 队列状态按 LEGACY 语义流转。
|
||||
7. `DemoApplication` 可运行并打印完整模拟结果。
|
||||
8. JUnit 5 测试数量大于 0,全部通过。
|
||||
9. 项目不访问真实数据库、PLC 或 WMS,不修改生产控制代码。
|
||||
Reference in New Issue
Block a user