【通识】RSL-RL快速上手
开动
强烈推荐张老师系列:张伟楠老师的动手学强化学习- PPO
目前完成了基于宇树rl_lab的RL仿真训练复现,踩了一些比较低级错误的坑后,发现纯RL的效果比预期的要好,算是pipeline流程通了,开始了解实现原理。
在智驾中,RL也已经实现了量产落地,能够在专家数据基础上实现性能拓展,效果还是很显著的。
拿unitree_rl_lab作为学习入口:
RSL-RL 做什么、PPO 和 Distillation 两条训练链路怎么跑、它如何接入 Unitree/Isaac Lab 任务,以及应该从哪些文件开始读。
好家伙:用的GPT5.5直出的图,很奈斯
1. 一句话理解 RSL-RL
extern/rsl_rl 是一个面向机器人强化学习的轻量 PyTorch 训练库。它不负责创建机器人环境、写奖励函数或管理仿真资产;这些由 Isaac Lab、Unitree RL Lab、Legged Gym 等环境库负责。RSL-RL 的职责是:
- 从环境批量采样交互数据。
- 把采样结果存入 rollout buffer。
- 用 PPO 或蒸馏算法更新策略网络。
- 记录日志、保存 checkpoint、导出 JIT/ONNX 策略。
换句话说:
环境库负责“机器人世界”
RSL-RL 负责“怎么学习”
2. 训练系统总览:两条主线
RSL-RL 不只有 PPO。当前源码里最重要的两条主线是:
| 主线 | 算法 | 典型用途 |
|---|---|---|
| On-policy RL | PPO |
直接通过环境 reward 学策略,例如 locomotion 速度跟踪 |
| Student-Teacher | Distillation |
让 student 模仿 teacher,把 privileged policy 压到可部署观测上 |
PPO 主流程:
Distillation 主流程:
这个图对应的核心源码是:
| 职责 | 文件 | 应先读的方法 |
|---|---|---|
| 训练主循环 | extern/rsl_rl/rsl_rl/runners/on_policy_runner.py |
OnPolicyRunner.__init__()、learn() |
| PPO 算法 | extern/rsl_rl/rsl_rl/algorithms/ppo.py |
act()、process_env_step()、compute_returns()、update() |
| 蒸馏 Runner | extern/rsl_rl/rsl_rl/runners/distillation_runner.py |
learn() |
| 蒸馏算法 | extern/rsl_rl/rsl_rl/algorithms/distillation.py |
act()、process_env_step()、update() |
| Rollout 缓冲区 | extern/rsl_rl/rsl_rl/storage/rollout_storage.py |
add_transition()、mini_batch_generator() |
| 默认 MLP 网络 | extern/rsl_rl/rsl_rl/models/mlp_model.py |
__init__()、forward()、get_latent() |
| 环境接口 | extern/rsl_rl/rsl_rl/env/vec_env.py |
VecEnv.get_observations()、VecEnv.step() |
3. RSL-RL 的目录结构
extern/rsl_rl/
├── rsl_rl/
│ ├── algorithms/ # PPO、Distillation 等算法
│ ├── runners/ # 训练入口和主循环
│ ├── storage/ # rollout buffer
│ ├── models/ # MLP / RNN / CNN 模型封装
│ ├── modules/ # MLP、分布、归一化、RNN 等网络积木
│ ├── env/ # VecEnv 抽象接口
│ ├── extensions/ # RND、Symmetry 等扩展
│ └── utils/ # 日志、配置解析、导出辅助
├── docs/ # 官方文档
├── tests/ # 单元测试
├── pyproject.toml # Python 包定义
└── README.md
初学者先不要从 modules/ 开始读。PPO 推荐路径是:
OnPolicyRunner.learn()
-> PPO.act()
-> PPO.process_env_step()
-> RolloutStorage.add_transition()
-> PPO.compute_returns()
-> PPO.update()
-> MLPModel.forward()
Distillation 推荐路径是:
DistillationRunner.learn()
-> OnPolicyRunner.learn()
-> Distillation.act()
-> Distillation.process_env_step()
-> RolloutStorage.add_transition()
-> Distillation.update()
-> MLPModel.forward()
4. RSL-RL 需要环境提供什么
RSL-RL 只依赖一个抽象环境接口:VecEnv。
环境必须提供这些属性:
num_envs 并行环境数量
num_actions 动作维度
max_episode_length episode 最大长度
episode_length_buf 每个环境当前 episode 长度
device 环境所在设备
cfg 环境配置
环境必须实现两个方法:
obs = env.get_observations()
obs, rewards, dones, extras = env.step(actions)
其中 obs 不是普通 Tensor,而是 TensorDict。它通常包含多个 observation group,例如:
obs["policy"] # actor 可见观测
obs["critic"] # critic 可见观测,通常包含特权信息
RSL-RL 再通过 obs_groups 决定 actor 和 critic 各自读取哪些组:
obs_groups = {
"actor": ["policy"],
"critic": ["critic"],
}
这是理解 Isaac Lab 接入 RSL-RL 的关键点:环境产生多个观测组,RSL-RL 的模型按配置选择并拼接这些观测组。
5. Runner:训练总控
OnPolicyRunner 是 RSL-RL 的通用 on-policy 训练入口;DistillationRunner 继承它,只额外检查 teacher 参数是否已经加载。创建 runner 时,它会:
- 保存环境、训练配置和训练设备。
- 读取一次
env.get_observations(),用来推断观测维度。 - 根据配置创建算法、模型和 rollout storage。PPO 创建 actor/critic,Distillation 创建 student/teacher。
- 创建 logger。
主循环在 learn() 中:
关键配置:
num_steps_per_env = 24
save_interval = 100
max_iterations = 50000
在 Unitree RL Lab 的 G1 locomotion PPO 配置中,这些值位于:
extern/unitree_rl_lab/source/unitree_rl_lab/unitree_rl_lab/tasks/locomotion/agents/rsl_rl_ppo_cfg.py
Isaac Lab 也提供 Distillation 配置示例:
extern/isaac_lab/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/anymal_d/agents/rsl_rl_distillation_cfg.py
6. PPO:一次训练迭代内部发生了什么
PPO 在 RSL-RL 中分成四个核心步骤。
6.1 act():采样动作并记录旧策略信息
PPO.act(obs) 做四件事:
- actor 根据当前 obs 采样动作。
- critic 估计当前状态价值
V(s)。 - 记录动作在旧策略下的
log_prob。 - 记录 actor 分布参数,供后续 PPO ratio/KL 使用。
示意:
obs
├─ actor -> action, log_prob, distribution params
└─ critic -> value
注意:PPO 更新时需要比较“采样动作时的旧策略”和“当前更新后的新策略”,所以 rollout 阶段必须存 old_log_prob 和旧分布参数。
6.2 process_env_step():处理环境返回
process_env_step(obs, rewards, dones, extras) 在每次 env.step() 后执行,主要负责:
- 更新 actor/critic 的 observation normalizer。
- 记录 reward 和 done。
- 如果启用 RND,加入 intrinsic reward。
- 如果
extras中有time_outs,对时间截断做 bootstrap。 - 将 transition 写入
RolloutStorage。 - 根据 done 重置 actor/critic 的 recurrent state。
time_outs 很重要:如果 episode 是因为时间上限结束,而不是机器人摔倒或任务失败结束,那么理论上不应该把它当作真实 terminal。RSL-RL 会用 critic value 对 reward 做补偿:
reward += gamma * V(s) * time_out
6.3 compute_returns():计算 GAE
rollout 收集完成后,PPO 从最后一步往前计算:
delta_t = r_t + gamma * V(s_{t+1}) - V(s_t)
adv_t = delta_t + gamma * lambda * adv_{t+1}
return = adv_t + V(s_t)
其中:
| 参数 | 含义 |
|---|---|
gamma |
折扣因子,越接近 1 越看重长期回报 |
lam |
GAE 平滑系数,控制 bias/variance 权衡 |
Unitree G1 默认配置一般是:
gamma = 0.99
lam = 0.95
6.4 update():PPO 多轮小批量更新
PPO 更新时会把 rollout buffer 展平:
[num_steps_per_env, num_envs, ...]
-> [num_steps_per_env * num_envs, ...]
然后分成 num_mini_batches,重复 num_learning_epochs 轮。
核心 loss:
ratio = exp(new_log_prob - old_log_prob)
surrogate_1 = -advantage * ratio
surrogate_2 = -advantage * clamp(ratio, 1 - clip, 1 + clip)
actor_loss = max(surrogate_1, surrogate_2)
value_loss = MSE(V(s), return)
loss = actor_loss + value_coef * value_loss - entropy_coef * entropy
这就是 PPO 的“保守更新”:如果新策略相对旧策略变化太大,clip_param 会限制收益,避免一步把策略推坏。
7. Distillation:学生-老师蒸馏
Distillation 是 RSL-RL 的第二条重要训练链路。它不是通过 reward 优化策略,而是让 student 模仿 teacher 的动作。典型用途是:先训练一个能看到 privileged observation 的强 teacher,再把行为蒸馏到只看部署可用观测的 student 上。
核心关系:
obs
├─ student -> action,用于 env.step
└─ teacher -> privileged_actions,作为监督目标
loss = mse(student_action, teacher_action)
# 或 huber loss
7.1 Distillation.act():student 行动,teacher 给标签
Distillation.act(obs) 做三件事:
- student 根据当前 obs 生成动作,并用这个动作推进环境。
- teacher 根据当前 obs 生成目标动作
privileged_actions。 - 把 obs、student action、teacher target 暂存在 transition 中。
这里的关键约束是:环境里真正执行的是 student action,teacher 只提供监督信号。
7.2 process_env_step():记录 transition
Distillation 仍然会接收 rewards、dones、extras,但它不使用 reward 来计算 return 或 advantage。reward 主要用于日志和环境侧统计;done 用来重置 student/teacher 的 recurrent state。
RolloutStorage 在 distillation 模式下会额外保存:
privileged_actions # teacher 输出的动作标签
7.3 compute_returns():空操作
Distillation 不做 GAE,也不需要 critic value target,所以 compute_returns() 是 no-op。
7.4 update():行为克隆更新 student
更新阶段从 storage 按时间步取数据:
student_actions = student(observations)
behavior_loss = mse(student_actions, privileged_actions)
然后只更新 student。teacher 保持 eval mode,不参与梯度更新。
关键参数:
| 参数 | 作用 |
|---|---|
num_learning_epochs |
每批采样数据重复训练几轮 |
gradient_length |
累积多少步 loss 后做一次反向传播,常用于 recurrent student |
learning_rate |
student 优化器学习率 |
loss_type |
mse 或 huber |
max_grad_norm |
student 梯度裁剪 |
7.5 teacher 从哪里来
DistillationRunner.learn() 会先检查 teacher 是否加载。如果没有加载 teacher checkpoint,会直接报错。
Distillation.load() 支持两种来源:
- 加载 distillation checkpoint:读取
student_state_dict和teacher_state_dict。 - 加载 PPO checkpoint:读取
actor_state_dict作为 teacher。
因此常见流程是:
先用 PPO 训练 teacher policy
再用 Distillation 加载 PPO actor 作为 teacher
最后导出 student policy 用于部署
Distillation 不兼容 RND 和 Symmetry 扩展;源码会显式检查并报错。
8. Actor、Critic、Student、Teacher 与 Observation Groups
RSL-RL 默认使用 MLPModel。它的输入不是环境给出的全部 obs,而是按 obs_groups 选择指定 group 后拼接:
latent = torch.cat([obs[obs_group] for obs_group in self.obs_groups], dim=-1)
PPO 典型配置:
actor = MLPModel(obs_set="actor")
critic = MLPModel(obs_set="critic")
Distillation 典型配置:
student = MLPModel(obs_set="student")
teacher = MLPModel(obs_set="teacher")
含义:
| 网络 | 所属训练方式 | 训练时输入 | 部署时是否需要 |
|---|---|---|---|
| actor | PPO | policy observation | 需要,PPO 导出的就是 actor |
| critic | PPO | privileged / critic observation | 不需要,只训练时评估 value |
| student | Distillation | 部署可用 observation | 需要,蒸馏导出的就是 student |
| teacher | Distillation | policy 或 privileged observation | 不需要,只训练时提供动作标签 |
机器人强化学习里常见做法是:critic 或 teacher 训练时看更多真值信息,比如 base linear velocity;actor 或 student 只能看部署时真实可获得的信息,比如 IMU、关节状态、命令、上一帧动作。
9. Unitree G1 29DOF 接入示例
Unitree 训练入口:
extern/unitree_rl_lab/scripts/rsl_rl/train.py
关键接入链路:
对应代码逻辑:
env = gym.make(args_cli.task, cfg=env_cfg, ...)
env = RslRlVecEnvWrapper(env, clip_actions=agent_cfg.clip_actions)
runner = OnPolicyRunner(env, agent_cfg.to_dict(), log_dir=log_dir, device=agent_cfg.device)
runner.learn(num_learning_iterations=agent_cfg.max_iterations, init_at_random_ep_len=True)
G1 29DOF locomotion 的 actor observation 通常包括:
base_ang_vel
projected_gravity
velocity_commands
joint_pos_rel
joint_vel_rel
last_action
并设置:
history_length = 5
enable_corruption = True
concatenate_terms = True
critic observation 通常额外包含:
base_lin_vel
这说明 critic 使用训练时特权信息,actor 保持部署可用输入。
10. 最快上手命令
10.1 确认 Python 实际 import 的 RSL-RL
如果想使用本工作区源码版本,先在对应 Python 环境中安装 editable 包:
python -m pip install -e extern/rsl_rl
验证 import 路径:
python -c "import rsl_rl, inspect; print(inspect.getfile(rsl_rl))"
期望输出应指向:
/home/nio/wangbin/unitree_workspace/extern/rsl_rl/rsl_rl/__init__.py
如果输出在 site-packages 下,说明当前环境用的是 pip 安装版本,而不是工作区源码。
10.2 Unitree RL Lab 训练入口
常见入口在:
extern/unitree_rl_lab/scripts/rsl_rl/train.py
具体任务名需要从 Unitree RL Lab 注册的 gym task 中选择。脚本会读取 task 对应的 rsl_rl_cfg_entry_point,创建 env 和 runner。
10.3 回放与导出
常见入口:
extern/unitree_rl_lab/scripts/rsl_rl/play.py
extern/unitree_rl_lab/scripts/rsl_rl/play_keyboard.py
RSL-RL 自身也提供导出接口:
runner.export_policy_to_jit(path, filename="policy.pt")
runner.export_policy_to_onnx(path, filename="policy.onnx")
PPO 部署时通常只需要 actor,不需要 critic。Distillation 部署时通常只需要 student,不需要 teacher。
11. 常用调参入口
Unitree locomotion PPO 配置:
extern/unitree_rl_lab/source/unitree_rl_lab/unitree_rl_lab/tasks/locomotion/agents/rsl_rl_ppo_cfg.py
Isaac Lab Distillation 配置示例:
extern/isaac_lab/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/anymal_d/agents/rsl_rl_distillation_cfg.py
常调参数:
| 参数 | 作用 | 现象与调参方向 |
|---|---|---|
num_steps_per_env |
每轮每个环境采样步数 | 太小可能估计不稳,太大更新滞后 |
num_learning_epochs |
每批数据重复训练轮数 | 太大可能过拟合旧数据 |
num_mini_batches |
每轮分多少 mini-batch | 影响梯度噪声和显存 |
learning_rate |
学习率 | 不稳定先降学习率 |
schedule |
学习率调度 | adaptive 会根据 KL 自动调 |
desired_kl |
目标 KL | KL 太大策略变化激进,太小学习慢 |
clip_param |
PPO ratio 裁剪范围 | 常用 0.2 |
entropy_coef |
探索强度 | 探索不足可增大,动作抖可减小 |
gamma |
长期回报折扣 | locomotion 常见 0.99 |
lam |
GAE 平滑 | 常见 0.95 |
max_grad_norm |
梯度裁剪 | 防止梯度爆炸 |
网络结构配置:
actor.hidden_dims = [512, 256, 128]
critic.hidden_dims = [512, 256, 128]
activation = "elu"
Distillation 常调参数:
| 参数 | 作用 | 现象与调参方向 |
|---|---|---|
gradient_length |
累积多少步再反传 | RNN 蒸馏常需要关注,太长显存压力更大 |
loss_type |
mse 或 huber |
动作标签有异常值时可考虑 huber |
student.hidden_dims |
student 容量 | 部署算力有限时先压 student |
teacher.hidden_dims |
teacher 结构 | 通常要匹配已加载 checkpoint |
student.obs_groups |
student 输入 | 必须只包含部署可用观测 |
teacher.obs_groups |
teacher 输入 | 可包含 privileged observation |
观测和奖励配置通常在机器人任务文件中,例如 G1 29DOF:
extern/unitree_rl_lab/source/unitree_rl_lab/unitree_rl_lab/tasks/locomotion/robots/g1/29dof/velocity_env_cfg.py
12. Debug 时优先看什么
12.1 训练直接 NaN
优先检查:
- 环境返回的
obs、rewards、dones是否有 NaN。 - reward 权重是否过大。
- action scale 或 PD gain 是否过激。
learning_rate是否过大。
OnPolicyRunner.learn() 中默认会执行 check_nan(obs, rewards, dones)。
12.2 策略学不会走路
优先检查:
- actor observation 是否包含命令、关节状态、上一帧动作。
- critic 是否有合理 privileged information。
- reward 中 tracking 项和姿态/能耗惩罚是否失衡。
- command curriculum 或 terrain curriculum 是否太难。
12.3 训练能走,部署不行
优先检查:
- actor 是否使用了部署拿不到的观测。
- 训练观测归一化是否正确导出。
- joint order、action scale、default joint pose 是否和部署端一致。
- history buffer 拼接顺序是否一致。
13. 建议阅读顺序
第一遍读 PPO 主干:
1. extern/rsl_rl/rsl_rl/runners/on_policy_runner.py
2. extern/rsl_rl/rsl_rl/algorithms/ppo.py
3. extern/rsl_rl/rsl_rl/storage/rollout_storage.py
4. extern/rsl_rl/rsl_rl/models/mlp_model.py
5. extern/rsl_rl/rsl_rl/env/vec_env.py
第二遍读 Distillation 主干:
1. extern/rsl_rl/rsl_rl/runners/distillation_runner.py
2. extern/rsl_rl/rsl_rl/algorithms/distillation.py
3. extern/rsl_rl/rsl_rl/storage/rollout_storage.py
4. extern/rsl_rl/rsl_rl/models/mlp_model.py
5. extern/isaac_lab/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/anymal_d/agents/rsl_rl_distillation_cfg.py
第三遍结合 Unitree:
1. extern/unitree_rl_lab/scripts/rsl_rl/train.py
2. extern/unitree_rl_lab/source/unitree_rl_lab/unitree_rl_lab/tasks/locomotion/agents/rsl_rl_ppo_cfg.py
3. extern/unitree_rl_lab/source/unitree_rl_lab/unitree_rl_lab/tasks/locomotion/robots/g1/29dof/velocity_env_cfg.py
第四遍再看扩展能力:
extern/rsl_rl/rsl_rl/extensions/rnd.py
extern/rsl_rl/rsl_rl/extensions/symmetry.py
extern/rsl_rl/rsl_rl/runners/distillation_runner.py
extern/rsl_rl/rsl_rl/algorithms/distillation.py
14. 版本注意事项
当前子模块源码的 pyproject.toml 中包版本为 5.4.1。但 extern/unitree_rl_lab/scripts/rsl_rl/train.py 里对分布式训练有最低版本检查,要求 rsl-rl-lib >= 2.3.1。
因此:
- 单卡训练通常重点确认实际 import 路径即可。
- 分布式训练前必须确认当前环境安装版本和 Unitree RL Lab 脚本要求一致。
- 如果修改了
extern/rsl_rl源码,记得在训练环境中使用 editable install,否则改动不会生效。
15. 最小心智模型
把 RSL-RL 压缩成一句话:
OnPolicyRunner / DistillationRunner 负责循环;
PPO / Distillation 负责算法;
RolloutStorage 负责存数据;
Model 负责把 obs 变成 action/value;
VecEnv 是环境和算法之间的接口。
把 PPO 压缩成一句话:
先用旧策略采一批数据,再用裁剪后的目标函数小步更新新策略,避免策略变化过猛。
把 Distillation 压缩成一句话:
student 负责行动,teacher 负责给动作标签,训练时只更新 student。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐




所有评论(0)