Files
cnc_wams/work/working8-暂停按钮/02-项目程序开发详细步骤.md
2026-07-07 16:46:39 -04:00

7.6 KiB
Raw Permalink Blame History

02-项目程序开发详细步骤

开发原则

  1. 以 LinuxCNC 源码语义为准,不在 JavaScript 层发明新的 CNC 暂停语义。
  2. wasm-port 的 wrapper 只能作为 native/WASM 边界适配,不能扩大为独立 CNC 语义实现。
  3. 先补 task/motion 可观测状态,再补 STEP再推进 TP 真实接入。
  4. 每一步必须有 Node WASM 测试和 Web 集成测试证据。

步骤 1补齐 task 层暂停恢复状态

目标文件:

  • wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_task_hal_wasm.cpp
  • wasm-port/tests/wasm/node/verify_task_hal_wasm.mjs
  • wasm-port/runtime/sdk/src/linuxcnc-task-hal.js
  • web-rtcp-5axis-xyzbc-trt-sim-plan/app/src/runtime/linuxcnc-task-hal-runtime.js

开发动作:

  1. TaskRuntime 增加字段:
    • std::string interp_resume_state = "IDLE";
  2. 初始化、reset、abort、home、program complete 时同步维护 interp_resume_state
  3. EMC_TASK_PLAN_PAUSE 分支中按 LinuxCNC 语义处理:
if (state.interp_state != "PAUSED") {
    state.interp_resume_state = state.interp_state.empty() ? "READING" : state.interp_state;
}
state.interp_state = "PAUSED";
state.exec_state = "PAUSED";
state.task_paused = true;
forward_motion_command("{\"type\":\"EMCMOT_PAUSE\"}");
  1. EMC_TASK_PLAN_RESUME 分支中按 LinuxCNC 语义处理:
const std::string resume = state.interp_resume_state == "PAUSED" || state.interp_resume_state.empty()
    ? "READING"
    : state.interp_resume_state;
state.interp_state = resume;
state.interp_resume_state = resume;
state.exec_state = resume == "IDLE" ? "DONE" : "WAITING_FOR_MOTION";
state.task_paused = false;
state.single_stepping = false;
forward_motion_command("{\"type\":\"EMCMOT_RESUME\"}");
  1. status_json() 输出 interpResumeState
  2. SDK 和 Web runtime wrapper 把 interpResumeState 转成小写并映射到 UI 状态。

验收:

  • pause 前为 READINGpause 后 interpResumeState=READING
  • resume 后恢复 READING,不是固定靠前端猜测。
  • pause 前为 WAITING 时 resume 能恢复 WAITING

步骤 2补齐 motion 层 immediate pause 语义

目标文件:

  • wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_motion_runtime.c
  • wasm-port/tests/wasm/node/verify_task_hal_wasm.mjs

当前风险:

lcmot_write_command_json()EMC_TRAJ_PAUSE 作为普通命令入队。如果队列中已有多个 movepause 可能排在 move 后执行。AXIS 用户点击暂停属于 GUI immediate command应尽快阻止继续消费运动队列。

开发动作:

  1. EMCMOT_PAUSEEMC_TRAJ_PAUSE 做即时状态切换:
    • lcmot_state.paused = 1
    • lcmot_state.current_vel = 0
    • lcmot_state.motion_type = 0
    • lcmot_state.in_position = 0
  2. 不清空运动队列。
  3. 暂停期间 lcmot_step_servo() 不消费普通 move只允许
    • STEP
    • RESUME
    • ABORT
  4. EMCMOT_RESUME 即时清除 paused后续 servo cycle 继续消费保留队列。
  5. 状态 JSON 增加:
    • motion.stepping
    • motion.idForStep 或同等 step 追踪字段。

验收:

  • 先入队多个 line move运行一部分后 pause。
  • pause 后连续运行 20 个 cycleprogramLine 不变、axis 不变、queueDepth 不减少。
  • resume 后 queueDepth 继续减少programLine 继续推进。

步骤 3实现 STEP 自动回暂停

目标文件:

  • wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_motion_runtime.c
  • wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_task_hal_wasm.cpp
  • wasm-port/tests/wasm/node/verify_task_hal_wasm.mjs
  • web-rtcp-5axis-xyzbc-trt-sim-plan/tests/node/verify_run_feedback_loop.mjs

LinuxCNC 对标:

  • EMCMOT_STEP 在 paused 时记录当前 motion id短暂恢复 TP
  • motion id 改变后自动 tpPause()
  • 外部仍把程序视为 paused。

开发动作:

  1. 在 motion runtime 增加:
    • int stepping;
    • int id_for_step;
    • int motion_id;
  2. 每执行一个普通 move 时递增 motion_id
  3. EMCMOT_STEP
    • 如果当前 paused设置 stepping=1id_for_step=motion_id
    • 允许消费一个普通 move
    • 保持对外 paused=true 或在状态中明确 paused=true, stepping=true
  4. lcmot_step_servo() 在 step 消费一个 move 后:
    • 自动恢复 paused=1
    • stepping=0
  5. task 层 EMC_TASK_PLAN_STEP
    • 不把解释器永久改成 running
    • step 完成后恢复 interpState=PAUSEDtaskPaused=true

验收:

  • paused 状态下 STEP 后只推进一个 line 或一个 motion id。
  • STEP 完成后 task.interpState=PAUSEDtaskPaused=truemotion.paused=true
  • 再次 Resume 可从 step 后位置继续运行。

步骤 4把 motion paused 字段接入 Web task policy

目标文件:

  • web-rtcp-5axis-xyzbc-trt-sim-plan/app/src/state/linuxcnc-task-policy.js
  • web-rtcp-5axis-xyzbc-trt-sim-plan/app/src/state/store.js
  • web-rtcp-5axis-xyzbc-trt-sim-plan/app/src/ui/axis-shell.js
  • web-rtcp-5axis-xyzbc-trt-sim-plan/tests/node/verify_run_feedback_loop.mjs

开发动作:

  1. taskHalStatus.uitaskHalStatus.motionStatus.motion.paused 映射 machine.motionPaused
  2. isProgramPaused() 判断改为包含:
    • state.machine.motionPaused === true
    • state.programRuntimeFeedback.paused === true
  3. canResumeRESUME gate 改为:
taskState == on
taskMode in auto/mdi
motionPaused 或 interpState paused 或 taskPaused
未被 resumeInhibit 阻止
  1. PAUSE_RESUME toggle 优先看 motion paused贴近 AXIS s.paused
  2. 保留菜单 Pause 的严格条件AUTO 且 interpStatereading/waiting

验收:

  • motion paused 已 true 但 interpState 同步稍晚时,工具栏按钮显示 Resume。
  • Resume 不再只依赖 interpState === paused
  • 菜单 Pause/Resume 与工具栏 toggle 逻辑仍分离。

步骤 5补充 TP 层暂停验证

目标文件:

  • wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_tp_wasm.c
  • wasm-port/tests/wasm/node/verify_tp_wasm.mjs

开发动作:

  1. 在 TP probe 中增加 pause/resume 场景:
    • 创建 TP
    • 加入至少两段 line
    • 运行若干 cycle
    • tpPause()
    • 继续运行若干 cycle
    • 验证位置不继续跨段推进或速度趋向 0
    • tpResume()
    • 验证可继续完成队列。
  2. 输出可测试字段:
    • tp_pause_rc=0
    • tp_resume_rc=0
    • tp_paused_velocity_zero=1
    • tp_resume_done=1

验收:

  • node wasm-port/tests/wasm/node/verify_tp_wasm.mjs 通过。
  • 证据显示 TP pause/resume 使用 vendored LinuxCNC TP API而不是 JS 模拟。

步骤 6构建与回归

推荐命令:

cd /home/mes123456/cnc_wams/wasm-port
./tools/build_task_hal_wasm.sh
./tools/build_tp_wasm.sh
node tests/wasm/node/verify_task_hal_wasm.mjs
node tests/wasm/node/verify_tp_wasm.mjs

Web 集成命令:

cd /home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan
npm --prefix app run build
node tests/node/verify_run_feedback_loop.mjs
APP_URL_PATH=/web-rtcp-5axis-xyzbc-trt-sim-plan/app/dist/index.html node tools/trace-pause-position-json.mjs
RUN_STABLE_BEFORE_FIRST_PAUSE_MS=3000 node tools/verify-estop-power-home-run-pause-50ms.mjs

验收输出至少包括:

  • linuxcnc_task_runtime_smoke=ok
  • tp_wasm_node_smoke=ok
  • run_feedback_status_loop_smoke=ok
  • pause_position_status=passed-position-frozen
  • verification_status=passed

步骤 7记录证据与关闭任务

每完成一个编号任务:

  1. 更新 03-推进台账.md
  2. 更新 04-任务矩阵.md 状态。
  3. 把命令、输出、trace 路径、截图目录写入 05-验收证据.md
  4. 如果出现新取舍,追加 06-决策记录.md