主题
域随机化(Domain Randomization)
域随机化是提升机器人策略泛化能力的关键技术,通过在训练数据中引入多样化的环境参数,使模型能够适应真实世界的不确定性。
快速开始
bash
# 基础使用(默认启用视频,每 5 个 episode 录一个)
uv run sim2lerobot scripted collect \
--enable_dr --num_demos 50 --num_envs 8
# 批量生成 500 条轨迹(渐进式强度)
uv run python scripts/batch_generate_with_dr.py \
--num_batches 5 --demos_per_batch 100 --num_envs 16 \
--curriculum --dr_start 0.5 --dr_end 1.2
# 禁用视频以加快速度
uv run sim2lerobot scripted collect \
--enable_dr --num_demos 100 --no_video实现的随机化项
本项目在 scripted 数据采集中实现了以下域随机化:
1. 物体初始位置随机化
- 范围:x ∈ [-0.2, 0.2] m,y ∈ [-0.3, 0.3] m(相对桌面中心)
- 作用:增加物体摆放位置的多样性,避免模型过拟合特定位置
- 实现:
mdp.reset_root_state_uniform
2. 物体质量随机化
- 范围:原质量的 50% ~ 150%
- 作用:模拟不同重量的物体,提升抓取和提升动作的鲁棒性
- 实现:
mdp.randomize_rigid_body_mass
3. 物体摩擦系数随机化
- 范围:静态/动态摩擦系数 ∈ [0.4, 1.2]
- 作用:模拟不同材质表面(光滑/粗糙),提升抓取稳定性
- 实现:
mdp.randomize_rigid_body_material
4. 机器人初始关节位置随机化
- 范围:每个关节 ±5° (±0.087 rad) 小扰动
- 作用:避免模型依赖精确的初始姿态,提升启动鲁棒性
- 实现:
mdp.reset_joints_by_offset
5. 目标位置随机化(扩大范围)
- 范围:
- x ∈ [0.35, 0.65] m(原本 [0.4, 0.6])
- y ∈ [-0.3, 0.3] m(原本 [-0.25, 0.25])
- z ∈ [0.2, 0.6] m(原本 [0.25, 0.5])
- 作用:增加目标位置的多样性
- 实现:修改
commands.object_pose.ranges
⚠️ 摩擦系数随机化(暂时禁用)
- 原计划:静态/动态摩擦系数 ∈ [0.4, 1.2]
- 状态:因 IsaacLab PhysX backend 的类型转换问题暂时禁用
- 位置:已在代码中注释并留下扩展点(
env_cfg_with_dr.py:128-142)
视频录制(默认启用)
视频录制现在默认启用,方便直观检查轨迹质量和域随机化效果:
- 默认间隔:每 5 个 episode 录一个视频
- 输出位置:
data/{task}/scripted/{run_id}/videos/*.mp4 - 性能开销:~10-20% 时间,每个视频约 600 KB
bash
# 录制所有 episode(详细检查)
uv run sim2lerobot scripted collect \
--enable_dr --num_demos 20 --video_interval 1
# 禁用视频(快速生成)
uv run sim2lerobot scripted collect \
--enable_dr --num_demos 100 --no_video详见:视频录制与域随机化
使用方法
基础用法
启用域随机化,使用标准强度(dr_scale=1.0):
bash
uv run sim2lerobot scripted collect \
--task lift_cube \
--num_demos 100 \
--num_envs 16 \
--enable_dr调整随机化强度
--dr_scale 参数控制随机化强度(0.0 ~ 2.0+):
bash
# 弱随机化(50% 强度)
uv run sim2lerobot scripted collect \
--enable_dr --dr_scale 0.5 \
--num_demos 100
# 标准随机化(100% 强度)
uv run sim2lerobot scripted collect \
--enable_dr --dr_scale 1.0 \
--num_demos 100
# 强随机化(150% 强度)
uv run sim2lerobot scripted collect \
--enable_dr --dr_scale 1.5 \
--num_demos 100批量生成(固定强度)
使用 Bash 脚本批量生成:
bash
# 生成 10 个批次,每批 100 条轨迹,使用 16 个并行环境
bash scripts/batch_generate_with_dr.sh 10 100 16
# 自定义 DR 强度
bash scripts/batch_generate_with_dr.sh 10 100 16 1.5批量生成(渐进式 Curriculum)
使用 Python 脚本支持渐进式强度增长:
bash
# DR 强度从 0.5 线性增长到 2.0
uv run python scripts/batch_generate_with_dr.py \
--num_batches 10 \
--demos_per_batch 100 \
--num_envs 16 \
--curriculum \
--dr_start 0.5 \
--dr_end 2.0
# 固定强度批量生成
uv run python scripts/batch_generate_with_dr.py \
--num_batches 5 \
--demos_per_batch 50 \
--dr_scale 1.2批量生成脚本对比
| 特性 | Bash 脚本 | Python 脚本 |
|---|---|---|
| 固定 DR 强度 | ✅ | ✅ |
| 渐进式 curriculum | ❌ | ✅ |
| 元数据记录 | 简单 | 详细 JSON |
| 依赖 | bash, grep, awk | Python 3 |
| 推荐场景 | 快速测试 | 生产批量 |
输出结构
批量生成的输出结构(每批是一个 run 子目录,默认输出根目录是 data/{task}/scripted):
data/lift_cube/scripted/
├── batch_001_20260604_143022/
│ ├── episodes.hdf5
│ ├── run.log # collect 自身 stdout(log() tee)
│ ├── batch.log # 批量脚本捕获的完整 subprocess 输出(含 stderr)
│ └── meta.json
├── batch_002_20260604_143145/
│ ├── episodes.hdf5
│ ├── run.log
│ ├── batch.log
│ └── meta.json
├── ...
├── batch_010_20260604_145512/
│ └── ...
└── metadata_20260604_143022.json # 批量元数据(仅 Python 脚本)元数据文件示例
json
{
"task": "lift_cube",
"num_batches": 10,
"demos_per_batch": 100,
"num_envs": 16,
"curriculum": true,
"dr_start": 0.5,
"dr_end": 2.0,
"timestamp": "20260604_143022",
"total_success": 982,
"total_failed": 18,
"batches": [
{
"batch_id": 1,
"batch_name": "batch_001_20260604_143022",
"dr_scale": 0.5,
"num_demos": 100,
"success": 100,
"failed": 3,
"output_file": "data/lift_cube/scripted/batch_001_20260604_143022/episodes.hdf5",
"log_file": "data/lift_cube/scripted/batch_001_20260604_143022/batch.log"
},
...
]
}合并与转换
批量生成后,将所有 HDF5 文件合并并转换为 LeRobot 格式:
bash
# 合并所有批次(convert 对目录输入做递归 glob,自动收集所有 run 子目录下的 hdf5)
uv run python src/sim2lerobot/l3/convert.py \
--input data/lift_cube/scripted \
--output data/lerobot/lift_cube_scripted_dr \
--fps 50
# 检查合并后的数据
uv run python tools/h5_inspect.py data/lerobot/lift_cube_scripted_dr --stats性能考虑
采集速度
- 无 DR:~5-10 demos/min(4 envs)
- 有 DR:~5-10 demos/min(开销可忽略,DR 在 reset 时执行)
- 加视频:~3-7 demos/min(-30% ~ -40%)
并行环境数
| num_envs | GPU 内存 | 速度 | 推荐场景 |
|---|---|---|---|
| 4 | ~2 GB | 基准 | 开发测试 |
| 8 | ~3 GB | 1.8x | 日常采集 |
| 16 | ~5 GB | 3.2x | 批量生产 |
| 32 | ~9 GB | 5.5x | 大规模(需要 RTX 3090+ 24GB) |
批量生成建议
小规模测试(验证 DR 效果):
bash
uv run python scripts/batch_generate_with_dr.py \
--num_batches 3 \
--demos_per_batch 20 \
--num_envs 8 \
--dr_scale 1.0中等规模(日常训练数据):
bash
uv run python scripts/batch_generate_with_dr.py \
--num_batches 10 \
--demos_per_batch 100 \
--num_envs 16 \
--curriculum \
--dr_start 0.5 \
--dr_end 1.5大规模(生产级数据集):
bash
uv run python scripts/batch_generate_with_dr.py \
--num_batches 50 \
--demos_per_batch 200 \
--num_envs 32 \
--curriculum \
--dr_start 0.3 \
--dr_end 2.0扩展点
当前未实现但可扩展的随机化项:
1. 光照随机化
需要自定义 event term 修改 scene.light 的 intensity:
python
cfg.events.randomize_light_intensity = EventTerm(
func=custom_randomize_light,
mode="reset",
params={"intensity_range": (2000.0, 5000.0)},
)2. 物体尺寸随机化
需要在 mode="startup" 时调用 mdp.randomize_rigid_body_scale(不能在 reset 时调用)。
3. 相机参数随机化
- 相机位置/朝向
- 焦距、视野角
- 需要先实现相机观测(当前 scripted 只用 proprio)
4. 视觉随机化
- 纹理、颜色
- 背景
- 通常在 L3 数据增强阶段做(如 Cosmos),不在仿真层
验证 DR 效果
1. 可视化轨迹多样性
bash
# 生成带视频的数据
uv run sim2lerobot scripted collect \
--enable_dr --num_demos 10 --video --video_interval 1
# 查看视频,应该看到:
# - 物体位置各不相同
# - 抓取策略略有差异(适应不同摩擦/质量)2. 统计分析
python
import h5py
import numpy as np
with h5py.File("data/lift_cube/scripted/batch_001_20260604_143022/episodes.hdf5", "r") as f:
# 收集所有 episode 的初始物体位置
positions = []
for ep_key in f["data"].keys():
obj_pos = f[f"data/{ep_key}/obs/object_position"][0] # 初始位置
positions.append(obj_pos)
positions = np.array(positions)
print("物体初始位置分布:")
print(f" x: mean={positions[:, 0].mean():.3f}, std={positions[:, 0].std():.3f}")
print(f" y: mean={positions[:, 1].mean():.3f}, std={positions[:, 1].std():.3f}")
print(f" z: mean={positions[:, 2].mean():.3f}, std={positions[:, 2].std():.3f}")应该看到 std > 0.05(有显著随机化),而无 DR 时 std < 0.02。