Isaac Lab四足机器人强化学习:奖励函数设计的5个实战技巧
2026/9/18 4:11:19 网站建设 项目流程

Unitree B2W 的强化学习训练真正跑通以后,我最大的感受是:Isaac Lab 的并行采样确实快,但真正决定四足机器人策略上限的,往往是奖励函数里那些看起来不起眼的项。这篇文章不讲复杂数学,只讲我从轮足机器人 B2W 迁移到通用四足模型时反复验证过的 5 个实战技巧,适合正在用 Isaac Lab 做四足机器人控制器、又被奖励调参搞到头大的朋友。

先说清楚这篇内容适合谁来读:如果你已经在 Isaac Lab 里跑过 Unitree 系列或其他四足机器人,但训练出来的策略要么走不起来、要么走了几步就摔,或者动作看起来非常僵硬、像在抽搐,那这篇文章应该能帮到你。如果你只是刚开始接触强化学习和四足机器人,里面的大部分经验也可以直接套用,只是建议你先跑通 Isaac Lab 自带示例,再拿这些技巧去改自己的任务。

1. 先别急着写奖励:B2W的轮足混合构型决定了很多设计的默认值

1.1 B2W到底特殊在哪里

我最早接触 Unitree B2W 时,第一反应是把它当成“多了四个轮子的四足机器人”,后来才发现这个简化会让奖励函数设计走很多弯路。B2W 的四个轮子安装在腿的末端,相当于每条腿末端多了一个连续旋转关节。这个构型带来的结果是:轮子贡献前进速度,腿部关节贡献机身高度和姿态,两者职责完全不同。

这和纯四足有很大区别。纯四足机器人的前进速度完全依赖腿部关节的周期性摆动,落脚点、步态相位、足端轨迹都会直接影响速度。B2W 则更像一个“四条腿撑起来的轮式底盘”,在平坦地面上最省力、最高效的运动方式是轮子持续转动,腿只负责维持车身姿态和离地间隙。

所以写奖励函数前,一定要记住一个原则:B2W 的速度控制入口主要在轮子上,姿态控制入口在腿部关节上。如果奖励函数不区分这两条通路,策略很可能发现一个“作弊解”:用力蹬腿也能让机器人移动,但步态难看、能耗巨大、姿态抖动,甚至把轮子完全忽略掉。

1.2 在Isaac Lab里动手前必须确认的三件事

我在 Isaac Lab 里接 B2W 模型时,最先踩的坑不是奖励函数,而是动作空间和控制接口没对齐。很多新手直接把网上四足示例的关节位置动作空间拿过来套,结果轮子关节也被当成了“角度位置关节”来控制。轮子本质上是连续旋转关节,位置控制会非常别扭,策略可能学会把轮子来回摆动,而不是持续滚动。

动手前我会按下面三件事检查环境配置:

  • 关节定义:确认机器人文件里哪些关节是腿部位置关节,哪些是轮子连续关节。这个信息决定了动作空间怎么拆分。
  • 动作空间:腿部关节建议用位置控制或者速度控制,轮子建议用速度控制。两者可以组成混合动作空间,而不是把所有关节塞进同一个动作接口。
  • 控制频率:轮足机器人的轮子转速往往很高,接触状态变化快,如果仿真步长太大,奖励会被接触力噪声严重污染。我一般让仿真频率保持在 200Hz 以上,策略控制频率 50Hz 左右,这样奖励曲线更容易看出真实趋势。

另外还要确认默认姿态和关节偏移。B2W 站直时腿的关节角度是多少、机身离地多高,这些默认值会影响初始状态。如果初始状态和训练目标的差异太大,奖励函数还没来得及发挥作用,终止条件就先触发了。

1.3 为什么奖励函数要跟着控制接口走

很多人在 Isaac Lab 里调试奖励函数,习惯从数学公式出发,先想“我要让机器人速度多快、姿态多稳”,然后直接堆奖励项。这个思路没问题,但容易忽略一个关键点:同一个“速度目标”,在位置控制接口和速度控制接口下的实现方式完全不同。

位置控制接口下,策略输出的是目标关节角度,机器人移动靠的是关节角度的反复变化,所以奖励函数里通常需要配合“关节摆动幅度”“步态相位”“足端轨迹”这些隐含信息。速度控制接口下,策略输出的是关节角速度或轮速,机器人移动靠的是持续的速度指令,奖励函数更需要关注的是实际速度和目标速度之间的偏差、加速度突变。

如果控制接口和奖励函数不匹配,训练能收敛,但收敛出来的动作往往是扭曲的。比如你用位置控制接口,却只给一个“机器人前进速度越高越好”的奖励,策略很容易学会高频抖动腿部,让人误以为它“很努力”,但实际上并没有产生稳定的步态。

2. 技巧一、二:速度跟踪和姿态稳定要拆开设计,不能“一把梭”

2.1 技巧一:线速度奖励按X、Y、偏航角分开建模

我见过很多四足机器人示例里的速度跟踪奖励,直接写成:

lin_vel_err = torch.sqrt(torch.sum((lin_vel - cmd_vel) ** 2, dim=1)) reward_vel = torch.exp(-lin_vel_err)

这个写法在简单仿真里能跑,但在 B2W 和更复杂的四足任务里非常容易出问题。原因是它把 X 方向速度误差、Y 方向速度误差和偏航角速度误差全部揉成了一个标量,策略无法判断哪个方向更重要。结果经常是:机器人斜着走也能拿到不错的奖励,因为三个方向的误差被平均掉了,看起来每个方向都差一点,但总和不大。

我的做法是把线速度拆成三个独立分量,每个分量单独计算误差,再用指数函数转换:

@torch.jit.script def track_lin_vel( root_states: torch.Tensor, command: torch.Tensor, vel_sigma: float, ) -> torch.Tensor: # 实际线速度:世界系 x y,偏航角速度 lin_vel_x = root_states[:, 7] lin_vel_y = root_states[:, 8] yaw_rate = root_states[:, 10] # 目标速度 cmd_x = command[:, 0] cmd_y = command[:, 1] cmd_yaw = command[:, 2] # 分量误差 err_x = torch.square(lin_vel_x - cmd_x) err_y = torch.square(lin_vel_y - cmd_y) err_yaw = torch.square(yaw_rate - cmd_yaw) # 分开放入高斯型奖励 reward_x = torch.exp(-err_x / (vel_sigma * vel_sigma)) reward_y = torch.exp(-err_y / (vel_sigma * vel_sigma)) reward_yaw = torch.exp(-err_yaw / (vel_sigma * vel_sigma)) return reward_x + reward_y + reward_yaw

其中最容易被忽略的是坐标框架。命令通常在世界坐标系下给出,而机器人本体测到的速度可能来自本体坐标系,两者不统一时,奖励函数相当于在训练一个带系统性误差的控制器。我的习惯是先在观测或状态接口里统一成同一个坐标系,再进奖励函数。

2.2 技巧二:姿态奖励要加相位处理,并区分“水平”与“倾斜地形”

四足机器人训练里最常见的姿态奖励是“让机身滚转角接近0、俯仰角接近0”。这个目标在纯平地上没问题,但到了轮足机器人身上就要小心了。

B2W 在转弯时,机身会产生自然侧倾,就像摩托车压弯一样。如果你用一个很严格的水平姿态奖励,策略会把转弯速度压得很低,因为它发现“只要不转弯,姿态奖励就不会掉”。这是典型的奖励函数和任务目标打架:你想让机器人既转得快又转得稳,但奖励函数只奖励了“稳”,没有奖励“转得快”。

所以我在设计姿态奖励时,通常先做一个相位处理:

# 目标姿态角不再固定为0,而是根据转向速度给一个合理倾角 target_roll = 0.0 target_pitch = 0.0 # 把角度误差转换到[-pi, pi]区间再计算 roll_err = wrap_to_pi(roll - target_roll) pitch_err = wrap_to_pi(pitch - target_pitch) reward_attitude = torch.exp(-(roll_err**2 + pitch_err**2) / attitude_sigma**2)

另外,roll 和 pitch 是对机身坐标系的姿态角,但如果在斜坡或者随机地形上训练,绝对水平并不是唯一正确的目标。更好的做法是把姿态奖励的目标值设成“当前地形坡度对应的期望姿态”,或者干脆只惩罚“姿态角变化速度”,让它根据地形自然适应。

2.3 速度奖励和姿态奖励耦合时的权重顺序

速度跟踪和姿态稳定不是两件独立的事。在 B2W 这种轮足机器人上,高速前进时姿态略微倾斜是正常的,低速时姿态则需要更稳定。如果把速度项和姿态项设成固定比例,策略会陷入两难。

我的经验是先确定速度项的权重,再在这个基础上给姿态项设一个随速度变化的权重:

  • 当目标速度低于 0.3m/s 时,姿态奖励权重提高,让机器人站得住、站得稳。
  • 当目标速度高于 0.8m/s 时,姿态奖励权重适当降低,给速度项让路。
  • 当机器人实际速度离目标速度误差很大时,优先优化速度误差,姿态奖励退到辅助位置。

这里的配比可以在课程学习里动态调整,也可以在奖励函数内部加一个类似“速度误差大时降低姿态硬惩罚”的平滑系数。直接改权重值当然也可以,但如果每次训练都要手动调一遍,迭代效率会很低。

3. 技巧三、四:动作平滑项和权重归一化,是稳定训练的两板斧

3.1 技巧三:动作增量惩罚和绝对动作惩罚必须拆开

我在调试 B2W 时发现,单纯加一个“动作越大惩罚越大”的项,会让训练变得非常奇怪。因为轮子本来就是靠持续旋转来前进的,如果惩罚绝对轮速,策略就学会了不转轮子,靠腿爬。这个动作在仿真里也能往前走一点,但完全不符合我们想要的轮足运动方式。

正确的做法是把两类惩罚拆开:

  • 动作增量惩罚:惩罚相邻两个决策时刻动作的变化量,目的是抑制高频抖动和关节速度突变。
  • 绝对动作惩罚:惩罚动作距离某个“合理基准”的偏移,比如腿部目标关节角度距离默认站姿角度不能太远,轮子速度不能没有上限。

动作增量惩罚的典型实现是:

action_rate = env.action_manager.action - env.action_manager.prev_action penalty = torch.sum(torch.square(action_rate), dim=-1)

这个项对四足机器人非常重要。如果不加,策略很容易输出高频震荡的关节指令,仿真里表现得像“帕金森式抖动”,部署到真机上不仅步态很差,还容易损坏电机。

绝对动作惩罚则要分动作类型:腿部关节惩罚“当前目标角度与默认角度的偏差”,轮子则不要直接惩罚轮速本身,而是惩罚“轮速超出设定上限的部分”。这样既不会阻碍轮子正常工作,又能防止策略输出一些离谱的轮速指令。

3.2 技巧四:先把所有奖励项缩放到可比数量级,再谈权重微调

奖励函数里最难调的不是每一项的公式,而是不同项的尺度差异。我见过很多训练失败的案例,问题不在奖励设计思路上,而在奖励项之间的数量级差了上百倍。

举个例子,速度跟踪奖励如果采用高斯型,误差为 0.1m/s 时奖励值大约是 0.98,姿态奖励在角度误差为 0.01rad 时可能也是 0.99,两者看起来差不多。但动作惩罚项如果直接算关节力矩的平方,数值可能是几千甚至几万。这个时候,不管你怎么调整其他项,训练都会被力矩惩罚项主导。

我的习惯是先给每一项做一次“常见数值范围估算”,把所有项统一成量级接近的数值,再设置权重。这个过程中最重要的不是精确计算,而是先消除明显失衡。

奖励项常见原始数值范围建议变换方式初始权重
速度跟踪0.1 到 1.0按分量做高斯衰减1.0
姿态稳定0.01 到 0.1 弧度按角度误差做高斯衰减0.5
动作增量1 到 100除以动作维度后取平方均值-0.01
关节力矩10 到 10000除以关节数并取均值-1e-4
机身高度保持0 到 0.5 米按高度误差做高斯衰减0.3

这个表并不精确,但它代表了一种重要思路:先把每一项的“体量”对齐,再去做权重微调。否则你调的其实不是权重,而是在和各项自身的数值尺度搏斗。

3.3 一组可参考的奖励项配置

在 Isaac Lab 的 Manager 风格配置里,奖励项通常写成一个字典。下面是我在类似任务里常用的一组初始配置,具体权重需要根据机器人参数微调:

from isaaclab.managers import RewardTermCfg as RewTerm rewards = { "track_lin_vel": RewTerm( func=track_lin_vel, weight=1.0, params={"vel_sigma": 0.5}, ), "track_ang_vel": RewTerm( func=track_ang_vel, weight=0.5, params={"ang_sigma": 0.25}, ), "orientation": RewTerm( func=orientation_penalty, weight=-0.2, params={}, ), "base_height": RewTerm( func=base_height_l2, weight=-0.5, params={"target_height": 0.4}, ), "action_rate": RewTerm( func=action_rate_l2, weight=-0.005, params={}, ), "joint_torque": RewTerm( func=joint_torque_l2, weight=-1e-4, params={}, ), }

这段配置演示的核心是:奖励项公式、参数、权重三者分离。调参时不要每次都改公式,而是先改 params 里的尺度参数,再改 weight。这样训练日志里的每一项变化更可控,也更容易定位问题。

4. 技巧五:课程学习与域随机化,相当于给奖励函数兜底

4.1 奖励函数没问题,训练仍然失败时先检查什么

有段时间我特别迷信奖励函数,觉得只要奖励写得好,机器人就应该学会完美步态。后来发现,很多训练失败根本不是奖励不对,而是任务太难,策略在训练一开始就掉进了局部最优。

四足机器人强化学习最常见的新手期问题是“起步即摔”:机器人从初始状态开始,需要同时学会保持平衡、跟踪速度、避免摔倒,这个多目标问题在早期非常难。如果一上来就给机器人一个高速命令,哪怕奖励函数设计得再合理,策略也很难在随机初始化下找到正确的上升方向。

所以后来我养成了一个习惯:在否定某个奖励函数之前,先检查命令速度范围、初始位形方差、地形随机程度这些训练设置。很多时候把命令速度从 1.0m/s 降到 0.2m/s,再把地形改成完全平坦,同一个奖励函数马上就能训练出像样的步态。

4.2 用课程学习解决新手期局部最优

课程学习的思路很朴素:让机器人从简单的任务开始,成功后再逐步增加难度。我在 B2W 任务里通常设计三个维度的课程:

  • 速度课程:从低速目标开始,先让命令速度在 0.1 到 0.3m/s 之间随机,等策略稳定后再逐步提升到更高速度。
  • 地形课程:先在平整地面训练,等步态成型后再加入坡度、随机高度差、摩擦变化。
  • 扰动课程:先不加随机推力,等策略稳定后,再加入侧向推力干扰。

在 Isaac Lab 里,课程学习可以放在环境配置里,依靠回合结束时的表现决定是否进入下一档难度。一个简单的实现思路是每隔一定训练步数检查一次平均回报,如果连续几个评估窗口都超过阈值,就把命令速度上限提高一档。

这个做法看起来绕过了“奖励函数不完美”的问题,但它实际上是奖励函数训练的助推器。奖励函数定义“什么是好行为”,课程学习决定“从哪一种难度的好行为开始学”。两者配合,比单纯堆奖励项有效得多。

4.3 域随机化的参数与开关位置

域随机化也是一种兜底手段。它让策略在训练中见过足够多变的动力学参数,部署时不会因为仿真和真实环境的微小差异而崩掉。

我在轮足和四足任务里常用的随机化对象包括:

  • 摩擦系数:修改腿末端与地面的摩擦,避免策略过拟合某个接触特性。
  • 质心位置:给机身质心加一个小的随机偏移,模拟电池或负载位置不同。
  • 关节电机力矩:在电机最大输出附近加噪声,模拟真实驱动器的响应差异。
  • 控制延迟:给动作加一两个控制步的延迟,增强策略抵抗通讯延时的能力。

需要特别注意:域随机化参数不要一开始就开得太猛。我的经验是先固定奖励函数,再用一个中等级别的随机化训练出基线,然后逐步加大随机化强度。否则你很难判断训练失败究竟是因为奖励设计有问题,还是因为随机化参数太激进。

5. 基于Isaac Lab的奖励函数调试链路与踩坑记录

5.1 训练日志里真正值得盯的指标

很多人训练时只看 total reward,这个习惯我强烈建议改掉。总奖励是多个奖励项的加权和,它上升了不代表策略行为变好,因为策略可能找到了一个“欺骗性局部最优”,某个奖励项吃得很满,其他项全部崩掉。

我自己训练时会在日志里单独输出这几类指标:

  • 平均速度误差:看策略有没有真的在跟踪命令,而不是只在原地折腾。
  • 机身高度和姿态角:看机器人是不是经常摔倒、机身是否过低。
  • 动作增量均值:看策略输出是否平滑,是否出现高频抖动。
  • 终止原因统计:看是因为摔倒终止、超时还是其他原因。

在 Isaac Lab 里,可以通过自定义 extras 或直接打印奖励子项来监控这些值。不要觉得麻烦,这个监控过程能帮你省下好几轮重复训练的时间。

5.2 三个导致奖励“短路”的典型情况

第一种是“跳跃式刷高度奖励”。如果奖励函数里有“机身高度越高越好”,策略很容易学会快速蹬地跳起,拿到高度奖励后再落回地面。看起来平均高度不错,但实际步态完全没有前进能力。解决方法是把高度奖励设计成“围绕目标高度的高斯型”,而不是单调增加。

第二种是 B2W 独有的“腿部助推替轮子”。由于速度奖励只关心机器人整体速度,策略会发现用腿蹬地也能让机身移动,于是轮子全程不转,腿却像青蛙一样乱蹬。解决方法是把轮速动作单独拿出来做激励,或者对腿部动作增量给一个更高的惩罚。

第三种是“原地站立卡死”。当终止条件对摔倒惩罚很重,而速度命令又比较低时,策略会认为“不动就不会摔”,从而找到一个局部最优:完全静止。这时你需要引入一个速度误差的连续惩罚,或者将命令速度低于某阈值的时段单独处理,避免机器人通过“偷懒”来规避风险。

5.3 从B2W迁移到通用四足机器人的奖励函数改造清单

最后聊一下标题里的“从 B2W 到四足机器人”。我把 B2W 上验证过的奖励思路迁移到纯四足时,通常会做这几个改造:

  • 动作空间:把轮子速度动作替换成腿部关节位置或速度动作,其余腿部关节结构基本保留。
  • 速度奖励:保留按 X、Y 和偏航角拆分的思路,但对纯四足来说,线速度误差的 sigma 要适当调大,因为纯四足步态本身就有速度波动。
  • 姿态奖励:纯四足的姿态稳定性要求更高,权重可以比轮足调得更大一些,但因为步态天然存在周期性俯仰和侧倾,sigma 也要留余量。
  • 补充足端轨迹奖励:纯四足对落脚点更敏感,可以增加足端离地高度、支撑相切换相关的奖励项,帮助策略形成清晰的步态相位。
  • 终止条件:轮足机器人可以接受短暂的低头、弯腰,纯四足一旦机身高度过低很可能摔倒,所以终止条件要更严格。

这套迁移逻辑最核心的地方在于:奖励函数的骨架不要大改,优先调整 sigma、权重和动作空间。骨架代表的是“任务目标”,那些可调参数代表的才是“机器人特性”。把两者分开管理,一个项目的奖励调参经验才能复用给下一个项目。

在我自己实际使用中,最值钱的习惯并不是把奖励函数调到完美,而是始终保持“先监控、再微调、最后才改结构”的顺序。B2W 让我深刻体会到,轮足混合构型下奖励项之间非常容易互相打架,而纯四足只是换了一种方式在打架。只要你的调试链路清晰,哪怕每一项权重都不完美,也能快速定位问题,让策略沿着正确的方向收敛。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询