使用 Genesis 训练 Unitree Go2 四足机器人步态控制
使用Genesis 训练 Unitree Go2 四足机器人步态控制
作者背景:北航自动化控制水组硕士,C++ 扎实,Python 在学。已完成 PPO vs PID 倒立摆对比实验,本文记录从零开始用 Genesis 仿真器训练 Go2 步态策略的完整过程,包含所有踩坑和解决方案。
本文只是跑了案例,后续打算继续。
环境:Windows 11 + WSL2 Ubuntu + RTX 5060(Blackwell, sm_120)+ Conda + PyTorch nightly cu128
一、背景:为什么选 Genesis 而不是 Isaac Gym?
很多教程都在用 unitree_rl_gym,它依赖的是 Isaac Gym Preview 4。但在开始之前必须搞清楚一个关键概念区分,否则会踩大坑:
| 名称 | 版本号形式 | 状态 | 用途 |
|---|---|---|---|
| Isaac Gym Preview 4 | Preview 1/2/3/4,没有4.5/5.0 | ❌ 已弃用,停止维护 | unitree_rl_gym 依赖它 |
| Isaac Sim | 4.0 / 4.5 / 5.0 | ✅ 现役 | Isaac Lab 依赖它 |
| Isaac Lab | v1.x / v2.x | ✅ 官方推荐 | 新一代RL框架 |
| Genesis | 0.4.x | ✅ 2024年底新出 | 本文使用 |
RTX 5060(Blackwell架构,sm_120)的特殊问题:Isaac Gym Preview 4 的物理引擎是预编译闭源二进制,不支持 sm_120,大概率跑不起来(失败记录见上一篇博客RTX 5060 + WSL2 搭建 Go2 强化学习训练环境记录(失败记录)-CSDN博客)。Isaac Sim 在 WSL2 上也有严重的 GPU 识别问题。Genesis 是纯 Python 实现,对新架构友好,且官方有完整的 Go2 示例,因此是当前环境下的最优选择。
二、环境配置
2.1 前提条件
- Windows 侧已安装最新 NVIDIA 驱动(支持 Blackwell)
- WSL2 Ubuntu 已安装
- Conda 虚拟环境 rl 已建好
- PyTorch nightly cu128 已装好,运行输出torch.cuda.is_available() 返回 True
2.2 安装 Genesis
Genesis 可以直接 pip 安装,不需要克隆整个仓库:
pip install genesis-world
# 验证
python -c "import genesis; print('Genesis OK')"
# 找到包的安装路径(示例文件在这里)
python -c "import genesis; import os; print(os.path.dirname(genesis.__file__))"
2.3 安装训练依赖
# 注意:必须是 rsl-rl-lib >= 5.0.0,旧版会报 ImportError
pip install "rsl-rl-lib>=5.0.0" tensorboard -i https://pypi.tuna.tsinghua.edu.cn/simple
踩坑1:如果 pip 报 ProxyError,是因为之前设置了错误的代理环境变量。解决方法:
unset http_proxy && unset https_proxy && unset HTTP_PROXY && unset HTTPS_PROXY
sed -i '/WINDOWS_HOST/d' ~/.bashrc
sed -i '/https_proxy/d' ~/.bashrc
sed -i '/http_proxy/d' ~/.bashrc
2.4 获取 Go2 示例文件
由于国内网络问题,我直接 git clone Genesis 仓库会失败(GnuTLS TLS 解码错误)。解决方案:在 Windows 浏览器里直接下载以下三个文件,然后复制到 WSL2:
https://raw.githubusercontent.com/Genesis-Embodied-AI/Genesis/main/examples/locomotion/go2_train.py
https://raw.githubusercontent.com/Genesis-Embodied-AI/Genesis/main/examples/locomotion/go2_eval.py
https://raw.githubusercontent.com/Genesis-Embodied-AI/Genesis/main/examples/locomotion/go2_env.py
假设下载到 D:\RL\Genesis\,在 WSL2 里执行:
mkdir -p ~/genesis_examples/locomotion
cp /mnt/d/RL/Genesis/go2_train.py ~/genesis_examples/locomotion/
cp /mnt/d/RL/Genesis/go2_eval.py ~/genesis_examples/locomotion/
cp /mnt/d/RL/Genesis/go2_env.py ~/genesis_examples/locomotion/
三、关键报错与解决方案汇总
报错1:libcuda.so lib not found / Arch=[cuda] is not supported
[W] [cuda_driver.cpp:load_lib@35] libcuda.so lib not found.
RuntimeError: Arch=[<Arch.cuda: 4>] is not supported
原因:Genesis 的底层物理引擎(quadrants)找不到 WSL2 里的 CUDA 库。WSL2 的 libcuda.so 在特殊路径下,不在标准 LD_LIBRARY_PATH 里。
解决:
# 验证 libcuda.so 确实存在
ls /usr/lib/wsl/lib/libcuda*
# 临时修复
export LD_LIBRARY_PATH=/usr/lib/wsl/lib:$LD_LIBRARY_PATH
# 永久修复(写入 bashrc)
echo 'export LD_LIBRARY_PATH=/usr/lib/wsl/lib:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc
报错2:unrecognized arguments: --headless
新版 Genesis 不需要 --headless 参数,WSL2 无显示器环境下会自动检测。直接去掉该参数:
python go2_train.py -e go2_experiment
报错3:ImportError: Please install ‘rsl-rl-lib>=5.0.0’
pip install "rsl-rl-lib>=5.0.0" -i https://pypi.tuna.tsinghua.edu.cn/simple
报错4:FileNotFoundError: logs/go2-walking/cfgs.pkl
eval 默认找 go2-walking 这个实验名,但训练时用了自定义名字。加 -e 参数指定:
python go2_eval.py -e go2_v2
报错5:GenesisException: No display detected
WSL2 没有显示器,eval 脚本默认开 viewer 会失败。在 Go2Env() 初始化时设置 show_viewer=False。
报错6:GenesisException: Scene is already built
相机必须在 scene.build() 之前添加。Go2Env 初始化时已经 build 了 scene,所以需要用 monkey-patch 方式在 build 前插入相机(见第五节 eval 完整代码)。
报错7:TypeError: can’t assign a str to a torch.FloatTensor
follow_entity 的 fixed_axis 参数不是字符串,是三元组。正确用法:
# 错误
cam.follow_entity(env.robot, fixed_axis="z")
# 正确:(x, y, z),None 表示跟随,数值表示固定在该值
cam.follow_entity(env.robot, fixed_axis=(None, 2.5, 0.8))
四、训练
cd ~/genesis_examples/locomotion
# 设置 CUDA 库路径(每次新终端都要,或者已写入 bashrc)
export LD_LIBRARY_PATH=/usr/lib/wsl/lib:$LD_LIBRARY_PATH
# 开始训练(1000轮约12分钟)
python go2_train.py -e go2_v2 --max_iterations 1000
另开一个终端监控训练曲线:
conda activate rl
cd ~/genesis_examples/locomotion
tensorboard --logdir logs
# Windows 浏览器打开 http://localhost:6006
训练指标解读
Steps per second: 415948 ← RTX 5060 跑 Genesis,41万步/秒
Mean reward: 21.90 ← 核心指标,从0涨到21说明策略在收敛
rew_tracking_lin_vel: 0.9924 ← 线速度跟踪,接近1.0表示基本收敛 ✅
rew_tracking_ang_vel: 0.1995 ← 角速度跟踪,还有提升空间
rew_lin_vel_z: -0.0054 ← 惩罚项,接近0说明机器人没有乱跳 ✅
Time elapsed: 00:12:08 ← 1000轮只用了12分钟
模型保存位置:logs/go2_v2/model_0.pt, model_100.pt, …, model_999.pt
五、可视化:录制步态视频
由于 WSL2 没有图形界面,使用 Genesis 内置的录制功能生成 mp4。
完整 go2_eval.py(含镜头跟随):
import argparse
import os
import pickle
from importlib import metadata
import torch
try:
if int(metadata.version("rsl-rl-lib").split(".")[0]) < 5:
raise ImportError
except (metadata.PackageNotFoundError, ImportError, ValueError) as e:
raise ImportError("Please install 'rsl-rl-lib>=5.0.0'.") from e
from rsl_rl.runners import OnPolicyRunner
import genesis as gs
from go2_env import Go2Env
def main():
parser = argparse.ArgumentParser()
parser.add_argument("-e", "--exp_name", type=str, default="go2-walking")
parser.add_argument("--ckpt", type=int, default=None)
args = parser.parse_args()
gs.init(backend=gs.cpu)
log_dir = f"logs/{args.exp_name}"
with open(f"logs/{args.exp_name}/cfgs.pkl", "rb") as f:
env_cfg, obs_cfg, reward_cfg, command_cfg, train_cfg = pickle.load(f)
reward_cfg["reward_scales"] = {}
# 必须在 scene.build() 前添加相机,用 monkey-patch 实现
original_build = gs.Scene.build
cam_holder = {}
def patched_build(self, *args, **kwargs):
cam_holder['cam'] = self.add_camera(
res=(1280, 720),
pos=(0.0, 2.5, 0.8), # 侧面视角
lookat=(0.0, 0.0, 0.3),
fov=45,
GUI=False,
)
return original_build(self, *args, **kwargs)
gs.Scene.build = patched_build
env = Go2Env(
num_envs=1,
env_cfg=env_cfg,
obs_cfg=obs_cfg,
reward_cfg=reward_cfg,
command_cfg=command_cfg,
show_viewer=False,
)
gs.Scene.build = original_build
cam = cam_holder['cam']
# 自动选最新 checkpoint
if args.ckpt is None:
ckpts = [f for f in os.listdir(log_dir) if f.startswith("model_") and f.endswith(".pt")]
ckpts.sort(key=lambda x: int(x.split("_")[1].split(".")[0]))
ckpt_num = int(ckpts[-1].split("_")[1].split(".")[0])
print(f"Auto-selected checkpoint: model_{ckpt_num}.pt")
else:
ckpt_num = args.ckpt
runner = OnPolicyRunner(env, train_cfg, log_dir, device=gs.device)
runner.load(os.path.join(log_dir, f"model_{ckpt_num}.pt"))
policy = runner.get_inference_policy(device=gs.device)
obs_dict = env.reset()
# 镜头跟随:X轴跟机器人,Y轴固定2.5(侧面),Z轴固定0.8(高度)
cam.follow_entity(env.robot, fixed_axis=(None, 2.5, 0.8), smoothing=0.1)
output_path = os.path.abspath(f"logs/{args.exp_name}/go2_follow.mp4")
print(f"Recording to: {output_path}")
cam.start_recording()
with torch.no_grad():
for i in range(500):
actions = policy(obs_dict)
obs_dict, rews, dones, infos = env.step(actions)
cam.render()
if (i + 1) % 100 == 0:
print(f" Step {i+1}/500")
cam.stop_recording(save_to_filename=output_path, fps=50)
print(f"✅ Done! Video: {output_path}")
if __name__ == "__main__":
main()
运行并复制到 Windows:(“mnt/h后面跟自己路径”)
python go2_eval.py -e go2_v2
cp ~/genesis_examples/locomotion/logs/go2_v2/go2_follow.mp4 /mnt/d/RL/Genesis/
最后在windows对应的盘可以找到视频:
go2_follow
六、项目结构总览
~/genesis_examples/locomotion/
├── go2_env.py # 核心:观测空间、动作空间、奖励函数定义
├── go2_train.py # 训练入口
├── go2_eval.py # 推理+录视频
└── logs/
└── go2_v2/
├── cfgs.pkl # 训练配置存档
├── model_0.pt # 各轮次模型
├── model_100.pt
├── ...
├── model_999.pt # 最终模型
└── go2_follow.mp4 # 录制的步态视频
七、参考资料
- Genesis 官方文档:https://genesis-world.readthedocs.io
- unitree_rl_gym:https://github.com/unitreerobotics/unitree_rl_gym
- unitree_rl_lab(Isaac Lab版):https://github.com/unitreerobotics/unitree_rl_lab
- NVIDIA CUDA on WSL2:https://docs.nvidia.com/cuda/wsl-user-guide/index.html
更多推荐



所有评论(0)