Files
cnc_wams/wasm-port/working/10-taskintf-usrmot-shim设计.md
2026-07-08 09:20:47 -04:00

8.3 KiB
Raw Blame History

10-taskintf usrmot shim 设计

目标

T-032 定义 taskintf.cc 在 WASM 中继续保留的 usrmot 语义边界,以及这些边界如何落到 standalone lcmot_* runtime。目标是给 T-033 之后的实现提供窄 shim 合同,而不是在本阶段直接编译完整 linuxcnc/src/emc/motion/usrmotintf.cc

上游锚点:

  • linuxcnc/src/emc/motion/usrmotintf.h
  • linuxcnc/src/emc/motion/usrmotintf.cc
  • linuxcnc/src/emc/task/taskintf.cc

WASM runtime 锚点:

  • runtime/core/linuxcnc_wrap/linuxcnc_motion_runtime.h
  • runtime/core/linuxcnc_wrap/linuxcnc_motion_runtime.c
  • vendor/linuxcnc/src/emc/task/taskintf_wasm_subset.hh
  • vendor/linuxcnc/src/emc/task/taskintf_wasm_subset.cc

不直接复用完整 usrmotintf.cc

完整上游 usrmotintf.cc 绑定 native shared memory、mutex、command ack 轮询、split read、error ring buffer、RTAPI init/exit 和 compensation file loading。WASM 当前 motion runtime 是同进程 standalone C ABI不存在上游共享内存段也没有 native emcmot process ack 通道。

因此 T-032 采用一个窄 usrmot shim

taskintf.cc-compatible calls
  -> wasm usrmot shim
  -> lcmot_* C ABI
  -> standalone motion runtime

shim 必须保留上游函数的返回值语义,但只能承诺当前 lcmot_* 已有或明确新增的能力。

映射总表

usrmot 边界 上游行为 WASM shim 映射 当前状态
usrmotIniLoad(file) 读取 INI 中的 motion shared memory key、timeout 等 只保存 ini_path,等待 usrmotInit() 调用 lcmot_init_from_ini(ini_path, ini_text) 需要 shim 缓存 staged INI text
usrmotInit(name) 连接 native emcmot shared memory 初始化 standalone motion runtime映射到 lcmot_init_from_ini() 已有底层 ABI
usrmotExit() 断开 native emcmot shared memory/RTAPI 映射到 lcmot_reset();不退出 WASM runtime 已有底层 ABI
usrmotWriteEmcmotCommand(c) emcmot_command_t,等待 commandNumEcho ack 将 taskintf 命令转换为 lcmot_write_command_json() 可接受的 command JSON 已有底层 ABIack 语义需降级
usrmotReadEmcmotStatus(s) split-read 复制 emcmot_status_t 映射 lcmot_read_status_snapshot() 到窄 emcmot_status_t/EMC_MOTION_STAT subset 已有底层 ABI
usrmotReadEmcmotConfig(s) split-read 复制 emcmot_config_t 新增 lcmot_read_config_snapshot(),输出 axes/joints/queue/config_num/limits/default units 等窄 config subset T-033 已实现窄底层 ABI
usrmotReadEmcmotInternal(s) 读取 debug/internal shared memory 第一阶段返回空 internal subset后续可新增 lcmot_read_internal_snapshot() 非 T-032 必需
usrmotReadEmcmotError(e) 从 motion error ring 取最早错误 新增 lcmot_read_error_message(char *out, int out_len) 或等价 JSON/error buffer API T-033 已实现窄 error message queue
usrmotLoadComp() / usrmotPrintComp() joint compensation 文件 IO 暂不支持;返回 EMCMOT_COMM_ERROR_COMMAND 或独立 unsupported code 后续 joint compensation 批次处理

command write

上游 usrmotWriteEmcmotCommand(emcmot_command_t *c) 做三件事:

  1. 校验 motion id。
  2. 写入 shared memory command slot。
  3. 轮询 usrmotReadEmcmotStatus(),等待 commandNumEchocommandStatus

WASM shim 的 T-033 最小实现合同:

usrmotWriteEmcmotCommand(c)
  -> validate supported command and motion id
  -> convert emcmot_command_t to taskintf/lcmot command JSON
  -> lcmot_write_command_json(json)
  -> return EMCMOT_COMM_OK on accepted enqueue

返回值映射:

条件 返回值
command 转换成功且 lcmot_write_command_json() 返回 0 EMCMOT_COMM_OK
command unsupported、queue full、字段非法 EMCMOT_COMM_ERROR_COMMAND
runtime 未初始化 EMCMOT_COMM_ERROR_CONNECT
motion id 为 invalid sentinel EMCMOT_COMM_INVALID_MOTION_ID
in-process WASM runtime 无 ack 通道 不使用 EMCMOT_COMM_ERROR_TIMEOUT,除非后续引入 command ack

现有 taskintf_wasm_subset 已覆盖的 command family

  • emcTrajAbort() / EMCMOT_ABORT
  • emcTrajPause() / EMCMOT_PAUSE
  • emcTrajStep() / EMCMOT_STEP
  • emcTrajResume() / EMCMOT_RESUME
  • emcTrajLinearMove() / EMCMOT_SET_LINE
  • emcJogIncr() / EMCMOT_JOG_INCR
  • emcJointHome() / homing command envelope
  • emcMotionSetAout() / EMCMOT_SET_AOUT

后续 T-034 到 T-036 可以把这些 command family 从 JSON 拼接继续收缩到 emcmot_command_t -> shim -> lcmot 的窄转换层。

status read

上游 usrmotReadEmcmotStatus(emcmot_status_t *s) 是 split-read只复制 shared memory不推进 servo。WASM 语义必须保持这一点:

usrmotReadEmcmotStatus(s)
  -> lcmot_read_status_snapshot(&snapshot)
  -> map snapshot to status subset
  -> return EMCMOT_COMM_OK

硬性约束:

  • 不调用 lcmot_step_servo()
  • 不消费 motion command queue。
  • 不调用 lctask_run_cycles()
  • 不从 JSON status 反向解析。
  • statusin_positionqueue_fullqueue_countmotion_idprogram_lineaxis_cmd/fbjoint_cmd/fbmotion_erroron_soft_limit 必须来自 LcmotStatusSnapshot

LcmotStatusSnapshot.status 到 RCS 子状态的第一阶段映射:

LcmotStatusSnapshot.status 语义
0 motion DONE
1 motion EXEC
2 motion ERROR

config read

上游 usrmotReadEmcmotConfig(emcmot_config_t *s) 读取 config shared memory并依赖 head == tail 的 split-read 稳定性。当前 lcmot_* 只有 lcmot_init_from_ini(),没有 config snapshot read API。

T-032 设计结论:

usrmotReadEmcmotConfig(s)
  -> lcmot_read_config_snapshot(&config)
  -> map config to emcmot_config_t subset

T-033 已新增窄实现:

typedef struct {
    int config_num;
    int axes;
    int joints;
    int queue_capacity;
    double linear_units;
    double angular_units;
    double axis_min_limit[LCMOT_MAX_AXES];
    double axis_max_limit[LCMOT_MAX_AXES];
} LcmotConfigSnapshot;

int lcmot_read_config_snapshot(LcmotConfigSnapshot *snapshot);

如果后续替换或重命名该 APIshim 不能假装 usrmotReadEmcmotConfig() 已支持。允许的临时行为只有:

  • task 初始化阶段使用 lcmot_init_from_ini() 建立 runtime defaults。
  • emcMotionUpdate() 遇到 config read 需求时返回错误,保持 readiness false。
  • 文档和验证脚本继续记录 config read 是窄 runtime-edge ABI不是 native shared-memory config promotion。

error read

上游 usrmotReadEmcmotError(char *e) 从 motion error ring 取最早错误字符串。当前 LcmotStatusSnapshot 只有 motion_erroron_soft_limit 标志,不能替代错误队列。

T-032 设计结论:

usrmotReadEmcmotError(e)
  -> lcmot_read_error_message(e, EMCMOT_ERROR_LEN)

T-033 已新增窄实现:

int lcmot_read_error_message(char *out, int out_len);

行为合同:

  • 有错误消息时返回 0并复制最早错误。
  • 无错误消息时返回 -1匹配上游 “no error” 分支。
  • EMCMOT_INJECT_ERROR、soft-limit、abort cleanup 写入该 error buffer。
  • status flag 仍来自 lcmot_read_status_snapshot(),错误文本只通过 error read 消费。

T-033 实施入口

  1. T-033 已在 taskintf_wasm_subset 中新增 lc_taskintf_subset_motion_init()lc_taskintf_subset_motion_update()lc_taskintf_subset_motion_abort()
  2. T-033 已新增 lcmot_read_config_snapshot()lcmot_read_error_message()
  3. T-033 已让 lctask_init_session()、task-cycle motion update 和 task abort path 通过 shim 访问 motion runtime。
  4. 继续保持 task status read 和 motion status read 的周期隔离:外部 lctask_read_status_json() 不触发新的 motion update。
  5. T-034+ 可继续把 traj control command family 从 envelope 迁到更完整的 usrmot command conversion。

禁止路线

  • 不把完整 usrmotintf.cc 直接加入 WASM build。
  • 不用 lcmot_read_status_json() 反解析生成 emcmot_status_t
  • 不让 status read 推进 servo 或 task cycle。
  • 不把 config read 映射成 HAL snapshot。
  • 不把 motion_error boolean 当成 usrmotReadEmcmotError() 的错误队列。
  • 不把 T-032/T-033 的 usrmot shim 解释为 nativeTaskReady=truenativeHalSyncReady=true