Files
JointModule/docs/architecture.md
T
chenshijue 4240bb889a 初始提交:关节模组仿真平台
- 三接口契约:自包含 MJCF / 配置 schema / 报告计算规范
- Python 流水线:urdf_to_mjcf → generate_schema → simulate_report(validate_module 一键编排)
- 输入案例 urdf + 生成产物 output(自包含 MJCF/schema/报告/网格副本)
- 详细架构说明 docs/architecture.md
2026-08-28 11:37:47 +08:00

11 KiB
Raw Blame History

关节模组仿真平台 —— 架构与开发说明(详细版)

想快速上手,先看根目录 README.md(一页看懂);本文件是详细版,讲脚本语义、网页接入、用户上传流程与占位参数。

本项目是「浏览器在线 MuJoCo 仿真平台」的关节模组部分:把关节模组(行星轮系)在本地用 MuJoCo 跑通,并留好三个接口给网页团队,最终让「平台内置的关节模组」和「用户上传的关节模组」 都能在浏览器里跑仿真、出报告。

团队三模块分工:关节模组(本目录)/ 机械臂 / 四足机器狗。团队用 MuJoCo WASM @mujoco/mujoco)做网页展示,引擎与本地 Python 是同一个 C++ 核心,MJCF.xml)是统一模型格式


1. 文件清单(哪个文件是什么)

文件 是什么 给谁用
../urdf/planetary_joint_split_motor_demo.urdf 原始 URDF(本案例的输入,只有运动学+视觉,缺质量/惯量/电机) 转换工具输入
../urdf/meshes/*.stl 原始网格(STL,单位 mm 转换工具读体积分
../output/planetary_joint_split_motor_demo.xml MJCF 模型urdf_to_mjcf.py 生成,自包含,可直接仿真) 网页端加载 / 仿真
../output/meshes/*.stl 自包含网格副本(MJCF 的 meshdir 指向这里) 随 MJCF 一起交付
../output/*.json / report.txt / timeseries.csv / report_curves.png 生成的 schema / 报告 / 观测 / 曲线 交付与对照
../scripts/urdf_to_mjcf.py URDF→MJCF 转换工具(关节模组专用) 后端转换
../scripts/generate_schema.py URDF→schema 生成器(读输入/输出关节、减速比、限位) 后端生成
../scripts/simulate_report.py 通用仿真 + 报告脚本(读 schema 跑仿真、采数据、出报告) 本地验证 / 报告参考实现
../scripts/validate_module.py 一键验证入口(编排上面三步:URDF→MJCF→schema→报告) 本地验证 / 后端流水线
schema.md 接口 2:配置 schema(观测接口:输入/输出/减速比/限位) 网页团队
report_spec.md 接口 3:报告计算规范(指标→公式) 网页团队

一句话速记: URDF 是「输入」,MJCF 是「引擎吃的模型」,schema/report_spec 是「网页团队要看的接口文档」。 流水线是 urdf_to_mjcf.py → generate_schema.py → simulate_report.py 三步,validate_module.py 把三步打包成一条命令。


2. 三个接口(给网页团队)

接口 文件 是什么 谁负责产出
① 自包含 MJCF *.xml + meshes/ 浏览器加载的模型,含网格/质量/惯量/齿轮约束/电机 转换工具
② 配置 schema schema.md 输入/输出关节名、减速比、限位、仿真参数 后端从 URDF 生成
③ 报告规范 report_spec.md 报告要测哪些值、怎么算 固定逻辑,前端照实现

关系:MJCF 管「怎么动」,schema 管「观测什么」,报告规范管「算出什么」。 schema 不描述内部构型(几级、几个行星轮都在 MJCF 里),只统一观测接口。


3. 本案例怎么跑起来

一条命令跑完整条流水线(推荐):

cd scripts
python3 validate_module.py \
    --urdf ../urdf/planetary_joint_split_motor_demo.urdf \
    --input sun_input_joint --output carrier_output_joint \
    --work-dir ../output --plot

产出(都在 ../output/):planetary_joint_split_motor_demo.xmlMJCF+ planetary_joint_split_motor_demo.json schema+ timeseries.csv(逐时间步)+ report_curves.png(曲线)。

只想跑最后一步仿真/报告(已有 MJCF + schema 时):

cd scripts
python3 simulate_report.py --schema ../output/planetary_joint_split_motor_demo.json --plot   # 读 schema 跑
python3 simulate_report.py --schema ../output/planetary_joint_split_motor_demo.json --headless  # 无显示器,只计算

依赖:mujoconumpy(绘图需 matplotlib;转换需 trimesh)。


4. 三个脚本各自怎么用(分步跑)

流水线三步各自都能单独跑,validate_module.py 只是把它们按顺序调用。三步都显式指定 输入/输出关节--input / --output),因为自动识别在真实 URDF 上不可靠(多级级联有 多个正 multiplier 的 mimic、fixed 关节也没有 mimic,程序分不清哪级是末端输出)。

cd scripts

# ① URDF → MJCF(自包含:<compiler meshdir="meshes"/> + 拷贝网格)
python3 urdf_to_mjcf.py \
    --urdf ../urdf/planetary_joint_split_motor_demo.urdf \
    --input sun_input_joint --output carrier_output_joint \
    --out ../output/planetary_joint_split_motor_demo.xml --meshdir ../output/meshes

# ② URDF → schema(读输入/输出、减速比、限位、默认仿真参数)
python3 generate_schema.py \
    --urdf ../urdf/planetary_joint_split_motor_demo.urdf \
    --input sun_input_joint --output carrier_output_joint \
    --model planetary_joint_split_motor_demo.xml \
    --out ../output/planetary_joint_split_motor_demo.json

# ③ schema → 仿真 + 报告
python3 simulate_report.py --schema ../output/planetary_joint_split_motor_demo.json --plot

依赖:numpytrimeshpip install trimesh,仅转换步骤需要)。

工具做的事(详见脚本头注释):

  1. 照搬不改:关节层级、<joint><origin>→子 <body pos><axis><joint axis><limit><joint range><mimic><equality> polycoef、<visual><origin><geom pos>
  2. 补质量/惯量:从每个 link 的 STL 做体积分,按脚本顶部的密度常数算出质量/重心/惯性张量, 多网格用平行轴定理合成。
  3. 补作动器input_motor(输入端)+ load_motor(输出端负载)。
  4. 渲染网格覆盖:个别 STL 面数超 MuJoCo 上限,渲染换降采样版(质量仍按原始网格算)。

要改的常数都在脚本顶部

常数 位置 说明
材料密度 DENSITIES / DEFAULT_DENSITY 顶部 kg/m³,换材料时改这里
TORQUE_LIMIT 顶部 力矩限位(占位,应填真实电机额定值)
JOINT_DAMPING / JOINT_ARMATURE 顶部 数值稳定参数

⚠️ 本工具是关节模组专用。它假设「一个电机输入 + 一个模组输出 + 减速比关系」, 用「无 <mimic> 的关节 = 输入、正 multiplier 跟随者 = 输出」自动识别。所有类别 URDF 的 通用转换器由团队后续开发,本工具只覆盖关节模组。


5. 把「本案例」接入网页需要什么

  1. 模型文件planetary_joint_split_motor_demo.xml + meshes/(自包含,一起上传)。
  2. 配置:按 schema.md 第 4 节填好这份 JSON,随模型一起给前端。
  3. 报告逻辑:前端按 report_spec.md 实现(或后端把本案例的 simulate_report.py 逻辑翻译到 JS)。

前端只需:加载 MJCF → 读 schema 拿 input_joint/output_joint/gear_ratio/limits → 跑仿真 → 按报告规范输出。不需要理解行星轮系的内部构型。


6. 把「用户上传 URDF」接入网页需要什么

用户上传的是 zip 包(URDF + mesh 文件),不是单个 .urdf(只有 urdf 没有 STL 加载不出模型)。

后端流水线(就是 validate_module.py 干的同一件事):

  1. 接收 + 校验:解压 zip,检查 URDF 可解析、mesh 引用齐全、路径无穿越(../ 之类)。
  2. 转换:跑 urdf_to_mjcf.py → 产出自包含 MJCF + 网格。
  3. 生成 schema:跑 generate_schema.py(输入/输出关节显式指定,减速比从 <mimic> 取或手动给)→ 产出 schema JSON。
  4. 返回给前端{ mjcf + meshes, schema }

前端拿到这两样后,与「本案例」走同一条路(见第 5 节)。用户始终只传 URDF+mesh 不传 schema——schema 是后端算出来的。

6.1 内置模组 vs 用户上传,靠谁区分?

是的,全看前端在哪一步分叉。 分叉点只有一个:模型从哪来。分叉之后,两条路立刻并回 同一条流水线(跑仿真 → 出报告 → 出曲线),后面不再有任何区别:

                 ┌─ 内置模组:直接用预生成的 MJCF + schema(跳过①②)
 前端选择 ────────┤
                 └─ 用户上传:上传 URDF+mesh → 后端 ①转MJCF ②生成schema
                                        (此分支需要额外给「输入/输出关节」)
                                        ↓
                        两条路都拿到 { MJCF + schema }
                                        ↓
                         ③ 跑仿真 → 出报告 → 出曲线(完全相同)

所以前端要做的「分割」只有两件事:

  1. 选哪个入口:内置(有现成的 MJCF+schema)还是上传(现转)。
  2. 给输入/输出关节:内置模组的输入/输出已经写死在它自带的 schema 里;上传模组则要 前端在用户上传时让用户选一下(或后端自动识别 + 用户确认),因为只有用户/构型才知道 哪两个关节是输入输出端——这一步程序猜不靠谱(见第 4 节)。

除这两点外,报告计算、曲线绘制、安全余量判定零差别,前端不需要写两套报告逻辑。


7. 各角色去哪个文件看什么

你想知道… 去看…
哪个是 URDF / MJCF / 仿真脚本 本文件第 1 节
转换工具怎么跑、改什么常数 ../scripts/urdf_to_mjcf.py 头部注释 + 本文件第 4 节
schema 怎么从 URDF 生成 ../scripts/generate_schema.py 头部注释
一键验证 / 用户上传流水线怎么编排 ../scripts/validate_module.py 头部注释
schema 的字段和示例 schema.md
报告测什么、怎么算 report_spec.md
URDF→MJCF 的关键语义(易错点) ../scripts/urdf_to_mjcf.py 头部注释(<joint><origin><body pos> 等)
通用仿真/报告参考实现 ../scripts/simulate_report.py

8. 仍需填的占位参数

  1. 力矩限位(默认 ±10 N·m,对应 URDF effort="1" 占位):填真实电机额定值。有两处:
    • MJCF 作动器 ctrlrange../scripts/urdf_to_mjcf.py 顶部的 TORQUE_LIMIT
    • 报告安全余量用的限位:../scripts/generate_schema.py--torque-limit(写进 schema.limits.torque)。
  2. 关节阻尼JOINT_DAMPING = 0.01):报告中 ~98% 的「效率损失」来自这个阻尼; 真实摩擦/效率需用实际参数建模。
  3. 材料密度../scripts/urdf_to_mjcf.py 顶部 DENSITIES / DEFAULT_DENSITY):目前无真值,先不改。