Files
linuxcncWebWASM/docs/linuxcnc-web-wasm-kinematics-migration-plan.md

325 lines
36 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# LinuxCNC Web/WASM 运动学完整移植计划
**文档状态**:重梳理版 v1.0
**适用基线**:LinuxCNC `2.10.0~pre0`,以 [`context-lock.json`](../context-lock.json) 为准
**目标**:完成所有纳入 `configs/sim/**` 的运动学类型、配置变体、正解/逆解、回零、模式切换和浏览器可视化闭环
**上位实施**:[完整仿真机床实施蓝图](linuxcnc-web-wasm-full-port-implementation.md)
**源程序关联**:[功能与源程序关联目录](linuxcnc-web-wasm-source-map.md)
**覆盖验收**:[仿真全功能覆盖矩阵](linuxcnc-web-wasm-simulation-coverage.md)
本文件将运动学从“CORE-04 的一个任务”提升为贯穿核心、运动、HAL、数字孪生、可视化和回归的主线。它不把算法按文件名简单罗列,而是要求每个类型都闭合:配置选择、参数解析、坐标/关节映射、正解、逆解、分支标志、回零、限制/奇异性、固定 tick、故障注入、native/WASM oracle、UI 姿态和恢复。
## 1. 为什么运动学必须单独成线
LinuxCNC 的 `KINEMATICS` 不只是一个 `forward()`/`inverse()` 函数:
- `KINEMATICS_IDENTITY`、`FORWARD_ONLY`、`INVERSE_ONLY`、`BOTH` 会改变 Task、motion、jog、home 和世界/关节模式转换。
- `coordinates=` 可以重复轴字母(如 `XYYZ`),额外关节不进入 kinematics;映射错误会让解释器正确的轨迹驱动错误的关节。
- 正解和逆解可能有多分支,需要 `KINEMATICS_FORWARD_FLAGS`、`KINEMATICS_INVERSE_FLAGS` 保持姿态连续;并行机构和机器人还需要上一次 pose 作为迭代初值。
- 许多配置使用 `switchkins`、HAL 实现的 CoreXY 或 GUI 专用 kinematics,不能只按 `[KINS]KINEMATICS` 的模块名判断。
- 5 轴刀尖跟随、转台/摆头、Delta/Hexapod、SCARA/PUMA 等算法的单位、角度、奇异点和收敛策略不同;“能编译”不代表“可运行”。
因此运动学主线是 M2 核心行为进入 M3 HAL/数字孪生和 M4 UI 的硬门。运动学主线未达到 `verified`,不得把任意非 trivkins 配置标为可运行。
## 2. 锁定来源和类型清单
### 2.1 公共接口和适配基础
必须逐文件登记并保留 `source_sha`:
| 来源组 | 文件 | 作用 |
|---|---|---|
| ABI/类型 | `src/emc/kinematics/kinematics.h` | `EmcPose`、四种 kinematics 类型、正逆解 flags、home 和 switch API |
| 映射/通用 | `kins_util.c`、`userkfuncs.c`、`ugenserkins.c` | `coordinates` 到 joint 映射、identity 实现、用户模板 |
| 切换 | `switchkins.c`、`switchkins.h` | 0/1/2 类型选择、last pose、迭代正解和 GUI pins |
| 几何 | `src/libnml/posemath/**`、`src/libnml/gomath/**` | 变换、矩阵、向量、数值容差和姿态表示 |
| 运动耦合 | `src/emc/motion/control.c`、`command.c`、`motion.c`、`homing.c` | kinematics 类型如何影响 mode、home、限位、following error 和实际位置 |
### 2.2 LinuxCNC 实际运动学实现族
下表是代码级实现族,不等同于配置数量。每个文件都要进入 manifest;同一算法的 `.c/.cc` 变体不能只保留一个目录状态。
| 族 | 实现文件 | 几何类别 | 典型配置入口 |
|---|---|---|---|
| 笛卡尔/映射 | `trivkins.c`、`maxkins.c`、`rotatekins.c` | 轴与关节同构、最大轴/旋转映射、identity/both 变体 | `axis/*.ini`、`qtaxis/xyz`、`gmoccapy/*axis*` |
| 耦合线性 | `corexykins.c`、`rosekins.c` | 线性关节耦合、双电机/特殊并联映射 | `axis/corexy/*`、`axis/rose_engine/*` |
| 泡沫/扩展轴 | `5axiskins.c`、`trivkins` 重复轴/extra joints | XYZ 与 UVW、旋转轴、非 kins extra joints | `axis/foam/*`、9 轴/extra-joints 配置 |
| 转台/摆头 | `trtfuncs.c`、`xyzac-trt-kins.c`、`xyzbc-trt-kins.c` | table-rotary-tilting、刀尖/偏置变换 | `axis/vismach/5axis/*`、`gmoccapy/non_trivial_kinematics/*` |
| Delta | `lineardeltakins.c/.cc`、`lineardeltakins-common.h` | 线性 Delta 正逆解、工作空间限制 | `axis/ldelta*`、`tklinuxcnc/ldelta.ini` |
| Rotary Delta | `rotarydeltakins.c/.cc`、`rotarydeltakins-common.h` | 旋转 Delta 几何 | `axis/rdelta.ini` |
| Tripod/并联 | `tripodkins.c` | 三腿并联、姿态分支 | `tklinuxcnc/tripod.ini` |
| Hexapod | `genhexkins.c`、`genhexkins.h` | 六杆并联、迭代正解、平台上下分支 | `axis/vismach/hexapod-sim/*` |
| Pentapod | `pentakins.c/.h` | 五杆并联、平台姿态和分支 | `axis/pentapod/*` |
| 通用串联机器人 | `genserkins.c`、`genserfuncs.c`、`genserkins.h` | DH 链、Jacobian、迭代逆/正解 | `qtaxis/non-trivial/scara` 及机器人样例 |
| SCARA | `scarakins.c` | 平面串联、腕部旋转、分支选择 | `axis/vismach/scara/*`、`qtvcp_screens/non-trivial/scara/*` |
| PUMA | `pumakins.c` | 6 轴串联、腕部奇异性和分支 | `axis/vismach/puma/*` |
| Scorbot | `scorbot-kins.c` | 机器人专用几何和姿态分支 | `configs/sim` 中 Scorbot/robot 资源 |
| 用户/示例 | `cubic.c/.h`、`userkfuncs.c`、`ugenserkins.c` | 用户参数和模板;不允许动态宿主插件 | 只在 manifest 明确登记后启用 |
| 切换容器 | `switchkins.c` | 多算法运行时切换 | SCARA、Hexapod 和含 switchkins 的配置 |
除了 `KINEMATICS` 值,还要扫描 `HALFILE` 中的 `corexy_by_hal`、`xyzab_tdr_kins`、`loadrt` 和 GUI pin;这些可能在 HAL 或用户组件层实现变换。
### 2.4 K0-INV-01 闭合审计(2026-08-20)
`coverage/kinematics-source-closure.report.json`(schema `v2`)是本节点的机器可读证据,并以当前 `context_id` 绑定到锁定来源。报告不只按文件名计数,而是把 source index、source-symbols、配置行和 HAL 行转成稳定 ID:
| 审计面 | 结果 | 证据字段 |
|---|---:|---|
| `src/emc/kinematics` 全目录文件 | 38 个,其中 35 个 `.c/.cc/.h` 实现/头文件 | `source.files[*].source_id`、`extension`、`sha256` |
| `KINEMATICS=`(`.ini` 和 `.inc`) | 268 条 | `configuration.entries[*].config_id` |
| `loadrt`、HAL 变换、switchkins 控制 | 111 条;模板 `[KINS]KINEMATICS`、`corexy_by_hal`、`motion.switchkins-type` 分别保留 | `hal.entries[*].config_id`、`kind`、`family` |
| 实现族 | 11 族均有源码 ID 和配置候选映射 | `families[*].source_ids`、`configuration_ids` |
| 测试输入 | `tests/matrixkins` 6 个文件;`linuxcnc/unit_tests/kinematics` 缺失 | `tests.*`、`missing_required_test_roots` |
| FK/IK oracle | 11 族全部 `blocked` | `families[*].oracle.reason`、`closure.oracle_blocked_families` |
缺失的官方测试根目录来自锁定提交本身;报告不会把 `tests/matrixkins/**` 改名或升级为 `unit_tests/kinematics/**`。`matrixkins` 仍作为 HAL 组件/配置入口候选登记,待契约变更或补充官方输入后才能产生 native FK/IK golden。2 个 TRT `.c` 文件在现有 source-symbols 报告中是 `indexed_empty`,不是静默丢失;其 source ID、哈希和待补符号状态均保留。
### 2.5 K0-INV-02 配置图与样本集(2026-08-20)
`coverage/kinematics-config-graph.report.json` 将审计报告中的 262 个 `KINEMATICS` 条目和 111 个 HAL/切换条目展开为 373 个入口节点、1,491 个文件/族/资源节点和 2,774 条有向边。模板化 `loadrt [KINS]KINEMATICS` 的解析状态分为 `explicit_reference`、`directory_owner` 和 `inactive_reference`;后两类保留来源事实,但不能当作已启动配置。图的 `orphan_entry_ids` 和 `unowned_template_ids` 必须为空。
`coverage/kinematics-oracle-samples.jsonl` 为 11 个实现族各登记一个固定 `fk_ik_fk_roundtrip` 样本、候选配置、输入姿态/关节、容差和精确字段。样本当前全部 `blocked`,原因仍是锁定提交没有 `linuxcnc/unit_tests/kinematics/**`;`tests/matrixkins/test.ini` 只作为 `user_static` 的配置候选,未被提升为官方 oracle。只有补充/批准输入契约后,才允许把 `execution.status` 改为可运行并生成 native golden。
### 2.6 K0-ORACLE-01 runner/schema(2026-08-20)
`scripts/generate_kinematics_oracle_report.py` 在固定 `PATH/HOME/LANG/LC_ALL/TZ/PYTHONHASHSEED` 环境中运行 `build-native/sim_kinematics_test` 作为 native smoke,并为 11 个样本输出 `coverage/kinematics-oracle.report.json`。`coverage/kinematics-golden-schema.json`(`linuxcnc-web-wasm/kinematics-golden.v1`)要求 `status/error_code/kinematics_type/branch_id/flags/current_tick/config_hash/axis_joint_mapping` 等字段;缺字段不会通过比较。当前 native smoke 为 `passed`,但 11 个样本均为 `blocked`,错误码为 `MISSING_OFFICIAL_ORACLE`,没有伪造数值 golden。
### 2.7 K1-CONTRACT-01 ABI contract(2026-08-20)
`coverage/kinematics-abi-contract.json` 从 `sim_kinematics.h`、`wasm-core/CMakeLists.txt` 和固定数值策略生成。它锁定 ABI version 1、8 个公开函数、结果/类型/mode 枚举、3 个结构体字段列表、`SIM_KIN_ERR_*` 错误码、`-ffp-contract=off`/`-fno-fast-math`、非有限值拒绝、100000 最大迭代和 FNV-1a-64 state hash;缺失 Emscripten export 会使 contract `blocked`。当前 contract `verified`,native/WASM 构建及 8 个 CTest 均通过。
`coverage/kinematics-mapping-contract.json` 进一步锁定 ASCII case-fold、重复轴 first-wins、extra-joint 数量、home 零位、inclusive limits、forward/inverse 映射和 state hash 输入字段;`sim_kinematics_test` 已覆盖 `XYYZ`、越界和 home 样本。
`coverage/kinematics-numeric-policy.json` 固定 `-ffp-contract=off`、禁用 fast-math、角度单位、100000 迭代上限、1e-12 奇异阈值、1e-9 golden 容差和 exact 字段;NaN/Inf、负容差、超迭代、奇异和越界都列入边界矩阵。
### 2.3 当前 WASM 雏形的真实边界
当前 `wasm-core/include/sim_kinematics.h`/`sim_kinematics.c` 只能作为 K1 之前的实验切片,不能作为完整实现证据:
| 已存在 | 尚未闭合 |
|---|---|
| `trivkins`、`XYZAC-TRT`、`XYZBC-TRT`、`XYZBCW` 的有限正逆解和基础 joint limit 检查 | LinuxCNC 全部实现族:CoreXY、Rose、5axiskins 完整模式、Delta/RotaryDelta、Tripod、Hexapod、Pentapod、GenSer、SCARA、PUMA、Scorbot、switchkins 和用户静态扩展 |
| 基础 `coordinates` 字符串和重复关节填充 | `KINEMATICS_TYPE` 四种语义、extra joints、完整轴 bitmap、world/joint mode 约束和 home 语义 |
| 有限性检查、少量奇异性检查和 FNV 状态 hash | `fflags/iflags` 分支状态、last-pose/seed、residual、iterations、branch_id、确定性迭代策略和恢复字段 |
| C API 单元样例 | LinuxCNC native FK/IK oracle、每个配置入口的 golden、HAL 实现等价性和 UI/Vismach 姿态证据 |
另外,现有 `sim_kinematics.c` 尚未加入 `wasm-core/CMakeLists.txt` 的 `sim_core`/Emscripten module,`sim_kinematics_test.c` 也未进入 CTest;因此当前 `ctest` 的 7/7 通过不包含运动学验证。K1 的第一项集成工作必须先修复构建和测试注册,再谈算法族扩展。
因此 K0/K1 不能只围绕现有 `sim_kinematics_*` 函数补测试;必须先完成统一契约,再按 K2-K5 族逐步替换或扩展实现。现有切片的错误码和字段若与统一 ABI 冲突,应通过版本化契约迁移,不得在旧 ABI 上堆叠不可兼容的类型。
## 3. 统一运动学契约
### 3.1 输入、输出和状态
WASM 内部使用固定宽度、明确大小的结构,TypeScript 不接触 C 结构体布局。逻辑契约如下:
```text
KinematicsRequest {
kind: FORWARD | INVERSE | HOME | CHECK
joints[N] / pose{ x,y,z,a,b,c,u,v,w }
fflags: uint64
iflags: uint64
seed_pose: optional pose # 迭代正解初值
config_hash: bytes32
simulation_tick: uint64
}
KinematicsResult {
status: OK | INVALID_INPUT | OUT_OF_RANGE | SINGULAR | NO_SOLUTION |
NOT_CONVERGED | UNSUPPORTED | NUMERIC_ERROR
joints[N] / pose
fflags: uint64
iflags: uint64
residual: float64
iterations: uint32
branch_id: uint32
state_hash: bytes32
}
```
必须固定以下语义:
1. `forward(joints)` 返回世界 pose,并更新适用的 `iflags`;`inverse(pose)` 返回关节,并更新适用的 `fflags`。
2. flags 是会话状态的一部分,必须进入快照、golden 和恢复账本;不能每次调用清零来掩盖分支变化。
3. `home()` 产生已知的世界 pose、joint 和 flags;不能只把所有关节设为零。
4. `KINEMATICS_FORWARD_ONLY`、`INVERSE_ONLY` 的 mode 转换限制要与 LinuxCNC 一致;不支持的调用返回 `UNSUPPORTED`,不能返回伪造 pose。
5. 所有输入输出先检查有限性、维数、单位和配置 hash;NaN/Inf、数组越界、未知轴字母和未知类型在进入算法前拒绝。
### 3.2 坐标、关节和 extra joints
`coordinates` 解析为轴索引到 joint 编号的稳定映射,并记录重复轴 bitmap。运动学 joint 数量与 `EMCMOT_MAX_JOINTS`、`NO_OF_KINS_JOINTS`、extra joints 的边界必须分开表示:
- kinematics 只接收前 `NO_OF_KINS_JOINTS` 个关节;extra joints 由 motion/Task 管理,不得误传给算法。
- `XYYZ`、`XYZY` 等重复坐标必须在配置加载时生成映射 golden,并在 joint/world 模式切换时复用。
- 旋转轴的角度单位、绕轴方向、回绕策略和连续性要逐类型登记;不能用统一的线性限位代码代替。
- UI 显示的 axis pose、joint pose、commanded/actual pose 必须注明坐标系和来源 tick。
### 3.3 正逆解数值策略
解析解与迭代解使用同一个数值政策:
- Emscripten/native 固定编译选项、舍入模式和 `sin/cos/sqrt/atan2` 包装;算法不得调用墙钟或未锁定随机数。
- 解析算法返回工作空间、关节限位、姿态范围和分支错误,而不是将超界结果钳位后返回 `OK`。
- 迭代算法固定初值来源、最大迭代次数、收敛残差、步长/阻尼、奇异阈值和失败码;每次结果记录 `iterations/residual/branch_id`。
- 对正逆解只使用定义好的几何容差;状态、分支、错误码和事件顺序必须精确一致。
- 迭代正解(Hexapod、通用串联等)在相邻 tick 使用上一次有效 pose,但恢复后必须从 checkpoint 中恢复该 seed。
## 4. 按算法族的实施要求
### 4.1 笛卡尔和耦合线性族
先完成 `trivkins` 的 identity/both/inverse-only/forward-only、坐标重复映射和 max/rotate 变体,再完成 `corexykins`、`rosekins` 的矩阵映射。每一类需要:
- 正逆解矩阵和符号方向的单元向量测试;
- 重复轴、extra joints、关节限位、回零和 joint/world 模式测试;
- HAL 实现的 `corexy_by_hal` 与 kinematics 模块实现的对照,证明同一轨迹在两条链上等价;
- 快速/1x/暂停恢复后的关节和世界 pose hash 一致。
当前 K2 耦合切片已完成 CoreXY、Rose、MaxKins 和 RotateKins 的统一实现。CoreXY 复现 LinuxCNC 的半和/半差公式,并分别登记 `corexy_by_kins.ini` 与 `corexy_by_hal.ini`,HAL 组件路径保持为独立入口;Rose inverse 保存上一象限和累计圈数,跨 2→3 象限得到连续角度和稳定 branch;MaxKins 保留 pivot/B/C/U/V/W 修正公式并覆盖真实 `max5kins.ini` 的 `pivot-length=0`;RotateKins 覆盖负 C 旋转方向和 90°边界。锁定 LinuxCNC 没有 shipped 的 rotatekins `.ini`,因此新增的 `linuxcnc/configs/sim/axis/rotate/rotatekins.ini` 明确标为 workspace-derived fixture,不冒充官方配置或 oracle。`coverage/coupled-kinematics.report.json` 使用相同样本运行 native 与 WASM,并比较规范化 JSON 和 state hash;由于 `linuxcnc/unit_tests/kinematics` 不在锁定源中,报告状态仍为 partial/blocked,不生成伪造官方 golden。
`K2-HAL-01` 已在同一契约上接入静态 `corexy_by_hal`。SimHAL 注册组件的 8 个 float pin 和 servo-thread function,周期内执行 `.comp` 的 `alpha/beta` 命令矩阵与 `j0/j1` 反馈矩阵;HAL 配置中的 `j0home/j1home` 路由在变换前保留 Cartesian home 语义,并与 `corexykins` 的 motor-joint home 明确区分。`coverage/corexy-hal.report.json` 对配置连接、公式、native/WASM 输出和 oracle 阻塞状态做确定性检查;完整 HAL 命令解析、其它组件和真实 unit-test oracle 仍属于后续节点。
`K3-5AXIS-01` 已接入 `5axiskins` 的 XYZBCW spherical pivot 链。真实 `bridgemill/5axis.ini` 使用 `coordinates=xyzbcwy` 和七个 joints,重复 Y 由 first-wins 映射并在 inverse 后同步 suffix;pivot length 250、B/C 角度和 W 工具运动均进入 FK/IK 与 state hash。缺少 XYZBCW 任一必需字母返回 configuration error;`coverage/fiveaxis-kinematics.report.json` 对配置、源公式、重复轴、边界和 native/WASM 样本做确定性记录,官方 unit-test oracle 仍 blocked。
`K3-TRT-01` 已接入 `xyzac-trt-kins` 与 `xyzbc-trt-kins` 共用的 `trtfuncs.c` 姿态链。`table-rotary-tilting/xyzac-trt.ini` 与 `xyzbc-trt.ini` 的 `sparm=identityfirst`、五关节、tool/offset HAL pins 均登记;XYZAC 保持 C→A 顺序,XYZBC 保持 C→B 顺序,offset 与 tool length 进入固定解析式。B=90 的配置边界显式返回 singular,native/WASM 样本和 hash 见 `coverage/trt-kinematics.report.json`;switchkins 运行时切换容器留到 K5,不在本节点伪装完成。
`K3-ROBOT-01` 已接入 SCARA、PUMA 和 Scorbot 专用解析式。SCARA 使用 D1-D6、C 总姿态和 elbow 分支;PUMA 使用 A2/A3/D3/D4/D6、完整旋转矩阵/RPY 转换以及 shoulder/elbow/wrist 分支和 wrist singular 检查;Scorbot 使用固定 L0/L1/L2 链和受控点 RZ 逆解。SCARA 与 PUMA 取自 shipped Vismach 配置,Scorbot 因锁定源没有 shipped INI 使用明确标注的 workspace-derived fixture。PUMA 等复杂三角函数的 native/WASM state hash 在 `1e-9` golden 容差上规范化,避免后端 libm 末位差异成为伪状态分叉;所有不可达/奇异边界和官方 oracle 状态见 `coverage/robot-kinematics.report.json`。
`K3-GENSER-01` 已接入六关节 Craig DH 链和固定零初值的阻尼数值 Jacobian inverse。DH `A/ALPHA/D` 数组、alpha 弧度与 joint 度数转换、有限差分步长、阻尼、最大迭代次数、residual 和不收敛错误均进入配置/报告;melfa 与 puma560 的真实 `genserkins` 配置作为候选,样本在 native/WASM 逐字一致。此节点不把动态 `switchkins` 或用户库放行到浏览器,官方 unit-test oracle 仍 blocked,详见 `coverage/genser-kinematics.report.json`。
`K4-DELTA-01` 已接入 linear/rotary Delta 的统一 forward/inverse/mapping 路径。线性 Delta 使用锁定 `lineardeltakins-common.h` 的 120 度塔架与杆长解析二次式;旋转 Delta 使用锁定 `rotarydeltakins-common.h` 的平台/大腿/小腿/足端几何。两者均固定 XYZ 到前三个 kinematics joints 的映射,A/B/C/U/V/W 透传,额外 joints 不进入算法;默认根保持 LinuxCNC 的平台根,`SIM_KIN_DELTA_ALTERNATE_ROOT` bit 0 使 alternate root、`branch_id` 和 state hash 可观察。真实 `ldelta.ini`、`ldelta_demo.ini`、`tklinuxcnc/ldelta.ini`、`rdelta.ini` 均登记;nominal/alternate root、工作空间无解、关节限位和 rotary `z=0` 奇异边界在 native/WASM 逐字对照。配置引用的 HAL 文件在锁定工作区缺失,作为 resource gap 保留,不能升级为配置 smoke 或数值 golden;官方 `linuxcnc/unit_tests/kinematics/**` 同样缺失,全部 Delta oracle 明确 blocked,详见 `coverage/delta-kinematics.report.json`。
### 4.2 5 轴转台/摆头族
`5axiskins`、`xyzac-trt-kins`、`xyzbc-trt-kins` 必须共享但不能混用各自的旋转顺序、刀尖点和 offset 语义。验收至少包括:
- A/B/C 旋转顺序、正负方向、角度单位和回绕;
- table-rotary 与 tool-rotary 的姿态链;
- `identityfirst` 参数、刀长/刀尖偏置、G43/G43.1/G49 与逆解;
- 旋转轴接近 0/180/360 度、万向节/姿态奇异和无解报警;
- impeller、table-rotary-tilting、dual-rotary 的真实 `configs/sim` 入口和 Vismach 姿态。
### 4.3 Delta、Tripod、Hexapod、Pentapod
并联机构不能只测“一个可达姿态”。每种机构需要工作空间边界、腿长/关节范围、平台上下分支、奇异面和迭代初值测试:
- Delta:塔架几何、臂长、平台平移边界、负根/无根和线性/旋转变体;
- Tripod:三腿约束、姿态分支、回零和连续轨迹;
- Hexapod:六杆长度、平台上下姿态、迭代正解、last-pose 和 GUI pins;
- Pentapod:五杆约束、平台姿态、不可达/奇异区域和 `pentapod.var` 参数。
每次迭代必须输出 residual 和迭代次数。相同 seed、输入和 tick 必须得到相同分支;越过分支边界时要产生可解释的 `SINGULAR` 或 `NO_SOLUTION` 事件,不能突然跳姿态。
### 4.4 通用串联机器人族
`genserkins` 以 DH 链、Jacobian 和迭代求解为核心;`scarakins`、`pumakins`、`scorbot-kins` 是专用参数化实现。实施顺序:
1. 统一 link 参数、角度单位、joint offset、正方向和关节范围。
2. 先用 FK 生成 pose oracle,再用 FK→IK→FK round-trip 验证每一个分支。
3. 对 Jacobian 条件数、阻尼、步长、初值和最大迭代建立配置字段,全部进入快照。
4. 覆盖 elbow-up/down、腕部翻转、SCARA 平面无解、PUMA wrist singularity 和 Scorbot 专用姿态。
5. UI 轨迹显示必须消费 kinematics 输出的姿态,不能用线性 axis 拼接替代机器人 FK。
### 4.5 Switchkins 和用户扩展
`switchkins` 不是动态加载的放行口,而是静态注册的最多三种实现容器。每个 `switchkins_type` 必须有:
- 类型、坐标要求、最大 joint 数、是否允许重复轴、是否迭代正解的 manifest;
- 切换前后同步点、flags/lastpose 初始化和 GUI pin;
- 非法类型、缺失实现、切换中运动、恢复后重建和回滚测试。
`userkfuncs`、`ugenserkins` 和 `.so/.so` 类宿主动态模块不能直接加载。可移植用户运动学必须在构建期编译为静态 WASM 模块,提供相同 ABI、版本和 capability;不满足时返回 `UNSUPPORTED_USER_KINS` 并阻断配置启动。
## 5. 运动学主线任务和里程碑
M0/M1 的基线和会话骨架保持不变;从原 `M2-CORE-04` 起,采用以下 K 系列主线。K 系列任务完成后才能解锁对应的 M3/M4 工作流。
| 里程碑 | 任务 | 结果 | 依赖 | 退出门槛 |
|---|---|---|---|---|
| K0 清单与 oracle | `K0-INV-01` 源文件/符号索引;`K0-INV-02` 配置入口图;`K0-ORACLE-01` native FK/IK/golden schema | 完整类型、参数和配置清单 | M0 | 所有 kinematics 文件和入口有 source/feature/test/oracle;缺失输入显式 blocked |
| K1 ABI 与数值 | `K1-CONTRACT-01` C ABI;`K1-CONTRACT-02` flags/pose/映射;`K1-NUM-01` 浮点/迭代政策 | `sim_kinematics.h`、错误码、状态 hash | K0、M1 | 同输入三次字节和 hash 一致;非法/NaN/Inf/越界全有测试 |
| K2 笛卡尔/耦合 | `K2-TRIV-01` trivkins 全类型;`K2-TRIV-02` 重复轴/extra joints;`K2-COUPLED-01` corexy/rose/max/rotate;`K2-HAL-01` HAL 等价链 | identity、both、耦合线性运动学 | K1 | 轴/关节模式、home、限位、HAL 和恢复 golden 全绿 |
| K3 5 轴串联 | `K3-5AXIS-01` 5axiskins;`K3-TRT-01` xyzac/xyzbc/trt;`K3-ROBOT-01` SCARA/PUMA/Scorbot;`K3-GENSER-01` DH/Jacobian | 5 轴、转台/摆头和串联机器人 | K2、posemath | FK/IK round-trip、分支、奇异、刀尖/刀长和真实配置入口通过 |
| K4 并联机构 | `K4-DELTA-01` linear/rotary Delta;`K4-TRIPOD-01` tripod;`K4-HEX-01` genhex;`K4-PENTA-01` pentapod | 全部并联正逆解和迭代恢复 | K1、K2 | 工作空间边界、无解、奇异、分支、lastpose、GUI pins 和故障注入通过 |
| K5 切换/扩展 | `K5-SWITCH-01` switchkins;`K5-USER-01` 静态 userk/ugenser;`K5-CFG-01` 参数和能力注册 | 可切换和构建期扩展模型 | K3、K4 | 非法切换、缺模块、恢复、版本和权限错误明确;无动态宿主加载 |
| K6 运动集成 | `K6-MOTION-01` TP→IK→motion;`K6-MOTION-02` FK feedback;`K6-HOME-01` home/limit;`K6-IO-01` spindle/tool/probe | 运动学与 Task/HAL/IO/数字孪生闭环 | K2-K5 | `configs/sim` 运动学入口可启动、运行、暂停、急停、恢复 |
| K7 UI/回归 | `K7-VIS-01` 姿态/关节/刀尖渲染;`K7-RECOVERY-01` 固定 tick checkpoint/replay 与 workspace 恢复;`K7-REG-01` 全配置;`K7-REG-02` 浏览器故障矩阵 | 可视化、恢复和全量回归 | K6、M3/M4 | 轨迹、姿态、joint/world、报警、恢复终点与连续运行一致、回放和多浏览器证据齐全 |
| K8 发布闭合 | `K8-REL-01` 兼容报告;`K8-REL-02` 迁移/回滚;`K8-REL-03` 许可证/来源闭包 | 运动学纳入完整仿真机床发布 | K0-K7 | 受影响条目全部 `accepted`,无孤儿、无未解释差异、无静默降级 |
`K4-TRIPOD-01` 已完成:`tripodkins.c` 的点顶点三杆并联机构已接入统一 forward/inverse/mapping,使用真实 `linuxcnc/configs/sim/tklinuxcnc/tripod.ini` 和 `linuxcnc/lib/hallib/tripodsim.hal` 验证 XYZ/AD-BD-CD 映射、above/below 根分支、三角不等式无解、基面奇异、关节限位、退化基座和固定零迭代;native/WASM JSON 与 state hash 一致,官方 oracle 因锁定来源缺少 `linuxcnc/unit_tests/kinematics/**` 继续显式 blocked。证据见 `coverage/tripod-kinematics.report.json`。
`K4-PENTA-01` 已完成:`pentakins.c/.h` 的五杆并联机构已接入统一 forward/inverse/mapping,使用真实 `linuxcnc/configs/sim/axis/pentapod/pentapod.ini`/`kinematics.hal` 和派生非零姿态 seed,固定 XYZAB 映射、roll/pitch 姿态约束、tool-offset 双端几何、Newton 5x5 收敛/迭代上限/最大误差/奇异/非正杆长/关节限位边界;native/WASM JSON 与 state hash 一致。官方 oracle 因锁定来源缺少 `linuxcnc/unit_tests/kinematics/**` 继续显式 blocked。证据见 `coverage/pentapod-kinematics.report.json`。
`K5-SWITCH-01` 已完成:基于真实 `xyzac-trt.ini` 的 `sparm=identityfirst` 约定接入三槽位 switchkins 容器,固定 type 0 identity、type 1 xyzac-trt、type 2 userk 注册表;切换通过旧模式 FK、目标模式 IK 的 prepare/commit,保证 pose 连续,失败和 abort 保持旧模式,非法模式、缺模块和切换中断分别返回稳定错误码;native/WASM runner、模式状态 hash 和恢复计数一致。官方 oracle 因锁定来源缺少 `linuxcnc/unit_tests/kinematics/**` 继续显式 blocked。证据见 `coverage/switchkins-kinematics.report.json`。
`K5-USER-01` 已完成:`userkfuncs.c` 的 identity 模板和 `ugenserkins.c` 的 genser 使用面已收敛为构建期静态描述符,固定 ABI v1 与 forward/inverse/static capability mask;userk 可注册到 switchkins type 2,ugenser 复用已验证的静态 genser FK/IK,调用计数与 state hash 进入确定性状态。带路径名称、宿主 `.so`、ABI/能力不匹配、未知和未初始化模块均 fail-closed;旧 ugenser userspace CLI 按其源码警告明确排除,不作为 oracle。native/WASM runner 一致,官方 oracle 继续显式 blocked。证据见 `coverage/userkins-kinematics.report.json`。
`K5-CFG-01` 已完成:18 个内建运动学类型进入 ABI v1 构建期只读注册表,稳定登记 LinuxCNC 模块名、type、必需坐标、关节范围、forward/inverse/identity/iterative/switchable/extra-joint/duplicate-coordinate 能力位,以及 mapping/limits/offsets/tool/pivot/geometry/DH/solver 参数族。18 个最小配置全部经实际 `sim_kinematics_init` 验证;能力/参数不满足、type/坐标/关节错配、未知和路径名称均返回稳定错误。native/WASM 注册表 JSON 与 hash 一致,官方 oracle 继续显式 blocked。证据见 `coverage/kinematics-registry.report.json`。
`K6-MOTION-01` 已完成:新增固定 tick 的 TP→IK→关节样本队列适配器,复用现有 `sim_tp` 和 `sim_kinematics_inverse_ex`,每帧先推进 planner 再事务式生成关节样本;队列容量 64、暂停/恢复、非有限输入、planner 错误、IK 奇异和容量满边界均有固定错误码。IK 或容量失败会回滚 planner/kinematics 状态,nominal/capacity/inverse rollback 的 native/WASM JSON 与 state hash 一致;官方 oracle 继续显式 blocked。证据见 `coverage/kinematics-motion.report.json`。
`K6-MOTION-02` 已完成:新增固定 tick 的 actual-joint→FK feedback 适配器,保存世界 pose、joint snapshot、forward/inverse flags、tick、valid 和双层错误码;首次读取前返回 stale,非有限和 joint-count 错误不推进有效状态,forward 不支持/失败时保留无效状态且不发布 pose。native/WASM feedback JSON 与 state hash 一致,官方 oracle 继续显式 blocked。证据见 `coverage/kinematics-feedback.report.json`。
`K6-HOME-01` 已完成:新增固定 home sequence、`sim_kinematics_home` 初始化和 joint limit/FK 检查适配器;未 home、非法 sequence、越界、非有限和 joint-count 错误均 fail-closed,越界时保留上一帧有效 pose/joints,home/limit state hash 稳定,native/WASM JSON 一致。官方 oracle 继续显式 blocked。证据见 `coverage/kinematics-home-limit.report.json`。
`K6-IO-01` 已完成:新增固定 tick 的 `sim_io` spindle/tool/probe 适配器,注册 LinuxCNC motion/iocontrol pins 和 `sim-io-servo` 调度函数;主轴覆盖限速、加减速、inhibit、到速、制动、revs/index、orient 和故障,换刀覆盖 prepare/prepared/change/changed、停主轴互锁、abort/fault/恢复,探针覆盖 arm、输入边沿和 forward pose 锁存。非法 pin 类型、超限、未 ready、急停、故障清除和恢复均有稳定错误码;native/WASM JSON 与 state hash 一致。官方 IO/kinematics oracle 继续显式 blocked。证据见 `coverage/io-runtime.report.json`。
`K7-RECOVERY-01` 已完成当前恢复适配子集:固定 tick checkpoint 携带 context、event cursor、snapshot/state hash 和 operation ledger;Worker replay 严格拒绝损坏 checkpoint、未知 schema、缺号/重复事件和未确认副作用,abort 进入显式 `aborted`,恢复终点与连续运行状态 hash 对齐;native `sim_event_import` 与 Worker replay/recovery 测试均通过。官方 recovery oracle、完整 native/WASM 全状态对照和浏览器 OPFS 崩溃场景因锁定来源缺失继续显式 blocked。证据见 `coverage/workspace-recovery.report.json`、`web/worker/replay.mjs`、`web/workspace/recovery.mjs`。
`K8-REG-01` 已完成全配置回归适配:从统一配置图确定性枚举 264 个运动学入口(覆盖 233 个 `configs/sim` 主入口及 include/测试入口),逐入口保留 INI 形状、资源行、缺失/未解析资源、注册表归属和静态启动预检结果;资源图没有新增孤儿入口或未拥有模板。native/WASM 的 kinematics、motion、feedback、home/limit、IO 固定样本和重复运行 hash 均稳定,Worker replay、workspace recovery、sim session 摘要重复一致;恢复终点与连续状态 hash 对齐。当前资源缺失、未索引 include、未注册模块和官方 kinematics/recovery oracle 均显式 blocked,派生配置摘要不作为官方 golden。证据见 `coverage/configuration-regression.report.json`、`scripts/generate_configuration_regression.py`、`scripts/test_configuration_regression.py`。
`K4-HEX-01` 已完成:`genhexkins.c` 的六腿 Stewart 平台已接入统一 forward/inverse/mapping,使用真实 `linuxcnc/configs/sim/axis/vismach/hexapod-sim/hexapod.ini` 与 `kinematics.hal` 验证六腿闭式逆解、Newton 6x6 正解、确定性初始种子、alternate seed、非正 strut、迭代上限、最大误差、奇异 Jacobian、限位、HAL GUI/迭代 pin 和 native/WASM state hash;官方 oracle 继续显式 blocked。证据见 `coverage/genhex-kinematics.report.json`。
每个 K 里程碑都必须同时更新 `coverage/manifest.jsonl`、source map、golden 索引、任务指针和证据摘要。算法代码通过单测但没有配置入口或 UI 姿态证据时,不能推进到下一个里程碑。
## 6. 运动学测试矩阵
每个实现族至少有以下测试层;参数和样本由 K0 清单生成,不允许只挑“容易收敛”的点:
| 层 | 样本 | 必测内容 |
|---|---|---|
| 纯函数 | 合法 pose/joint、边界、随机种子固定的网格 | FK、IK、FK→IK→FK、IK→FK→IK、flags 和 residual |
| 几何边界 | 轴/关节最小最大、工作空间边缘、旋转回绕 | limit、无解、奇异、分支连续性 |
| 配置 | 每个非 trivkins `configs/sim` 入口及所有 `trivkins` 变体 | 参数、坐标、HALFILE、tool/var、资源图和启动错误 |
| 运动 | G0/G1/G2/G3、5 轴刀尖、jog、home、暂停、abort | TP→IK→motion、反馈、following error、最终姿态 |
| 故障 | 探针、限位、主轴/换刀、迭代不收敛、Python 异常 | 报警、停止、恢复、状态 hash 和事件顺序 |
| 持久化 | checkpoint、journal、刷新、Worker 重启、离线 | flags、lastpose、seed、工具和姿态恢复一致 |
| 浏览器 | Chromium/Firefox/Safari 计划矩阵、窄屏/触摸 | 3D 非空、姿态无跳变、背压、错误可见 |
### 6.1 Golden 和容差
native runner 为每个样本保存输入 hash、配置 hash、算法版本、pose/joint、flags、residual、iterations、branch、错误和最终 state hash。WASM 只允许在已登记的浮点字段使用容差;以下字段必须精确:
```text
status / error_code / kinematics_type / branch_id
flags / current_tick / event_order / config_hash
axis-to-joint mapping / home result presence / state transition
```
差异报告必须包含首个 divergent tick、字段路径、原生值、WASM 值、容差、source_id 和可重放命令。迭代不收敛不得被提高最大迭代次数或放宽容差“修绿”;应记录算法参数和失败原因。
## 7. 与整体仿真机床的接合顺序
运动学主线不是独立库,接合顺序固定如下:
1. K1 ABI 完成后,`sim_motion` 只通过 `KinematicsRegistry` 调用,不再硬编码 trivkins。
2. K2 完成后,解释器/TP 的 canonical 轨迹接入 axis/joint 变换,HAL 反馈接入 FK。
3. K3/K4 完成后,数字孪生为每种机床提供真实 joint/pose 反馈、限位、回零和故障;Vismach/Three.js 使用同一 FK 结果。
4. K5 完成后,Python/remap/VCP 获得只读 kinematics 状态和受控切换命令;切换必须经过 Task 同步点。
5. K6 完成后,OPFS checkpoint 保存 kinematics type、参数、flags、lastpose、seed 和 joint/pose 状态。
6. K7 完成后,UI 同时显示世界坐标、关节坐标、机床姿态、刀尖和限制原因;不能把 axis 数值当成所有机床的刀具姿态。
## 8. 当前执行和停止线
当前 `M2-CORE-04` 的 `unit_tests/kinematics/**` 缺失仍然是 K0 的输入审计事项,不自动改成实现任务。立即顺序为:
1. `K0-INV-01` 确认锁定提交的 kinematics 文件、符号和测试路径,生成缺失输入报告。
2. `K0-INV-02` 从 `configs/sim`、`tests/matrixkins` 和实际 kinematics 配置生成入口图;这些可以作为配置 oracle,但不能冒充缺失的官方 unit test。
3. `K0-ORACLE-01` 在原生 runner 中建立 FK/IK JSONL schema 和最小 trivkins/corexy/非平凡样本。
4. 经审查决定是否创建新的输入契约/context lock;未决定前保持 blocked,不跳到 HAL 节点。
5. K1 ABI 和数值政策完成后,再按 K2→K5 算法族推进;K6 以前不开放全量 UI 运动学声明。
以下条件必须停止并回到对应里程碑:输入源或配置入口遗漏;正逆解首次差异未定位;分支/flags/lastpose 未进入快照;算法依赖墙钟或随机数;用伪造 pose、钳位越界值、放宽容差或刷新重建掩盖失败;用户运动学需要未登记的动态宿主库。
完成 K8 后,运动学才能从“核心切片”升级为“仿真机床完整能力”,并作为整个 LinuxCNC Web/WASM 发布的必要条件。