4240bb889a
- 三接口契约:自包含 MJCF / 配置 schema / 报告计算规范 - Python 流水线:urdf_to_mjcf → generate_schema → simulate_report(validate_module 一键编排) - 输入案例 urdf + 生成产物 output(自包含 MJCF/schema/报告/网格副本) - 详细架构说明 docs/architecture.md
7.7 KiB
7.7 KiB
接口 2 —— 关节模组配置 Schema
用途:给「浏览器端 WASM 仿真」一个统一观测接口。无论用户上传的是什么构型的关节模组 (一级/多级、三个/四个行星轮、太阳轮+行星架、谐波、摆线…),后端把它归一化成这份 JSON, 前端只读这份 JSON 就能:找到输入端/输出端、知道减速比、拿到限位、按默认参数跑仿真。
1. Schema 是什么 / 不是什么
| 说明 | |
|---|---|
| ✅ 是什么 | 关节模组的对外观测契约:输入关节、输出关节、减速比、限位、默认仿真参数 |
| ❌ 不是什么 | 不描述内部构型(几级传动、几个行星轮、齿数、几何)。这些全部已经编码在 MJCF 里,前端不需要知道 |
| ❌ 不是用户上传的 | 这份 JSON 是后端从 URDF 生成的,不是用户填写的。用户上传的始终是「URDF + mesh」的 zip |
为什么必须要有 schema?
- 报告里要测的输入/输出力矩,是「哪个关节」取决于构型。schema 告诉前端哪两个关节是输入/输出端。
- 减速比的标称值(
gear_ratio)可能来自 URDF 的<mimic>,也可能是标定/手动填的,需要显式声明来源。 - 前端要做统一的限位检查、统一的安全余量,就需要统一格式的限位。
一句话:MJCF 管「怎么动」,schema 管「观测什么」,报告规范管「算出什么」。
2. 字段定义(格式契约,定义一次)
| 字段 | 类型 | 单位 | 必填 | 含义 | 取值来源 |
|---|---|---|---|---|---|
module_id |
string | — | ✅ | 模组唯一标识 | 后端生成(如模型名) |
name |
string | — | 显示名 | 后端生成 | |
model |
string | — | ✅ | 要加载的 MJCF 文件名(自包含,网格与它同目录) | 转换工具输出 |
input_joint |
string | — | ✅ | 输入关节名(电机端) | URDF 里唯一没有 <mimic> 的关节 |
output_joint |
string | — | ✅ | 输出关节名(模组输出端) | URDF 里以正 multiplier 跟随输入的关节 |
gear_ratio |
number | — | ✅ | 标称减速比 = 输入 / 输出 = 1/multiplier |
默认取 <mimic multiplier> 倒数;可标定覆盖 |
gear_ratio_source |
enum | — | ✅ | mimic / calibrated / manual |
减速比来源 |
limits.position |
[number, number] | rad | ✅ | 输入关节位置限位 [lower, upper] |
URDF <limit lower/upper> |
limits.torque |
[number, number] | N·m | ✅ | 输入力矩限位 [-T, +T] |
MJCF <actuator ctrlrange>(占位,待填真实值) |
limits.velocity |
[number, number] | rad/s | 速度限位 | URDF <limit velocity>(若有) |
|
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)
{
"$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. 本案例的实例
{
"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 个关节中,唯一没有 <mimic> 的是 sun_input_joint(独立驱动源) |
output_joint = carrier_output_joint |
<mimic joint="sun_input_joint" multiplier="0.16667">,正 multiplier → 减速输出端 |
gear_ratio = 6.0 |
1 / 0.166666666666667 = 6(1 级行星轮系,齿圈固定,太阳轮:行星架 = 6:1) |
limits.position = ±37.6991 |
URDF <limit lower="-37.6991118431" upper="37.6991118431">(±6 圈 = ±12π) |
limits.torque = ±10 |
MJCF <actuator ctrlrange="-10 10">(占位,待填真实电机额定值) |
limits.velocity = ±6.2832 |
URDF <limit velocity="6.28318530718">(1 圈/秒) |
simulation.* |
报告规范的默认场景参数,见 report_spec.md |
5. 减速比来源的优先级(多来源怎么取)
后端生成 schema 时,gear_ratio 按下面顺序确定,并在 gear_ratio_source 里记录用的是哪个:
mimic—— URDF<mimic multiplier>的倒数(最优先,本案例)。calibrated—— 跑一次仿真,mean(q_out / q_in)标定得到(无<mimic>或传动力不可靠时)。manual—— 前端手动填(都没有时兜底)。
减速比只进 schema 与报告,不进 MJCF——MJCF 里的传动关系由
<equality>精确表达, schema 里的gear_ratio只是「标称参考值」,用于报告的效率/理想力矩计算。