Unitree G1 强化学习实战:从 IsaacLab 训练到 MuJoCo Sim2Sim 验证
人形机器人在一个模拟器里能运动,并不代表换一个物理引擎之后还能正常运动。
真正做过 Sim2Sim 的同学通常会遇到这种情况:策略在训练环境里表现正常,一迁移就开始打滑、漂移、抖动,甚至刚起步就摔倒。问题往往不只是“模型没训练好”,还可能来自关节顺序、观测定义、动作缩放、控制周期和接触参数没有对齐。
这篇文章以 Unitree G1 为例,讲清楚一个完整链路:
Isaac Sim / IsaacLab 搭建环境
↓
RSL-RL + PPO 训练行走策略
↓
复杂地形与扰动下鲁棒微调
↓
导出 Actor 和控制元数据
↓
MuJoCo 中进行 Sim2Sim 验证
文章最后给出了精简开源项目,代码、MuJoCo 机器人资产、训练入口和演示权重都包含在仓库中;Isaac G1 USD 通过一条命令从 NVIDIA 官方资产地址准备。

一、这个项目解决什么问题?
项目目标不是只录一段“机器人走起来了”的视频,而是建立一套可以复现、可以评估、也能暴露失败工况的 G1 行走实验链路。
具体包含以下内容:
- 在 IsaacLab 中定义 G1 强化学习环境;
- 使用 PPO 从零训练 baseline 行走策略;
- 在粗糙地形、随机摩擦和外力扰动下进行鲁棒微调;
- 在 Isaac Sim 中播放并批量评估;
- 将策略导出为 NPZ / TorchScript;
- 在 MuJoCo 中对齐 123 维观测和 37 维动作;
- 测试平地、粗糙地形、斜坡和台阶;
- 输出 CSV 和 JSON 评估结果;本文截图与视频由原始私有项目的媒体流程制作,不包含在开源仓库中。
这里要特别说明:本文展示的是仿真和 Sim2Sim 验证,不是实机部署结果。
二、技术栈与项目结构
本项目已验证的主要环境如下:
| 组件 | 版本或用途 |
|---|---|
| Isaac Sim | 5.1.0 standalone |
| IsaacLab | 2.3.2 |
| Python | Isaac Sim 内置 Python 3.11 |
| PyTorch | 2.7.0 + CUDA 12.8 |
| 强化学习 | PPO / rsl-rl-lib 3.0.1 |
| Sim2Sim | MuJoCo 3.10 |
| 机器人 | Unitree G1,37-DoF |
精简后的项目结构是:
g1-walk-isaaclab-mujoco/
├─ isaac_sim/
│ ├─ assets/ # 一键准备 Isaac G1 USD
│ ├─ g1_walk_sim51/ # 场景、观测、动作、奖励和 PPO 配置
│ ├─ train.py # baseline 训练
│ ├─ train_robust.py # 鲁棒微调
│ ├─ play.py # 可视化播放
│ ├─ eval.py # 指标评估
│ └─ checkpoints/ # baseline 和 robust 演示权重
├─ mujoco/
│ ├─ assets/ # G1 MJCF 与 mesh
│ ├─ mujoco_eval/ # viewer、地形与批量评估
│ └─ policies/ # 导出的 Actor
├─ environment/ # 依赖与版本记录
├─ run.ps1 # Windows 统一入口
└─ run.sh # Linux 统一入口
三、Isaac Sim、IsaacLab 和 RSL-RL 分别负责什么?
这三个名字很容易混在一起,可以把它们理解成三层:
- Isaac Sim 负责机器人、场景和物理仿真;
- IsaacLab 负责把场景组织成强化学习环境,包括观测、动作、奖励、终止条件和并行环境;
- RSL-RL 负责 PPO 训练和策略网络更新。
也就是说,Isaac Sim 不是 PPO 算法,RSL-RL 也不负责渲染机器人。三者配合起来,才构成完整训练链路。

图 2:baseline 策略在 Isaac Sim 平地环境中的评估画面。
四、强化学习环境里最关键的三件事
1. 观测:机器人“看见”什么
本项目的策略输入共 123 维:
| 观测项 | 维度 |
|---|---|
| 基座线速度 | 3 |
| 基座角速度 | 3 |
| 投影重力 | 3 |
| 速度命令 | 3 |
| 相对关节位置 | 37 |
| 关节速度 | 37 |
| 上一次动作 | 37 |
| 合计 | 123 |
其中“投影重力”可以帮助策略判断身体当前是直立、前倾还是侧倾;“上一次动作”可以让策略感知动作变化,减少突然的大幅控制跳变。
2. 动作:策略能控制什么
策略输出 37 维动作,与 37 个受控关节一一对应。动作不会直接当作电机力矩,而是先转成目标关节位置:
目标关节位置 = 默认关节位置 + 0.5 × 策略动作
然后由 PD 控制器根据目标位置和当前状态计算力矩。
3. 奖励:什么样的走路算“好”
奖励通常不只是“向前走得越远越好”。还需要同时考虑:
- 跟踪目标速度;
- 保持身体直立;
- 减少横向漂移和多余旋转;
- 控制动作幅度与动作变化率;
- 限制不合理的关节速度和姿态;
- 对摔倒或异常接触进行惩罚。
如果只奖励前进速度,机器人可能学会一种速度很快但姿态极不稳定的“冲出去”动作。
五、先训练 baseline,再做鲁棒微调
1. 从零训练 baseline
Windows PowerShell 下可以通过统一入口启动:
.\run.ps1 isaac-train --headless --num_envs 4096 --max_iters 1500 --seed 42 --run_name baseline
--headless 表示关闭实时渲染,把 GPU 资源优先留给并行仿真和训练;--num_envs 4096 表示同时采集 4096 个环境的数据。显存不足时,可以先改成 2048、1024 或更小。

图 3:把主要在平地训练的 baseline 放到粗糙地形中,能够更快暴露策略薄弱环节。
2. 鲁棒微调
有了 baseline 以后,再进入粗糙地形、随机摩擦和外力扰动环境微调:
.\run.ps1 isaac-train-robust --headless --num_envs 4096 --max_iters 2000 --seed 42
项目默认从已有 baseline checkpoint 开始,而不是重新从随机策略训练。这样做的原因很直观:先让机器人学会基本行走,再学习如何应对地形变化和扰动,通常比一开始就把所有困难同时塞进去更容易收敛。

图 4:鲁棒微调后的策略仍需回到平地检查,避免为了复杂地形牺牲基础步态。

图 5:robust quick-ft 策略在 Isaac 粗糙地形中的评估画面。
六、terrain_difficulty 0.35 到底是什么意思?
地形难度是一个 0 到 1 的归一化参数,不是 35 度,也不是 35 厘米。
它的基本计算方式是:
实际参数 = 最小值 + difficulty ×(最大值 - 最小值)
例如当前台阶高度范围是 0.05~0.23 米,当难度为 0.35 时:
0.05 + 0.35 × (0.23 - 0.05) = 0.113 米
也就是每级台阶高度约 11.3 厘米。不同地形会把同一个 difficulty 映射到坡度、台阶高度或障碍物高度,所以它描述的是“在当前地形参数范围中的位置”。
七、为什么还要迁移到 MuJoCo?
如果策略只在训练它的物理环境中评估,很难判断它到底学到了稳定的控制规律,还是对某个模拟器的接触细节产生了依赖。
换到 MuJoCo 后,下面这些差异会被放大:
- 接触和摩擦模型;
- 关节阻尼、刚度和力矩限制;
- 基座姿态与速度的坐标系;
- 关节名称与排列顺序;
- 仿真步长和策略更新周期;
- 模型质量、惯量和碰撞几何。

图 6:同一 baseline Actor 导入 MuJoCo 后,在平地工况中进行独立推理。
八、Sim2Sim 最容易踩坑的地方
1. 关节顺序必须完全一致
策略输出的第 0 个动作如果在 Isaac 中控制左髋关节,在 MuJoCo 中就不能变成右膝关节。维度都是 37 并不代表顺序正确。
2. 观测定义必须一致
除了维度,还要检查:
- 线速度是在世界坐标系还是机体坐标系;
- 四元数顺序是
wxyz还是xyzw; - 角速度单位是否一致;
- 关节角是否减去了默认姿态;
- 上一次动作使用的是裁剪前还是裁剪后的值。
3. 控制频率必须一致
当前 MuJoCo 侧使用 1 ms 物理步长,每 20 ms 更新一次策略目标,也就是 50 Hz 策略频率。PD 力矩仍然在每一个物理步重新计算。
如果误把策略改成每 1 ms 推理一次,控制行为会和训练时完全不同。
4. 不要只看“有没有摔倒”
还应该记录速度跟踪误差、横向漂移、身体高度、倾角、动作变化率和关节速度等指标。机器人没摔倒,也可能只是站着不动。
九、真实评估结果:成功和失败都保留
下面是本次视频选取的四个 MuJoCo 工况,目标指令均为向前 1.0 m/s:
| 策略 | 地形 | 摩擦系数 | 单次录像结果 |
|---|---|---|---|
| baseline model_1499 | 平地 | 0.8 | 约 6 秒录像内未记录摔倒 |
| baseline model_1499 | 粗糙地形 | 0.8 | 1.84 秒摔倒 |
| robust quick-ft model_1548 | 斜坡 | 1.0 | 约 6 秒录像内未记录摔倒 |
| robust quick-ft model_1548 | 台阶 | 0.8 | 0.60 秒摔倒 |

图 7:baseline 在粗糙地形中于 1.84 秒摔倒。失败画面比单纯的成功演示更有诊断价值。

图 8:robust quick-ft 在摩擦系数 1.0 的斜坡录像中保持行走。

图 9:同一 robust quick-ft 在摩擦系数 0.8 的台阶工况中于 0.60 秒摔倒。
这组结果不能证明 robust 策略已经适应全部复杂地形。更准确的结论是:当前微调对特定斜坡工况有效,但台阶仍然是明显短板;下一步需要针对落脚高度变化、足端接触和台阶课程学习继续优化。
十、如何运行开源项目?
1. 准备 Isaac G1 USD
.\run.ps1 prepare-isaac-asset
脚本会从 NVIDIA 官方资产地址获取本项目所需的 USD,并校验 SHA-256;该第三方资产不直接进入公开 Git 历史。
2. 静态审计
.\run.ps1 verify
检查许可证、模型文件哈希、123→37 Actor 契约、路径可移植性、MuJoCo 模型和 mesh 引用。
3. Isaac 环境自检
.\run.ps1 isaac-self-check --headless
这一步会真实启动 Isaac Sim、加载 USD、创建环境并验证观测和动作维度。
4. 直接播放演示权重
.\run.ps1 isaac-play-baseline --terrain plane --max_steps 2000
.\run.ps1 isaac-play-robust --terrain rough --terrain_difficulty 0.35 --max_steps 2000
.\run.ps1 isaac-play-robust --terrain slope --terrain_difficulty 0.35 --max_steps 2000
.\run.ps1 isaac-play-robust --terrain stairs --terrain_difficulty 0.35 --max_steps 2000
5. MuJoCo 播放与批量评估
.\run.ps1 mujoco-viewer-baseline --terrain plane --friction 0.8
.\run.ps1 mujoco-viewer-robust --terrain slope --friction 1.0
.\run.ps1 mujoco-eval --terrain plane,rough,slope,steps --frictions 0.4,0.6,0.8,1.0 --duration 10
总结
一个完整的人形机器人强化学习项目,不应该停在“训练窗口里能走”。更可靠的流程应该包括:明确观测与动作契约、保留训练和评估入口、在多种地形下测试、导出独立策略,并换一个物理引擎检查策略对仿真细节的依赖。
这次 G1 实验既保留了平地和斜坡中的正常行走,也保留了粗糙地形和台阶中的摔倒结果。后者不是项目的污点,而是下一轮奖励设计、域随机化和课程学习最直接的依据。
B站解析视频:
https://www.bilibili.com/video/BV1963d6kE36/?vd_source=6aeed6700d488ca78e0e8c51ab08c727
开源项目地址(即将开源):https://github.com/yezzzzye/g1-walk-isaaclab-mujoco
如果你正在做人形机器人、强化学习、IsaacLab 环境开发或 Sim2Sim 验证,欢迎交流。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)