LeRobot documentation

机器人和远程操作员处理器

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

机器人和远程操作员处理器

本指南展示了如何构建和修改处理流水线,以连接远程操作员(例如电话)与机器人及数据集。流水线标准化了不同动作/观测空间之间的转换,因此您可以在不重写胶水代码的情况下替换远程操作方式和机器人。

我们以 Phone 到 SO‑100 跟随者示例来说明,但相同的模式也适用于其他机器人。

你将学到

  • 绝对 EE 控制与相对 EE 控制:各自的含义、权衡取舍以及如何根据任务进行选择。
  • 三流水线模式:如何将遥操作动作映射为数据集动作,再映射为机器人指令,以及将机器人观测映射为数据集观测。
  • 适配器(to_transition / to_output):这些适配器如何将原始字典转换为 EnvTransition 并转换回来,以减少样板代码。
  • 数据集特征契约:步骤如何通过 transform_features(...) 声明特征,以及如何聚合/合并这些特征以进行记录。
  • 选择表示方式:何时存储关节、绝对末端执行器位姿或相对末端执行器增量——以及这对训练的影响。
  • Pipeline 自定义指南:如何安全地更换机器人/URDF,并调整边界、步长以及 IK 初始化等选项。

绝对 EE 控制与相对 EE 控制

本指南中的示例使用绝对末端执行器(EE)位姿,因为它们更易于理解。在实际应用中,通常更倾向于将相对 EE 增量或关节位置作为学习特征。

使用处理器时,您可以选择策略所需的学习特征。这些特征可以是关节位置/速度、绝对末端执行器位置或相对末端执行器位置。您还可以选择存储其他特征,例如关节力矩、电机电流等。

三条流水线

我们通常会组合三条流水线。根据您的配置,如果动作空间和观测空间已经匹配,其中一些流水线可以为空。 这些流水线中的每一条都负责在不同动作空间和观测空间之间进行不同的转换。下面简要介绍每条流水线。

  1. Pipeline 1: 遥操作动作空间 → 数据集动作空间(手机位姿 → 末端执行器目标)
  2. Pipeline 2:数据集动作空间 → 机器人指令空间(末端执行器目标 → 关节)
  3. Pipeline 3: 机器人观测空间 → 数据集观测空间(关节 → 末端执行器位姿)

以下是我们在手机到 SO-100 跟随器示例中使用的三个流水线的示例:

phone_to_robot_ee_pose_processor = RobotProcessorPipeline[tuple[RobotAction, RobotObservation], RobotAction]( # teleop -> dataset action
    steps=[
        MapPhoneActionToRobotAction(platform=teleop_config.phone_os),
        EEReferenceAndDelta(
            kinematics=kinematics_solver, end_effector_step_sizes={"x": 0.5, "y": 0.5, "z": 0.5}, motor_names=list(robot.bus.motors.keys()),
        ),
        EEBoundsAndSafety(
            end_effector_bounds={"min": [-1.0, -1.0, -1.0], "max": [1.0, 1.0, 1.0]}, max_ee_step_m=0.20,
        ),
        GripperVelocityToJoint(),
    ],
    to_transition=robot_action_observation_to_transition,
    to_output=transition_to_robot_action,
)

robot_ee_to_joints_processor = RobotProcessorPipeline[tuple[RobotAction, RobotObservation], RobotAction]( # dataset action -> robot
    steps=[
        InverseKinematicsEEToJoints(
            kinematics=kinematics_solver, motor_names=list(robot.bus.motors.keys()), initial_guess_current_joints=True,
        ),
    ],
    to_transition=robot_action_observation_to_transition,
    to_output=transition_to_robot_action,
)

robot_joints_to_ee_pose = RobotProcessorPipeline[RobotObservation, RobotObservation]( # robot obs -> dataset obs
    steps=[
        ForwardKinematicsJointsToEE(kinematics=kinematics_solver, motor_names=list(robot.bus.motors.keys()))
    ],
    to_transition=observation_to_transition,
    to_output=transition_to_observation,
)

为什么要使用 to_transition / to_output

要在 robot/teleoperator 与 pipeline 之间进行转换,我们使用 to_transition 和 to_output pipeline 适配器。 它们通过标准化转换来减少样板代码,并在 robot 和 teleoperator 的原始字典与 pipeline 的 EnvTransition 格式之间架起桥梁。 在 phone 到 SO-100 follower 的示例中,我们使用以下适配器:

  • robot_action_observation_to_transition:将(action, robot observation)对转换为流水线转换(EE 和 IK 步骤需要机器人的当前关节位置)。
  • transition_to_robot_action:将流水线转换转换为机器人动作字典。
  • observation_to_transition:将机器人观测字典转换为流水线转换。
  • transition_to_observation:将流水线转换(transition)转换为观测字典(observation dict)。

有关更多详细信息,请查看 src/lerobot/processor/converters.py。

数据集功能合约

数据集的特征由数据集中保存的键决定。每个步骤都可以在名为 transform_features(...) 的契约中声明它所修改的特征。构建处理器后,处理器可以使用 aggregate_pipeline_dataset_features() 来聚合所有这些特征,并使用 combine_feature_dicts(...) 来合并多个特征字典。

以下是我们在电话到 SO-100 跟随者示例中如何使用 transform_features 方法声明特征的示例:

    def transform_features(
        self, features: dict[PipelineFeatureType, dict[str, PolicyFeature]]
    ) -> dict[PipelineFeatureType, dict[str, PolicyFeature]]:
        # We only use the ee pose in the dataset, so we don't need the joint positions
        for n in self.motor_names:
            features[PipelineFeatureType.ACTION].pop(f"{n}.pos", None)
        # We specify the dataset features of this step that we want to be stored in the dataset
        for k in ["x", "y", "z", "wx", "wy", "wz", "gripper_pos"]:
            features[PipelineFeatureType.ACTION][f"ee.{k}"] = PolicyFeature(
                type=FeatureType.STATE, shape=(1,)
            )
        return features

在此,我们声明本步骤中修改的 PolicyFeatures,以便了解运行处理器时可以预期哪些特征。随后,这些特征可以被聚合并用于创建数据集特征。

以下是我们在手机到 SO-100 记录示例中聚合和合并特征的方法:

features=combine_feature_dicts(
        # Run the feature contract of the pipelines
        # This tells you how the features would look like after the pipeline steps
        aggregate_pipeline_dataset_features(
            pipeline=phone_to_robot_ee_pose_processor,
            initial_features=create_initial_features(action=phone.action_features), # <- Action features we can expect, these come from our teleop device (phone) and action processor
            use_videos=True,
        ),
        aggregate_pipeline_dataset_features(
            pipeline=robot_joints_to_ee_pose,
            initial_features=create_initial_features(observation=robot.observation_features), # <- Observation features we can expect, these come from our robot and observation processor
            use_videos=True,
            patterns=["observation.state.ee"], # <- Here you could optionally filter the features we want to store in the dataset, with a specific pattern

        ),
    ),

工作原理:

  • aggregate_pipeline_dataset_features(...):在整个 pipeline 中应用 transform_features,并根据模式进行过滤(当 use_videos=True 时包含图像,当指定了 patterns 时包含状态特征)。
  • combine_feature_dicts(...):合并多个特征字典。
  • 使用 record_loop(...) 进行录制时,会先调用 build_dataset_frame(...) 构建与 dataset.features 一致的帧,然后再调用 add_frame(...) 将该帧添加到数据集中。

自定义机器人流水线时的指导

您可以将以下任意功能存储为动作/观察空间:

  • 关节位置
  • 绝对 EE 位姿
  • 相对 EE 差值
  • 其他功能:联合速度、扭矩等。

选择用于策略动作和观测空间的内容,并相应地配置/修改流水线及步骤。

不同的机器人

  • 您可以轻松复用流水线,例如使用另一台机器人配合手机遥操作。只需修改示例并替换机器人的 RobotKinematics(URDF)和 motor_names,即可使用您自己的机器人进行手机遥操作。此外,请确保 target_frame_name 指向您的夹爪/腕部。

安全第一

  • 在更改流水线时,请从严格的边界条件开始,并在与真实机器人协作时实施安全步骤。
  • 建议先从模拟开始,然后再过渡到真实机器人。

就是这样!我们希望本指南能帮助你开始定制机器人流水线。如果在任何环节遇到问题,请加入我们的 Discord 社区 获取支持。

Update on GitHub