7.2 KiB
高压清洗机批量上料/下料/换料设计
背景
高压清洗机(设备ID=5,WASHER_HP)是2槽位 batch 设备。当前实现是"单次 Load + StartupWasher"模式,每次只上1个工件就启动清洗。
新需求:灵活策略 — 有2个待清洗工件就上满2个再启动,只有1个就上1个启动。批量完成后逐槽位判断卸载/换料,有 Exchange 或 Load 就追加 StartupWasher。
核心决策
- 启动策略:灵活 — 有2个待清洗就上满2个再启动,只有1个就上1个启动
- 完成信号:保持 batch 机制,一个信号 = 所有在加工槽位同时完成
- 上料方式:连续上料,中间无需等待
- 换料策略:逐槽位判断 — 有排队就 Exchange,没有就只卸载
- 启动判断:actions 中包含 Exchange 或 Load → 追加 StartupWasher;纯 Unload 不启动
方案选择
方案 A:调度器层面批量编排(已确认)
在 trySchedule dispatch 阶段,当发现 WASHER_HP 相关候选时,查询槽位状态和配对情况,编排 []RobotAction 数组一次性 dispatch。
理由:
- 符合现有架构(调度器驱动,EventLoop 串行处理)
- 不修改 Station 接口或 MockPLC 核心逻辑
handleMachineDone保持只改状态不编排
设计细节
1. RobotAction 数组
HardwareWorker.Execute 接口变更:
从 Execute(ctx, RobotAction) 改为 Execute(ctx, []RobotAction)。
Worker 串行执行数组中的每个 action,任一失败则中止后续 action,返回结果。
RobotWorker 适配:
func (w *RobotWorker) Execute(ctx context.Context, actions []action.RobotAction) error {
for _, act := range actions {
if err := w.executeSingle(ctx, act); err != nil {
return err
}
}
return nil
}
2. StartupWasher 作为 RobotAction
新增 StartupWasher 类型,与 Load/Unload/Exchange 同级。Worker 执行时调用 PLC 启动信号。
// action.RobotAction 中 Kind 字段新增值
case "startup_washer":
// 调用 robotCtrl.StartupWasher(ctx)
3. 上料编排
trySchedule dispatch 阶段新增逻辑:
当候选任务包含 WASHER_HP Load 时:
- 查询 WASHER_HP 槽位状态(空槽位数量)
- 检查是否有第二个待清洗工件(
jobRuntimes中StepType_Load + ResourceType=WASHER_HP + OnBuffer) - 编排
[]RobotAction:
| 条件 | actions |
|---|---|
| 1个空槽位 + 1个候选 | Load + StartupWasher |
| 2个空槽位 + 2个候选 | Load1 + Load2 + StartupWasher |
| 2个空槽位 + 1个候选 | Load + StartupWasher |
4. 卸载/换料编排
trySchedule dispatch 阶段新增逻辑:
当 dispatch 一个 WASHER_HP Unload 或 Exchange 时:
- 检查
batchMachines[machineID]是否为 true - 是 → 查询同设备另一个槽位状态
- 另一个槽位有 Done 工件 + 有配对 → 追加 Exchange
- 另一个槽位有 Done 工件 + 无配对 → 追加 Unload
- 另一个槽位空 + 有待上料工件 → 追加 Load
- 另一个槽位空 + 无待上料工件 → 不追加
- 否 → 正常单 action
完整场景表:
| 场景 | actions | 启动? |
|---|---|---|
| 2个 Done,0个配对 | Unload + Unload | 否 |
| 2个 Done,1个配对 | Exchange + Unload + StartupWasher | 是 |
| 2个 Done,2个配对 | Exchange + Exchange + StartupWasher | 是 |
| 1个 Done,0个配对 | Unload | 否 |
| 1个 Done,1个配对 | Exchange + Load + StartupWasher | 是 |
启动判断规则:actions 中包含 Exchange 或 Load → 追加 StartupWasher。纯 Unload 不追加。
5. handleWorkerResult 适配
Worker 返回结果后,handleWorkerResult 需要处理多 action 的结果:
- 每个 action 的状态变更(位置更新、步骤推进)按顺序处理
- Exchange 成功 → Done 工件放暂存台 + 新工件上料到槽位
- Unload 成功 → Done 工件放暂存台 + 释放槽位
- Load 成功 → 新工件上料到槽位
- StartupWasher 成功 → 无状态变更(仅 PLC 信号)
- 任一 action 失败 → 中止后续,已成功的 action 状态保留不变(不回滚),失败的 Job 标记为 ERROR
EquipmentSlot 一致性:每个 action 成功后立即更新 equipment_slot 表状态(通过 DBState),确保 DB SSOT 与实际状态一致。后续 action 失败时,已更新的槽位状态反映真实物理状态(工件已在槽位中或已离开)。
6. 时序保证
不存在"等第二个工件"的中间态。编排时已确定 Load 数量:
- 1个候选 →
Load + StartupWasher(上1个就启动,不等第二个) - 2个候选 →
Load1 + Load2 + StartupWasher(上满2个再启动)
Worker 串行执行,Load1 完成后立即执行 Load2,中间无等待。不存在"上了1个但还没启动,等第二个候选出现"的状态。
7. 卸载优先级
当 trySchedule 发现 WASHER_HP 有 Done 槽位时,立即处理,不等待更多 Done 槽位出现。1个 Done 就 dispatch 对应的 Unload/Exchange,2个 Done 就一起编排。batch 信号保证所有 Occupied 槽位同时变为 Done,不会出现"先1个 Done,稍后另1个 Done"的情况。
8. MarkAllOccupiedDone 对单槽位的正确性
MarkAllOccupiedDone() 将所有 Occupied 槽位标记为 Done。当只有1个 Occupied 槽位时,只标记那1个,空槽位不受影响。这与"1个 Done"场景一致,无需特殊处理。
9. MockPLC 适配
当前 MockPLC 的 washerDone atomic 标志是"首个上料触发计时"。新逻辑下:
StartupWasher作为独立 RobotAction,调用robotCtrl.StartupWasher(ctx)触发 PLC 启动信号- MockPLC 收到启动信号后开始 4s 计时,到期后触发 WasherDone
- MockPLC 核心逻辑不变:
triggerMachineDone中case 5的washerDoneatomic 防重复触发逻辑保留 executeLoadToMachine中machineID == 5时调用StartupWasher的逻辑移除,改为由[]RobotAction编排决定何时调用
10. batch_unload 移除
当前 candidateToRobotAction 中有 batch_unload 逻辑(检查 FindAllDoneJobsOnMachine > 1 时批量卸载)。新逻辑下:
- 卸载/换料由
tryScheduledispatch 阶段逐槽位编排 batch_unload逻辑移除executeBatchUnload方法保留(用于 Worker 串行执行多个 Unload action)
改动文件清单
| 文件 | 改动 |
|---|---|
internal/eventloop/worker.go |
Execute 接口改为接收 []RobotAction |
internal/processor/robot_worker.go |
适配新接口,串行执行 action 数组 |
internal/eventloop/loop.go |
trySchedule dispatch 阶段新增 WASHER_HP 槽位查询 + 批量编排逻辑 |
internal/eventloop/loop.go |
handleWorkerResult 适配多 action 结果处理 |
internal/processor/robot_worker.go |
移除 executeLoadToMachine 中 machineID==5 的 StartupWasher 调用 |
internal/robot/washer.go |
新增 StartupWasher RobotAction 执行逻辑 |
internal/action/ |
RobotAction Kind 新增 "startup_washer" |
不改动的部分
handleMachineDone— 只改状态,不编排WasherStation— 槽位管理逻辑不变- MockPLC 核心逻辑 — 不变
- 调度器 Generator/Filter/Policy — 候选任务生成逻辑不变