Skip to content

教程github.com7 天前

强化学习运控策略 Sim-to-Real 全链路实操:从 Isaac Lab 导出 ONNX 到真机 500Hz 闭环 ​

在 Isaac Lab 或 Isaac Gym 中训练出一个能走能跑的 Actor-Critic 策略只需几十分钟,但把 .pt 权重搬上真机却常常遇到**「一上电就劈叉、起立后疯狂抽搐、或者一迈步就后仰摔倒」**。本文总结从仿真到真机(Sim-to-Real)必须严丝合缝对齐的 6 个工程契约。


1. Sim-to-Real 双频控制架构 ​

text
[50Hz 策略推理线程 (ONNX Runtime / LibTorch, 周期 20ms)]
  输入:观测向量 obs_t (角速度、重力投影、速度指令、关节位置偏差、关节速度、上一帧动作)
  输出:归一化动作向量 action_t ∈ [-clip_actions, +clip_actions]
  目标角度计算:q_target = q_default + action_scale * action_t
         │ (无锁环形缓冲区 / 原子指针交换)
         ▼
[500Hz–1000Hz 实时关节伺服线程 (DDS / EtherCAT / CAN, 周期 1–2ms)]
  底层电机驱动器执行:tau = kp * (q_target - q) + kd * (0 - dq) + tau_ff

2. 上真机前必须逐项核对的 6 张对齐表 ​

2.1 四元数顺序与重力投影向量(projected_gravity) ​

  • 仿真器差异:Isaac Gym 使用 (x, y, z, w),而 Isaac Lab、MuJoCo 以及宇树/智身底层 IMU 消息通常使用 (w, x, y, z)。如果四元数实部 w 位置搞反,算出的重力投影向量会旋转 180°,机器人在真机上一激活就会猛烈翻滚!
  • 标准重力投影计算公式(输入单位四元数 q = [w, x, y, z]):
    python
    import numpy as np
    
    def quat_rotate_inverse(q_wxyz: np.ndarray, v: np.ndarray) -> np.ndarray:
        q_w = q_wxyz[0]
        q_vec = q_wxyz[1:4]
        a = v * (2.0 * q_w**2 - 1.0)
        b = np.cross(q_vec, v) * q_w * 2.0
        c = q_vec * np.dot(q_vec, v) * 2.0
        return a - b + c
    
    # 静止水平放置时,projected_gravity 必须近似为 [0.0, 0.0, -1.0]
    projected_gravity = quat_rotate_inverse(imu_quat_wxyz, np.array([0.0, 0.0, -1.0]))

2.2 关节索引双向映射表(sim2real_idx 与 real2sim_idx) ​

仿真器的关节顺序由 URDF/USD 解析树决定,而真机 SDK 的电机数组常按控制器硬件通道排列。必须显式定义两个映射数组:

python
## 从真机传感器读入后,重排为仿真顺序再构建 obs
q_sim = q_real[real2sim_idx]
dq_sim = dq_real[real2sim_idx]

## 策略算出仿真顺序的 target_q_sim 后,重排回真机顺序再下发
target_q_real = target_q_sim[sim2real_idx]

2.3 观测缩放因子(obs_scales)与历史帧栈(History Buffer) ​

训练配置中的每一项缩放系数必须在真机 C++/Python 代码里 1:1 复刻:

  • ang_vel * 0.25
  • dof_pos_err = (q_sim - default_dof_pos) * 1.0
  • dof_vel * 0.05
  • 若策略使用了 frame_stack = 5 或特权估计器(Estimator),切入 RL 模式前必须先用当前静止状态填充全部历史帧缓冲区,禁止用全 0 历史帧直接推理第一拍。

3. Sim-to-Sim 交叉验证(MuJoCo 守门员机制) ​

严禁把 Isaac Lab 导出的 ONNX 直接拿到真机上试错! 标准工程流程是先过 Sim-to-Sim(Isaac Lab → MuJoCo) 关口:

  1. 将导出的 .onnx 策略加载到独立的 MuJoCo Python/C++ 脚本中;
  2. 如果策略在 MuJoCo 中能稳定站立并响应 vx, vy, wz 指令,说明你的 ONNX 导出图、观测拼装顺序、四元数约定、默认关节角 default_dof_pos 与 kp/kd 已经 100% 正确;
  3. 随后只需替换底层的 read_sensors() 与 write_actuators() 为真机 SDK 接口,并在真机推理环中加入 倾角超限保护(|roll| > 45° 或 |pitch| > 45° 立即切回全阻尼模式 Damp()) 即可安全落地。

来源

本页事实对应的公开页面,以原文为准。

  1. GitHub isaac-sim/IsaacLab访问 2026-10-21
  2. GitHub unitreerobotics/unitree_rl_gym访问 2026-10-21