Files
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

7.3 KiB
Raw Permalink Blame History

接口 3 —— 报告计算规范(指标接口)

用途:定义「关节模组仿真报告」里固定要测、要输出的值,以及每个值怎么从 MuJoCo 数据算出来。 前端(WASM)照着这份规范实现报告模块即可,不需要后端再给脚本

为什么报告逻辑是固定的? 运动关系随上传的构型不同而不同(几级、几个行星轮都不一样),但 「要测什么」是确定的:输入/输出的位置、速度、加速度、力矩,以及由它们导出的功率、效率、减速比、 安全余量。唯一随构型变的是哪个关节是输入、哪个是输出——这由 schema.md 提供。


1. 输入

报告模块需要的输入分三类:

输入 来源 说明
模型 MJCFschema.model 含网格、质量/惯量、齿轮约束、作动器
观测配置 schema input_joint / output_joint / gear_ratio / limits
场景参数 schema 的 simulation 步长、时长、PD 增益、参考轨迹、负载

约定记号(下文统一用):

记号 含义
q_in, qd_in, qacc_in 输入关节位置 / 速度 / 加速度
q_out, qd_out, qacc_out 输出关节位置 / 速度 / 加速度
τ_in, τ_out 输入力矩 / 输出力矩
N 减速比(schema.gear_ratio

2. 仿真流程(固定)

加载 MJCF → mj_resetData
for k in 0..(duration/timestep)-1:
    t      = k · timestep
    q_ref  = amplitude · sin(2π · frequency · t)
    qd_ref = amplitude · 2π·frequency · cos(2π · frequency · t)

    τ_in = kp·(q_ref  q_in) + kd·(qd_ref  qd_in)      # PD 位置控制
    ctrl[input_motor]  = τ_in                           # 输入电机力矩
    ctrl[load_motor]   = load_torque                    # 输出端恒值负载
    mj_step()                                            # 齿轮约束在步内解算
    记录本步数据

齿轮耦合是软约束<equality> + solref),mj_step 内自动解算;输出力矩 τ_out 从约束反力读出(见下)。


3. 指标 → 数据源 → 公式(核心表)

MuJoCo 数据源以 d.* 表示 MjData 的字段;input_dof / output_dof 是输入/输出关节 的自由度下标(m.jnt_dofadr[...])。

3.1 运动学(跟踪精度)

指标 符号 数据源(逐时间步) 单位
输入位置 q_in d.qpos[input_dof] rad
输入速度 qd_in d.qvel[input_dof] rad/s
输入加速度 qacc_in d.qacc[input_dof] rad/s²
输出位置 q_out d.qpos[output_dof] rad
输出速度 qd_out d.qvel[output_dof] rad/s
输出加速度 qacc_out d.qacc[output_dof] rad/s²

汇总(对整段轨迹统计):

指标 公式 说明
输入位置峰值 `max q_in
位置跟踪误差 RMS √ mean((q_in q_ref)²) 越小越准
速度跟踪误差 RMS √ mean((qd_in qd_ref)²) 越小越准
输出位置峰值 `max q_out
传动比实测 带截距最小二乘斜率(q_outq_in 拟合,取稳态后半段) 期望 ≈ 1/N

不要用逐点 q_out/q_in 再取均值:正弦参考下 q_in 每周期过零,软约束相位滞后会让 过零处比值爆表甚至变号,把均值带偏(实测 0.112368 vs 真实 0.111111)。带截距的 最小二乘斜率对相位滞后和负载静偏置(q_out 恒滞后一个常数角)都不敏感,能精确还原 1/N

3.2 动力学(力矩 / 功率)

指标 符号 数据源 / 公式 单位
输入力矩 τ_in d.actuator_force[input_motor] N·m
输出力矩 τ_out d.qfrc_constraint[output_dof] N·m
输出功率 P_out τ_out · qd_out W
理想输出力矩 τ_ideal N · τ_in N·m
力矩损失 Δτ N·τ_in τ_out N·m
效率 η τ_out / (N · τ_in) × 100%(稳态均值) %

稳态均值 = 取时间序列后半段(让瞬态衰减完)的 mean(|·|)

3.3 安全性(安全余量)

指标 公式 单位
位置余量 `(‖limit_pos‖ max q_in
力矩余量 `(‖limit_trq‖ max τ_in
过载判定 力矩余量 < 20% → 警告

其中 limit_pos = schema.limits.position[1]limit_trq = schema.limits.torque[1]

3.4 可选:行星轮观测(仅行星构型)

若模组有行星轮(本案例有 3 个),可额外记录某一行星轮的位置/速度 q_p, qd_pd.qpos[planet_dof])。 这是可选项——报告必填的只有输入/输出端;行星轮数量/命名随构型变,不属于固定指标。


4. 输出格式

4.1 逐时间步数据(CSV

列名与关节名解耦(用固定的 input_* / output_*,不写死太阳轮/行星架), 前端按 schema.input_joint / schema.output_joint 填充即可:

内容
time 时间 [s]
input_q, input_qd, input_qacc 输入位置/速度/加速度(schema.input_joint
q_ref, qd_ref 参考轨迹位置/速度
output_q, output_qd, output_qacc 输出位置/速度/加速度(schema.output_joint
planet_q, planet_qd (可选)行星轮位置/速度,仅行星构型且有记录时才有
tau_in, tau_out, power_out 输入/输出力矩、输出功率

本地 simulate_report.py 按固定顺序写出:time, input_q, input_qd, input_qacc, q_ref, qd_ref, output_q, output_qd, output_qacc, [planet_q, planet_qd,] tau_in, tau_out, power_out

4.2 汇总报告(终端 / JSON

按第 3 节的三类汇总指标输出:运动学(峰值、跟踪误差、传动比实测)、动力学(力矩、 功率、效率)、安全性(两类余量 + 过载判定)。

报告首行需注明仿真模式schema.simulation.modenormal / overload),并显示当前 使用的负载力矩与阻尼。当 mode = overload 时,额外产出一份 过载报告overload_report.txt):

指标 公式 单位
额定力矩限位 limit_trq = schema.limits.torque[1] N·m
施加负载力矩 schema.simulation.load_torque N·m
输入力矩峰值 `max τ_in
力矩余量 `(limit_trq max τ_in
位置跟踪误差 √ mean((q_in q_ref)²) rad
过载判定 余量 ≤ 0 → 已过载;0 < 余量 < 20% → 接近过载;否则未过载

5. 参考实现

本地参考实现见 ../scripts/simulate_report.py,它就是这份规范的可执行版本。 前端实现时应以本规范为准,脚本只作对照。

两个易错点(实现时务必注意):

  1. 输出力矩读约束反力,不读作动器力。 齿轮耦合是 <equality> 约束,τ_outd.qfrc_constraint[output_dof];若读 load_motoractuator_force 只会得到常数负载。
  2. 稳态统计取后半段。 参考轨迹从静止起跳会有初始瞬态尖峰,前半段不参与均值/效率计算。