最完整Droid数据集处理指南:从原始机器人数据到训练格式的无缝转换
【免费下载链接】openpi 项目地址: https://gitcode.com/GitHub_Trending/op/openpi
引言:机器人学习的数据痛点与解决方案
你是否还在为机器人学习项目中的数据格式转换而烦恼?面对DROID平台采集的原始数据,如何将其标准化为可直接用于训练的格式?本文将系统讲解openpi项目中Droid数据集的完整处理流程,从数据解析到格式转换,再到训练准备,帮助你高效完成机器人数据的预处理工作。
读完本文后,你将能够:
- 理解Droid数据集的结构与特点
- 掌握使用openpi工具转换Droid数据的方法
- 了解数据处理中的关键技术点与优化策略
- 成功将原始机器人数据转换为LeRobot格式用于模型训练
Droid数据集概述
Droid数据集是一个用于机器人学习的高质量数据集,包含机器人在执行各种任务时的传感器数据和动作指令。该数据集主要特点包括:
数据采集平台
- 基于Panda机械臂(7自由度)
- 配备多视角摄像头系统(手腕相机和外部相机)
- 采样频率为15fps
数据内容
- 图像数据:多个视角的RGB图像
- 关节数据:关节位置、速度
- gripper( gripper)状态
- 动作指令:关节速度和 gripper位置
- 语言指令:任务描述
数据格式挑战
原始Droid数据以HDF5格式存储,包含复杂的层次结构,直接用于训练前需要进行格式转换和预处理。openpi项目提供了专门的转换工具,可将Droid数据转换为LeRobot格式,便于后续模型训练。
转换工具与环境准备
工具介绍
openpi提供的convert_droid_data_to_lerobot.py脚本是转换Droid数据集的核心工具,位于examples/droid/目录下。该脚本实现了从原始Droid数据到LeRobot格式的完整转换流程。
环境要求
系统要求
- Linux操作系统(推荐Ubuntu 22.04)
- Python 3.8+
- 足够的存储空间(根据数据集大小,至少需要原始数据2倍以上空间)
主要依赖库
- lerobot:机器人学习数据集处理库
- h5py:HDF5文件处理
- OpenCV:图像处理
- NumPy:数值计算
- Pillow:图像操作
- tqdm:进度条显示
安装步骤
- 克隆项目仓库:
git clone https://gitcode.com/GitHub_Trending/op/openpi
cd openpi
- 使用uv安装依赖:
uv sync
数据转换流程详解
转换工具工作原理
转换工具的核心工作流程如下:
主要功能模块
工具主要包含以下功能模块:
- 数据读取模块:读取HDF5格式的轨迹数据和MP4格式的图像数据
- 数据解析模块:解析原始数据结构,提取关键信息
- 图像处理模块:图像大小调整、格式转换
- 数据整合模块:将多源数据整合为统一格式
- 格式转换模块:转换为LeRobot数据集格式
- 输出模块:本地保存或上传到Hugging Face Hub
详细步骤解析
1. 命令行参数解析
工具支持的主要参数:
| 参数名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| data_dir | str | 无 | 原始数据目录路径 |
| push_to_hub | bool | False | 是否推送到Hugging Face Hub |
使用示例:
uv run examples/droid/convert_droid_data_to_lerobot.py --data_dir /path/to/your/data
如需推送到Hugging Face Hub:
uv run examples/droid/convert_droid_data_to_lerobot.py --data_dir /path/to/your/data --push_to_hub
2. LeRobot数据集初始化
创建LeRobot数据集对象,定义要存储的特征:
dataset = LeRobotDataset.create(
repo_id=REPO_NAME,
robot_type="panda",
fps=15, # DROID数据通常以15fps录制
features={
# 外部相机1左视图
"exterior_image_1_left": {
"dtype": "image",
"shape": (180, 320, 3), # DROID RLDS数据集使用的分辨率
"names": ["height", "width", "channel"],
},
# 外部相机2左视图
"exterior_image_2_left": {
"dtype": "image",
"shape": (180, 320, 3),
"names": ["height", "width", "channel"],
},
# 手腕相机左视图
"wrist_image_left": {
"dtype": "image",
"shape": (180, 320, 3),
"names": ["height", "width", "channel"],
},
# 关节位置
"joint_position": {
"dtype": "float32",
"shape": (7,),
"names": ["joint_position"],
},
# gripper位置
"gripper_position": {
"dtype": "float32",
"shape": (1,),
"names": ["gripper_position"],
},
# 动作(7维关节速度 + 1维gripper位置)
"actions": {
"dtype": "float32",
"shape": (8,),
"names": ["actions"],
},
},
image_writer_threads=10,
image_writer_processes=5,
)
3. 语言标注加载
加载Droid数据集的语言标注:
with (data_dir / "aggregated-annotations-030724.json").open() as f:
language_annotations = json.load(f)
4. 数据解析与转换
遍历所有 episodes 并进行转换:
episode_paths = list(data_dir.glob("**/trajectory.h5"))
print(f"找到 {len(episode_paths)} 个 episodes 待转换")
for episode_path in tqdm(episode_paths, desc="转换 episodes"):
# 加载原始数据
recording_folderpath = episode_path.parent / "recordings" / "MP4"
trajectory = load_trajectory(str(episode_path), recording_folderpath=str(recording_folderpath))
# 解析 episode_id 以获取语言指令
metadata_filepath = next(iter(episode_path.parent.glob("metadata_*.json")))
episode_id = metadata_filepath.name.split(".")[0].split("_")[-1]
language_instruction = language_annotations.get(episode_id, {"language_instruction1": "Do something"})[
"language_instruction1"
]
# 写入LeRobot数据集
for step in trajectory:
camera_type_dict = step["observation"]["camera_type"]
wrist_ids = [k for k, v in camera_type_dict.items() if v == 0]
exterior_ids = [k for k, v in camera_type_dict.items() if v != 0]
dataset.add_frame(
{
# 注意:需要将BGR格式转换为RGB格式
"exterior_image_1_left": resize_image(
step["observation"]["image"][exterior_ids[0]][..., ::-1], (320, 180)
),
"exterior_image_2_left": resize_image(
step["observation"]["image"][exterior_ids[1]][..., ::-1], (320, 180)
),
"wrist_image_left": resize_image(step["observation"]["image"][wrist_ids[0]][..., ::-1], (320, 180)),
"joint_position": np.asarray(
step["observation"]["robot_state"]["joint_positions"], dtype=np.float32
),
"gripper_position": np.asarray(
step["observation"]["robot_state"]["gripper_position"][None], dtype=np.float32
),
# 重要:使用关节速度动作,因为pi05-droid预训练使用关节速度动作
"actions": np.concatenate(
[step["action"]["joint_velocity"], step["action"]["gripper_position"][None]], dtype=np.float32
),
"task": language_instruction,
}
)
dataset.save_episode()
5. 数据上传(可选)
如果指定了--push_to_hub参数,转换完成后会将数据集推送到Hugging Face Hub:
if push_to_hub:
dataset.push_to_hub(
tags=["libero", "panda", "rlds"],
private=False,
push_videos=True,
license="apache-2.0",
)
关键技术点解析
1. 图像数据处理
Droid数据集包含多个视角的图像数据,需要进行统一处理:
def resize_image(image, size):
image = Image.fromarray(image)
return np.array(image.resize(size, resample=Image.BICUBIC))
处理流程:
- 读取原始图像(BGR格式)
- 转换为RGB格式(
[..., ::-1]实现通道翻转) - 调整大小为(320, 180)
- 保存为LeRobot格式
2. 动作数据处理
Droid数据集的动作数据包含关节速度和 gripper位置,需要进行适当拼接:
# 关节速度(7维)+ gripper位置(1维)= 8维动作向量
"actions": np.concatenate(
[step["action"]["joint_velocity"], step["action"]["gripper_position"][None]], dtype=np.float32
),
注意:pi05-droid模型预训练使用关节速度动作,因此在转换时应使用关节速度而非位置作为动作信号。
3. 多线程图像写入
为提高处理效率,LeRobot数据集支持多线程图像写入:
image_writer_threads=10, # 线程数
image_writer_processes=5, # 进程数
这在处理大量图像数据时能显著提升转换速度。
常见问题与解决方案
1. 数据路径问题
问题:找不到轨迹文件或图像文件。
解决方案:确保data_dir参数正确指向包含Droid数据的根目录,且目录结构符合预期:
RAW_DROID_PATH/
- <...>/
- recordings/
- MP4/
- <camera_id>.mp4 # 单视角视频
- trajectory.hdf5
- <...>/
2. 内存占用过高
问题:处理大型数据集时内存不足。
解决方案:
- 增加
--max_files参数限制同时处理的文件数 - 分批次处理数据集
- 确保系统有足够的交换空间
3. 图像格式不兼容
问题:图像读取或转换错误。
解决方案:
- 检查OpenCV和Pillow库版本是否兼容
- 验证输入图像文件是否损坏
- 尝试使用不同的重采样方法(如Image.LANCZOS)
优化建议
1. 数据过滤
对于特别长的轨迹,可以考虑均匀采样以减少数据量:
# 示例:从长轨迹中均匀采样1000个样本
indices_to_save = np.linspace(0, horizon-1, 1000, dtype=int)
2. 并行处理
对于包含大量episodes的数据集,可以考虑并行处理多个episodes:
from concurrent.futures import ProcessPoolExecutor
with ProcessPoolExecutor() as executor:
executor.map(process_episode, episode_paths)
3. 数据验证
转换完成后,建议对生成的数据集进行基本验证:
# 检查数据集大小是否符合预期
assert len(dataset) > 0, "转换后的数据集为空"
# 检查特征形状是否正确
assert dataset[0]["joint_position"].shape == (7,), "关节位置特征形状不正确"
总结与展望
本文详细介绍了使用openpi工具将Droid机器人数据集转换为LeRobot格式的完整流程,包括环境准备、数据解析、格式转换和优化建议。通过这套流程,你可以高效地将原始机器人数据转换为适合模型训练的格式。
未来,openpi项目计划进一步优化数据转换工具,增加更多自动化预处理功能,如异常检测、数据增强等,以提高机器人学习数据的质量和可用性。
希望本文能帮助你顺利完成Droid数据集的处理工作,为后续的机器人学习研究打下坚实基础。如有任何问题或建议,欢迎参与openpi项目的开发与讨论。
附录:数据集结构对比
| 数据类型 | 原始Droid格式 | LeRobot格式 |
|---|---|---|
| 图像数据 | HDF5中的二进制数据 | 单独的图像文件 + JSON元数据 |
| 关节数据 | 嵌套HDF5结构 | 扁平化数组 |
| 动作数据 | 分离的关节和 gripper数据 | 合并的8维向量 |
| 语言指令 | 单独JSON文件 | 与对应轨迹关联 |
| 存储方式 | 单个HDF5文件 | 目录化结构,支持流式访问 |
【免费下载链接】openpi 项目地址: https://gitcode.com/GitHub_Trending/op/openpi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



