577 lines
13 KiB
Markdown
577 lines
13 KiB
Markdown
# 2026-07-07 AXIS 按钮 LinuxCNC 真实 C++ 对标验收测试
|
||
|
||
## 1. 验收原则
|
||
|
||
本文件由 `19-20260707-AXIS按钮LinuxCNC-task-motion状态机制源码分析.md` 拆分而来,定义“急停、上电、Home、执行、暂停、单步执行”的真实验收标准。
|
||
|
||
验收原则:
|
||
|
||
- `compare 60/60 pass` 不是最终验收结论,只是旧 compare 摘要。
|
||
- 验收必须证明 Web 行为符合 LinuxCNC C++ task/motion/homing 真实实现。
|
||
- 每个按钮必须同时验收 UI gate、runtime gate、状态记录、非法命令拒绝、真实程序执行影响。
|
||
- 如果表面 compare 通过,但 C++ 状态机硬规则失败,结论必须是失败。
|
||
|
||
最终验收结论字段建议:
|
||
|
||
```json
|
||
{
|
||
"surfaceSummary": {
|
||
"legacyComparePassCount": 60,
|
||
"legacyCompareFailCount": 0
|
||
},
|
||
"functionalSummary": {
|
||
"status": "pass",
|
||
"failCount": 0,
|
||
"requiredImprovements": []
|
||
}
|
||
}
|
||
```
|
||
|
||
只有 `functionalSummary.status == "pass"` 才允许写“真实通过”。
|
||
|
||
## 2. 验收准备
|
||
|
||
### 2.1 Native LinuxCNC 准备
|
||
|
||
命令:
|
||
|
||
```bash
|
||
/home/mes123456/cnc_wams/linuxcnc/scripts/rip-environment \
|
||
python3 /home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/tools/collect-native-xyzbc-trt-evidence.py \
|
||
--run --timeout 90
|
||
```
|
||
|
||
必须采集:
|
||
|
||
- `task.state`
|
||
- `task.mode`
|
||
- `task.interpState`
|
||
- `task.execState`
|
||
- `task.task_paused`
|
||
- `task.currentLine`
|
||
- `task.readLine`
|
||
- `task.motionLine`
|
||
- `motion.traj.enabled`
|
||
- `motion.traj.paused`
|
||
- `motion.traj.single_stepping`
|
||
- `motion.traj.queue`
|
||
- `motion.joint[].homing`
|
||
- `motion.joint[].homed`
|
||
- active G-code line、motion id、axis pose、tcp pose、tool axis
|
||
|
||
### 2.2 Web 准备
|
||
|
||
命令:
|
||
|
||
```bash
|
||
npm --prefix /home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/app run smoke:node
|
||
npm --prefix /home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/app run smoke:browser
|
||
npm --prefix /home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/app run evidence:web
|
||
```
|
||
|
||
必须采集与 native 同名字段,并额外采集:
|
||
|
||
- UI button enabled/disabled
|
||
- operator message
|
||
- runtime command accepted/rejected
|
||
- `machine.*` 状态快照
|
||
- Task/HAL status 快照
|
||
|
||
### 2.3 Compare 准备
|
||
|
||
命令:
|
||
|
||
```bash
|
||
npm --prefix /home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/app run evidence:compare
|
||
```
|
||
|
||
compare 必须输出:
|
||
|
||
- 旧摘要 `surfaceSummary`
|
||
- 新硬规则 `functionalSummary`
|
||
- 每个 C++ 对标规则的 pass/fail 原因
|
||
|
||
## 3. 基础状态枚举验收
|
||
|
||
### T-STATE-001 task state 枚举一致
|
||
|
||
步骤:
|
||
|
||
1. 启动 Web runtime。
|
||
2. 依次发 `ESTOP`、`ESTOP_RESET`、`ON`、`OFF`。
|
||
3. 对照 LinuxCNC `EMC_TASK_STATE`。
|
||
|
||
期望:
|
||
|
||
- `ESTOP -> estop`
|
||
- `ESTOP_RESET -> estop-reset`
|
||
- `ON -> on`
|
||
- `OFF -> estop-reset/off 语义`,Web 显示必须与项目约定一致,但不能伪装为 on。
|
||
|
||
失败条件:
|
||
|
||
- Web 只用 `powerOn` 推导 state。
|
||
- runtime status 与 UI 状态不一致。
|
||
|
||
### T-STATE-002 task mode 枚举一致
|
||
|
||
步骤:
|
||
|
||
1. 在 machine on 状态依次切 `manual`、`auto`、`mdi`。
|
||
2. 在 `auto + reading` 时尝试切出 auto。
|
||
|
||
期望:
|
||
|
||
- 正常 idle 下切换成功。
|
||
- `auto + reading` 切出 auto 必须被拒绝,或按 LinuxCNC abort/close/synch 语义处理并记录。
|
||
|
||
失败条件:
|
||
|
||
- 解释器运行中静默切到 manual/mdi。
|
||
|
||
### T-STATE-003 interp/exec 状态一致
|
||
|
||
步骤:
|
||
|
||
1. Run 前检查 `interpState=idle`、`execState=done`。
|
||
2. Run 中检查 `interpState=reading/waiting`,`execState` 可进入 waiting 状态。
|
||
3. 完成后检查 `interpState=idle`、`execState=done`。
|
||
|
||
失败条件:
|
||
|
||
- 只记录 `runState`,没有 `interpState/execState`。
|
||
|
||
## 4. 急停验收
|
||
|
||
### T-ESTOP-001 ESTOP 可在任意状态触发
|
||
|
||
步骤:
|
||
|
||
1. machine on。
|
||
2. Home All。
|
||
3. Run 真实程序。
|
||
4. 在执行中发 ESTOP。
|
||
|
||
期望:
|
||
|
||
- runtime 接受 `EMC_TASK_SET_STATE ESTOP`。
|
||
- `taskState=estop`。
|
||
- `motionEnabled=false`。
|
||
- `interpState=idle`。
|
||
- `taskPaused=false`、`motionPaused=false`。
|
||
- `singleStepping=false`、`motionStepping=false`。
|
||
- feed velocity 为 0。
|
||
- spindle/coolant 关闭。
|
||
|
||
失败条件:
|
||
|
||
- ESTOP 后仍显示 running/paused/stepping。
|
||
- 位置继续推进。
|
||
- 只改 UI,不改 runtime status。
|
||
|
||
### T-ESTOP-002 ESTOP_RESET 只解除急停但不上电
|
||
|
||
步骤:
|
||
|
||
1. 进入 ESTOP。
|
||
2. 发 RESET/ESTOP_RESET。
|
||
|
||
期望:
|
||
|
||
- `taskState=estop-reset`。
|
||
- `powerOn=false`。
|
||
- `motionEnabled=false`。
|
||
- `interpState=idle`。
|
||
|
||
失败条件:
|
||
|
||
- RESET 后直接上电。
|
||
|
||
## 5. 上电/下电验收
|
||
|
||
### T-POWER-001 ESTOP 下 Power 被拒绝
|
||
|
||
步骤:
|
||
|
||
1. 设置 `taskState=estop`。
|
||
2. 点击/发送 Power。
|
||
|
||
期望:
|
||
|
||
- UI 禁用或 operator message 提示先解除急停。
|
||
- runtime 不接受 `ON`。
|
||
- 状态保持 estop。
|
||
|
||
失败条件:
|
||
|
||
- ESTOP 下进入 on。
|
||
|
||
### T-POWER-002 ESTOP_RESET 下 Power On
|
||
|
||
步骤:
|
||
|
||
1. RESET 到 `estop-reset`。
|
||
2. 点击 Power。
|
||
|
||
期望:
|
||
|
||
- 发送 `EMC_TASK_SET_STATE ON`。
|
||
- `motionEnabled=true`。
|
||
- 最终 `taskState=on`。
|
||
|
||
失败条件:
|
||
|
||
- 只设置 `powerOn=true`,runtime status 未 on。
|
||
|
||
### T-POWER-003 ON 下 Power Off
|
||
|
||
步骤:
|
||
|
||
1. machine on。
|
||
2. Home All。
|
||
3. Run 或进入 idle。
|
||
4. 点击 Power Off。
|
||
|
||
期望:
|
||
|
||
- 发送 `EMC_TASK_SET_STATE OFF`。
|
||
- abort/disable。
|
||
- `motionEnabled=false`。
|
||
- `interpState=idle`。
|
||
- pause/step 状态清理。
|
||
|
||
失败条件:
|
||
|
||
- 下电后保留 running/paused/stepping。
|
||
|
||
## 6. Home 验收
|
||
|
||
### T-HOME-001 未上电 Home 被拒绝
|
||
|
||
步骤:
|
||
|
||
1. taskState=estop-reset。
|
||
2. 发 `EMC_JOINT_HOME -1` 或点击 Home All。
|
||
|
||
期望:
|
||
|
||
- runtime 拒绝。
|
||
- operator message 指出 machine must be on。
|
||
- `homed[]` 不变化。
|
||
|
||
### T-HOME-002 MANUAL/ON/IDLE Home All
|
||
|
||
步骤:
|
||
|
||
1. RESET。
|
||
2. Power On。
|
||
3. 切 Manual。
|
||
4. 发 Home All。
|
||
|
||
期望:
|
||
|
||
- 出现 `homing=true` 瞬态。
|
||
- 完成后 `homing=false`。
|
||
- `homed[]` 全 true。
|
||
- `allHomed=true`。
|
||
- `homeState=homed` 或等价状态。
|
||
|
||
失败条件:
|
||
|
||
- 没有 homing 状态事件。
|
||
- 只设置 `allHomed=true`,没有 per-joint `homed[]`。
|
||
|
||
### T-HOME-003 Homing 中禁止重复 Home/Run/Step/Jog
|
||
|
||
步骤:
|
||
|
||
1. 启动 Home All。
|
||
2. 在 homing 仍 active 时发 Home、Run、Step、Jog。
|
||
|
||
期望:
|
||
|
||
- 全部拒绝。
|
||
- 原 homing 流程不被破坏。
|
||
|
||
失败条件:
|
||
|
||
- homing 中允许 Run 或 Step。
|
||
|
||
## 7. Run 验收
|
||
|
||
### T-RUN-001 未 Home Run 被拒绝
|
||
|
||
步骤:
|
||
|
||
1. machine on。
|
||
2. mode=auto。
|
||
3. 保持 `allHomed=false`。
|
||
4. 发 `EMC_TASK_PLAN_RUN`。
|
||
|
||
期望:
|
||
|
||
- runtime 拒绝。
|
||
- 错误等价于 LinuxCNC `Can't run a program when not homed`。
|
||
- `interpState` 保持 idle。
|
||
|
||
失败条件:
|
||
|
||
- 只因 UI 禁用,但 runtime 可直接 Run。
|
||
|
||
### T-RUN-002 合法 Run 真实程序
|
||
|
||
步骤:
|
||
|
||
1. RESET。
|
||
2. Power On。
|
||
3. Home All。
|
||
4. 加载真实 G-code。
|
||
5. mode=auto。
|
||
6. Run。
|
||
|
||
期望:
|
||
|
||
- `interpState=reading/waiting`。
|
||
- `taskPaused=false`。
|
||
- `singleStepping=false`。
|
||
- `currentLine/readLine/motionLine` 随执行推进。
|
||
- axis pose、tcp pose、tool axis 随真实程序变化。
|
||
- 完成后 `interpState=idle`。
|
||
|
||
失败条件:
|
||
|
||
- 只播放前端路径,不产生 task/motion 状态流。
|
||
- line/motion id 不推进。
|
||
|
||
### T-RUN-003 非 idle Run 被拒绝
|
||
|
||
步骤:
|
||
|
||
1. 合法 Run。
|
||
2. 在 reading 或 paused 状态再次发 Run。
|
||
|
||
期望:
|
||
|
||
- reading 时拒绝。
|
||
- paused 时应提示 resume,而不是重新 Run。
|
||
|
||
失败条件:
|
||
|
||
- 运行中重入 Run。
|
||
|
||
## 8. Pause/Resume 验收
|
||
|
||
### T-PAUSE-001 AUTO/READING Pause
|
||
|
||
步骤:
|
||
|
||
1. 合法 Run。
|
||
2. 等待进入 reading。
|
||
3. 发 Pause。
|
||
4. 连续采样至少 5 帧,每帧间隔 50ms。
|
||
|
||
期望:
|
||
|
||
- `interpState=paused`。
|
||
- `interpResumeState=reading` 或 waiting。
|
||
- `taskPaused=true`。
|
||
- `motionPaused=true`。
|
||
- feed velocity 为 0。
|
||
- activeLine、axis pose、tcp pose、tool axis 在暂停采样中冻结。
|
||
|
||
失败条件:
|
||
|
||
- 状态 paused 但位置继续变化。
|
||
- 只冻结 UI,不冻结 runtime feedback。
|
||
|
||
### T-PAUSE-002 Resume 恢复 interpResumeState
|
||
|
||
步骤:
|
||
|
||
1. 在 T-PAUSE-001 暂停状态发 Resume。
|
||
|
||
期望:
|
||
|
||
- `interpState` 恢复到 `interpResumeState`。
|
||
- `taskPaused=false`。
|
||
- `motionPaused=false`。
|
||
- `singleStepping=false`。
|
||
- 执行继续推进。
|
||
|
||
失败条件:
|
||
|
||
- Resume 固定写 reading,丢失 waiting/mdi 语义。
|
||
|
||
### T-PAUSE-003 非运行 Pause 被拒绝
|
||
|
||
步骤:
|
||
|
||
1. idle 状态发菜单 Pause。
|
||
|
||
期望:
|
||
|
||
- 拒绝或忽略。
|
||
- 状态保持 idle。
|
||
|
||
失败条件:
|
||
|
||
- idle 下进入 paused。
|
||
|
||
## 9. Step 验收
|
||
|
||
### T-STEP-001 IDLE Step 等价 Run 后 Pause
|
||
|
||
步骤:
|
||
|
||
1. RESET。
|
||
2. Power On。
|
||
3. Home All。
|
||
4. 加载真实程序。
|
||
5. mode=auto。
|
||
6. 在 idle 发 Step。
|
||
|
||
期望:
|
||
|
||
- 启动 program run。
|
||
- 随后进入 paused。
|
||
- `taskPaused=true`。
|
||
- `motionPaused=true`。
|
||
- `singleStepping=true` 或 evidence 中记录 single stepping 事件。
|
||
- active line/motion id 到第一步后停止。
|
||
|
||
失败条件:
|
||
|
||
- Step 只是前端 sample+1,没有 task/motion 状态。
|
||
|
||
### T-STEP-002 PAUSED Step 放行到下一个 motion id
|
||
|
||
步骤:
|
||
|
||
1. 执行 T-STEP-001 或 Run 后 Pause。
|
||
2. 记录当前 `motionId/currentLine`。
|
||
3. 发 Step。
|
||
4. 等待下一次 paused。
|
||
|
||
期望:
|
||
|
||
- motion id 或 currentLine 前进到下一段。
|
||
- 再次 `motionPaused=true`。
|
||
- `motionStepping` 事件出现后清理。
|
||
- 不是按固定采样点数量推进。
|
||
|
||
失败条件:
|
||
|
||
- Step 后没有 line/motion id 变化。
|
||
- Step 后持续 running 不再暂停。
|
||
|
||
### T-STEP-003 Resume/Abort/ESTOP/OFF 清 Step
|
||
|
||
步骤:
|
||
|
||
1. 进入 stepping/paused。
|
||
2. 分别执行 Resume、Abort、ESTOP、OFF。
|
||
|
||
期望:
|
||
|
||
- `singleStepping=false`。
|
||
- `motionStepping=false`。
|
||
- 不残留 step lock。
|
||
|
||
失败条件:
|
||
|
||
- 后续 Run 被旧 step 状态影响。
|
||
|
||
## 10. 非法命令矩阵验收
|
||
|
||
必须在无 UI runtime 层执行:
|
||
|
||
| 状态 | 命令 | 期望 |
|
||
|---|---|---|
|
||
| estop | ON | 拒绝,必须先 estop reset |
|
||
| estop-reset | RUN | 拒绝,machine must be on |
|
||
| on/manual/idle/unhomed | RUN | 拒绝,home first |
|
||
| on/auto/reading | HOME | 拒绝,interpreter must be idle |
|
||
| on/auto/reading | SET_MODE manual | 拒绝或按 C++ abort/synch 明确处理 |
|
||
| on/auto/idle/no program | RUN | 拒绝,无程序 |
|
||
| on/manual/idle | PAUSE | 拒绝 |
|
||
| on/auto/idle | PAUSE | 拒绝或忽略 |
|
||
| on/auto/paused/resumeInhibit | RESUME | 拒绝 |
|
||
| homing active | RUN/STEP/JOG/HOME | 拒绝 |
|
||
|
||
失败条件:
|
||
|
||
- UI 禁用但 runtime 接受非法命令。
|
||
- runtime 拒绝但 UI 显示允许。
|
||
- 非法命令改变状态。
|
||
|
||
## 11. 真实程序功能验收
|
||
|
||
真实程序验收不能只看按钮状态,需要验证程序执行功能:
|
||
|
||
1. 使用 LinuxCNC `xyzbc-trt` 配置真实可运行 G-code。
|
||
2. Native 和 Web 使用同一 G-code、同一 INI/HAL/profile、同一采样周期。
|
||
3. 采集预览路径、执行路径、task 状态、motion 状态、joint home 状态、line/motion id。
|
||
4. 在执行中插入 Pause、Resume、Step、ESTOP。
|
||
5. 对比每个动作前后真实程序状态。
|
||
|
||
必须检查:
|
||
|
||
- G-code line 读取顺序。
|
||
- `readLine/currentLine/motionLine` 对齐。
|
||
- motion id 单步推进。
|
||
- Pause 时路径冻结。
|
||
- Resume 后继续同一程序,不重头执行。
|
||
- ESTOP 后停止且不能继续运动。
|
||
- Home 前 Run 必须失败。
|
||
|
||
## 12. Compare 硬通过标准
|
||
|
||
compare 输出必须包含以下硬检查:
|
||
|
||
| 检查名 | 必须为 pass 的依据 |
|
||
|---|---|
|
||
| `cppTaskStateMachineParity` | ESTOP/RESET/ON/OFF 与 `emcTaskSetState()` 和 task update 推导一致 |
|
||
| `cppModeGateParity` | `emcTaskSetMode()` 的 AUTO 非 idle 限制一致 |
|
||
| `cppHomingParity` | `EMCMOT_JOINT_HOME` 和 `homing.c` 状态流一致 |
|
||
| `cppRunGateParity` | `EMC_TASK_PLAN_RUN` 的 ON/AUTO/IDLE/Home/Program gate 一致 |
|
||
| `cppPauseResumeParity` | `EMC_TASK_PLAN_PAUSE/RESUME` 和 `EMCMOT_PAUSE/RESUME` 一致 |
|
||
| `cppStepParity` | `EMC_TASK_PLAN_STEP` 和 `EMCMOT_STEP` 的 motion id 单步一致 |
|
||
| `illegalCommandParity` | runtime 和 UI gate 一致拒绝非法命令 |
|
||
| `realProgramExecutionParity` | 真实程序 line/path/pose/status 一致 |
|
||
|
||
最终判定规则:
|
||
|
||
```text
|
||
如果 legacy compare 60/60 pass,但任一 cpp*Parity 或 realProgramExecutionParity fail,则整体验收 fail。
|
||
如果 smoke pass,但非法命令矩阵 fail,则整体验收 fail。
|
||
如果截图正常,但 task/motion 状态流不符合 C++,则整体验收 fail。
|
||
```
|
||
|
||
## 13. 验收记录模板
|
||
|
||
每轮验收必须记录:
|
||
|
||
```text
|
||
验收时间:
|
||
LinuxCNC 源码 commit/版本:
|
||
Web 项目 commit/工作区状态:
|
||
使用 INI:
|
||
使用 G-code:
|
||
Native evidence:
|
||
Web evidence:
|
||
Compare evidence:
|
||
surfaceSummary:
|
||
functionalSummary:
|
||
失败项:
|
||
是否允许宣称真实通过:
|
||
结论:
|
||
```
|
||
|
||
结论只能使用:
|
||
|
||
- `真实通过`:所有 functional hard checks 通过。
|
||
- `表面通过但功能未通过`:legacy 60/60 通过但硬规则失败。
|
||
- `未通过`:legacy 或 functional 任一失败。
|
||
- `阻塞`:缺少 native evidence、Web evidence 或 C++ 映射。
|
||
|