115 lines
4.4 KiB
Markdown
115 lines
4.4 KiB
Markdown
# 扫码失败废料搬运流程
|
||||
|
|
|
|||
|
|
**日期**: 2026-05-20
|
|||
|
|
**状态**: 已确认
|
|||
|
|
**类型**: 新功能
|
|||
|
|
|
|||
|
|
## 1. 概述
|
|||
|
|
|
|||
|
|
从接驳台取料扫码后,如果扫码失败,工件放到暂存台(状态 `WAITING_WASTE`),等 `WasteReady` 信号为 true 时搬运到废料台,释放暂存台槽位,Job 标记为 `SCRAPPED`。
|
|||
|
|
|
|||
|
|
### 流程
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
接驳台取料 → 扫码失败 → 放入暂存台(WAITING_WASTE) → 等待 WasteReady → 搬运至废料台 → 释放暂存台槽位 → Job SCRAPPED
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 2. 涉及模块
|
|||
|
|
|
|||
|
|
| 模块 | 改动 |
|
|||
|
|
|------|------|
|
|||
|
|
| `constants/constants.go` | 新增 `JobStatus_WaitingWaste` |
|
|||
|
|
| `schema/job.go` | ent 枚举更新(先改,再 `go generate`) |
|
|||
|
|
| `internal/processor/replenisher.go` | 扫码失败时写 `WAITING_WASTE` + alarm |
|
|||
|
|
| `internal/processor/scheduler/types.go` | `SystemState` 新增 `WasteReady bool` |
|
|||
|
|
| `internal/processor/eventloop/scheduler_bridge.go` | 快照读取 WasteReady 信号 |
|
|||
|
|
| `internal/processor/scheduler/generator.go` | 为 WAITING_WASTE job 生成废料搬运任务 |
|
|||
|
|
| `internal/processor/robot_worker.go` | 新增 `executeLoadToWaste` 分发 |
|
|||
|
|
| `internal/robot/dock.go` | 新增 `PlaceWorkpieceToWasteStation`(M1140) |
|
|||
|
|
| `internal/processor/eventloop/worker_dispatch.go` | 废料搬运完成后 ScrapJob + ReleaseSlot |
|
|||
|
|
|
|||
|
|
## 3. 详细设计
|
|||
|
|
|
|||
|
|
### 3.1 Job 状态
|
|||
|
|
|
|||
|
|
新增 `JobStatus_WaitingWaste = "WAITING_WASTE"`。
|
|||
|
|
|
|||
|
|
- **PositionType**: `ON_BUFFER`(工件物理占用暂存台槽位)
|
|||
|
|
- **SuspendedReason**: `"SCAN_FAILED"`
|
|||
|
|
- 调度器 `JobSuspended` filter 需要同步排除此状态(WAITING_WASTE 不应被常规调度选中)
|
|||
|
|
|
|||
|
|
### 3.2 Replenisher 扫码失败逻辑
|
|||
|
|
|
|||
|
|
`replenishOne` 方法中,扫码失败后:
|
|||
|
|
|
|||
|
|
1. 工件物理已在暂存台(机器人已放置)
|
|||
|
|
2. 写 DB:`SetStatus(WAITING_WASTE)` + `SetPositionType(ON_BUFFER)` + `SetSuspendedReason("SCAN_FAILED")`
|
|||
|
|
3. DockSlot 清空(status=0),可继续接收新料
|
|||
|
|
4. 创建 alarm(`alarm_code: SCAN_FAILED`),供追溯
|
|||
|
|
5. 不阻塞后续补料(continue 下一个 dock item)
|
|||
|
|
|
|||
|
|
### 3.3 WasteReady 信号
|
|||
|
|
|
|||
|
|
- 信号已定义:`WasteReady` = `M1150.1`(`doc/signal.csv` 行 19)
|
|||
|
|
- 通过 `preload.GetMAddress("WasteReady")` 获取地址,在 `trySchedule` 时读取 PLC 当前值
|
|||
|
|
- `SystemState.WasteReady bool` — 调度快照中携带,供 Generator 判断
|
|||
|
|
|
|||
|
|
### 3.4 调度
|
|||
|
|
|
|||
|
|
**Generator**: 遍历 `RuntimeSnapshot` 中 `Status == WAITING_WASTE` 的 job,若 `WasteReady == true`,生成:
|
|||
|
|
```
|
|||
|
|
CandidateTask{
|
|||
|
|
Action: ActionLoadWaste, // 已在 types.go 中定义
|
|||
|
|
TargetID: tempSlotNo,
|
|||
|
|
Priority: PriorityHigh,
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**SchedulerBridge**: 映射 `ActionLoadWaste` → `RobotAction{Kind: "load_to_waste", SrcSlot: tempSlotNo}`。
|
|||
|
|
|
|||
|
|
**优先级**: `PriorityHigh`,释放暂存台资源不应被普通装料阻塞。
|
|||
|
|
|
|||
|
|
### 3.5 RobotWorker
|
|||
|
|
|
|||
|
|
新增 `executeLoadToWaste`:
|
|||
|
|
```go
|
|||
|
|
// 暂存台取料 → 放入废料台
|
|||
|
|
func (w *RobotWorker) executeLoadToWaste(ctx context.Context, action action.RobotAction) error {
|
|||
|
|
// 1. 从暂存台取料
|
|||
|
|
if err := w.robotCtrl.FetchWorkpieceFromTempStation(ctx, ...); err != nil {
|
|||
|
|
return fmt.Errorf("fetch from temp station: %w", err)
|
|||
|
|
}
|
|||
|
|
// 2. 放入废料台 (M1140)
|
|||
|
|
if err := w.robotCtrl.PlaceWorkpieceToWasteStation(ctx, ...); err != nil {
|
|||
|
|
return fmt.Errorf("place to waste station: %w", err)
|
|||
|
|
}
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.6 Robot Controller
|
|||
|
|
|
|||
|
|
`internal/robot/dock.go` 新增:
|
|||
|
|
```go
|
|||
|
|
func (c *Controller) PlaceWorkpieceToWasteStation(ctx context.Context, ...) error {
|
|||
|
|
// 发送 M1140 信号
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.7 EventLoop 完成处理
|
|||
|
|
|
|||
|
|
废料搬运成功后:
|
|||
|
|
1. `TempStoreActor.ReleaseSlot(slotNo)` — 释放暂存台槽位
|
|||
|
|
2. `DBState.ScrapJob(jobID)` — Job 标记 SCRAPPED(终态)
|
|||
|
|
|
|||
|
|
### 3.8 启动恢复
|
|||
|
|
|
|||
|
|
`RecoverOnStartup` 中:`WAITING_WASTE` 状态的 job 视为已正确放置在暂存台,**不**转为 PAUSED。等待下次 `trySchedule` 时 `WasteReady` 信号触发搬运。
|
|||
|
|
|
|||
|
|
## 4. 边缘情况
|
|||
|
|
|
|||
|
|
- **多个 WAITING_WASTE job**: Generator 一次生成多个候选任务,由 PriorityPolicy 按优先级排序后依次执行
|
|||
|
|
- **WasteReady 长时间为 false**: job 留在暂存台,占用槽位,不阻塞其他正常 job 调度(JobSuspended filter 排除)
|
|||
|
|
- **暂存台满**: replenisher 的 `reserveFreeTempSlot` 分配失败会正常停止补料,不会抢占废料等待工件的槽位
|
|||
|
|
- **废料台满**: PLC 不会设置 WasteReady=true,搬运不会触发(硬件层保证)
|