cmvr_ai_lab/docs/humanoid_locomotion_onboarding_guide.md
2026-07-20 08:56:11 +08:00

42 KiB
Raw Blame History

EngineAI Lab 新人形机器人行走训练攻略

本文面向 engineai_lab 原生 Isaac Lab + RSL-RL 训练链路,目标是把一个新的人形机器人从 URDF/MJCF 资产逐步推进到:

  1. 模型能够稳定加载、复位和站立。
  2. 低速行走时左右脚交替,不靠滑动前进。
  3. 速度、稳定性和响应逐步提升。
  4. 手臂与腿形成自然的对侧摆动,手腕保持稳定。
  5. 通过课程学习达到更高速度,同时保留已有能力。

文中的数值以 Gen2 的实践为例。新机器人只能复用方法、结构和量级判断,不能直接照搬 Gen2 或 PM01 的高度、关节符号、摆幅和碰撞参数。

1. 先记住十条原则

  1. 先验证模型,再设计奖励。 错误的碰撞体、初始高度、关节方向和质量参数无法靠 PPO 修复。
  2. URDF root link 不等于运动控制 base。 root 可以是胸部,行走参考可以明确选髋部或 pelvis link。
  3. 所有高度和姿态奖励都必须绑定明确的连杆。 不要默认 root_pos_w 就是髋部状态。
  4. 先固定低速平地,再加入复杂地形、推力和大范围指令。 一次只增加一种难度。
  5. 总 reward 不能跨奖励版本直接比较。 应比较归一化跟踪能力、摔倒率、脚滑和固定指令回放。
  6. 训练日志必须配合 replay。 机器人可能用腰部扭转、脚底滑动或高频抖动获得看似不错的奖励。
  7. 速度上限必须用课程逐步扩展。0.6 m/s 直接跳到 1.6 m/s 通常会破坏已有步态。
  8. 关节坐标符号不能凭名字猜。 左右镜像关节经常需要相同数值符号才能产生物理上的反向运动。
  9. 训练任务和 Play 任务的 action scale 必须一致。 否则回放时手腕、手臂或脚踝动作会被错误放大。
  10. 每一阶段都保留可回退 checkpoint。 新奖励没有提升时,从阶段入口重新训练,不要在已经退化的最终模型上继续堆补丁。

2. EngineAI Lab 中各模块的职责

以当前 Gen2 实现为参考:

模块 典型路径 职责
机器人资产 source/engineai_lab/assets/gen2/ URDF、mesh 和简化碰撞体;审计结果写入 outputs/
机器人配置 source/engineai_lab/robots/gen2.py q0、初始高度、关节顺序、执行器参数和资产加载
环境共享配置 source/engineai_lab/tasks/velocity/config/gen2/common_env_cfg.py scene、action、observation、reset、termination 和 Play 公共设置
分阶段环境 source/engineai_lab/tasks/velocity/config/gen2/stages/ 每阶段独立的 reward、command、curriculum 和覆盖参数
分阶段 PPO source/engineai_lab/tasks/velocity/config/gen2/agents/ 每阶段独立的迭代数、熵系数和学习率
MDP 函数 source/engineai_lab/tasks/velocity/mdp/ 自定义命令、观测、奖励和终止逻辑
任务注册 source/engineai_lab/tasks/velocity/config/gen2/__init__.py Gym task ID 到环境/PPO 配置的映射
训练入口 scripts/train.py 创建环境、加载 checkpoint、运行 RSL-RL
回放入口 scripts/play.py 固定/随机/键盘指令、箭头、checkpoint 回放和 ONNX 导出
日志目录 logs/rsl_rl/<experiment_name>/ checkpoint、TensorBoard events、env.yaml 和 agent.yaml

推荐为新机器人复制结构,不要把所有机器人逻辑继续堆到 PM01 配置里:

source/engineai_lab/robots/<robot>.py
source/engineai_lab/tasks/velocity/config/<robot>/
├── __init__.py
├── registry.py
├── common_env_cfg.py
├── stages/
│   ├── walk.py
│   ├── speed.py
│   └── natural.py
└── agents/
    ├── __init__.py
    ├── walk_ppo_cfg.py
    ├── speed_ppo_cfg.py
    └── natural_ppo_cfg.py

3. 总体推进路线和阶段门

flowchart LR
    A["资产静态检查"] --> B["Isaac 中加载"]
    B --> C["q0 与 zero-action"]
    C --> D["站立"]
    D --> E["低速交替踏步"]
    E --> F["平地速度与稳定性"]
    F --> G["自然全身协调"]
    G --> H["高速课程"]
    H --> I["地形与扰动鲁棒性"]
阶段 必须达到的结果 未达到时禁止做什么
资产检查 质量、惯量、关节限位和碰撞体可信 禁止开始 PPO
加载与 reset 无 NaN、无爆炸、脚底不深陷地面 禁止调行走奖励
zero-action q0 附近短时稳定,力矩和速度有限 禁止扩大 command
站立 timeout 高、非法接触低、姿态正确 禁止加入地形课程
低速行走 左右交替,有真实位移,不靠脚滑 禁止直接追求高速
速度巩固 固定速度误差下降,滑动和晃动可控 禁止同时增加地形和推力
自然协调 对侧摆臂,腕部稳定,步态未退化 禁止直接改全身 action scale
高速课程 各级速度逐步通过,最终才接触目标上限 禁止一次性采样全范围高速

4. 第一步:建立机器人尺寸和语义表

在写配置之前,先从 URDF 和 CAD 资料整理一张表。后续所有奖励参数都从这里推导。

项目 要记录的内容 用途
URDF root root link 名称和物理位置 判断 root_* 状态代表胸还是髋
pelvis 最适合作为运动参考的髋部连杆 速度、朝向、高度和 command marker
torso 胸部/上身连杆 roll/pitch、上身稳定和腰髋一致性
feet 左右脚底对应的 link 接触、滑动、腾空时间和落脚速度
arm phase bodies 左右肘或前臂 link 判断对侧摆臂,避免手腕取巧
腿长 pelvis 到脚底的默认垂直距离 高度、步幅、相位距离和 clearance
臂长 肩到手或肘的近似链长 肩摆角、肘屈曲和空间相位幅度
髋宽 左右腿根或默认脚横向距离 站立脚位和交叉腿约束
默认站立高度 pelvis、torso 和 root 的世界高度 高度奖励与 reset z
关节语义 pitch/roll/yaw、左右符号和 limit action scale、默认位和对称奖励

4.1 不要用“机器人总身高”代替控制尺寸

行走奖励最常用的是:

  • pelvis 到脚底的有效腿长。
  • pelvis 和 torso 在 q0 下的实际世界高度。
  • 肩到肘、肩到腕的链长。
  • 默认两脚相对 pelvis 的三维位置。

头部高度通常不参与基础 locomotion。两台机器人总身高不同不代表 pelvis 高度按同一比例变化。

4.2 从参考机器人缩放参数

如果参考机器人有可用参数,只按对应物理量缩放。

步态相位距离:

d_phase,new = d_phase,ref * L_leg,new / L_leg,ref

若希望两台机器人手端的线位移接近,肩摆角近似按臂长反比缩放:

theta_shoulder,new = theta_shoulder,ref * L_arm,ref / L_arm,new

高度目标必须直接测量新机器人 q0不建议用总身高比例推算

h_pelvis,target = z(pelvis at q0 with soles on ground)
h_torso,target  = z(torso at q0 with soles on ground)

Gen2 实例中PM01 参考腿长约 0.82 mGen2 有效腿长约 0.786 mPM01 肩臂链约 0.575 mGen2 约 0.70 m。因此 Gen2 的相位距离略小,而肩、肘角幅也应减小。

5. 第二步:导入和清理模型资产

5.1 URDF 基础检查

导入前逐项确认:

检查项 合格标准
link 名唯一 无重复、空名字或非法层级
joint 名唯一 与控制器和硬件接口命名一致
joint 类型 固定、旋转和连续关节语义正确
axis 与实际 pitch/roll/yaw 方向一致
limit lower < uppereffort/velocity 为正
inertia 对称、正定、单位为 SI
mass 无 0 或负质量,整机总质量合理
mesh 单位 统一为米,视觉模型没有 1000 倍缩放
mesh 路径 绝对可解析或相对资产目录稳定
root fix_base=False 时形成合法浮动基座

可以把 Gen2 的静态检查脚本复制并参数化:

cd /home/xtkuang/Projects/cmvr/RL/cmvr_ai_lab

/home/xtkuang/App/anaconda3/envs/engineai_lab/bin/python \
  scripts/gen2_check_rl_readiness.py

该脚本检查质量、惯量、关节限位、碰撞重叠、脚底高度、reset z以及 pelvis/torso 高度目标。用于新机器人时,必须修改其中的 URDF、foot link、robot cfg 和高度常量路径;任何 unknown 都会使检查失败,不能当作通过。

5.2 视觉 mesh 不适合直接作为训练碰撞体

高精度 mesh collision 常见问题:

  • 碰撞三角面过多,仿真吞吐下降。
  • 相邻连杆在 q0 下互相穿透。
  • 足底不平,产生虚假侧向力和脚滑。
  • 手臂、手腕碰撞体过大,站立时与躯干接触。
  • 薄片 mesh 或非封闭 mesh 导致接触不稳定。

推荐顺序:

  1. 保留原始 URDF不直接覆盖。
  2. 为训练生成 box、capsule 或简化 convex collision。
  3. 单独输出碰撞审计 CSV。
  4. 渲染正视、侧视、俯视和 3D 图。
  5. 在 Isaac viewer 中打开 collision display 再确认。

Gen2 的辅助命令:

/home/xtkuang/App/anaconda3/envs/engineai_lab/bin/python \
  scripts/gen2_generate_simplified_collisions.py

/home/xtkuang/App/anaconda3/envs/engineai_lab/bin/python \
  scripts/gen2_visualize_collisions.py

5.3 足底碰撞体是第一优先级

足底应满足:

  • 底面平整并接近视觉鞋底。
  • q0 下左右脚底高度一致。
  • collision bottom 与地面留有约 5~10 mm 的初始化余量。
  • 足底前后长度和左右宽度合理,不能缩成点接触。
  • foot frame 不必与世界轴对齐,但必须记录其固定 RPY offset。

如果脚底碰撞体不可信,feet_slidefeet_contactfeet_orientationlanding_velocity 都会给出误导信号。

5.4 自碰撞的启用顺序

初期建议:

enabled_self_collisions = False

先让模型完成站立和基础行走。之后若真实部署需要处理手臂撞躯干、双腿相撞,再简化碰撞体并逐步启用 self collision。不要用严重重叠的碰撞体直接开启自碰撞训练。

6. 第三步:编写机器人 ArticulationCfg

机器人配置至少包含:

ROBOT_CFG = ArticulationCfg(
    spawn=sim_utils.UrdfFileCfg(
        asset_path=str(ROBOT_URDF_PATH),
        activate_contact_sensors=True,
        fix_base=False,
        replace_cylinders_with_capsules=True,
        rigid_props=...,
        articulation_props=...,
        joint_drive=...,
    ),
    init_state=ArticulationCfg.InitialStateCfg(
        pos=(0.0, 0.0, INITIAL_ROOT_Z),
        joint_pos={...},
        joint_vel={".*": 0.0},
    ),
    actuators={...},
)

6.1 建立唯一、固定的关节顺序

必须明确三份顺序:

  • 模型 articulation 内部顺序。
  • 策略 observation/action 顺序。
  • 硬件 DFS 或部署顺序。

推荐在机器人文件中显式定义:

ROBOT_LEG_JOINT_NAMES = [...]
ROBOT_WAIST_JOINT_NAMES = [...]
ROBOT_ARM_JOINT_NAMES = [...]
ROBOT_DFS_JOINT_NAMES = ROBOT_LEG_JOINT_NAMES + ROBOT_WAIST_JOINT_NAMES + ROBOT_ARM_JOINT_NAMES

ROBOT_DFS_JOINT_ORDER_ASSET_CFG = SceneEntityCfg(
    "robot",
    joint_names=ROBOT_DFS_JOINT_NAMES,
    preserve_order=True,
)

任何一次新增、删除或重排 observation/action 都会改变 policy 输入输出契约,旧 checkpoint 通常不能继续加载。

6.2 q0 的要求

q0 应满足:

  • 所有关节在 limit 内,并留出控制余量。
  • 膝盖不是完全奇异的锁直状态。
  • 左右脚底近似平行地面。
  • 手臂与躯干无碰撞。
  • 非零默认关节的位置真实可达。
  • 左右镜像姿态符合 URDF 的符号定义。

当前 action 使用 use_default_offset=True,因此策略输出零通常表示 q0而不是所有关节绝对角度为零。

6.3 为什么配置了 q0reset 后仍不完全相同

有效初始姿态还会受到以下配置影响:

  • randomize_joint_default_pos 修改 default_joint_pos
  • reset_joints_by_scale 对非零 q0 做乘法扰动。
  • reset velocity 给关节初速度。
  • delayed actuator 的历史缓冲在最初几步产生瞬态。
  • 接触和重力在第一帧后改变姿态。

尤其注意q0 为 1.57 rad 的腕关节使用 (0.8, 1.2) scale reset 时,会被随机到约 1.26~1.88 rad,幅度远大于零位关节。自然摆臂微调阶段应收窄 reset 范围或对腕部单独复位。

6.4 执行器参数的初始设置

先按硬件或厂商控制器给定的 stiffness、damping、effort 和 velocity limit 建模。没有可靠数据时:

  • 髋、膝通常比踝和腕更强。
  • 大腿主关节 stiffness/damping 较高。
  • 腰部需要足够阻尼,避免用腰摆满足 yaw 奖励。
  • 腕部执行器较弱action scale 和速度约束应更小。
  • 训练初期不要为了“站住”无限提高 stiffness。

7. 第四步:明确 locomotion reference body

7.1 root 在胸部时,不必强改 URDF 树

Gen2 的 URDF root 是胸部 body_link,但行走参考使用 pelvis waist_link_2。正确做法是让奖励、command metric 和 marker 显式选择 pelvis body而不是假定 root 就是髋。

建议至少定义:

ROBOT_TORSO_BODY_NAME = "..."
ROBOT_PELVIS_BODY_NAME = "..."
ROBOT_FEET_BODY_NAMES = ["left_foot", "right_foot"]

然后使用 body-specific 状态:

asset.data.body_pos_w[:, pelvis_id]
asset.data.body_quat_w[:, pelvis_id]
asset.data.body_lin_vel_w[:, pelvis_id]
asset.data.body_ang_vel_w[:, pelvis_id]

7.2 root/base 语义错误的典型表现

表现 原因
yaw reward 很好但腿没有转向 胸部或腰部旋转满足了 root yaw
orientation 很好但髋部明显歪 奖励只看胸部 roll/pitch
height 一直异常 使用胸部高度套用了 pelvis target
command 箭头位置不对 marker 仍画在 root body
实际速度箭头与运动方向不一致 使用了错误 body frame 或 heading offset

7.3 heading offset 的求法

如果 pelvis 局部前向轴不是 URDF frame 的 +X,需要固定 yaw offset。

heading_yaw = yaw(body_quat_w) - heading_yaw_offset

判断方法:

  1. q0 下令机器人面向世界 +X
  2. 读取 pelvis body 的世界 yaw。
  3. heading_yaw 等于 0。
  4. 得到固定 heading_yaw_offset
  5. 用固定前进指令检查目标箭头和实际箭头是否都指向世界 +X

7.4 同时约束 pelvis 和 torso

只看 pelvis 会允许胸部摆动,只看 torso 会允许腰部取巧。推荐组合:

  • pelvis 负责平面速度、高度和主要 heading。
  • torso 负责 roll/pitch 姿态。
  • pelvis 和 torso 共同跟踪 yaw rate。
  • 增加 torso-pelvis yaw alignment。
  • 增加 torso-pelvis yaw-rate difference penalty。

8. 第五步:测量 q0 几何常量

不要凭 URDF 文本手算所有目标。加载仿真并在 q0/reset 后直接记录:

pelvis height
torso height
left/right foot position in pelvis heading frame
left/right foot orientation offset
left/right shoulder/elbow/hand position

推荐把结果固化为机器人专属常量:

ROBOT_PELVIS_HEIGHT_TARGET = ...
ROBOT_TORSO_HEIGHT_TARGET = ...
ROBOT_PELVIS_HEADING_YAW_OFFSET = ...
ROBOT_DEFAULT_FOOT_POS_PELVIS_FRAME = (..., ...)
ROBOT_FOOT_SOLE_FRAME_OFFSETS_RPY = (..., ...)

高度 target 应以“脚底正确接触地面时的 body 高度”为准,而不是 init_state.pos.z。如果 root 是胸部,这两个数更不可能相同。

9. 第六步:接入 ManagerBasedRLEnv

9.1 Scene

Scene 至少包含:

  • terrain importer。
  • robot articulation。
  • contact sensor建议 history_length >= 3track_air_time=True
  • 可选 height scanner。
  • light仅影响显示。

基础站立和平地速度巩固阶段可以直接使用 plane 并移除 height scanner。复杂地形阶段再恢复 terrain generator。

9.2 Action

位置控制的常见形式:

joint_pos = mdp.JointPositionActionCfg(
    asset_name="robot",
    use_default_offset=True,
    preserve_order=True,
    joint_names=ROBOT_DFS_JOINT_NAMES,
    scale={...},
)

action scale 应按关节功能分组:

关节组 初始策略
髋/膝 sagittal 较大,允许形成步幅
髋 roll/yaw 较小,防止横摆和扭腿
踝 pitch 中等,允许推蹬和落脚
踝 roll 较小,避免脚底翻滚
肩 pitch 中等,用于摆臂
肩 roll/yaw 较小并保持默认位
中小
最小,通常单独限制

9.3 Observation

基础 humanoid velocity policy 推荐包含:

  • 按固定顺序排列的 joint position relative to q0。
  • joint velocity。
  • previous action。
  • pelvis angular velocity in heading frame。
  • torso projected gravity。
  • velocity command。
  • 可选 terrain height scan。

历史长度可以改善相位感知但输入维度会成倍增加。Gen2 使用 15 帧 history 后policy observation 为 1353 维。确定 history 后不要在续训中随意改变。

9.4 Command

如果 root 不是 pelvis使用类似 BodyVelocityCommand 的 body-referenced command term

  • 在指定 body heading frame 下计算实际速度。
  • marker 画在指定 body 上方。
  • yaw metric 使用指定 body 或 pelvis+torso 组合。
  • 支持 standing、straight、heading 等采样比例。

低速初始范围建议从保守范围开始,例如:

vx: 0.0 ~ 0.2/0.4 m/s
vy: 0 或非常小
wz: 0 或非常小

先学会向前,再加入横移和转向。

9.5 Event 和 reset

随机化应分阶段添加:

阶段 建议随机化
模型验证 全部关闭
站立 很小的 joint/reset 变化
基础行走 friction、轻微 q0 和 COM 变化
速度巩固 保留物理随机化,关闭 push
高速建立 plane、无 push、窄转向
鲁棒性 最后恢复 push、terrain、较宽 friction/COM

不要在“速度、地形、推力、横移、转向”五项中同时增加两三项以上。

9.6 Termination

基础终止通常包含:

  • time out。
  • 非法 body contact。
  • 可选姿态、高度或越界终止。

非法接触 body 列表应包含胸、腰、手臂、大腿/小腿等不应触地的部位,但不要误把足部或合法膝部接触加入。

9.7 注册 Train 和 Play task

每个机器人至少注册:

Flat-<Robot>-v0
Flat-<Robot>-Play-v0

不同阶段最好独立注册:

Flat-<Robot>-Speed-v0
Flat-<Robot>-Natural-v0
Flat-<Robot>-Fast-v0

config/<robot>/__init__.py 中使用明确的环境和 PPO 配置入口:

import gymnasium as gym

from . import agents


gym.register(
    id="Flat-<Robot>-v0",
    entry_point="isaaclab.envs:ManagerBasedRLEnv",
    disable_env_checker=True,
    kwargs={
        "env_cfg_entry_point": f"{__name__}.flat_env_cfg:RobotFlatEnvCfg",
        "rsl_rl_cfg_entry_point": f"{agents.__name__}.rsl_rl_ppo_cfg:RobotFlatPPORunnerCfg",
    },
)

gym.register(
    id="Flat-<Robot>-Play-v0",
    entry_point="isaaclab.envs:ManagerBasedRLEnv",
    disable_env_checker=True,
    kwargs={
        "env_cfg_entry_point": f"{__name__}.flat_env_cfg:RobotFlatEnvCfg_PLAY",
        "rsl_rl_cfg_entry_point": f"{agents.__name__}.rsl_rl_ppo_cfg:RobotFlatPPORunnerCfg",
    },
)

同时确认 source/engineai_lab/tasks/velocity/config/__init__.py 或其递归导入链会导入 <robot> 包。仅创建文件而不触发包导入,gym.make() 仍会报告 task ID 不存在。

只要 action mapping 不同,就必须有对应 Play task。例如训练中腕部 scale 为 0.06,普通 Play task 为 0.15,回放会把腕部动作放大 2.5 倍。

10. 第七步:训练前的静态与动态 sanity check

10.1 静态检查

/home/xtkuang/App/anaconda3/envs/engineai_lab/bin/python -m compileall \
  source/engineai_lab/robots/<robot>.py \
  source/engineai_lab/tasks/velocity/config/<robot>/

10.2 环境加载检查

用 1~4 个环境确认:

  • Gym task 能从 registry 加载。
  • scene、command、reward、termination manager 全部创建。
  • joint/body regex 恰好匹配预期实体。
  • observation 和 reward 全为 finite。
  • command body id 是 pelvis。
  • action dimension 与关节数一致。

10.3 reset/zero-action 检查

至少检查 20~100 个 policy steps

  • q0 误差。
  • 最大关节速度。
  • 最大力矩。
  • pelvis/torso 高度。
  • 足底是否穿地。
  • 非足部是否接触地面。
  • 延迟执行器启动时是否出现大动作。

如果 zero-action 会爆炸,不要开始 PPO。优先检查碰撞、初始高度、q0、执行器目标、关节索引和 reset 逻辑。

11. RewardManager 的数值语义

Isaac Lab RewardManager 每步执行:

step_reward_i = raw_term_i * weight_i * step_dt

Gen2 当前:

sim.dt = 0.002 s
decimation = 5
step_dt = 0.01 s
episode_length = 20 s

因此一个取值始终为 1、weight 为 1 的正奖励,完整 20 秒 episode 的累计值约为 20。TensorBoard 中 Episode_Reward/* 还会按 episode 最大时长归一化,所以对于原始范围为 [0,1] 的正奖励:

Episode_Reward / weight

可以近似理解为平均完成度。这个方法不适用于无界 penalty也不适用于改过公式或采样分布后的直接横向比较。

12. 奖励函数的推荐分层

不要从一开始加入几十个强奖励。按以下优先级逐层添加。

12.1 第一层:任务必要条件

奖励 目的
pelvis planar velocity tracking 真正跟随平面速度命令
whole-body yaw-rate tracking pelvis 和 torso 一起转向,腰不能取巧
torso orientation 控制胸部 roll/pitch
pelvis/torso height 防止蹲塌和跳跃
termination penalty 明确惩罚摔倒和非法接触

12.2 第二层:可行步态

奖励 目的
biped contact mode 移动时鼓励单脚支撑,站立时双脚接触
feet air time 形成完整摆动期
dense air time 避免稀疏奖励难以探索
swing clearance 抬脚越过地面而不是拖脚
default foot placement 站立时保持合理脚距
foot orientation 避免脚底翻转

12.3 第三层:质量和效率

惩罚 目的
feet slide 减少接触脚滑动
action rate 限制一阶动作变化
action smoothness 限制二阶动作变化
dof acceleration 降低高频关节振动
torque/energy 降低不必要输出
joint limits 避免撞限位
stumble 避免脚侧面撞击障碍/地面

12.4 第四层:全身自然性

奖励 目的
torso-pelvis alignment 防止腰胸相对扭转
contralateral arm phase 左脚前时右臂前,反之亦然
wrist default deviation 手腕只允许小范围补偿
wrist velocity 防止腕部高频乱动
speed-scaled arm target 速度越快摆臂越明显,但幅度封顶

13. 分阶段训练建议

下面是一套可复用的阶段划分。每一阶段从上一阶段最好的 checkpoint 续训。

13.1 阶段 0站立与模型验证

目标证明模型、q0、碰撞和执行器可用。

配置:

  • command 为零或绝大部分 standing。
  • plane。
  • 关闭 push 和 terrain curriculum。
  • 强化姿态、高度、双脚接触和 termination。
  • 暂不强调 air time 和高速 tracking。

通过标准:

  • timeout 接近 100%。
  • base contact 接近 0%。
  • pelvis/torso 高度稳定。
  • zero-action 和 policy replay 都不爆炸。

13.2 阶段 1低速交替踏步

目标:打破“原地站立最优解”,形成左右交替。

配置:

  • vx 上限约 0.2~0.4 m/s
  • vy=0wz=0 或很小。
  • 增加 contact mode、dense air time 和 clearance。
  • 跟踪奖励必须足够强,不能被站立姿态奖励淹没。

通过标准:

  • replay 中左右脚轮流抬起。
  • pelvis 实际速度方向与 command 一致。
  • 不是双脚小碎步或脚底滑行。
  • 固定低速命令下能完成大部分 episode。

13.3 阶段 2A步态清晰度

目标:解决“会挪动,但抬脚不清晰、步态像拖地”。

调整顺序:

  1. 检查足底 contact 和 clearance 几何是否正确。
  2. 增加 dense air time不先盲目提高稀疏 touchdown 奖励。
  3. 适度提高 clearance target 和 weight。
  4. 保留 feet slide penalty。
  5. 观察是否开始高抬腿;若是,降低 clearance 或增大落脚约束。

13.4 阶段 2B速度与稳定性

目标:从慢速挪动提升到稳定跟踪中速命令。

配置:

  • 扩大 vx,但保持 plane。
  • 大部分环境采样直线。
  • 增加 pelvis vertical velocity、pelvis/torso roll-pitch angular velocity 和 landing velocity。
  • 降低 PPO entropy减少后期探索抖动。
  • 暂停 terrain curriculum 和 push。

这一步最容易犯的错误是同时扩大速度、地形和推力。Gen2 曾出现 terrain level 从约 0.9 快速升到 5.5,速度跟踪只小幅提高,但 base contact、脚滑和加速度明显恶化。

13.5 阶段 2C平地巩固

如果速度增加但 replay 看起来没有变好,做一轮专门的平地巩固:

  • plane。
  • 无 terrain curriculum。
  • 无 push。
  • 约 80% 直线。
  • 加强 feet slide、落脚、pelvis vertical 和 torso angular velocity。
  • entropy 从约 0.008 降到 0.004 量级。

Gen2 在这一步才把 0.4 m/s 固定命令下的实际速度从约 0.23 提升到 0.31 m/s,同时显著降低胸部倾斜;代价是脚滑仍需继续约束。

13.6 阶段 3自然摆臂

目标:保持已有腿部步态,只让上肢学会自然协调。

推荐双重约束:

  1. 用肩 pitch 和肘 flexion joint target 跟踪腿部 phase。
  2. 用左右肘/前臂在 heading frame 下的空间位置验证真实对侧摆动。

不要用手端位置直接作为唯一相位奖励,否则策略可能通过大幅转动手腕来“移动手端”。

腕部处理:

  • J5/J6/J7 action scale 单独减小。
  • 位置偏差使用带小 deadband 的 L1 penalty避免指数奖励在大误差时完全饱和。
  • 增加 wrist velocity penalty。
  • Natural Play task 使用相同 action scale。
  • reset 对非零腕关节 q0 的随机范围要收窄。

13.7 阶段 4高速课程

目标速度跨度较大时使用分段 curriculum。例如从 0.6 提升到 1.6 m/s

0.3~0.8 -> 0.3~1.0 -> 0.3~1.2 -> 0.3~1.4 -> 0.3~1.6 m/s

每个阶段至少保留约 100~200 PPO iterations。最后一个目标速度还要单独训练一段时间不能课程一到 1.6 就结束。

高速阶段建议:

  • 90% 直线。
  • 5% standing。
  • 横向和 yaw 范围缩小。
  • plane、无 push。
  • 增加 dense forward undertracking L1 penalty。
  • 扩大 tracking kernel避免大误差下指数奖励接近零。
  • clearance 略提高,但放宽合理的 pelvis vertical motion 和 landing threshold。

达到目标速度后,再开一个独立鲁棒性阶段恢复 push、friction 和 terrain不要污染高速能力建立阶段。

14. 训练命令模板

14.1 从头训练

下列 <...> 是需要替换的占位符,不能原样执行。

cd /home/xtkuang/Projects/cmvr/RL/cmvr_ai_lab

/home/xtkuang/App/anaconda3/envs/engineai_lab/bin/python scripts/train.py \
  --task Flat-<Robot>-v0 \
  --num_envs 4096 \
  --seed 42 \
  --max_iterations <iterations> \
  --run_name <run_name> \
  --device cuda:0 \
  --rl_device cuda:0 \
  --headless

14.2 同一 Task 从 checkpoint 完整续训

同一任务中断后继续时使用 resume,它会恢复 optimizer、iteration 和 curriculum

/home/xtkuang/App/anaconda3/envs/engineai_lab/bin/python scripts/train.py \
  --task Flat-<Robot>-<Stage>-v0 \
  --num_envs 4096 \
  --seed 42 \
  --max_iterations <additional_iterations> \
  --resume True \
  --load_mode resume \
  --load_run <previous_run_directory> \
  --checkpoint model_<iteration>.pt \
  --run_name <new_run_name> \
  --device cuda:0 \
  --rl_device cuda:0 \
  --headless

当前 CLI 的 --resume 使用布尔值参数,应写成 --resume True,不能只写一个裸 --resume

14.3 跨阶段迁移 checkpoint

从一个 Task 进入下一阶段时必须使用 finetune。它只加载 actor/critic使用新阶段的 optimizer 和 curriculum

/home/xtkuang/App/anaconda3/envs/engineai_lab/bin/python scripts/train.py \
  --task Flat-<Robot>-<NextStage>-v0 \
  --num_envs 4096 \
  --seed 42 \
  --max_iterations <iterations> \
  --resume True \
  --load_mode finetune \
  --load_run <previous_stage_run_directory> \
  --checkpoint model_<iteration>.pt \
  --run_name <next_stage_run_name> \
  --device cuda:0 \
  --rl_device cuda:0 \
  --headless

checkpoint 会记录原 Task ID跨 Task 使用完整 resume 会被训练入口拒绝,这是为了防止错误恢复旧 curriculum。

14.4 TensorBoard

/home/xtkuang/App/anaconda3/envs/engineai_lab/bin/tensorboard \
  --logdir logs/rsl_rl/<experiment_name> \
  --port 6006

15. 回放与固定基准

15.1 不要用随机 replay 比较 checkpoint

随机命令、随机摩擦、随机 q0 和不同地形会掩盖真实差异。比较策略时统一使用:

  • 同一个 deterministic Play task。
  • 同一个 command source。
  • 同一个 vx/vy/wz
  • 同一个 command mode 和 acceleration limit。
  • 同一个仿真时长。

15.2 固定速度回放

/home/xtkuang/App/anaconda3/envs/engineai_lab/bin/python scripts/play.py \
  --task Flat-<Robot>-<Stage>-Play-v0 \
  --load_run '<run_regex>' \
  --checkpoint model_<iteration>.pt \
  --num_envs 1 \
  --command_source fixed \
  --command_mode ramp \
  --linear_accel 0.6 \
  --vx 0.4 \
  --vy 0.0 \
  --wz 0.0 \
  --device cuda:0 \
  --rl_device cuda:0

高速测试优先使用 ramp避免从 0 瞬间跳到目标速度。响应测试再使用 step。

15.3 建议记录的固定基准

指标 含义
commanded vx 目标速度
pelvis actual vx mean 实际平均前进速度
vx MAE 跟踪误差
vx std 前后速度抖动
lateral velocity RMS 左右晃动
torso tilt RMS 上身倾斜
pelvis vertical velocity RMS 上下颠簸
contact-foot slide 接触脚滑动
action delta RMS 控制抖动
base-contact resets 摔倒/非法接触

至少测试:

stand, 0.2, 0.4, 0.6 m/s

高速策略再测试:

0.8, 1.0, 1.2, 1.4, 1.6 m/s

16. 如何读训练日志

16.1 第一优先级:是否活着

指标 健康趋势
Episode_Termination/time_out 越接近 1 越好
Episode_Termination/base_contact 越接近 0 越好
Train/mean_episode_length 接近最大 episode steps

如果 base contact 持续升高,即使 mean reward 上升,也不能认为策略更好。

16.2 第二优先级:是否完成任务

[0,1] positive reward可以查看

normalized_completion ~= Episode_Reward / weight

例如 tracking 日志为 1.93、weight 为 2.5,归一化完成度约 0.77

调整 weight 后,必须用归一化值比较,不能比较原始日志。

16.3 第三优先级:动作质量

重点观察:

  • feet_slide
  • dof_acc
  • action_rate
  • action_smoothness
  • pelvis_vertical_velocity
  • pelvis_roll_pitch_ang_vel
  • feet_landing_velocity
  • Policy/mean_std

高速度奖励上升但 slide、acc、action rate 同时恶化,通常表示策略通过更激烈的动作换速度,视觉效果不一定提升。

16.4 不能直接比较的指标

  • 修改 reward 数量或 weight 后的 mean reward。
  • 修改 command 范围后的 tracking reward。
  • 修改 command resampling time 后的 command metric。
  • 修改 terrain curriculum 后的 episode reward。
  • 修改 action scale 后的 action magnitude。

当前 BodyVelocityCommand._update_metrics 使用最大 command 时间归一化。若 resampling 从 7.5 s 改成 5 s,同样误差的日志尺度也会变化。

17. 症状反查表

症状 首要检查 常见原因 优先修复
reset 后立即爆炸 collision、q0、root z、actuator 碰撞重叠、脚陷地、索引错 修模型,不调 reward
只能站立 command observation、tracking budget 站立奖励压过速度奖励 缩小任务并提高 tracking
原地碎步 actual pelvis vx、脚滑 air-time 有收益但前进无收益 增强 pelvis tracking 和 undertracking
双脚滑着前进 foot contact/velocity slide 太弱、足底碰撞错误 先修足底,再加 slide penalty
只抬一只脚 左右 foot id、phase、reset 顺序错或左右奖励不对称 强制 preserve_order查 id
同手同脚 关节轴、空间 arm phase 只按关节名猜符号 用肘/前臂空间位置验证反相
手腕乱甩 action scale、reward saturation 腕部 scale 太大exp 奖励接近 0 减 scale改 deadband L1 + vel penalty
胸转了但腿没转 yaw reference root 在胸部,腰部取巧 pelvis+torso 共同跟踪 yaw
身体高度不对 target body 和尺寸 复制 PM01 height 测量新机器人 q0 body height
箭头方向错误 heading offset pelvis frame 的前向轴不是 +X 标定固定 yaw offset
走得更快但更晃 std、action penalties、terrain 探索过高或任务同时变难 平地巩固,降低 entropy
reward 上升但 replay 无变化 weight 和 command 分布 总 reward 不可比 固定命令 benchmark
中后期越来越容易摔 curriculum、push terrain level 持续提升 冻结地形,回退较早 checkpoint
clearance 很好但高抬腿 target/weight 太高 clearance 主导步态 降 target/weight增 landing
速度上不去 tracking kernel、command curriculum 大误差下 exp 接近 0 分级扩速 + dense undertracking
低速好,高速一给就倒 速度跨度过大 没有逐级 checkpoint 0.2 m/s 一级课程
Play 比训练腕部动作大 Train/Play action scale 使用了错误 Play task 为该阶段注册专用 Play cfg
训练初期腕 J5 偏差很大 reset scale、delay 非零 q0 被乘法随机化 收窄 reset 或腕部单独 reset

18. 奖励微调的正确顺序

当行为不对时,按以下顺序定位,避免同时改十个 weight。

18.1 第 1 层:确认测量对象正确

检查 body/joint/sensor IDs、frame、heading offset、foot order 和 contact threshold。测量错了权重再大也无效。

18.2 第 2 层:确认奖励有数值

查看该项日志是否:

  • 长期接近上限,说明可能太容易或无区分度。
  • 长期接近 0说明公式饱和或事件太稀疏。
  • 数量级比其他项小 100 倍,说明几乎不起作用。
  • 数量级大到主导总 reward说明策略可能只优化这一项。

Gen2 的早期 speed stability 中vertical 和 landing 项只有约 -0.001,相对 action smoothness 约 -0.78 几乎不起作用。增加 reward 名称并不代表它真的影响策略。

18.3 第 3 层:先改公式,再改 weight

常见公式问题:

  • 大误差下 exp(-error) 接近 0没有学习信号。
  • touchdown-only 奖励太稀疏。
  • L2 对大异常过强,对小误差过弱。
  • 站立和移动使用同一目标。
  • 原始 body frame 与期望 heading frame 不一致。

对应修复:

  • 增加 linear/Huber undertracking term。
  • 增加 dense air-time 辅助项。
  • 使用 deadband L1 管理腕部等小动作。
  • 根据 command 判断 stand/move。
  • 统一转换到 pelvis heading frame。

18.4 第 4 层:小步调整 weight

一次调整约 1.5~3 倍,观察 100~300 iterations。不要从 -0.1 直接跳到 -10,否则已有 gait 很容易消失。

18.5 第 5 层:重新选择 checkpoint

最终 checkpoint 不一定最好。若 tracking 在中期已平台,而 terrain、fall 或 policy std 后期继续恶化,应固定条件比较中期和最终 checkpoint再从更平衡的模型续训。

19. 常见失败案例的完整处理

19.1 base 在胸部导致“假转向”

错误做法:所有 tracking、orientation 和 height 都读取 root。

正确做法:

  • pelvis 跟踪 planar velocity。
  • pelvis 和 torso 共同跟踪 yaw rate。
  • torso 控制 roll/pitch。
  • pelvis 使用自己的高度 target。
  • torso-pelvis alignment 防止腰部取巧。

19.2 复制 PM01 高度导致奖励长期异常

错误做法:直接把 PM01 base_height=0.82 用到新机器人。

正确做法:

  1. 确定 PM01 base 是髋,而新机器人 root 是否也是髋。
  2. 在 q0 下测新 pelvis 和 torso 高度。
  3. 分别写 body height reward。
  4. 检查 foot sole collision bottom而不是只看视觉模型。

19.3 第二阶段“看起来没有提升”

可能同时发生:

  • 实际速度提高。
  • 脚滑增加。
  • 前向速度 std 增加。
  • terrain 难度升高。
  • base contact 增加。

这不是单一结论。应在 deterministic plane 下固定 0.2/0.4/0.6 m/s 比较 actual vx、MAE、torso tilt、slide 和 reset。Gen2 的案例证明策略确实变快,但脚滑抵消了视觉收益,因此后续需要平地巩固而不是继续原配置。

19.4 自然摆臂出现同手同脚

先检查左右肩 pitch 的 URDF axis。左右镜像轴可能意味着

相同 joint delta -> 物理上相反的前后摆动

不要只看 joint sign。增加物理空间相位

leg_phase = x(left_foot) - x(right_foot)
arm_phase = x(right_elbow) - x(left_elbow)

希望两者同号。左脚在前时,右肘/前臂在前;右脚在前时,左肘/前臂在前。

19.5 高速目标奖励没有梯度

假设 command 为 1.6 m/s,实际只有 0.6 m/serror 为 1。若使用 exp(-5 * error^2),奖励约为 0.0067,继续变差或略微变好都很难区分。

修复:

  • 用课程把 command 每次只提高约 0.2 m/s
  • 降低 tracking kernel 的 sigma。
  • 增加 max(command_x - actual_x, 0) 形式的 dense undertracking penalty。
  • 在最终目标速度保留足够训练时间。

20. Checkpoint 和实验记录规范

每次训练至少保存:

run name
parent run
parent checkpoint
task ID
max iterations
command ranges
reward version
action scale version
terrain/push 状态
best visual checkpoint
final checkpoint
fixed-speed benchmark

推荐 run name

<robot>_stand_v1
<robot>_gait_low_speed_v1
<robot>_gait_clearance_v2
<robot>_speed_stability_v1
<robot>_speed_flat_consolidation_v2
<robot>_natural_arm_swing_stage3_v1
<robot>_fast_1p6_curriculum_v1

训练开始后,实际 env.yamlagent.yaml 才是这一轮的事实来源。不要只凭当前代码猜旧 run 使用了什么配置。

21. 新机器人接入模板清单

21.1 模型清单

  • URDF 能被 XML parser 和 Isaac converter 读取。
  • mesh 单位和路径正确。
  • 所有 movable joint 有合法 limit。
  • 所有 link 有合理 mass 和正定 inertia。
  • 足底 collision 平整。
  • q0 下无严重非相邻 collision overlap。
  • root z 使脚底不穿地。
  • 左右关节 axis 和 limit 已人工核对。

21.2 机器人配置清单

  • q0 在 limit 内且物理可站立。
  • joint order 明确并 preserve_order。
  • actuator stiffness/damping/effort/velocity 合理。
  • pelvis、torso、feet、arm phase body 名明确。
  • pelvis heading offset 已标定。
  • pelvis/torso height 已测量。
  • 默认 foot positions 和 sole RPY offsets 已测量。

21.3 环境清单

  • Scene 能创建。
  • observation/action dimension 正确。
  • command 使用 pelvis body。
  • contact sensor 匹配左右脚。
  • base contact 不包含合法 foot body。
  • reset 和 zero-action 全部 finite。
  • Play task 与 Train task action mapping 一致。

21.4 训练阶段清单

  • 站立通过后才训练低速。
  • 低速左右交替后才扩 command。
  • 速度和稳定性先在 plane 巩固。
  • terrain 和 push 后加。
  • 自然摆臂不改变 policy I/O dimension。
  • 高速使用课程,不一次跳到目标上限。
  • 每阶段都做固定指令 replay。

22. 最终推荐的工作习惯

  1. 每次只提出一个可验证假设,例如“慢是因为 tracking 梯度不足”,不要先改十个参数。
  2. 先检查日志数量级,再决定 weight。
  3. 每次奖励改动都记录 parent checkpoint 和固定速度基准。
  4. Train 和 Play 配置一起修改、一起验证。
  5. 任何姿态、高度和速度问题都先问“当前读取的是哪个 body、哪个 frame”。
  6. 任何左右协调问题都先检查 preserve_order 和 URDF axis。
  7. 任何脚滑问题都先检查 collision 和 contact再调 reward。
  8. 任何高速问题都先做课程和 dense tracking再放宽动作约束。
  9. 策略能力和鲁棒性分阶段训练,先会做,再学会在扰动中做。
  10. 最终评价标准永远是统一条件下的真实运动,而不是单个 TensorBoard 数字。

23. 当前 Gen2 参考实现

当前仓库中可以直接参考:

这些文件展示了从 pelvis base 对齐、平地巩固、自然摆臂到 1.6 m/s 高速课程的完整实现。接入新机器人时,应复制结构和诊断方法,再用新机器人的 URDF 语义与尺寸重新计算参数。