LeRobot documentation

Процессоры для роботов и телеоператоров

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.7.0).
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