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

Телефон

Управляйте своим роботом с помощью телефона (iOS или Android).

В этом руководстве вы узнаете:

  • Как подключить телефон на iOS/Android
  • Как поза телефона отображается на целевые позиции исполнительного органа (EE) робота
  • Как настроить ограничения безопасности, управление захватом и параметры IK

Чтобы управлять роботом со смартфона, установите необходимые зависимости с помощью:

pip install 'lerobot[phone,kinematics,feetech,core_scripts]'

kinematics содержит обратную кинематику, используемую в примерах, feetech — драйверы моторов SO-100/SO-101, а core_scripts — инструменты для записи и визуализации.

Начало работы

Поддерживаемые платформы

  • iOS: Использует приложение HEBI Mobile I/O (поза ARKit + кнопки). Сначала скачайте приложение, откройте его, и примеры обнаружат его в вашей сети и начнут передавать позу телефона и вводимые данные.
  • Android: использует пакет teleop (WebXR). При запуске Python-процесса выводится локальный URL. Откройте ссылку на телефоне, нажмите Start, затем используйте Move для потоковой передачи позы.

Ссылки:

Ориентация телефона и управление

  • Ориентация: держите телефон экраном вверх, а верхней кромкой в том же направлении, что и захват робота. Это обеспечивает выравнивание системы координат телефона с системой координат робота при калибровке, благодаря чему движение ощущается естественным. См. изображение ниже для справки.
  • Вкл/выкл — это кнопка аварийного останова: её нужно удерживать нажатой на протяжении всего движения:
    • iOS: удерживайте B1, чтобы перемещать робота, отпустите, чтобы зафиксировать руку в текущем положении. Каждое нажатие заново привязывает телефон к текущей позе руки, поэтому можно отпустить, вернуть руку в удобное положение, нажать снова и продолжить — робот не будет дёргаться.
    • Android: то же самое с кнопкой Move на странице WebXR.
  • Управление захватом (работает независимо от того, удерживается ли кнопка включения):
    • iOS: аналоговый слайдер A3 управляет захватом как вход скорости — нажимайте вверх, чтобы открыть, тяните вниз, чтобы закрыть, отпустите в центре, чтобы удержать.
    • Android: кнопки A и B работают как увеличение/уменьшение (A открывает, B закрывает). Скорость можно настроить на шаге GripperVelocityToJoint.
  • Ухват: держите телефон обеими руками, один большой палец на кнопке включения (B1), другой на ползунке захвата (A3), чтобы одновременно управлять рукой и захватом, не меняя хват. Держите телефон горизонтально во время движения — его положение является командой, поэтому смена хвата в процессе движения приводит к перемещению робота.
  • Позиция робота при запуске: teleoperate.py перемещает манипулятор в домашнюю позицию при старте (до калибровки телефона), а при нажатии Ctrl+C возвращает его в то положение, в котором он находился в момент запуска скрипта. Команды возврата в домашнюю позицию задают каждому суставу манипулятора значение полуоборота, которое set_half_turn_homings() центрировало во время калибровки — это та поза, что показана на схеме калибровки, — при этом захват остаётся в своём текущем положении, чтобы при возврате он не сомкнулся на каком-либо предмете. Это важно, потому что целевые позиции вычисляются методом IK от текущего положения манипулятора в момент нажатия кнопки включения — если манипулятор сложён или полностью вытянут, у него остаётся мало места для манёвра, и он упирается в пределы суставов. Другие примеры скриптов (record.py, evaluate.py, replay.py) не возвращают манипулятор в домашнюю позицию, поэтому разместите его там самостоятельно перед их запуском.
Phone teleop orientation

Шаг 1: Выберите платформу

Измените примеры так, чтобы использовать PhoneOS.IOS или PhoneOS.ANDROID в PhoneConfig. API идентично на всех платформах, различается только источник ввода. Все примеры находятся в examples/phone_to_so100/: teleoperate.py, record.py, replay.py, evaluate.py и rollout.py.

Пример телеуправления:

from lerobot.teleoperators.phone import Phone, PhoneConfig
from lerobot.teleoperators.phone.config_phone import PhoneOS

teleop_config = PhoneConfig(phone_os=PhoneOS.IOS)  # or PhoneOS.ANDROID
teleop_device = Phone(teleop_config)

Шаг 2: Подключение и калибровка

При создании Phone(teleop_config) и вызове connect() калибровка запускается автоматически. Удерживайте телефон в описанном выше положении, затем:

  • iOS: нажмите и удерживайте B1, чтобы зафиксировать опорную позу.
  • Android: нажмите кнопку Move на странице WebXR, чтобы зафиксировать опорную позу.

Зачем калибровать? Мы фиксируем текущую позу, чтобы последующие позы выражались в системе координат, выровненной по роботу. Когда вы снова нажимаете кнопку для включения управления, позиция фиксируется заново, чтобы избежать дрейфа, если телефон был перемещён во время отключённого состояния.

Шаг 3: Запустите пример

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

Все скрипты предполагают, что вы настроили и откалибровали вашего робота (например, SO-100 follower).

Необходимо предоставить URDF робота. Каждый пример решает задачу обратной кинематики, для которой требуется кинематическая модель манипулятора, а URDF не поставляется вместе с LeRobot.

Для SO-100/SO-101, используемых в этом учебнике, скопируйте папку SO101 из репозитория SO-ARM100 в examples/phone_to_so100/, чтобы файл оказался по пути examples/phone_to_so100/SO101/so101_new_calib.urdf, находясь в репозитории LeRobot:

git clone --depth 1 https://github.com/TheRobotStudio/SO-ARM100.git /tmp/SO-ARM100
cp -r /tmp/SO-ARM100/Simulation/SO101 examples/phone_to_so100/SO101

Если файл хранится в другом месте или вы управляете другой рукой, укажите путь к нему в скриптах с помощью --urdf.

  • Запустите этот пример для телеуправления, передав серийный порт вашей ведомой руки (найдите его с помощью lerobot-find-port):

    cd examples/phone_to_so100
    python teleoperate.py --port /dev/tty.usbmodem5A460814411

    --id выбирает, какую из сохранённых калибровок использовать, а --urdf указывает на описанный выше URDF.

После запуска примера:

  • Android: после запуска скрипта откройте напечатанный локальный URL на вашем телефоне, нажмите «Start», затем нажмите и удерживайте «Move».
  • iOS: сначала откройте HEBI Mobile I/O; удерживайте кнопку B1, чтобы перемещать робота. Кнопка A3 управляет захватом.

Additionally you can customize mapping or safety limits by editing the processor steps shown in the examples. You can also remap inputs (e.g., use a different analog input) or adapt the pipeline to other robots (e.g., LeKiwi) by modifying the input and kinematics steps. More about this in the Processors for Robots and Teleoperators guide.

  • Запустите этот пример, чтобы записать набор данных, который сохраняет абсолютные наблюдения и действия конечного эффектора:

    cd examples/phone_to_so100
    python record.py
  • Запустите этот пример, чтобы воспроизвести записанные эпизоды:

    cd examples/phone_to_so100
    python replay.py
  • Запустите этот пример, чтобы оценить предобученную политику:

    cd examples/phone_to_so100
    python evaluate.py

Важные этапы и параметры конвейера

  • Кинематика используется на нескольких этапах. Мы применяем Placo, который является обёрткой над Pinocchio для работы с нашей кинематикой. Объект кинематики создаётся путём передачи URDF робота и целевой системы координат. Мы устанавливаем target_frame_name в значение системы координат захвата.

    kinematics_solver = RobotKinematics(
      urdf_path="./SO101/so101_new_calib.urdf",
      target_frame_name="gripper_frame_link",
      joint_names=list(robot.bus.motors.keys()),
    )
    
  • Шаг MapPhoneActionToRobotAction преобразует откалиброванную позу телефона и входные данные в целевые дельты и команды захвата; ниже показано, что выводит этот шаг.

    action["enabled"] = enabled
    action["target_x"] = pos[1] if enabled else 0.0
    action["target_y"] = -pos[0] if enabled else 0.0
    action["target_z"] = pos[2] if enabled else 0.0
    action["target_wx"] = rotvec[1] if enabled else 0.0
    action["target_wy"] = -rotvec[0] if enabled else 0.0
    action["target_wz"] = rotvec[2] if enabled else 0.0
    action["gripper_vel"] = gripper_vel  # Still send gripper action when disabled
  • Шаг EEReferenceAndDelta преобразует целевые дельты в абсолютную желаемую позу ИК, сохраняя опорное значение при включении; end_effector_step_sizes — это размеры шагов для позы ИК, которые можно изменить, чтобы скорректировать скорость движения.

    EEReferenceAndDelta(
        kinematics=kinematics_solver,
        end_effector_step_sizes={"x": 0.5, "y": 0.5, "z": 0.5},
        motor_names=list(robot.bus.motors.keys()),
        use_latched_reference=True,
    ),
  • Шаг EEBoundsAndSafety ограничивает движение EE рамками рабочего пространства и проверяет наличие резких скачков в шагах EE для обеспечения безопасности. Параметр end_effector_bounds задаёт границы позы EE и может быть изменён для корректировки рабочего пространства. Параметр max_ee_step_m задаёт ограничения на шаг позы EE и может быть изменён для корректировки пределов безопасности.

    EEBoundsAndSafety(
        end_effector_bounds={"min": [-1.0, -1.0, -1.0], "max": [1.0, 1.0, 1.0]},
        max_ee_step_m=0.10,
    )
  • Шаг GripperVelocityToJoint преобразует входные данные захвата, похожие на скорость, в абсолютное положение захвата с использованием текущего измеренного состояния. Параметр speed_factor — это коэффициент, на который умножается скорость.

    GripperVelocityToJoint(speed_factor=20.0)

Различные начальные приближения для IK

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

  • Замкнутый контур (используется в режиме записи/оценки): устанавливает initial_guess_current_joints=True, чтобы IK начинался с измеренных суставов в каждом кадре.

    InverseKinematicsEEToJoints(
        kinematics=kinematics_solver,
        motor_names=list(robot.bus.motors.keys()),
        initial_guess_current_joints=True,  # closed loop
    )
  • Открытый контур (используется при воспроизведении): устанавливает initial_guess_current_joints=False, чтобы IK продолжался с предыдущего решения IK, а не с измеренного состояния. Это сохраняет стабильность действий при воспроизведении без обратной связи.

    InverseKinematicsEEToJoints(
        kinematics=kinematics_solver,
        motor_names=list(robot.bus.motors.keys()),
        initial_guess_current_joints=False,  # open loop
    )

Описание шагов конвейера

  • MapPhoneActionToRobotAction: преобразует откалиброванную позу телефона и входные данные в целевые дельты и команду захвата. Движение активируется сигналом включения (B1 на iOS, Move на Android).
  • EEReferenceAndDelta: фиксирует опорную позу EE при включении и комбинирует её с целевыми дельтами, чтобы формировать абсолютную желаемую позу EE в каждом кадре. При отключении продолжает отправлять последнюю заданную позу.
  • EEBoundsAndSafety: ограничивает позу EE рамками рабочего пространства и ограничивает скорость скачков для обеспечения безопасности. Также объявляет функции action.ee.*.
  • InverseKinematicsEEToJoints: преобразует позу исполнительного органа в положения суставов с помощью IK. Рекомендуется initial_guess_current_joints=True для управления по замкнутому контуру; установите False для воспроизведения по разомкнутому контуру ради стабильности.
  • GripperVelocityToJoint: интегрирует входные данные захвата, похожие на скорость, в абсолютное положение захвата с использованием текущего измеренного состояния.
  • ForwardKinematicsJointsToEE: вычисляет observation.state.ee.* на основе наблюдаемых суставов для логирования и обучения по состоянию EE.

Устранение неполадок

  • iOS не обнаружен: убедитесь, что приложение HEBI Mobile I/O открыто, и что ваш ноутбук и телефон подключены к одной сети.
  • Android URL недоступен: проверьте, что вы использовали https вместо http, используйте точный IP-адрес, выведенный скриптом, и разрешите браузеру продолжить, игнорируя проблему с сертификатом.
  • Движение ощущается инвертированным: проверьте каждую ось по отдельности, затем скорректируйте инверсию знака в MapPhoneActionToRobotAction или поменяйте оси местами, чтобы соответствовать вашей конфигурации.
  • Рука почти не двигается или упирается в свои пределы: перезапустите с позы в среднем диапазоне (см. выше) — IK решается из текущей конфигурации руки.
Update on GitHub