四足机器人爬楼梯:Reward 调参与训练检查表

问题背景

爬楼梯比平地走路难很多,因为它不只是“速度跟踪”问题,还同时要求机器人:

看见或感知台阶高度
把脚抬到足够高度
落脚位置不能踩空
机身要跟着台阶抬升
接触力不能过猛
不能用小腿/大腿/机身蹭台阶

所以如果四足机器人在楼梯上训练失败,常见现象会比较多:

  • 前脚撞到台阶立面;
  • 脚抬不够高,卡在台阶边缘;
  • 脚抬太高,动作很夸张,能耗大;
  • 身体没有跟着抬升,腹部或腿部碰撞;
  • 只会冲上去,速度一慢就失败;
  • 上楼能走,下楼直接摔;
  • 仿真能走,真机落脚不准或接触力过大。

这篇专门整理:针对爬楼梯任务,四足强化学习里哪些 reward、terrain curriculum、observation 和 reset 条件最值得调整。

先看官方基线里的楼梯训练

legged_gym 的 terrain curriculum 里包含 stairs:

terrain_proportions = [0.1, 0.1, 0.35, 0.25, 0.2]
# terrain types: [smooth slope, rough slope, stairs up, stairs down, discrete]

在 terrain 生成里,楼梯高度随 difficulty 增加:

step_height = 0.05 + 0.18 * difficulty
terrain_utils.pyramid_stairs_terrain(
terrain,
step_width=0.31,
step_height=step_height,
platform_size=3.0,
)

其中上楼和下楼通过 step_height 正负号区分。

Isaac Lab 的 rough locomotion 配置也保留了几个关键设计:

  • terrain generator + terrain levels curriculum;
  • height scanner / height scan observation;
  • foot contact sensor,并 track air time;
  • velocity tracking reward;
  • feet_air_time;
  • undesired_contacts;
  • base contact termination;
  • friction、base mass、COM、push 等 randomization。

这些设计共同说明:爬楼梯不能只改 reward,还要同时看地形课程、感知输入、接触检测和终止条件。

一句话结论

爬楼梯 reward 调参的优先级,我会这样排:

1. 先保证 terrain curriculum 合理:台阶高度/宽度从简单到困难
2. 保证 observation 里有高度信息:height scan / terrain scan / 未来落脚区域
3. 调 feet clearance / feet air time:鼓励抬脚,但限制夸张抬腿
4. 强化 collision / stumble / undesired contacts:前脚不要撞立面,腿身不要蹭台阶
5. 调 base height / orientation / lin_vel_z:身体要随地形抬升但不能跳
6. 调 tracking velocity:爬楼梯速度范围要保守,不能只奖励冲刺
7. 最后调能耗和平滑项:torques、dof_acc、action_rate

1. Terrain curriculum:先别一上来训练高台阶

爬楼梯最容易犯的错误是:reward 还没调清楚,就直接给很难的楼梯。

这会导致 policy 早期大量失败,最后学到一些奇怪策略,比如撞上去、跳上去、趴着蹭上去。

推荐调法

1)台阶高度从低到高

可以参考 legged_gym 的思路:

step_height = 0.05 + 0.18 * difficulty

对应大概是:

简单:5 cm
中等:10~15 cm
困难:20 cm+

真机如果是 Go2 / A1 / 小型四足,建议先从 3~8 cm 开始,不要直接用很高台阶。

2)台阶宽度不要过窄

legged_gym 里 stairs 示例的 step_width=0.31m。如果机器人步长、足端尺寸或控制频率不匹配,台阶太窄会导致踩空非常频繁。

建议先用宽台阶:

step_width: 0.30 ~ 0.40 m 起步

等策略稳定后再缩窄。

3)上楼和下楼分开调

上楼和下楼不是同一个问题:

  • 上楼需要足端 clearance 和身体抬升;
  • 下楼需要落脚控制、接触力控制和防俯冲。

建议先训练上楼,再混入下楼;或者至少分别看两组 eval 视频。

2. Observation:没有高度信息,reward 很难救

爬楼梯强依赖地形感知。如果 policy 只看到 proprioception:

base velocity
base angular velocity
projected gravity
joint pos / vel
action history

它可能能在固定楼梯上记住一种节奏,但泛化到不同台阶高度、宽度、起点相位时会很差。

推荐加入

1)height scan / terrain height measurements

legged_gym 默认 rough terrain observation 会加入机器人前方和周围的高度采样点:

measured_points_x = [-0.8, ..., 0.8]
measured_points_y = [-0.5, ..., 0.5]

Isaac Lab rough config 里也使用 height_scanner:

height_scanner = RayCasterCfg(
prim_path="{ENV_REGEX_NS}/Robot/base",
pattern_cfg=patterns.GridPatternCfg(resolution=0.1, size=[1.6, 1.0]),
)

爬楼梯建议保留这类高度观测。

2)重点覆盖前方落脚区域

爬楼梯主要需要知道前方台阶,所以高度点不要只覆盖身体正下方。

建议:

x 方向覆盖:身体前方 0.2 ~ 1.0 m
y 方向覆盖:左右脚落脚范围
分辨率:0.05 ~ 0.10 m

如果高度 scan 太稀疏,台阶边缘会被漏掉。

3. feet clearance:爬楼梯需要,但不能无限奖励

和平地不同,爬楼梯必须鼓励摆动腿抬高,否则脚会撞台阶立面。

但 clearance reward 最忌讳写成:

脚越高 reward 越大

这样 policy 很容易学成夸张高抬腿,速度慢、能耗大、真机危险。

推荐写法:目标高度,而不是越高越好

swing = foot_not_in_contact
target_clearance = terrain_height_under_foot + margin
err = foot_z - target_clearance
reward_clearance = exp(-err^2 / sigma) * swing

对于楼梯,target_clearance 最好不是固定值,而是跟地形高度相关:

目标脚高 = 当前/前方地形高度 + 安全余量

安全余量可以先从:

3 ~ 8 cm

开始试。

如果没有足端目标高度怎么办

可以先用简化版:

reward_clearance = exp(-(foot_height_in_base_frame - target)^2 / sigma) * swing * moving

但这对不同台阶高度泛化会差一些。

4. feet_air_time:爬楼梯可以比平地更重要,但要门控

爬楼梯时脚需要离地一段时间完成跨台阶,所以 feet_air_time 可以保留。

但要注意:

  • 低速/站立时不要奖励原地抬脚;
  • 离地太久不应该继续加奖励;
  • 上楼和下楼的合适 air time 不同;
  • 只奖励 first contact 通常比每步持续奖励更稳。

推荐调法

feet_air_time = 0.2 ~ 0.6  # 起步范围,按量级看曲线

并加门控:

moving = norm(command_xy) > 0.15
reward_air_time *= moving
reward_air_time = clamp(reward_air_time, max=max_bonus)

如果出现“楼梯上高抬腿但前进慢”,降低 air time,增强 velocity tracking 和 action cost。

如果出现“脚总撞台阶”,不要只加 air time,更应该加 terrain-aware clearance。

5. collision / stumble / undesired contacts:爬楼梯的核心安全项

楼梯任务里,碰撞惩罚比平地更关键。

需要区分:

允许:足端接触台阶平面
惩罚:脚撞台阶立面、大腿/小腿/机身碰撞
终止:base/body 严重碰撞或翻倒

1)undesired contacts

Isaac Lab rough cfg 中有:

undesired_contacts = RewTerm(
weight=-1.0,
body_names=".*THIGH",
threshold=1.0,
)

爬楼梯建议把 thigh / calf / base 的非期望接触都监控起来。

undesired_contacts:
base: terminate or strong penalty
thigh/calf: penalty
foot: allowed

2)feet_stumble:防止脚撞立面

legged_gym 里有 feet_stumble 思路:如果足端水平接触力远大于竖直接触力,说明可能在撞垂直面。

norm(contact_force_xy) > k * abs(contact_force_z)

楼梯上这个项很有用,因为脚撞台阶立面时水平冲击会明显变大。

建议:

feet_stumble = -0.2 ~ -1.0

如果这个项太强,机器人可能不敢靠近台阶;要和 clearance / curriculum 一起调。

3)base contact termination

机身碰楼梯通常应该直接 reset。

base_contact -> done

否则 policy 可能学到“用肚子蹭上去”。

6. base height / orientation:身体要跟着台阶走,不是平地高度固定

平地里 base_height 可以设固定目标,但爬楼梯时地形高度在变化。

如果仍然用固定世界高度目标,机器人上楼时会被错误惩罚。

推荐:相对地形高度

base_height_relative = base_z - terrain_height_under_base
penalty = (base_height_relative - target)^2

也就是身体高度目标应该相对于脚下/身体下方地形,而不是世界坐标固定 z。

orientation 不要过强

楼梯上身体可能需要轻微 pitch 调整。orientation / flat_orientation_l2 太强,会让机器人不愿意前倾或调整姿态。

建议:

平地:orientation 可以强一点
楼梯:orientation 适中,重点惩罚翻滚/大倾角,而不是要求绝对水平

可以把 roll 和 pitch 分开:

roll 稳定更重要
pitch 可允许小范围变化

7. velocity tracking:爬楼梯不要一开始追高速

如果速度跟踪奖励太强,policy 会为了追速度冲台阶,导致撞击、跳步、接触力过大。

推荐命令范围

上楼早期:

lin_vel_x = [0.1, 0.4]
lin_vel_y = [0.0, 0.0] 或很小
ang_vel_yaw = [0.0, 0.0] 或很小

稳定后再扩:

lin_vel_x = [0.0, 0.8]
lin_vel_y = [-0.2, 0.2]
ang_vel_yaw = [-0.3, 0.3]

爬楼梯初期不建议混太多横向速度和转向,否则问题很难定位。

8. contact forces:下楼尤其重要

下楼时最容易出现:

  • 前脚重重砸地;
  • base 俯冲;
  • 接触力尖峰很大;
  • 真机冲击大,电机和减速器压力大。

所以建议打开:

feet_contact_forces

逻辑:只惩罚超过阈值的接触力。

penalty = sum(clip(norm(contact_force) - max_contact_force, min=0))

不要惩罚所有接触力,否则机器人会不敢落脚。

9. action_rate / dof_acc / torques:最后用来收敛动作质量

爬楼梯需要足够大的动作幅度,所以动作代价不能太早太强。

推荐顺序:

先解决能不能上楼
再解决是否自然、省力、平滑

调参建议

action_rate = -0.01 ~ -0.03
dof_acc = -2.5e-7 起步,小步增加
torques = -1e-5 起步,小步增加

如果机器人脚抬不起来,先不要加大这些惩罚。

如果机器人能上楼但动作抽搐,再增加 action_rate / dof_acc。

10. 推荐 reward 配方:上楼 debug 起点

下面是一个偏工程 debug 的起点,不是标准答案:

class rewards:
class scales:
# task
tracking_lin_vel = 1.0
tracking_ang_vel = 0.2

# terrain-aware stepping
feet_clearance = 0.5 # 需要自定义,建议目标高度型
feet_air_time = 0.25
feet_stumble = -0.5
feet_slide = -0.05
feet_contact_forces = -0.01

# stability
lin_vel_z = -1.0 # 不要把上楼必要的 z 运动全压死
ang_vel_xy = -0.05
orientation = -0.5 # 楼梯上别像平地一样过强
base_height = -0.5 # 必须相对地形高度

# safety
collision = -1.0
undesired_contacts = -1.0
termination = -0.0

# smoothness / energy
torques = -1e-5
dof_acc = -2.5e-7
action_rate = -0.01

如果使用 Isaac Lab 风格,可以对应到:

track_lin_vel_xy_exp
track_ang_vel_z_exp
feet_air_time
undesired_contacts
lin_vel_z_l2
ang_vel_xy_l2
dof_torques_l2
dof_acc_l2
action_rate_l2
flat_orientation_l2 # 楼梯上谨慎使用

并额外自定义 terrain-aware feet_clearance、feet_stumble、feet_slide。

11. 推荐训练流程

Phase 1:低台阶,只上楼

step_height: 3~8 cm
step_width: 0.35~0.40 m
lin_vel_x: 0.1~0.3 m/s
不加横移,不加转向

目标:脚能稳定抬过台阶,机身不碰撞。

Phase 2:增加台阶高度和随机起点

step_height: 5~15 cm
随机 spawn phase
随机 friction / mass / COM

目标:不靠固定节奏死记硬背。

Phase 3:混入下楼

stairs up + stairs down
降低速度范围
增强 contact force penalty

目标:下楼不砸地、不俯冲。

Phase 4:扩展速度和转向

lin_vel_y 小范围打开
ang_vel_yaw 小范围打开
楼梯宽度/高度随机化

目标:更接近真实部署。

12. 看曲线时重点看什么

不要只看总 reward,爬楼梯一定要看分项和视频。

关键分项

rew_tracking_lin_vel:是否真的前进
rew_feet_clearance:是否过高或长期饱和
rew_feet_air_time:是否鼓励长时间悬空
penalty_feet_stumble:是否频繁撞立面
penalty_undesired_contacts:大腿/机身是否碰撞
penalty_contact_forces:是否砸地
penalty_action_rate / dof_acc:是否抽搐
terrain_level:课程是否在提升
reset reason:是 base contact、timeout 还是姿态失败

视频检查清单

脚是否踩在台阶平面,而不是边缘
前脚是否撞立面
身体是否跟随楼梯升高
下楼是否砸地
是否用腹部/小腿蹭台阶
是否只在固定起点有效

常见问题与调参方向

1)脚总撞台阶立面

优先调:

增加 terrain-aware feet_clearance
增加 feet_stumble penalty
降低初始台阶高度
增加 height scan 前方覆盖

2)脚抬太高、动作夸张

优先调:

clearance 改成目标高度型
降低 feet_air_time / clearance 权重
增加 action_rate / dof_acc
增加 torques 小权重

3)机身碰台阶

优先调:

base_contact termination
base_height relative to terrain
降低速度命令
增强 undesired_contacts

4)上楼能走,下楼摔

优先调:

单独训练/评估 stairs down
增加 feet_contact_forces penalty
降低 lin_vel_x
允许更保守的姿态调整

5)仿真能走,真机不稳

优先查:

台阶尺寸是否随机化
摩擦/质量/COM randomization 是否足够
接触力是否过大
动作频率和 PD 参数是否真机一致
height scan 是否来自真实可用传感器

总结

爬楼梯不是简单把平地 reward 里的 feet_air_time 调大。更靠谱的思路是:

terrain curriculum 先让任务可学
height scan 让 policy 看见台阶
clearance 让脚能跨过台阶
stumble/collision 防止撞台阶和蹭台阶
base height/orientation 让身体稳定跟随地形
contact force/action cost 让动作能上真机

我的建议是先做一个很小的上楼任务:低台阶、低速、无横移、无转向。等它稳定后,再逐步增加台阶高度、随机起点、下楼、转向和 sim2real 随机化。

参考资料

  • Nikita Rudin et al., Learning to Walk in Minutes Using Massively Parallel Deep Reinforcement Learning, CoRL 2021 / arXiv:2109.11978.
  • leggedrobotics/legged_gym:rough terrain locomotion task、terrain curriculum、reward scale 机制。
  • legged_gym/utils/terrain.py:pyramid_stairs_terrain、step_width=0.31、step_height=0.05+0.18*difficulty、stairs up/down terrain generation。
  • legged_gym/envs/base/legged_robot_config.py:rough terrain 的 reward scales、height measurements、terrain proportions。
  • legged_gym/envs/base/legged_robot.py:feet_air_time、stumble、base_height、feet_contact_forces、tracking_lin_vel 等 reward 实现。
  • Isaac Lab locomotion velocity rough config:terrain generator、height scanner、contact sensor、feet air time、undesired contacts、terrain levels curriculum。
知识共享许可协议