强化学习人形机器人奖励函数分析

1. 代码引用

代码引用自框架legged_gym

    #------------ reward functions----------------
    def _reward_lin_vel_z(self):
        # Penalize z axis base linear velocity
        return torch.square(self.base_lin_vel[:, 2])
    
    def _reward_ang_vel_xy(self):
        # Penalize xy axes base angular velocity
        return torch.sum(torch.square(self.base_ang_vel[:, :2]), dim=1)
    
    def _reward_orientation(self):
        # Penalize non flat base orientation
        return torch.sum(torch.square(self.projected_gravity[:, :2]), dim=1)

    def _reward_base_height(self):
        # Penalize base height away from target
        base_height = torch.mean(self.root_states[:, 2].unsqueeze(1) - self.measured_heights, dim=1)
        return torch.square(base_height - self.cfg.rewards.base_height_target)
    
    def _reward_torques(self):
        # Penalize torques
        return torch.sum(torch.square(self.torques), dim=1)

    def _reward_dof_vel(self):
        # Penalize dof velocities
        return torch.sum(torch.square(self.dof_vel), dim=1)
    
    def _reward_dof_acc(self):
        # Penalize dof accelerations
        return torch.sum(torch.square((self.last_dof_vel - self.dof_vel) / self.dt), dim=1)
    
    def _reward_action_rate(self):
        # Penalize changes in actions
        return torch.sum(torch.square(self.last_actions - self.actions), dim=1)
    
    def _reward_collision(self):
        # Penalize collisions on selected bodies
        return torch.sum(1.*(torch.norm(self.contact_forces[:, self.penalised_contact_indices, :], dim=-1) > 0.1), dim=1)
    
    def _reward_termination(self):
        # Terminal reward / penalty
        return self.reset_buf * ~self.time_out_buf
    
    def _reward_dof_pos_limits(self):
        # Penalize dof positions too close to the limit
        out_of_limits = -(self.dof_pos - self.dof_pos_limits[:, 0]).clip(max=0.) # lower limit
        out_of_limits += (self.dof_pos - self.dof_pos_limits[:, 1]).clip(min=0.)
        return torch.sum(out_of_limits, dim=1)

    def _reward_dof_vel_limits(self):
        # Penalize dof velocities too close to the limit
        # clip to max error = 1 rad/s per joint to avoid huge penalties
        return torch.sum((torch.abs(self.dof_vel) - self.dof_vel_limits*self.cfg.rewards.soft_dof_vel_limit).clip(min=0., max=1.), dim=1)

    def _reward_torque_limits(self):
        # penalize torques too close to the limit
        return torch.sum((torch.abs(self.torques) - self.torque_limits*self.cfg.rewards.soft_torque_limit).clip(min=0.), dim=1)

    def _reward_tracking_lin_vel(self):
        # Tracking of linear velocity commands (xy axes)
        lin_vel_error = torch.sum(torch.square(self.commands[:, :2] - self.base_lin_vel[:, :2]), dim=1)
        return torch.exp(-lin_vel_error/self.cfg.rewards.tracking_sigma)
    
    def _reward_tracking_ang_vel(self):
        # Tracking of angular velocity commands (yaw) 
        ang_vel_error = torch.square(self.commands[:, 2] - self.base_ang_vel[:, 2])
        return torch.exp(-ang_vel_error/self.cfg.rewards.tracking_sigma)

    def _reward_feet_air_time(self):
        # Reward long steps
        # Need to filter the contacts because the contact reporting of PhysX is unreliable on meshes
        contact = self.contact_forces[:, self.feet_indices, 2] > 1.
        contact_filt = torch.logical_or(contact, self.last_contacts) 
        self.last_contacts = contact
        first_contact = (self.feet_air_time > 0.) * contact_filt
        self.feet_air_time += self.dt
        rew_airTime = torch.sum((self.feet_air_time - 0.5) * first_contact, dim=1) # reward only on first contact with the ground
        rew_airTime *= torch.norm(self.commands[:, :2], dim=1) > 0.1 #no reward for zero command
        self.feet_air_time *= ~contact_filt
        return rew_airTime
    
    def _reward_stumble(self):
        # Penalize feet hitting vertical surfaces
        return torch.any(torch.norm(self.contact_forces[:, self.feet_indices, :2], dim=2) >\
             5 *torch.abs(self.contact_forces[:, self.feet_indices, 2]), dim=1)
        
    def _reward_stand_still(self):
        # Penalize motion at zero commands
        return torch.sum(torch.abs(self.dof_pos - self.default_dof_pos), dim=1) * (torch.norm(self.commands[:, :2], dim=1) < 0.1)

    def _reward_feet_contact_forces(self):
        # penalize high contact forces
        return torch.sum((torch.norm(self.contact_forces[:, self.feet_indices, :], dim=-1) -  self.cfg.rewards.max_contact_force).clip(min=0.), dim=1)


2. 奖励函数详解与数学建模

在机器人强化学习(RL)中,奖励函数的设计通常包含三个维度:任务追踪(Tracking)正则化/惩罚(Regularization/Penalties) 以及 步态/风格约束(Gait/Style)

以下是代码中各个奖励项的数学表达及其物理含义分析。

2.1 核心任务奖励 (Tracking Rewards)

此类奖励采用 高斯核(Gaussian Kernel) 形式,旨在最大化机器人对指令的跟随精度。

函数名数学表达式 (Reward)物理含义
_reward_tracking_lin_velrt=exp⁡(−∣vcmdxy−vbasexy∣2σtrack)r_t = \exp\left(-\frac{| \mathbf{v}_{cmd}^{xy} - \mathbf{v}_{base}^{xy} |^2}{\sigma_{track}}\right)rt=exp(σtrackvcmdxyvbasexy2)线速度追踪vcmdxy\mathbf{v}_{cmd}^{xy}vcmdxy 为指令速度,σ\sigmaσ 为带宽参数。当误差为 0 时奖励为 1。
_reward_tracking_ang_velrt=exp⁡(−(ωcmdz−ωbasez)2σtrack)r_t = \exp\left(-\frac{(\omega_{cmd}^{z} - \omega_{base}^{z})^2}{\sigma_{track}}\right)rt=exp(σtrack(ωcmdzωbasez)2)角速度追踪。鼓励机器人按照给定的偏航角速度(Yaw)转向。

2.2 惩罚与正则化项 (Penalties & Regularization)

此类通常采用 L2 范数(平方和) 形式,在总奖励计算中通常会被赋予负权重,作为 Cost/Penalty 使用,用于约束能量和保持稳定。

函数名数学表达式 (Penalty/Cost)物理含义
_reward_lin_vel_zpt=(vzbase)2p_t = (v_z^{base})^2pt=(vzbase)2限制垂直速度。防止机器人底座上下剧烈震荡。
_reward_ang_vel_xypt=(ωxbase)2+(ωybase)2p_t = (\omega_x^{base})^2 + (\omega_y^{base})^2pt=(ωxbase)2+(ωybase)2限制横滚/俯仰。保持躯干水平,防止翻车。
_reward_orientationpt=∣gprojxy∣2p_t = | \mathbf{g}_{proj}^{xy} |^2pt=gprojxy2姿态平衡。重力向量在体坐标系下的 xy 分量应为 0(即重力应垂直向下)。
_reward_torquespt=∑iτi2p_t = \sum_{i} \tau_i^2pt=iτi2最小化力矩。降低能耗,防止电机过热,鼓励柔顺动作。
_reward_dof_velpt=∑iq˙i2p_t = \sum_{i} \dot{q}_i^2pt=iq˙i2关节速度阻尼。防止动作过快,增加系统稳定性。
_reward_action_ratept=∑i(at,i−at−1,i)2p_t = \sum_{i} (a_{t,i} - a_{t-1,i})^2pt=i(at,iat1,i)2动作平滑。惩罚控制信号的高频抖动,保护执行器。
_reward_collisionpt=∑I(∣Fcontact∣>0.1)p_t = \sum \mathbb{I}(|F_{contact}| > 0.1)pt=I(Fcontact>0.1)碰撞惩罚。非足部位置接触环境时给予惩罚。

2.3 约束与安全限制 (Soft Limits)

用于处理物理限制的软约束,形式通常为单边损失(Hinge Loss)。

  • 关节位置/速度/力矩限制
    pt=∑clip(∣x∣−xlimit,min⁡=0)p_t = \sum \text{clip}(|x| - x_{limit}, \min=0)pt=clip(xxlimit,min=0)
    当状态 xxx 超过设定的安全阈值 xlimitx_{limit}xlimit 时,开始计算惩罚。

2.4 步态塑形 (Gait Shaping)

  • _reward_feet_air_time: 鼓励脚在空中停留更长时间(迈大步),仅在脚触地瞬间给予奖励。
  • _reward_stand_still: 当速度指令极小时,惩罚关节偏离默认位置,强制机器人站立不动。

3. 奖励函数在 PPO 算法中的作用机制

PPO (Proximal Policy Optimization) 是一种 Actor-Critic 架构算法。奖励函数是整个学习过程的指挥棒。

3.1 Total Reward 的计算

在每一个时间步 ttt,各个子奖励项被加权求和:
rtotal,t=∑kwk⋅rk,tr_{total, t} = \sum_{k} w_k \cdot r_{k, t}rtotal,t=kwkrk,t

  • wk>0w_k > 0wk>0: 用于 Tracking 和 Gait 奖励(鼓励行为)。
  • wk<0w_k < 0wk<0: 用于 Penalties(抑制行为)。

3.2 数据流向分析

total_reward 在 PPO 中通过以下路径影响最终策略:

  1. 价值估计 (Critic Update):
    Critic 网络 Vϕ(s)V_\phi(s)Vϕ(s) 学习预测未来的累积回报(Return)。它通过最小化以下损失函数来更新:
    Lcritic=Et[(Vϕ(st)−Rt)2]L_{critic} = \mathbb{E}_t \left[ (V_\phi(s_t) - R_t)^2 \right]Lcritic=Et[(Vϕ(st)Rt)2]
    其中 RtR_tRt 是由 rtotalr_{total}rtotal 计算出的真实回报。

  2. 优势函数计算 (Advantage Estimation):
    算法利用 Generalized Advantage Estimation (GAE) 计算优势 A^t\hat{A}_tA^t
    A^t=δt+(γλ)δt+1+…\hat{A}_t = \delta_t + (\gamma \lambda)\delta_{t+1} + \dotsA^t=δt+(γλ)δt+1+
    其中 δt=rtotal,t+γV(st+1)−V(st)\delta_t = r_{total, t} + \gamma V(s_{t+1}) - V(s_t)δt=rtotal,t+γV(st+1)V(st)

    • 关键点rtotalr_{total}rtotal 直接决定了 δt\delta_tδt 的正负。如果 rtotalr_{total}rtotal 很高,A^t\hat{A}_tA^t 为正,表示当前动作优于平均水平。
  3. 策略更新 (Actor Update):
    Actor 网络 πθ\pi_\thetaπθ 的更新目标是最大化优势:
    θ←θ+α∇θ(min⁡(rt(θ)A^t,clip(… )A^t))\theta \leftarrow \theta + \alpha \nabla_\theta \left( \min(r_t(\theta)\hat{A}_t, \text{clip}(\dots)\hat{A}_t) \right)θθ+αθ(min(rt(θ)A^t,clip()A^t))

    • A^t>0\hat{A}_t > 0A^t>0(奖励高),PPO 增大该动作的概率。
    • A^t<0\hat{A}_t < 0A^t<0(奖励低/惩罚高),PPO 减小该动作的概率。

4. 数学特性深度分析:Square vs. Exp

通过分析代码,我们发现所有的奖励项主要归为两类数学形式:平方项 (Square)指数项 (Exp)。这种设计是现代机器人控制领域的标准范式。

4.1 形式对比

特性Square (平方形式)Exp (指数/高斯形式)
典型式子f(x)=x2f(x) = x^2f(x)=x2f(x)=exp⁡(−x2/σ)f(x) = \exp(-x^2 / \sigma)f(x)=exp(x2/σ)
代码体现torch.square(...)torch.exp(...)
主要用途惩罚项 (Penalties)任务奖励 (Rewards)
值域[0,+∞)[0, +\infty)[0,+)(0,1](0, 1](0,1]
梯度特性∇=2x\nabla = 2x=2x (随误差线性增大)∇∝x⋅e−x2\nabla \propto x \cdot e^{-x^2}xex2 (先增后减)

4.2 为什么这样设计?(优劣势分析)

A. 为什么任务项使用 Exp (指数)?

代码中的 _reward_tracking_... 使用了 Exp,这被认为是优于 Square 的选择,原因如下:

  1. 有界性与归一化 (Boundedness): Exp 函数将奖励限制在 [0,1][0, 1][0,1] 之间。这防止了特定任务的奖励数值过大(例如速度误差极大时),从而掩盖了其他辅助奖励的作用。
  2. 数值稳定性 (Stability):
    • 若使用 Square 作为奖励(负距离),当机器人完全失控时,误差可能无穷大,导致 LossLossLoss 爆炸,梯度更新过猛,由于 PPO 是 On-policy 算法,这会直接破坏策略网络。
    • 使用 Exp,当误差极大时,奖励趋近于 0,梯度也趋近于 0。这意味着网络会“忽略”那些极其糟糕的样本,而不是被其误导。
  3. 核宽可调 (σ\sigmaσ): 通过调节 tracking_sigma,可以直观地定义“什么是好的动作”。σ\sigmaσ 越小,对精度的要求越高。
B. 为什么惩罚项使用 Square (平方)?

代码中的 _reward_torques 等使用 Square,原因如下:

  1. 强约束力: Square 是凸函数,且其梯度随误差增大而线性增大。这意味着违规越严重,惩罚力度越狠
  2. 明确的优化方向: 对于力矩、关节速度等物理量,我们的目标是将其压得越低越好(接近0),Square 函数在 0 点附近有良好的导数性质,能有效地引导优化器。

4.3 结论

  • Square 适合表达 “绝对不应该做的事”(软约束、能耗最小化),因为它提供无上限的惩罚信号。
  • Exp 适合表达 “尽量做好的事”(目标追踪),因为它提供了数值稳定的、归一化的优化目标,避免了梯度爆炸问题。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值