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

162 lines
7.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 接口 3 —— 报告计算规范(指标接口)
> 用途:定义「关节模组仿真报告」里**固定要测、要输出的值**,以及每个值**怎么从 MuJoCo 数据算出来**。
> 前端(WASM)照着这份规范实现报告模块即可,**不需要后端再给脚本**。
**为什么报告逻辑是固定的?** 运动关系随上传的构型不同而不同(几级、几个行星轮都不一样),但
「要测什么」是确定的:输入/输出的位置、速度、加速度、力矩,以及由它们导出的功率、效率、减速比、
安全余量。唯一随构型变的是**哪个关节是输入、哪个是输出**——这由 [schema.md](schema.md) 提供。
---
## 1. 输入
报告模块需要的输入分三类:
| 输入 | 来源 | 说明 |
|---|---|---|
| 模型 | MJCF`schema.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|` | 参考幅值 `amplitude` |
| 位置跟踪误差 RMS | `√ mean((q_in q_ref)²)` | 越小越准 |
| 速度跟踪误差 RMS | `√ mean((qd_in qd_ref)²)` | 越小越准 |
| 输出位置峰值 | `max |q_out|` | 期望 ≈ `amplitude / N` |
| **传动比实测** | 带截距最小二乘斜率(`q_out``q_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_pos‖ × 100%` | % |
| 力矩余量 | `(‖limit_trq‖ max|τ_in|) / ‖limit_trq‖ × 100%` | % |
| 过载判定 | 力矩余量 < 20% → 警告 | — |
其中 `limit_pos = schema.limits.position[1]``limit_trq = schema.limits.torque[1]`
### 3.4 可选:行星轮观测(仅行星构型)
若模组有行星轮(本案例有 3 个),可额外记录某一行星轮的位置/速度 `q_p, qd_p``d.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.mode``normal` / `overload`),并显示当前
使用的负载力矩与阻尼。当 `mode = overload` 时,额外产出一份 **过载报告**`overload_report.txt`):
| 指标 | 公式 | 单位 |
|---|---|---|
| 额定力矩限位 | `limit_trq = schema.limits.torque[1]` | N·m |
| 施加负载力矩 | `schema.simulation.load_torque` | N·m |
| 输入力矩峰值 | `max |τ_in|` | N·m |
| 力矩余量 | `(limit_trq max|τ_in|) / limit_trq × 100%` | % |
| 位置跟踪误差 | `√ mean((q_in q_ref)²)` | rad |
| 过载判定 | 余量 ≤ 0 → 已过载;0 < 余量 < 20% → 接近过载;否则未过载 | — |
---
## 5. 参考实现
本地参考实现见 [../scripts/simulate_report.py](../scripts/simulate_report.py),它就是这份规范的可执行版本。
前端实现时应**以本规范为准**,脚本只作对照。
**两个易错点(实现时务必注意):**
1. **输出力矩读约束反力,不读作动器力。** 齿轮耦合是 `<equality>` 约束,`τ_out`
`d.qfrc_constraint[output_dof]`;若读 `load_motor``actuator_force` 只会得到常数负载。
2. **稳态统计取后半段。** 参考轨迹从静止起跳会有初始瞬态尖峰,前半段不参与均值/效率计算。