# 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 发布的必要条件。