1182 lines
42 KiB
Markdown
1182 lines
42 KiB
Markdown
# 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 配置里:
|
||
|
||
```text
|
||
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. 总体推进路线和阶段门
|
||
|
||
```mermaid
|
||
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 从参考机器人缩放参数
|
||
|
||
如果参考机器人有可用参数,只按对应物理量缩放。
|
||
|
||
步态相位距离:
|
||
|
||
```text
|
||
d_phase,new = d_phase,ref * L_leg,new / L_leg,ref
|
||
```
|
||
|
||
若希望两台机器人手端的线位移接近,肩摆角近似按臂长反比缩放:
|
||
|
||
```text
|
||
theta_shoulder,new = theta_shoulder,ref * L_arm,ref / L_arm,new
|
||
```
|
||
|
||
高度目标必须直接测量新机器人 q0,不建议用总身高比例推算:
|
||
|
||
```text
|
||
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 m`,Gen2 有效腿长约 `0.786 m`;PM01 肩臂链约 `0.575 m`,Gen2 约 `0.70 m`。因此 Gen2 的相位距离略小,而肩、肘角幅也应减小。
|
||
|
||
## 5. 第二步:导入和清理模型资产
|
||
|
||
### 5.1 URDF 基础检查
|
||
|
||
导入前逐项确认:
|
||
|
||
| 检查项 | 合格标准 |
|
||
|---|---|
|
||
| link 名唯一 | 无重复、空名字或非法层级 |
|
||
| joint 名唯一 | 与控制器和硬件接口命名一致 |
|
||
| joint 类型 | 固定、旋转和连续关节语义正确 |
|
||
| axis | 与实际 pitch/roll/yaw 方向一致 |
|
||
| limit | `lower < upper`,effort/velocity 为正 |
|
||
| inertia | 对称、正定、单位为 SI |
|
||
| mass | 无 0 或负质量,整机总质量合理 |
|
||
| mesh 单位 | 统一为米,视觉模型没有 1000 倍缩放 |
|
||
| mesh 路径 | 绝对可解析或相对资产目录稳定 |
|
||
| root | `fix_base=False` 时形成合法浮动基座 |
|
||
|
||
可以把 Gen2 的静态检查脚本复制并参数化:
|
||
|
||
```bash
|
||
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 的辅助命令:
|
||
|
||
```bash
|
||
/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_slide`、`feet_contact`、`feet_orientation` 和 `landing_velocity` 都会给出误导信号。
|
||
|
||
### 5.4 自碰撞的启用顺序
|
||
|
||
初期建议:
|
||
|
||
```python
|
||
enabled_self_collisions = False
|
||
```
|
||
|
||
先让模型完成站立和基础行走。之后若真实部署需要处理手臂撞躯干、双腿相撞,再简化碰撞体并逐步启用 self collision。不要用严重重叠的碰撞体直接开启自碰撞训练。
|
||
|
||
## 6. 第三步:编写机器人 ArticulationCfg
|
||
|
||
机器人配置至少包含:
|
||
|
||
```python
|
||
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 或部署顺序。
|
||
|
||
推荐在机器人文件中显式定义:
|
||
|
||
```python
|
||
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 为什么配置了 q0,reset 后仍不完全相同
|
||
|
||
有效初始姿态还会受到以下配置影响:
|
||
|
||
- `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 就是髋。
|
||
|
||
建议至少定义:
|
||
|
||
```python
|
||
ROBOT_TORSO_BODY_NAME = "..."
|
||
ROBOT_PELVIS_BODY_NAME = "..."
|
||
ROBOT_FEET_BODY_NAMES = ["left_foot", "right_foot"]
|
||
```
|
||
|
||
然后使用 body-specific 状态:
|
||
|
||
```python
|
||
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。
|
||
|
||
```text
|
||
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 后直接记录:
|
||
|
||
```text
|
||
pelvis height
|
||
torso height
|
||
left/right foot position in pelvis heading frame
|
||
left/right foot orientation offset
|
||
left/right shoulder/elbow/hand position
|
||
```
|
||
|
||
推荐把结果固化为机器人专属常量:
|
||
|
||
```python
|
||
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 >= 3` 且 `track_air_time=True`。
|
||
- 可选 height scanner。
|
||
- light,仅影响显示。
|
||
|
||
基础站立和平地速度巩固阶段可以直接使用 plane 并移除 height scanner。复杂地形阶段再恢复 terrain generator。
|
||
|
||
### 9.2 Action
|
||
|
||
位置控制的常见形式:
|
||
|
||
```python
|
||
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 等采样比例。
|
||
|
||
低速初始范围建议从保守范围开始,例如:
|
||
|
||
```text
|
||
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
|
||
|
||
每个机器人至少注册:
|
||
|
||
```text
|
||
Flat-<Robot>-v0
|
||
Flat-<Robot>-Play-v0
|
||
```
|
||
|
||
不同阶段最好独立注册:
|
||
|
||
```text
|
||
Flat-<Robot>-Speed-v0
|
||
Flat-<Robot>-Natural-v0
|
||
Flat-<Robot>-Fast-v0
|
||
```
|
||
|
||
在 `config/<robot>/__init__.py` 中使用明确的环境和 PPO 配置入口:
|
||
|
||
```python
|
||
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 静态检查
|
||
|
||
```bash
|
||
/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 每步执行:
|
||
|
||
```text
|
||
step_reward_i = raw_term_i * weight_i * step_dt
|
||
```
|
||
|
||
Gen2 当前:
|
||
|
||
```text
|
||
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]` 的正奖励:
|
||
|
||
```text
|
||
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=0`、`wz=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`:
|
||
|
||
```text
|
||
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 从头训练
|
||
|
||
下列 `<...>` 是需要替换的占位符,不能原样执行。
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
/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:
|
||
|
||
```bash
|
||
/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
|
||
|
||
```bash
|
||
/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 固定速度回放
|
||
|
||
```bash
|
||
/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 | 摔倒/非法接触 |
|
||
|
||
至少测试:
|
||
|
||
```text
|
||
stand, 0.2, 0.4, 0.6 m/s
|
||
```
|
||
|
||
高速策略再测试:
|
||
|
||
```text
|
||
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,可以查看:
|
||
|
||
```text
|
||
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。左右镜像轴可能意味着:
|
||
|
||
```text
|
||
相同 joint delta -> 物理上相反的前后摆动
|
||
```
|
||
|
||
不要只看 joint sign。增加物理空间相位:
|
||
|
||
```text
|
||
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/s`,error 为 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 和实验记录规范
|
||
|
||
每次训练至少保存:
|
||
|
||
```text
|
||
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:
|
||
|
||
```text
|
||
<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.yaml` 和 `agent.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 参考实现
|
||
|
||
当前仓库中可以直接参考:
|
||
|
||
- [`robots/gen2.py`](../source/engineai_lab/robots/gen2.py)
|
||
- [`config/gen2/README.md`](../source/engineai_lab/tasks/velocity/config/gen2/README.md)
|
||
- [`config/gen2/common_env_cfg.py`](../source/engineai_lab/tasks/velocity/config/gen2/common_env_cfg.py)
|
||
- [`config/gen2/stages/`](../source/engineai_lab/tasks/velocity/config/gen2/stages)
|
||
- [`config/gen2/agents/`](../source/engineai_lab/tasks/velocity/config/gen2/agents)
|
||
- [`mdp/commands.py`](../source/engineai_lab/tasks/velocity/mdp/commands.py)
|
||
- [`mdp/rewards.py`](../source/engineai_lab/tasks/velocity/mdp/rewards.py)
|
||
- [`scripts/train.py`](../scripts/train.py)
|
||
- [`scripts/play.py`](../scripts/play.py)
|
||
- [`scripts/gen2_check_rl_readiness.py`](../scripts/gen2_check_rl_readiness.py)
|
||
|
||
这些文件展示了从 pelvis base 对齐、平地巩固、自然摆臂到 `1.6 m/s` 高速课程的完整实现。接入新机器人时,应复制结构和诊断方法,再用新机器人的 URDF 语义与尺寸重新计算参数。
|