以 DeepRobotics Lite3 强化学习项目 为例 看 观测量(Observation)在足式机器人强化学习中的作用 (Isaac Gym vs Isaac Lab 双版本)


观测量概述

在 Lite3 强化学习项目中,观测量(Observation)是 Policy 网络的输入,它编码了机器人当前的状态信息。观测量的设计直接影响到策略学习的效果和泛化能力。

重要说明:本文档涵盖两个版本:

  • 🔵 Isaac Gym 版本: 基于 NVIDIA Isaac Gym 的 Lite3_rl_training 项目:https://github.com/DeepRoboticsLab/Lite3_rl_training
  • 🟢 Isaac Lab 版本: 基于 Isaac Lab 的新版 rl_training 项目:https://github.com/DeepRoboticsLab/rl_training

观测量的作用

观测量 → Policy Network → 动作输出
   ↓
用于奖励计算
   ↓
环境状态评估

核心理念

  • 可观测性:只包含机器人传感器能实际测量的信息
  • 充分性:包含足够的信息支持决策
  • 高效性:维度适中,避免冗余
  • 鲁棒性:考虑传感器噪声和误差

框架对比说明

Isaac Gym vs Isaac Lab

特性Isaac Gym 版本Isaac Lab 版本
仿真引擎Isaac GymIsaac Lab (基于 Isaac Sim)
配置方式类继承 + 硬编码Manager-based + 声明式配置
观测定义compute_observations() 函数ObservationsCfg 配置类
模块化较低高度模块化
扩展性需修改代码配置文件即可
版本较早 (2023)最新 (2024-2025)

配置文件位置对比

🔵 Isaac Gym 版本:
Lite3_rl_training/
└── legged_gym/legged_gym/envs/
    ├── lite3/lite3_config.py           # 观测维度配置
    └── base/
        ├── legged_robot.py              # compute_observations()
        └── legged_robot_config.py       # 缩放和噪声

🟢 Isaac Lab 版本:
rl_training/source/rl_training/tasks/
└── manager_based/locomotion/velocity/
    ├── velocity_env_cfg.py              # 基础观测配置
    ├── mdp/observations.py              # 观测函数实现
    └── config/quadruped/deeprobotics_lite3/
        └── rough_env_cfg.py             # Lite3 特定配置

🔵 Isaac Gym 版本

核心观测量详解

1. 速度指令 (Commands)
# 维度: 3
self.commands[:, :3] * self.commands_scale
分量含义范围单位
commands[0]前后线速度指令[-1.0, 1.0]m/s
commands[1]左右线速度指令[-1.0, 1.0]m/s
commands[2]偏航角速度指令[-1.0, 1.0]rad/s

作用

  • 告诉 Policy 用户希望机器人以什么速度运动
  • 是 Policy 跟踪的目标
  • 用于计算跟踪奖励

参与强化学习

# 奖励计算
tracking_lin_vel_reward = exp(-||v_actual - v_command||^2 / sigma)
tracking_ang_vel_reward = exp(-||w_actual - w_command||^2 / sigma)

2. 身体姿态 (Roll, Pitch, Yaw)
# 维度: 3
self.rpy * self.obs_scales.orientation  # 缩放系数: 1.0
分量含义物理意义典型值
rpy[0]Roll (横滚角)身体左右倾斜[-0.5, 0.5] rad
rpy[1]Pitch (俯仰角)身体前后倾斜[-1.0, 1.0] rad
rpy[2]Yaw (偏航角)身体旋转方向[-π, π] rad

作用

  • 描述机器人身体在世界坐标系中的朝向
  • 用于姿态稳定控制
  • 检测机器人是否翻倒

参与强化学习

# 终止条件
reset_buf = torch.logical_or(
    torch.abs(self.rpy[:, 1]) > 1.0,  # pitch > 60°
    torch.abs(self.rpy[:, 0]) > 0.5   # roll > 30°
)

# 姿态奖励(惩罚倾斜)
orientation_reward = -torch.sum(torch.square(self.rpy[:, :2]))

3. 身体角速度 (Angular Velocity)
# 维度: 3
self.base_ang_vel * self.obs_scales.ang_vel  # 缩放系数: 1.0
分量含义单位作用
ang_vel[0]绕 x 轴角速度rad/s检测翻滚
ang_vel[1]绕 y 轴角速度rad/s检测俯仰
ang_vel[2]绕 z 轴角速度rad/s转向控制

坐标系:身体坐标系(Body Frame)

作用

  • 提供动态平衡信息
  • 用于快速反应控制
  • 阻尼不稳定的旋转

参与强化学习

# 惩罚 xy 平面角速度(抑制翻滚和俯仰)
ang_vel_xy_penalty = -torch.sum(torch.square(self.base_ang_vel[:, :2]))

# z 轴角速度用于跟踪偏航指令
tracking_ang_vel = exp(-||ang_vel_z - command_yaw||^2 / sigma)

4. 关节位置 (Joint Positions)
# 维度: 12 (四足 × 3 关节/腿)
self.dof_pos * self.obs_scales.dof_pos  # 缩放系数: 1.0

关节布局 (Lite3):

腿部编号:
FL (前左)  FR (前右)
HL (后左)  HR (后右)

每条腿 3 个关节:
- HipX (髋关节横向)
- HipY (髋关节纵向)
- Knee (膝关节)

总计: 4 腿 × 3 关节 = 12 DoF
关节索引关节名称范围 (rad)默认角度
0FL_HipX[-0.523, 0.523]0.0
1FL_HipY[-0.314, 3.6]-1.0
2FL_Knee[-2.792, -0.524]1.8
3-5HL (后左)同上同上
6-8FR (前右)同上同上
9-11HR (后右)同上同上

作用

  • 描述机器人当前的肢体形态
  • 检测关节极限
  • 用于运动学正向计算

参与强化学习

# 惩罚超出软限位
dof_pos_limits_penalty = torch.sum(
    torch.clamp(self.dof_pos - self.dof_pos_limits[:, 1], min=0.) +
    torch.clamp(self.dof_pos_limits[:, 0] - self.dof_pos, min=0.)
)

5. 关节速度 (Joint Velocities)
# 维度: 12
self.dof_vel * self.obs_scales.dof_vel  # 缩放系数: 0.1

单位: rad/s

作用

  • 提供关节运动的动态信息
  • 用于阻尼控制
  • 检测异常快速运动

参与强化学习

# 惩罚过快的关节速度
dof_vel_penalty = -torch.sum(torch.square(self.dof_vel))

# 在 PD 控制器中计算阻尼力矩
torques = Kp * (target - pos) - Kd * vel

6. 上一动作 (Previous Actions)

配置1 (117维) 和配置3 (304维) 不直接包含上一动作,而是包含动作历史

配置2 (133维) 和配置4 (320维) 包含:

# 维度: 12
self.actions  # 上一时刻的动作输出

作用

  • 提供动作连续性信息
  • 帮助 Policy 理解自己的控制影响
  • 用于动作平滑

历史观测量

仅在 117 和 304 维配置中包含

历史更新机制
# 更新频率控制
if self.history_update_cnt % self.cfg.normalization.dof_history_interval == 0:
    self.last_last_actions[:] = self.last_actions[:]
    self.last_actions[:] = self.actions[:]
    self.last_last_dof_vel[:] = self.last_dof_vel[:]
    self.last_dof_vel[:] = self.dof_vel[:]
    self.last_last_last_pos[:] = self.last_last_pos[:]
    self.last_last_pos[:] = self.last_pos[:]
    self.last_pos[:] = self.dof_pos[:]

更新间隔: dof_history_interval = 1 (每步更新)

1. 关节位置历史
# 维度: 36 (12 × 3 时刻)
dof_pos_history = torch.cat(
    (self.last_last_last_pos,  # t-3
     self.last_last_pos,       # t-2
     self.last_pos),           # t-1
    dim=-1
)

时间跨度: 3 个历史时刻 (默认每时刻 12ms, 总共 ~36ms)

作用

  • 捕捉关节运动的时序模式
  • 帮助 Policy 预测未来状态
  • 提供速度和加速度的隐式信息

2. 关节速度历史
# 维度: 24 (12 × 2 时刻)
dof_pos_vel_history = torch.cat(
    (self.last_last_dof_vel,  # t-2
     self.last_dof_vel),      # t-1
    dim=-1
)

作用

  • 提供关节加速度的隐式信息
  • 帮助预测动态趋势
  • 用于动作平滑

3. 动作目标历史
# 维度: 24 (12 × 2 时刻)
dof_pos_target_history = torch.cat(
    (self.last_last_actions,  # t-2
     self.last_actions),      # t-1
    dim=-1
)

作用

  • 记录 Policy 的控制历史
  • 用于动作平滑奖励
  • 避免抖动

参与强化学习

# 动作变化率惩罚
action_rate_penalty = -torch.sum(
    torch.square(self.actions - self.last_actions)
)

地形感知观测量

仅在 304 和 320 维配置中包含

高度测量 (Height Measurements)
# 维度: 187
heights = torch.clip(
    self.root_states[:, 2].unsqueeze(1) - 
    self.cfg.rewards.base_height_target - 
    self.measured_heights, 
    -1, 1.
) * self.obs_scales.height_measurements  # 缩放系数: 5.0

测量范围配置

# 17 × 11 = 187 个测量点
measured_points_x = [
    -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 
    0., 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8
]  # 前后 1.6m

measured_points_y = [
    -0.5, -0.4, -0.3, -0.2, -0.1, 0., 
    0.1, 0.2, 0.3, 0.4, 0.5
]  # 左右 1.0m

测量布局

机器人周围的高度采样网格 (俯视图):

    -0.5y ←→ 0.5y
    ↑
    |  ● ● ● ● ● ● ● ● ● ● ●
    |  ● ● ● ● ● ● ● ● ● ● ●
-0.8|  ● ● ● ● ● ● ● ● ● ● ●
    |  ● ● ● ● ● ● ● ● ● ● ●
    x  ● ● ● ● ● 🤖 ● ● ● ● ●  (机器人位置)
    |  ● ● ● ● ● ● ● ● ● ● ●
 0.8|  ● ● ● ● ● ● ● ● ● ● ●
    ↓  ● ● ● ● ● ● ● ● ● ● ●
       ● ● ● ● ● ● ● ● ● ● ●

总计: 17 × 11 = 187 个测量点

高度值含义

  • 正值: 前方有凸起(上坡、台阶、障碍物)
  • 负值: 前方有凹陷(下坡、坑洞)
  • 0 值: 平坦地形

作用

  • 提供局部地形信息
  • 用于足点规划
  • 避免碰撞和摔倒

参与强化学习

# 隐式作用:Policy 学习根据地形调整步态
# 例如:检测到台阶时抬高腿部

特权观测量

维度: 54

概念:仅在训练时 Critic 可见,部署时不可获得的信息。

self.privileged_obs_buf = torch.cat(
    (contact_states * self.priv_obs_scales.contact_state,      # 4
     friction_coefficients * self.priv_obs_scales.friction,    # 4
     external_forces_and_torques * self.priv_obs_scales.external_wrench,  # 6
     
     (self.mass_payloads - 6) * self.priv_obs_scales.mass_payload,  # 1
     self.com_displacements * self.priv_obs_scales.com_displacement,  # 3
     (self.motor_strengths - 1) * self.priv_obs_scales.motor_strength,  # 12
     (self.Kp_factors - 1) * self.priv_obs_scales.kp_factor,  # 12
     (self.Kd_factors - 1) * self.priv_obs_scales.kd_factor,  # 12
), dim=1)
# 总计: 4 + 4 + 6 + 1 + 3 + 12 + 12 + 12 = 54
特权观测量分类
类别维度内容缩放系数
接触状态4四足接触地面标志1.0
摩擦系数4地面摩擦系数1.0
外力/外力矩6推力和推力矩1.0
负载质量1额外载重0.5
质心偏移3质心位置偏移20.0
电机强度12电机输出倍率5.0
Kp 因子12位置增益倍率4.0
Kd 因子12速度增益倍率2.0

作用

  • 训练更好的 Critic (价值估计)
  • 学习对扰动的鲁棒性
  • 提高 sim-to-real 迁移能力

观测量在强化学习中的作用

1. Actor 输入
# Actor 网络
obs = compute_observations()  # [num_envs, 117/304/...]
actions = policy(obs)          # [num_envs, 12]

作用流程

观测量 → Actor MLP [512-256-128] → 关节动作
2. Critic 输入
# Critic 网络(使用特权观测)
privileged_obs = compute_privileged_observations()  # [num_envs, 54]
value = critic(privileged_obs)  # [num_envs, 1]

非对称训练

  • 训练: Critic 使用特权观测,准确评估状态价值
  • 部署: Actor 仅使用普通观测,无需特权信息
3. 奖励计算

几乎所有观测量都参与奖励计算:

def compute_reward(self):
    # 跟踪奖励
    rew_tracking_lin_vel = tracking_reward(self.base_lin_vel, self.commands[:, :2])
    rew_tracking_ang_vel = tracking_reward(self.base_ang_vel[:, 2], self.commands[:, 2])
    
    # 稳定性奖励
    rew_orientation = -torch.sum(torch.square(self.rpy[:, :2]))
    rew_ang_vel_xy = -torch.sum(torch.square(self.base_ang_vel[:, :2]))
    
    # 能量效率
    rew_torques = -torch.sum(torch.square(self.torques))
    rew_dof_vel = -torch.sum(torch.square(self.dof_vel))
    
    # 动作平滑
    rew_action_rate = -torch.sum(torch.square(self.actions - self.last_actions))
    
    # 总奖励
    total_reward = (
        rew_tracking_lin_vel * 1.0 +
        rew_tracking_ang_vel * 0.5 +
        rew_orientation * -0.2 +
        rew_ang_vel_xy * -0.05 +
        rew_torques * -0.00001 +
        rew_dof_vel * -0.0 +
        rew_action_rate * -0.01
    )
4. 终止条件
def check_termination(self):
    # 姿态倾覆
    self.reset_buf = torch.logical_or(
        torch.abs(self.rpy[:, 1]) > 1.0,  # pitch > 60°
        torch.abs(self.rpy[:, 0]) > 0.5   # roll > 30°
    )
    
    # 不良接触
    self.reset_buf |= torch.any(
        torch.norm(self.contact_forces[:, self.termination_contact_indices, :], dim=-1) > 1., 
        dim=1
    )
    
    # 超时
    self.time_out_buf = self.episode_length_buf > self.max_episode_length
    
    self.reset_buf |= self.time_out_buf

🟢 Isaac Lab 版本

观测配置架构

# velocity_env_cfg.py (Isaac Lab 基础配置)
@configclass
class ObservationsCfg:
    """Observation specifications for the MDP."""

    @configclass
    class PolicyCfg(ObsGroup):
        """Policy 网络的观测 (Actor 输入)"""
        
        # 基础运动观测
        base_lin_vel = ObsTerm(
            func=mdp.base_lin_vel,                 # 观测函数
            noise=Unoise(n_min=-0.1, n_max=0.1),   # 均匀噪声
            clip=(-100.0, 100.0),                  # 裁剪范围
            scale=1.0                              # 缩放因子
        )
        base_ang_vel = ObsTerm(func=mdp.base_ang_vel, noise=Unoise(n_min=-0.2, n_max=0.2))
        projected_gravity = ObsTerm(func=mdp.projected_gravity, noise=Unoise(n_min=-0.05, n_max=0.05))
        
        # 指令观测
        velocity_commands = ObsTerm(
            func=mdp.generated_commands, 
            params={"command_name": "base_velocity"}  # 函数参数
        )
        
        # 关节观测
        joint_pos = ObsTerm(
            func=mdp.joint_pos_rel,
            params={"asset_cfg": SceneEntityCfg("robot", joint_names=".*", preserve_order=True)},
            noise=Unoise(n_min=-0.01, n_max=0.01)
        )
        joint_vel = ObsTerm(
            func=mdp.joint_vel_rel,
            params={"asset_cfg": SceneEntityCfg("robot", joint_names=".*", preserve_order=True)},
            noise=Unoise(n_min=-1.5, n_max=1.5)
        )
        
        # 动作观测
        actions = ObsTerm(func=mdp.last_action)
        
        # 地形观测
        height_scan = ObsTerm(
            func=mdp.height_scan,
            params={"sensor_cfg": SceneEntityCfg("height_scanner")},
            noise=Unoise(n_min=-0.1, n_max=0.1),
            clip=(-1.0, 1.0)
        )

        def __post_init__(self):
            self.enable_corruption = True      # 启用噪声
            self.concatenate_terms = True      # 自动拼接所有观测项

    @configclass
    class CriticCfg(ObsGroup):
        """Critic 网络的观测 (Value 估计输入)"""
        # 与 Policy 相同的观测项,但无噪声干扰
        base_lin_vel = ObsTerm(func=mdp.base_lin_vel)
        base_ang_vel = ObsTerm(func=mdp.base_ang_vel)
        projected_gravity = ObsTerm(func=mdp.projected_gravity)
        velocity_commands = ObsTerm(func=mdp.generated_commands, params={"command_name": "base_velocity"})
        joint_pos = ObsTerm(func=mdp.joint_pos_rel, params={"asset_cfg": SceneEntityCfg("robot", joint_names=".*")})
        joint_vel = ObsTerm(func=mdp.joint_vel_rel, params={"asset_cfg": SceneEntityCfg("robot", joint_names=".*")})
        actions = ObsTerm(func=mdp.last_action)
        height_scan = ObsTerm(func=mdp.height_scan, params={"sensor_cfg": SceneEntityCfg("height_scanner")})

        def __post_init__(self):
            self.enable_corruption = False     # Critic 不添加噪声
            self.concatenate_terms = True

    # 观测组配置
    policy: PolicyCfg = PolicyCfg()
    critic: CriticCfg = CriticCfg()

关键设计:

  • ObsGroup: 观测组,包含多个观测项
  • ObsTerm: 单个观测项配置
  • func: 指向 mdp 模块中的观测函数
  • params: 传递给观测函数的参数
  • noise: 噪声模型配置
  • clip: 观测值裁剪范围
  • scale: 观测值缩放因子
  • enable_corruption: 是否启用噪声 (Policy=True, Critic=False)
  • concatenate_terms: 是否自动拼接观测项

ObsTerm 配置说明

ObsTerm(
    func=mdp.base_lin_vel,              # 观测函数 (来自 mdp 模块)
    noise=Unoise(n_min=-0.1, n_max=0.1), # 均匀噪声
    clip=(-10.0, 10.0),                  # 裁剪范围
    scale=1.0                            # 缩放因子
)

Lite3 在 Isaac Lab 中的观测配置

# rough_env_cfg.py (Lite3 特定配置)
@configclass
class DeeproboticsLite3RoughEnvCfg(LocomotionVelocityRoughEnvCfg):
    
    def __post_init__(self):
        super().__post_init__()
        
        # 🔴 禁用某些观测
        self.observations.policy.base_lin_vel = None      # 禁用线速度 (3维)
        self.observations.policy.height_scan = None       # 禁用地形扫描 (187维)
        
        # ✏️ 修改观测缩放
        self.observations.policy.base_ang_vel.scale = 0.25   # 角速度缩放
        self.observations.policy.joint_pos.scale = 1.0       # 关节位置缩放
        self.observations.policy.joint_vel.scale = 0.05      # 关节速度缩放 (vs 0.1 in Gym)
        
        # ✏️ 修改动作缩放
        self.actions.joint_pos.scale = {
            ".*_HipX_joint": 0.125,              # HipX 关节: 0.125
            "^(?!.*_HipX_joint).*": 0.25         # 其他关节: 0.25
        }

自定义观测函数

Isaac Lab 支持自定义观测函数:

# observations.py
def joint_pos_rel_without_wheel(env: ManagerBasedRLEnv, asset_cfg: SceneEntityCfg) -> torch.Tensor:
    """关节位置观测 (相对于默认位置,排除轮子关节)"""
    asset: Articulation = env.scene[asset_cfg.name]
    return asset.data.joint_pos[:, asset_cfg.joint_ids] - asset.data.default_joint_pos[:, asset_cfg.joint_ids]

def phase(env: ManagerBasedRLEnv) -> torch.Tensor:
    """步态相位观测"""
    # 自定义步态相位计算逻辑
    return env.command_manager.get_term("base_velocity").pos_command_b[:, :2]

代码实现

# velocity_env_cfg.py (配置文件)
@configclass
class PolicyCfg(ObsGroup):
    """仅需声明观测项,Manager 自动处理拼接和噪声"""
    
    velocity_commands = ObsTerm(
        func=mdp.generated_commands, 
        params={"command_name": "base_velocity"}
    )  # 3维
    
    base_ang_vel = ObsTerm(
        func=mdp.base_ang_vel, 
        noise=Unoise(n_min=-0.2, n_max=0.2),
        scale=1.0
    )  # 3维
    
    projected_gravity = ObsTerm(
        func=mdp.projected_gravity, 
        noise=Unoise(n_min=-0.05, n_max=0.05)
    )  # 3维
    
    joint_pos = ObsTerm(
        func=mdp.joint_pos_rel,
        params={"asset_cfg": SceneEntityCfg("robot", joint_names=".*")},
        noise=Unoise(n_min=-0.01, n_max=0.01)
    )  # 12维
    
    joint_vel = ObsTerm(
        func=mdp.joint_vel_rel,
        params={"asset_cfg": SceneEntityCfg("robot", joint_names=".*")},
        noise=Unoise(n_min=-1.5, n_max=1.5),
        scale=1.0
    )  # 12维
    
    actions = ObsTerm(func=mdp.last_action)  # 12维

# rough_env_cfg.py (Lite3 定制)
def __post_init__(self):
    # 禁用不需要的观测项
    self.observations.policy.base_lin_vel = None     # 禁用
    self.observations.policy.height_scan = None      # 禁用
    
    # 修改缩放因子
    self.observations.policy.base_ang_vel.scale = 0.25
    self.observations.policy.joint_vel.scale = 0.05

Lite3 观测维度分析 (Isaac Lab)

根据 rough_env_cfg.pyvelocity_env_cfg.py 配置分析:

基础观测配置 (velocity_env_cfg.py)
@configclass
class PolicyCfg(ObsGroup):
    base_lin_vel = ObsTerm(...)        # 3 维 [vx, vy, vz]
    base_ang_vel = ObsTerm(...)        # 3 维 [ωx, ωy, ωz]
    projected_gravity = ObsTerm(...)   # 3 维 [gx, gy, gz]
    velocity_commands = ObsTerm(...)   # 3 维 [vx_cmd, vy_cmd, ωz_cmd]
    joint_pos = ObsTerm(...)           # 12 维 (12个关节)
    joint_vel = ObsTerm(...)           # 12 维 (12个关节)
    actions = ObsTerm(...)             # 12 维 (上一时刻动作)
    height_scan = ObsTerm(...)         # 187 维 (17×11地形网格)

基础配置总维度: 3 + 3 + 3 + 3 + 12 + 12 + 12 + 187 = 235 维

Lite3 特定修改 (rough_env_cfg.py)
# 禁用的观测
self.observations.policy.base_lin_vel = None      # ❌ -3 维
self.observations.policy.height_scan = None       # ❌ -187 维

Lite3 实际 Policy 观测维度: 235 - 3 - 187 = 45 维

Policy 观测详细组成
# Lite3 Policy 观测 (45 维)
base_ang_vel (3)           # 身体角速度 [ωx, ωy, ωz]
projected_gravity (3)      # 投影重力 [gx, gy, gz]  
velocity_commands (3)      # 速度指令 [vx_cmd, vy_cmd, ωz_cmd]
joint_pos (12)             # 关节位置相对值
joint_vel (12)             # 关节速度
actions (12)               # 上一时刻动作

# 总计: 3 + 3 + 3 + 12 + 12 + 12 = 45 维
Critic 特权观测组成
# Critic 观测 (基础版,无额外特权信息)
base_lin_vel (3)           # 线速度 (Policy中被禁用)
base_ang_vel (3)           # 角速度
projected_gravity (3)      # 投影重力
velocity_commands (3)      # 速度指令
joint_pos (12)             # 关节位置
joint_vel (12)             # 关节速度
actions (12)               # 上一时刻动作
height_scan (187)          # 地形扫描 (Policy中被禁用)

# 总计: 3 + 3 + 3 + 3 + 12 + 12 + 12 + 187 = 235 维

注意: Isaac Lab 中 Critic 默认配置与 Policy 相同的观测项,但不禁用任何项,并且没有噪声干扰。

与 Isaac Gym 的维度对比
版本Policy 维度Critic 维度关键差异
Isaac Gym11754包含历史观测(84维)
Isaac Lab45235无历史观测,Critic包含地形

核心区别:

  • 🔵 Isaac Gym: 使用历史缓冲(3时刻位置+2时刻速度+2时刻动作) = 84维历史
  • 🟢 Isaac Lab: 不使用历史观测,仅使用当前时刻的观测 = 更轻量级

观测量的噪声处理

🔵 Isaac Gym 噪声配置

class noise:
    add_noise = True
    noise_level = 1.0  # 全局噪声缩放

    class noise_scales:
        dof_pos = 0.01        # 关节位置噪声
        dof_vel = 1.5         # 关节速度噪声
        lin_vel = 0.1         # 线速度噪声
        ang_vel = 0.2         # 角速度噪声
        gravity = 0.05        # 重力方向噪声
        height_measurements = 0.1  # 地形高度噪声
        orientation = 0.5     # 姿态噪声

噪声添加方式

🔵 Isaac Gym:

if self.add_noise:
    # 均匀噪声: U(-noise_scale, +noise_scale)
    self.obs_buf += (2 * torch.rand_like(self.obs_buf) - 1) * self.noise_scale_vec
    
    # 地形高度使用高斯噪声
    self.obs_buf[:, -187:] += torch.normal(
        mean=self.height_noise_mean,  # 均值 (可变)
        std=0.05,                      # 标准差
        size=(self.obs_buf[:, -187:].shape)
    ) * self.obs_scales.height_measurements

🟢 Isaac Lab:

# 每个观测项独立配置噪声
ObsTerm(
    func=mdp.joint_vel_rel,
    noise=Unoise(n_min=-1.5, n_max=1.5),  # 均匀噪声 [-1.5, 1.5]
)

# 或使用高斯噪声
ObsTerm(
    func=mdp.base_lin_vel,
    noise=GaussianNoise(mean=0.0, std=0.1),  # 高斯噪声 N(0, 0.1)
)

噪声的作用

  1. 提高鲁棒性: 模拟真实传感器误差
  2. 防止过拟合: 避免 Policy 依赖精确值
  3. Sim-to-Real: 减小仿真与现实的差距

观测量维度总结表

🔵 Isaac Gym 观测维度

配置指令姿态角速度关节位置关节速度位置历史速度历史动作历史地形总计
11733312123624240117
3043331212362424187304

🟢 Isaac Lab 观测维度

Isaac Lab 的观测维度由配置类动态组合。

Lite3 实际配置

Policy 观测: 45 维

base_ang_vel (3) + projected_gravity (3) + velocity_commands (3) +
joint_pos (12) + joint_vel (12) + actions (12) = 45

Critic 观测: 235 维

base_lin_vel (3) + base_ang_vel (3) + projected_gravity (3) + velocity_commands (3) +
joint_pos (12) + joint_vel (12) + actions (12) + height_scan (187) = 235
关键特性对比
特性Isaac Gym (117维)Isaac Lab (45维)
历史观测✅ 84维 (3时刻位置+2时刻速度+2时刻动作)❌ 无历史
当前观测33维45维
地形扫描❌ 默认关闭✅ Critic启用(187维)
线速度✅ 包含❌ Policy禁用
维度优势时序信息丰富轻量级,推理快

设计理念差异:

  • 🔵 Isaac Gym: 通过历史观测隐式提供速度/加速度信息
  • 🟢 Isaac Lab: 直接使用当前状态,依赖网络学习动态特性

灵活性: Isaac Lab 可以通过配置轻松调整观测维度,无需修改代码。如需历史观测,可使用 ObservationHistory wrapper 或自定义 MDP 函数。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值