# 接口 2 —— 关节模组配置 Schema > 用途:给「浏览器端 WASM 仿真」一个**统一观测接口**。无论用户上传的是什么构型的关节模组 > (一级/多级、三个/四个行星轮、太阳轮+行星架、谐波、摆线…),后端把它归一化成这份 JSON, > 前端只读这份 JSON 就能:找到输入端/输出端、知道减速比、拿到限位、按默认参数跑仿真。 --- ## 1. Schema 是什么 / 不是什么 | | 说明 | |---|---| | ✅ 是什么 | 关节模组的**对外观测契约**:输入关节、输出关节、减速比、限位、默认仿真参数 | | ❌ 不是什么 | **不描述内部构型**(几级传动、几个行星轮、齿数、几何)。这些全部已经编码在 MJCF 里,前端不需要知道 | | ❌ 不是用户上传的 | 这份 JSON 是**后端从 URDF 生成**的,不是用户填写的。用户上传的始终是「URDF + mesh」的 zip | **为什么必须要有 schema?** 1. 报告里要测的输入/输出力矩,是「哪个关节」取决于构型。schema 告诉前端哪两个关节是输入/输出端。 2. 减速比的标称值(`gear_ratio`)可能来自 URDF 的 ``,也可能是标定/手动填的,需要显式声明来源。 3. 前端要做统一的限位检查、统一的安全余量,就需要统一格式的限位。 > 一句话:**MJCF 管「怎么动」,schema 管「观测什么」,报告规范管「算出什么」。** --- ## 2. 字段定义(格式契约,定义一次) | 字段 | 类型 | 单位 | 必填 | 含义 | 取值来源 | |---|---|---|---|---|---| | `module_id` | string | — | ✅ | 模组唯一标识 | 后端生成(如模型名) | | `name` | string | — | | 显示名 | 后端生成 | | `model` | string | — | ✅ | 要加载的 MJCF 文件名(自包含,网格与它同目录) | 转换工具输出 | | `input_joint` | string | — | ✅ | **输入关节名**(电机端) | URDF 里唯一没有 `` 的关节 | | `output_joint` | string | — | ✅ | **输出关节名**(模组输出端) | URDF 里以正 multiplier 跟随输入的关节 | | `gear_ratio` | number | — | ✅ | 标称减速比 = 输入 / 输出 = `1/multiplier` | 默认取 `` 倒数;可标定覆盖 | | `gear_ratio_source` | enum | — | ✅ | `mimic` / `calibrated` / `manual` | 减速比来源 | | `limits.position` | [number, number] | rad | ✅ | 输入关节位置限位 `[lower, upper]` | URDF `` | | `limits.torque` | [number, number] | N·m | ✅ | 输入力矩限位 `[-T, +T]` | MJCF ``(占位,待填真实值) | | `limits.velocity` | [number, number] | rad/s | | 速度限位 | URDF ``(若有) | | `simulation.timestep` | number | s | ✅ | 仿真步长 | 默认 `0.001` | | `simulation.duration` | number | s | ✅ | 仿真时长 | 默认 `4.0` | | `simulation.kp` / `kd` | number | — | ✅ | 输入 PD 位置控制增益 | 默认 `20.0` / `0.3` | | `simulation.amplitude` | number | rad | ✅ | 参考轨迹幅值 | 默认 `2π`(1 圈) | | `simulation.frequency` | number | Hz | ✅ | 参考轨迹频率 | 默认 `0.25` | | `simulation.load_torque` | number | N·m | ✅ | 输出端恒值负载(负 = 阻力) | 默认 `-3.0` | | `simulation.damping` | number | N·m·s/rad | ✅ | 关节粘性阻尼 | 默认 `0.01` | | `simulation.mode` | enum | — | ✅ | 仿真模式:`normal` / `overload` | 默认 `normal` | > 所有带默认值的字段,前端都可以覆盖(用户调参)。`input_joint` / `output_joint` / > `limits` / `gear_ratio` 是后端算好的「事实」,前端只读。 --- ## 3. 形式化 JSON Schema(供前端校验用,draft 2020-12) ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "joint-module.schema.json", "title": "关节模组配置", "type": "object", "required": ["module_id", "model", "input_joint", "output_joint", "gear_ratio", "gear_ratio_source", "limits", "simulation"], "additionalProperties": false, "properties": { "module_id": { "type": "string" }, "name": { "type": "string" }, "model": { "type": "string" }, "input_joint": { "type": "string" }, "output_joint": { "type": "string" }, "gear_ratio": { "type": "number", "exclusiveMinimum": 0 }, "gear_ratio_source": { "type": "string", "enum": ["mimic", "calibrated", "manual"] }, "limits": { "type": "object", "required": ["position", "torque"], "properties": { "position": { "type": "array", "items": { "type": "number" }, "minItems": 2, "maxItems": 2 }, "torque": { "type": "array", "items": { "type": "number" }, "minItems": 2, "maxItems": 2 }, "velocity": { "type": "array", "items": { "type": "number" }, "minItems": 2, "maxItems": 2 } } }, "simulation": { "type": "object", "properties": { "timestep": { "type": "number", "default": 0.001 }, "duration": { "type": "number", "default": 4.0 }, "kp": { "type": "number", "default": 20.0 }, "kd": { "type": "number", "default": 0.3 }, "amplitude": { "type": "number", "default": 6.283185307179586 }, "frequency": { "type": "number", "default": 0.25 }, "load_torque": { "type": "number", "default": -3.0 }, "damping": { "type": "number", "default": 0.01 }, "mode": { "type": "string", "enum": ["normal", "overload"], "default": "normal" } } } } } ``` --- ## 4. 本案例的实例 ```json { "module_id": "planetary_joint_split_motor_demo", "name": "行星轮系分体电机关节模组", "model": "planetary_joint_split_motor_demo.xml", "input_joint": "sun_input_joint", "output_joint": "carrier_output_joint", "gear_ratio": 6.0, "gear_ratio_source": "mimic", "limits": { "position": [-37.6991118431, 37.6991118431], "torque": [-10.0, 10.0], "velocity": [-6.28318530718, 6.28318530718] }, "simulation": { "timestep": 0.001, "duration": 4.0, "kp": 20.0, "kd": 0.3, "amplitude": 6.283185307179586, "frequency": 0.25, "load_torque": -3.0, "damping": 0.01, "mode": "normal" } } ``` 对照说明: | 实例值 | 怎么来的 | |---|---| | `input_joint = sun_input_joint` | URDF 里 5 个关节中,唯一没有 `` 的是 `sun_input_joint`(独立驱动源) | | `output_joint = carrier_output_joint` | ``,正 multiplier → 减速输出端 | | `gear_ratio = 6.0` | `1 / 0.166666666666667 = 6`(1 级行星轮系,齿圈固定,太阳轮:行星架 = 6:1) | | `limits.position = ±37.6991` | URDF ``(±6 圈 = ±12π) | | `limits.torque = ±10` | MJCF ``(**占位**,待填真实电机额定值) | | `limits.velocity = ±6.2832` | URDF ``(1 圈/秒) | | `simulation.*` | 报告规范的默认场景参数,见 [report_spec.md](report_spec.md) | --- ## 5. 减速比来源的优先级(多来源怎么取) 后端生成 schema 时,`gear_ratio` 按下面顺序确定,并在 `gear_ratio_source` 里记录用的是哪个: 1. **`mimic`** —— URDF `` 的倒数(最优先,本案例)。 2. **`calibrated`** —— 跑一次仿真,`mean(q_out / q_in)` 标定得到(无 `` 或传动力不可靠时)。 3. **`manual`** —— 前端手动填(都没有时兜底)。 > 减速比只进 schema 与报告,**不进 MJCF**——MJCF 里的传动关系由 `` 精确表达, > schema 里的 `gear_ratio` 只是「标称参考值」,用于报告的效率/理想力矩计算。