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 follower, однако те же паттерны применимы и к другим роботам.

Чему вы научитесь

  • Абсолютный и относительный контроль EE: что означает каждый из них, плюсы и минусы, и как выбрать подходящий для вашей задачи.
  • Схема из трёх конвейеров: как сопоставить действия телеуправления → действия в наборе данных → команды роботу, а также наблюдения от робота → наблюдения в наборе данных.
  • Адаптеры (to_transition / to_output): как они преобразуют исходные словари в EnvTransition и обратно, чтобы сократить шаблонный код.
  • Контракты признаков датасета: как шаги объявляют признаки через transform_features(...) и как их агрегировать/объединять для записи.
  • Выбор представления: когда сохранять суставы, абсолютные позы конечного эффектора или относительные дельты конечного эффектора — и как это влияет на обучение.
  • Рекомендации по настройке конвейера: как безопасно заменять роботов/URDF и настраивать границы, размеры шагов и параметры, такие как инициализация IK.

Абсолютный и относительный контроль EE

Примеры в этом руководстве используют абсолютные позы конечного эффектора (EE), поскольку за ними проще проследить. На практике в качестве обучающих признаков чаще предпочитают использовать относительные смещения конечного эффектора или позиции суставов.

С помощью процессоров вы выбираете обучающие признаки, которые хотите использовать для своей политики. Это могут быть позиции/скорости суставов, абсолютное положение концевой эффекторной системы или относительные позиции концевой эффекторной системы. Вы также можете выбрать, какие дополнительные признаки сохранять, например, моменты на суставах, токи двигателей и т. д.

Три конвейера

Часто мы комбинируем три конвейера. В зависимости от вашей конфигурации некоторые из них могут быть пустыми, если пространства действий и наблюдений уже совпадают. Каждый из этих конвейеров выполняет различные преобразования между пространствами действий и наблюдений. Ниже приведено краткое описание каждого конвейера.

  1. Pipeline 1: Пространство действий телеуправления → пространство действий датасета (поза телефона → целевые позиции EE)
  2. Pipeline 2: Пространство действий датасета → пространство команд робота (цели для EE → суставы)
  3. Pipeline 3: Пространство наблюдений робота → пространство наблюдений набора данных (суставы → поза EE)

Ниже приведен пример трех конвейеров, которые мы используем в примерах последователя phone to 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

Для перехода от робота/телоуправителя к конвейеру и обратно мы используем адаптеры конвейера to_transition и to_output. Они стандартизируют преобразования, чтобы сократить шаблонный код, и служат связующим звеном между «сырыми» словарями робота и телоуправителя и форматом EnvTransition конвейера. В примерах с телефоном и следящим роботом SO-100 мы используем следующие адаптеры:

  • robot_action_observation_to_transition: преобразует пару (action, robot observation) в переход пайплайна (для шагов EE и IK необходимы текущие позиции суставов робота).
  • transition_to_robot_action: преобразует переход пайплайна в словарь действий робота.
  • observation_to_transition: преобразует словарь наблюдений робота в переход пайплайна.
  • transition_to_observation: преобразует переход пайплайна в словарь наблюдений.

Подробнее см. в src/lerobot/processor/converters.py.

Контракты признаков датасета

Особенности набора данных определяются ключами, сохранёнными в нём. Каждый шаг может объявить, какие именно особенности он изменяет, в контракте transform_features(...). После создания процессора он может агрегировать все эти особенности с помощью aggregate_pipeline_dataset_features() и объединять несколько словарей особенностей с помощью combine_feature_dicts(...).

Ниже приведен пример того, как мы объявляем признаки с помощью метода transform_features в примерах последователя для телефона и SO-100:

    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(...): применяет transform_features по всему конвейеру и фильтрует по шаблонам (изображения включаются, если use_videos=True, а признаки состояния включаются, если задан patterns).
  • combine_feature_dicts(...): объединяет несколько словарей признаков.
  • Запись с помощью record_loop(...) использует build_dataset_frame(...) для построения кадров, соответствующих dataset.features, перед вызовом add_frame(...) для добавления кадра в набор данных.

Рекомендации по настройке конвейеров роботов

Вы можете использовать в качестве пространства действий/наблюдений любую из следующих характеристик:

  • Положения суставов
  • Абсолютные позы EE
  • Относительные дельты EE
  • Другие характеристики: совместная скорость, моменты и т. д.

Выберите, что вы хотите использовать для пространства действий и наблюдений вашей политики, и соответствующим образом настройте/измените конвейеры и шаги.

Разные роботы

  • Вы можете легко переиспользовать конвейеры, например, чтобы использовать другого робота с телеуправлением через телефон: измените примеры и замените RobotKinematics (URDF) и motor_names, чтобы подключить собственный робот к Phone teleop. Кроме того, убедитесь, что target_frame_name указывает на ваш захват/запястье.

Безопасность прежде всего

  • При смене конвейеров начинайте с узких границ и внедряйте меры безопасности при работе с реальными роботами.
  • Рекомендуется сначала начать с симуляции, а затем переходить к реальным роботам.

Всё готово! Мы надеемся, что это руководство поможет вам начать настраивать конвейеры роботов. Если у вас возникнут какие-либо проблемы, присоединяйтесь к нашему сообществу Discord за поддержкой.

Update on GitHub