type
Post
status
Published
date
Jan 21, 2026
slug
summary
tags
isaaclab
robotics
仿真
category
技术
icon
password
文本
基础结构
环境注册
- 文件:config/anymal_c/__init__.py
- 理解:环境如何注册到 Gymnasium
环境配置
- 文件:config/anymal_c/navigation_env_cfg.py
- 理解:各个配置类的作用(Actions, Observations, Rewards, Commands, Terminations)
配置类 (Configuration Class) | 作用 (Function) | 关键点 (Key Points) |
ActionsCfg | 定义 RL Agent 可输出的动作空间及执行方式。 | 1. pre_trained_policy_action: 采用分层控制,动作不是直接驱动电机,而是作为信号输入给预训练的低级行走策略。
2. low_level_decimation=4: 高级策略频率较低,每 4 个物理步决策一次。 |
ObservationsCfg | 定义策略网络(Agent)的输入状态信息(State)。 | 1. pose_command: 核心输入,告知 Agent 当前的目标位置和方向。2. base_lin_vel & projected_gravity: 感知自身速度与姿态(平衡状态)。 |
RewardsCfg | 定义奖励函数,指导 Agent 学习“好”的行为。 | 1. position_tracking: 正向奖励,距离目标越近得分越高(使用 tanh 平滑)。2. orientation_tracking: 负向奖励(惩罚),约束机器人朝向目标。
3. termination_penalty: 重罚 (-400),机器人摔倒或非法接触时给予巨大惩罚。 |
CommandsCfg | 负责生成任务目标(Goal),如位置和航向。 | 1. UniformPose2dCommandCfg: 在 2D 平面上随机生成目标点。范围: 3m x 3m 区域内随机。
2. resampling_time_range=(8.0, 8.0): 每 8 秒重置一次新目标,训练连续适应能力。 |
TerminationsCfg | 定义 Episode(一局游戏)何时结束。 | 1. base_contact: 失败判定,检测基座(躯干)是否触地,触地即视为摔倒/失败。
2. time_out: 超时强制结束。 |
EventCfg | 定义环境重置(Reset)时的状态初始化和随机化。 | 1. reset_base: 虽然名为 reset,实际上包含域随机化。每次重置时,机器人的初始位置和朝向在小范围内随机扰动,防止过拟合。 |
预训练策略动作
- 文件:`mdp/pre_trained_policy_action.py
- 理解:层次化控制的实现原理
1. PreTrainedPolicyActionCfg (配置类)
这个类定义了构建层次化动作所需的参数,是静态配置。
参数 | 解释 |
asset_name | 要控制的机器人实体名称。 |
policy_path | 低级策略模型路径 (.pt 文件)。这是预先训练好、会走路的大脑。 |
low_level_decimation | 频率倍数。例如=4,意味着高级策略每思考1次,低级策略要执行4次动作。 |
low_level_actions | 低级策略原本的动作配置(如关节位置控制)。 |
low_level_observations | 低级策略需要的输入(Obs)配置。 |
2.PreTrainedPolicyAction
1. 初始化 (
__init__)
作用:初始化动作项,加载神经网络模型,并建立观测数据的“重定向”机制。- 加载模型:载入
.pt预训练网络。
- 重映射输入:通过
lambda将低级策略的观测(动作历史、速度指令)强制指向当前类缓存的变量,实现接管控制。
- 初始化管理器:创建专属的动作与观测管理器。
2. 接收指令 (
process_actions)作用:接收高级指令。每当高级策略决策一次(比如每 0.1秒),这个函数被调用一次。
- 缓存:接收高级策略输出的 Tensor(速度指令),存入
_raw_actions备用。
3. 执行控制 (
apply_actions)
作用:执行控制循环。在每一个物理仿真步(Simulation Step,比如每 0.005秒)都会被调用- 降频:通过
counter实现频率分频(Decimation)。
- 推理:达到触发频率时,使用新指令计算观测 -> 喂给 Policy 网络 -> 得到关节目标。
- 驱动:调用底层
_low_level_action_term应用关节控制信号。
4. 属性访问 (Properties)
action_dim(self) -> int作用:定义暴露给高级策略的动作维度。
- 实现方式:返回
3。因为对于高级策略来说,它只需要输出[vx, vy, yaw_rate](X轴速度, Y轴速度, 偏航角速度) 这三个数,而不需要关心机器人的 12 个关节具体怎么动。
raw_actions(self) & processed_actions(self)作用:提供对当前存储的高级指令的访问接口。
- 实现方式:直接返回内部存储的 Tensor
self._raw_actions。
5. 调试与可视化 (Debug Visualization)
这部分用于在仿真画面中画出箭头,帮助开发者判断指令是否被执行。
_set_debug_vis_impl(self, debug_vis: bool)作用:开启或关闭可视化工具。
- 实现方式:
- 实例化
VisualizationMarkers类。 - 创建两个可视化器:
- 绿色箭头 (Goal):代表高级策略想要的速度(
velocity_goal)。 - 蓝色箭头 (Current):代表机器人当前的实际速度(
velocity_current)。
_debug_vis_callback(self, event)作用:每一帧更新箭头的状态。
- 实现方式:
- 获取机器人当前的基座位置
root_pos_w。 - 调用
_resolve_xy_velocity_to_arrow将二维速度变为箭头的旋转和缩放。 - 高级指令 -> 绿色箭头。
- 实际速度 -> 蓝色箭头。
- 调用
visualize在 3D 场景中绘制。 - 目的:如果绿箭头和蓝箭头重合度高,说明低级策略执行能力强;如果绿箭头指东,蓝箭头往西,说明控制失效。
_resolve_xy_velocity_to_arrow(self, xy_velocity: torch.Tensor)作用:辅助函数,将 2D 速度向量
(vx, vy) 转换为 3D 箭头的 缩放比例 (Scale) 和 旋转四元数 (Quaternion)。- 实现方式:
- 长度:速度越大,箭头拉伸得越长 (
norm * 3.0)。 - 方向:使用
atan2(vy, vx)算出角度,转为四元数,并叠加上机器人当前的基座朝向(因为通常指令是在机身坐标系下发出的,需要转
到世界坐标系显示)。
奖励函数
- 文件:`mdp/rewards.py`
- 理解:如何计算位置和朝向跟踪奖励
1. 步态诱导类 (Gait Shaping)
这些奖励函数旨在“教会”机器人怎么走步子。如果没有它们,机器人可能只会像溜冰一样在地板上滑行,因为那样也是一种移动方式。
feet_air_time (重要)- 作用:腾空时间奖励。鼓励机器人在每一步中把脚抬起来并在空中停留足够长的时间。
- 实现逻辑:
- 检测此帧每一个脚是否刚落地 (
first_contact)。 - 如果是刚落地,就回看这只脚在空中呆了多久 (
last_air_time)。 - 如果呆的时间超过了阈值 (
threshold),就给分。呆得越久分越高。 - 关键条件:如果目前的速度指令很小(
command < 0.1,即让它站着不动),这分就不给了。防止机器人原地踏步骗分。
- 目的:这是训练出**Trot(小跑)**步态的关键。
feet_air_time_positive_biped- 作用:双足腾空时间奖励。这是给双足机器人(如 H1, Casssie)专用的。
- 实现逻辑:
- 检查有多少只脚着地 (
single_stance)。 - 对于双足机器人,理想的步态是单脚支撑相(一次只有一只脚着地)。
- 如果是单脚支撑,就根据支撑时间或腾空时间给予奖励,但设置了上限 (
threshold)。
- 目的:强迫双足机器人交替迈步,而不是双脚跳(Hopping)。
feet_slide- 作用:脚底打滑惩罚。
- 实现逻辑:
- 检测脚是否触地 (
contacts)。 - 检测脚底是否有水平速度 (
body_vel)。 - 如果脚触地了,但速度不为0(说明在滑),就根据速度大小进行惩罚。
- 目的:消除“溜冰鞋”效应(Ice-skating),增加仿真的真实感,确保机器人是靠摩擦力在走。
2. 速度追踪变体 (Tracking Variants)
这些是核心库中
tracking 函数的改良版,处理坐标系转换。track_lin_vel_xy_yaw_frame_exp- 作用:航向坐标系下的速度追踪。
- 背景:机器人的根节点坐标系(Base Frame)会随着身体抖动(Roll/Pitch)而倾斜。直接用 Base Frame 测速有时不准。
- 实现逻辑:
- 构造一个虚拟的“航向坐标系”(Yaw-aligned Frame):Z 轴永远垂直向上(重力反方向),只保留机器人的 Yaw 旋转。
- 把世界坐标系下的速度投影到这个虚拟坐标系中。
- 计算与指令的误差并指数奖励。
- 目的:让速度追踪不受身体侧倾或俯仰的影响,更加鲁棒。
track_ang_vel_z_world_exp- 作用:世界坐标系下的角速度追踪。
- 实现逻辑:直接对比世界坐标系下的角速度 Z 分量与指令。
- 通常用途:大多数时候用机身坐标系更好,但在某些特殊构型或某些特定的任务定义下,使用世界坐标系可能更直观。
3. 静止约束 (Stillness Constraint)
stand_still_joint_deviation_l1- 作用:静止时的姿态惩罚。
- 实现逻辑:
- 检查当前的指令是否接近 0(
command < threshold)。 - 如果是(此时应该站着不动),就惩罚关节偏离默认位置的程度 (
joint_deviation_l1)。
- 目的:
- 当没有速度指令时,机器人应该乖乖且优雅地站好。
- 防止机器人在待机时出现奇怪的扭曲姿势或不必要的动作。
- 相当于对
joint_deviation_l1加了一个“仅在低速时生效”的开关。
低层环境配置
- 文件:`locomotion/velocity/config/anymal_c/flat_env_cfg.py`
- 理解:低层策略需要什么观测和动作
观测
关节位置 (Pos)、关节速度 (Vel)、基座姿态 (Projected Gravity)、基座速度 (Lin/Ang Vel)。
动作
• Joint Position Control:输出 12 个关节的目标角度。这是最底层的驱动信号。
深入理解
研究低层策略
查看低层策略的输入输出
1. 动作输出 (Actions)
代码位于 velocity_env_cfg.py 的 ActionsCfg 类中:
- 输出内容: 12 个关节的目标位置(关节角度)。
- 控制方式: PD 控制(位置控制)。
2. 观测输入 (Observations)
代码位于 velocity_env_cfg.py 的 ObservationsCfg.PolicyCfg 类中:
理解为什么需要 low_level_decimation
low_level_decimation 实际上是用更少的大脑(RL)计算换取更稳定的物理表现和更高效的训练。1. 时间尺度的本质差异
- 控制层 (Low Level): 需要极高的频率(例如 200Hz - 1000Hz)来保证物理仿真的稳定性和电机控制的平滑性。如果控制频率太低,机器人会抖动、不稳定甚至飞出物理世界。
- 决策层 (High Level): 往往只需要较低的频率(例如 10Hz - 50Hz)。人类决定“往左转”可能只需要 0.5 秒思考一次,并不需要每毫秒都重新决定一次“往左转”。
2. 为什么不让决策层也跑 200Hz?
如果强行让 RL 策略和物理仿真跑得一样快(Decimation = 1),会有以下坏处:
- 训练极其困难 (Sample Inefficiency):
- 如果策略是 200Hz,那么做 1 秒钟的动作需要 200 步决策。
- 强化学习算法(如 PPO)很难关联第 1 步的动作和第 200 步后的奖励(Credit Assignment Problem)。"远水救不了近火",步数越多,奖励传递越难。
- 计算浪费:
- 大部分时候,相邻两毫秒的决策(Status)几乎是一模一样的。让神经网络重复计算几乎相同的输入输出,是对算力的巨大浪费。
- 动作抖动:
- 高频决策容易导致策略输出高频噪声。通过降频(Hold Action),相当于天然加了一个“零阶保持器”(Zero-Order Hold),让动作更连贯平滑。
修改奖励函数
navigation_env_cfg.py
- 尝试不同的奖励权重
- 理解奖励函数对训练的影响

navigation_env_cfg.py
- 改变目标位置范围
- 修改命令重采样时间

周报内容
为什么需要层次化控制?
层次化控制(Hierarchical Control)就像是一个军队的指挥体系:
- 分而治之,降低复杂度:
- 高层(指挥官/Agent):只关心战术目标(“向北走 5 米”),不用管具体的腿怎么迈。这减少了它的搜索空间,训练起来更快。
- 低层(士兵/Locomotion Controller):只关心怎么稳稳地迈步子(保持平衡、不摔倒)。它不用知道要去哪,只需要把“走”这件事做好。
- 复用性(Reusability):
- 会走的腿(低层策略)一旦练好了,可以被拿去教它“巡逻”、“踢球”、“甚至搬运”。如果用端到端(End-to-End)的方法,每换一个任务可能就要重新学一遍怎么走路。
- Sim-to-Real 的稳定性:
- 低层策略通常经过了大量的物理扰动训练,非常鲁棒(Robust)。有了这层保护,高层策略即使偶尔发出了不完美的指令,低层控制器也会尽力在物理上“圆”回来,不至于让机器人直接翻车。
low_level_decimation 的作用是什么?
low_level_decimation(低层降频/Sub-stepping)是连接高层与低层两个不同时间世界的变速齿轮。
- 时间尺度的匹配:
- 控制层 (低层) 需要极快(如 200Hz,即每 5ms 一次)来响应地面的微小变化,防止摔倒。
- 决策层 (高层) 思考不需要那么快(如 50Hz,即每 20ms 一次)。如果你每 5ms 就改一次主意说“往左”、“往右”,机器人会像得了帕金森一样抖动。
- 更稳定的动作:
- low_level_decimation = 4 意味着:高层说一句话,低层执行 4 遍。这天然地让动作指令保持了一段时间(Zero-Order Hold),使得运动更加连贯平滑。
- 计算效率:
- 高层网络通常比较大(因为它要处理任务逻辑)。让它少跑几次(降频),可以显著节省算力,让训练更快。
低层策略的观测从哪里来?
- 大部分来自真实物理状态:
- 机器人的关节位置 (Joint Pos)、关节速度 (Joint Vel)、基座速度 (Base Vel)、重力向量等。这些都是从环境 (env.scene) 里实时读取的,代表了机器人当下的身体状况。
- 关键部分被“劫持” (Hijacked):
- 低层策略原本在训练时有一个输入叫“速度指令 (Velocity Command)”(即告诉它往哪走)。
- 在层次化架构中,我们通过
lambda函数把这个输入源强行替换成了高层策略刚刚输出的动作。 - 代码证据(pre_trained_policy_action.py):
如何修改目标位置范围?
输出一个episode完整数据流的示意图
