chore: close wasm status contract work
This commit is contained in:
191
wasm-port/working/10-taskintf-usrmot-shim设计.md
Normal file
191
wasm-port/working/10-taskintf-usrmot-shim设计.md
Normal file
@@ -0,0 +1,191 @@
|
||||
# 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:
|
||||
|
||||
```text
|
||||
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 | 已有底层 ABI,ack 语义需降级 |
|
||||
| `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()`,等待 `commandNumEcho` 和 `commandStatus`。
|
||||
|
||||
WASM shim 的 T-033 最小实现合同:
|
||||
|
||||
```text
|
||||
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 语义必须保持这一点:
|
||||
|
||||
```text
|
||||
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 反向解析。
|
||||
- `status`、`in_position`、`queue_full`、`queue_count`、`motion_id`、`program_line`、`axis_cmd/fb`、`joint_cmd/fb`、`motion_error`、`on_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 设计结论:
|
||||
|
||||
```text
|
||||
usrmotReadEmcmotConfig(s)
|
||||
-> lcmot_read_config_snapshot(&config)
|
||||
-> map config to emcmot_config_t subset
|
||||
```
|
||||
|
||||
T-033 已新增窄实现:
|
||||
|
||||
```c
|
||||
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);
|
||||
```
|
||||
|
||||
如果后续替换或重命名该 API,shim 不能假装 `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_error` 和 `on_soft_limit` 标志,不能替代错误队列。
|
||||
|
||||
T-032 设计结论:
|
||||
|
||||
```text
|
||||
usrmotReadEmcmotError(e)
|
||||
-> lcmot_read_error_message(e, EMCMOT_ERROR_LEN)
|
||||
```
|
||||
|
||||
T-033 已新增窄实现:
|
||||
|
||||
```c
|
||||
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=true` 或 `nativeHalSyncReady=true`。
|
||||
Reference in New Issue
Block a user