Files
FT546-WCS/docs/superpowers/specs/2026-07-30-wcs-dispatch-traffic-demo-design.md

9.0 KiB
Raw Permalink Blame History

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. 目录结构

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:端到端运行关键场景并验证真实事件结果。

验证命令:

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,不修改生产控制代码。