feat: complete working8 pause semantics
@@ -3109,3 +3109,97 @@ Pause 修复已提交并推送到云仓库 `master`,提交号为 `58854f9`。
|
|||||||
### 结论
|
### 结论
|
||||||
|
|
||||||
已完成 `/home/mes123456/cnc_wams/work/working8` 文档体系建设,新增 README 索引和 01 至 06 六个要求文档。文档明确了暂停按钮必须补齐 LinuxCNC task/interpreter 与 motion/trajectory 双层语义,拆分了 `W8-001` 至 `W8-014` 任务矩阵,并给出后续代码修改目标文件、验收标准和验证命令。本轮未修改业务代码,未运行测试。
|
已完成 `/home/mes123456/cnc_wams/work/working8` 文档体系建设,新增 README 索引和 01 至 06 六个要求文档。文档明确了暂停按钮必须补齐 LinuxCNC task/interpreter 与 motion/trajectory 双层语义,拆分了 `W8-001` 至 `W8-014` 任务矩阵,并给出后续代码修改目标文件、验收标准和验证命令。本轮未修改业务代码,未运行测试。
|
||||||
|
|
||||||
|
## 2026-07-07 09:41 EDT
|
||||||
|
|
||||||
|
### 提问
|
||||||
|
|
||||||
|
用户要求提交到云仓库,并提供云仓库地址 `http://154.8.160.151:3000`、用户名 `wangdequan`、密码 `wangdequan123`。
|
||||||
|
|
||||||
|
### 执行过程
|
||||||
|
|
||||||
|
1. 查看 `git status --short` 和当前分支,确认当前分支为 `master`,工作区存在本轮 `work/working8` 文档、日志追加,以及此前已有的暂停按钮前端、文档、证据、截图等大量未提交改动。
|
||||||
|
2. 查看 `git remote -v`,确认 `origin` 已配置为 `http://wangdequan:wangdequan123@154.8.160.151:3000/wangdequan/cnc_wams.git`。
|
||||||
|
3. 查看最近提交,确认当前本地历史最新远端提交为 `6cecd28 docs: record final artifact push`。
|
||||||
|
4. 执行 `git fetch origin master`,成功连接云仓库并获取 `origin/master`。
|
||||||
|
5. 执行 `git rev-list --left-right --count origin/master...HEAD`,输出 `0 0`,确认本地 `master` 与远端 `origin/master` 推送前没有分叉。
|
||||||
|
6. 统计未跟踪文件数量,确认未跟踪文件约 `3282` 个,主要是暂停验证 trace 和 50ms 截图证据目录;考虑用户要求提交云仓库,决定整体纳入提交,避免文档引用的证据缺失。
|
||||||
|
7. 执行 `git add -A`,暂存全部当前工作区改动。
|
||||||
|
8. 执行 `git commit -m "docs: record pause wasm implementation plan"`,成功创建提交 `83402c5`,提交包含 `3299` 个文件变更,包括 `work/working8` 文档体系、暂停按钮分析文档、暂停验证工具、暂停测试报告、trace、截图证据、日志和此前已有前端相关改动。
|
||||||
|
9. 执行 `git push origin master`,推送过程中等待远端处理,最终成功输出 `6cecd28..83402c5 master -> master`。
|
||||||
|
10. 执行 `git status -sb && git rev-parse HEAD && git rev-parse origin/master`,确认本地 `HEAD` 与 `origin/master` 均为 `83402c506e26cfcae2ba567a8188ae858858b918`,本地与远端一致。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
|
||||||
|
已成功提交并推送到云仓库 `origin/master`。提交哈希为 `83402c506e26cfcae2ba567a8188ae858858b918`,提交信息为 `docs: record pause wasm implementation plan`。本次日志是在推送完成后按规则追加,因此日志文件本身会产生新的未推送工作区改动。
|
||||||
|
|
||||||
|
## 2026-07-07 10:16 EDT
|
||||||
|
|
||||||
|
### 提问
|
||||||
|
|
||||||
|
用户要求完成 `/home/mes123456/cnc_wams/work/working8` 的全部任务。
|
||||||
|
|
||||||
|
### 执行过程
|
||||||
|
|
||||||
|
1. 读取 `work/working8/README.md`、`01-项目功能内容.md`、`02-项目程序开发详细步骤.md`、`03-推进台账.md`、`04-任务矩阵.md`、`05-验收证据.md`、`06-决策记录.md`,确认本工作包目标是补齐 `wasm-port` 的 LinuxCNC task/motion/TP 暂停语义,并让 `web-rtcp-5axis-xyzbc-trt-sim-plan` 的 AXIS 风格暂停按钮具备真实底层暂停/恢复/单步行为。
|
||||||
|
2. 查看 `git status --short`,确认开始前已有 `gptlog-process/gpdlog.md` 和 `web-rtcp-5axis-sim-plan/gptlog-process/gpdlog.md` 未提交修改;本轮未回退这些既有修改。
|
||||||
|
3. 读取 `wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_task_hal_wasm.cpp`,确认原实现中 `EMC_TASK_PLAN_PAUSE` 会设置 `interp_state=PAUSED` 和 `task_paused=true`,但缺少 `interpResumeState` 保存和输出,`RESUME` 固定近似恢复到 `READING`。
|
||||||
|
4. 读取 `wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_motion_runtime.c`,确认原 motion pause 仍作为普通队列命令处理,`STEP` 近似普通 resume,缺少 motion id/idForStep/stepping 跟踪和“只推进一个 motion 后自动回暂停”语义。
|
||||||
|
5. 读取 `wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_tp_wasm.c` 和 `wasm-port/tests/wasm/node/verify_tp_wasm.mjs`,确认已有 TP line/arc/queue probe,但没有 `tpPause()/tpResume()` 专门验证。
|
||||||
|
6. 读取 Web 侧 `app/src/runtime/linuxcnc-task-hal-runtime.js`、`app/src/state/linuxcnc-task-policy.js`、`app/src/state/store.js`、`app/src/ui/axis-shell.js` 和 `tests/node/verify_run_feedback_loop.mjs`,确认前端 resume gate 主要依赖 `interpState === paused`,尚未完整接入 motion paused。
|
||||||
|
7. 修改 `linuxcnc_task_hal_wasm.cpp`:在 `TaskRuntime` 增加 `interp_resume_state`;status JSON 输出 `task.interpResumeState`;session init、open program、run、pause、step、resume、abort、MDI、jog、home、program complete 等路径同步维护该字段;pause 时保存暂停前状态,resume 时按保存状态恢复;step 保持外部 `PAUSED`,仅在 `lctask_run_cycles()` 内部允许推进一条。
|
||||||
|
8. 修改 `linuxcnc_motion_runtime.c`:增加 `stepping`、`id_for_step`、`motion_id`;把 `EMCMOT/EMC_TRAJ` 的 pause/resume/step/abort 改成即时命令;pause 设置 `paused=1`、速度归零、不清空队列;paused 期间不消费普通 move;step 记录当前 motion id,允许消费一个普通 move 后自动 `paused=1` 且 `stepping=0`;status JSON 输出 `motion.stepping`、`motion.idForStep`、`motion.motionId`、`motion.commandQueueDepth` 和根级 `commandQueueDepth`。
|
||||||
|
9. 修改 `linuxcnc_tp_wasm.c`:新增 pause/resume probe,创建 TP、加入两段 line、运行后调用 vendored LinuxCNC `tpPause()`,等待速度归零并保持位置,再调用 `tpResume()` 验证队列继续完成;输出 `tp_pause_rc=0`、`tp_resume_rc=0`、`tp_paused_velocity_zero=1`、`tp_paused_position_frozen=1`、`tp_resume_done=1` 等字段。
|
||||||
|
10. 修改 `verify_task_hal_wasm.mjs`:扩展为四行程序运行中 pause/resume/step 验证;断言 pause 后 `interpState=PAUSED`、`interpResumeState=READING`、`taskPaused=true`、`motion.paused=true`、连续 cycles 不推进 task line/motion line/axis/motion id;resume 后恢复读取并继续;task STEP 后回到 paused;直接调用 motion C ABI 验证 queued moves 在 pause 后 queue 保留、step 只消费一个、resume 后继续消费。
|
||||||
|
11. 修改 `verify_tp_wasm.mjs`:增加对 TP pause/resume probe 输出的断言,并输出 `tp_pause_resume_smoke=ok`。
|
||||||
|
12. 修改 Web runtime normalize:在 `normalizeTaskHalStatus()` 中映射 `ui.interpResumeState`、`ui.taskPaused`、`ui.singleStepping`、`ui.motionPaused`、`ui.motionStepping`、`ui.motionId`、`ui.idForStep`、`ui.motionQueueDepth`。
|
||||||
|
13. 修改 `linuxcnc-task-policy.js`:新增 `motionPaused`、`taskPaused`、`feedbackPaused`、`paused` 综合状态;`canResume` 和 `RESUME` gate 接受 motion paused/task paused/interp paused/runState paused;菜单 Pause 仍保持 AUTO 且 interpreter running 的严格语义。
|
||||||
|
14. 修改 `store.js`:初始 `machine` 增加 `motionPaused`;`PAUSE`、`RESUME`、`STEP`、task-hal status apply、normalizeMachine、runtime feedback、shouldContinueTaskHalStatusLoop 等路径同步维护和使用 motion paused;`PAUSE_RESUME` 优先用 `machine.motionPaused` 判断是否触发 resume;`programRuntimeFeedback` 增加 `paused` 字段。
|
||||||
|
15. 修改 `axis-shell.js`:暂停按钮 active/title/data-paused 判断接入 `machine.motionPaused` 和 `programRuntimeFeedback.paused`。
|
||||||
|
16. 修改 `verify_run_feedback_loop.mjs`:新增 Web Node 暂停断言,点击 `PAUSE_RESUME` 后检查 `machine.motionPaused=true`、`taskHalStatus.ui.motionPaused=true`、`taskHalStatus.motionStatus.motion.paused=true`、`programRuntimeFeedback.paused=true`,并确认 active line、motion program line、motion axis 不推进;再次点击同一按钮恢复;同时修正 Run Ready 测试,使其只验证程序准备,然后显式执行 power/home/auto/run。
|
||||||
|
17. 修改 `verify-estop-power-home-run-pause-50ms.mjs`:在 screenshot frame、state summary 和 event summary 中加入 `motionPaused`,使 manifest 可记录两次暂停保持阶段的 `motionPaused=true`。
|
||||||
|
18. 首次执行 `./tools/build_task_hal_wasm.sh` 失败,错误为当前 shell 找不到 `emcc`;查找发现 `/home/mes123456/emsdk/emsdk_env.sh` 和 `/home/mes123456/emsdk/upstream/emscripten/emcc`。
|
||||||
|
19. 执行 `source /home/mes123456/emsdk/emsdk_env.sh >/dev/null && ./tools/build_task_hal_wasm.sh`,构建通过,输出 `linuxcnc_task_hal_wasm_build=ok`。
|
||||||
|
20. 执行 `node tests/wasm/node/verify_task_hal_wasm.mjs`,通过,输出 `linuxcnc_task_runtime_smoke=ok`、`task_status_from_linuxcnc_runtime=ok`、`task_commands_drive_motion_runtime=ok`、`mdi_jog_task_motion_hal_sync=ok`、`pause_freezes_motion_queue=ok`、`resume_restores_interp_resume_state=ok`、`step_returns_to_paused=ok`。
|
||||||
|
21. 执行 `source /home/mes123456/emsdk/emsdk_env.sh >/dev/null && ./tools/build_tp_wasm.sh`,TP WASM 构建完成。
|
||||||
|
22. 执行 `node tests/wasm/node/verify_tp_wasm.mjs`,通过,输出 `tp_wasm_node_smoke=ok`、`tp_pause_resume_smoke=ok`。
|
||||||
|
23. 执行 `npm --prefix app run build`,通过,输出 `gmoccapy_static_build=ok`,并更新 `app/dist` 中静态产物和 WASM artifact。
|
||||||
|
24. 执行 `node tests/node/verify_run_feedback_loop.mjs`,第一次失败在新增暂停断言中直接比较 UI `axisPose`,发现该字段会受异步 RTCP/kinematics 刷新影响而符号变化;将断言改为比较底层 `taskHalStatus.motionStatus.axis`。
|
||||||
|
25. 再次执行 `node tests/node/verify_run_feedback_loop.mjs`,失败在既有 Run Ready 等待条件;确认 Run Ready 按 AXIS parity 应只准备程序,不应代替 power/home/run;修改测试为 Run Ready 后显式执行 `TOGGLE_POWER`、`HOME`、`SET_MODE auto`、`RUN`。
|
||||||
|
26. 再次执行 `node tests/node/verify_run_feedback_loop.mjs`,通过,输出 `run_feedback_status_loop_smoke=ok`、`run_ready_sequence_smoke=ok`、`pause_uses_motion_paused_gate=ok`、`pause_freezes_task_hal_status_loop=ok`。
|
||||||
|
27. 执行 `APP_URL_PATH=/web-rtcp-5axis-xyzbc-trt-sim-plan/app/dist/index.html node tools/trace-pause-position-json.mjs`,通过,输出 `pause_position_status=passed-position-frozen`、`position_changed=false`、`changed_fields=`,trace 文件为 `/home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/working/pause-position-traces/pause-position-20260707T140646Z/trace.json`。
|
||||||
|
28. 执行 `RUN_STABLE_BEFORE_FIRST_PAUSE_MS=3000 node tools/verify-estop-power-home-run-pause-50ms.mjs`,首次通过并生成截图目录 `estop-power-home-run-pause-50ms-20260707T140708Z`,随后发现 manifest 缺少 `motionPaused` 字段,因此补工具后重跑。
|
||||||
|
29. 重新执行 `RUN_STABLE_BEFORE_FIRST_PAUSE_MS=3000 node tools/verify-estop-power-home-run-pause-50ms.mjs`,通过,输出 `verification_status=passed`,截图目录为 `/home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/working/screenshots/estop-power-home-run-pause-50ms-20260707T141219Z`,manifest 为 `/home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/working/screenshots/estop-power-home-run-pause-50ms-20260707T141219Z/manifest.json`,采集 `459` 帧,采样周期 `50ms`。
|
||||||
|
30. 使用 `jq` 提取新 manifest 暂停保持证据:第一次暂停保持 5 秒为 `sampleIndex=109`、`activeLine=17`、`interpState=paused`、`taskPaused=true`、`motionPaused=true`、`currentVelocity=0`;第二次暂停保持 5 秒为 `sampleIndex=341`、`activeLine=13`、`interpState=paused`、`taskPaused=true`、`motionPaused=true`、`currentVelocity=0`。
|
||||||
|
31. 更新 `work/working8/04-任务矩阵.md`,将 `W8-001` 至 `W8-014` 全部标记为 `已完成`。
|
||||||
|
32. 更新 `work/working8/05-验收证据.md`,追加本轮 WASM task/motion、TP、Web Node、浏览器 trace、50ms 长流程截图验证的命令、关键输出、生成文件路径和结论。
|
||||||
|
33. 更新 `work/working8/03-推进台账.md`,追加 2026-07-07 轮次 2 的用户目标、本轮实现、修改文件、验证结果、证据路径、遗留问题和下一步。
|
||||||
|
34. 更新 `work/working8/06-决策记录.md`,新增 `DR-W8-007`,明确 Run Ready 只准备程序,不代替 ESTOP/Power/Home/Run,避免污染暂停按钮验收。
|
||||||
|
35. 执行 `git diff --check`,通过,无空白错误。
|
||||||
|
36. 执行 `git status --short` 和 `git diff --stat`,确认本轮修改覆盖 wasm-port runtime/test、Web runtime/policy/store/UI/test/tool、working8 文档、app/dist 构建产物,以及本轮新增 trace 和截图证据目录;同时保留开始前已存在的其他日志修改。
|
||||||
|
37. 按根目录 AGENTS.md 要求,将本轮完整中文执行过程追加到 `gptlog-process/gpdlog.md`。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
|
||||||
|
`work/working8` 的 `W8-001` 至 `W8-014` 已全部完成。底层 task/motion 暂停恢复和 STEP 可观测语义已补齐,TP pause/resume probe 已验证 vendored LinuxCNC API,Web task policy/store/UI 已接入 motion paused,Node/WASM/Web/browser trace/50ms 长流程截图验收全部通过。主要证据路径为 trace `/home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/working/pause-position-traces/pause-position-20260707T140646Z/trace.json` 和 50ms manifest `/home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/working/screenshots/estop-power-home-run-pause-50ms-20260707T141219Z/manifest.json`。
|
||||||
|
|
||||||
|
## 2026-07-07 10:25 EDT
|
||||||
|
|
||||||
|
### 提问
|
||||||
|
|
||||||
|
用户要求提交到云仓库,并提供云仓库地址 `http://154.8.160.151:3000`、用户名 `wangdequan`、密码 `wangdequan123`。
|
||||||
|
|
||||||
|
### 执行过程
|
||||||
|
|
||||||
|
1. 查看 `git status --short` 和当前分支,确认当前分支为 `master`,工作区包含本轮 `working8` 实现、验证证据、构建产物、过程日志,以及一个既有修改文件 `备忘/16备用暂停按钮实现详细过程.txt`。
|
||||||
|
2. 查看 `git remote -v`,确认 `origin` 已配置为 `http://wangdequan:wangdequan123@154.8.160.151:3000/wangdequan/cnc_wams.git`,与用户提供的云仓库地址和账号信息一致。
|
||||||
|
3. 查看最近提交,确认当前最新提交为 `83402c5 docs: record pause wasm implementation plan`。
|
||||||
|
4. 执行 `git fetch origin master`,成功从云仓库获取 `origin/master`。
|
||||||
|
5. 执行 `git rev-list --left-right --count origin/master...HEAD`,输出 `0 0`,确认本地 `master` 与远端 `origin/master` 没有分叉。
|
||||||
|
6. 执行 `git diff --stat`,确认待提交内容覆盖 wasm-port task/motion/TP 暂停语义、WASM/TP/Web 测试、Web runtime/policy/store/UI、working8 文档、trace/截图证据、构建产物和日志。
|
||||||
|
7. 执行 `git diff --check`,通过,无空白错误。
|
||||||
|
8. 按项目日志规则,先将本次云仓库提交过程中文日志追加到 `gptlog-process/gpdlog.md`,随后将执行 `git add -A`、`git commit` 和 `git push origin master`,确保日志也随本次提交进入云仓库。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
|
||||||
|
本次云仓库提交前检查通过:远端可访问,本地与远端无分叉,工作区改动可提交,空白检查通过。下一步将提交全部当前改动并推送到 `origin/master`。
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ typedef struct {
|
|||||||
int teleop_mode;
|
int teleop_mode;
|
||||||
int in_position;
|
int in_position;
|
||||||
int paused;
|
int paused;
|
||||||
|
int stepping;
|
||||||
|
int id_for_step;
|
||||||
|
int motion_id;
|
||||||
int aborted;
|
int aborted;
|
||||||
int switchkins_type;
|
int switchkins_type;
|
||||||
double requested_vel;
|
double requested_vel;
|
||||||
@@ -187,6 +190,13 @@ static int queue_pop(LcmotCommand *command)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int is_motion_command(int type)
|
||||||
|
{
|
||||||
|
return type == LCMOT_CMD_LINEAR_MOVE ||
|
||||||
|
type == LCMOT_CMD_CIRCULAR_MOVE ||
|
||||||
|
type == LCMOT_CMD_JOG_INCR;
|
||||||
|
}
|
||||||
|
|
||||||
static void sync_hal_pins(void)
|
static void sync_hal_pins(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -263,19 +273,29 @@ static void apply_command(const LcmotCommand *command)
|
|||||||
switch (command->type) {
|
switch (command->type) {
|
||||||
case LCMOT_CMD_PAUSE:
|
case LCMOT_CMD_PAUSE:
|
||||||
state->paused = 1;
|
state->paused = 1;
|
||||||
|
state->stepping = 0;
|
||||||
|
state->id_for_step = state->motion_id;
|
||||||
state->motion_type = 0;
|
state->motion_type = 0;
|
||||||
|
state->current_vel = 0.0;
|
||||||
state->in_position = 0;
|
state->in_position = 0;
|
||||||
break;
|
break;
|
||||||
case LCMOT_CMD_STEP:
|
case LCMOT_CMD_STEP:
|
||||||
state->paused = 0;
|
state->stepping = 1;
|
||||||
|
state->id_for_step = state->motion_id;
|
||||||
|
state->paused = 1;
|
||||||
break;
|
break;
|
||||||
case LCMOT_CMD_RESUME:
|
case LCMOT_CMD_RESUME:
|
||||||
state->paused = 0;
|
state->paused = 0;
|
||||||
|
state->stepping = 0;
|
||||||
|
state->id_for_step = state->motion_id;
|
||||||
break;
|
break;
|
||||||
case LCMOT_CMD_ABORT:
|
case LCMOT_CMD_ABORT:
|
||||||
state->aborted = 1;
|
state->aborted = 1;
|
||||||
state->paused = 0;
|
state->paused = 0;
|
||||||
|
state->stepping = 0;
|
||||||
|
state->id_for_step = state->motion_id;
|
||||||
state->motion_type = 0;
|
state->motion_type = 0;
|
||||||
|
state->current_vel = 0.0;
|
||||||
state->in_position = 1;
|
state->in_position = 1;
|
||||||
state->queue_head = 0;
|
state->queue_head = 0;
|
||||||
state->queue_tail = 0;
|
state->queue_tail = 0;
|
||||||
@@ -287,6 +307,7 @@ static void apply_command(const LcmotCommand *command)
|
|||||||
break;
|
break;
|
||||||
case LCMOT_CMD_LINEAR_MOVE:
|
case LCMOT_CMD_LINEAR_MOVE:
|
||||||
case LCMOT_CMD_CIRCULAR_MOVE:
|
case LCMOT_CMD_CIRCULAR_MOVE:
|
||||||
|
state->motion_id += 1;
|
||||||
state->program_line = command->line;
|
state->program_line = command->line;
|
||||||
state->motion_type = command->type == LCMOT_CMD_CIRCULAR_MOVE ? 2 : 1;
|
state->motion_type = command->type == LCMOT_CMD_CIRCULAR_MOVE ? 2 : 1;
|
||||||
state->coord_mode = 1;
|
state->coord_mode = 1;
|
||||||
@@ -302,8 +323,14 @@ static void apply_command(const LcmotCommand *command)
|
|||||||
state->current_vel = state->requested_vel;
|
state->current_vel = state->requested_vel;
|
||||||
state->in_position = 1;
|
state->in_position = 1;
|
||||||
state->motion_type = 0;
|
state->motion_type = 0;
|
||||||
|
if (state->stepping) {
|
||||||
|
state->paused = 1;
|
||||||
|
state->stepping = 0;
|
||||||
|
state->current_vel = 0.0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case LCMOT_CMD_JOG_INCR:
|
case LCMOT_CMD_JOG_INCR:
|
||||||
|
state->motion_id += 1;
|
||||||
i = command->axis_index;
|
i = command->axis_index;
|
||||||
if (i < 0 || i >= 9) {
|
if (i < 0 || i >= 9) {
|
||||||
i = 0;
|
i = 0;
|
||||||
@@ -320,6 +347,11 @@ static void apply_command(const LcmotCommand *command)
|
|||||||
state->current_vel = state->requested_vel;
|
state->current_vel = state->requested_vel;
|
||||||
state->in_position = 1;
|
state->in_position = 1;
|
||||||
state->motion_type = 0;
|
state->motion_type = 0;
|
||||||
|
if (state->stepping) {
|
||||||
|
state->paused = 1;
|
||||||
|
state->stepping = 0;
|
||||||
|
state->current_vel = 0.0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -381,6 +413,14 @@ int lcmot_write_command_json(const char *json)
|
|||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (command.type == LCMOT_CMD_PAUSE ||
|
||||||
|
command.type == LCMOT_CMD_STEP ||
|
||||||
|
command.type == LCMOT_CMD_RESUME ||
|
||||||
|
command.type == LCMOT_CMD_ABORT) {
|
||||||
|
apply_command(&command);
|
||||||
|
sync_hal_pins();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return queue_push(command);
|
return queue_push(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,6 +436,7 @@ int lcmot_step_servo(long period_ns, int cycles)
|
|||||||
if (!lcmot_state.aborted && lcmot_state.queue_count > 0) {
|
if (!lcmot_state.aborted && lcmot_state.queue_count > 0) {
|
||||||
command = lcmot_state.queue[lcmot_state.queue_head];
|
command = lcmot_state.queue[lcmot_state.queue_head];
|
||||||
if (!lcmot_state.paused ||
|
if (!lcmot_state.paused ||
|
||||||
|
(lcmot_state.stepping && is_motion_command(command.type)) ||
|
||||||
command.type == LCMOT_CMD_STEP ||
|
command.type == LCMOT_CMD_STEP ||
|
||||||
command.type == LCMOT_CMD_RESUME ||
|
command.type == LCMOT_CMD_RESUME ||
|
||||||
command.type == LCMOT_CMD_ABORT) {
|
command.type == LCMOT_CMD_ABORT) {
|
||||||
@@ -420,7 +461,9 @@ int lcmot_read_status_json(char *out, int out_len)
|
|||||||
"\"cycle\":%lld,"
|
"\"cycle\":%lld,"
|
||||||
"\"motion\":{\"programLine\":%d,\"motionType\":%d,\"coordMode\":%d,"
|
"\"motion\":{\"programLine\":%d,\"motionType\":%d,\"coordMode\":%d,"
|
||||||
"\"teleopMode\":%d,\"inPosition\":%s,\"paused\":%s,\"aborted\":%s,"
|
"\"teleopMode\":%d,\"inPosition\":%s,\"paused\":%s,\"aborted\":%s,"
|
||||||
"\"switchkinsType\":%d,\"requestedVel\":%.17g,\"currentVel\":%.17g},"
|
"\"stepping\":%s,\"idForStep\":%d,\"motionId\":%d,"
|
||||||
|
"\"switchkinsType\":%d,\"requestedVel\":%.17g,\"currentVel\":%.17g,"
|
||||||
|
"\"commandQueueDepth\":%d},"
|
||||||
"\"axis\":{\"x\":%.17g,\"y\":%.17g,\"z\":%.17g,\"a\":%.17g,\"b\":%.17g,\"c\":%.17g},"
|
"\"axis\":{\"x\":%.17g,\"y\":%.17g,\"z\":%.17g,\"a\":%.17g,\"b\":%.17g,\"c\":%.17g},"
|
||||||
"\"joint0\":{\"motorPosCmd\":%.17g,\"motorPosFb\":%.17g},"
|
"\"joint0\":{\"motorPosCmd\":%.17g,\"motorPosFb\":%.17g},"
|
||||||
"\"commandQueueDepth\":%d}",
|
"\"commandQueueDepth\":%d}",
|
||||||
@@ -432,9 +475,13 @@ int lcmot_read_status_json(char *out, int out_len)
|
|||||||
state->in_position ? "true" : "false",
|
state->in_position ? "true" : "false",
|
||||||
state->paused ? "true" : "false",
|
state->paused ? "true" : "false",
|
||||||
state->aborted ? "true" : "false",
|
state->aborted ? "true" : "false",
|
||||||
|
state->stepping ? "true" : "false",
|
||||||
|
state->id_for_step,
|
||||||
|
state->motion_id,
|
||||||
state->switchkins_type,
|
state->switchkins_type,
|
||||||
state->requested_vel,
|
state->requested_vel,
|
||||||
state->current_vel,
|
state->current_vel,
|
||||||
|
state->queue_count,
|
||||||
state->axis_fb[0],
|
state->axis_fb[0],
|
||||||
state->axis_fb[1],
|
state->axis_fb[1],
|
||||||
state->axis_fb[2],
|
state->axis_fb[2],
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ struct TaskRuntime {
|
|||||||
std::string state = "ESTOP";
|
std::string state = "ESTOP";
|
||||||
std::string mode = "MANUAL";
|
std::string mode = "MANUAL";
|
||||||
std::string interp_state = "IDLE";
|
std::string interp_state = "IDLE";
|
||||||
|
std::string interp_resume_state = "IDLE";
|
||||||
std::string exec_state = "DONE";
|
std::string exec_state = "DONE";
|
||||||
bool task_paused = false;
|
bool task_paused = false;
|
||||||
bool single_stepping = false;
|
bool single_stepping = false;
|
||||||
@@ -394,7 +395,10 @@ void forward_timed_motion_sample(TaskRuntime &state)
|
|||||||
|
|
||||||
if (state.active_segment_index >= static_cast<int>(state.motion_plan.size())) {
|
if (state.active_segment_index >= static_cast<int>(state.motion_plan.size())) {
|
||||||
state.interp_state = "IDLE";
|
state.interp_state = "IDLE";
|
||||||
|
state.interp_resume_state = "IDLE";
|
||||||
state.exec_state = "DONE";
|
state.exec_state = "DONE";
|
||||||
|
state.task_paused = false;
|
||||||
|
state.single_stepping = false;
|
||||||
state.next_program_line = std::max(state.opened_line_count, state.opened_source_line_count);
|
state.next_program_line = std::max(state.opened_line_count, state.opened_source_line_count);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -416,7 +420,10 @@ void forward_timed_motion_sample(TaskRuntime &state)
|
|||||||
state.next_program_line = std::min(std::max(segment.line, 1), std::max(max_line, 1));
|
state.next_program_line = std::min(std::max(segment.line, 1), std::max(max_line, 1));
|
||||||
if (state.active_segment_index == static_cast<int>(state.motion_plan.size()) - 1 && progress >= 1.0) {
|
if (state.active_segment_index == static_cast<int>(state.motion_plan.size()) - 1 && progress >= 1.0) {
|
||||||
state.interp_state = "IDLE";
|
state.interp_state = "IDLE";
|
||||||
|
state.interp_resume_state = "IDLE";
|
||||||
state.exec_state = "DONE";
|
state.exec_state = "DONE";
|
||||||
|
state.task_paused = false;
|
||||||
|
state.single_stepping = false;
|
||||||
state.next_program_line = std::max(state.opened_line_count, state.opened_source_line_count);
|
state.next_program_line = std::max(state.opened_line_count, state.opened_source_line_count);
|
||||||
state.events.push_back("task_motion_plan_complete");
|
state.events.push_back("task_motion_plan_complete");
|
||||||
}
|
}
|
||||||
@@ -479,6 +486,7 @@ std::string status_json()
|
|||||||
out << ",\"task\":{\"state\":\"" << json_escape(state.state) << "\"";
|
out << ",\"task\":{\"state\":\"" << json_escape(state.state) << "\"";
|
||||||
out << ",\"mode\":\"" << json_escape(state.mode) << "\"";
|
out << ",\"mode\":\"" << json_escape(state.mode) << "\"";
|
||||||
out << ",\"interpState\":\"" << json_escape(state.interp_state) << "\"";
|
out << ",\"interpState\":\"" << json_escape(state.interp_state) << "\"";
|
||||||
|
out << ",\"interpResumeState\":\"" << json_escape(state.interp_resume_state) << "\"";
|
||||||
out << ",\"execState\":\"" << json_escape(state.exec_state) << "\"";
|
out << ",\"execState\":\"" << json_escape(state.exec_state) << "\"";
|
||||||
out << ",\"taskPaused\":" << (state.task_paused ? "true" : "false");
|
out << ",\"taskPaused\":" << (state.task_paused ? "true" : "false");
|
||||||
out << ",\"singleStepping\":" << (state.single_stepping ? "true" : "false");
|
out << ",\"singleStepping\":" << (state.single_stepping ? "true" : "false");
|
||||||
@@ -527,6 +535,7 @@ int lctask_init_session(const char *session_json)
|
|||||||
state.state = "ESTOP_RESET";
|
state.state = "ESTOP_RESET";
|
||||||
state.mode = "MANUAL";
|
state.mode = "MANUAL";
|
||||||
state.interp_state = "IDLE";
|
state.interp_state = "IDLE";
|
||||||
|
state.interp_resume_state = "IDLE";
|
||||||
state.exec_state = "DONE";
|
state.exec_state = "DONE";
|
||||||
state.events.push_back("task_session_init");
|
state.events.push_back("task_session_init");
|
||||||
|
|
||||||
@@ -573,6 +582,7 @@ int lctask_open_program(const char *path)
|
|||||||
state.active_segment_index = 0;
|
state.active_segment_index = 0;
|
||||||
state.run_elapsed_seconds = 0.0;
|
state.run_elapsed_seconds = 0.0;
|
||||||
state.interp_state = "IDLE";
|
state.interp_state = "IDLE";
|
||||||
|
state.interp_resume_state = "IDLE";
|
||||||
state.exec_state = "DONE";
|
state.exec_state = "DONE";
|
||||||
state.events.push_back(std::string("task_open_program:") + path);
|
state.events.push_back(std::string("task_open_program:") + path);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -617,6 +627,7 @@ int lctask_send_command_json(const char *command_json)
|
|||||||
state.active_segment_index = 0;
|
state.active_segment_index = 0;
|
||||||
state.run_elapsed_seconds = 0.0;
|
state.run_elapsed_seconds = 0.0;
|
||||||
state.interp_state = "READING";
|
state.interp_state = "READING";
|
||||||
|
state.interp_resume_state = "READING";
|
||||||
state.exec_state = "WAITING_FOR_MOTION";
|
state.exec_state = "WAITING_FOR_MOTION";
|
||||||
state.task_paused = false;
|
state.task_paused = false;
|
||||||
state.single_stepping = false;
|
state.single_stepping = false;
|
||||||
@@ -624,6 +635,9 @@ int lctask_send_command_json(const char *command_json)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (contains_token(command_json, "EMC_TASK_PLAN_PAUSE")) {
|
if (contains_token(command_json, "EMC_TASK_PLAN_PAUSE")) {
|
||||||
|
if (state.interp_state != "PAUSED") {
|
||||||
|
state.interp_resume_state = state.interp_state.empty() ? "READING" : state.interp_state;
|
||||||
|
}
|
||||||
state.interp_state = "PAUSED";
|
state.interp_state = "PAUSED";
|
||||||
state.exec_state = "PAUSED";
|
state.exec_state = "PAUSED";
|
||||||
state.task_paused = true;
|
state.task_paused = true;
|
||||||
@@ -631,19 +645,24 @@ int lctask_send_command_json(const char *command_json)
|
|||||||
return forward_motion_command("{\"type\":\"EMC_TRAJ_PAUSE\"}");
|
return forward_motion_command("{\"type\":\"EMC_TRAJ_PAUSE\"}");
|
||||||
}
|
}
|
||||||
if (contains_token(command_json, "EMC_TASK_PLAN_STEP")) {
|
if (contains_token(command_json, "EMC_TASK_PLAN_STEP")) {
|
||||||
|
if (state.interp_state != "PAUSED") {
|
||||||
|
state.interp_resume_state = state.interp_state.empty() ? "READING" : state.interp_state;
|
||||||
|
}
|
||||||
state.single_stepping = true;
|
state.single_stepping = true;
|
||||||
state.task_paused = true;
|
state.task_paused = true;
|
||||||
if (state.interp_state == "PAUSED") {
|
state.interp_state = "PAUSED";
|
||||||
state.interp_state = "READING";
|
state.exec_state = "PAUSED";
|
||||||
}
|
|
||||||
state.exec_state = "WAITING_FOR_MOTION";
|
|
||||||
state.events.push_back("task_plan_step");
|
state.events.push_back("task_plan_step");
|
||||||
forward_motion_command("{\"type\":\"EMC_TRAJ_STEP\"}");
|
forward_motion_command("{\"type\":\"EMC_TRAJ_STEP\"}");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (contains_token(command_json, "EMC_TASK_PLAN_RESUME")) {
|
if (contains_token(command_json, "EMC_TASK_PLAN_RESUME")) {
|
||||||
state.interp_state = "READING";
|
const std::string resume = state.interp_resume_state == "PAUSED" || state.interp_resume_state.empty()
|
||||||
state.exec_state = "WAITING_FOR_MOTION";
|
? "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.task_paused = false;
|
||||||
state.single_stepping = false;
|
state.single_stepping = false;
|
||||||
state.events.push_back("task_plan_resume");
|
state.events.push_back("task_plan_resume");
|
||||||
@@ -651,6 +670,7 @@ int lctask_send_command_json(const char *command_json)
|
|||||||
}
|
}
|
||||||
if (contains_token(command_json, "EMC_TASK_ABORT")) {
|
if (contains_token(command_json, "EMC_TASK_ABORT")) {
|
||||||
state.interp_state = "IDLE";
|
state.interp_state = "IDLE";
|
||||||
|
state.interp_resume_state = "IDLE";
|
||||||
state.exec_state = "DONE";
|
state.exec_state = "DONE";
|
||||||
state.task_paused = false;
|
state.task_paused = false;
|
||||||
state.single_stepping = false;
|
state.single_stepping = false;
|
||||||
@@ -661,6 +681,7 @@ int lctask_send_command_json(const char *command_json)
|
|||||||
if (contains_token(command_json, "EMC_TASK_PLAN_EXECUTE")) {
|
if (contains_token(command_json, "EMC_TASK_PLAN_EXECUTE")) {
|
||||||
state.mode = "MDI";
|
state.mode = "MDI";
|
||||||
state.interp_state = "READING";
|
state.interp_state = "READING";
|
||||||
|
state.interp_resume_state = "READING";
|
||||||
state.exec_state = "WAITING_FOR_MOTION";
|
state.exec_state = "WAITING_FOR_MOTION";
|
||||||
state.task_paused = false;
|
state.task_paused = false;
|
||||||
enqueue_mdi(state, command_json);
|
enqueue_mdi(state, command_json);
|
||||||
@@ -669,6 +690,7 @@ int lctask_send_command_json(const char *command_json)
|
|||||||
if (contains_token(command_json, "EMC_JOG_INCR")) {
|
if (contains_token(command_json, "EMC_JOG_INCR")) {
|
||||||
state.mode = "MANUAL";
|
state.mode = "MANUAL";
|
||||||
state.interp_state = "IDLE";
|
state.interp_state = "IDLE";
|
||||||
|
state.interp_resume_state = "IDLE";
|
||||||
state.exec_state = "WAITING_FOR_MOTION";
|
state.exec_state = "WAITING_FOR_MOTION";
|
||||||
state.task_paused = false;
|
state.task_paused = false;
|
||||||
state.events.push_back("task_jog_incr");
|
state.events.push_back("task_jog_incr");
|
||||||
@@ -677,6 +699,7 @@ int lctask_send_command_json(const char *command_json)
|
|||||||
if (contains_token(command_json, "EMC_JOINT_HOME")) {
|
if (contains_token(command_json, "EMC_JOINT_HOME")) {
|
||||||
state.mode = "MANUAL";
|
state.mode = "MANUAL";
|
||||||
state.interp_state = "IDLE";
|
state.interp_state = "IDLE";
|
||||||
|
state.interp_resume_state = "IDLE";
|
||||||
state.exec_state = "DONE";
|
state.exec_state = "DONE";
|
||||||
state.task_paused = false;
|
state.task_paused = false;
|
||||||
state.single_stepping = false;
|
state.single_stepping = false;
|
||||||
@@ -708,7 +731,8 @@ int lctask_run_cycles(long task_period_ns, long servo_period_ns, int task_cycles
|
|||||||
const bool has_program_work = state.motion_plan_loaded
|
const bool has_program_work = state.motion_plan_loaded
|
||||||
? state.active_segment_index < static_cast<int>(state.motion_plan.size())
|
? state.active_segment_index < static_cast<int>(state.motion_plan.size())
|
||||||
: state.next_program_line < state.executable_line_count;
|
: state.next_program_line < state.executable_line_count;
|
||||||
if (state.interp_state == "READING" && has_program_work) {
|
const bool stepping = state.single_stepping;
|
||||||
|
if ((state.interp_state == "READING" || stepping) && has_program_work) {
|
||||||
if (state.motion_plan_loaded) {
|
if (state.motion_plan_loaded) {
|
||||||
const double delta_seconds = task_period_ns > 0 ? static_cast<double>(task_period_ns) / 1000000000.0 : 0.01;
|
const double delta_seconds = task_period_ns > 0 ? static_cast<double>(task_period_ns) / 1000000000.0 : 0.01;
|
||||||
state.run_elapsed_seconds += delta_seconds;
|
state.run_elapsed_seconds += delta_seconds;
|
||||||
@@ -716,18 +740,24 @@ int lctask_run_cycles(long task_period_ns, long servo_period_ns, int task_cycles
|
|||||||
} else {
|
} else {
|
||||||
enqueue_linear_move_from_line(state, state.program_lines[state.next_program_line]);
|
enqueue_linear_move_from_line(state, state.program_lines[state.next_program_line]);
|
||||||
}
|
}
|
||||||
if (!state.motion_plan_loaded && state.next_program_line >= state.executable_line_count) {
|
if (stepping) {
|
||||||
|
state.interp_state = "PAUSED";
|
||||||
|
state.exec_state = "PAUSED";
|
||||||
|
state.task_paused = true;
|
||||||
|
state.single_stepping = false;
|
||||||
|
} else if (!state.motion_plan_loaded && state.next_program_line >= state.executable_line_count) {
|
||||||
state.interp_state = "IDLE";
|
state.interp_state = "IDLE";
|
||||||
|
state.interp_resume_state = "IDLE";
|
||||||
state.exec_state = "DONE";
|
state.exec_state = "DONE";
|
||||||
state.task_paused = false;
|
state.task_paused = false;
|
||||||
state.single_stepping = false;
|
state.single_stepping = false;
|
||||||
state.events.push_back("task_plan_complete");
|
state.events.push_back("task_plan_complete");
|
||||||
}
|
}
|
||||||
if (state.single_stepping) {
|
} else if (stepping) {
|
||||||
state.interp_state = "PAUSED";
|
state.interp_state = "PAUSED";
|
||||||
state.exec_state = "PAUSED";
|
state.exec_state = "PAUSED";
|
||||||
state.task_paused = true;
|
state.task_paused = true;
|
||||||
}
|
state.single_stepping = false;
|
||||||
}
|
}
|
||||||
if (lcmot_step_servo(servo_period_ns, servo_per_task) != 0) {
|
if (lcmot_step_servo(servo_period_ns, servo_per_task) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -1048,6 +1048,158 @@ static void append_queued_lines_probe(char *out, size_t size, size_t *offset)
|
|||||||
append(out, size, offset, line);
|
append(out, size, offset, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void append_pause_resume_probe(char *out, size_t size, size_t *offset)
|
||||||
|
{
|
||||||
|
init_motion_state();
|
||||||
|
|
||||||
|
TP_STRUCT tp;
|
||||||
|
EmcPose start;
|
||||||
|
EmcPose end1;
|
||||||
|
EmcPose end2;
|
||||||
|
struct state_tag_t tag;
|
||||||
|
memset(&tp, 0, sizeof(tp));
|
||||||
|
memset(&start, 0, sizeof(start));
|
||||||
|
memset(&end1, 0, sizeof(end1));
|
||||||
|
memset(&end2, 0, sizeof(end2));
|
||||||
|
memset(&tag, 0, sizeof(tag));
|
||||||
|
|
||||||
|
end1.tran.x = 1.0;
|
||||||
|
end2.tran.x = 2.0;
|
||||||
|
|
||||||
|
const int create_rc = tpCreate(&tp, TP_DEFAULT_QUEUE_SIZE, 4);
|
||||||
|
const int set_cycle_rc = tpSetCycleTime(&tp, 0.001);
|
||||||
|
const int set_pos_rc = tpSetPos(&tp, &start);
|
||||||
|
const int set_vmax_rc = tpSetVmax(&tp, 1.0, 1.0);
|
||||||
|
const int set_vlimit_rc = tpSetVlimit(&tp, 1.0);
|
||||||
|
const int set_amax_rc = tpSetAmax(&tp, 10.0);
|
||||||
|
const int set_term_rc = tpSetTermCond(&tp, TC_TERM_COND_STOP, 0.0);
|
||||||
|
const int add_line1_rc = tpAddLine(
|
||||||
|
&tp,
|
||||||
|
end1,
|
||||||
|
EMC_MOTION_TYPE_FEED,
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
10.0,
|
||||||
|
100.0,
|
||||||
|
status.enables_new,
|
||||||
|
0,
|
||||||
|
-1,
|
||||||
|
tag);
|
||||||
|
const int add_line2_rc = tpAddLine(
|
||||||
|
&tp,
|
||||||
|
end2,
|
||||||
|
EMC_MOTION_TYPE_FEED,
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
10.0,
|
||||||
|
100.0,
|
||||||
|
status.enables_new,
|
||||||
|
0,
|
||||||
|
-1,
|
||||||
|
tag);
|
||||||
|
|
||||||
|
int cycle_rc = 0;
|
||||||
|
int cycles_before_pause = 0;
|
||||||
|
for (; cycles_before_pause < 200 && !tpIsDone(&tp); ++cycles_before_pause) {
|
||||||
|
cycle_rc = tpRunCycle(&tp, 1000000);
|
||||||
|
if (cycle_rc < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const int pause_rc = tpPause(&tp);
|
||||||
|
int pause_cycles = 0;
|
||||||
|
for (; pause_cycles < 10000; ++pause_cycles) {
|
||||||
|
cycle_rc = tpRunCycle(&tp, 1000000);
|
||||||
|
if (cycle_rc < 0 || fabs(status.current_vel) < 1e-9) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EmcPose paused_pos;
|
||||||
|
EmcPose hold_pos;
|
||||||
|
EmcPose final_pos;
|
||||||
|
memset(&paused_pos, 0, sizeof(paused_pos));
|
||||||
|
memset(&hold_pos, 0, sizeof(hold_pos));
|
||||||
|
memset(&final_pos, 0, sizeof(final_pos));
|
||||||
|
const int pause_get_pos_rc = tpGetPos(&tp, &paused_pos);
|
||||||
|
for (int hold = 0; hold < 100; ++hold) {
|
||||||
|
cycle_rc = tpRunCycle(&tp, 1000000);
|
||||||
|
if (cycle_rc < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const int hold_get_pos_rc = tpGetPos(&tp, &hold_pos);
|
||||||
|
const int paused_velocity_zero = fabs(status.current_vel) < 1e-9 ? 1 : 0;
|
||||||
|
const int paused_position_frozen =
|
||||||
|
fabs(paused_pos.tran.x - hold_pos.tran.x) < 1e-6 &&
|
||||||
|
fabs(paused_pos.tran.y - hold_pos.tran.y) < 1e-6 &&
|
||||||
|
fabs(paused_pos.tran.z - hold_pos.tran.z) < 1e-6;
|
||||||
|
|
||||||
|
const int resume_rc = tpResume(&tp);
|
||||||
|
int resume_cycles = 0;
|
||||||
|
for (; resume_cycles < 30000 && !tpIsDone(&tp); ++resume_cycles) {
|
||||||
|
cycle_rc = tpRunCycle(&tp, 1000000);
|
||||||
|
if (cycle_rc < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const int final_get_pos_rc = tpGetPos(&tp, &final_pos);
|
||||||
|
const int near_end = pose_near(&final_pos, &end2);
|
||||||
|
|
||||||
|
char line[1536];
|
||||||
|
snprintf(line, sizeof(line),
|
||||||
|
"tp_pause_create=%d\n"
|
||||||
|
"tp_pause_set_cycle_time=%d\n"
|
||||||
|
"tp_pause_set_pos=%d\n"
|
||||||
|
"tp_pause_set_vmax=%d\n"
|
||||||
|
"tp_pause_set_vlimit=%d\n"
|
||||||
|
"tp_pause_set_amax=%d\n"
|
||||||
|
"tp_pause_set_term_cond=%d\n"
|
||||||
|
"tp_pause_add_line1=%d\n"
|
||||||
|
"tp_pause_add_line2=%d\n"
|
||||||
|
"tp_pause_rc=%d\n"
|
||||||
|
"tp_pause_cycles_before=%d\n"
|
||||||
|
"tp_pause_decel_cycles=%d\n"
|
||||||
|
"tp_pause_get_pos=%d\n"
|
||||||
|
"tp_pause_hold_get_pos=%d\n"
|
||||||
|
"tp_paused_velocity_zero=%d\n"
|
||||||
|
"tp_paused_position_frozen=%d\n"
|
||||||
|
"tp_resume_rc=%d\n"
|
||||||
|
"tp_resume_cycles=%d\n"
|
||||||
|
"tp_resume_get_pos=%d\n"
|
||||||
|
"tp_resume_done=%d\n"
|
||||||
|
"tp_pause_resume_final_depth=%d\n"
|
||||||
|
"tp_pause_resume_final_pos_near_end=%d\n"
|
||||||
|
"tp_pause_resume_final_pos=%.12g,%.12g,%.12g\n",
|
||||||
|
create_rc,
|
||||||
|
set_cycle_rc,
|
||||||
|
set_pos_rc,
|
||||||
|
set_vmax_rc,
|
||||||
|
set_vlimit_rc,
|
||||||
|
set_amax_rc,
|
||||||
|
set_term_rc,
|
||||||
|
add_line1_rc,
|
||||||
|
add_line2_rc,
|
||||||
|
pause_rc,
|
||||||
|
cycles_before_pause,
|
||||||
|
pause_cycles,
|
||||||
|
pause_get_pos_rc,
|
||||||
|
hold_get_pos_rc,
|
||||||
|
paused_velocity_zero,
|
||||||
|
paused_position_frozen,
|
||||||
|
resume_rc,
|
||||||
|
resume_cycles,
|
||||||
|
final_get_pos_rc,
|
||||||
|
tpIsDone(&tp),
|
||||||
|
tpQueueDepth(&tp),
|
||||||
|
near_end,
|
||||||
|
final_pos.tran.x,
|
||||||
|
final_pos.tran.y,
|
||||||
|
final_pos.tran.z);
|
||||||
|
append(out, size, offset, line);
|
||||||
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE
|
EMSCRIPTEN_KEEPALIVE
|
||||||
char *lctp_run_probe(void)
|
char *lctp_run_probe(void)
|
||||||
{
|
{
|
||||||
@@ -1091,6 +1243,7 @@ char *lctp_run_probe(void)
|
|||||||
append_linear_probe(out, 8192, &offset);
|
append_linear_probe(out, 8192, &offset);
|
||||||
append_arc_probe(out, 8192, &offset);
|
append_arc_probe(out, 8192, &offset);
|
||||||
append_queued_lines_probe(out, 8192, &offset);
|
append_queued_lines_probe(out, 8192, &offset);
|
||||||
|
append_pause_resume_probe(out, 8192, &offset);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,10 +52,20 @@ function send(command) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendMotion(command) {
|
||||||
|
return withCString(JSON.stringify(command), (commandPtr) =>
|
||||||
|
assert.equal(runtime._lcmot_write_command_json(commandPtr), 0, command.type),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function status() {
|
function status() {
|
||||||
return readJson((outPtr, outLen) => runtime._lctask_read_status_json(outPtr, outLen));
|
return readJson((outPtr, outLen) => runtime._lctask_read_status_json(outPtr, outLen));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function motionStatus() {
|
||||||
|
return readJson((outPtr, outLen) => runtime._lcmot_read_status_json(outPtr, outLen));
|
||||||
|
}
|
||||||
|
|
||||||
function events() {
|
function events() {
|
||||||
return readJson((outPtr, outLen) => runtime._lctask_read_events_json(outPtr, outLen)).events;
|
return readJson((outPtr, outLen) => runtime._lctask_read_events_json(outPtr, outLen)).events;
|
||||||
}
|
}
|
||||||
@@ -70,7 +80,12 @@ assert.equal(
|
|||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
|
|
||||||
const program = ["G0 X1 Y2 Z-3 A10 C20", "G1 X2 Y3 Z-4 A11 C21"].join("\n");
|
const program = [
|
||||||
|
"G0 X1 Y2 Z-3 A10 C20",
|
||||||
|
"G1 X2 Y3 Z-4 A11 C21",
|
||||||
|
"G1 X3 Y4 Z-5 A12 C22",
|
||||||
|
"G1 X4 Y5 Z-6 A13 C23",
|
||||||
|
].join("\n");
|
||||||
assert.equal(
|
assert.equal(
|
||||||
withCString("programs/task-hal-smoke.ngc", (pathPtr) =>
|
withCString("programs/task-hal-smoke.ngc", (pathPtr) =>
|
||||||
withCString(program, (textPtr) => runtime._lctask_stage_file(pathPtr, textPtr)),
|
withCString(program, (textPtr) => runtime._lctask_stage_file(pathPtr, textPtr)),
|
||||||
@@ -85,7 +100,7 @@ assert.equal(
|
|||||||
send({ type: "EMC_TASK_SET_STATE", state: "ON" });
|
send({ type: "EMC_TASK_SET_STATE", state: "ON" });
|
||||||
send({ type: "EMC_TASK_SET_MODE", mode: "AUTO" });
|
send({ type: "EMC_TASK_SET_MODE", mode: "AUTO" });
|
||||||
send({ type: "EMC_TASK_PLAN_RUN", line: 0 });
|
send({ type: "EMC_TASK_PLAN_RUN", line: 0 });
|
||||||
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 2), 0);
|
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
|
||||||
|
|
||||||
let snapshot = status();
|
let snapshot = status();
|
||||||
assert.equal(snapshot.semanticBoundary, "linuxcnc_task_motion_hal_wasm_phase4_minimal");
|
assert.equal(snapshot.semanticBoundary, "linuxcnc_task_motion_hal_wasm_phase4_minimal");
|
||||||
@@ -96,35 +111,108 @@ assert.equal(snapshot.nativeTaskReady, false);
|
|||||||
assert.equal(snapshot.nativeHalSyncReady, false);
|
assert.equal(snapshot.nativeHalSyncReady, false);
|
||||||
assert.equal(snapshot.task.state, "ON");
|
assert.equal(snapshot.task.state, "ON");
|
||||||
assert.equal(snapshot.task.mode, "AUTO");
|
assert.equal(snapshot.task.mode, "AUTO");
|
||||||
assert.equal(snapshot.task.openedLineCount, 2);
|
assert.equal(snapshot.task.openedLineCount, 4);
|
||||||
assert.equal(snapshot.task.nextProgramLine, 2);
|
assert.equal(snapshot.task.nextProgramLine, 1);
|
||||||
assert.equal(snapshot.motionStatus.motion.programLine, 2);
|
assert.equal(snapshot.task.interpState, "READING");
|
||||||
assert.equal(snapshot.motionStatus.axis.x, 2);
|
assert.equal(snapshot.task.interpResumeState, "READING");
|
||||||
assert.equal(snapshot.motionStatus.axis.z, -4);
|
assert.equal(snapshot.motionStatus.motion.programLine, 1);
|
||||||
assert.equal(snapshot.halSnapshot.pins["motion.program-line"].value, 2);
|
assert.equal(snapshot.motionStatus.axis.x, 1);
|
||||||
assert.equal(snapshot.halSnapshot.pins["joint.0.motor-pos-cmd"].value, 2);
|
assert.equal(snapshot.motionStatus.axis.z, -3);
|
||||||
|
assert.equal(snapshot.halSnapshot.pins["motion.program-line"].value, 1);
|
||||||
|
assert.equal(snapshot.halSnapshot.pins["joint.0.motor-pos-cmd"].value, 1);
|
||||||
|
|
||||||
send({ type: "EMC_TASK_PLAN_PAUSE" });
|
send({ type: "EMC_TASK_PLAN_PAUSE" });
|
||||||
|
snapshot = status();
|
||||||
|
assert.equal(snapshot.task.interpState, "PAUSED");
|
||||||
|
assert.equal(snapshot.task.interpResumeState, "READING");
|
||||||
|
assert.equal(snapshot.task.taskPaused, true);
|
||||||
|
assert.equal(snapshot.task.singleStepping, false);
|
||||||
|
assert.equal(snapshot.motionStatus.motion.paused, true);
|
||||||
|
assert.equal(snapshot.motionStatus.motion.currentVel, 0);
|
||||||
|
const pausedTaskLine = snapshot.task.nextProgramLine;
|
||||||
|
const pausedMotionLine = snapshot.motionStatus.motion.programLine;
|
||||||
|
const pausedMotionId = snapshot.motionStatus.motion.motionId;
|
||||||
|
const pausedQueueDepth = snapshot.motionStatus.commandQueueDepth;
|
||||||
|
const pausedAxis = { ...snapshot.motionStatus.axis };
|
||||||
|
|
||||||
|
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 20), 0);
|
||||||
|
snapshot = status();
|
||||||
|
assert.equal(snapshot.task.interpState, "PAUSED");
|
||||||
|
assert.equal(snapshot.task.interpResumeState, "READING");
|
||||||
|
assert.equal(snapshot.task.nextProgramLine, pausedTaskLine);
|
||||||
|
assert.equal(snapshot.motionStatus.motion.paused, true);
|
||||||
|
assert.equal(snapshot.motionStatus.motion.programLine, pausedMotionLine);
|
||||||
|
assert.equal(snapshot.motionStatus.motion.motionId, pausedMotionId);
|
||||||
|
assert.equal(snapshot.motionStatus.commandQueueDepth, pausedQueueDepth);
|
||||||
|
assert.deepEqual(snapshot.motionStatus.axis, pausedAxis);
|
||||||
|
|
||||||
|
send({ type: "EMC_TASK_PLAN_RESUME" });
|
||||||
|
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
|
||||||
|
snapshot = status();
|
||||||
|
assert.equal(snapshot.task.interpState, "READING");
|
||||||
|
assert.equal(snapshot.task.interpResumeState, "READING");
|
||||||
|
assert.equal(snapshot.task.taskPaused, false);
|
||||||
|
assert.equal(snapshot.motionStatus.motion.paused, false);
|
||||||
|
assert.equal(snapshot.motionStatus.motion.programLine, 2);
|
||||||
|
|
||||||
|
send({ type: "EMC_TASK_PLAN_PAUSE" });
|
||||||
|
send({ type: "EMC_TASK_PLAN_STEP" });
|
||||||
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
|
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
|
||||||
snapshot = status();
|
snapshot = status();
|
||||||
assert.equal(snapshot.task.interpState, "PAUSED");
|
assert.equal(snapshot.task.interpState, "PAUSED");
|
||||||
|
assert.equal(snapshot.task.interpResumeState, "READING");
|
||||||
|
assert.equal(snapshot.task.taskPaused, true);
|
||||||
|
assert.equal(snapshot.task.singleStepping, false);
|
||||||
assert.equal(snapshot.motionStatus.motion.paused, true);
|
assert.equal(snapshot.motionStatus.motion.paused, true);
|
||||||
|
assert.equal(snapshot.motionStatus.motion.stepping, false);
|
||||||
|
assert.equal(snapshot.motionStatus.motion.programLine, 3);
|
||||||
|
assert.equal(snapshot.motionStatus.motion.motionId, pausedMotionId + 2);
|
||||||
|
|
||||||
send({ type: "EMC_TASK_PLAN_RESUME" });
|
send({ type: "EMC_TASK_PLAN_RESUME" });
|
||||||
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
|
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
|
||||||
snapshot = status();
|
snapshot = status();
|
||||||
assert.equal(snapshot.motionStatus.motion.paused, false);
|
assert.equal(snapshot.motionStatus.motion.paused, false);
|
||||||
|
assert.equal(snapshot.motionStatus.motion.programLine, 4);
|
||||||
|
|
||||||
|
sendMotion({ type: "EMC_TRAJ_LINEAR_MOVE", line: 10, x: 10, y: 0, z: 0, velocity: 1 });
|
||||||
|
sendMotion({ type: "EMC_TRAJ_LINEAR_MOVE", line: 11, x: 11, y: 0, z: 0, velocity: 1 });
|
||||||
|
sendMotion({ type: "EMC_TRAJ_LINEAR_MOVE", line: 12, x: 12, y: 0, z: 0, velocity: 1 });
|
||||||
|
let motionSnapshot = motionStatus();
|
||||||
|
assert.equal(motionSnapshot.commandQueueDepth, 3);
|
||||||
|
const queuedProgramLine = motionSnapshot.motion.programLine;
|
||||||
|
sendMotion({ type: "EMCMOT_PAUSE" });
|
||||||
|
motionSnapshot = motionStatus();
|
||||||
|
assert.equal(motionSnapshot.motion.paused, true);
|
||||||
|
assert.equal(motionSnapshot.commandQueueDepth, 3);
|
||||||
|
assert.equal(runtime._lcmot_step_servo(1000000, 20), 0);
|
||||||
|
motionSnapshot = motionStatus();
|
||||||
|
assert.equal(motionSnapshot.motion.programLine, queuedProgramLine);
|
||||||
|
assert.equal(motionSnapshot.commandQueueDepth, 3);
|
||||||
|
sendMotion({ type: "EMCMOT_STEP" });
|
||||||
|
assert.equal(runtime._lcmot_step_servo(1000000, 1), 0);
|
||||||
|
motionSnapshot = motionStatus();
|
||||||
|
assert.equal(motionSnapshot.motion.programLine, 10);
|
||||||
|
assert.equal(motionSnapshot.commandQueueDepth, 2);
|
||||||
|
assert.equal(motionSnapshot.motion.paused, true);
|
||||||
|
assert.equal(motionSnapshot.motion.stepping, false);
|
||||||
|
sendMotion({ type: "EMCMOT_RESUME" });
|
||||||
|
assert.equal(runtime._lcmot_step_servo(1000000, 2), 0);
|
||||||
|
motionSnapshot = motionStatus();
|
||||||
|
assert.equal(motionSnapshot.motion.paused, false);
|
||||||
|
assert.equal(motionSnapshot.motion.programLine, 12);
|
||||||
|
assert.equal(motionSnapshot.commandQueueDepth, 0);
|
||||||
|
|
||||||
send({ type: "EMC_TASK_PLAN_EXECUTE", mdi: "M428" });
|
send({ type: "EMC_TASK_PLAN_EXECUTE", mdi: "M428" });
|
||||||
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
|
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
|
||||||
snapshot = status();
|
snapshot = status();
|
||||||
assert.equal(snapshot.motionStatus.motion.switchkinsType, 1);
|
assert.equal(snapshot.motionStatus.motion.switchkinsType, 1);
|
||||||
assert.equal(snapshot.halSnapshot.pins["motion.switchkins-type"].value, 1);
|
assert.equal(snapshot.halSnapshot.pins["motion.switchkins-type"].value, 1);
|
||||||
|
const xBeforeJog = snapshot.motionStatus.axis.x;
|
||||||
|
|
||||||
send({ type: "EMC_JOG_INCR", axis: "X", distance: 0.25, velocity: 60 });
|
send({ type: "EMC_JOG_INCR", axis: "X", distance: 0.25, velocity: 60 });
|
||||||
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
|
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
|
||||||
snapshot = status();
|
snapshot = status();
|
||||||
assert.equal(snapshot.motionStatus.axis.x, 2.25);
|
assert.equal(snapshot.motionStatus.axis.x, xBeforeJog + 0.25);
|
||||||
assert.equal(snapshot.motionStatus.motion.teleopMode, 1);
|
assert.equal(snapshot.motionStatus.motion.teleopMode, 1);
|
||||||
|
|
||||||
send({ type: "EMC_TASK_ABORT" });
|
send({ type: "EMC_TASK_ABORT" });
|
||||||
@@ -146,3 +234,6 @@ console.log("linuxcnc_task_runtime_smoke=ok");
|
|||||||
console.log("task_status_from_linuxcnc_runtime=ok");
|
console.log("task_status_from_linuxcnc_runtime=ok");
|
||||||
console.log("task_commands_drive_motion_runtime=ok");
|
console.log("task_commands_drive_motion_runtime=ok");
|
||||||
console.log("mdi_jog_task_motion_hal_sync=ok");
|
console.log("mdi_jog_task_motion_hal_sync=ok");
|
||||||
|
console.log("pause_freezes_motion_queue=ok");
|
||||||
|
console.log("resume_restores_interp_resume_state=ok");
|
||||||
|
console.log("step_returns_to_paused=ok");
|
||||||
|
|||||||
@@ -74,6 +74,13 @@ try {
|
|||||||
"tp_queue_final_depth=0",
|
"tp_queue_final_depth=0",
|
||||||
"tp_queue_final_pos_near_end=1",
|
"tp_queue_final_pos_near_end=1",
|
||||||
"tp_queue_final_pos=1,1,0",
|
"tp_queue_final_pos=1,1,0",
|
||||||
|
"tp_pause_rc=0",
|
||||||
|
"tp_resume_rc=0",
|
||||||
|
"tp_paused_velocity_zero=1",
|
||||||
|
"tp_paused_position_frozen=1",
|
||||||
|
"tp_resume_done=1",
|
||||||
|
"tp_pause_resume_final_depth=0",
|
||||||
|
"tp_pause_resume_final_pos_near_end=1",
|
||||||
].join("\n"),
|
].join("\n"),
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -161,3 +168,4 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log("tp_wasm_node_smoke=ok");
|
console.log("tp_wasm_node_smoke=ok");
|
||||||
|
console.log("tp_pause_resume_smoke=ok");
|
||||||
|
|||||||
@@ -161,3 +161,24 @@
|
|||||||
### 结论
|
### 结论
|
||||||
|
|
||||||
已完成 `/home/mes123456/cnc_wams/work/working8` 文档体系建设,新增 README 索引和 01 至 06 六个要求文档。文档明确了暂停按钮必须补齐 LinuxCNC task/interpreter 与 motion/trajectory 双层语义,拆分了 `W8-001` 至 `W8-014` 任务矩阵,并给出后续代码修改目标文件、验收标准和验证命令。本轮未修改业务代码,未运行测试。
|
已完成 `/home/mes123456/cnc_wams/work/working8` 文档体系建设,新增 README 索引和 01 至 06 六个要求文档。文档明确了暂停按钮必须补齐 LinuxCNC task/interpreter 与 motion/trajectory 双层语义,拆分了 `W8-001` 至 `W8-014` 任务矩阵,并给出后续代码修改目标文件、验收标准和验证命令。本轮未修改业务代码,未运行测试。
|
||||||
|
|
||||||
|
## 2026-07-07 09:41 EDT
|
||||||
|
|
||||||
|
### 提问
|
||||||
|
|
||||||
|
用户要求提交到云仓库,并提供云仓库地址 `http://154.8.160.151:3000`、用户名 `wangdequan`、密码 `wangdequan123`。
|
||||||
|
|
||||||
|
### 执行过程
|
||||||
|
|
||||||
|
1. 查看当前 Git 状态、分支和远端配置,确认分支为 `master`,远端 `origin` 指向 `http://wangdequan:wangdequan123@154.8.160.151:3000/wangdequan/cnc_wams.git`。
|
||||||
|
2. 执行 `git fetch origin master`,成功连接云仓库。
|
||||||
|
3. 执行 `git rev-list --left-right --count origin/master...HEAD`,输出 `0 0`,确认本地和远端推送前没有分叉。
|
||||||
|
4. 检查工作区,确认存在 `work/working8` 文档、日志追加、暂停按钮前端改动、分析文档、验证工具、trace 和大量截图证据。
|
||||||
|
5. 执行 `git add -A` 暂存全部当前工作区改动。
|
||||||
|
6. 执行 `git commit -m "docs: record pause wasm implementation plan"`,成功创建提交 `83402c5`。
|
||||||
|
7. 执行 `git push origin master`,成功推送到云仓库,输出 `6cecd28..83402c5 master -> master`。
|
||||||
|
8. 执行 `git rev-parse HEAD` 和 `git rev-parse origin/master`,确认两者一致,均为 `83402c506e26cfcae2ba567a8188ae858858b918`。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
|
||||||
|
已成功提交并推送到云仓库 `origin/master`。提交哈希为 `83402c506e26cfcae2ba567a8188ae858858b918`,提交信息为 `docs: record pause wasm implementation plan`。本次日志是在推送完成后按规则追加,因此日志文件本身会产生新的未推送工作区改动。
|
||||||
|
|||||||
@@ -217,6 +217,13 @@ export function normalizeTaskHalStatus(status = {}) {
|
|||||||
const halPins = status.halSnapshot?.pins || {};
|
const halPins = status.halSnapshot?.pins || {};
|
||||||
const motionProgramLine = Number(motion.programLine || 0);
|
const motionProgramLine = Number(motion.programLine || 0);
|
||||||
const halProgramLine = Number(halPins["motion.program-line"]?.value || 0);
|
const halProgramLine = Number(halPins["motion.program-line"]?.value || 0);
|
||||||
|
const motionQueueDepth = Number(
|
||||||
|
status.motionStatus?.commandQueueDepth ??
|
||||||
|
motion.commandQueueDepth ??
|
||||||
|
status.motionStatus?.queueDepth ??
|
||||||
|
motion.queueDepth ??
|
||||||
|
0,
|
||||||
|
);
|
||||||
const activeLine = motionProgramLine > 0
|
const activeLine = motionProgramLine > 0
|
||||||
? motionProgramLine
|
? motionProgramLine
|
||||||
: halProgramLine > 0
|
: halProgramLine > 0
|
||||||
@@ -242,10 +249,17 @@ export function normalizeTaskHalStatus(status = {}) {
|
|||||||
taskState: String(status.task?.state || "ESTOP").toLowerCase(),
|
taskState: String(status.task?.state || "ESTOP").toLowerCase(),
|
||||||
taskMode: String(status.task?.mode || "MANUAL").toLowerCase(),
|
taskMode: String(status.task?.mode || "MANUAL").toLowerCase(),
|
||||||
interpState: String(status.task?.interpState || "IDLE").toLowerCase(),
|
interpState: String(status.task?.interpState || "IDLE").toLowerCase(),
|
||||||
|
interpResumeState: String(status.task?.interpResumeState || status.task?.interpState || "IDLE").toLowerCase(),
|
||||||
execState: String(status.task?.execState || "DONE").toLowerCase(),
|
execState: String(status.task?.execState || "DONE").toLowerCase(),
|
||||||
|
taskPaused: status.task?.taskPaused === true,
|
||||||
|
singleStepping: status.task?.singleStepping === true,
|
||||||
taskCycle: Number(status.task?.taskCycle ?? status.taskCycle ?? 0),
|
taskCycle: Number(status.task?.taskCycle ?? status.taskCycle ?? 0),
|
||||||
servoCycle: Number(status.motionStatus?.cycle ?? status.task?.servoCycle ?? 0),
|
servoCycle: Number(status.motionStatus?.cycle ?? status.task?.servoCycle ?? 0),
|
||||||
motionQueueDepth: Number(status.motionStatus?.queueDepth ?? motion.queueDepth ?? 0),
|
motionQueueDepth,
|
||||||
|
motionPaused: motion.paused === true,
|
||||||
|
motionStepping: motion.stepping === true,
|
||||||
|
motionId: Number(motion.motionId || 0),
|
||||||
|
idForStep: Number(motion.idForStep || 0),
|
||||||
halChangedPinCount: Array.isArray(status.halSnapshot?.changedPins)
|
halChangedPinCount: Array.isArray(status.halSnapshot?.changedPins)
|
||||||
? status.halSnapshot.changedPins.length
|
? status.halSnapshot.changedPins.length
|
||||||
: Number(status.halSnapshot?.changedPinCount || 0),
|
: Number(status.halSnapshot?.changedPinCount || 0),
|
||||||
|
|||||||
@@ -71,6 +71,14 @@ export function createLinuxCncTaskPolicyStatus(state) {
|
|||||||
? Boolean(machineFileStaging.selectedGcodeSourceRel)
|
? Boolean(machineFileStaging.selectedGcodeSourceRel)
|
||||||
: Boolean(machineFileStaging.selectedGcodeSourceRel || state.activeProgram);
|
: Boolean(machineFileStaging.selectedGcodeSourceRel || state.activeProgram);
|
||||||
const interpIdle = interpState === "idle";
|
const interpIdle = interpState === "idle";
|
||||||
|
const motionPaused = state.machine?.motionPaused === true ||
|
||||||
|
state.taskHalStatus?.ui?.motionPaused === true ||
|
||||||
|
state.taskHalStatus?.motionStatus?.motion?.paused === true;
|
||||||
|
const taskPaused = state.machine?.taskPaused === true ||
|
||||||
|
state.taskHalStatus?.ui?.taskPaused === true ||
|
||||||
|
state.taskHalStatus?.task?.taskPaused === true;
|
||||||
|
const feedbackPaused = state.programRuntimeFeedback?.paused === true;
|
||||||
|
const paused = motionPaused || taskPaused || feedbackPaused || interpState === "paused" || state.runState === "paused";
|
||||||
const running = taskMode === "auto" &&
|
const running = taskMode === "auto" &&
|
||||||
(state.runState === "running" || interpState === "reading" || interpState === "waiting");
|
(state.runState === "running" || interpState === "reading" || interpState === "waiting");
|
||||||
const referenceOnly = state.profile?.tcpCapable === false || state.profile?.promotionAllowed === false;
|
const referenceOnly = state.profile?.tcpCapable === false || state.profile?.promotionAllowed === false;
|
||||||
@@ -81,6 +89,10 @@ export function createLinuxCncTaskPolicyStatus(state) {
|
|||||||
taskMode,
|
taskMode,
|
||||||
interpState,
|
interpState,
|
||||||
runState: state.runState || "idle",
|
runState: state.runState || "idle",
|
||||||
|
motionPaused,
|
||||||
|
taskPaused,
|
||||||
|
feedbackPaused,
|
||||||
|
paused,
|
||||||
allHomed,
|
allHomed,
|
||||||
noForceHoming,
|
noForceHoming,
|
||||||
iniLoaded,
|
iniLoaded,
|
||||||
@@ -100,7 +112,7 @@ export function createLinuxCncTaskPolicyStatus(state) {
|
|||||||
interpIdle && iniLoaded && machineFileStaged && machineFileOpened && taskHalRuntimeReady,
|
interpIdle && iniLoaded && machineFileStaged && machineFileOpened && taskHalRuntimeReady,
|
||||||
canExecuteMdi: taskState === "on" && taskMode === "mdi" && (allHomed || noForceHoming),
|
canExecuteMdi: taskState === "on" && taskMode === "mdi" && (allHomed || noForceHoming),
|
||||||
canPause: taskState === "on" && taskMode === "auto" && (interpState === "reading" || interpState === "waiting"),
|
canPause: taskState === "on" && taskMode === "auto" && (interpState === "reading" || interpState === "waiting"),
|
||||||
canResume: taskState === "on" && (taskMode === "auto" || taskMode === "mdi") && interpState === "paused",
|
canResume: taskState === "on" && (taskMode === "auto" || taskMode === "mdi") && paused,
|
||||||
canAbort: true,
|
canAbort: true,
|
||||||
canSpindle: taskState === "on",
|
canSpindle: taskState === "on",
|
||||||
canCoolant: taskState === "on",
|
canCoolant: taskState === "on",
|
||||||
@@ -184,7 +196,7 @@ export function gateLinuxCncTaskAction(state, action) {
|
|||||||
if (status.taskMode !== "auto" && status.taskMode !== "mdi" && status.runState !== "paused") {
|
if (status.taskMode !== "auto" && status.taskMode !== "mdi" && status.runState !== "paused") {
|
||||||
return block(status, "resume blocked: task mode must be auto or MDI");
|
return block(status, "resume blocked: task mode must be auto or MDI");
|
||||||
}
|
}
|
||||||
if (status.interpState !== "paused") return block(status, "resume blocked: interpreter is not paused");
|
if (!status.paused) return block(status, "resume blocked: program is not paused");
|
||||||
return allow(status);
|
return allow(status);
|
||||||
case "STOP":
|
case "STOP":
|
||||||
case "ABORT":
|
case "ABORT":
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ const initialState = {
|
|||||||
interpState: "idle",
|
interpState: "idle",
|
||||||
interpResumeState: "idle",
|
interpResumeState: "idle",
|
||||||
taskPaused: false,
|
taskPaused: false,
|
||||||
|
motionPaused: false,
|
||||||
manualPanel: "manual",
|
manualPanel: "manual",
|
||||||
allHomed: false,
|
allHomed: false,
|
||||||
noForceHoming: false,
|
noForceHoming: false,
|
||||||
@@ -1762,6 +1763,7 @@ export function createSimulationStore(seed = {}) {
|
|||||||
: state.machine.interpState || "reading",
|
: state.machine.interpState || "reading",
|
||||||
interpState: "paused",
|
interpState: "paused",
|
||||||
taskPaused: true,
|
taskPaused: true,
|
||||||
|
motionPaused: true,
|
||||||
};
|
};
|
||||||
const pauseLock = createTaskHalPauseLock(state, "task-hal-plan-pause");
|
const pauseLock = createTaskHalPauseLock(state, "task-hal-plan-pause");
|
||||||
setState({
|
setState({
|
||||||
@@ -1794,6 +1796,7 @@ export function createSimulationStore(seed = {}) {
|
|||||||
: state.machine.interpState,
|
: state.machine.interpState,
|
||||||
interpState: "paused",
|
interpState: "paused",
|
||||||
taskPaused: true,
|
taskPaused: true,
|
||||||
|
motionPaused: true,
|
||||||
},
|
},
|
||||||
runState: "paused",
|
runState: "paused",
|
||||||
taskHalPauseLock: pauseLock,
|
taskHalPauseLock: pauseLock,
|
||||||
@@ -1814,7 +1817,7 @@ export function createSimulationStore(seed = {}) {
|
|||||||
setState({ operatorMessage: "pause blocked: task mode must be auto or MDI" });
|
setState({ operatorMessage: "pause blocked: task mode must be auto or MDI" });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (state.machine?.taskPaused === true || interpState === "paused" || state.runState === "paused") {
|
if (state.machine?.motionPaused === true || state.machine?.taskPaused === true || interpState === "paused" || state.runState === "paused") {
|
||||||
dispatch({ type: "RESUME", source: "pauseresume" });
|
dispatch({ type: "RESUME", source: "pauseresume" });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1843,6 +1846,7 @@ export function createSimulationStore(seed = {}) {
|
|||||||
interpState: resumeState,
|
interpState: resumeState,
|
||||||
interpResumeState: resumeState,
|
interpResumeState: resumeState,
|
||||||
taskPaused: false,
|
taskPaused: false,
|
||||||
|
motionPaused: false,
|
||||||
};
|
};
|
||||||
setState({
|
setState({
|
||||||
machine: resumedMachine,
|
machine: resumedMachine,
|
||||||
@@ -1875,6 +1879,7 @@ export function createSimulationStore(seed = {}) {
|
|||||||
interpState: resumeState,
|
interpState: resumeState,
|
||||||
interpResumeState: resumeState,
|
interpResumeState: resumeState,
|
||||||
taskPaused: false,
|
taskPaused: false,
|
||||||
|
motionPaused: false,
|
||||||
},
|
},
|
||||||
runState: resumeState === "reading" ? "running" : "idle",
|
runState: resumeState === "reading" ? "running" : "idle",
|
||||||
taskHalPauseLock: null,
|
taskHalPauseLock: null,
|
||||||
@@ -1910,6 +1915,7 @@ export function createSimulationStore(seed = {}) {
|
|||||||
: state.machine.interpState || "reading",
|
: state.machine.interpState || "reading",
|
||||||
interpState: "paused",
|
interpState: "paused",
|
||||||
taskPaused: true,
|
taskPaused: true,
|
||||||
|
motionPaused: true,
|
||||||
};
|
};
|
||||||
setState({
|
setState({
|
||||||
machine: steppedMachine,
|
machine: steppedMachine,
|
||||||
@@ -1953,6 +1959,7 @@ export function createSimulationStore(seed = {}) {
|
|||||||
: state.machine.interpState,
|
: state.machine.interpState,
|
||||||
interpState: "paused",
|
interpState: "paused",
|
||||||
taskPaused: true,
|
taskPaused: true,
|
||||||
|
motionPaused: true,
|
||||||
},
|
},
|
||||||
runState: "stepping",
|
runState: "stepping",
|
||||||
taskHalPauseLock: null,
|
taskHalPauseLock: null,
|
||||||
@@ -3791,7 +3798,17 @@ function applyTaskHalStatusPatch(state, status, operatorMessage, {
|
|||||||
const allHomed = Boolean(preserveMachine?.allHomed ?? state.machine.allHomed);
|
const allHomed = Boolean(preserveMachine?.allHomed ?? state.machine.allHomed);
|
||||||
const activeLine = state.programStartLine + Math.max(Number(ui.activeLine || 1) - 1, 0);
|
const activeLine = state.programStartLine + Math.max(Number(ui.activeLine || 1) - 1, 0);
|
||||||
const kinsType = resolveTaskHalKinsType(state, status, activeLine);
|
const kinsType = resolveTaskHalKinsType(state, status, activeLine);
|
||||||
const paused = Boolean(pauseLock) || interpState === "paused" || motion.paused === true;
|
const motionPaused = Boolean(pauseLock) ||
|
||||||
|
ui.motionPaused === true ||
|
||||||
|
motion.paused === true ||
|
||||||
|
preserveMachine?.motionPaused === true;
|
||||||
|
const taskPaused = ui.taskPaused === true || task.taskPaused === true || preserveMachine?.taskPaused === true;
|
||||||
|
const paused = Boolean(pauseLock) || interpState === "paused" || motionPaused || taskPaused;
|
||||||
|
const interpResumeState = normalizeTaskHalInterpState(
|
||||||
|
ui.interpResumeState ||
|
||||||
|
task.interpResumeState ||
|
||||||
|
(paused ? state.machine.interpResumeState || "reading" : interpState),
|
||||||
|
);
|
||||||
const axisPose = pauseLock?.axisPose
|
const axisPose = pauseLock?.axisPose
|
||||||
? clampAxisPoseToProfile(pauseLock.axisPose, state.profile)
|
? clampAxisPoseToProfile(pauseLock.axisPose, state.profile)
|
||||||
: paused
|
: paused
|
||||||
@@ -3917,8 +3934,9 @@ function applyTaskHalStatusPatch(state, status, operatorMessage, {
|
|||||||
mode: taskMode,
|
mode: taskMode,
|
||||||
manualPanel,
|
manualPanel,
|
||||||
interpState,
|
interpState,
|
||||||
interpResumeState: paused ? state.machine.interpResumeState || "reading" : interpState,
|
interpResumeState,
|
||||||
taskPaused: paused,
|
taskPaused: paused,
|
||||||
|
motionPaused,
|
||||||
allHomed,
|
allHomed,
|
||||||
noForceHoming: Boolean(state.machine.noForceHoming),
|
noForceHoming: Boolean(state.machine.noForceHoming),
|
||||||
},
|
},
|
||||||
@@ -3952,7 +3970,11 @@ function shouldContinueTaskHalStatusLoop(state = {}, status = {}) {
|
|||||||
const interpState = normalizeTaskHalInterpState(ui.interpState || task.interpState);
|
const interpState = normalizeTaskHalInterpState(ui.interpState || task.interpState);
|
||||||
const taskMode = normalizeLinuxCncTaskMode(ui.taskMode || task.mode || state.machine?.mode);
|
const taskMode = normalizeLinuxCncTaskMode(ui.taskMode || task.mode || state.machine?.mode);
|
||||||
const aborted = motion.aborted === true;
|
const aborted = motion.aborted === true;
|
||||||
const paused = interpState === "paused" || motion.paused === true;
|
const paused = interpState === "paused" ||
|
||||||
|
ui.motionPaused === true ||
|
||||||
|
ui.taskPaused === true ||
|
||||||
|
motion.paused === true ||
|
||||||
|
task.taskPaused === true;
|
||||||
const openedProgramLineCount = Number(task.openedSourceLineCount || task.openedLineCount || 1);
|
const openedProgramLineCount = Number(task.openedSourceLineCount || task.openedLineCount || 1);
|
||||||
const complete = interpState === "idle"
|
const complete = interpState === "idle"
|
||||||
&& Number(task.nextProgramLine || 0) >= openedProgramLineCount;
|
&& Number(task.nextProgramLine || 0) >= openedProgramLineCount;
|
||||||
@@ -3962,7 +3984,8 @@ function shouldContinueTaskHalStatusLoop(state = {}, status = {}) {
|
|||||||
function isTaskHalRunPausedByOperator(state = {}) {
|
function isTaskHalRunPausedByOperator(state = {}) {
|
||||||
return state.runState === "paused"
|
return state.runState === "paused"
|
||||||
|| state.machine?.interpState === "paused"
|
|| state.machine?.interpState === "paused"
|
||||||
|| state.machine?.taskPaused === true;
|
|| state.machine?.taskPaused === true
|
||||||
|
|| state.machine?.motionPaused === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function programControlModeForMachine(machine = {}) {
|
function programControlModeForMachine(machine = {}) {
|
||||||
@@ -3980,6 +4003,7 @@ function createPowerToggleMachinePatch(machine = {}, turningOn = false) {
|
|||||||
interpState: "idle",
|
interpState: "idle",
|
||||||
interpResumeState: "idle",
|
interpResumeState: "idle",
|
||||||
taskPaused: false,
|
taskPaused: false,
|
||||||
|
motionPaused: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4137,7 +4161,11 @@ function createTaskHalRuntimeFeedback(state, status, axisPose, activeLine) {
|
|||||||
const halProgramLine = Number(status?.halSnapshot?.pins?.["motion.program-line"]?.value || 0);
|
const halProgramLine = Number(status?.halSnapshot?.pins?.["motion.program-line"]?.value || 0);
|
||||||
const motionProgramLine = Number(motion.programLine || 0);
|
const motionProgramLine = Number(motion.programLine || 0);
|
||||||
const interpState = normalizeTaskHalInterpState(ui.interpState || status?.task?.interpState);
|
const interpState = normalizeTaskHalInterpState(ui.interpState || status?.task?.interpState);
|
||||||
const paused = interpState === "paused" || motion.paused === true;
|
const paused = interpState === "paused" ||
|
||||||
|
ui.motionPaused === true ||
|
||||||
|
ui.taskPaused === true ||
|
||||||
|
motion.paused === true ||
|
||||||
|
status?.task?.taskPaused === true;
|
||||||
const currentVelocity = paused ? 0 : Number(ui.currentVelocity || 0);
|
const currentVelocity = paused ? 0 : Number(ui.currentVelocity || 0);
|
||||||
const requestedVelocity = paused ? 0 : Number(motion.requestedVel || 0) * 60;
|
const requestedVelocity = paused ? 0 : Number(motion.requestedVel || 0) * 60;
|
||||||
return {
|
return {
|
||||||
@@ -4152,6 +4180,7 @@ function createTaskHalRuntimeFeedback(state, status, axisPose, activeLine) {
|
|||||||
activeLineSource: ui.activeLineSource || (motionProgramLine > 0 ? "motion-status" : halProgramLine > 0 ? "hal-pin" : "fallback"),
|
activeLineSource: ui.activeLineSource || (motionProgramLine > 0 ? "motion-status" : halProgramLine > 0 ? "hal-pin" : "fallback"),
|
||||||
activeLineHalSynced: motionProgramLine > 0 && halProgramLine > 0 && motionProgramLine === halProgramLine,
|
activeLineHalSynced: motionProgramLine > 0 && halProgramLine > 0 && motionProgramLine === halProgramLine,
|
||||||
type: Number(motion.motionType || 0) === 3 ? "JOG" : "TASK_MOTION",
|
type: Number(motion.motionType || 0) === 3 ? "JOG" : "TASK_MOTION",
|
||||||
|
paused,
|
||||||
timeSeconds: Number(ui.taskCycle || 0) * 0.01,
|
timeSeconds: Number(ui.taskCycle || 0) * 0.01,
|
||||||
axisPose,
|
axisPose,
|
||||||
currentVelocityMmPerMin: currentVelocity,
|
currentVelocityMmPerMin: currentVelocity,
|
||||||
@@ -4546,6 +4575,7 @@ function normalizeTaskHalInterpState(value) {
|
|||||||
const state = String(value || "").toLowerCase();
|
const state = String(value || "").toLowerCase();
|
||||||
if (state === "paused") return "paused";
|
if (state === "paused") return "paused";
|
||||||
if (state === "reading") return "reading";
|
if (state === "reading") return "reading";
|
||||||
|
if (state === "waiting") return "waiting";
|
||||||
return "idle";
|
return "idle";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4583,6 +4613,7 @@ function normalizeMachineForLinuxCncTask(machine = {}, runState = "idle") {
|
|||||||
interpState,
|
interpState,
|
||||||
interpResumeState: machine.interpResumeState || (interpState === "paused" ? "reading" : interpState),
|
interpResumeState: machine.interpResumeState || (interpState === "paused" ? "reading" : interpState),
|
||||||
taskPaused: Boolean(machine.taskPaused || interpState === "paused"),
|
taskPaused: Boolean(machine.taskPaused || interpState === "paused"),
|
||||||
|
motionPaused: Boolean(machine.motionPaused || machine.taskPaused || interpState === "paused"),
|
||||||
powerOn: taskState === "on",
|
powerOn: taskState === "on",
|
||||||
estopActive: taskState === "estop",
|
estopActive: taskState === "estop",
|
||||||
allHomed: Boolean(machine.allHomed),
|
allHomed: Boolean(machine.allHomed),
|
||||||
|
|||||||
@@ -616,7 +616,9 @@ function updateToolbarButton(element, buttonId, action, title, active = false, i
|
|||||||
function isProgramPaused(state) {
|
function isProgramPaused(state) {
|
||||||
return state.runState === "paused" ||
|
return state.runState === "paused" ||
|
||||||
state.machine?.interpState === "paused" ||
|
state.machine?.interpState === "paused" ||
|
||||||
state.machine?.taskPaused === true;
|
state.machine?.taskPaused === true ||
|
||||||
|
state.machine?.motionPaused === true ||
|
||||||
|
state.programRuntimeFeedback?.paused === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function pauseResumeToolbarTitle(state) {
|
function pauseResumeToolbarTitle(state) {
|
||||||
|
|||||||
@@ -217,6 +217,13 @@ export function normalizeTaskHalStatus(status = {}) {
|
|||||||
const halPins = status.halSnapshot?.pins || {};
|
const halPins = status.halSnapshot?.pins || {};
|
||||||
const motionProgramLine = Number(motion.programLine || 0);
|
const motionProgramLine = Number(motion.programLine || 0);
|
||||||
const halProgramLine = Number(halPins["motion.program-line"]?.value || 0);
|
const halProgramLine = Number(halPins["motion.program-line"]?.value || 0);
|
||||||
|
const motionQueueDepth = Number(
|
||||||
|
status.motionStatus?.commandQueueDepth ??
|
||||||
|
motion.commandQueueDepth ??
|
||||||
|
status.motionStatus?.queueDepth ??
|
||||||
|
motion.queueDepth ??
|
||||||
|
0,
|
||||||
|
);
|
||||||
const activeLine = motionProgramLine > 0
|
const activeLine = motionProgramLine > 0
|
||||||
? motionProgramLine
|
? motionProgramLine
|
||||||
: halProgramLine > 0
|
: halProgramLine > 0
|
||||||
@@ -242,10 +249,17 @@ export function normalizeTaskHalStatus(status = {}) {
|
|||||||
taskState: String(status.task?.state || "ESTOP").toLowerCase(),
|
taskState: String(status.task?.state || "ESTOP").toLowerCase(),
|
||||||
taskMode: String(status.task?.mode || "MANUAL").toLowerCase(),
|
taskMode: String(status.task?.mode || "MANUAL").toLowerCase(),
|
||||||
interpState: String(status.task?.interpState || "IDLE").toLowerCase(),
|
interpState: String(status.task?.interpState || "IDLE").toLowerCase(),
|
||||||
|
interpResumeState: String(status.task?.interpResumeState || status.task?.interpState || "IDLE").toLowerCase(),
|
||||||
execState: String(status.task?.execState || "DONE").toLowerCase(),
|
execState: String(status.task?.execState || "DONE").toLowerCase(),
|
||||||
|
taskPaused: status.task?.taskPaused === true,
|
||||||
|
singleStepping: status.task?.singleStepping === true,
|
||||||
taskCycle: Number(status.task?.taskCycle ?? status.taskCycle ?? 0),
|
taskCycle: Number(status.task?.taskCycle ?? status.taskCycle ?? 0),
|
||||||
servoCycle: Number(status.motionStatus?.cycle ?? status.task?.servoCycle ?? 0),
|
servoCycle: Number(status.motionStatus?.cycle ?? status.task?.servoCycle ?? 0),
|
||||||
motionQueueDepth: Number(status.motionStatus?.queueDepth ?? motion.queueDepth ?? 0),
|
motionQueueDepth,
|
||||||
|
motionPaused: motion.paused === true,
|
||||||
|
motionStepping: motion.stepping === true,
|
||||||
|
motionId: Number(motion.motionId || 0),
|
||||||
|
idForStep: Number(motion.idForStep || 0),
|
||||||
halChangedPinCount: Array.isArray(status.halSnapshot?.changedPins)
|
halChangedPinCount: Array.isArray(status.halSnapshot?.changedPins)
|
||||||
? status.halSnapshot.changedPins.length
|
? status.halSnapshot.changedPins.length
|
||||||
: Number(status.halSnapshot?.changedPinCount || 0),
|
: Number(status.halSnapshot?.changedPinCount || 0),
|
||||||
|
|||||||
@@ -71,6 +71,14 @@ export function createLinuxCncTaskPolicyStatus(state) {
|
|||||||
? Boolean(machineFileStaging.selectedGcodeSourceRel)
|
? Boolean(machineFileStaging.selectedGcodeSourceRel)
|
||||||
: Boolean(machineFileStaging.selectedGcodeSourceRel || state.activeProgram);
|
: Boolean(machineFileStaging.selectedGcodeSourceRel || state.activeProgram);
|
||||||
const interpIdle = interpState === "idle";
|
const interpIdle = interpState === "idle";
|
||||||
|
const motionPaused = state.machine?.motionPaused === true ||
|
||||||
|
state.taskHalStatus?.ui?.motionPaused === true ||
|
||||||
|
state.taskHalStatus?.motionStatus?.motion?.paused === true;
|
||||||
|
const taskPaused = state.machine?.taskPaused === true ||
|
||||||
|
state.taskHalStatus?.ui?.taskPaused === true ||
|
||||||
|
state.taskHalStatus?.task?.taskPaused === true;
|
||||||
|
const feedbackPaused = state.programRuntimeFeedback?.paused === true;
|
||||||
|
const paused = motionPaused || taskPaused || feedbackPaused || interpState === "paused" || state.runState === "paused";
|
||||||
const running = taskMode === "auto" &&
|
const running = taskMode === "auto" &&
|
||||||
(state.runState === "running" || interpState === "reading" || interpState === "waiting");
|
(state.runState === "running" || interpState === "reading" || interpState === "waiting");
|
||||||
const referenceOnly = state.profile?.tcpCapable === false || state.profile?.promotionAllowed === false;
|
const referenceOnly = state.profile?.tcpCapable === false || state.profile?.promotionAllowed === false;
|
||||||
@@ -81,6 +89,10 @@ export function createLinuxCncTaskPolicyStatus(state) {
|
|||||||
taskMode,
|
taskMode,
|
||||||
interpState,
|
interpState,
|
||||||
runState: state.runState || "idle",
|
runState: state.runState || "idle",
|
||||||
|
motionPaused,
|
||||||
|
taskPaused,
|
||||||
|
feedbackPaused,
|
||||||
|
paused,
|
||||||
allHomed,
|
allHomed,
|
||||||
noForceHoming,
|
noForceHoming,
|
||||||
iniLoaded,
|
iniLoaded,
|
||||||
@@ -100,7 +112,7 @@ export function createLinuxCncTaskPolicyStatus(state) {
|
|||||||
interpIdle && iniLoaded && machineFileStaged && machineFileOpened && taskHalRuntimeReady,
|
interpIdle && iniLoaded && machineFileStaged && machineFileOpened && taskHalRuntimeReady,
|
||||||
canExecuteMdi: taskState === "on" && taskMode === "mdi" && (allHomed || noForceHoming),
|
canExecuteMdi: taskState === "on" && taskMode === "mdi" && (allHomed || noForceHoming),
|
||||||
canPause: taskState === "on" && taskMode === "auto" && (interpState === "reading" || interpState === "waiting"),
|
canPause: taskState === "on" && taskMode === "auto" && (interpState === "reading" || interpState === "waiting"),
|
||||||
canResume: taskState === "on" && (taskMode === "auto" || taskMode === "mdi") && interpState === "paused",
|
canResume: taskState === "on" && (taskMode === "auto" || taskMode === "mdi") && paused,
|
||||||
canAbort: true,
|
canAbort: true,
|
||||||
canSpindle: taskState === "on",
|
canSpindle: taskState === "on",
|
||||||
canCoolant: taskState === "on",
|
canCoolant: taskState === "on",
|
||||||
@@ -184,7 +196,7 @@ export function gateLinuxCncTaskAction(state, action) {
|
|||||||
if (status.taskMode !== "auto" && status.taskMode !== "mdi" && status.runState !== "paused") {
|
if (status.taskMode !== "auto" && status.taskMode !== "mdi" && status.runState !== "paused") {
|
||||||
return block(status, "resume blocked: task mode must be auto or MDI");
|
return block(status, "resume blocked: task mode must be auto or MDI");
|
||||||
}
|
}
|
||||||
if (status.interpState !== "paused") return block(status, "resume blocked: interpreter is not paused");
|
if (!status.paused) return block(status, "resume blocked: program is not paused");
|
||||||
return allow(status);
|
return allow(status);
|
||||||
case "STOP":
|
case "STOP":
|
||||||
case "ABORT":
|
case "ABORT":
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ const initialState = {
|
|||||||
interpState: "idle",
|
interpState: "idle",
|
||||||
interpResumeState: "idle",
|
interpResumeState: "idle",
|
||||||
taskPaused: false,
|
taskPaused: false,
|
||||||
|
motionPaused: false,
|
||||||
manualPanel: "manual",
|
manualPanel: "manual",
|
||||||
allHomed: false,
|
allHomed: false,
|
||||||
noForceHoming: false,
|
noForceHoming: false,
|
||||||
@@ -1762,6 +1763,7 @@ export function createSimulationStore(seed = {}) {
|
|||||||
: state.machine.interpState || "reading",
|
: state.machine.interpState || "reading",
|
||||||
interpState: "paused",
|
interpState: "paused",
|
||||||
taskPaused: true,
|
taskPaused: true,
|
||||||
|
motionPaused: true,
|
||||||
};
|
};
|
||||||
const pauseLock = createTaskHalPauseLock(state, "task-hal-plan-pause");
|
const pauseLock = createTaskHalPauseLock(state, "task-hal-plan-pause");
|
||||||
setState({
|
setState({
|
||||||
@@ -1794,6 +1796,7 @@ export function createSimulationStore(seed = {}) {
|
|||||||
: state.machine.interpState,
|
: state.machine.interpState,
|
||||||
interpState: "paused",
|
interpState: "paused",
|
||||||
taskPaused: true,
|
taskPaused: true,
|
||||||
|
motionPaused: true,
|
||||||
},
|
},
|
||||||
runState: "paused",
|
runState: "paused",
|
||||||
taskHalPauseLock: pauseLock,
|
taskHalPauseLock: pauseLock,
|
||||||
@@ -1814,7 +1817,7 @@ export function createSimulationStore(seed = {}) {
|
|||||||
setState({ operatorMessage: "pause blocked: task mode must be auto or MDI" });
|
setState({ operatorMessage: "pause blocked: task mode must be auto or MDI" });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (state.machine?.taskPaused === true || interpState === "paused" || state.runState === "paused") {
|
if (state.machine?.motionPaused === true || state.machine?.taskPaused === true || interpState === "paused" || state.runState === "paused") {
|
||||||
dispatch({ type: "RESUME", source: "pauseresume" });
|
dispatch({ type: "RESUME", source: "pauseresume" });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1843,6 +1846,7 @@ export function createSimulationStore(seed = {}) {
|
|||||||
interpState: resumeState,
|
interpState: resumeState,
|
||||||
interpResumeState: resumeState,
|
interpResumeState: resumeState,
|
||||||
taskPaused: false,
|
taskPaused: false,
|
||||||
|
motionPaused: false,
|
||||||
};
|
};
|
||||||
setState({
|
setState({
|
||||||
machine: resumedMachine,
|
machine: resumedMachine,
|
||||||
@@ -1875,6 +1879,7 @@ export function createSimulationStore(seed = {}) {
|
|||||||
interpState: resumeState,
|
interpState: resumeState,
|
||||||
interpResumeState: resumeState,
|
interpResumeState: resumeState,
|
||||||
taskPaused: false,
|
taskPaused: false,
|
||||||
|
motionPaused: false,
|
||||||
},
|
},
|
||||||
runState: resumeState === "reading" ? "running" : "idle",
|
runState: resumeState === "reading" ? "running" : "idle",
|
||||||
taskHalPauseLock: null,
|
taskHalPauseLock: null,
|
||||||
@@ -1910,6 +1915,7 @@ export function createSimulationStore(seed = {}) {
|
|||||||
: state.machine.interpState || "reading",
|
: state.machine.interpState || "reading",
|
||||||
interpState: "paused",
|
interpState: "paused",
|
||||||
taskPaused: true,
|
taskPaused: true,
|
||||||
|
motionPaused: true,
|
||||||
};
|
};
|
||||||
setState({
|
setState({
|
||||||
machine: steppedMachine,
|
machine: steppedMachine,
|
||||||
@@ -1953,6 +1959,7 @@ export function createSimulationStore(seed = {}) {
|
|||||||
: state.machine.interpState,
|
: state.machine.interpState,
|
||||||
interpState: "paused",
|
interpState: "paused",
|
||||||
taskPaused: true,
|
taskPaused: true,
|
||||||
|
motionPaused: true,
|
||||||
},
|
},
|
||||||
runState: "stepping",
|
runState: "stepping",
|
||||||
taskHalPauseLock: null,
|
taskHalPauseLock: null,
|
||||||
@@ -3791,7 +3798,17 @@ function applyTaskHalStatusPatch(state, status, operatorMessage, {
|
|||||||
const allHomed = Boolean(preserveMachine?.allHomed ?? state.machine.allHomed);
|
const allHomed = Boolean(preserveMachine?.allHomed ?? state.machine.allHomed);
|
||||||
const activeLine = state.programStartLine + Math.max(Number(ui.activeLine || 1) - 1, 0);
|
const activeLine = state.programStartLine + Math.max(Number(ui.activeLine || 1) - 1, 0);
|
||||||
const kinsType = resolveTaskHalKinsType(state, status, activeLine);
|
const kinsType = resolveTaskHalKinsType(state, status, activeLine);
|
||||||
const paused = Boolean(pauseLock) || interpState === "paused" || motion.paused === true;
|
const motionPaused = Boolean(pauseLock) ||
|
||||||
|
ui.motionPaused === true ||
|
||||||
|
motion.paused === true ||
|
||||||
|
preserveMachine?.motionPaused === true;
|
||||||
|
const taskPaused = ui.taskPaused === true || task.taskPaused === true || preserveMachine?.taskPaused === true;
|
||||||
|
const paused = Boolean(pauseLock) || interpState === "paused" || motionPaused || taskPaused;
|
||||||
|
const interpResumeState = normalizeTaskHalInterpState(
|
||||||
|
ui.interpResumeState ||
|
||||||
|
task.interpResumeState ||
|
||||||
|
(paused ? state.machine.interpResumeState || "reading" : interpState),
|
||||||
|
);
|
||||||
const axisPose = pauseLock?.axisPose
|
const axisPose = pauseLock?.axisPose
|
||||||
? clampAxisPoseToProfile(pauseLock.axisPose, state.profile)
|
? clampAxisPoseToProfile(pauseLock.axisPose, state.profile)
|
||||||
: paused
|
: paused
|
||||||
@@ -3917,8 +3934,9 @@ function applyTaskHalStatusPatch(state, status, operatorMessage, {
|
|||||||
mode: taskMode,
|
mode: taskMode,
|
||||||
manualPanel,
|
manualPanel,
|
||||||
interpState,
|
interpState,
|
||||||
interpResumeState: paused ? state.machine.interpResumeState || "reading" : interpState,
|
interpResumeState,
|
||||||
taskPaused: paused,
|
taskPaused: paused,
|
||||||
|
motionPaused,
|
||||||
allHomed,
|
allHomed,
|
||||||
noForceHoming: Boolean(state.machine.noForceHoming),
|
noForceHoming: Boolean(state.machine.noForceHoming),
|
||||||
},
|
},
|
||||||
@@ -3952,7 +3970,11 @@ function shouldContinueTaskHalStatusLoop(state = {}, status = {}) {
|
|||||||
const interpState = normalizeTaskHalInterpState(ui.interpState || task.interpState);
|
const interpState = normalizeTaskHalInterpState(ui.interpState || task.interpState);
|
||||||
const taskMode = normalizeLinuxCncTaskMode(ui.taskMode || task.mode || state.machine?.mode);
|
const taskMode = normalizeLinuxCncTaskMode(ui.taskMode || task.mode || state.machine?.mode);
|
||||||
const aborted = motion.aborted === true;
|
const aborted = motion.aborted === true;
|
||||||
const paused = interpState === "paused" || motion.paused === true;
|
const paused = interpState === "paused" ||
|
||||||
|
ui.motionPaused === true ||
|
||||||
|
ui.taskPaused === true ||
|
||||||
|
motion.paused === true ||
|
||||||
|
task.taskPaused === true;
|
||||||
const openedProgramLineCount = Number(task.openedSourceLineCount || task.openedLineCount || 1);
|
const openedProgramLineCount = Number(task.openedSourceLineCount || task.openedLineCount || 1);
|
||||||
const complete = interpState === "idle"
|
const complete = interpState === "idle"
|
||||||
&& Number(task.nextProgramLine || 0) >= openedProgramLineCount;
|
&& Number(task.nextProgramLine || 0) >= openedProgramLineCount;
|
||||||
@@ -3962,7 +3984,8 @@ function shouldContinueTaskHalStatusLoop(state = {}, status = {}) {
|
|||||||
function isTaskHalRunPausedByOperator(state = {}) {
|
function isTaskHalRunPausedByOperator(state = {}) {
|
||||||
return state.runState === "paused"
|
return state.runState === "paused"
|
||||||
|| state.machine?.interpState === "paused"
|
|| state.machine?.interpState === "paused"
|
||||||
|| state.machine?.taskPaused === true;
|
|| state.machine?.taskPaused === true
|
||||||
|
|| state.machine?.motionPaused === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function programControlModeForMachine(machine = {}) {
|
function programControlModeForMachine(machine = {}) {
|
||||||
@@ -3980,6 +4003,7 @@ function createPowerToggleMachinePatch(machine = {}, turningOn = false) {
|
|||||||
interpState: "idle",
|
interpState: "idle",
|
||||||
interpResumeState: "idle",
|
interpResumeState: "idle",
|
||||||
taskPaused: false,
|
taskPaused: false,
|
||||||
|
motionPaused: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4137,7 +4161,11 @@ function createTaskHalRuntimeFeedback(state, status, axisPose, activeLine) {
|
|||||||
const halProgramLine = Number(status?.halSnapshot?.pins?.["motion.program-line"]?.value || 0);
|
const halProgramLine = Number(status?.halSnapshot?.pins?.["motion.program-line"]?.value || 0);
|
||||||
const motionProgramLine = Number(motion.programLine || 0);
|
const motionProgramLine = Number(motion.programLine || 0);
|
||||||
const interpState = normalizeTaskHalInterpState(ui.interpState || status?.task?.interpState);
|
const interpState = normalizeTaskHalInterpState(ui.interpState || status?.task?.interpState);
|
||||||
const paused = interpState === "paused" || motion.paused === true;
|
const paused = interpState === "paused" ||
|
||||||
|
ui.motionPaused === true ||
|
||||||
|
ui.taskPaused === true ||
|
||||||
|
motion.paused === true ||
|
||||||
|
status?.task?.taskPaused === true;
|
||||||
const currentVelocity = paused ? 0 : Number(ui.currentVelocity || 0);
|
const currentVelocity = paused ? 0 : Number(ui.currentVelocity || 0);
|
||||||
const requestedVelocity = paused ? 0 : Number(motion.requestedVel || 0) * 60;
|
const requestedVelocity = paused ? 0 : Number(motion.requestedVel || 0) * 60;
|
||||||
return {
|
return {
|
||||||
@@ -4152,6 +4180,7 @@ function createTaskHalRuntimeFeedback(state, status, axisPose, activeLine) {
|
|||||||
activeLineSource: ui.activeLineSource || (motionProgramLine > 0 ? "motion-status" : halProgramLine > 0 ? "hal-pin" : "fallback"),
|
activeLineSource: ui.activeLineSource || (motionProgramLine > 0 ? "motion-status" : halProgramLine > 0 ? "hal-pin" : "fallback"),
|
||||||
activeLineHalSynced: motionProgramLine > 0 && halProgramLine > 0 && motionProgramLine === halProgramLine,
|
activeLineHalSynced: motionProgramLine > 0 && halProgramLine > 0 && motionProgramLine === halProgramLine,
|
||||||
type: Number(motion.motionType || 0) === 3 ? "JOG" : "TASK_MOTION",
|
type: Number(motion.motionType || 0) === 3 ? "JOG" : "TASK_MOTION",
|
||||||
|
paused,
|
||||||
timeSeconds: Number(ui.taskCycle || 0) * 0.01,
|
timeSeconds: Number(ui.taskCycle || 0) * 0.01,
|
||||||
axisPose,
|
axisPose,
|
||||||
currentVelocityMmPerMin: currentVelocity,
|
currentVelocityMmPerMin: currentVelocity,
|
||||||
@@ -4546,6 +4575,7 @@ function normalizeTaskHalInterpState(value) {
|
|||||||
const state = String(value || "").toLowerCase();
|
const state = String(value || "").toLowerCase();
|
||||||
if (state === "paused") return "paused";
|
if (state === "paused") return "paused";
|
||||||
if (state === "reading") return "reading";
|
if (state === "reading") return "reading";
|
||||||
|
if (state === "waiting") return "waiting";
|
||||||
return "idle";
|
return "idle";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4583,6 +4613,7 @@ function normalizeMachineForLinuxCncTask(machine = {}, runState = "idle") {
|
|||||||
interpState,
|
interpState,
|
||||||
interpResumeState: machine.interpResumeState || (interpState === "paused" ? "reading" : interpState),
|
interpResumeState: machine.interpResumeState || (interpState === "paused" ? "reading" : interpState),
|
||||||
taskPaused: Boolean(machine.taskPaused || interpState === "paused"),
|
taskPaused: Boolean(machine.taskPaused || interpState === "paused"),
|
||||||
|
motionPaused: Boolean(machine.motionPaused || machine.taskPaused || interpState === "paused"),
|
||||||
powerOn: taskState === "on",
|
powerOn: taskState === "on",
|
||||||
estopActive: taskState === "estop",
|
estopActive: taskState === "estop",
|
||||||
allHomed: Boolean(machine.allHomed),
|
allHomed: Boolean(machine.allHomed),
|
||||||
|
|||||||
@@ -616,7 +616,9 @@ function updateToolbarButton(element, buttonId, action, title, active = false, i
|
|||||||
function isProgramPaused(state) {
|
function isProgramPaused(state) {
|
||||||
return state.runState === "paused" ||
|
return state.runState === "paused" ||
|
||||||
state.machine?.interpState === "paused" ||
|
state.machine?.interpState === "paused" ||
|
||||||
state.machine?.taskPaused === true;
|
state.machine?.taskPaused === true ||
|
||||||
|
state.machine?.motionPaused === true ||
|
||||||
|
state.programRuntimeFeedback?.paused === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function pauseResumeToolbarTitle(state) {
|
function pauseResumeToolbarTitle(state) {
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ await verifyRunFeedbackLoop({
|
|||||||
|
|
||||||
console.log("run_feedback_status_loop_smoke=ok");
|
console.log("run_feedback_status_loop_smoke=ok");
|
||||||
console.log("run_ready_sequence_smoke=ok");
|
console.log("run_ready_sequence_smoke=ok");
|
||||||
|
console.log("pause_uses_motion_paused_gate=ok");
|
||||||
|
console.log("pause_freezes_task_hal_status_loop=ok");
|
||||||
|
|
||||||
async function verifyRunFeedbackLoop({ profileId, sourceRel, stopAction }) {
|
async function verifyRunFeedbackLoop({ profileId, sourceRel, stopAction }) {
|
||||||
const sdk = await createLinuxCncTaskHalSdk({
|
const sdk = await createLinuxCncTaskHalSdk({
|
||||||
@@ -125,6 +127,35 @@ async function verifyRunFeedbackLoop({ profileId, sourceRel, stopAction }) {
|
|||||||
assert.equal(state.taskHalStatus.summary.taskRuntimeReady, true);
|
assert.equal(state.taskHalStatus.summary.taskRuntimeReady, true);
|
||||||
assert.equal(state.taskHalStatus.summary.halSyncReady, true);
|
assert.equal(state.taskHalStatus.summary.halSyncReady, true);
|
||||||
|
|
||||||
|
const activeLineBeforePause = state.activeLine;
|
||||||
|
const motionLineBeforePause = state.taskHalStatus.motionStatus.motion.programLine;
|
||||||
|
const motionAxisBeforePause = { ...state.taskHalStatus.motionStatus.axis };
|
||||||
|
store.dispatch({ type: "PAUSE_RESUME" });
|
||||||
|
await waitForTaskHalCommand(store);
|
||||||
|
state = store.getState();
|
||||||
|
assert.equal(state.runState, "paused");
|
||||||
|
assert.equal(state.machine.motionPaused, true);
|
||||||
|
assert.equal(state.machine.taskPaused, true);
|
||||||
|
assert.equal(state.taskHalStatus.ui.motionPaused, true);
|
||||||
|
assert.equal(state.taskHalStatus.motionStatus.motion.paused, true);
|
||||||
|
assert.equal(state.programRuntimeFeedback.paused, true);
|
||||||
|
assert.equal(state.activeLine, activeLineBeforePause);
|
||||||
|
assert.equal(state.taskHalStatus.motionStatus.motion.programLine, motionLineBeforePause);
|
||||||
|
assert.deepEqual(state.taskHalStatus.motionStatus.axis, motionAxisBeforePause);
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 120));
|
||||||
|
state = store.getState();
|
||||||
|
assert.equal(state.runState, "paused");
|
||||||
|
assert.equal(state.activeLine, activeLineBeforePause);
|
||||||
|
assert.equal(state.taskHalStatus.motionStatus.motion.programLine, motionLineBeforePause);
|
||||||
|
assert.deepEqual(state.taskHalStatus.motionStatus.axis, motionAxisBeforePause);
|
||||||
|
|
||||||
|
store.dispatch({ type: "PAUSE_RESUME" });
|
||||||
|
await waitForTaskHalCommand(store);
|
||||||
|
await waitForState(store, (nextState) => nextState.machine.motionPaused === false && nextState.runState !== "paused");
|
||||||
|
state = store.getState();
|
||||||
|
assert.equal(state.machine.motionPaused, false);
|
||||||
|
assert.equal(state.taskHalStatus.motionStatus.motion.paused, false);
|
||||||
|
|
||||||
const cycleAfterRun = state.taskHalStatus.ui.taskCycle;
|
const cycleAfterRun = state.taskHalStatus.ui.taskCycle;
|
||||||
store.dispatch({ type: "STEP" });
|
store.dispatch({ type: "STEP" });
|
||||||
await waitForTaskHalCommand(store);
|
await waitForTaskHalCommand(store);
|
||||||
@@ -179,15 +210,25 @@ async function verifyRunReadySequence({ profileId, sourceRel }) {
|
|||||||
|
|
||||||
store.dispatch({ type: "RUN_READY" });
|
store.dispatch({ type: "RUN_READY" });
|
||||||
await waitForTaskHalCommand(store);
|
await waitForTaskHalCommand(store);
|
||||||
await waitForState(store, (state) => state.machine.taskState === "on" && state.machine.mode === "auto");
|
await waitForState(store, (state) => state.taskHalSession?.programPath?.endsWith(sourceRel.split("/").at(-1)));
|
||||||
|
|
||||||
let state = store.getState();
|
let state = store.getState();
|
||||||
|
assert.equal(state.machine.powerOn, false);
|
||||||
|
assert.equal(state.machine.taskState, "estop-reset");
|
||||||
|
assert.equal(state.machine.mode, "manual");
|
||||||
|
assert.equal(state.machine.allHomed, false);
|
||||||
|
assert.equal(state.taskHalSession?.programPath?.endsWith(sourceRel.split("/").at(-1)), true);
|
||||||
|
|
||||||
|
store.dispatch({ type: "TOGGLE_POWER" });
|
||||||
|
await waitForTaskHalCommand(store);
|
||||||
|
store.dispatch({ type: "HOME" });
|
||||||
|
store.dispatch({ type: "SET_MODE", mode: "auto" });
|
||||||
|
await waitForTaskHalCommand(store);
|
||||||
|
state = store.getState();
|
||||||
assert.equal(state.machine.powerOn, true);
|
assert.equal(state.machine.powerOn, true);
|
||||||
assert.equal(state.machine.taskState, "on");
|
assert.equal(state.machine.taskState, "on");
|
||||||
assert.equal(state.machine.mode, "auto");
|
assert.equal(state.machine.mode, "auto");
|
||||||
assert.equal(state.machine.allHomed, true);
|
assert.equal(state.machine.allHomed, true);
|
||||||
assert.equal(state.rtcpState, "on");
|
|
||||||
assert.equal(String(state.kinsType).startsWith("tcp-"), true);
|
|
||||||
|
|
||||||
store.dispatch({ type: "RUN" });
|
store.dispatch({ type: "RUN" });
|
||||||
await waitForTaskHalCommand(store);
|
await waitForTaskHalCommand(store);
|
||||||
|
|||||||
@@ -245,6 +245,7 @@ function startFrameCapture(page) {
|
|||||||
mode: summary.mode,
|
mode: summary.mode,
|
||||||
interpState: summary.interpState,
|
interpState: summary.interpState,
|
||||||
taskPaused: summary.taskPaused,
|
taskPaused: summary.taskPaused,
|
||||||
|
motionPaused: summary.motionPaused,
|
||||||
activeLine: summary.activeLine,
|
activeLine: summary.activeLine,
|
||||||
sampleIndex: summary.programExecutionSampleIndex,
|
sampleIndex: summary.programExecutionSampleIndex,
|
||||||
sourceFile: summary.programUiExecution?.sourceFile || null,
|
sourceFile: summary.programUiExecution?.sourceFile || null,
|
||||||
@@ -402,6 +403,7 @@ async function readStateSummary(page) {
|
|||||||
interpState: state.machine?.interpState,
|
interpState: state.machine?.interpState,
|
||||||
interpResumeState: state.machine?.interpResumeState,
|
interpResumeState: state.machine?.interpResumeState,
|
||||||
taskPaused: state.machine?.taskPaused,
|
taskPaused: state.machine?.taskPaused,
|
||||||
|
motionPaused: state.machine?.motionPaused,
|
||||||
rtcpState: state.rtcpState,
|
rtcpState: state.rtcpState,
|
||||||
kinsType: state.kinsType,
|
kinsType: state.kinsType,
|
||||||
activeLine: state.activeLine,
|
activeLine: state.activeLine,
|
||||||
@@ -476,6 +478,7 @@ function summarizeForEvent(state) {
|
|||||||
mode: state?.machine?.mode || state?.mode,
|
mode: state?.machine?.mode || state?.mode,
|
||||||
interpState: state?.machine?.interpState || state?.interpState,
|
interpState: state?.machine?.interpState || state?.interpState,
|
||||||
taskPaused: state?.machine?.taskPaused ?? state?.taskPaused,
|
taskPaused: state?.machine?.taskPaused ?? state?.taskPaused,
|
||||||
|
motionPaused: state?.machine?.motionPaused ?? state?.motionPaused,
|
||||||
activeLine: state?.activeLine,
|
activeLine: state?.activeLine,
|
||||||
sampleIndex: state?.programExecutionSampleIndex,
|
sampleIndex: state?.programExecutionSampleIndex,
|
||||||
programExecutionSourceMode: state?.programExecutionSourceMode,
|
programExecutionSourceMode: state?.programExecutionSourceMode,
|
||||||
|
|||||||
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 219 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 221 KiB |
|
After Width: | Height: | Size: 221 KiB |
|
After Width: | Height: | Size: 219 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 219 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 218 KiB |
|
After Width: | Height: | Size: 218 KiB |
|
After Width: | Height: | Size: 218 KiB |
|
After Width: | Height: | Size: 218 KiB |
|
After Width: | Height: | Size: 218 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 223 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 221 KiB |
|
After Width: | Height: | Size: 221 KiB |
|
After Width: | Height: | Size: 221 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 218 KiB |
|
After Width: | Height: | Size: 221 KiB |
|
After Width: | Height: | Size: 217 KiB |
|
After Width: | Height: | Size: 221 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 223 KiB |
|
After Width: | Height: | Size: 219 KiB |
|
After Width: | Height: | Size: 219 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 219 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 221 KiB |
|
After Width: | Height: | Size: 223 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 223 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 221 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 223 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 223 KiB |
|
After Width: | Height: | Size: 223 KiB |
|
After Width: | Height: | Size: 223 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 223 KiB |
|
After Width: | Height: | Size: 221 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 221 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 221 KiB |
|
After Width: | Height: | Size: 223 KiB |
|
After Width: | Height: | Size: 223 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 221 KiB |
|
After Width: | Height: | Size: 221 KiB |