四足机器人爬楼梯: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_clearancefeet_stumblefeet_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.pypyramid_stairs_terrainstep_width=0.31step_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.pyfeet_air_timestumblebase_heightfeet_contact_forcestracking_lin_vel 等 reward 实现。
  • Isaac Lab locomotion velocity rough config:terrain generator、height scanner、contact sensor、feet air time、undesired contacts、terrain levels curriculum。
algorithms axis-angle bang-bang bode calibration chrome cmake cmakelists cnn colcon conan control cpp cpu d435i data_struct db design-pattern dots economics eigen factory-pattern fcpx figure finance forge fov gazebo gdb git gnu ibus interest isaac gym isaac lab isaaclab kdl latex launch learning-notes legged locomotion legged-robot life linux linux-kernel mac math matlab matrix memory mlp money motion-control motor moveit mpc mujoco network ocs2 ode operator optimal algorithm optimal-control perf performance personal-finance ppo profiling python qos quadrotor realsense reinforcement learning reward tuning rnn robot robotics ros ros2 rtb security shell simulation socket stairs stl tcp-ip thread tools twist ubuntu uml unitree urdf vae valgrind vcxsrv velocity vim web wifi work wsl 中文输入 交叉编译 依赖管理 分支管理 四足机器人 实验诊断 强化学习 机器人视觉 构建系统 深度学习 深度相机 点云 版本控制 神经网络 训练曲线 输入法 配置类 飞控
知识共享许可协议