20 KiB
3axis Tutorial Web 控制面板源程序对标实施方案
目标
为固定案例 linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.ini 建立与 LinuxCNC AXIS 控制面板可观察行为一致的 Web 控制面板。
唯一运行时数据来源是 LinuxCNC 源码编译得到的 WASM core,以及由 Dedicated Worker 投影的 authoritative snapshot/event。React 只能发送命令、显示状态和呈现诊断;不得在浏览器端重新推导任务状态、运动轨迹、DRO、工具状态、门禁或错误结果。
本方案是固定案例的控制面板实施合同,不宣称全量 LinuxCNC、实时硬件或 release candidate。机器可读的源语义规则见 coverage/linuxcnc-source-semantics-contract.json,共享实现见 web/workspace/linuxcnc-source-semantics.mjs。
硬约束和功能矩阵
以下约束是所有 PANEL 任务的共同通过条件:
- 网页控制面板的唯一数据来源是 LinuxCNC WASM;React 不得生成、修正或覆盖 canonical state。
- 状态机严格对标 LinuxCNC 源程序;状态数值、迁移顺序、错误码和 gate reason 必须有 source line 和 WASM/Worker evidence。
- 所有按钮逻辑制约必须与 LinuxCNC AXIS 源程序一致;按钮 disabled/enabled、模式切换、ESTOP/limit/fault gate 不允许由 UI 自行猜测。
- 刀具路径预览必须来自 WASM canonical motion events,并与原生 LinuxCNC 的 segment 顺序、source line、端点、圆弧中心/法向、turn、units 和最终 hash 一致;没有 WASM event 时必须 fail-closed。
| # | 功能 | LinuxCNC 原生 | WASM 支持 | Web 实现状态 | 优先级 | 主要任务 |
|---|---|---|---|---|---|---|
| 1 | 加载数控程序 | ✅ | ✅ | PANEL-07 |
P0 | PROGRAM_LOAD、exact source/hash、diagnostic |
| 2 | 刀具路径预览 | ✅ | ✅ | PANEL-11 |
P0 | WASM motion event、segment golden、no JS preview |
| 3 | 取消急停 | ✅ | ✅ | PANEL-05 |
P0 | ESTOP_RESET/recover source state transition |
| 4 | 上电 | ✅ | ✅ | PANEL-05 |
P0 | STATE_OFF -> STATE_ON and gate |
| 5 | 复位 | ✅ | ✅ | PANEL-05/PANEL-12 |
P0 | task reset、fault clear、checkpoint reconciliation |
| 6 | HOME 回零 | ✅ | ✅ | PANEL-06 |
P0 | individual/all home、home sequence、home-limit ABI |
| 7 | 执行 G 代码 | ✅ | ✅ | PANEL-07 |
P0 | run/pause/resume/step/abort/restart |
| 8 | 实时路径显示 | ✅ | ✅ | PANEL-10 |
P0 | authoritative pose/toolpath -> Three.js |
| 9 | 实时坐标显示 | ✅ | ✅ | PANEL-08 |
P0 | commanded/actual/relative DRO、units |
| 10 | MDI 功能 | ✅ | ✅ | PANEL-07 |
P1 | MDI mode、queue limit、active program rejection |
| 11 | JOG 功能 | ✅ | ✅ | PANEL-06 |
P1 | manual mode、continuous/incremental、stop |
| 12 | 按钮逻辑制约 | ✅ | ✅ | PANEL-03 |
P0 | complete AXIS gate matrix and error reasons |
表中的“Web 实现状态”在任务完成前只能是 queued、in_progress 或 blocked;现有 selected-case smoke/Worker evidence 不得自动把矩阵项标记为 verified。
功能项统一验收证据
每个矩阵项必须同时保存:LinuxCNC source path/line/hash、WASM export/state field、Worker command/event、React control ID、normal/boundary/error/ESTOP/recovery sample、native/WASM/Worker logical tick、输入/输出/state/event hash 和 self-hashed report。P0 项缺任一项即保持 blocked;P1 项不能阻塞 P0 实施,但不能被宣称完成。
源程序映射
| Web 控制面板区域 | LinuxCNC 源输入 | WASM/Worker 唯一来源 | React 允许行为 | 禁止行为 |
|---|---|---|---|---|
| 电源、急停、状态灯 | axis.py 状态更新、linuxcnc STATE_*/MODE_*/INTERP_* |
sim_task canonical + axis_state |
显示、发送命令、显示 gate reason | 本地切换 ON/ESTOP |
| File/Program | axis.py open_file_guts, reload_file, task_run |
WASM interpreter events + Worker program state | 编辑器输入、发送 LOAD/RUN/RESTART | JS 解析 G-code 或伪造当前行 |
| MDI | axis.py ensure_mode, send_mdi_command |
WASM interpreter/task mode/queue | 提交文本、显示拒绝 | 本地判断 MDI 成功 |
| Manual/Jog/Home | axis.py jog_plus, jog_minus, home_all_joints, home_joint |
WASM motion queue + home/limit ABI | 按钮、方向、速度输入 | JS 插值、修改 position/home |
| DRO/active codes | axis.py update, task_modename, motion_modename, interp_statename |
WASM task/interpreter/motion snapshot | 格式化显示 | 从命令文本推导状态 |
| Feed/spindle override | axis.py set_feedrate, set_spindlerate |
WASM/Worker device canonical | slider/number input | 直接修改 React store |
| Spindle/coolant/tool/probe | axis.py manual controls、案例 HAL、sim_io |
WASM IO/device canonical | 显示、发送命令、fault recovery | mock device response |
| Preview/3D | axis.py preview/canon、案例 Vismach executable |
WASM canonical motion + Worker visual snapshot | Three.js 渲染 | JS G-code preview/几何 authority |
| 配置诊断 | linuxcnc-source-semantics-contract.v1 |
Worker startup snapshot | 显示 TASK_READY/BLOCKED_*、source/line |
basename 替换、隐藏缺失资源 |
源代码锚点:
- AXIS startup/open-file:
linuxcnc/src/emc/usr_intf/axis/scripts/axis.py约 3991-3998 行。 - AXIS status projection:同文件
update、task_modename、motion_modename、interp_statename。 - AXIS command gates:同文件
ensure_mode、task_run、task_pause、task_resume、task_stop、jog_*、home_*、estop_clicked。 - 参数文件和程序前缀:
linuxcnc/src/emc/rs274ngc/rs274ngc_pre.cc、linuxcnc/src/emc/task/emctask.cc。 - 案例 UI/HAL/Vismach:
linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.ini、.hal和3axis-tutorial。
控制面板数据契约
Worker 每次响应必须能追溯到同一个 context_id、session_id、logical_tick 和 state_hash。控制面板消费以下投影字段:
snapshot:
task: wasm sim_task canonical state
program: WASM interpreter/program state
motion: WASM motion queue state
home_limit: WASM kinematics home/limit state
hal: static/virtual HAL projection with source diagnostics
devices: WASM sim_io/tool/spindle/coolant/probe state
configuration: startup state, exact resources, optional_missing, runtime_fixtures
axis_state: additive AXIS state/mode/interpreter view
visual: pose, joints, toolpath and Vismach pose projection
state_hash: hash of the canonical projection
每个命令必须携带 operation_id,并产生 pending/result/error event。UI gate 只读取上一份 authoritative snapshot;命令被拒绝时显示 Worker 返回的 stable error code、message key、source/line 和 gate reason。错误、ESTOP、limit、following-error、资源缺失和能力边界必须可见,不能变成静默 disabled。
分层接口责任
| 层 | 必须提供 | 允许缓存 | 不得提供 |
|---|---|---|---|
| LinuxCNC source/native recorder | 常量、状态迁移、命令顺序、错误/拒绝语义、segment golden | stdout/log/screenshot hash | 浏览器状态 |
wasm-core |
canonical task/interpreter/motion/home-limit/HAL/IO state、fixed tick、canonical event | raw ABI bytes、read-only sample | UI 文案或按钮 gate |
| Dedicated Worker | command ledger、session lifecycle、snapshot/event 转发、diagnostic/source line、checkpoint/trace | 序列化协议和 operation trace | JS authority mirror、JS G-code 解析 |
| React/Web panel | command input、snapshot projection、accessibility、visual rendering | 最近一份 snapshot 用于显示 | 改写 state、推导成功、推导轨迹 |
任何层违反责任都必须在测试中以 authority_violation 失败;“结果看起来一致”不能替代唯一来源证明。
面板命令 envelope
所有 P0/P1 命令使用已有 protocol.v1 envelope,不为 UI 单独发明协议:
{
"schema_version": 1,
"context_id": "linuxcnc-2.10.0-pre0-wasm-m1-py-c1",
"session_id": "axis3-panel",
"seq": 42,
"operation_id": "axis-program-run-000042",
"kind": "PROGRAM_RUN",
"payload": {}
}
响应至少包含 kind、seq、operation_id、logical_tick、payload.task、payload.program、payload.motion、payload.axis_state、payload.state_hash。错误响应必须包含 code、message_key、source/line(若有)、gate_reason 和拒绝时的完整 snapshot。
严格状态机和按钮真值表
源常量和 AXIS 视图必须使用 docs/linuxcnc-web-wasm-3axis-tutorial-state-machine.md 中的数值,不得只使用同名字符串:
| AXIS 状态 | LinuxCNC source state | 允许的面板操作 | 必须拒绝 |
|---|---|---|---|
ESTOP |
STATE_ESTOP |
cancel ESTOP、显示诊断 | power/home/run/MDI/JOG |
ESTOP_RESET |
STATE_ESTOP_RESET |
power on、ESTOP | run/home/MDI/JOG |
OFF |
STATE_OFF |
power/reset、ESTOP | run/home/MDI/JOG |
ON/IDLE |
STATE_ON + INTERP_IDLE |
load/run/MDI/manual/home/jog/device | 与当前 mode/limit/fault 冲突的操作 |
HOME |
source home transient | 等待 home result、ESTOP | run/MDI/重复 home |
RUNNING |
INTERP_READING/WAITING |
pause/abort/ESTOP | home/jog/MDI/load |
PAUSED |
INTERP_PAUSED |
resume/abort/ESTOP/step(按源 gate) | home/jog/普通 MDI |
按钮 gate 的可执行真值样本必须至少包含:
| 操作 | 正常条件 | 拒绝样本 |
|---|---|---|
| 加载程序 | ON + INTERP_IDLE 或源允许的 manual load |
OFF、RUNNING、资源缺失 |
| 预览 | WASM motion events 已存在 | WASM event 缺失、解析错误 |
| 取消急停 | ESTOP/ESTOP_RESET 按源状态转换 |
snapshot 过期、seq/tick 错误 |
| 上电 | ESTOP_RESET -> ON 或源定义 reset 流程 |
ESTOP 未 reset、fault latch |
| 复位 | abort/clear/recover 的源顺序 | active motion、坏 checkpoint |
| HOME | ON + MANUAL + INTERP_IDLE |
OFF、AUTO/MDI、limit/fault、未满足 previous home |
| G-code run | ON + AUTO + IDLE + taskfile |
无程序、MDI、paused、ESTOP |
| 实时路径/DRO | snapshot tick/hash 可验证 | snapshot stale、state hash mismatch |
| MDI | ON + MDI 且 queue 未满 |
AUTO active、queue full、ESTOP |
| JOG | ON + MANUAL + IDLE |
AUTO/MDI、未 home、limit/fault |
刀具路径预览一致性算法
预览和执行都必须使用 WASM interpreter canonical motion event;Web 不得将原始 G-code 再解析一遍。每个 segment 的比较字段固定为:
segment:
source_line: integer
motion_type: rapid|linear|arc
start: pose(x,y,z,a,b,c,u,v,w)
end: pose(x,y,z,a,b,c,u,v,w)
center: pose_or_null
normal: vector_or_null
turn: integer
velocity: finite_number
units: mm|inch
plane: G17|G18|G19
sequence: integer
验收顺序:
- native recorder 使用固定程序和固定 units/modal 初始状态生成 segment JSONL。
- WASM
sim_interpreter_read_motion生成同字段事件;Worker 只排序/封装,不补字段。 - 比较 segment count、source line、顺序、字段值和 canonical hash;浮点比较使用 source/ABI 规定的 exact或明确 tolerance,不能用截图相似度替代。
- Three.js 只渲染已比较的
visualprojection;canvas 非空是必要条件,不是轨迹正确性的充分条件。 - 任意字段首差必须记录
first_divergent_segment、source_line、logical_tick、field、native、wasm,并阻止 preview/execute 继续宣称一致。
禁止条件:WASM event buffer 为空时调用 JS previewGcode;用当前 DRO 终点反推完整路径;用 native screenshot 通过 Web segment hash;用墙钟时间推进路径。
功能矩阵报告模板
每个功能项使用同一结构,便于控制面板任务和后续自动聚合:
feature_id: PANEL-07
matrix_item: execute_gcode
priority: P0
status: queued|in_progress|verified|blocked
source:
paths: []
lines: []
sha256: []
authority:
wasm_exports: []
canonical_fields: []
worker:
commands: []
events: []
react:
control_ids: []
projection_fields: []
samples:
normal: []
boundary: []
error: []
estop_or_fault: []
recovery: []
comparison:
native_hash: null
wasm_hash: null
worker_hash: null
first_divergent_tick: null
stop_reason: null
report_sha256: null
verified 只允许在 source、authority、worker、react、5 类 samples、comparison 和 self-hash 全部存在时使用。任何 REAL-EXCLUDED、SOURCE_BLOCKED、WASM_CAPABILITY_BLOCKED 都必须保持 blocked,并带 failure sample。
面板布局和交互范围
桌面和移动布局都必须保持以下固定区域,不因动态文字改变尺寸:
- 顶栏:案例名、WASM capability、连接/session、
TASK_READY/BLOCKED、ESTOP 和 recover。 - 左侧状态:machine power、task mode、interp state、program status、current line、logical tick、state hash。
- 中央机床视图:Three.js Vismach 3-axis model、tool pose、joints、limits、toolpath、axis labels。
- 右侧 DRO:commanded/actual/relative 的 X/Y/Z、unit、feed/spindle override、active G/M codes。
- 下方 tabs:Manual、MDI、Program、Diagnostics;每个 tab 的控件 gate 来自 Worker snapshot。
- 操作条:Home all/individual、jog +/-/stop、Run/Pause/Resume/Step/Abort/Restart、spindle/coolant/tool/probe/ESTOP。
- 诊断面板:按事件顺序显示 source path、line、code、reason、first divergent tick、recovery status。
熟悉符号使用 AXIS 源图标或 lucide icon;按钮必须有 accessible name、disabled reason 和 keyboard path。控件不能仅通过颜色表示 fault/ESTOP。
功能缺口移植流程
当 WASM/Worker 当前能力不满足 AXIS 行为时,严格按以下顺序处理:
- 从 LinuxCNC 源文件定位函数、状态常量、命令顺序和错误语义,记录 source path、line、source hash。
- 判断是否属于纯仿真可移植行为。实时内核、真实硬件、宿主动态 loader、宿主 GUI/Python 进程只能登记
REAL-EXCLUDED/HOST_EXCLUDED,不能伪造 WASM parity。 - 先增加 native source sample 和失败测试,再在
wasm-core增加 C ABI/状态实现;ABI 变更必须建立新 context,不能就地改锁定 ABI。 - 增加真实 WASM module 测试,再接
web/workeradapter;Worker 只投影 WASM canonical,不保留 JS authority 镜像。 - 最后接 React 命令/渲染,补 normal、boundary、error、non-finite、capacity、pause/resume、ESTOP、recovery 样本。
- 记录首个 divergent phase/tick、native/WASM/Worker hash、checkpoint/trace/recovery hash,更新 self-hashed report。
详细实施任务
P0/P1 执行顺序
先完成 P0 的 authority、状态机、按钮 gate、程序加载/执行、preview、实时路径和实时坐标,再实现 P1 的 MDI/JOG 扩展。P0 任务之间按 PANEL-01 -> PANEL-02 -> PANEL-03 -> PANEL-05 -> PANEL-06/PANEL-07 -> PANEL-08/PANEL-10/PANEL-11 -> PANEL-14 -> PANEL-15 执行;P1 的 MDI/JOG 只能复用同一 WASM/Worker authority,不能另建一套 UI state。
P0 完成的硬条件:12 项矩阵中的 1-9、12 有 native source reference、真实 WASM module、Worker sequence 和 React evidence;刀具路径 preview 与 native canonical segments 的 hash/端点一致;所有按钮 gate 在正常、运行、暂停、MDI、ESTOP、limit、fault、未 home 和 queue-full 样本中一致。P1 完成的硬条件:10-11 的 MDI/JOG 与 P0 状态机、queue、home/limit、ESTOP gate 共用同一 snapshot,不能产生 divergent tick。
| ID | 任务 | 主要实现 | 直接源输入 | 验收输出 | 依赖 |
|---|---|---|---|---|---|
PANEL-01 |
源控件 inventory | 把 AXIS 菜单、toolbar、快捷键、Manual/MDI/Auto、DRO、诊断控件登记为稳定 IDs | axis.py、AXIS Tcl UI、案例 INI |
source inventory + control ID contract | 无 |
PANEL-02 |
snapshot projection contract | 固定 task/program/motion/home/hal/devices/configuration/axis_state/visual 字段、tick/hash 和 event envelope | sim-session.mjs、T4/T3 reports |
schema-compatible projection test | 01 |
PANEL-03 |
source gate matrix | 逐命令复刻 AXIS ensure_mode、状态和 gate;禁止 React 自判定 |
axis.py command functions、axis-contract.mjs |
gate matrix normal/error/ESTOP test | 01/02 |
PANEL-04 |
startup/config panel | 显示 exact resources、optional OPEN_FILE/graphic、HAL/resource/INI diagnostics 和 runtime fixtures |
source semantics contract、案例 INI/HAL | TASK_READY/BLOCKED_* UI test |
02 |
PANEL-05 |
power/ESTOP/recover | 对齐 STATE_OFF/ON/ESTOP/ESTOP_RESET 和 recover transition |
axis.py、sim_task、sim_io |
transition/event/hash report | 02/03 |
PANEL-06 |
Manual/Home/Jog | 对齐 individual/all home、continuous/incremental jog、stop、joint/teleop gate | axis.py jog_*/home_*、T4 home-limit |
native/WASM/Worker sequence report | 03/05 |
PANEL-07 |
Program/MDI | 对齐 open/load/reload/run/pause/resume/step/abort/restart/MDI queue and active-program rejection | axis.py、WASM interpreter/task |
program control and current-line report | 03/05 |
PANEL-08 |
DRO/active codes | 对齐 actual/commanded/relative、units、feed/spindle、active G/M/modal display | AXIS update/stat mixins、WASM snapshot |
DRO golden and unit switch test | 02/06/07 |
PANEL-09 |
device panels | 对齐 spindle ramp/at-speed, coolant, tool prepare/change, probe, limit/FERROR faults | 案例 HAL、sim_io、tool-IO report |
device fault/recovery report | 05/06/07 |
PANEL-10 |
Vismach/3D | 按 3axis-tutorial Python model 和 HAL pins 实现 geometry/pose/tool continuity |
案例 executable、Vismach source、Three.js view | canvas pixel/nonblank/pose report | 02/06/08/09 |
PANEL-11 |
editor/preview | Worker WASM preview、source line highlighting、active G-code 和 diagnostics | sim_interpreter、AXIS editor/preview |
no-JS-preview test + source-line parity | 07/08 |
PANEL-12 |
persistence/recovery UI | checkpoint, journal, trace import, .var/.bak/position/tool.tbl restart and fail-closed recovery |
T4/T6 reports、workspace recovery | recovered endpoint and no duplicate side effects | 05/07/09 |
PANEL-13 |
keyboard/accessibility/layout | AXIS shortcut mapping、focus order、ARIA、desktop/mobile no-overlap | AXIS shortcut table、React source | DOM/accessibility/visual report | 01/03/08/10/11 |
PANEL-14 |
native/Worker/UI recorder | 同一 operation sequence、same logical ticks、first divergence and hash comparison | native runner、Dedicated Worker、React | sequence ledger and diff report | 05..13 |
PANEL-15 |
selected-case acceptance | 汇总所有面板区域、normal/boundary/error/recovery 和 release boundaries | all PANEL evidence | self-hashed closure report | 14 |
验收和停止条件
通过条件:每个 PANEL row 有 source reference、WASM authority、Worker test、UI evidence、state/event hash 和 recovery sample;同一操作序列 native/WASM/Worker/UI 的首个差异可定位;控制面板无 JS authority、无 JS G-code preview、无 basename 替换。
保持 blocked:缺 source/oracle/resource、WASM ABI 不足、首个 divergent tick 未定位、Worker snapshot/hash 不稳定、恢复重复副作用、只在 Chromium 可见但 browser minimum 未锁定,或只能靠 mock/墙钟/宿主能力通过。
停止发布:不把固定案例 verified 写成全量 LinuxCNC parity;Firefox/Safari、OPFS 物理崩溃、实时硬件、官方 oracle、许可证和 owner release gate 继续保持 STOP_RELEASE。
证据命令
python3 scripts/validate_baseline.py
python3 scripts/validate_task_pointer.py nextTask1.md --lock context-lock.json
python3 scripts/test_source_semantics_contract.py
node web/workspace/test_source_semantics.mjs
node web/workspace/test_sim_case_loader.mjs
node web/worker/test_sim_case_matrix_s8_06.mjs
node web/worker/test_wasm_canonical_state.mjs
node web/worker/test_wasm_canonical_state_checkpoint.mjs
node web/worker/test_axis3_selected_case.mjs
node web/worker/test_axis3_visible_completion.mjs
npm --prefix web/react run typecheck
npm --prefix web/react run build
每个 PANEL 任务必须增加专属测试和 self-hashed report;未完成的任务保留 queued/blocked,不能从 UI smoke 直接升级为 parity。