请你阅读这个文件夹中的四个.py文件,并详细告诉我这四个文件的作用。请再详细告诉我legged_robot_config.py中的参数都有什么作用。
| |
base_config.py
| |
base_task.py
| |
legged_robot.py
| |
legged_robot_config.py
| |
legged_robot.py 代码解析
整体思路
LeggedRobot 类是用于腿式机器人强化学习环境的核心实现,基于 NVIDIA Isaac Gym 框架。其主要功能包括:
- 仿真环境管理:创建和维护机器人、地形及物理仿真环境。
- 动作执行与物理模拟:将智能体输出的动作转换为关节扭矩,并驱动物理引擎进行仿真。
- 观测与奖励计算:根据机器人状态计算观测值和奖励函数。
- 环境重置与课程学习:支持动态调整地形难度和任务复杂度(curriculum learning)。
- 域随机化(Domain Randomization):通过随机化摩擦力、质量等参数提高策略泛化能力。
代码结构遵循模块化设计,通过回调函数处理机器人属性配置,并利用 PyTorch 张量实现 GPU 加速的并行计算。
核心方法详解
初始化与环境创建
| |
- 功能:初始化环境配置,创建物理仿真环境,加载机器人模型。
- 关键步骤:
- 解析配置文件 (
_parse_cfg) - 调用父类
BaseTask初始化 - 构建地形 (
create_sim) - 初始化缓冲区 (
_init_buffers) - 准备奖励函数 (
_prepare_reward_function)
- 解析配置文件 (
| |
- 功能:创建物理仿真环境和地形。
- 实现:
- 支持平面、高度场(heightfield)和三角网格(trimesh)地形
- 调用
_create_envs创建多个并行环境实例
核心控制循环
| |
- 功能:执行一步环境交互
- 流程:
- 动作裁剪 (
torch.clip) - 执行
decimation次物理模拟步(降低控制频率) - 调用
post_physics_step()处理后续计算 - 返回观测、奖励和终止标志
- 动作裁剪 (
| |
- 功能:物理模拟后的处理
- 关键操作:
- 更新机器人状态(线速度、角速度、重力投影)
- 调用
_post_physics_step_callback(命令重采样、地形高度测量) - 检查终止条件 (
check_termination) - 计算奖励 (
compute_reward) - 环境重置 (
reset_idx) - 生成观测值 (
compute_observations)
环境管理与重置
| |
- 功能:重置指定环境
- 关键逻辑:
- 地形课程更新 (
_update_terrain_curriculum) - 命令范围课程更新 (
update_command_curriculum) - 重置 DOF 状态 (
_reset_dofs) - 重置根状态 (
_reset_root_states) - 缓冲区清零
- 地形课程更新 (
| |
- 功能:随机化关节位置(在默认值 ±50% 范围内)
| |
- 功能:重置机器人根部状态(位置、速度)
奖励函数系统
| |
- 功能:聚合所有奖励项
- 机制:
- 遍历所有非零奖励项(如
_reward_lin_vel_z,_reward_tracking_lin_vel) - 应用缩放系数并累加
- 支持仅保留正奖励(
only_positive_rewards)
- 遍历所有非零奖励项(如
典型奖励项示例:
| |
物理属性回调函数
| |
- 功能:随机化摩擦系数(domain randomization)
| |
- 功能:存储 DOF 限制(位置、速度、扭矩)
| |
- 功能:随机化机器人基础质量
地形与高度测量
| |
- 功能:获取机器人周围地形高度
- 实现:
- 基于 base 姿态变换采样点
- 使用双线性插值计算高度
- 支持多种地形类型(heightfield/trimesh)
| |
- 功能:初始化高度测量点(网格布局)
关键数据流
动作 → 扭矩
actions→_compute_torques(PD 控制器) →gym.set_dof_actuation_force_tensor观测生成
compute_observations组合以下信息:- 基础速度
- 重力投影
- 命令值
- 关节状态
- 地形高度(可选)
奖励计算
各奖励项通过独立函数实现,最终通过compute_reward聚合
课程学习(Curriculum Learning)
| |
- 机制:
- 根据机器人移动距离动态调整地形难度
- 达到阈值时升级/降级地形级别
- 最终地形由
terrain_levels和terrain_types控制
| |
- 机制:
- 根据线速度跟踪表现扩展命令范围
- 提高最大前进速度阈值
域随机化(Domain Randomization)
- 摩擦系数:每个环境独立随机化
- 基础质量:在默认值基础上添加随机质量
- 初始状态扰动:位置、速度的随机偏移
- 传感器噪声:观测值添加随机噪声(
_get_noise_scale_vec)
性能优化
- Decimation:降低控制频率(
control.decimation),减少 GPU 负载 - 批量操作:使用 PyTorch 张量批量处理多个环境
- 内存优化:通过
gymtorch.wrap_tensor直接操作 GPU 内存
调试与可视化
| |
- 功能:绘制高度测量点(黄色小球)
- 条件:仅在启用
debug_viz时生效
该实现完整覆盖了腿式机器人强化学习环境的关键要素,通过模块化设计实现了灵活的配置和高效的并行计算。
对,你的理解很对 —— 这份 LeggedRobot 类的代码可以清晰地分成几个职责区块(或者“模块”/“区域”),每一块负责不同的工作。下面我按“区域”把所有重要函数/方法按职责分类并逐一说明它们的作用、输入、处理和输出,以及相互关系与注意点。为了方便阅读我会先给出总体分区列表,再对每个区块内的方法逐个解释(中文、务实、直白)。
总体分区(高层)
- 初始化 / 主流程相关:
__init__,step,post_physics_step,负责生命周期和主循环。 - 仿真创建与环境管理:
create_sim,_create_envs,_create_ground_plane,_create_heightfield,_create_trimesh,_get_env_origins。 - 状态/缓冲区初始化:
_init_buffers,_init_height_points。 - 回调 / 属性处理(在创建环境时被调用):
_process_rigid_shape_props,_process_dof_props,_process_rigid_body_props。 - 控制器(从 action 到 torques):
_compute_torques。 - 重置与扰动:
reset_idx,_reset_dofs,_reset_root_states,_push_robots。 - 命令/课程(curriculum)管理:
_resample_commands,_post_physics_step_callback,_update_terrain_curriculum,update_command_curriculum。 - 观测与噪声:
compute_observations,_get_noise_scale_vec。 - 高度测量相关:
_init_height_points,_get_heights,_draw_debug_vis。 - 奖励体系:
_prepare_reward_function(构造器),以及一堆_reward_*函数(实际的奖励项)。 - 配置解析 / 工具:
_parse_cfg等小工具函数。
下面我按上面的分区逐一详细说明每个方法(含输入、处理、输出、注意点)。
1. 初始化 / 主流程相关
__init__(self, cfg, sim_params, physics_engine, sim_device, headless)
- 作用:构造函数,解析配置,调用父类创建仿真环境(通过
super()),设置摄像头,初始化缓冲区与奖励函数表。 - 输入:
cfg(配置对象LeggedRobotCfg)、sim_params(gym 的 SimParams)、physics_engine(物理后端)、sim_device、headless(是否无头)。 - 处理:
- 保存 cfg、sim_params 等;
_parse_cfg(cfg)解析一些派生变量(如dt,max_episode_length);- 调用
super().__init__(父类BaseTask会负责create_sim()的调用与 viewer 等); - 若非 headless,设置相机;
_init_buffers():初始化所有 torch 缓冲区(非常关键);_prepare_reward_function():准备 reward 函数列表和缩放;- 标记
init_done = True。
- 输出:无(对象初始化完毕)。
- 注意:很多后续方法依赖
_init_buffers()中的张量已存在(例如self.dof_pos,self.root_states),因此初始化顺序很关键。
step(self, actions)
- 作用:主执行步骤 —— 接收动作、执行控制、推进物理、多步子步(decimation),然后返回观测/奖励/重置信息给训练算法。
- 输入:
actions,形状通常(num_envs, num_actions)的 torch.Tensor。 - 处理:
- 对 actions 做剪切(
clip_actions)并移到正确设备; render()(如果开启渲染);- 循环
decimation次:计算 torques(_compute_torques),把 torques 写入 gym 的 DOF actuation,调用gym.simulate(),取回状态(CPU 模式时需要fetch_results),刷新 DOF 状态张量; - 调用
post_physics_step()(处理观测、奖励、重置等); - 对输出 obs 做裁剪,返回
(obs_buf, privileged_obs_buf, rew_buf, reset_buf, extras)。
- 对 actions 做剪切(
- 输出:五元组(obs、privileged obs 或 None、reward、done/reset 布尔、额外信息
extras)。 - 注意:
decimation控制动作的更新频率 vs. 仿真步长的比例;step是训练循环调用的入口。
post_physics_step(self)
- 作用:物理推进后统一的后处理 —— 刷新根状态/接触力、更新各种速度/姿态量、调用回调、检查终止、计算奖励、重置、计算观测等。
- 输入:无(使用内部张量)。
- 处理:
gym.refresh_actor_root_state_tensor,gym.refresh_net_contact_force_tensor;- 更新内部计数器(
episode_length_buf,common_step_counter); - 计算
base_quat,base_lin_vel,base_ang_vel,projected_gravity(把全局速度换算到 base frame); _post_physics_step_callback()调用(定期采样命令、测高度、随机推等);check_termination()、compute_reward();- 找到需要重置的 env(
reset_buf.nonzero()),调用reset_idx(env_ids); compute_observations();- 记录
last_actions,last_dof_vel,last_root_vel; - 可选 debug 可视化
_draw_debug_vis()。
- 输出:无(内部状态更新并准备好输出)。
2. 仿真创建与环境管理
create_sim(self)
- 作用:实际创建 gym/IsaacGym 的
sim,并创建地形与环境。 - 输入:无(使用
self.sim_params,self.cfg)。 - 处理:
- 设置
up_axis_idx(这里用 z=2); gym.create_sim(...)创建仿真对象;- 根据
cfg.terrain.mesh_type选择构建地形 (Terrain、plane、heightfield、trimesh); - 调用
_create_envs()在场景里实例化每个 robot 环境。
- 设置
- 输出:无(创建
self.sim,self.terrain,self.envs等)。
_create_envs(self)
- 作用:加载 robot asset(URDF/MJCF),并对每个 env 创建 actor,设置 DOF/刚体属性,记录 body/dof 索引。
- 输入:无(使用
self.cfg.asset、self.env_origins等)。 - 处理:
- 组合 asset_path,设置
gymapi.AssetOptions(来自 cfg.asset); gym.load_asset(...)得到robot_asset,并读取 DOF/刚体数量与属性;- 识别 body 名称、dof 名称,找出 feet、penalized contact、termination contact 的名字集合;
- 将
base_init_state变为 torch 张量; - 调用
_get_env_origins()得到每个 env 的起点; - 循环
num_envs:gym.create_env->self._process_rigid_shape_props->gym.set_asset_rigid_shape_properties->gym.create_actor->_process_dof_props->gym.set_actor_dof_properties->_process_rigid_body_props->gym.set_actor_rigid_body_properties; - 记录
feet_indices,penalised_contact_indices,termination_contact_indices(用于接触检测与奖励/终止判定)。
- 组合 asset_path,设置
- 输出:无(内部数据结构填充完毕)。
_create_ground_plane, _create_heightfield, _create_trimesh
- 作用:根据 cfg 创建不同类型地面(平面/高度图/三角网格),并把材质摩擦/弹性参数写入。
- 输入:
self.terrain(对于 heightfield/trimesh)和cfg.terrain。 - 处理:
- 创建相应的 gym 参数对象,设置 scale, nbRows/nbColumns, transform, friction/restitution 等;
- 调用
gym.add_ground/gym.add_heightfield/gym.add_triangle_mesh; - 对 heightfield/trimesh 保存
self.height_samples为张量以便后续查询。
- 输出:无。
_get_env_origins(self)
- 作用:确定每个 env 的初始位置(在粗糙地形时来自 terrain 平台,否则生成网格排列),并初始化
terrain_levels、terrain_types。 - 输入:
cfg.terrain与num_envs等。 - 处理:
- 如果是 heightfield/trimesh:从
self.terrain.env_origins中读取平台 origin,并随机化初始 terrain level; - 否则创建按
env_spacing的网格排列位置。
- 如果是 heightfield/trimesh:从
- 输出:无(写
self.env_origins等)。
3. 状态/缓冲区初始化
_init_buffers(self)
- 作用:把 gym 的状态张量包装成 torch 张量,并创建所有训练/计算需要的中间缓存(obs_buf、rew_buf、各种速度、动作历史、PD gains 等)。非常关键。
- 输入:需要
self.sim已创建(即在create_sim()之后或由父类在合适时机调用)。 - 处理:
gym.acquire_actor_root_state_tensor,gym.acquire_dof_state_tensor,gym.acquire_net_contact_force_tensor,并wrap_tensor成 torch 张量(self.root_states,self.dof_state,self.contact_forces);- 从
dof_state切片得到dof_pos,dof_vel;从root_states切片得到base_quat等; - 初始化
self.torques,self.p_gains,self.d_gains,self.actions,self.last_actions等; - 通过
cfg.init_state.default_joint_angles设置self.default_dof_pos;根据cfg.control.stiffness/damping填p_gains/d_gains(按 dof 名称匹配)。
- 输出:无(初始化一堆关键张量)。
- 注意:
- 这里把很多东西放在 GPU(或 CPU),确保 device 一致;
self.dof_names、self.num_dofs等必须先被填好(由_create_envs)。
_init_height_points(self)
- 作用:根据 cfg 中提供的
measured_points_x/measured_points_y在 base frame 生成一批测高点坐标,返回(num_envs, n_points, 3)的张量(x,y,z,其中 z 暂为 0)。 - 输入:
cfg.terrain.measured_points_x/y、num_envs。 - 处理:网格化 x,y,flatten 后填充到每个 env 的 points(x,y列),z 默认 0。
- 输出:
self.height_points,并记录self.num_height_points。
4. 回调 / 属性处理(环境创建阶段会调用)
_process_rigid_shape_props(self, props, env_id)
- 作用:可用于随机化每个 env 中每个 shape 的摩擦等刚体形状参数。默认实现:若
cfg.domain_rand.randomize_friction,为每个 env 选一个摩擦系数并写入props[s].friction。 - 输入:
props(asset 的 rigid shape properties 列表/数组),env_id。 - 处理:
- 当
env_id == 0时会为整个批次构造 friction_buckets 与 bucket_ids; - 用
self.friction_coeffs[env_id]给每个 shape 的 friction 赋值。
- 当
- 输出:返回修改后的
props(供gym.set_asset_rigid_shape_properties使用)。 - 扩展点:用户可以覆写或在子类中修改来随机化 restitution、摩擦各向异性等。
_process_dof_props(self, props, env_id)
- 作用:在创建 actor 时对 DOF 属性做进一步处理或记录(例如读取 URDF 给出的 pos/vel/torque limits 并写入到
self.dof_pos_limits、self.dof_vel_limits、self.torque_limits)。 - 输入:
props(每个 DOF 的属性结构),env_id。 - 处理:
- 仅在
env_id==0时填充dof_pos_limits,dof_vel_limits,torque_limits;同时基于 cfg.rewards.soft_dof_pos_limit 调整软限制区间。
- 仅在
- 输出:返回可能修改过的
props(继续被写回到 actor)。
_process_rigid_body_props(self, props, env_id)
- 作用:对 asset 刚体属性(质量等)进行随机化,比如随机增加 base mass(
cfg.domain_rand.randomize_base_mass)。 - 输入:
props(刚体属性列表),env_id。 - 处理:如果允许随机化,在
props[0].mass上加一个随机量。 - 输出:返回修改后的
props。
5. 控制器(action -> torques)
_compute_torques(self, actions)
- 作用:将网络输出的 actions 转换为实际发送给 simu 的扭矩(torques)。支持三类 control type:P(位置 PD)、V(速度 PD)、T(直接扭矩)。
- 输入:
actions((num_envs, num_actions),通常 -1..1,随后乘以cfg.control.action_scale)。 - 处理:
actions_scaled = actions * action_scale;- 若
control_type=="P":torques = p_gains * (actions_scaled + default_dof_pos - dof_pos) - d_gains * dof_vel(目标角度 = actions_scaled + default); - 若
"V":torques = p_gains*(actions_scaled - dof_vel) - d_gains*(dof_vel - last_dof_vel)/sim_dt(目标速度); - 若
"T":torques = actions_scaled(直接把 scaled action 当作扭矩); - 最后 clip 到
[-torque_limits, torque_limits]。
- 输出:
torques张量,shape 与num_actions对应。 - 注意:
p_gains/d_gains是每个 DOF 的比例/微分增益;PD 控制用法和单位必须与 URDF 的关节定义匹配。
6. 重置与扰动
reset_idx(self, env_ids)
- 作用:对一组需要 reset 的 env 执行重置步骤(环境课程更新、命令重采样、DOF/ROOT 状态重置、缓冲清零、统计上报)。
- 输入:
env_ids(tensor或长列表,含要重置的 env id)。 - 处理:
- 可选地调用
_update_terrain_curriculum(env_ids)与update_command_curriculum(env_ids); - 调用
_reset_dofs(env_ids),_reset_root_states(env_ids),_resample_commands(env_ids); - 清零
last_actions,last_dof_vel,feet_air_time等,并设置episode_length_buf[env_ids]=0、reset_buf[env_ids]=1; - 填写
extras["episode"]:每个 reward 的平均值与课程信息(terrain_level、max_command_x); - 如果 cfg.env.send_timeouts 则
extras["time_outs"] = self.time_out_buf。
- 可选地调用
- 输出:无(状态被重置)。
_reset_dofs(self, env_ids)
- 作用:将指定 env 的各关节位置设为
default_dof_pos的随机比例(0.5~1.5倍),速度清零,并把其 DOF 状态写回仿真。 - 输入:
env_ids。 - 处理:通过
torch_rand_float生成随机系数,写self.dof_pos[env_ids]和self.dof_vel[env_ids],再调用gym.set_dof_state_tensor_indexed。 - 输出:无。
_reset_root_states(self, env_ids)
- 作用:重置根(base)位姿与速度。
- 输入:
env_ids。 - 处理:
- 若
custom_origins(rough terrain),则把root_states[env_ids] = base_init_state并加上 terrain origin(并在 xy 上小幅随机偏移);否则只加 env_origins; root_states[env_ids, 7:13](线速度与角速度)被随机化在 [-0.5,0.5];- 写回仿真
gym.set_actor_root_state_tensor_indexed。
- 若
- 输出:无。
_push_robots(self)
- 作用:模拟突的外力:通过一次性设置 base 的线速度来“推”机器人(作为域随机的一部分),在训练中强化鲁棒性。
- 输入:无(使用 cfg.domain_rand.max_push_vel_xy)。
- 处理:
root_states[:, 7:9] = rand(-max_vel, max_vel),写回 root states。 - 输出:无。
7. 命令 / 课程(Curriculum)管理
_resample_commands(self, env_ids)
- 作用:为指定 env 重新采样控制命令(线速度 x/y、角速度或 heading),作为训练任务的输入命令。
- 输入:
env_ids。 - 处理:
- 用
torch_rand_float在command_ranges范围内采样lin_vel_x,lin_vel_y; - 如果
heading_command为真,采样heading到commands[:,3];否则采样ang_vel_yaw到commands[:,2]; - 把小幅命令(norm < 0.2)设为 0(避免无意义的小动作)。
- 用
- 输出:无(修改
self.commands)。
_post_physics_step_callback(self)
- 作用:物理步之后的额外处理(在
post_physics_step中被调用):定期重采样命令、如果使用 heading 模式则把 heading 转换为 yaw 角速度命令、测高度、周期性推机器人。 - 输入:无(使用内部计时器与 cfg)。
- 处理:
- 计算满足
resampling_time的 env_ids 并调用_resample_commands; - 若
heading_command,依据 base 方向和 heading 计算 yaw 速度命令commands[:,2]; - 若
measure_heights,调用_get_heights()更新measured_heights; - 若开启
push_robots并到达push_interval,调用_push_robots()。
- 计算满足
- 输出:无(更新 commands / heights / 推动)。
_update_terrain_curriculum(self, env_ids) 与 update_command_curriculum(self, env_ids)
- 作用:实现课程学习逻辑:根据机器人是否完成任务(走远、追踪奖励高)来调整 terrain level 或命令难度(扩大 command 范围)。
- 输入:
env_ids(待调整的 env 索引)。 - 处理:
_update_terrain_curriculum:比较机器人行走距离与terrain.env_length / 2判断 move_up 或 move_down,更新terrain_levels,并把成功的送到下一级或随机回溯;更新env_origins;update_command_curriculum:若tracking_lin_vel的平均成绩超过阈值(0.8 * scale),则扩展command_ranges["lin_vel_x"](上下限分别扩展)。
- 输出:无(修改课程相关参数)。
8. 观测与噪声
compute_observations(self)
- 作用:构建每个 env 的观测向量
obs_buf(包含基座线/角速度、重力投影、命令、关节位置偏差、关节速度、上一步动作)并追加地形测高与噪声。 - 输入:内部状态张量(
base_lin_vel,base_ang_vel,projected_gravity,commands,dof_pos,default_dof_pos,dof_vel,actions等)。 - 处理:
torch.cat把各个部分按顺序拼接(并乘以obs_scales进行归一化);- 若
cfg.terrain.measure_heights:计算heights = clip(root_z - 0.5 - measured_heights, -1,1) * obs_scales.height_measurements并拼接到 obs; - 若
add_noise:把噪声向量(由_get_noise_scale_vec返回)乘随机均匀噪声并加到 obs。
- 输出:
self.obs_buf(形状(num_envs, obs_dim))。 - 注意:obs 的结构必须与训练网络的
num_observations匹配。
_get_noise_scale_vec(self, cfg)
- 作用:构建与
obs_buf[0]同形状的噪声尺度向量,用于按元素缩放均匀噪声。 - 输入:
cfg.noise和self.obs_scales。 - 处理:根据 cfg 分段设置不同观测部分的噪声量(lin_vel, ang_vel, gravity, dof_pos, dof_vel, height_measurements 等)。
- 输出:噪声尺度向量
noise_vec。
9. 高度测量 / 可视化
_init_height_points(self)(已在「缓冲区初始化」中解释)
- 作用:生成相对于 base 的测高点网格(x,y), 返回
(num_envs, n_points, 3)。
_get_heights(self, env_ids=None)
- 作用:在地形上采样指定点的高度值(将 base frame 的点转换到 world/heightfield 索引并从
self.height_samples中取值)。 - 输入:
env_ids(可选,若不传则对所有 env 采样)。 - 处理:
- 若地形类型为 plane 返回零高度;若 none 抛错;
- 通过
quat_apply_yaw把 base 的 yaw 旋转应用到测点(得到世界坐标),再加上root_states[:, :3]得到全局点坐标; - 为了索引 height samples 做偏移、缩放(
border_size,horizontal_scale),然后转成整数索引并 clip 到合法范围; - 从
height_samples中获取 3 个相邻格子的高度 (heights1/2/3) 并取 min(作者用了 min,以避免某些网格边界问题?); - reshape 回
(num_envs, -1)并乘vertical_scale返回物理高度值。
- 输出:
heights,shape(num_envs, num_height_points)。 - 注意:采样时需要确保
self.height_samples已经初始化(在创建 heightfield/trimesh 时有赋值)。
_draw_debug_vis(self)
- 作用:基于
measured_heights在 viewer 中绘制小球或线,用于调试高度采样。 - 输入:viewer 已存在且
terrain.measure_heights为 True。 - 处理:按 env 循环,通过
gymutil.draw_lines在位置处画 wireframe sphere。 - 输出:无(仅用于可视化)。
10. 奖励体系(reward)
_prepare_reward_function(self)
- 作用:从 cfg 中读取 reward scales,把非零的 reward 加入到
self.reward_functions列表(映射到_reward_前缀的函数),并把 scale 乘以dt(时间增量)以便用作每步累加。还初始化episode_sums用于统计。 - 输入:
self.reward_scales已由_parse_cfg从 cfg 转换得到。 - 处理:
- 删除 scale==0 的项(节省计算);
- 每个非
termination的 reward 名称拼接_reward_<name>,取函数引用放到reward_functions; - 每个 scale *= self.dt;
- 初始化
episode_sums(用于后续平均/记录)。
- 输出:无(但填充
reward_functions,reward_names,episode_sums)。
_reward_*(一系列)
- 作用:每个
_reward_xxx计算一个原始的 reward 项(未乘 scale),返回形状(num_envs,)的张量。常见项包括:_reward_lin_vel_z:惩罚 z 方向线速度(base_lin_vel[:,2]^2);_reward_ang_vel_xy:惩罚 x,y 轴角速度(sum(square(base_ang_vel[:, :2]), dim=1));_reward_orientation:惩罚倾斜(projected_gravity的 xy 分量平方和);_reward_tracking_lin_vel:速度追踪(用 exp(-error/tracking_sigma));_reward_feet_air_time:奖励更长的步态空中时间(复杂、基于接触过滤);- 还有扭矩、关节速度/加速度限制、碰撞惩罚、终止惩罚等。
- 输入:使用类内已存在的各种张量(
self.base_lin_vel、self.commands、self.contact_forces等)。 - 处理:按定义做数学计算并返回
(num_envs,)。 - 输出:每个 reward 函数返回单独项,
compute_reward()中会把它们乘以对应的 scale 并累加到self.rew_buf与episode_sums。
compute_reward(self)
- 作用:遍历
self.reward_functions,调用每个 reward,乘以 scale 并叠加;可选地把负值裁为 0(only_positive_rewards);最后把terminationreward(若存在)加上。 - 输入:无(使用
self.reward_functions与self.reward_scales)。 - 处理:
self.rew_buf[:] = 0.;- 对于每个 reward 调用并累加到
rew_buf与episode_sums; - 可选 clip(只保留正 reward);
- 终止奖励在之后单独加。
- 输出:写入
self.rew_buf,self.episode_sums。
11. 配置解析 / 工具
_parse_cfg(self, cfg)
- 作用:从 cfg 读取并计算一些派生量(例如
dt = control.decimation * sim_params.dt、max_episode_length = ceil(episode_length_s / dt)、把 reward scales/command ranges 用class_to_dict转成字典等)。 - 输入:
cfg。 - 处理:如上,主要是把易用的变量存在实例中。并把
cfg.domain_rand.push_interval_s转换为 step 数。 - 输出:无(填内部变量)。
结论 / 你可以如何理解这份架构(要点)
- 是的,可以把整个类看成若干“功能区”:
- 主循环/接口层(
step,post_physics_step) —— 对外(训练代码)交互; - 仿真与环境创建层 —— 把 URDF/MJCF 加进模拟,建立地形;
- 状态缓冲层 —— 把 gym 的原始张量包装成 torch,用于高效并行计算;
- 回调/随机化层 —— 在资产创建或每次 step 时注入域随机、摩擦随机、推力随机、命令随机等;
- 控制器层 —— action 到 torque 的映射;
- 观测与噪声层 —— 构建 agent 的观测向量;
- 奖励层 —— 计算并组合不同奖励项。
- 主循环/接口层(
- 这种模块化使得你可以 单独替换/扩展任意一个区域:比如想改 reward,只加/改
_reward_xxx并在 cfg 中设置 scale;想改命令/课程策略就改_resample_commands或update_command_curriculum;想改动作表示(从 P 改到 T)只改 cfg.control.control_type。
实战建议 / 注意点(务实)
- 修改 reward 函数的时候要注意 返回 shape 必须是
(num_envs,),且不要忘了_prepare_reward_function会把 scale 乘以dt;scale 为 0 的项会被剔除。 obs_buf的构成必须和训练网络的输入维度env.num_observations对齐,否则会维度错配。- 在多环境并行训练时(大规模
num_envs),确保 tensor device(CPU/GPU)一致,避免频繁的 device copy。 self.dof_names与cfg.control.stiffness的匹配是基于字符串包含(if dof_name in name),如果你的 dof 名称与 cfg 不匹配,会出现p_gains为 0 的警告。height采样、terrain相关的索引逻辑(取最小的三个邻近格)是实现细节,若你使用较粗/细格子或不同边界策略,需留意边界条件(clip 的部分)。
如果你愿意,我可以接着做两件事(选其一或两个都做):
- 把上面按“区域”整理成一张简化的函数调用关系图(文本版或伪代码流程图),帮助你快速定位函数调用链;
- 给出一个修改 reward 或加入新的回调 的示例代码片段,演示如何安全地扩展(并说明要修改哪些 cfg 字段)。
你想先看哪一个?
下面我按 每个 class 一个一节 来解释 LeggedRobotCfg(和 LeggedRobotCfgPPO)里每个字段的语义、单位、典型取值、对仿真/训练的影响以及注意事项。为了易读,每个字段会给出「作用 / 含义」、「单位/类型 / 典型范围」和「影响与提示」。
env(环境总体参数)
- num_envs
- 含义:并行环境数量(同时在 GPU/CPU 上模拟的独立机器人实例数)。
- 类型/典型值:整数(示例 4096)。
- 影响:越多并行样本速度越高(样本效率),但显著增加显存/内存和物理碰撞计算负担。选择受硬件限制。
- num_observations
- 含义:每个环境的观测向量长度(神经网络输入维度)。
- 类型:整数(示例 235)。
- 影响:必须与 agent 的网络输入一致。改动需同步网络结构。
- num_privileged_obs
- 含义:是否使用 privilege observations(用于不对称训练,给 critic 更多信息)。
None表示不使用。 - 类型:整数或 None。
- 影响:若不为 None,
step()会返回privileged_obs_buf。用于带辅助信息的 critic。
- 含义:是否使用 privilege observations(用于不对称训练,给 critic 更多信息)。
- num_actions
- 含义:每个环境的动作维度(网络输出数)。
- 类型:整数(示例 12)。
- 影响:要和机器人 actuated DOFs 或控制策略一致。
- env_spacing
- 含义:在平面/非自定义地形时,环境网格之间的间距(m)。多个 env 在场景中布置成网格时使用。
- 单位:米(示例 3.0)。
- 影响:过小会导致 env 之间互相干扰(碰撞/渲染问题),过大浪费空间。
- send_timeouts
- 含义:是否在
extras中报告超时信息。 - 类型:bool。
- 影响:若 True,训练算法可以区分是超时结束还是被终止(有助于奖励/统计分析)。
- 含义:是否在
- episode_length_s
- 含义:单个 episode 的时长(秒)。
- 单位:秒(示例 20)。
- 影响:与
dt、decimation联合决定步数(max_episode_length = ceil(episode_length_s / dt))。太短可能无法学习长任务,太长训练收敛慢。
terrain(地形与地形课程参数)
- mesh_type
- 含义:地形类型,选项:
none、plane、heightfield、trimesh。trimesh表示使用三角网格地形。 - 影响:不同地形影响碰撞、接触报告、测高逻辑等。
- 含义:地形类型,选项:
- horizontal_scale / vertical_scale
- 含义:高度图网格的水平/垂直缩放(将离散高度样本转换为米)。
- 单位:米(示例 horizontal 0.1 m, vertical 0.005 m)。
- 影响:控制 terrain 的物理尺寸与分辨率。vertical_scale 小会把样本高度压缩。
- border_size
- 含义:高度图或三角网格的边界偏移量(用于坐标变换/索引)。
- 单位:米(示例 25)。
- curriculum
- 含义:是否启用地形课程学习(逐步增加难度)。
- 类型:bool。
- 影响:若 True,会使用
_update_terrain_curriculum动态调整terrain_levels。
- static_friction / dynamic_friction / restitution
- 含义:地面静/动摩擦系数和弹性系数。
- 影响:直接影响接触力和走路稳定性。域随机时这些可随机化。
- measure_heights
- 含义:是否启用机器人周围点位的高度测量(作为观测的一部分)。
- 影响:若 True,观测向量会包含地形高度信息(提高感知但增加 obs 维度)。
- measured_points_x / measured_points_y
- 含义:以 base frame 为参考的测高采样点列表(x、y 坐标的集合,组成采样网格)。
- 单位:米(示例数组)。
- 影响:决定观测中高度信息的空间分辨率与覆盖区域。
- selected / terrain_kwargs
- 含义:用于手动选择具体 terrain 类型及其参数(高级用法)。
- 类型:bool / dict。
- max_init_terrain_level
- 含义:初始地形难度等级的最大值(课程起始),用于随机初始化 terrain_levels。
- terrain_length / terrain_width
- 含义:单个地形平台的尺寸(m),用于粗糙地形布局。
- num_rows / num_cols
- 含义:地形集合的行数(等级)与列数(类型)—— 用于把多种地形以矩阵方式组织(课程中不同列代表不同地形类型)。
- 影响:影响
terrain_origins布局与terrain_levels取值范围。
- terrain_proportions
- 含义:各类地形在生成时的占比(例如:斜坡、台阶等)。
- 影响:用于生成 terrain 时的概率分配(用于多样化训练集)。
- slope_treshold
- 含义:仅 trimesh 时使用,高于该坡度阈值的斜面会被修正为垂直面(防止穿透/不稳定接触)。
- 影响:控制地形可行走表面与不可行走区域的分界。
commands(外部运动命令 / 任务参数)
- curriculum
- 含义:是否对命令范围使用课程学习(逐步增大 max command)。
- 影响:如果 True,
update_command_curriculum会根据表现扩大命令范围。
- max_curriculum
- 含义:命令课程允许的最大线速度(或范围扩展界限)。
- 影响:限制课程中
lin_vel_x的上限。
- num_commands
- 含义:命令矢量的长度(例如 [lin_vel_x, lin_vel_y, ang_vel_yaw, heading])。
- 影响:决定
self.commands的维度以及compute_observations中拼接的位置。
- resampling_time
- 含义:命令在多少秒后重采样(s)。
- 单位:秒(示例 10s)。
- 影响:命令变化频率影响学习难度与策略鲁棒性。
- heading_command
- 含义:是否使用 heading 模式(用 heading 错误计算 yaw 角速度命令)。
- 影响:若 True,
commands[:,3]存 heading,_post_physics_step_callback会把 heading 转换为 yaw 速度命令。
- ranges.lin_vel_x / lin_vel_y / ang_vel_yaw / heading
- 含义:各命令的最小/最大值范围(例:线速度→m/s,角速度→rad/s,heading→rad)。
- 影响:训练时 agent 需要在此范围内跟踪命令;课程策略会扩展/收窄这些范围。
init_state(初始位姿/速度与关节默认角)
- pos
- 含义:机器人 base 的初始位置 [x,y,z](m)。
- rot
- 含义:初始四元数 [x,y,z,w](表示朝向)。
- lin_vel / ang_vel
- 含义:初始线速度和角速度向量(m/s,rad/s)。
- default_joint_angles
- 含义:动作为 0 时各关节的目标角度(作为 default_dof_pos),通常以字典形式按 joint 名称给出。
- 影响:控制策略(尤其 P 控制)会以
default_joint_angles为基准;设置不合理可能导致启动抖动或不自然姿态。
control(控制器相关)
- control_type
- 含义:动作解释类型:
'P'(位置目标 PD 控制),'V'(速度目标 PD 控制),'T'(直接扭矩)。 - 影响:决定
_compute_torques如何将 action 转换为 torques。不同类型对 reward/稳定性影响大。
- 含义:动作解释类型:
- stiffness(比例增益)
- 含义:每种关节/关节组的 P(比例)增益(N·m / rad)。
- 影响:P 太大会引发振荡 / 不稳定;太小控制响应慢。通过 joint 名称匹配给每个 dof 指定 gain。
- damping(阻尼 / D 增益)
- 含义:每关节的 D 增益(N·m·s / rad)。
- 影响:抵消速度引起的振荡,通常与 stiffness 配合调整。
- action_scale
- 含义:动作缩放系数,目标角度 = action * action_scale + defaultAngle(对于 P 控制)。
- 影响:控制动作的实际幅度;需要与 default_joint_angles 和关节极限配合。
- decimation
- 含义:策略输出周期对应的仿真子步数(policy 每次更新间隔内仿真步的数量)。
- 影响:较大 decimation 表示 agent 的动作更新频率更低(每个动作在仿真中持续更多步),有时有利于稳定训练但降低控制精细度。
dt = sim_params.dt * decimation。
asset(机器人资源 / 资产设置)
- file
- 含义:URDF/MJCF 文件路径(可以使用路径格式化变量)。
- 影响:指定机器人模型。
- name
- 含义:actor 名称(在 gym 中的标识)。
- foot_name
- 含义:用于识别腿/足的 body 名称子串(用于接触检测/奖励索引)。
- 影响:确保字符串能匹配到模型里的脚体名,否则脚相关奖励/检测失效。
- penalize_contacts_on / terminate_after_contacts_on
- 含义:分别是要惩罚接触的 body 名称列表和导致终止的接触 body 名称列表(按子串匹配)。
- 影响:定义哪些碰触算作不良接触或终止条件。
- disable_gravity / collapse_fixed_joints / fix_base_link
- 含义:资产加载时的选项,控制是否禁用重力、是否合并固定关节、是否固定 base(用于测试)。
- 影响:改变动力学行为或简化模型。
- default_dof_drive_mode
- 含义:DOF 驱动模式(例如 0 none, 1 pos tgt, 2 vel tgt, 3 effort)。与 URDF/physx 驱动对应。
- 影响:决定如何把 torques/targets 应用到 DOF。
- self_collisions
- 含义:是否启用自碰撞(以及碰撞位掩码设置)。
- 影响:自碰撞开会增加计算成本,但更真实。
- replace_cylinder_with_capsule / flip_visual_attachments
- 含义:优化碰撞体(用胶囊代替圆柱)和可视化网格方向修正。
- 影响:能提升仿真稳定性和渲染显示正确性。
- density, angular_damping, linear_damping, max_angular_velocity, max_linear_velocity, armature, thickness
- 含义:资产的物理属性(密度、阻尼、速度上限、骨架惯量调整、碰撞厚度)。
- 影响:直接影响惯性、稳定性以及碰撞行为。调整需谨慎。
domain_rand(域随机化)
- randomize_friction
- 含义:是否随机化摩擦系数(true/false)。
- 影响:可以提升策略在不同表面上的鲁棒性。
- friction_range
- 含义:随机摩擦的最小/最大值范围(数组)。
- 单位:无量纲(摩擦系数)。
- 影响:范围太宽可能导致训练困难,太窄效果差。
- randomize_base_mass / added_mass_range
- 含义:是否在 base(身体)上随机增加质量,以及增加质量的范围(kg)。
- 影响:训练得到对负载变化更鲁棒的策略。
- push_robots / push_interval_s / max_push_vel_xy
- 含义:是否周期性对机器人施加“脉冲推力”(通过设置基座速度实现),推的时间间隔(s)和最大线速度(m/s)。
- 影响:通过随机外力提高鲁棒性;过强或太频繁可能阻碍学习。
rewards(奖励设计)
- scales(子类)
- 这里列出了各个 reward 项的基准 scale(会在
_prepare_reward_function中乘以dt)。例如:termination:终止奖励/惩罚(通常用于倒地或触地等)。示例-0.0。tracking_lin_vel:线速度跟踪奖励权重(示例 1.0)。tracking_ang_vel:角速度跟踪权重(示例 0.5)。- 其他项如
lin_vel_z(惩罚竖直速度)、ang_vel_xy、torques、dof_acc、collision、feet_air_time等。
- 提示:scale 的符号与含义重要(正的奖励,负的惩罚)。
_prepare_reward_function会把非零 scale 乘以dt(因此 scale 的物理含义是 每秒 的权重)。
- 这里列出了各个 reward 项的基准 scale(会在
- only_positive_rewards
- 含义:若 True,则训练步骤中总 reward 会被裁剪为 >= 0(负值变为 0)。
- 影响:避免 early termination 导致大量负奖励影响训练稳定性,但也会掩盖惩罚信号。
- tracking_sigma
- 含义:用于 tracking reward 计算的 sigma(高斯/指数项扩展因子),例如
exp(-error/tracking_sigma)。 - 影响:sigma 越大,误差容忍度越高;越小则更苛刻。
- 含义:用于 tracking reward 计算的 sigma(高斯/指数项扩展因子),例如
- soft_dof_pos_limit / soft_dof_vel_limit / soft_torque_limit
- 含义:软限制系数(作为 URDF 上限的比例),超出该比例会被惩罚。
- 影响:限制策略对关节范围、速度、扭矩的鲁棒使用,避免损伤/非物理动作。
- base_height_target
- 含义:基座高度目标(m),用于
_reward_base_height的目标跟踪。 - 影响:与机器人体型/默认姿态匹配。
- 含义:基座高度目标(m),用于
- max_contact_force
- 含义:接触力阈值,超过此值开始惩罚(单位:N)。
- 影响:约束步态冲击力,防止暴力接触。
normalization(归一化与裁剪)
- obs_scales
- 含义:用于对不同观测分量进行缩放归一(例如
lin_vel,ang_vel,dof_pos,dof_vel,height_measurements)。 - 影响:影响观测数值范围,从而影响训练稳定性和网络输入分布。合理归一化很重要。
- 含义:用于对不同观测分量进行缩放归一(例如
- clip_observations
- 含义:对观测值的 element-wise 上下界裁剪(绝对值上限)。
- 单位:与观测值同量纲(示例 100)。
- 影响:防止数值爆炸和异常值。
- clip_actions
- 含义:对 actions 的裁剪上限(绝对值)。
- 影响:防止网络输出产生极端动作。
noise(观测噪声)
- add_noise
- 含义:是否给观测添加噪声(uniform in [-1,1] scaled by
_get_noise_scale_vec)。 - 影响:提高策略在传感器噪声下的鲁棒性。
- 含义:是否给观测添加噪声(uniform in [-1,1] scaled by
- noise_level
- 含义:全局噪声强度缩放(乘子)。
- 影响:放大/缩小噪声幅度。
- noise_scales
- 含义:对各观测分量的噪声基准尺度(dof_pos, dof_vel, lin_vel, ang_vel, gravity, height_measurements)。
- 影响:针对不同传感器信号设置不同噪声,模拟现实传感器特性。
viewer(可视化摄像机)
- ref_env
- 含义:参考环境编号(viewer 用哪个 env 的位置作为参考)。
- pos / lookat
- 含义:摄像机位置与目标点(世界坐标,米)。
- 影响:仅用于可视化调试,无训练语义影响。
sim(物理仿真参数)
- dt
- 含义:仿真主时间步(s)。
- 影响:与
control.decimation一起决定策略步长policy_dt = dt * decimation。dt 太大可能导致数值不稳定。
- substeps
- 含义:物理内部子步数(每个 sim 主步内的细分步)。
- 影响:增加子步数可提高稳定性但开销更大。
- gravity
- 含义:重力向量(m/s²)。
- 影响:直接影响机器人动力学行为。
- up_axis
- 含义:哪一轴作“上”(0: x/y? 注:代码里用 2 表示 z 上),此配置决定坐标系的约定。
- 注意:代码中
up_axis_idx = 2(z-up),cfg 中up_axis = 1(有可能是 y-up)需保持一致,否则会出现坐标/重力方向不匹配。
sim.physx(PhysX 专项参数)
- num_threads
- 含义:PhysX 使用的 CPU 线程数(仅 CPU 计算相关)。
- solver_type
- 含义:解算器类型(0 pgs,1 tgs 等)。
- num_position_iterations / num_velocity_iterations
- 含义:物理迭代次数,影响接触求解精度与稳定性。
- contact_offset / rest_offset
- 含义:碰撞偏移参数(m),用于接触检测阈值。
- bounce_threshold_velocity / max_depenetration_velocity
- 含义:弹跳阈值速度与最大分离速度限制。
- max_gpu_contact_pairs, default_buffer_size_multiplier, contact_collection
- 含义:GPU contact 缓冲区、缓冲区扩展、接触收集策略(0/1/2 表示何时收集接触信息)。
- 影响:大规模并行 env(数千)时需要较大的 contact buffer。
LeggedRobotCfgPPO(训练与 PPO 算法相关)
这是训练框架/超参数(与仿真配置分开),包含策略网络、PPO 算法与 runner(训练循环)设置。
顶层
- seed
- 含义:随机种子(保证可复现)。
- runner_class_name
- 含义:训练 runner 的类型(例如 OnPolicyRunner)。
policy(策略/网络结构)
- init_noise_std
- 含义:策略输出初始噪声标准差(用于探索或初始化)。
- actor_hidden_dims / critic_hidden_dims
- 含义:actor / critic 网络的隐藏层维度列表(例如 [512,256,128])。
- 影响:网络容量越大拟合能力越强但更易过拟合、训练更慢。
- activation
- 含义:激活函数类型(如 elu, relu 等)。
- 影响:训练稳定性与收敛性。
(若使用 RNN,会有 rnn_type / rnn_hidden_size / rnn_num_layers 等)
algorithm(PPO 超参数)
- value_loss_coef
- 含义:价值损失在总损失中的权重。
- use_clipped_value_loss
- 含义:是否对 value loss 使用裁剪(PPO 的常见做法)。
- clip_param
- 含义:PPO 的策略剪切参数 ε(典型 0.1~0.3)。
- entropy_coef
- 含义:熵项权重(鼓励探索)。
- num_learning_epochs
- 含义:每轮更新中使用的 epoch 数(通过数据多次迭代)。
- num_mini_batches
- 含义:将一次 rollout 数据拆分成多少小批量(影响每次更新的小批大小)。
- learning_rate
- 含义:学习率。
- schedule
- 含义:学习率调度策略(adaptive / fixed)。
- gamma
- 含义:折扣因子(通常 0.95~0.999)。
- lam
- 含义:GAE 的 lambda 参数。
- desired_kl
- 含义:如自适应学习率,目标 KL 值。
- max_grad_norm
- 含义:梯度裁剪上限(用于保持训练稳定)。
runner(训练循环 / 运行配置)
- policy_class_name / algorithm_class_name
- 含义:使用的策略和算法类名(如 ActorCritic, PPO)。
- num_steps_per_env
- 含义:每个环境在一次 rollout 中走多少步(采样长度),决定每次更新的数据量(nsteps)。
- max_iterations
- 含义:总的策略更新次数(迭代次数)。
日志与检查点
- save_interval
- 含义:每多少次迭代检查是否需要保存模型。
- experiment_name / run_name
- 含义:记录实验与结果命名(用于日志管理)。
- resume / load_run / checkpoint / resume_path
- 含义:与恢复训练相关的配置(是否从已有 checkpoint 恢复、加载哪个 run 等)。
最后 — 实用建议(汇总)
- 一致性:
num_actions、num_observations、default_joint_angles、dof_names与 robot asset 必须一致,否则会出现索引或匹配错误。 - 单位一致:速度(m/s)与角速度(rad/s)、位置(m)等要保持一致。
horizontal_scale/vertical_scale用于高度map转换,容易搞错。 - 课程学习:开启 terrain / command curriculum 可以加速并稳健提升能力,但需要合理的晋级条件(如 tracking reward 阈值)。
- 域随机:摩擦、质量、推力等的随机化能大幅提升 sim2real 的鲁棒性,但过强会阻碍收敛。
- 观测维度:
measure_heights会大幅增加 obs 维度(height map 点数),对应要扩展网络输入或减少其他观测项。 - 调试:先用较小
num_envs和较短episode_length_s做快速迭代,参数稳定后再放大规模。
如果你希望,我可以:
- 针对某个
class(例如rewards或control)把每个字段列成表格并给出调参建议(例如如何在真实机器人上设置stiffness/damping的起点);或者 - 帮你把
obs_scales和num_observations对齐(检查当前 cfg 是否与代码中拼接的 obs 结构一致,列出每一段观测的维度)。
你想先看哪一个?