跳到主要内容Isaac Lab 机器人强化学习实战:配置架构、添加流程与调参技巧 | 极客日志PythonAI算法
Isaac Lab 机器人强化学习实战:配置架构、添加流程与调参技巧
综述由AI生成基于 NVIDIA Isaac Lab 构建的 Robot Lab 强化学习扩展库。内容涵盖配置继承体系解析,包括场景、命令、动作、观测、事件、奖励、终止及课程学习配置详解。详细说明了如何添加新机器人(如 Agibot D1),涉及资产配置、RL Agent 配置、环境配置及 Gym 注册流程。最后提供了四足、人形及轮式机器人的调参指南,包含奖励权重设置、常见问题诊断及 TensorBoard 监控方法,旨在帮助开发者高效完成机器人运动控制策略的训练与部署。
开源信徒31 浏览 0. 前言
Robot Lab 是基于 NVIDIA Isaac Lab 构建的机器人强化学习扩展库,专注于足式机器人的运动控制任务。目前已支持包括 Unitree Go2、G1、H1 在内的十余款主流机器人平台。与原生 Isaac Lab 相比,Robot Lab 提供了更加完善的奖励函数库、域随机化配置以及针对不同机器人形态优化的训练参数。
在深入技术细节之前,有必要先理解 Isaac Lab 的基本架构。Isaac Lab 构建于 Isaac Sim 之上,采用分层设计:最底层是 Omniverse 渲染引擎与 PhysX 物理引擎,中间层是 Isaac Sim 提供的机器人仿真接口,最上层则是 Isaac Lab 封装的强化学习环境。Robot Lab 在此基础上进一步抽象,将运动控制任务的通用配置提取为基类,使得添加新机器人变得简单高效。
1. 配置继承体系解析
1.1 整体架构概览
Robot Lab 的环境配置采用面向对象的继承体系,这一设计决策源于对机器人强化学习任务共性的深刻理解。无论是四足机器人、人形机器人还是轮式机器人,其速度跟踪任务都包含相似的核心组件:观测空间定义、动作空间设计、奖励函数构建等。将这些共性抽象为基类,可以显著减少重复代码,同时保持各机器人配置的独立性与可维护性。
继承链从 Isaac Lab 的 ManagerBasedRLEnvCfg 基类开始,该类定义了强化学习环境的基本框架。Robot Lab 在此基础上派生出 LocomotionVelocityRoughEnvCfg,封装了运动控制任务的通用配置。针对具体机器人,如 G1,则进一步派生出粗糙地形配置 UnitreeG1RoughEnvCfg,最后是针对平地训练的简化配置 UnitreeG1FlatEnvCfg。
这种多层继承结构带来三个核心优势。首先是代码复用:基类中定义的 30 余个奖励项、8 种域随机化事件、多组传感器配置等均可被所有子类继承,无需重复编写。其次是灵活定制:每个机器人可以通过 __post_init__ 方法选择性地覆盖父类参数,例如 G1 需要启用摔倒惩罚而四足机器人可能不需要。最后是易于维护:当基类的奖励函数实现优化后,所有子类自动受益,无需逐一修改。
1.2 基类详解:LocomotionVelocityRoughEnvCfg
LocomotionVelocityRoughEnvCfg 是 Robot Lab 运动控制任务的核心基类,位于 velocity_env_cfg.py 文件中。该类定义了构成马尔可夫决策过程(MDP)的全部要素,包括状态空间、动作空间、奖励函数、状态转移规则等。理解这个基类的设计,是掌握整个 Robot Lab 配置体系的关键。
基类的核心结构如下,包含 8 个配置模块:
@configclass
class LocomotionVelocityRoughEnvCfg(ManagerBasedRLEnvCfg):
"""运动速度跟踪环境配置基类"""
scene: MySceneCfg = MySceneCfg(num_envs=4096, env_spacing=2.5)
observations: ObservationsCfg = ObservationsCfg()
actions: ActionsCfg = ActionsCfg()
commands: CommandsCfg = CommandsCfg()
rewards: RewardsCfg = RewardsCfg()
terminations: TerminationsCfg = TerminationsCfg()
events: EventCfg = EventCfg()
curriculum: CurriculumCfg = CurriculumCfg()
这 8 个模块可以分为两类:输入配置(Scene、Commands、Actions、Observations)定义了智能体与环境的交互接口;训练配置(Rewards、Terminations、Events、Curriculum)则控制训练过程的行为。以下逐一详解各模块的设计原理与关键参数。
1.2.1 场景配置 (MySceneCfg)
场景配置定义了仿真环境中的物理世界,包括地形、机器人模型以及各类传感器。在 Isaac Lab 的架构中,场景是所有物理实体的容器,其配置直接影响仿真的物理真实性与计算效率。
@configclass
class MySceneCfg(InteractiveSceneCfg):
"""场景配置:定义地形、机器人、传感器"""
terrain = TerrainImporterCfg(
prim_path="/World/ground",
terrain_type="generator",
terrain_generator=ROUGH_TERRAINS_CFG,
max_init_terrain_level=5,
collision_group=-1,
physics_material=sim_utils.RigidBodyMaterialCfg(
friction_combine_mode="multiply",
static_friction=1.0,
dynamic_friction=1.0,
),
)
robot: ArticulationCfg = MISSING
height_scanner = RayCasterCfg(
prim_path="{ENV_REGEX_NS}/Robot/base",
offset=RayCasterCfg.OffsetCfg(pos=(0.0,0.0,20.0)),
pattern_cfg=patterns.GridPatternCfg(resolution=0.1, size=[1.6,1.0]),
mesh_prim_paths=["/World/ground"],
)
contact_forces = ContactSensorCfg(
prim_path="{ENV_REGEX_NS}/Robot/.*",
history_length=3,
track_air_time=True,
)
这里有几个关键设计值得深入理解。首先是 {ENV_REGEX_NS} 占位符,这是 Isaac Lab 实现大规模并行仿真的核心机制。当设置 num_envs=4096 时,Isaac Lab 会自动将场景中的机器人克隆 4096 份,每份位于独立的命名空间中。{ENV_REGEX_NS} 在运行时会被替换为 /World/envs/env_0、/World/envs/env_1 等具体路径,从而实现单个配置支持大规模并行训练。
其次是高度扫描传感器的设计。该传感器模拟了真实机器人上常见的激光雷达或深度相机,通过向下发射射线网格来感知前方地形。默认配置采用 0.1m 分辨率、1.6m×1.0m 范围的网格,这一参数需要根据机器人的尺寸和任务需求进行调整。
1.2.2 命令配置 (CommandsCfg)
命令配置定义了策略需要跟踪的目标速度。在速度跟踪任务中,命令生成器会周期性地产生新的目标速度,策略的目标是使机器人的实际速度尽可能接近这些命令值。命令的设计直接影响训练出的策略的泛化能力。
@configclass
class CommandsCfg:
"""命令配置:定义目标速度的采样范围与重采样策略"""
base_velocity = mdp.UniformThresholdVelocityCommandCfg(
asset_name="robot",
resampling_time_range=(10.0,10.0),
rel_standing_envs=0.02,
rel_heading_envs=1.0,
heading_command=True,
heading_control_stiffness=0.5,
ranges=mdp.UniformThresholdVelocityCommandCfg.Ranges(
lin_vel_x=(-1.0,1.0),
lin_vel_y=(-1.0,1.0),
ang_vel_z=(-1.0,1.0),
heading=(-math.pi, math.pi),
),
)
rel_standing_envs=0.02 这个参数蕴含重要的训练技巧。在强化学习训练过程中,如果所有环境都持续发送非零速度命令,策略可能学不会站立不动。通过让 2% 的环境持续发送零速度命令,可以确保策略具备稳定站立的能力。
1.2.3 动作配置 (ActionsCfg)
动作配置定义了策略网络输出如何转换为机器人的控制指令。Robot Lab 主要采用关节位置控制模式,即策略输出目标关节角度,底层 PD 控制器负责跟踪这些目标角度。
@configclass
class ActionsCfg:
"""动作配置:定义策略输出到关节控制的映射"""
joint_pos = mdp.JointPositionActionCfg(
asset_name="robot",
joint_names=[".*"],
scale=0.5,
use_default_offset=True,
clip=None,
preserve_order=True,
)
对于轮式机器人如 Go2W,动作配置需要更复杂的设计,因为腿部关节和轮子关节需要不同的控制模式:
@configclass
class UnitreeGo2WActionsCfg(ActionsCfg):
joint_pos = mdp.JointPositionActionCfg(
joint_names=[".*_hip_joint",".*_thigh_joint",".*_calf_joint"],
scale=0.25,
)
joint_vel = mdp.JointVelocityActionCfg(
joint_names=[".*_foot_joint"],
scale=5.0,
)
1.2.4 观测配置 (ObservationsCfg)
观测配置是连接环境状态与策略输入的桥梁。Robot Lab 采用了非对称 Actor-Critic 架构的观测设计:策略网络(Actor)接收带噪声的观测,模拟真实传感器的测量误差;评论家网络(Critic)则接收无噪声的"特权信息"。
@configclass
class ObservationsCfg:
"""观测配置:定义策略和评论家的输入"""
@configclass
class PolicyCfg(ObsGroup):
"""策略网络观测组 - 带噪声以模拟真实传感器"""
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)
joint_pos = ObsTerm(func=mdp.joint_pos_rel, noise=Unoise(n_min=-0.01, n_max=0.01))
joint_vel = ObsTerm(func=mdp.joint_vel_rel, noise=Unoise(n_min=-1.5, n_max=1.5))
actions = ObsTerm(func=mdp.last_action)
height_scan = ObsTerm(func=mdp.height_scan, noise=Unoise(n_min=-0.1, n_max=0.1))
def __post_init__(self):
self.enable_corruption = True
self.concatenate_terms = True
@configclass
class CriticCfg(ObsGroup):
"""评论家网络观测组 - 无噪声的特权信息"""
def __post_init__(self):
self.enable_corruption = False
policy: PolicyCfg = PolicyCfg()
critic: CriticCfg = CriticCfg()
1.2.5 事件配置 (EventCfg) - 域随机化
域随机化(Domain Randomization)是弥合仿真与现实差距的核心技术。其基本思想是:如果策略能够在具有广泛物理参数变化的仿真环境中稳定工作,那么它很可能也能在真实世界中表现良好。
@configclass
class EventCfg:
"""事件配置:定义域随机化策略"""
randomize_rigid_body_material = EventTerm(
func=mdp.randomize_rigid_body_material,
mode="startup",
params={"asset_cfg": SceneEntityCfg("robot", body_names=".*"),
"static_friction_range":(0.3,1.0),
"dynamic_friction_range":(0.3,0.8),
"restitution_range":(0.0,0.5),
"num_buckets":64},
)
randomize_rigid_body_mass_base = EventTerm(
func=mdp.randomize_rigid_body_mass,
mode="startup",
params={"asset_cfg": SceneEntityCfg("robot", body_names="base"),
"mass_distribution_params":(-1.0,3.0),
"operation":"add",
"recompute_inertia":True},
)
randomize_actuator_gains = EventTerm(
func=mdp.randomize_actuator_gains,
mode="reset",
params={"asset_cfg": SceneEntityCfg("robot", joint_names=".*"),
"stiffness_distribution_params":(0.5,2.0),
"damping_distribution_params":(0.5,2.0),
"operation":"scale",},
)
randomize_reset_base = EventTerm(
func=mdp.reset_root_state_uniform,
mode="reset",
params={"pose_range":{"x":(-0.5,0.5),"y":(-0.5,0.5),"yaw":(-3.14,3.14)},
"velocity_range":{"x":(-0.5,0.5),"y":(-0.5,0.5)},},
)
randomize_push_robot = EventTerm(
func=mdp.push_by_setting_velocity,
mode="interval",
interval_range_s=(10.0,15.0),
params={"velocity_range":{"x":(-0.5,0.5),"y":(-0.5,0.5)}},
)
三种事件模式的设计体现了对真实世界不确定性来源的深刻理解。Startup 事件模拟的是制造公差,Reset 事件模拟的是使用场景的多样性,Interval 事件则模拟运行时的外部干扰。
1.2.6 奖励配置 (RewardsCfg)
奖励函数是强化学习的核心,它定义了我们希望智能体学习的行为。Robot Lab 提供了超过 30 个预定义的奖励项,涵盖速度跟踪、能耗优化、姿态稳定、步态协调等多个维度。
@configclass
class RewardsCfg:
"""奖励配置:定义强化学习的目标函数"""
track_lin_vel_xy_exp = RewTerm(
func=mdp.track_lin_vel_xy_exp,
weight=0.0,
params={"command_name":"base_velocity","std": math.sqrt(0.25)},
)
track_ang_vel_z_exp = RewTerm(
func=mdp.track_ang_vel_z_exp,
weight=0.0,
params={"command_name":"base_velocity","std": math.sqrt(0.25)},
)
lin_vel_z_l2 = RewTerm(func=mdp.lin_vel_z_l2, weight=0.0)
ang_vel_xy_l2 = RewTerm(func=mdp.ang_vel_xy_l2, weight=0.0)
flat_orientation_l2 = RewTerm(func=mdp.flat_orientation_l2, weight=0.0)
joint_torques_l2 = RewTerm(func=mdp.joint_torques_l2, weight=0.0)
joint_acc_l2 = RewTerm(func=mdp.joint_acc_l2, weight=0.0)
action_rate_l2 = RewTerm(func=mdp.action_rate_l2, weight=0.0)
joint_power = RewTerm(func=mdp.joint_power, weight=0.0)
feet_air_time = RewTerm(func=mdp.feet_air_time, weight=0.0)
feet_gait = RewTerm(func=mdp.GaitReward, weight=0.0)
feet_slide = RewTerm(func=mdp.feet_slide, weight=0.0)
feet_stumble = RewTerm(func=mdp.feet_stumble, weight=0.0)
joint_pos_limits = RewTerm(func=mdp.joint_pos_limits, weight=0.0)
undesired_contacts = RewTerm(func=mdp.undesired_contacts, weight=0.0)
is_terminated = RewTerm(func=mdp.is_terminated, weight=0.0)
1.2.7 终止条件配置 (TerminationsCfg)
终止条件定义了 episode 何时结束。合理的终止条件对训练效率至关重要。
@configclass
class TerminationsCfg:
"""终止条件配置"""
time_out = DoneTerm(func=mdp.time_out, time_out=True)
terrain_out_of_bounds = DoneTerm(
func=mdp.terrain_out_of_bounds,
params={"asset_cfg": SceneEntityCfg("robot"),"distance_buffer":3.0},
time_out=True,
)
illegal_contact = DoneTerm(
func=mdp.illegal_contact,
params={"sensor_cfg": SceneEntityCfg("contact_forces", body_names=""),"threshold":1.0},
)
1.2.8 课程学习配置 (CurriculumCfg)
课程学习是一种渐进式训练策略,通过逐步增加任务难度来提高学习效率。
@configclass
class CurriculumCfg:
"""课程学习配置"""
terrain_levels = CurrTerm(func=mdp.terrain_levels_vel)
command_levels_lin_vel = CurrTerm(
func=mdp.command_levels_lin_vel,
params={"reward_term_name":"track_lin_vel_xy_exp","range_multiplier":(0.1,1.0)},
)
command_levels_ang_vel = CurrTerm(
func=mdp.command_levels_ang_vel,
params={"reward_term_name":"track_ang_vel_z_exp","range_multiplier":(0.1,1.0)},
)
1.3 子类配置示例:UnitreeG1RoughEnvCfg
理解了基类的设计之后,我们来看如何通过子类实现机器人特定的配置。
@configclass
class UnitreeG1RoughEnvCfg(LocomotionVelocityRoughEnvCfg):
"""Unitree G1 人形机器人粗糙地形环境配置"""
base_link_name = "torso_link"
foot_link_name = ".*_ankle_roll_link"
def __post_init__(self):
super().__post_init__()
self.scene.robot = UNITREE_G1_29DOF_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot")
self.scene.height_scanner.prim_path = "{ENV_REGEX_NS}/Robot/" + self.base_link_name
self.observations.policy.base_lin_vel.scale = 2.0
self.observations.policy.base_ang_vel.scale = 0.25
self.observations.policy.joint_vel.scale = 0.05
self.observations.policy.base_lin_vel = None
self.observations.policy.height_scan = None
self.actions.joint_pos.scale = UNITREE_G1_29DOF_ACTION_SCALE
self.rewards.is_terminated.weight = -200.0
self.rewards.track_lin_vel_xy_exp.weight = 3.0
self.rewards.track_lin_vel_xy_exp.func = mdp.track_lin_vel_xy_yaw_frame_exp
self.rewards.track_ang_vel_z_exp.weight = 3.0
self.rewards.ang_vel_xy_l2.weight = -0.1
self.rewards.flat_orientation_l2.weight = -0.2
self.rewards.joint_torques_l2.weight = -1.5e-7
self.rewards.joint_acc_l2.weight = -1.25e-7
self.rewards.action_rate_l2.weight = -0.005
self.rewards.feet_air_time.weight = 0.25
self.rewards.feet_air_time.func = mdp.feet_air_time_positive_biped
self.rewards.feet_slide.weight = -0.2
self.rewards.upward.weight = 1.0
if self.__class__.__name__ == "UnitreeG1RoughEnvCfg":
self.disable_zero_weight_rewards()
self.curriculum.terrain_levels = None
self.curriculum.command_levels_lin_vel = None
self.curriculum.command_levels_ang_vel = None
1.4 简化配置:UnitreeG1FlatEnvCfg
在完成粗糙地形配置之后,Robot Lab 通常还会提供一个平地配置作为训练的入门版本。
@configclass
class UnitreeG1FlatEnvCfg(UnitreeG1RoughEnvCfg):
def __post_init__(self):
super().__post_init__()
self.scene.terrain.terrain_type = "plane"
self.scene.terrain.terrain_generator = None
self.scene.height_scanner = None
self.observations.policy.height_scan = None
self.curriculum.terrain_levels = None
self.rewards.track_ang_vel_z_exp.weight = 1.0
2. 强化学习 Agent 配置
Robot Lab 支持多种强化学习框架,其中 RSL-RL 是最常用的选择。Agent 配置定义了强化学习算法的超参数,包括网络架构、优化器设置、PPO 特定参数等。
2.1 RSL-RL PPO 配置详解
RL Agent 配置位于各机器人目录下的 agents/rsl_rl_ppo_cfg.py 文件中。
@configclass
class UnitreeG1RoughPPORunnerCfg(RslRlOnPolicyRunnerCfg):
num_steps_per_env = 24
max_iterations = 20000
save_interval = 200
experiment_name = "unitree_g1_rough"
policy = RslRlPpoActorCriticCfg(
init_noise_std=1.0,
actor_obs_normalization=False,
critic_obs_normalization=False,
actor_hidden_dims=[512,256,128],
critic_hidden_dims=[512,256,128],
activation="elu",
)
algorithm = RslRlPpoAlgorithmCfg(
value_loss_coef=1.0,
use_clipped_value_loss=True,
clip_param=0.2,
entropy_coef=0.008,
num_learning_epochs=5,
num_mini_batches=4,
learning_rate=1.0e-3,
schedule="adaptive",
gamma=0.99,
lam=0.95,
desired_kl=0.01,
max_grad_norm=1.0,
)
2.2 关键参数说明
| 参数 | 默认值 | 说明 |
|---|
num_steps_per_env | 24 | 每个环境在一次更新中采样的步数 |
actor_hidden_dims | [512, 256, 128] | Actor 网络架构 |
clip_param | 0.2 | PPO 裁剪范围,防止策略更新过大 |
entropy_coef | 0.008-0.01 | 熵系数,控制探索程度 |
gamma | 0.99 | 折扣因子,决定对未来奖励的重视程度 |
lam | 0.95 | GAE 参数,平衡偏差和方差 |
desired_kl | 0.01 | 目标 KL 散度,用于自适应学习率 |
num_steps_per_env(每环境采样步数):这个参数决定了在每次策略更新前,每个并行环境需要收集多少步的经验数据。假设有 4096 个并行环境,num_steps_per_env=24 意味着每次更新前会收集 4096 × 24 = 98304 个样本。
clip_param(PPO 裁剪参数):这是 PPO 算法的核心超参数,用于限制策略更新的幅度。具体来说,PPO 的目标函数会裁剪重要性采样比率到 [1-clip_param, 1+clip_param] 范围内。
entropy_coef(熵系数):熵正则化用于鼓励策略保持一定程度的随机性,避免过早收敛到局部最优。
gamma 和 lam(折扣因子和 GAE 参数):gamma=0.99 意味着智能体会重视未来约 100 步的累积奖励。lam=0.95 是 GAE 的平滑参数。
schedule="adaptive"(自适应学习率):RSL-RL 支持自适应学习率调整,当策略更新的 KL 散度超过 desired_kl 时自动降低学习率。
2.3 不同机器人的 Agent 配置对比
| 参数 | G1 (人形) | GO2 (四足) | Agibot D1 |
|---|
max_iterations | 20000 | 20000 | 20000 |
entropy_coef | 0.008 | 0.01 | 0.01 |
save_interval | 200 | 100 | 100 |
3. 添加新机器人(以 Agibot 为例)
将新机器人集成到 Robot Lab 是一个结构化的过程,需要按照特定的步骤创建配置文件并注册环境。
3.1 完整流程概览
添加新机器人涉及 5 个核心步骤,需要在两个目录下创建相应的文件。assets/ 目录存放机器人资产配置,定义模型文件路径、关节参数、执行器特性等;tasks/.../config/ 目录存放任务配置,定义环境参数、奖励函数、训练算法等。
robot_lab/
├── assets/
│ └── agibot.py
└── tasks/manager_based/locomotion/velocity/config/quadruped/agibot_d1/
├── __init__.py
├── rough_env_cfg.py
├── flat_env_cfg.py
└── agents/
├── __init__.py
├── rsl_rl_ppo_cfg.py
└── cusrl_ppo_cfg.py
3.2 步骤 1: 创建资产配置
文件:robot_lab/assets/agibot.py
import isaaclab.sim as sim_utils
from isaaclab.actuators import DCMotorCfg
from isaaclab.assets.articulation import ArticulationCfg
from robot_lab.assets import ISAACLAB_ASSETS_DATA_DIR
AGIBOT_D1_CFG = ArticulationCfg(
spawn=sim_utils.UrdfFileCfg(
fix_base=False,
merge_fixed_joints=True,
asset_path=f"{ISAACLAB_ASSETS_DATA_DIR}/Robots/agibot/d1/urdf/edu.urdf",
activate_contact_sensors=True,
rigid_props=sim_utils.RigidBodyPropertiesCfg(
disable_gravity=False,
max_linear_velocity=1000.0,
max_angular_velocity=1000.0,
),
articulation_props=sim_utils.ArticulationRootPropertiesCfg(
enabled_self_collisions=False,
solver_position_iteration_count=4,
),
),
init_state=ArticulationCfg.InitialStateCfg(
pos=(0.0,0.0,0.42),
joint_pos={".*L_ABAD_JOINT":0.0,".*R_ABAD_JOINT":0.0,"F.*_HIP_JOINT":0.8,"R.*_HIP_JOINT":0.8,".*_KNEE_JOINT":-1.5},
joint_vel={".*":0.0},
),
actuators={"legs": DCMotorCfg(
joint_names_expr=[".*_(ABAD|HIP|KNEE)_JOINT"],
effort_limit=33.5,
saturation_effort=33.5,
velocity_limit=21.0,
stiffness=20.0,
damping=0.5,
),},
)
3.3 步骤 2: 创建 RL Agent 配置
文件:agents/rsl_rl_ppo_cfg.py
from isaaclab.utils import configclass
from isaaclab_rl.rsl_rl import RslRlOnPolicyRunnerCfg, RslRlPpoActorCriticCfg, RslRlPpoAlgorithmCfg
@configclass
class AgibotD1RoughPPORunnerCfg(RslRlOnPolicyRunnerCfg):
num_steps_per_env = 24
max_iterations = 20000
save_interval = 100
experiment_name = "agibot_d1_rough"
policy = RslRlPpoActorCriticCfg(
init_noise_std=1.0,
actor_hidden_dims=[512,256,128],
critic_hidden_dims=[512,256,128],
activation="elu",
)
algorithm = RslRlPpoAlgorithmCfg(
clip_param=0.2,
entropy_coef=0.01,
learning_rate=1.0e-3,
gamma=0.99,
lam=0.95,
)
@configclass
class AgibotD1FlatPPORunnerCfg(AgibotD1RoughPPORunnerCfg):
def __post_init__(self):
super().__post_init__()
self.max_iterations = 5000
self.experiment_name = "agibot_d1_flat"
3.4 步骤 3: 创建粗糙地形环境配置
from isaaclab.utils import configclass
from robot_lab.tasks.manager_based.locomotion.velocity.velocity_env_cfg import LocomotionVelocityRoughEnvCfg
from robot_lab.assets.agibot import AGIBOT_D1_CFG
@configclass
class AgibotD1RoughEnvCfg(LocomotionVelocityRoughEnvCfg):
base_link_name = "BASE_LINK"
foot_link_name = ".*_FOOT_LINK"
joint_names = ["FR_ABAD_JOINT","FR_HIP_JOINT","FR_KNEE_JOINT","FL_ABAD_JOINT","FL_HIP_JOINT","FL_KNEE_JOINT","RR_ABAD_JOINT","RR_HIP_JOINT","RR_KNEE_JOINT","RL_ABAD_JOINT","RL_HIP_JOINT","RL_KNEE_JOINT"]
def __post_init__(self):
super().__post_init__()
self.scene.robot = AGIBOT_D1_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot")
self.scene.height_scanner.prim_path = "{ENV_REGEX_NS}/Robot/" + self.base_link_name
self.observations.policy.base_lin_vel.scale = 2.0
self.observations.policy.base_ang_vel.scale = 0.25
self.observations.policy.base_lin_vel = None
self.observations.policy.height_scan = None
self.observations.policy.joint_pos.params["asset_cfg"].joint_names = self.joint_names
self.actions.joint_pos.scale = {".*_ABAD_JOINT":0.125,"^(?!.*_ABAD_JOINT).*":0.25}
self.actions.joint_pos.joint_names = self.joint_names
self.rewards.lin_vel_z_l2.weight = -2.0
self.rewards.ang_vel_xy_l2.weight = -0.05
self.rewards.joint_torques_l2.weight = -2.5e-5
self.rewards.joint_acc_l2.weight = -2.5e-7
self.rewards.track_lin_vel_xy_exp.weight = 3.0
self.rewards.track_ang_vel_z_exp.weight = 1.5
self.rewards.action_rate_l2.weight = -0.01
self.rewards.feet_height_body.weight = -5.0
self.rewards.upward.weight = 1.0
self.rewards.feet_gait.params["synced_feet_pair_names"] = (("FL_FOOT_LINK","RR_FOOT_LINK"),("FR_FOOT_LINK","RL_FOOT_LINK"),)
self.terminations.illegal_contact = None
if self.__class__.__name__ == "AgibotD1RoughEnvCfg":
self.disable_zero_weight_rewards()
3.5 步骤 4: 创建平地环境配置
from isaaclab.utils import configclass
from .rough_env_cfg import AgibotD1RoughEnvCfg
@configclass
class AgibotD1FlatEnvCfg(AgibotD1RoughEnvCfg):
def __post_init__(self):
super().__post_init__()
self.scene.terrain.terrain_type = "plane"
self.scene.terrain.terrain_generator = None
self.scene.height_scanner = None
self.observations.policy.height_scan = None
self.curriculum.terrain_levels = None
if self.__class__.__name__ == "AgibotD1FlatEnvCfg":
self.disable_zero_weight_rewards()
3.6 步骤 5: 注册 Gym 环境
import gymnasium as gym
from . import agents
gym.register(id="RobotLab-Isaac-Velocity-Flat-Agibot-D1-v0", entry_point="isaaclab.envs:ManagerBasedRLEnv", disable_env_checker=True, kwargs={"env_cfg_entry_point":f"{__name__}.flat_env_cfg:AgibotD1FlatEnvCfg","rsl_rl_cfg_entry_point":f"{agents.__name__}.rsl_rl_ppo_cfg:AgibotD1FlatPPORunnerCfg",})
gym.register(id="RobotLab-Isaac-Velocity-Rough-Agibot-D1-v0", entry_point="isaaclab.envs:ManagerBasedRLEnv", disable_env_checker=True, kwargs={"env_cfg_entry_point":f"{__name__}.rough_env_cfg:AgibotD1RoughEnvCfg","rsl_rl_cfg_entry_point":f"{agents.__name__}.rsl_rl_ppo_cfg:AgibotD1RoughPPORunnerCfg",})
完成以上五个步骤后,新机器人就成功集成到 Robot Lab 中了。
4. 调参指南
奖励函数的调优是强化学习训练成功的关键因素之一。不同类型的机器人由于其物理结构、动力学特性和任务需求的差异,需要针对性地设置奖励权重。
Robot Lab 目前支持超过 24 款机器人,涵盖三种主要形态:
| 类型 | 支持的机器人 |
|---|
| 人形机器人 | Unitree G1、Unitree H1、FFTAI GR1T1/GR1T2、Magiclab MagicBot Gen1/Z1、Booster T1、Robotera XBot、OpenLoong Loong、RoboParty Atom01 |
| 四足机器人 | Unitree Go2/A1/B2、Anymal D、Agibot D1、Magiclab MagicDog、DeepRobotics Lite3、ZSIBot ZSL1 |
| 轮式机器人 | Unitree Go2W、DeepRobotics M20 等 |
4.1 四足机器人调参(以 GO2 为例)
4.1.1 核心奖励权重
| 奖励项 | 推荐值 | 作用 |
|---|
track_lin_vel_xy_exp | 3.0 | 线速度跟踪(核心目标) |
track_ang_vel_z_exp | 1.5 | 角速度跟踪 |
lin_vel_z_l2 | -2.0 | 抑制垂直跳动 |
ang_vel_xy_l2 | -0.05 | 抑制翻滚 |
joint_torques_l2 | -2.5e-5 | 能耗惩罚 |
joint_acc_l2 | -2.5e-7 | 动作平滑 |
action_rate_l2 | -0.01 | 动作变化率 |
feet_air_time | 0.1 | 腾空时间奖励 |
feet_gait | 0.5 | 步态同步 |
feet_slide | -0.1 | 滑动惩罚 |
upward | 1.0 | 保持直立 |
4.1.2 调参技巧
问题 1:速度跟踪不收敛
解决方法是增大速度跟踪奖励或减小其他惩罚项的权重。
问题 2:步态不稳定
需要加强步态相关的奖励。feet_gait 奖励鼓励对角腿同步运动。
问题 3:能耗过高
通过增大力矩和功率相关的惩罚可以引导策略学习更加节能的运动方式。
4.2 人形机器人调参(以 G1 为例)
人形机器人的调参与四足有着本质的不同。由于只有两条腿支撑,人形机器人的平衡余量极小,一旦失去平衡很难恢复。因此,人形机器人的配置更加侧重于姿态稳定性和防摔倒。
4.2.1 核心奖励权重
下表对比了 Robot Lab 中支持的主要人形机器人的奖励权重配置:
| 奖励项 | G1 | H1 | GR1T2 | XBot | 说明 |
|---|
track_lin_vel_xy_exp | 3.0 | 3.0 | 5.0 | 2.0 | 核心任务奖励 |
track_ang_vel_z_exp | 3.0 | 3.0 | 5.0 | 2.0 | 角速度跟踪 |
feet_air_time | 0.25 | 1.0 | 1.0 | 2.0 | 迈腿奖励(关键) |
upward | 1.0 | 1.0 | 1.0 | 0.2 | 站立奖励(关键) |
is_terminated | -200 | -200 | -200 | -200 | 摔倒惩罚 |
flat_orientation_l2 | -0.2 | -0.2 | -0.5 | 0 | 姿态惩罚 |
joint_torques_l2 | -1.5e-7 | -1.0e-8 | -2.5e-5 | -2.5e-5 | 能耗惩罚 |
joint_acc_l2 | -1.25e-7 | -2.5e-7 | -2.5e-7 | -2.5e-7 | 动作平滑 |
action_rate_l2 | -0.005 | -0.01 | -0.005 | -0.01 | 动作变化率 |
feet_slide | -0.2 | -0.4 | -0.2 | -0.2 | 滑动惩罚 |
关键发现:从上表可以看出,feet_air_time(腾空时间奖励)和 upward(站立奖励)是人形机器人学会行走的关键。
4.2.2 人形机器人'坐着不走'问题诊断
典型症状:训练 10 万步后,平均 reward 到达 15-25,但机器人保持蹲坐姿态不迈腿。
- 启用并增大迈腿奖励(最重要)
- 增大站立奖励
- 增大速度跟踪奖励
- 减小关节位置惩罚(让机器人敢于动)
4.2.3 人形特殊配置
人形机器人需要一些四足机器人不需要的特殊配置,包括双足专用的腾空时间函数和关节偏差惩罚。
self.rewards.feet_air_time.func = mdp.feet_air_time_positive_biped
self.rewards.feet_air_time.params["threshold"] = 0.4
self.rewards.track_lin_vel_xy_exp.func = mdp.track_lin_vel_xy_yaw_frame_exp
4.2.4 常见问题诊断
问题 1:机器人坐着不走(最常见)
详见 4.2.2 节。核心是启用 feet_air_time 和 upward 奖励。
问题 2:容易摔倒
如果机器人在训练过程中频繁摔倒,需要进一步强化防摔倒的惩罚。
问题 3:姿态不稳/身体晃动
如果机器人能够行走但身体晃动明显,需增大直立奖励和角速度惩罚。
问题 4:迈腿幅度太小/原地踏步
机器人有迈腿动作但位移很小,需增大速度跟踪奖励和腾空时间奖励。
问题 5:步态不对称/单腿支撑时间不均
调整腾空时间阈值或增大关节对称性惩罚。
问题 6:训练初期不稳定/所有机器人集中在最简单地形
人形机器人在训练初期往往连站立都难以完成。必须禁用地形课程学习。
4.3 轮式机器人调参(以 GO2W 为例)
轮式机器人结合了腿式和轮式运动的优点,但也带来了独特的控制挑战。最大的区别在于需要同时处理两种不同类型的关节:腿部关节使用位置控制保持身体高度和姿态,轮子关节则使用速度控制实现行进。
4.3.1 特殊配置
self.actions.joint_pos.joint_names = self.leg_joint_names
self.actions.joint_vel.joint_names = self.wheel_joint_names
self.rewards.joint_torques_l2.params["asset_cfg"].joint_names = self.leg_joint_names
self.rewards.joint_acc_wheel_l2.weight = -2.5e-9
4.3.2 核心差异
| 配置项 | GO2W (轮式) | GO2 (四足) |
|---|
feet_air_time | 0 (禁用) | 0.1 |
feet_gait | 0 (禁用) | 0.5 |
feet_slide | 0 (禁用) | -0.1 |
base_height_l2.target_height | 0.40 | 0.33 |
joint_acc_wheel_l2 | -2.5e-9 | N/A |
轮式机器人禁用了所有与步态相关的奖励,因为轮子始终接触地面,这些概念不再适用。
4.3.3 调参技巧
问题 1:轮子抖动
如果轮子速度输出不稳定、出现高频振动,需要增大轮子加速度惩罚来平滑控制信号。
问题 2:腿部不稳
参考四足机器人的调参方法,增大关节位置相关的惩罚。
4.4 综合调参策略与奖励函数设计
4.4.1 奖励函数完整列表
Robot Lab 基类 LocomotionVelocityRoughEnvCfg 定义了 40+ 个奖励项,以下按类别整理:
track_lin_vel_xy_exp: 指数形式速度跟踪,推荐范围 2.0-5.0
track_ang_vel_z_exp: 指数形式角速度跟踪,推荐范围 1.5-5.0
feet_air_time: 腾空时间奖励,推荐范围 0.1-2.0
feet_gait: 步态同步,推荐范围 0.3-1.0
upward: 直立奖励,推荐范围 0.5-2.0
lin_vel_z_l2: 垂直速度 L2,推荐范围 -1.0 ~ -3.0
ang_vel_xy_l2: 横滚俯仰角速度,推荐范围 -0.05 ~ -0.3
flat_orientation_l2: 姿态偏差,推荐范围 -0.1 ~ -0.5
base_height_l2: 高度偏差,推荐范围 0 ~ -1.0
joint_torques_l2: 关节力矩 L2
joint_acc_l2: 关节加速度 L2
action_rate_l2: 动作变化率
joint_power: 关节功率
feet_slide: 滑动惩罚
feet_stumble: 绊倒惩罚
feet_height: 抬脚高度
is_terminated: 终止惩罚
joint_pos_limits: 关节限位
undesired_contacts: 非期望接触
4.4.2 人形 vs 四足 配置差异总结
| 配置类别 | 四足机器人 | 人形机器人 | 原因 |
|---|
| 速度跟踪 | 3.0 | 3.0-5.0 | 人形需要更强激励 |
| 腾空时间 | 0.1 | 0.25-2.0 | 人形步态关键 |
| 腾空函数 | feet_air_time | feet_air_time_positive_biped | 双足专用 |
| 步态同步 | 0.5 | 0(禁用) | 人形无对角步态 |
| 直立奖励 | 1.0 | 1.0-2.0 | 人形平衡困难 |
| 终止惩罚 | 0 | -200 | 人形摔倒不可恢复 |
| 力矩惩罚 | -2.5e-5 | -1.5e-7 | 人形需要更大力矩 |
| 地形课程 | 启用 | 禁用 | 人形初期无法应对复杂地形 |
| 训练步数 | 200k | 500k-1M | 人形收敛慢 |
4.4.3 从 TensorBoard 诊断问题
训练过程中通过观察 TensorBoard 指标可以快速定位问题:
- Mean Reward: 总奖励的移动平均值,是最重要的训练指标。
- Episode Length: 每个 episode 的平均长度。如果机器人频繁摔倒,这个值会很低。
- Policy Loss / Value Loss: 策略网络和价值网络的损失值。
4.4.4 调参优先级
- 第一优先级:确保机器人有动力行走
track_lin_vel_xy_exp.weight ≥ 3.0
feet_air_time.weight ≥ 0.25(人形)
upward.weight ≥ 1.0
- 第二优先级:确保使用正确的函数
- 人形机器人必须用
feet_air_time_positive_biped
- 人形机器人用
track_lin_vel_xy_yaw_frame_exp
- 第三优先级:禁用不适合的配置
- 人形禁用
curriculum.terrain_levels
- 人形禁用
feet_gait
- 第四优先级:调整平衡参数
4.4.5 快速调参模板
def __post_init__(self):
super().__post_init__()
self.rewards.track_lin_vel_xy_exp.weight = 3.0
self.rewards.track_lin_vel_xy_exp.func = mdp.track_lin_vel_xy_yaw_frame_exp
self.rewards.track_ang_vel_z_exp.weight = 3.0
self.rewards.feet_air_time.weight = 1.0
self.rewards.feet_air_time.func = mdp.feet_air_time_positive_biped
self.rewards.feet_air_time.params["threshold"] = 0.4
self.rewards.upward.weight = 1.0
self.rewards.is_terminated.weight = -200.0
self.rewards.flat_orientation_l2.weight = -0.2
self.rewards.ang_vel_xy_l2.weight = -0.1
self.rewards.joint_torques_l2.weight = -1.5e-7
self.rewards.joint_acc_l2.weight = -1.25e-7
self.rewards.action_rate_l2.weight = -0.005
self.rewards.feet_slide.weight = -0.2
self.curriculum.terrain_levels = None
self.curriculum.command_levels_lin_vel = None
self.curriculum.command_levels_ang_vel = None
def __post_init__(self):
super().__post_init__()
self.rewards.track_lin_vel_xy_exp.weight = 3.0
self.rewards.track_ang_vel_z_exp.weight = 1.5
self.rewards.feet_air_time.weight = 0.1
self.rewards.feet_gait.weight = 0.5
self.rewards.upward.weight = 1.0
self.rewards.lin_vel_z_l2.weight = -2.0
self.rewards.ang_vel_xy_l2.weight = -0.05
self.rewards.joint_torques_l2.weight = -2.5e-5
self.rewards.joint_acc_l2.weight = -2.5e-7
self.rewards.action_rate_l2.weight = -0.01
self.rewards.feet_slide.weight = -0.1
self.rewards.feet_height_body.weight = -5.0
5. 训练与测试命令
完成配置后,就可以开始训练和测试了。Robot Lab 提供了标准化的训练和测试脚本,支持多种常用选项。
5.1 训练命令
训练脚本位于 scripts/reinforcement_learning/rsl_rl/train.py,支持多种命令行参数。
python scripts/reinforcement_learning/rsl_rl/train.py --task=RobotLab-Isaac-Velocity-Rough-Unitree-G1-v0 --headless --num_envs 4096
python scripts/reinforcement_learning/rsl_rl/train.py --task=RobotLab-Isaac-Velocity-Flat-Unitree-G1-v0 --headless --num_envs 4096
python scripts/reinforcement_learning/rsl_rl/train.py --task=RobotLab-Isaac-Velocity-Rough-Unitree-G1-v0 --resume --load_run="2024-01-01_12-00-00"
--headless 参数禁用图形渲染,可以显著提高训练速度。--num_envs 指定并行环境数量,4096 是大多数任务的推荐值。
5.2 测试命令
训练完成后,可以使用测试脚本加载模型并可视化机器人的行为。
python scripts/reinforcement_learning/rsl_rl/play.py --task=RobotLab-Isaac-Velocity-Rough-Unitree-G1-v0 --num_envs 16
python scripts/reinforcement_learning/rsl_rl/play.py --task=RobotLab-Isaac-Velocity-Rough-Unitree-G1-v0 --video --video_length 200
5.3 TensorBoard 监控
TensorBoard 是监控训练过程的重要工具。
tensorboard --logdir=logs/rsl_rl
在 TensorBoard 中,重点关注以下指标:
- Mean Reward:总奖励的移动平均值。
- Episode Length:每个 episode 的平均长度。
- Policy Loss / Value Loss:策略网络和价值网络的损失值。
6. 总结
本文系统性地介绍了 Robot Lab 强化学习项目的核心设计理念与实现细节。通过对配置继承体系、机器人添加流程和调参策略的深入剖析,读者应该能够:
- 理解配置继承机制:从
ManagerBasedRLEnvCfg 基类到机器人特定配置的完整继承链。
- 掌握新机器人添加流程:包括资产配置、环境配置、Agent 配置以及 Gym 环境注册的完整五步流程。
- 应用调参策略:针对四足、人形、轮式三种不同类型机器人的特点,给出了具体的奖励权重设置建议和常见问题的解决方案。
Robot Lab 的设计体现了软件工程中'开放封闭原则'的精髓——对扩展开放(轻松添加新机器人),对修改封闭(无需修改基类即可定制行为)。
参考资料
相关免费在线工具
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- RSA密钥对生成器
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
- Mermaid 预览与可视化编辑
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
- 随机西班牙地址生成器
随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online
- Gemini 图片去水印
基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
- curl 转代码
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online