233 lines
7.6 KiB
Markdown
233 lines
7.6 KiB
Markdown
# 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 语义处理:
|
||
|
||
```cpp
|
||
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\"}");
|
||
```
|
||
|
||
4. 在 `EMC_TASK_PLAN_RESUME` 分支中按 LinuxCNC 语义处理:
|
||
|
||
```cpp
|
||
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\"}");
|
||
```
|
||
|
||
5. `status_json()` 输出 `interpResumeState`。
|
||
6. SDK 和 Web runtime wrapper 把 `interpResumeState` 转成小写并映射到 UI 状态。
|
||
|
||
验收:
|
||
|
||
- pause 前为 `READING`,pause 后 `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` 作为普通命令入队。如果队列中已有多个 move,pause 可能排在 move 后执行。AXIS 用户点击暂停属于 GUI immediate command,应尽快阻止继续消费运动队列。
|
||
|
||
开发动作:
|
||
|
||
1. 对 `EMCMOT_PAUSE` 或 `EMC_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 个 cycle,`programLine` 不变、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=1`、`id_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=PAUSED`、`taskPaused=true`。
|
||
|
||
验收:
|
||
|
||
- paused 状态下 STEP 后只推进一个 line 或一个 motion id。
|
||
- STEP 完成后 `task.interpState=PAUSED`、`taskPaused=true`、`motion.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.ui` 或 `taskHalStatus.motionStatus.motion.paused` 映射 `machine.motionPaused`。
|
||
2. `isProgramPaused()` 判断改为包含:
|
||
- `state.machine.motionPaused === true`
|
||
- `state.programRuntimeFeedback.paused === true`
|
||
3. `canResume` 和 `RESUME` gate 改为:
|
||
|
||
```text
|
||
taskState == on
|
||
taskMode in auto/mdi
|
||
motionPaused 或 interpState paused 或 taskPaused
|
||
未被 resumeInhibit 阻止
|
||
```
|
||
|
||
4. `PAUSE_RESUME` toggle 优先看 motion paused,贴近 AXIS `s.paused`。
|
||
5. 保留菜单 Pause 的严格条件:AUTO 且 `interpState` 为 `reading/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:构建与回归
|
||
|
||
推荐命令:
|
||
|
||
```bash
|
||
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 集成命令:
|
||
|
||
```bash
|
||
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`。
|
||
|