14 KiB
02 RUN 前置条件、详细测试与编写步骤
生成时间:2026-06-22
1. 核心原则
RUN 不是孤立按钮逻辑。对五轴机床,必须先确定 LinuxCNC 机床上下文,再执行程序。
正确顺序是:
明确 INI 文件
-> 确定机床类型、坐标轴、joint、HAL、remap、tool-table
-> 确定五轴运动学算法和 switchkins 映射
-> 验证 kinematics WASM 和 task/HAL runtime 已处在同一机床上下文
-> 加载并打开 G-code
-> RUN 发送 LinuxCNC task command
-> 持续 runCycles/readStatus 或 worker push feedback
-> UI 只消费 task/HAL/motion feedback
不能先写一个通用 RUN,再猜测当前机床是什么。否则 activeLine、DRO、RTCP、A/B/C 旋转轴、TCP 补偿和 switchkins 状态都可能来自不同来源。
2. 必须先确认的机床上下文
当前项目内可作为 RUN 上下文的五轴 profile 只有两个:
| profile | LinuxCNC INI | 机床类型 | 坐标 | kinematics module |
|---|---|---|---|---|
xyzac-trt |
configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini |
table rotary tilting | XYZAC |
xyzac-trt |
xyzbc-trt |
configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini |
table rotary tilting | XYZBC |
xyzbc-trt |
源码落点:
app/src/profiles/index.js
app/src/profiles/xyzac-trt.js
app/src/profiles/xyzbc-trt.js
app/src/runtime/linuxcnc-ini-runtime.js
app/src/runtime/linuxcnc-kinematics-runtime.js
wasm-port/runtime/sdk/src/linuxcnc-kinematics.js
2.1 xyzac-trt
必须确认:
profile id: xyzac-trt
INI: configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini
[EMC] MACHINE: sim-xyzac-trt-kins (switchkins)
[TRAJ] COORDINATES: XYZAC
[KINS] KINEMATICS: xyzac-trt-kins sparm=identityfirst
WASM module id: xyzac-trt
WASM file: linuxcnc_xyzac_trt_kinematics.wasm
LinuxCNC source: src/emc/kinematics/xyzac-trt-kins.c
shared source: src/emc/kinematics/trtfuncs.c
switchkins source: src/emc/kinematics/switchkins.c
switchkins 映射:
M429 -> switchkins type 0 -> identity
M428 -> switchkins type 1 -> tcp-xyzac
M430 -> switchkins type 2 -> userk
HAL link: motion.analog-out-03 => motion.switchkins-type
2.2 xyzbc-trt
必须确认:
profile id: xyzbc-trt
INI: configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini
[EMC] MACHINE: sim-xyzbc-trt-kins (switchkins)
[TRAJ] COORDINATES: XYZBC
[KINS] KINEMATICS: xyzbc-trt-kins sparm=identityfirst
WASM module id: xyzbc-trt
WASM file: linuxcnc_xyzbc_trt_kinematics.wasm
LinuxCNC source: src/emc/kinematics/xyzbc-trt-kins.c
shared source: src/emc/kinematics/trtfuncs.c
switchkins source: src/emc/kinematics/switchkins.c
switchkins 映射:
M429 -> switchkins type 0 -> identity
M428 -> switchkins type 1 -> tcp-xyzbc
M430 -> switchkins type 2 -> userk
HAL link: motion.analog-out-03 => motion.switchkins-type
3. RUN 前置状态检查
RUN action 进入真正执行前,应要求这些状态全部明确:
state.profile.id 是 xyzac-trt 或 xyzbc-trt
state.profile.iniPath 非空且已加载
state.iniConfigReadiness.loaded === true
state.iniConfigReadiness.ready === true
state.iniConfigReadiness.coordinates 与 profile.traj.coordinates 一致
state.profile.kinematicsModuleId 与 INI [KINS] KINEMATICS 推导结果一致
state.kinematicsRuntimeReadiness.loaded === true
state.kinematicsRuntimeReadiness.moduleId === state.profile.kinematicsModuleId
state.rtcpFrame.sourceMode === source-derived-kinematics-wasm
state.machineFileStaging.status === staged
state.taskHalRuntimeReadiness.taskRuntimeReady === true
state.taskHalRuntimeReadiness.motionRuntimeReady === true
state.taskHalRuntimeReadiness.halRuntimeReady === true
state.taskHalSession.programPath 指向当前选中的 G-code
如果任一项不满足,RUN 应返回明确 operatorMessage,不应进入 fixture line playback 后伪装成真实运行。
建议阻断消息:
run blocked: LinuxCNC INI not loaded
run blocked: machine profile and INI coordinates mismatch
run blocked: LinuxCNC kinematics runtime not ready
run blocked: task/HAL runtime not ready
run blocked: no machine-file G-code opened for task/HAL session
4. 详细测试计划
4.1 INI/profile 解析测试
目标:证明 RUN 使用的不是手写机床参数,而是明确 LinuxCNC INI。
测试文件建议:
tests/node/verify_run_preconditions.mjs
断言:
1. 读取 xyzac-trt.ini,parseLinuxCncIni() 返回:
profileId=xyzac-trt
machineName=sim-xyzac-trt-kins (switchkins)
traj.coordinates=XYZAC
kinematics.name=xyzac-trt-kins
kinematicsModuleId=xyzac-trt
validation.ready=true
2. 读取 xyzbc-trt.ini,parseLinuxCncIni() 返回:
profileId=xyzbc-trt
machineName=sim-xyzbc-trt-kins (switchkins)
traj.coordinates=XYZBC
kinematics.name=xyzbc-trt-kins
kinematicsModuleId=xyzbc-trt
validation.ready=true
3. applyIniConfigToProfile() 后:
profile.traj.coordinates 与 INI 一致
profile.kinematicsModuleId 与 INI 推导结果一致
axisLimits 和 jointConfig 来自 INI
命令:
node web-rtcp-5axis-sim-plan/tests/node/verify_run_preconditions.mjs
通过标准:
run_preconditions_ini_profile_smoke=ok
4.2 运动学模块确认测试
目标:证明当前机床的五轴运动学算法已经按 INI/profile 加载。
断言:
1. createLinuxCncKinematicsRuntime({ moduleId: "xyzac-trt" }) 成功。
2. readiness.moduleId === "xyzac-trt"。
3. wasmFile === "linuxcnc_xyzac_trt_kinematics.wasm"。
4. frameForJoints([10,20,30,25,40]) 返回 moduleId=xyzac-trt。
5. switchKinematics(1) 后 switchkinsType=1,frame source 仍是 linuxcnc_kinematics_wasm_c_abi。
6. 对 xyzbc-trt 重复同样测试。
已有相关测试:
node web-rtcp-5axis-sim-plan/tests/node/verify_linuxcnc_kinematics_runtime.mjs
新增 RUN 前置测试应把这个结果纳入 RUN gate,而不是只作为独立 smoke。
4.3 machine-file staging 测试
目标:证明 RUN 打开的程序、INI、remap、tool table 是同一个 LinuxCNC 机床目录上下文。
断言:
1. stageProfileMachineFiles(profile) 成功。
2. save.files 中包含:
- 当前 profile 的 INI
- 当前 profile 的 tool table
- remap_subs/428remap.ngc
- remap_subs/429remap.ngc
- remap_subs/430remap.ngc
- 当前 profile 的 demo G-code
3. buildTaskHalSessionFromMachineFiles() 生成:
profileId 与 state.profile.id 一致
iniPath 与 profile.iniPath 一致
programPath 指向当前 selectedGcodeSourceRel
已有相关测试:
node web-rtcp-5axis-sim-plan/tests/node/verify_machine_file_staging.mjs
4.4 RUN 连续 feedback 测试
目标:证明点击 RUN 后,不是只推进一次 taskCycles=5,而是持续从 task/HAL/motion 获取反馈。
测试程序:
G90 G21
M429
G0 X0 Y0 Z5 A0 C0
M428
G1 X10 Y0 Z5 A10 C20 F600
G1 X10 Y10 Z0 A20 C30 F300
M429
G1 X0 Y0 Z5 A0 C0 F600
M30
对 xyzbc-trt 时把 A 轴替换为 B 轴:
G90 G21
M429
G0 X0 Y0 Z5 B0 C0
M428
G1 X10 Y0 Z5 B10 C20 F600
G1 X10 Y10 Z0 B20 C30 F300
M429
G1 X0 Y0 Z5 B0 C0 F600
M30
采集至少 8 个 feedback tick,断言:
1. 每个 tick 的 sourceMode 都是 linuxcnc-task-motion-hal-wasm。
2. taskCycle 或 servoCycle 单调递增。
3. activeLine 随 feedback 推进,不停留在 RUN 后第一帧。
4. axisPose 来自同一 tick 的 task/HAL status.ui.axisPose。
5. currentVelocityMmPerMin 来自同一 tick 的 motion currentVel。
6. M428 后 kinsType 切到 tcp-xyzac 或 tcp-xyzbc。
7. M429 后 kinsType 回到 identity。
8. UI 当前高亮行、DRO、runtime feedback 文本读取的是同一个 feedback snapshot。
9. 程序完成后 runState 变为 complete 或 idle,不继续显示 running。
失败判定:
RUN 后 servoCycle 只增加一次,然后 0.5s/2s/5s 不变。
activeLine 固定在某一行不再推进。
axisPose 从 HOME 位姿被 task-local 0 值覆盖。
programRuntimeFeedback.sourceMode 不是 linuxcnc-task-motion-hal-wasm。
RTCP 状态与当前 G-code 的 M428/M429 不一致。
4.5 浏览器端测试
建议扩展:
qa/web-rtcp-5axis-site-test/capture-toolpath-preview-cases.mjs
新增 case:
07-run-preconditions-and-feedback
浏览器断言:
1. 首屏等待 state.iniConfigReadiness.loaded === true。
2. 选择 xyzac-trt,确认 titlebar/profile/INI/kinematics module 都是 xyzac-trt。
3. 点击 POWER、HOME、AUTO。
4. 加载上述短 G-code。
5. 点击 RUN。
6. 采集 t=0.2s、0.5s、1.0s、2.0s、5.0s 状态。
7. 断言 task/servo cycle 单调递增。
8. 断言 UI `.gcode-row.active` 的 data-program-line 等于 state.activeLine。
9. 断言 DRO X/Y/Z/A/C 等于 state.programRuntimeFeedback.axisPose。
10. 断言 canvas dataset 的 RTCP 状态与 state.rtcpState 一致。
输出证据:
qa/web-rtcp-5axis-site-test/output/run-preconditions-feedback.json
qa/web-rtcp-5axis-site-test/screenshots/run-preconditions-feedback/*.png
5. 编写 RUN 程序的实现步骤
Step 1: 增加 validateRunPreconditions(state)
位置建议:
app/src/state/store.js
职责:
1. 检查 INI 已加载。
2. 检查 profile 与 INI 坐标一致。
3. 检查 profile.kinematicsModuleId 与 kinematics runtime moduleId 一致。
4. 检查 kinematics runtime ready。
5. 检查 task/HAL runtime ready。
6. 检查 machine file staging ready。
7. 检查 taskHalSession.programPath 指向当前 G-code。
返回结构:
{
ok: true,
profileId: "xyzac-trt",
iniPath: ".../xyzac-trt.ini",
coordinates: "XYZAC",
kinematicsModuleId: "xyzac-trt"
}
失败时:
{
ok: false,
operatorMessage: "run blocked: LinuxCNC INI not loaded"
}
Step 2: RUN action 先调用前置检查
当前 RUN 不能直接进入:
runTaskHalCommandSequence([...], { taskCycles: 5 })
应先:
1. gateLinuxCncTaskAction(state, action)
2. validateRunPreconditions(state)
3. initializeTaskHalSession({ openProgram: true }) 如需要
4. 确认 readStatus() 的 openProgram/programPath 与 state.activeProgram 对齐
未满足前置条件时,只设置 operatorMessage,不推进任何 line/sample。
Step 3: 拆分 task command 与执行 pump
RUN 应只发送 LinuxCNC task 命令:
EMC_TASK_SET_STATE ON
EMC_TASK_SET_MODE AUTO
EMC_TASK_PLAN_RUN line = activeLine - programStartLine
然后启动 feedback pump:
while running:
taskHalRuntime.runCycles({ taskCycles: batchSize })
status = taskHalRuntime.readStatus()
dispatch TASK_HAL_STATUS_APPLIED(status)
append feedback history
if complete/paused/aborted/stopped:
stop pump
说明:
这里的 pump 可以在 store 主线程调度,也可以放到 worker 内部 postMessage 推送。
关键不是 timer 本身,而是每个 tick 都必须由 task/HAL/motion runtime 的 runCycles/readStatus 产生反馈。
Step 4: 增加 RUN pump 状态
建议 state 增加:
taskHalRunPump: {
active: false,
sequence: 0,
profileId: null,
iniPath: null,
kinematicsModuleId: null,
tickCount: 0,
lastStatusAt: null,
lastError: null
}
同时增加:
programRuntimeFeedbackHistory: []
历史最多保留 100 到 500 条,避免浏览器长程序内存无限增长。
Step 5: TASK_HAL_STATUS_APPLIED 只消费 status
applyTaskHalStatusPatch() 应继续负责:
activeLine
axisPose
kinsType
rtcpState
runState
feed.currentVelocity
programRuntimeFeedback
但需要补充:
1. programRuntimeFeedbackHistory append 当前 feedback。
2. 记录 feedback.profileId、iniPath、kinematicsModuleId。
3. 对 ui.axisPoseFrame 做严格处理,避免 task-local 0 值覆盖 HOME/work pose。
4. 运行态 axisPose、velocity、DTG、activeLine 必须来自同一个 status snapshot。
Step 6: STOP/ABORT/PAUSE/RESUME 控制 pump
行为要求:
STOP/ABORT:
send EMC_TASK_ABORT
stop pump
read final status
PAUSE:
send EMC_TASK_PLAN_PAUSE
pump 可停止或降频读取 paused status
runState=paused
RESUME:
send EMC_TASK_PLAN_RESUME
restart pump
STEP:
不走 fixture sample playback
发送/推进一个明确的 task cycle batch
readStatus 一次
runState=stepping 或 paused
Step 7: UI 显示执行历史
在 app/src/ui/gmoccapy-shell.js 的 info/sidebar 区域增加:
Last feedback:
sourceMode / sample / line / taskCycle / servoCycle / velocity / kinsType
Run history:
最近 10 条 line/tick
UI 只显示 programRuntimeFeedbackHistory,不自行推导行号或坐标。
Step 8: 移除真实 RUN 的 fixture fallback 混淆
保留 fallback 可以用于开发,但必须明确标记:
programExecutionSourceMode=fixture-line-playback
operatorMessage=LinuxCNC task/HAL unavailable; fixture playback only
fullLinuxCncProgramExecutionReady=false
在真实 taskHalRuntime.loaded === true 且前置条件失败时,不应退回 fixture playback。
6. 开发验收命令
基础检查:
node web-rtcp-5axis-sim-plan/tests/node/verify_run_preconditions.mjs
node web-rtcp-5axis-sim-plan/tests/node/verify_linuxcnc_kinematics_runtime.mjs
node web-rtcp-5axis-sim-plan/tests/node/verify_machine_file_staging.mjs
node web-rtcp-5axis-sim-plan/tests/node/verify_linuxcnc_task_hal_runtime.mjs
npm --prefix web-rtcp-5axis-sim-plan/app run build
完整 node smoke:
npm --prefix web-rtcp-5axis-sim-plan/app run smoke:node
浏览器 smoke:
bash web-rtcp-5axis-sim-plan/tests/browser/verify_gmoccapy_shell_browser.sh
bash web-rtcp-5axis-sim-plan/tests/browser/verify_gmoccapy_dist_browser.sh
QA 证据采集:
node qa/web-rtcp-5axis-site-test/capture-toolpath-preview-cases.mjs
7. 完成标准
RUN 可以判定为完善,必须同时满足:
1. 每次 RUN 都能追溯到明确 INI。
2. 每次 RUN 都能说明机床类型和坐标轴。
3. 每次 RUN 都能说明使用哪个 LinuxCNC 五轴 kinematics module。
4. M428/M429/M430 的 switchkins 状态来自 LinuxCNC remap/HAL/task feedback 链。
5. activeLine、DRO、速度、DTG、程序时间来自同一个 task/HAL/motion feedback snapshot。
6. RUN 后 taskCycle/servoCycle 随时间持续推进,直到 paused/stopped/complete。
7. UI 高亮行和执行历史能复现逐行执行过程。
8. fallback playback 不能冒充 LinuxCNC task/HAL runtime。
未满足以上条件时,状态应继续标记为:
fullLinuxCncProgramExecutionReady=false
hardwareDrive=false
hostRealtimeKernel=false
externalUserMProcessReady=false