Soma Zero Tutorials
🔍 搜索功能尚未开启,敬请期待。

1.4 官方示例

本节目标:把 Isaac Lab 2.3.2 自带的 G1 行走任务逐层吃透——它做什么、用什么策略、观测/动作/奖励/域随机化/终止各是怎么定义的。吃透它有两个意义:(1) 这就是我们后续"策略"章节的 baseline;(2) 只有看懂官方每个旋钮,第 2 章起我们才能精准地在它之上做差异化。

本节所有数字均来自本机源码:$ISAACLAB_DIR/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/ 下的 velocity_env_cfg.py(基类)与 config/g1/(G1 专属覆盖)。

1. 任务总览:它到底在做什么

官方 G1 任务解决的是一个经典问题——速度跟踪行走(velocity tracking):每隔一段时间随机给机器人一个"目标速度指令"(往前多快、横向多快、转多快),策略要驱动 G1 全身关节,让躯干实际速度跟上这个指令,同时别摔、别抖、别浪费力气。

  • 策略(算法):RSL-RL 的 PPO(on-policy actor-critic)。
  • 地形:分两种——Flat 平地(入门、收敛快)和 Rough 崎岖地形(带地形难度课程)。
  • 规模:默认 4096 个 G1 在 GPU 上并行训练。

⚠️ 关键认知:速度跟踪是个已被解决的问题,把它跑通≈完成 5%、且和官方 demo 没区别。本节是为了"看懂",不是终点。我们的价值在第 12 节说的那些 baseline 解决的事上。

2. 四个注册的任务 ID

config/g1/__init__.pygym.register 注册了 4 个 Gym 环境:

任务 ID用途迭代数
Isaac-Velocity-Flat-G1-v0平地训练(M1)1500
Isaac-Velocity-Flat-G1-Play-v0平地回放/导出(少量 env、关随机化)
Isaac-Velocity-Rough-G1-v0崎岖地形训练(M2)3000
Isaac-Velocity-Rough-G1-Play-v0崎岖地形回放/导出

每个 ID 绑定两样东西:环境配置*_env_cfg.py)和 PPO 配置agents/rsl_rl_ppo_cfg.py)。

3. 配置的继承关系

LocomotionVelocityRoughEnvCfg     ← 通用基类(velocity_env_cfg.py):定义全部 MDP 骨架
        ▲
        │ G1 专属覆盖(rough_env_cfg.py):换上 G1 本体、关掉部分随机化、调奖励权重
        │
   G1RoughEnvCfg ───────────► G1RoughEnvCfg_PLAY   (回放:50 个 env、关噪声/外力)
        ▲
        │ 再覆盖(flat_env_cfg.py):地形换平地、去掉地形扫描、再调奖励/指令
        │
   G1FlatEnvCfg  ───────────► G1FlatEnvCfg_PLAY    (回放)

重点:G1FlatEnvCfg 继承自 G1RoughEnvCfg。所以 Rough 里做的所有改动(尤其是"关掉域随机化",见第 8 节)Flat 也都继承了,除非 Flat 又显式改回来。

4. 时序:物理频率 vs 控制频率

参数含义
sim.dt0.005 s物理仿真步长 → 200 Hz 物理
decimation4每 4 个物理步,策略才输出一次动作 → 50 Hz 控制
episode_length_s20 s一个回合最长 20 秒(不摔的话到点重置)

即:策略每 20ms 决策一次目标关节角,中间由底层 PD 以 200Hz 跟踪。这个 50Hz 也是导出策略后在 MuJoCo 部署时要对齐的控制频率。

5. 场景 Scene(机器人住在哪)

  • num_envs = 4096,env_spacing 2.5m —— 4096 个 G1 网格排开同时仿真。
  • 地形 terrain:Flat = 纯平面 plane;Rough = ROUGH_TERRAINS_CFG 地形生成器(坡、台阶、碎石等,带难度分级)。
  • height_scanner(地形高度扫描,1.6×1.0m 网格):只有 Rough 有,挂在 torso_link 上,让策略"看到"脚下地形;Flat 直接去掉。
  • contact_forces:全身接触力传感器,用于算落脚时间、检测非法接触(摔倒)。
  • 本体 = G1_MINIMAL_CFG(G1 精简关节模型)。

6. MDP(一):观测与动作

6.1 观测 Observation(策略每步看到什么)

策略组观测按固定顺序拼成一个向量,每项都加了均匀噪声(enable_corruption=True,模拟真实传感器误差):

观测项含义噪声范围
base_lin_vel躯干线速度 (x,y,z)±0.1
base_ang_vel躯干角速度±0.2
projected_gravity重力在躯干坐标系的投影(≈姿态/倾倒方向)±0.05
velocity_commands目标速度指令(x、y、yaw 角速度)
joint_pos各关节角度(相对默认站姿)±0.01
joint_vel各关节角速度±1.5
actions上一步的动作(帮助平滑)
height_scan脚下地形高度网格(仅 Rough±0.1(clip −1~1)

注意:观测里没有全局位置、没有 root 高度——这是有意的,让策略只依赖本体感知(proprioception),这样才有希望迁移到真机/别的仿真。这点对我们的 sim2sim 和蒸馏至关重要。

6.2 动作 Action(策略每步输出什么)

动作类型是 JointPositionAction:对所有关节输出增量,scale=0.5use_default_offset=True——即最终目标角 = 默认站姿角 + 0.5 × 网络输出,再交给底层 PD 变成力矩。围绕默认站姿做增量,比从零学绝对角度稳定得多。

7. MDP(二):指令与奖励

7.1 指令 Command(行走目标怎么来)

UniformVelocityCommand:每 10 秒 重采一次目标速度,并开启 heading_command(用朝向误差自动算转向指令)。Flat 与 Rough 的采样范围不同:

指令分量Flat 范围Rough 范围
前进 lin_vel_x (m/s)0 ~ 1.00 ~ 1.0
横移 lin_vel_y (m/s)−0.5 ~ 0.50(不练横移)
转向 ang_vel_z (rad/s)−1.0 ~ 1.0−1.0 ~ 1.0

7.2 奖励 Reward(最该读懂的部分)

奖励=一个主任务奖励 + 一堆塑形/惩罚项。下表是 G1 的有效奖励(权重以 Flat 为准,Rough 不同处单列):

奖励项权重(Flat)作用
track_lin_vel_xy_exp+1.0主任务:实际线速度跟上指令(指数型,越准分越高)
track_ang_vel_z_exp+1.0(Rough +2.0)主任务:转向角速度跟上指令
feet_air_time+0.75(Rough +0.25)鼓励抬脚(摆动时间),逼出"迈步"而非拖行;阈值 0.4s
feet_slide−0.1惩罚脚着地时打滑
flat_orientation_l2−1.0惩罚躯干倾斜(保持上身直立)
termination_penalty−200摔倒/非法接触触发终止时的大额惩罚
joint_deviation_hip/arms/fingers/torso−0.1/−0.1/−0.05/−0.1惩罚这些"非行走必需"关节偏离默认姿态(别瞎甩手、别扭腰)
dof_pos_limits(踝)−1.0惩罚踝关节顶到限位
action_rate_l2−0.005惩罚动作突变(平滑、防抖)
dof_torques_l2 / dof_acc_l2−2e−6 / −1e−7能耗与关节加速度惩罚(省力、护电机)
lin_vel_z_l2 / ang_vel_xy_l2−0.2 / −0.05惩罚竖直方向乱动/侧翻角速度

设计哲学:正分只给"跟上速度 + 好好迈步",其余全是负分约束(别摔、别抖、别歪、别费电)。我们后续做鲁棒、做爬起时,本质就是在这张表上加新项 / 调权重。Rough 还把 lin_vel_z_l2 关掉(=0)、undesired_contacts 去掉,因为崎岖地形上下起伏是正常的。

8. MDP(三):事件 / 域随机化 ★重点★

Events 决定训练时"世界有多随机",直接决定策略能不能迁移、抗不抗扰。基类 EventCfg 本备了一整套,但 G1RoughEnvCfg(Flat 也继承)关掉了其中一大半。这是本节最该记住的一张表:

随机化项基类默认G1 实际(Flat/Rough)
地面摩擦 physics_material静 0.8 / 动 0.6(范围退化)固定不随机(范围就是 0.8~0.8)
质量 add_base_mass±5 kg关闭(=None)
质心 base_com±0.05 m关闭(=None)
外力/力矩 base_external_force_torque0(范围退化)挂到 torso,但力仍为 0
随机推 push_robot每 10~15s 推一次关闭(=None)
初始位姿 reset_basex/y ±0.5m,yaw ±π位姿随机✓,初速度归 0
初始关节 reset_robot_joints0.5~1.5 倍缩放固定 1.0(不随机)
观测噪声 enable_corruption✓(见第 6 节)

这就是金矿。 官方 G1 baseline 的域随机化其实非常单薄——除了观测噪声和随机初始位姿,不推、不随机摩擦、不随机质量、不加外力。难怪它"看起来能走",但抗扰和迁移完全没保证。
👉 我们后续的主攻方向 A(鲁棒性)和 C(sim2sim 迁移),本质就是把这张表"填满并量化":开启并加大 push / 外力 / 摩擦 / 质量随机化,再画出"随机化强度 ↔ 抗推/迁移成功率"曲线。详见 附录待办 的阶 2 与阶 4。

9. MDP(四):终止与课程

  • 终止 Terminations:(1) time_out——到 20s 自然结束;(2) base_contact——当 torso_link 发生非法接触(躯干触地=摔倒)立即终止,吃 −200 惩罚。
  • 课程 Curriculumterrain_levels仅 Rough)——走得好的机器人被自动"升级"到更难地形,由易到难逐步加压;Flat 没有课程。

10. PPO 超参与网络(agents/rsl_rl_ppo_cfg.py)

FlatRough
最大迭代 max_iterations15003000
每环境采样步 num_steps_per_env2424
actor/critic 网络[256,128,128][512,256,128]
激活函数ELU
PPO clip / 熵系数0.2 / 0.008
学习率 / 调度1e−3 / adaptive(按 KL 自适应)
γ / λ(GAE)0.99 / 0.95
desired_kl / 训练轮数 / minibatch0.01 / 5 / 4
experiment_nameg1_flatg1_rough

都是腿足 locomotion 的标准 PPO 配方:on-policy、采样 24 步×4096 env、自适应学习率按 KL 散度调。Rough 网络更大、迭代更多,因为要额外处理地形扫描和更难的地形。

11. 怎么跑、怎么读结果

# 1) 冒烟(确认链路) —— 详见 1.2
scripts/train_flat.sh --max_iterations 10 --headless

# 2) 正式训练平地(约 1500 迭代,headless)
scripts/train_flat.sh

# 3) 看训练曲线
tensorboard --logdir $ISAACLAB_DIR/logs/rsl_rl/g1_flat

# 4) 回放最新策略 + 导出可部署模型(policy.pt / policy.onnx)
scripts/play.sh flat
#    导出位置:<run>/exported/policy.onnx —— 这是 sim2sim 的输入

# 5) 崎岖地形
scripts/train_rough.sh && scripts/play.sh rough

该盯哪些指标(TensorBoard):

  • Train/mean_reward 总奖励是否稳步上升;
  • Episode/rew_track_lin_vel_xy_exp 速度跟踪奖励——主任务学没学会;
  • Train/mean_episode_length 回合时长——越接近 20s 说明越不摔;
  • rew_* 惩罚项有没有异常(比如能耗惩罚过大压得不敢动)。

12. 吃透之后:通往我们的"策略"章节

读完本节,你应该能指着官方任意一个旋钮说出"它在控什么"。第 2 章起进入"策略",不改 Isaac Lab 源码,而是在项目的 configs/ 里继承这些 env、只覆盖要动的旋钮,由简到难循序渐进:

后续策略章节(循序渐进)要动官方的哪个旋钮
策略1 · 平地行走(baseline 跑通)直接用官方 Flat 任务,训收敛、导出、回放
策略2 · 鲁棒行走第 8 节 Events:开启并加大 push_robot/外力/摩擦/质量随机化 + 抗推成功率评估
策略3 · 摔倒爬起新建 recovery 任务:改 reset_base 从随机摔倒姿态初始化 + 重设计 reward + 跌倒检测状态机
策略4 · sim2sim 迁移导出 onnx → 对齐第 4/6 节控制频率与观测契约 → MuJoCo 部署 → DR 强度消融

👉 完整路线与每一步的"通过标准",见 附录 待办事项