LeRobot documentation
Телефон
Телефон
Управляйте своим роботом с помощью телефона (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 для потоковой передачи позы.
Ссылки:
- Библиотека Android WebXR:
teleopна PyPI - Приложение для iOS: HEBI Mobile I/O
Ориентация телефона и управление
- Ориентация: держите телефон экраном вверх, а верхней кромкой в том же направлении, что и захват робота. Это обеспечивает выравнивание системы координат телефона с системой координат робота при калибровке, благодаря чему движение ощущается естественным. См. изображение ниже для справки.
- Вкл/выкл — это кнопка аварийного останова: её нужно удерживать нажатой на протяжении всего движения:
- iOS: удерживайте
B1, чтобы перемещать робота, отпустите, чтобы зафиксировать руку в текущем положении. Каждое нажатие заново привязывает телефон к текущей позе руки, поэтому можно отпустить, вернуть руку в удобное положение, нажать снова и продолжить — робот не будет дёргаться. - Android: то же самое с кнопкой
Moveна странице WebXR.
- iOS: удерживайте
- Управление захватом (работает независимо от того, удерживается ли кнопка включения):
- iOS: аналоговый слайдер
A3управляет захватом как вход скорости — нажимайте вверх, чтобы открыть, тяните вниз, чтобы закрыть, отпустите в центре, чтобы удержать. - Android: кнопки
AиBработают как увеличение/уменьшение (A открывает, B закрывает). Скорость можно настроить на шагеGripperVelocityToJoint.
- iOS: аналоговый слайдер
- Ухват: держите телефон обеими руками, один большой палец на кнопке включения (
B1), другой на ползунке захвата (A3), чтобы одновременно управлять рукой и захватом, не меняя хват. Держите телефон горизонтально во время движения — его положение является командой, поэтому смена хвата в процессе движения приводит к перемещению робота. - Позиция робота при запуске:
teleoperate.pyперемещает манипулятор в домашнюю позицию при старте (до калибровки телефона), а при нажатии Ctrl+C возвращает его в то положение, в котором он находился в момент запуска скрипта. Команды возврата в домашнюю позицию задают каждому суставу манипулятора значение полуоборота, котороеset_half_turn_homings()центрировало во время калибровки — это та поза, что показана на схеме калибровки, — при этом захват остаётся в своём текущем положении, чтобы при возврате он не сомкнулся на каком-либо предмете. Это важно, потому что целевые позиции вычисляются методом IK от текущего положения манипулятора в момент нажатия кнопки включения — если манипулятор сложён или полностью вытянут, у него остаётся мало места для манёвра, и он упирается в пределы суставов. Другие примеры скриптов (record.py,evaluate.py,replay.py) не возвращают манипулятор в домашнюю позицию, поэтому разместите его там самостоятельно перед их запуском.
Шаг 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 решается из текущей конфигурации руки.