12 KiB
12 KiB
2026-07-07 AXIS 按钮 LinuxCNC 真实 C++ 对标实施步骤
1. 实施原则
本文件由 19-20260707-AXIS按钮LinuxCNC-task-motion状态机制源码分析.md 拆分而来,目标是把源码分析转成可执行的工程步骤。后续实现不能以 compare 60/60 pass 作为功能完成依据;60/60 pass 只能说明当前 compare 规则没有发现问题。真实合格标准必须是:Web 项目的按钮、状态、Task/HAL/WASM、evidence 和 UI 行为逐项符合 LinuxCNC C++ task/motion/homing 的真实实现。
权威基线:
- LinuxCNC 源码:
/home/mes123456/cnc_wams/linuxcnc - 目标项目:
/home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan - 核心 C++ 对标文件:
linuxcnc/src/emc/task/emctaskmain.cclinuxcnc/src/emc/task/emctask.cclinuxcnc/src/emc/task/taskintf.cclinuxcnc/src/emc/motion/command.clinuxcnc/src/emc/motion/control.clinuxcnc/src/emc/motion/homing.clinuxcnc/src/emc/nml_intf/emc.hhlinuxcnc/src/emc/nml_intf/emc_nml.hh
2. 实施输出物
必须形成以下输出物:
| 输出物 | 目标 |
|---|---|
| C++ 行为映射表 | 每个按钮对应 LinuxCNC 源码入口、NML 命令、task 处理、motion 处理、状态字段 |
| Web 状态字段表 | machine.taskState/mode/interpState/... 与 LinuxCNC EMC_STAT 字段一一对应 |
| Task/HAL/WASM 命令 ABI | EMC_TASK_SET_STATE、EMC_TASK_SET_MODE、EMC_JOINT_HOME、EMC_TASK_PLAN_RUN/PAUSE/RESUME/STEP 的 JSON 输入输出 |
| 硬门禁测试 | 不允许只靠 UI disabled,必须验证底层 task runtime 拒绝非法命令 |
| 真实程序执行证据 | 用真实 G-code、真实 line/motion id、真实状态流证明 Run/Pause/Step/Home 行为 |
| compare 增强规则 | compare 不只检查字段存在和误差,还检查 C++ 状态机不可变规则 |
3. 阶段 1:固定 LinuxCNC C++ 源码事实
3.1 建立源码事实清单
实施步骤:
- 在工作文档中建立
按钮 -> AXIS Python -> emcmodule -> NML -> emctaskmain -> emctask/taskintf -> motion的链路表。 - 每条链路必须标注具体源码文件和函数名。
- 每条链路必须标注输入命令、先决条件、状态变更、错误路径。
必须覆盖:
- 急停:
axis.py estop_clicked()、EMC_TASK_SET_STATE、emcTaskSetState(ESTOP/ESTOP_RESET)。 - 上电/下电:
axis.py onoff_clicked()、emcTaskSetState(ON/OFF)、EMCMOT_ENABLE/DISABLE。 - Home:
home_all_joints()、home_joint()、EMC_JOINT_HOME、EMCMOT_JOINT_HOME、homing.c。 - Run:
task_run()、EMC_TASK_PLAN_RUN、all_homed()、programStartLine、interpState=READING。 - Pause/Resume:
task_pause()、task_pauseresume()、EMC_TASK_PLAN_PAUSE/RESUME、EMCMOT_PAUSE/RESUME。 - Step:
task_step()、EMC_TASK_PLAN_STEP、stepping、single_stepping、EMCMOT_STEP、motion id 变化后再暂停。
完成标准:
- 任一 Web 状态或测试断言都能追溯到 LinuxCNC C++ 源码。
- 没有“按前端习惯推测”的状态规则。
3.2 建立状态字段对应关系
实施步骤:
- 对照
EMC_STAT.task、motion.traj、motion.joint[]建立 Web 字段映射。 - 区分 task 层暂停和 motion 层暂停。
- 区分 task state 命令请求和最终发布状态。
必须字段:
machine: {
taskState: "estop" | "estop-reset" | "on",
mode: "manual" | "auto" | "mdi",
interpState: "idle" | "reading" | "paused" | "waiting",
interpResumeState: "idle" | "reading" | "waiting",
execState: "done" | "waiting-for-motion" | "waiting-for-io" | "waiting-for-motion-and-io" | "error",
taskPaused: boolean,
motionPaused: boolean,
singleStepping: boolean,
motionStepping: boolean,
motionEnabled: boolean,
homing: boolean,
homed: boolean[],
allHomed: boolean,
noForceHoming: boolean,
resumeInhibit: boolean,
currentLine: number,
readLine: number,
motionLine: number
}
完成标准:
taskState不再只从powerOn派生,而是符合 LinuxCNC “IO estop + motion enabled” 语义。paused不再是单字段,必须拆成interpState/taskPaused/motionPaused。Step不再只用sampleIndex + 1表示,必须能表达singleStepping/motionStepping/motion id。
4. 阶段 2:实现 Task/HAL/WASM 真实状态机
4.1 实现 NML 命令 ABI
实施文件:
wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_task_hal_wasm.cppwasm-port/runtime/sdk/src/linuxcnc-task-hal.jsweb-rtcp-5axis-xyzbc-trt-sim-plan/app/src/runtime/linuxcnc-task-hal-runtime.js
实施步骤:
- 统一 JSON 命令名称为 LinuxCNC NML 名称。
- 每条命令返回 command accepted/rejected、operator error、状态快照。
- 非法命令必须在 runtime 层拒绝,不能只靠 UI gate。
命令要求:
| 命令 | 必须实现的 C++ 语义 |
|---|---|
EMC_TASK_SET_STATE ESTOP |
abort motion/task/io/spindle,disable motion,清 pause/step,volatile home 处理 |
EMC_TASK_SET_STATE ESTOP_RESET |
IO estop off,machine off,abort/synch |
EMC_TASK_SET_STATE ON |
motion enable,只有 enable 成功后最终 state 才是 on |
EMC_TASK_SET_STATE OFF |
abort、disable、清运行、清 pause/step、volatile unhome |
EMC_TASK_SET_MODE MANUAL |
AUTO 非 idle 时拒绝或必须按 LinuxCNC abort/close/synch 语义处理 |
EMC_TASK_SET_MODE AUTO/MDI |
motion coord mode、abort、plan synch |
EMC_JOINT_HOME |
只在 on/manual/free/idle/非 homing/homing-inhibit=false 时启动 |
EMC_TASK_PLAN_RUN |
on/auto/idle/homed/program open/motion plan loaded |
EMC_TASK_PLAN_PAUSE |
保存 interpResumeState,task paused + motion paused |
EMC_TASK_PLAN_RESUME |
恢复 interpResumeState,清 single stepping |
EMC_TASK_PLAN_STEP |
idle step 等价 run 后 pause;paused step 放行到下一个 motion id |
完成标准:
- Runtime 层能在无 UI 的 Node 测试中复现所有先决条件和状态变化。
- 任一非法命令都有明确错误消息,且状态保持不被破坏。
4.2 实现 Home 状态机
实施步骤:
- 增加 per-joint
homed[]、homing[]、homeState[]。 - Home All 使用
joint=-1。 - Home 过程至少记录
HOME_START -> HOME_FINISHED/HOME_IDLE的可观测状态。 - 正在 homing 时再次 Home 必须拒绝。
- 下电/急停只清 LinuxCNC 语义中应清的 home 状态;若当前 Web 无 volatile home 配置,必须显式记录简化边界。
完成标准:
- Home All 后所有 active joints
homed[] = true。 - Home 期间 Run、Step、Jog、再次 Home 都被拒绝。
- Evidence 能看到 homing 瞬态,不允许直接静默从 unhomed 跳到 homed 而无事件记录。
4.3 实现 Pause/Resume/Step 真实 motion 语义
实施步骤:
- Pause 时冻结执行位置、active line、tcp pose、tool axis、feed velocity。
- Resume 恢复
interpResumeState,不是固定写reading。 - Step 从 idle 开始时:先进入 run,再立即 pause。
- Step 从 paused 开始时:只放行到下一个
motionId/currentLine后再次 pause。 - Abort、ESTOP、OFF、Resume 都必须清理
singleStepping/motionStepping。
完成标准:
- 暂停期间 50ms 多帧采样位置完全冻结。
- Step 后 active line 或 motion id 按 LinuxCNC 语义变化,不能只看 sample index。
- Resume 后速度和执行状态恢复,且暂停锁消失。
5. 阶段 3:收敛 Web 状态与 UI 门禁
实施文件:
app/src/state/linuxcnc-task-policy.jsapp/src/state/store.jsapp/src/ui/axis-shell.jsapp/src/ui/gmoccapy-shell.js
实施步骤:
linuxcnc-task-policy.js作为唯一按钮门禁入口。- UI 组件只读取 policy,不再各自写 LinuxCNC 状态判断。
store.js的每个 action 都映射到 LinuxCNC NML 命令或明确的 UI 辅助流程。- Task/HAL runtime 存在时,前端可先进入预期状态,但最终必须以 status 回写覆盖。
按钮 gate 要求:
| 按钮 | Web gate 必须等价的 LinuxCNC 条件 |
|---|---|
| ESTOP | 始终可触发 |
| RESET ESTOP | 当前 taskState=estop |
| POWER ON | taskState=estop-reset |
| POWER OFF | taskState=on |
| HOME | taskState=on、mode=manual、interpState=idle、非 homing |
| RUN | taskState=on、mode=auto、interpState=idle、allHomed 或 noForceHoming、programOpen |
| PAUSE | taskState=on、mode=auto、interpState=reading/waiting |
| PAUSE_RESUME | taskState=on、mode=auto/mdi,paused 走 resume,非 idle 走 pause |
| STEP | taskState=on、mode=auto、programOpen、已 homed 或 noForceHoming、resumeInhibit=false |
完成标准:
- UI 按钮禁用状态、operator message、runtime 拒绝状态三者一致。
- UI 显示状态必须能追溯到 task/HAL status,而不是只看本地
runState。
6. 阶段 4:重构 evidence 与 compare
6.1 evidence 必须采真实功能
实施步骤:
- Native evidence 采集 LinuxCNC 真实
task.state/mode/interpState/execState/currentLine/readLine/motionLine。 - Native evidence 采集 motion
enabled/paused/stepping/queue/motion id/homing/homed[]。 - Web evidence 输出同名字段。
- 每个按钮输出 action 前、命令接受/拒绝、action 后、下一周期状态。
必须新增 evidence 段:
{
"taskMotionStateTrace": [],
"buttonCommandTrace": [],
"homingTrace": [],
"pauseFreezeTrace": [],
"stepMotionIdTrace": [],
"illegalCommandTrace": [],
"cppParityAssertions": []
}
完成标准:
- 证据能说明“为什么允许/拒绝”,而不是只说明最终 pass。
- 每个 pass 都有对应 LinuxCNC C++ 规则名称。
6.2 compare 必须从表面 pass 升级为硬规则
现有 60/60 pass 只能保留为兼容摘要。必须增加真实功能硬检查:
| 新检查 | 失败条件 |
|---|---|
cppTaskStateMachineParity |
Web 状态转移不符合 emcTaskSetState() 或 task update 推导 |
cppModeGateParity |
AUTO 非 idle 可切出或 MDI/AUTO gate 不符合 C++ |
cppHomingParity |
Home 无 homing 瞬态、非法 Home 未拒绝、homed[] 错误 |
cppRunGateParity |
未 home 可 Run、非 idle 可 Run、无 program 可 Run |
cppPauseResumeParity |
pause 未冻结、resume 未恢复 interpResumeState |
cppStepParity |
Step 不是 motion id/line 语义,只推进 sample |
illegalCommandParity |
UI 禁用但 runtime 接受非法命令,或 runtime 拒绝但 UI 显示允许 |
realProgramExecutionParity |
真实 G-code 执行 line/motion/path/status 与 native 不一致 |
完成标准:
- compare 输出
surfaceSummary和functionalSummary两部分。 - 只有
functionalSummary.failCount=0才能称为真实通过。 surfaceSummary 60/60 pass但functionalSummary失败时,结论必须是失败。
7. 阶段 5:测试实现顺序
建议顺序:
- 先补 Task/HAL runtime 的无 UI 状态矩阵测试。
- 再补 store/action 状态测试。
- 再补 UI gate 测试。
- 再补 native/Web evidence 字段。
- 最后补 compare functional checks。
对应测试文件建议:
| 测试文件 | 目标 |
|---|---|
wasm-port/tests/wasm/node/verify_task_state_matrix.mjs |
C++ task state/mode/run/pause/step/home gate |
wasm-port/tests/wasm/node/verify_task_hal_wasm.mjs |
WASM command ABI 和 status 字段 |
app/tests/node/verify_linuxcnc_task_policy.mjs 或现有同类测试 |
Web policy gate |
tests/node/verify_rtcp_store.mjs |
store action 状态写入 |
tests/node/verify_run_preconditions.mjs |
Run/Home/Power/ESTOP 前置 |
tests/browser/xyzbc_trt_browser_smoke.html |
UI 按钮状态与实际流程 |
tools/collect-native-xyzbc-trt-evidence.py |
native C++ 行为证据 |
tools/collect-web-xyzbc-trt-evidence.mjs |
Web 同名证据 |
tools/compare-xyzbc-trt-evidence.mjs |
functionalSummary 硬检查 |
8. 完成判定
实施完成必须同时满足:
- C++ 源码规则已映射到文档和测试断言。
- Task/HAL runtime 无 UI 情况下能拒绝非法命令。
- Web UI gate、store 状态、runtime status 三者一致。
- Native/Web evidence 包含真实状态流、非法命令、Home、Run、Pause、Step。
- compare 输出功能级硬检查,且功能级检查通过。
- 真实 G-code 程序执行过程中,active line、motion id、path、pose、task/motion 状态与 LinuxCNC 对齐。
明确禁止把以下结果单独作为完成依据:
compare 60/60 pass- 页面截图看起来正常
- UI 按钮样式 active/disabled 正常
- 单个 smoke 测试通过
- Web 本地
runState看起来合理