更新时间:2026-09-08 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或Galaxea A1Z)、千寻墨子(Moz1)、节卡(Jaka)、青龙(Azureloong)。
  • 输入: 包含ROS bag文件与可选配置文件(config.yaml和prompt.json)。
  • 输出: LeRobot V2.1或V3格式数据集目录。如果用户输出选的OBS路径,预置算法会判断是否有冲突目录,如果有冲突目录,则创建一个新目录并将结果放在新目录下。

参数配置

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

表1 参数说明

参数名

是否必填

默认值

可选值

说明

robot

auto

galaxea、galaxea_a1z、jaka、moz1、azureloong、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四个必需字段。

由于轨迹生成可根据配置生成不同参数的数据集,建议用户使用自定义配置文件完成转换。以下给出平台内置的6个本体的示例配置文件,当用户通过自动生成轨迹使用不同参数生成数据集后(如视频尺寸、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 r1)
    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

  • 星海图(galaxea a1z)
    processor:
      a1z_o3de_processor.A1ZO3DEProcessor
    fps: 30
    repo_id: a1z_demo
    initial:
      arm: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
      gripper: [100.0]
      vacuum: [0.0]
    topic_handlers:
      camera:
        /wrist_camera/camera_image_color: observation.images.wrist
        /external_camera/camera_image_color: observation.images.external
      arm_state:
        - /joint_states
      arm_action:
        - /arm_position_controller/commands
      gripper_state:
        - /gripper_width
    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.wrist:
        dtype: video
        shape:
          - 3
          - 480
          - 640
        names:
          - channel
          - height
          - width
      observation.images.external:
        dtype: video
        shape:
          - 3
          - 720
          - 1280
        names:
          - channel
          - height
          - width

  • 青龙(azureloong)
    processor:
      azureloong_o3de_processor.AzureLoongO3DEProcessor
    fps: 10
    repo_id: azureloong_demo
    initial:
      left_arm: [0.0174533, -0.977384,1.48353,2.35619, -1.39626, -1.13446,0.959931]
      right_arm: [0.0174533, -0.977384,-1.48353,2.35619, 1.39626, -1.13446,-0.959931]
      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:
        - /qinglong_controller/follow_joint_trajectory/_action/feedback
      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
  • 字段说明:
    表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子字段:
    表3 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

    头部相机图像。星海图r1的第三方视角是/camera_head_left/camera_image_color。星海图的a1z的第三方视角/external_camera/camera_image_color。节卡的第三方视角为/camera_external/camera_image_color。青龙的第三方视角为/camera_front/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或/head_camera/camera_image_color;节卡为单臂,gripper_action的对应的话题填一个,比如/gripper_position_controller/commands;以及有些本体单臂的手腕相机话题/wrist_camera/camera_image_color
    • 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/

相关文档