Configure single-DOF machine joints and drive them from WASM axes

This commit is contained in:
2026-09-21 11:24:22 +08:00
parent 989866b3ab
commit d8488641ca
32 changed files with 12058 additions and 215 deletions

View File

@@ -8,12 +8,12 @@
1. 对话框包含独立的 Three.js 三维预览,实时显示正在配置的机床。
2. 支持逐个导入自包含 `.glb` 机床部件,不允许依赖外部纹理或网格文件。
3. 每个部件可绑定 `底座、X、Y、Z、刀具、A/B、C、工件` 角色,并编辑父级关系。可运行结构必须满足:
3. 每个部件可绑定 `底座、X、Y、Z、刀具、A/B、C、工件` 结构角色,并编辑父级关系。MGR-17 以独立的 XYZABC 自由度绑定驱动视觉层级,允许单 GLB 多关节。数控求解器仍按 TRT 的控制参考链运行:
- 刀具链:底座 → X → Y → Z → 刀具。
- 转台链:底座 → A/B → C → 工件。
4. 每个部件可定义局部坐标原点。模型网格相对该原点偏移,运动关节围绕该原点运动。
5. 每个部件可独立显示或隐藏原点坐标轴辅助线。
6. 每个部件可用数值和 Three.js 操纵器平移、旋转;变换只修改装配配置,不修改原 GLB 字节。Three.js 管理器通过 `camera.up.set(0, 0, 1)` 使用机床 Z-up 场景,机床 XY 为地面平面;导入 GLB 的节点、几何、材质、内部层级和原始变换保持不变。
6. 每个运动节点只允许通过绑定的唯一自由度修改位移或转角,固定节点锁定;旧六分量自由编辑和操纵器由单值关节输入替代。变换只修改预览配置,不修改原 GLB 字节。Three.js 管理器通过 `camera.up.set(0, 0, 1)` 使用机床 Z-up 场景,机床 XY 为地面平面;导入 GLB 的节点、几何、材质、内部层级和原始变换保持不变。
7. 可定义 C 轴原点位置和 A/B 到 C 的运动学偏置。应用时写入底座场景节点及整机场景的 `userData.linuxcncMachineGeometry`,同时生成 URDF:
- `C 原点 P = (x-rot-point, y-rot-point, z-rot-point)`。
- `A/B 偏置 D = (x-offset, y-offset, z-offset)`。
@@ -50,3 +50,5 @@
- 非法层级、重复角色、缺失部件、错误机型和外部资源 GLB 明确拒绝,已生效模型不改变。
15. 树中每个节点独立编辑相对父级的位置(mm)和 XYZ 欧拉姿态(deg)。数值输入回显节点当前局部值,旋转以自身原点为中心;子节点随动,父级和兄弟节点不变。源 GLB 保留,节点编辑保存在草稿并进入组合导出。
16. MGR-17:每个节点可配置一个 XYZABC 自由度、父坐标轴方向和正负向。配置以 `linuxcnc.joint-model/1` JSON 写入原 userData,包含层级、零姿态、轴索引、物理零点和 RTCP 标定。管理器实时跟随与正式机床共用驱动逻辑;详见 [07-单自由度JSON与实时驱动](07-单自由度JSON与实时驱动.md)。

View File

@@ -15,3 +15,5 @@
13. `MGR-16`:将根节点部件变换和内部节点 `nodeTransforms[path]` 分开保存;编辑当前节点相对父级的位置和姿态,验证子节点继承、父兄节点不受影响、拖放换父级后保持世界姿态,并验证组合 GLB 与 AC/BC 应用结果。
每轮只推进任务矩阵中依赖已满足的任务。代码完成后必须同步更新 03、04、05;若改变数据契约或坐标定义,先更新 06。
14. `MGR-17`:定义单自由度 JSON/Schema;收敛 UI 输入;增加单文件层级应用和 GLB 恢复;接入实际 WASM 关节位置;验证每轴、反向、物理零点、导出往返和锁定行为。

View File

@@ -82,3 +82,13 @@
- MILL700 选择 `MILL700-A-主轴-JT3`,输入 X=120 mm、RZ=25° 后,节点局部位置和四元数分别变为 `0.120 m` 和 `25°`;8 部件 AC/BC 生产回归、导出和应用继续通过。
- MILL700 补充断言:JT3 局部 Z 减少 44 mm 时 JT2 与兄弟滑轨不动、JT4 同步移动;RZ=25° 时 JT3 原点不动、JT4 绕该原点运动;父链预先旋转 20°,位移仍按父坐标系计算。切换选择和重开对话框保留输入;带编辑姿态的门节点换父级后世界姿态不变且能继续编辑。
- MGR-16 verified;验收证据 E12。
## R11 / 2026-09-21 / 单自由度关节与控制器映射
- 每个节点固定或只绑定一个 XYZABC 轴;父级 x/y/z 方向和 ±1 可配,平移/旋转类型及单位由数控轴确定。旧自由位置/姿态编辑改成单值关节输入。
- 新增 `machine-joints.ts`:版本化节点与控制器映射、严格校验、零姿态驱动;预览与运行共用。
- `makeJointAssembly` 保留已有模型层级,支持 MILL700 单文件配置完整五轴后应用;新配置不再要求八个独立 GLB。
- 实际床身节点、控制底座和场景写入关节 JSON,兼容原 URDF 与机床几何 userData。导出显式 Scene extras;GLB 重导入恢复轴绑定、方向、物理零点和标定。
- App 快照接入对话框实时跟随;运行模型通过实际 WASM 关节名映射驱动,并发布同 tick 的轴输入/模型变换诊断。
- 大型关节模型运行关闭 MSAA 和实时阴影,减轻软件 WebGL 绘制开销。
- 数学/JSON 校验、八部件 AC/BC 回归与完整 MILL700 AC/BC 实时/导出往返验证均通过;每机型 8 个不同 tick,五个轴均变化,浏览器 warning/error=0。MGR-17 verified;证据 E13。

View File

@@ -18,3 +18,5 @@
|MGR-14 层级运动验证|verified|MGR-12,MGR-13|模型删除;树节点轴绑定;XYZ mm、A/B/C deg 输入驱动局部层级;local/world 变换和 MILL700 父子联动验收|
|MGR-15 关节局部坐标系|verified|MGR-12,MGR-14|选中树节点时局部 XYZ 辅助轴挂在节点 `(0,0,0)`,随关节和父链变换,不重建 WebGL|
|MGR-16 部件节点相对父级变换|verified|MGR-05,MGR-14|编辑树中当前节点的“部件平移/部件旋转”后,该节点相对父级的位置和姿态改变;父节点与兄弟节点不被误改;子节点继承;预览、导出和 AC/BC 应用保持一致|
|MGR-17 单自由度与运行轴映射|verified|MGR-16|每节点固定或唯一 XYZABC 自由度;单值编辑;JSON 保存到场景/底座;单 GLB 完整应用;导出往返与 AC/BC 实时轴映射验收|

View File

@@ -103,3 +103,26 @@
- JT3 的父、兄弟、子节点编辑前后位置与四元数记录于 MILL700 报告的 `nodeEditing`;验证重选、重开对话框、编辑后换父级和再次输入。
- 线上 E12:`https://49.232.250.35:58015/` 已发布代码 `91ebd56`,资源 `assets/index-CJLtuazD.js`。以线上 URL 重跑 MILL700(含父/兄弟节点隔离、子节点继承、换父级和重开对话框),全部通过、浏览器错误 0。发布报告:`coverage/glb-machine-manager/parent-transform-deployment.report.json`(`GLB-MGR-E12-CLOUD`)。
## E13 / R11 / 单自由度、JSON 与实时轴映射
- 数学与错误边界:`node scripts/test_machine_joint_model.mjs`;`GLB-MGR-E13-MATH`,报告 `coverage/glb-machine-manager/joint-dof/math.report.json`。验证父级旋转、非单位零姿态旋转、正负号、mm/deg、物理零点、100 次更新无累积、错误 JSON、缺失轴值整帧拒绝。
- 完整浏览器命令:`MACHINE_MANAGER_URL=http://127.0.0.1:5180/ node scripts/test_machine_joint_dof_browser.mjs`;`GLB-MGR-E13`,报告 `coverage/glb-machine-manager/joint-dof/browser.report.json`。
- AC/BC 分别导入 MILL700,五个关节独立绑定;Z 轴改方向并反向,固定节点锁定,无六分量输入和自由操纵器;重复轴拒绝,子节点继承、父兄节点保持不变。
- 导出 JSON 与 GLB 场景 extras、实际床身底座 extras 内容一致;GLB 重新导入管理器恢复方向和物理零点,标准“导入机床模型”也可载入;单 GLB 可应用到控制面板。
- 同时五轴程序:`M428; G21 G90 G94 G17 G40 G49; G1 X20 Y10 Z10 A/B20 C30 F120; G1 X-10 Y-5 Z-5 A/B-10 C-20 F120; M2`。每种机型采样 8 个不同渲染 tick,逐轴校验实际 WASM 关节值减物理零点、方向符号及父级局部运动。
- 示例:`coverage/glb-machine-manager/joint-dof/xyzac.json`、`xyzbc.json`;截图 `xyzac-live.png`、`xyzbc-live.png`;Schema 用 Python `jsonschema` 对两份实例验证。
- 八个独立部件回归:`scripts/test_machine_manager_browser.mjs` 已更新单自由度 UI;生产和源模式均通过,旧 URDF 驱动兼容性检查保留。
- 控件清单 115 项;双画布、XYZAC Three.js 契约、TypeScript 和生产构建通过。
- E13 最终状态:verified。XYZAC/XYZBC 各 8 个不同渲染 tick,五个轴均发生变化;浏览器 warning/error=0。此前 E01–E12 为历史验证记录,本次现行输入契约以 E13 为准。
|E13 文件|SHA-256|
|---|---|
|`joint-dof/browser.report.json`|`7b92b906fcdce8f30a9d22e0a8f9ac116b2fd3ebe3b5eef60aa770d134d7f6b7`|
|`joint-dof/math.report.json`|`ea994774e16ea5b506d028c8f7bcd3ff19fe8d3e2514aaa8447b870738fb07f4`|
|`joint-dof/controls.report.json`|`03a734e9a9b09610818a010dea90eb9ba196b01dfbd3c9e4d21501c8baa0f6c8`|
|`joint-dof/xyzac.json`|`99fa305279f05a331916138274c1bc1586ca4d4bdc93a1e34848fee160fe3fda`|
|`joint-dof/xyzbc.json`|`5e59370657eff67156f4a6338897e35e73c0b3bd3f955345a2698b05b88ea522`|
|`joint-dof/xyzac-live.png`|`6e4574082a11703c2b537e452aad039293100bb22a6420c2b7551d02ffef44fe`|
|`joint-dof/xyzbc-live.png`|`51fcd171ac07ad67ef6c1d733c098f24e1938474e1de2c1322701eb33ed49647`|

View File

@@ -10,7 +10,7 @@
## D03 / 编辑层级自由,应用层级受求解器限制
UI 允许用户选择父级以建立层级和发现错误;应用时只接受底座→X→Y→Z→刀具及底座→A/B→C→工件。当前 WASM 只支持这两类 TRT,不能把任意树伪装成可执行机床。
UI 允许用户选择父级以建立层级和发现错误;应用时只接受底座→X→Y→Z→刀具及底座→A/B→C→工件。当前 WASM 只支持这两类 TRT,不能把任意树伪装成可执行机床。MGR-17 起允许任意视觉层级按单自由度绑定五轴,数控仍使用所选 AC/BC TRT;八个独立文件不再是应用前提。
## D04 / 原 GLB 不原地改写
@@ -55,3 +55,7 @@ GLB 树节点 ID 使用导入时的子节点索引路径,不使用可能重复
## D14 / 部件编辑变换作用于当前树节点的父级局部空间
“部件平移”和“部件旋转”编辑当前选中的树节点。根节点的值保存为部件级 `translationMm`、`rotationDeg`;内部节点的值按稳定源路径保存为 `nodeTransforms[path]`,直接表示该节点相对当前父节点的位置和姿态。节点自身局部原点是旋转中心,子节点自然继承父节点变换,父节点和兄弟节点不因编辑子节点而改变。拖放改变父级后,先保持世界姿态,再重新计算局部值。导出和应用复用同一套局部变换,保证预览、组合 GLB 和运行机床一致。
## D15 / 单自由度约束与 JSON 运动契约(替代 D14 的自由编辑)
每个运动节点只能绑定一个 CNC 轴,每轴只绑定一个节点。固定装配节点无自由度。输入为相对物理零点的单个关节量;保留导入零姿态,禁止通过其他数值或自由操纵器绕过约束。节点身份使用稳定 ID,实际绘制以父级方向和正负号驱动。以 `linuxcnc.joint-model/1` 扩展既有 userData,不更换数控 RTCP 求解器;URDF 坐标框架与视觉装配分离以避免双重运动。临时测试姿态不保存为零姿态。

View File

@@ -0,0 +1,68 @@
# 单自由度 JSON 与实时驱动
配置字段为 `userData.linuxcncJointModel`,版本 `linuxcnc.joint-model/1`。它与原 `linuxcncMachine`(URDF)和 `linuxcncMachineGeometry`(TRT 标定)一起保存在导出 GLB 的场景、运行底座及被标记为“床身底座”的实际模型节点中。GLB 将 userData 序列化为 extras。源 GLB 文件不覆盖。
## 对话框
1. 选中层级节点,设置“唯一自由度”:X/Y/Z 是平移,A/B/C 是旋转;固定零件选择“固定(无自由度)”。每个运动节点只有一个自由度,每个数控轴只能绑定一个节点。
2. 设置父级坐标系中的 X/Y/Z 运动方向和正负向。AC 模型可用 XYZAC,BC 模型可用 XYZBC;另一倾转轴禁用。
3. 当前节点只有一个“位移/转角”可编辑数值,单位 mm/deg。固定节点不能编辑;已导入的局部位置、姿态作为零姿态保留。旧版六分量自由编辑和自由操纵器已被单自由度输入替代(MGR-17)。
4. 层级运动测试与节点输入共用对应轴值,所有输入均为相对物理零点的运动量,不写数控系统。配置 JSON 和 GLB 保存零姿态、自由度和标定,不将临时测试姿态烘焙进去。
5. “跟随数控系统实时关节位置”使用当前机型的有效 WASM 快照,锁定手动关节输入。控制面板正式模型始终由 WASM 实际关节位置驱动。
6. 绑定齐五个轴后可应用机床、导出 GLB;单个已有层级的 GLB 也可应用。可单独导出 JSON。未完成绑定的 JSON 是草稿,控制器读取时必须通过完整性校验。
7. 重新导入本工具导出的 GLB 到管理器,可恢复层级、自由度、正负向、C 原点、倾转轴偏置和物理零点。GLB 机型必须与当前工作区相同。
## 字段契约
正式 JSON Schema:[joint-model.schema.json](joint-model.schema.json)。AC/BC 完整实例由验收程序生成,见 `coverage/glb-machine-manager/joint-dof/xyzac.json` 和 `xyzbc.json`。
| 字段 | 意义 |
|---|---|
| `schema` | 固定版本 `linuxcnc.joint-model/1` |
| `coordinates` | `XYZAC` 或 `XYZBC` |
| `units` | 设计长度 mm、角度 deg;GLB 节点实际长度 m |
| `controller.source` | `linuxcnc-wasm.visual.joints`,取实际运动学关节值 |
| `controller.axisOrder` | 实际快照数组的轴顺序,AC 为 `[X,Y,Z,A,C]`,BC 为 `[X,Y,Z,B,C]` |
| `calibration.cOriginMm` | C 轴原点,沿用 TRT rot-point 参数 |
| `calibration.tiltOffsetMm` | A/B 到 C 偏置,沿用 TRT offset 参数 |
| `calibration.physicalZero` | 每个数控轴对应模型零姿态的实际读数 |
| `axisMap` | 数控轴名到模型节点 ID,避免按名称或树排序推测关节 |
| `nodes[].id / parentId` | 唯一节点 ID 与直接父级;根为 null |
| `nodes[].source` | 源文件名、SHA-256 和导入路径,便于追溯 |
| `nodes[].zero` | 相对父级的零姿态:位置 mm、四元数 `[x,y,z,w]`、比例 |
| `nodes[].joint` | null 表示固定;对象表示唯一自由度 |
| `joint.axis / type / unit` | 数控轴 / prismatic 或 revolute / mm 或 deg |
| `joint.direction / frame` | 父级坐标系中的 x/y/z;frame 固定 parent |
| `joint.sign` | +1 或 −1,控制模型运动与数控轴正向的关系 |
| `joint.dof` | 固定为 1 |
Z 轴关节的配置片段:
```json
{
"id": "part-id:scene/0/2/1",
"parentId": "part-id:scene/0/2",
"name": "主轴 Z 滑台",
"role": "z",
"source": { "file": "MILL700-U_1.glb", "hash": "源文件SHA256", "path": "scene/0/2/1" },
"zero": { "positionMm": [-20.804, -904.049, 368.925], "quaternion": [0,0,0,1], "scale": [1,1,1] },
"joint": { "axis": "Z", "direction": "z", "sign": -1, "dof": 1, "type": "prismatic", "unit": "mm", "frame": "parent" }
}
```
## 驱动规则
控制器先根据 `controller.axisOrder` 把快照数组转换为轴名 → 实际位置,然后通过 `axisMap` 找到运动节点。GLB 节点上的 `userData.linuxcncNodeId` 对应 `nodes[].id`,不依赖可重名的中文模型名称。
设实际位置 q、物理零点 q0、正负方向 s,则位移或转角 d = s × (q − q0)。设 e 为 `joint.direction` 对应的父级单位向量:
- 平移:`p = zero.positionMm / 1000 + e * d / 1000`,四元数仍为零姿态。
- 旋转:`Q = Quaternion(e, d * PI / 180) * zero.quaternion`,位置仍为零姿态,因此绕自身原点旋转。
- 子节点继承父级世界矩阵;父级与兄弟节点不会因本节点运动改变。
- 每次从零姿态求绝对变换,不进行增量累加,连续运行不产生累积漂移。
预览和运行复用 `machine-joints.ts` 的同一驱动函数。JSON 用于视觉关节映射;当前数控求解器仍为原生 AC/BC TRT,不根据任意视觉层级生成新的逆运动学。实际配置需要符合所选机床的机械结构、轴正向和标定;轴行程、速度和回零仍以控制器 INI 为准。
运行场景中的 URDF 控制坐标框架继续承担既有刀尖、刀长和刀路投影。导入模型的视觉装配位于固定底座下,仅由 JSON 关节绑定驱动,避免同一节点同时受到 URDF 和 JSON 两次运动。
读取时还要校验:节点 ID 唯一、父级有效且无环、每个节点最多一个自由度、轴绑定不重复、机型完整、轴索引一致、零姿态与标定为有限数值、四元数归一化。缺少实时轴值时整帧拒绝更新,避免只更新部分轴。

View File

@@ -11,7 +11,7 @@
现有整机 GLB + 内嵌 URDF 导入能力继续保留。新管理器生成与现有 `linuxcnc.machine/1` 相同的严格结构,再通过已有配置、Worker、WASM 和 Three.js 投影链运行。
当前状态:MGR-01 至 MGR-16 全部 verified,MILL700 实测覆盖照明、Z-up、132 节点树、拖放、节点原点、关节局部坐标系、节点相对父级平移旋转、模型删除、轴绑定、XYZ/AC 层级运动和 WebGL 资源降级。最新台账 R10,证据 `GLB-MGR-E01/E02/E05/E07/E08/E09/E10/E12` 位于 `coverage/glb-machine-manager/`。
当前状态:MGR-17 单自由度/JSON/实时映射已 verified;MGR-01 至 MGR-16 已完成历史验收,MILL700 实测覆盖照明、Z-up、132 节点树、拖放、节点原点、关节局部坐标系、节点相对父级平移旋转、模型删除、轴绑定、XYZ/AC 层级运动和 WebGL 资源降级。最新台账 R11,证据 `GLB-MGR-E01/E02/E05/E07/E08/E09/E10/E12/E13` 位于 `coverage/glb-machine-manager/`。
文档:
@@ -23,3 +23,6 @@
- [06-决策记录](06-决策记录.md)
相关旧专项:[GLB / URDF 五轴机床子项目](../glb-machine/README.md)。旧专项已完成整机导入、AC/BC 识别、几何参数同步和实际关节驱动,本专项不重复这些底层能力。
- [07-单自由度JSON与实时驱动](07-单自由度JSON与实时驱动.md)
- [关节 JSON Schema](joint-model.schema.json)

View File

@@ -0,0 +1,475 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "urn:linuxcnc:joint-model:1",
"title": "Web LinuxCNC single-DOF joint model",
"type": "object",
"additionalProperties": false,
"required": [
"schema",
"coordinates",
"units",
"controller",
"calibration",
"axisMap",
"nodes"
],
"properties": {
"schema": {
"const": "linuxcnc.joint-model/1"
},
"coordinates": {
"enum": [
"XYZAC",
"XYZBC"
]
},
"units": {
"const": {
"length": "mm",
"angle": "deg",
"gltfLength": "m"
}
},
"controller": {
"type": "object",
"additionalProperties": false,
"required": [
"source",
"axisOrder"
],
"properties": {
"source": {
"const": "linuxcnc-wasm.visual.joints"
},
"axisOrder": {
"enum": [
[
"X",
"Y",
"Z",
"A",
"C"
],
[
"X",
"Y",
"Z",
"B",
"C"
]
]
}
}
},
"calibration": {
"type": "object",
"additionalProperties": false,
"required": [
"cOriginMm",
"tiltOffsetMm",
"physicalZero"
],
"properties": {
"cOriginMm": {
"$ref": "#/$defs/vector3"
},
"tiltOffsetMm": {
"$ref": "#/$defs/vector3"
},
"physicalZero": {
"type": "object",
"required": [
"x",
"y",
"z",
"a",
"b",
"c"
],
"additionalProperties": false,
"properties": {
"x": {
"type": "number"
},
"y": {
"type": "number"
},
"z": {
"type": "number"
},
"a": {
"type": "number"
},
"b": {
"type": "number"
},
"c": {
"type": "number"
}
}
}
}
},
"axisMap": {
"type": "object",
"additionalProperties": false,
"properties": {
"X": {
"type": "string",
"minLength": 1
},
"Y": {
"type": "string",
"minLength": 1
},
"Z": {
"type": "string",
"minLength": 1
},
"A": {
"type": "string",
"minLength": 1
},
"B": {
"type": "string",
"minLength": 1
},
"C": {
"type": "string",
"minLength": 1
}
}
},
"nodes": {
"type": "array",
"minItems": 1,
"maxItems": 12000,
"items": {
"$ref": "#/$defs/node"
}
}
},
"$defs": {
"vector3": {
"type": "array",
"items": {
"type": "number"
},
"minItems": 3,
"maxItems": 3
},
"node": {
"type": "object",
"additionalProperties": false,
"required": [
"id",
"parentId",
"name",
"role",
"source",
"zero",
"joint"
],
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"parentId": {
"type": [
"string",
"null"
]
},
"name": {
"type": "string"
},
"role": {
"type": "string"
},
"source": {
"type": "object",
"additionalProperties": false,
"required": [
"file",
"hash",
"path"
],
"properties": {
"file": {
"type": "string"
},
"hash": {
"type": "string"
},
"path": {
"type": "string"
}
}
},
"zero": {
"type": "object",
"additionalProperties": false,
"required": [
"positionMm",
"quaternion",
"scale"
],
"properties": {
"positionMm": {
"$ref": "#/$defs/vector3"
},
"quaternion": {
"type": "array",
"items": {
"type": "number",
"minimum": -1,
"maximum": 1
},
"minItems": 4,
"maxItems": 4
},
"scale": {
"type": "array",
"items": {
"type": "number",
"exclusiveMinimum": 0
},
"minItems": 3,
"maxItems": 3
}
}
},
"joint": {
"anyOf": [
{
"type": "null"
},
{
"$ref": "#/$defs/dof"
}
]
}
}
},
"dof": {
"type": "object",
"additionalProperties": false,
"required": [
"axis",
"direction",
"sign",
"dof",
"type",
"unit",
"frame"
],
"properties": {
"axis": {
"enum": [
"X",
"Y",
"Z",
"A",
"B",
"C"
]
},
"direction": {
"enum": [
"x",
"y",
"z"
]
},
"sign": {
"enum": [
-1,
1
]
},
"dof": {
"const": 1
},
"frame": {
"const": "parent"
},
"type": {
"enum": [
"prismatic",
"revolute"
]
},
"unit": {
"enum": [
"mm",
"deg"
]
}
},
"allOf": [
{
"if": {
"properties": {
"axis": {
"enum": [
"X",
"Y",
"Z"
]
}
}
},
"then": {
"properties": {
"type": {
"const": "prismatic"
},
"unit": {
"const": "mm"
}
}
},
"else": {
"properties": {
"type": {
"const": "revolute"
},
"unit": {
"const": "deg"
}
}
}
}
]
}
},
"allOf": [
{
"if": {
"properties": {
"coordinates": {
"const": "XYZAC"
}
}
},
"then": {
"properties": {
"controller": {
"properties": {
"axisOrder": {
"const": [
"X",
"Y",
"Z",
"A",
"C"
]
}
}
},
"axisMap": {
"propertyNames": {
"enum": [
"X",
"Y",
"Z",
"A",
"C"
]
}
},
"nodes": {
"items": {
"properties": {
"joint": {
"anyOf": [
{
"type": "null"
},
{
"properties": {
"axis": {
"enum": [
"X",
"Y",
"Z",
"A",
"C"
]
}
}
}
]
}
}
}
}
}
}
},
{
"if": {
"properties": {
"coordinates": {
"const": "XYZBC"
}
}
},
"then": {
"properties": {
"controller": {
"properties": {
"axisOrder": {
"const": [
"X",
"Y",
"Z",
"B",
"C"
]
}
}
},
"axisMap": {
"propertyNames": {
"enum": [
"X",
"Y",
"Z",
"B",
"C"
]
}
},
"nodes": {
"items": {
"properties": {
"joint": {
"anyOf": [
{
"type": "null"
},
{
"properties": {
"axis": {
"enum": [
"X",
"Y",
"Z",
"B",
"C"
]
}
}
}
]
}
}
}
}
}
}
}
]
}