更新时间:2026-08-05 GMT+08:00
分享

ROS2转LeRobot数据集

Rosbag转LeRobot算子用于将ROS bag文件(.bag / .db3)转换为LeRobot标准数据集格式,支持输出LeRobot V2.1LeRobot V3两种格式。平台支持节卡、千寻、星海图三个类型的本体数据,可直接使用数据生产中生成的轨迹数据集作为输入。

  • 核心能力:
    • 数据提取:从ROS bag中提取图像、关节状态、控制命令等多路话题数据。
    • 时间同步:对多路相机图像与机械臂状态/动作执行时间对齐与帧同步。
    • 格式重组:按LeRobot标准目录结构(data/、meta/、videos/ 或 images/)重组数据。
    • 任务描述注入:支持通过prompt.json为各episode注入多样化任务指令,或通过统一description 描述任务。
    • 批量处理:支持一次提交多个bag目录并行转换,单个失败不影响其他。
  • 当前支持机型: 星海图R1(Galaxea R1)、千寻墨子(Moz1)、节卡(Jaka)。
  • 输入: 包含ROS bag文件与可选配置文件(config.yaml和prompt.json)。
  • 输出: LeRobot V2.1或V3格式数据集目录。

参数配置

平台内置星海图R1(Galaxea R1)、千寻墨子(Moz1)、节卡(Jaka)三种本体配置文件。系统配置加载遵循“数据集配置优先>环境变量设置的内置配置>默认配置“的优先级:当数据集目录下存在 config.yaml 时,优先使用该文件并忽略环境变量;若数据集中无配置文件,则尝试读取环境变量robot以加载对应的内置配置(此时无需上传 config.yaml);若两者均未设置,系统将默认采用星海图R1配置进行处理。

表1 参数说明

参数名

是否必填

默认值

可选值

说明

robot

auto

galaxea、jaka、moz1、auto

指定机器人型号,使用平台内置支持的三种本体类型之一,在数据集目录中未配置config.yaml文件时使用。填写无效值时自动回退为galaxea。默认选择auto,即回退到config.yaml配置,或进一步回退到galaxea。

flat

true

true/false

结果输出是否平铺。若选择true,则不会创建repo_id文件夹,输出数据集直接展示data、meta、videos目录;若设置为false,则按照repo_id来设置。

repo_id

auto

任意字符串类型

在创建数据处理任务时,用户可添加或修改该环境变量。含义为转换完成的数据集repo_id,未设置时默认按照config.yaml中的repo_id字段获取;默认设置为auto,即读取config.yaml中的值。

输入说明

输入数据支持ros2 db3格式数据,db3文件同级可配置转换映射配置文件config.yaml或任务描述文件task.txt。

输入目录结构

每个待转换的bag目录需包含ROS bag文件与配置文件:

<bag_dir>/                                  # 输入目录
├── traj_1/                              # 轨迹1目录(目录下通常为 *.db3 metadata.yaml) 
├── traj_2/                              # 轨迹2目录(目录下通常为 *.db3 metadata.yaml)
├── task.txt                             # 针对所有bag的统一描述(数据生成数据资产默认自带)
├── config.yaml                          # 放置在数据集一级目录下,数据集与话题映射配置(可选)
└── prompt.json                          # 对每个bag单独,任务描述列表(可选)

平台轨迹生成数据通常采用上述traj_1, traj_2目录平铺模式,推荐用户按照该目录结构组织待转换ros数据。同时,也支持在一级目录下直接存放ros数据文件。

config.yaml配置文件

config.yaml描述bag内话题到LeRobot字段的映射、机械臂初始位姿以及所用处理器。配置顶层必须为dict,且需包含initial、topic_handlers、features、processor四个必需字段。

由于轨迹生成可根据配置生成不同参数的数据集,建议用户使用自定义配置文件完成转换。以下给出平台内置的3个本体的示例配置文件,当用户通过自动生成轨迹使用不同参数生成数据集后(如视频尺寸、FPS参数设置不同时),可修改配置中的参数实现数据转换,用户需将该config.yaml放置在数据集的一级目录下。

节卡(jaka)
processor:
  jaka_o3de_processor.JAKAO3DEProcessor  # 配置类,jaka本体,请勿修改
fps: 5                                   # 根据实际视频帧率修改
repo_id: jaka_minicobo_pickplace         # 根据输出数据集需要修改
initial:
  arm: [1.5, 0.12, 1.06, -2.23, -0.09, -0.9076]
  gripper: [100]
  vacuum: [0.0]
topic_handlers:
  camera:
    /camera_external/camera_image_color: observation.images.external
    /camera_wrist/camera_image_color: observation.images.wrist
  arm_state:
    - /joint_states
  arm_action:
    - /arm_position_controller/commands
  gripper_state:
    - /gripper_width
  gripper_action:
    - /gripper_position_controller/commands
features:
  observation.state:
    dtype: float64
    shape:
      - 7
    names:
      axes:
        - arm_1
        - arm_2
        - arm_3
        - arm_4
        - arm_5
        - arm_6
        - gripper
  action:
    dtype: float64
    shape:
      - 7
    names:
      axes:
        - arm_exp_1
        - arm_exp_2
        - arm_exp_3
        - arm_exp_4
        - arm_exp_5
        - arm_exp_6
        - gripper_exp
  observation.images.external:     # 根据实际视频的尺寸进行修改
    dtype: video
    shape:
      - 3
      - 480
      - 640
    names:
      - channel
      - height
      - width
  observation.images.wrist:
    dtype: video
    shape:
      - 3
      - 480
      - 640
    names:
      - channel
      - height
      - width

千寻(moz1)
processor:
  moz1_o3de_processor.MOZ1O3DEProcessor      # 配置类,moz1本体,请勿修改
fps: 10                                      # 根据实际视频帧率修改
repo_id: moz1_minicobo_pickplace             # 根据输出数据集需要修改
initial:
  left_arm: [-0.1571, -0.8727, -0.3491, -1.5708, -0.6109, 0.1396, -0.1222]
  right_arm: [0.1571, -0.8727, 0.3491, 1.5708, 0.6109, 0.1396, 0.1222]
  torso:  [0.0, 0.0, 0.0, 0.0]
  gripper: [100]
  vacuum: [0.0]
topic_handlers:
  camera:
    /camera_front/camera_image_color: observation.images.front
    /camera_right/camera_image_color: observation.images.wrist_right
    /camera_left/camera_image_color: observation.images.wrist_left
  arm_state:
    - /joint_states
  arm_action:
    - /left_arm_position_controller/commands
    - /right_arm_position_controller/commands
  gripper_state:
    - /left_gripper_width
    - /right_gripper_width
  gripper_action:
    - /left_gripper_position_controller/commands
    - /right_gripper_position_controller/commands
features:
  observation.state:
    dtype: float64
    shape:
      - 16
    names:
      axes:
        - left_arm_1
        - left_arm_2
        - left_arm_3
        - left_arm_4
        - left_arm_5
        - left_arm_6
        - left_arm_7
        - left_gripper
        - right_arm_1
        - right_arm_2
        - right_arm_3
        - right_arm_4
        - right_arm_5
        - right_arm_6
        - right_arm_7
        - right_gripper
  action:
    dtype: float64
    shape:
      - 16
    names:
      axes:
        - left_arm_exp_1
        - left_arm_exp_2
        - left_arm_exp_3
        - left_arm_exp_4
        - left_arm_exp_5
        - left_arm_exp_6
        - left_arm_exp_7
        - left_gripper_exp
        - right_arm_exp_1
        - right_arm_exp_2
        - right_arm_exp_3
        - right_arm_exp_4
        - right_arm_exp_5
        - right_arm_exp_6
        - right_arm_exp_7
        - right_gripper_exp
  observation.images.front:              # 根据实际视频的尺寸进行修改
    dtype: video
    shape:
      - 3
      - 480
      - 640
    names:
      - channel
      - height
      - width
  observation.images.wrist_left:
    dtype: video
    shape:
      - 3
      - 480
      - 640
    names:
      - channel
      - height
      - width
  observation.images.wrist_right:
    dtype: video
    shape:
      - 3
      - 480
      - 640
    names:
      - channel
      - height
      - width

星海图(galaxea)
processor:
  galaxea_o3de_processor.GalaxeaO3DEProcessor    # 配置类,galaxea本体,请勿修改
fps: 10                                          # 根据实际视频帧率修改
repo_id: pick_red_test                           # 根据输出数据集需要修改
initial:
  left_arm: [0.0, 2.0,-0.873, -1.57, -1.117, 1.57]
  right_arm: [0.0, 2.0,-0.873, 1.57, 1.117, -1.57]
  gripper: [80]
topic_handlers:
  camera:
    /camera_right/camera_image_color: observation.images.wrist_right
    /camera_left/camera_image_color: observation.images.wrist_left
    /camera_head_left/camera_image_color: observation.images.front
  arm_state:
    - /joint_states
  arm_action:
    - /left_arm_position_controller/commands
    - /right_arm_position_controller/commands
  gripper_action:
    - /left_gripper_position_controller/commands
    - /right_gripper_position_controller/commands
features:
  observation.state:
    dtype: float64
    shape:
      - 14
    names:
      - left_arm_1
      - left_arm_2
      - left_arm_3
      - left_arm_4
      - left_arm_5
      - left_arm_6
      - left_gripper
      - right_arm_1
      - right_arm_2
      - right_arm_3
      - right_arm_4
      - right_arm_5
      - right_arm_6
      - right_gripper
  action:
    dtype: float64
    shape:
      - 14
    names:
      - left_arm_exp_1
      - left_arm_exp_2
      - left_arm_exp_3
      - left_arm_exp_4
      - left_arm_exp_5
      - left_arm_exp_6
      - left_gripper_exp
      - right_arm_exp_1
      - right_arm_exp_2
      - right_arm_exp_3
      - right_arm_exp_4
      - right_arm_exp_5
      - right_arm_exp_6
      - right_gripper_exp
  observation.images.front:
    dtype: video
    shape:
      - 3
      - 360
      - 640
    names:
      - channel
      - height
      - width
  observation.images.wrist_left:
    dtype: video
    shape:
      - 3
      - 360
      - 640
    names:
      - channel
      - height
      - width
  observation.images.wrist_right:
    dtype: video
    shape:
      - 3
      - 360
      - 640
    names:
      - channel
      - height
      - width
  • 字段说明:
    表2 字段说明

    字段

    类型

    必填

    说明

    initial

    dict

    机械臂初始位姿,用于填充录制开头各传感器通道数据尚未到达时的空隙帧。通常填机器人零位姿态即可;若机器人实际起始位姿非零位,建议填入真实初始角度以保证开头几帧数据准确,见下表。

    topic_handlers

    dict

    ROS 话题到处理器类型的映射,见下表。

    features

    dict

    LeRobot 特征字段定义,键为特征路径(如observation.state),值为特征配置(含dtype、shape、names)。包括相机特征(observation.images.*)、状态特征(observation.state)和动作特征(action),见下表。

    processor

    string

    处理器类路径,当前仅支持galaxea_o3de_processor.GalaxeaO3DEProcessor(星海图R1专用)。

    repo_id

    string

    数据集标识符,作为输出子目录名。

    fps

    int

    采集帧率,默认10。

    description

    string

    统一任务描述文本。

  • initial子字段:

    子字段

    类型

    长度

    说明

    left_arm

    list

    6

    左臂6关节初始角度(弧度),录制开始时左臂各关节的实际角度值。

    right_arm

    list

    6

    右臂6关节初始角度(弧度),录制开始时右臂各关节的实际角度值。

    gripper

    list

    1

    夹爪初始值,录制开始时夹爪的开合程度。

    这些值用于填充时间同步过程中,各传感器通道数据尚未到达时的空隙帧。大多数情况下填零即可;若机器人录制开始时不在零位,建议填入实际起始角度,以保证数据集开头几帧的状态/动作数据准确。

  • topic_handlers子字段与消息类型:

    topic_handlers

    features

    对应关系说明

    camera 话题名含

    /camera_head_left/camera_image_color

    observation.images.front

    头部相机图像。星海图的第三方视角是/camera_head_left/camera_image_color。节卡的第三方视角为/camera_external/camera_image_color

    camera 话题名含

    /camera_left/camera_image_color

    observation.images.wrist_left

    左腕部相机图像

    camera 话题名含

    /camera_right/camera_image_color

    observation.images.wrist_right

    右腕部相机图像

    arm_state

    observation.state

    状态:左臂6关节 + 左夹爪1 + 右臂6关节 + 右夹爪1 = 14维(夹爪状态数据包含在 arm_state 话题中)

    arm_action + gripper_action

    action

    动作:左臂6关节 + 左夹爪1 + 右臂6关节 + 右夹爪1 = 14维

    • features中必须配置与camera话题对应的图像字段:话题缺失,将会删除相关观测feature信息。
    • 其他机器人的camera第三方视角话题可能为/camera_external/camera_image_color;以及节卡为单臂,gripper_action的对应的话题填一个,比如/gripper_position_controller/commands
    • observation.state 和action 的shape 取决于机器人配置。星海图R1为14维(左臂6关节+左夹爪1+右臂6关节+右夹爪1)。

task.txt任务描述文件(数据生产后若添加了描述信息会包含该文件)

task.txt为单一字符串,设置后所有episode统一使用该任务描述

The robot uses its right arm to grasp a black-and-white pen from the table and places it into a small black cylindrical container. 

此外,平台保留历史prompt.json任务描述文件兼容性,当目录下无task.txt时会检查是否有该文件存在,若存在该文件,任务描述文件可参照该文件,支持多个轨迹使用不同的任务描述(可选)

格式为JSON字典,键为对应轨迹数据文件(db3)在数据集目录中的相对路径,值为该条轨迹的任务描述。

{
  "traj_1/traj_1_0.db3":"pick up the red box",
  "traj_2/traj_2_0.db3":"place the plug into the socket",
  "traj_3/traj_3_0.db3":"grab the gray cylinder"
}

task.txt为单一字符串,设置后所有episode统一使用该任务描述。prompt.json为多轨迹独立任务描述,用户可自由配置。

输出说明

flat=true 模式:

```
<output_dir>/
├── data/
│   └── chunk-000/
│       ├── episode_000000.parquet
│       └── ...
├── meta/
│   ├── info.json
│   ├── tasks.jsonl
│   ├── episodes.jsonl
│   └── episodes_stats.jsonl
├── images/
│   ├── observation.images.front/
│   └── ...
└── videos/

如果flat为false且提供repo_id,则转换结果输出到<repo_id>/目录下,格式由目标类型决定(V2.1或 V3),repo_id可通过repo_id环境变量进行设置,若未设置按照config配置文件中获取repo_id。

LeRobot V2.1输出结构

<repo_id>/
├── data/
│   └── chunk-000/
│       ├── episode_000000.parquet       # 轨迹数据
│       ├── episode_000001.parquet
│       └── ...
├── meta/
│   ├── info.json                        # 数据集基本信息(版本、帧率等)
│   ├── tasks.jsonl                      # 任务定义(jsonl 格式)
│   ├── episodes.jsonl                   # Episode 元信息
│   └── episodes_stats.jsonl             # Episode 统计信息
├── images/                              # 图像数据(图片序列,可选)
│   ├── observation.images.front/
│   ├── observation.images.wrist_left/
│   └── observation.images.wrist_right/
└── videos/                              # 视频数据(V2.1 必需字段)

LeRobot V3输出结构

<repo_id>/
├── data/
│   └── chunk-000/
│       ├── file_000000.parquet       
│       ├── file_000001.parquet
│       └── ...
├── meta/
│   ├── info.json                        # 数据集基本信息(版本、帧率、特征等)
│   ├── stats.json                       # 数据统计信息
│   ├── tasks.parquet                    # 任务定义
│   └── episodes/                        # Episode 元信息
└── videos/                              # 视频数据
    ├── observation.images.front/
    ├── observation.images.wrist_left/
    └── observation.images.wrist_right/

相关文档