LeRobot documentation
Teléfono
Teléfono
Usa tu teléfono (iOS o Android) para controlar tu robot.
En esta guía aprenderás:
- Cómo conectar un teléfono iOS/Android
- Cómo se mapea la postura del teléfono a los objetivos del efector final (EE) del robot
- Cómo ajustar los límites de seguridad, el control del agarre y la configuración de IK
Para usar el teléfono para controlar tu robot, instala las dependencias relevantes con:
pip install 'lerobot[phone,kinematics,feetech,core_scripts]'kinematics proporciona la cinemática inversa que usan los ejemplos, feetech los motores SO-100/SO-101 y core_scripts las herramientas de grabación y visualización.
Comenzar
Plataformas compatibles
- iOS: Utiliza la aplicación HEBI Mobile I/O (pose de ARKit + botones). Descarga primero la aplicación, ábrela y los ejemplos la detectarán en tu red y transmitirán la pose del teléfono y las entradas.
- Android: usa el paquete
teleop(WebXR). Al iniciar el proceso de Python, se imprime una URL local. Abre el enlace en tu teléfono, toca Start y luego usa Move para transmitir la pose.
Enlaces:
- Biblioteca de WebXR para Android:
teleopen PyPI - Aplicación de iOS: HEBI Mobile I/O
Orientación del teléfono y controles
- Orientación: sostenga el teléfono con la pantalla hacia arriba y el borde superior apuntando en la misma dirección que el efector final del robot. Esto garantiza que la calibración alinee el marco del teléfono con el marco del robot para que el movimiento se sienta natural, consulte la imagen siguiente como referencia.
- Activar/desactivar — esto es un interruptor de seguridad, debes mantenerlo presionado durante todo el movimiento:
- iOS: Mantén pulsado
B1para mover el robot y suéltalo para congelar el brazo en su posición actual. Cada pulsación reancla el teléfono a la pose actual del brazo, por lo que puedes soltarlo, llevar la mano de vuelta a una posición cómoda, pulsar de nuevo y continuar: el robot no salta. - Android: Igual que con el botón
Moveen la página de WebXR.
- iOS: Mantén pulsado
- Control del agarre (funciona con o sin mantener pulsado el botón de activación):
- iOS: El control deslizante analógico
A3controla la pinza como entrada de velocidad: empuja hacia arriba para abrir, tira hacia abajo para cerrar y suelta en el centro para mantener. - Android: Los botones
AyBactúan como incremento/decremento (A abre, B cierra). Puedes ajustar la velocidad en el pasoGripperVelocityToJoint.
- iOS: El control deslizante analógico
- Agarre: sujete el teléfono con ambas manos, un pulgar sobre el botón de activación (
B1) y el otro sobre el deslizador del agarre (A3), para que pueda controlar el brazo y el agarre a la vez sin cambiar de posición. Mantenga el teléfono plano mientras lo hace: su postura es el comando, por lo que cambiar el agarre a mitad del movimiento desplaza al robot. - Postura inicial del robot:
teleoperate.pymueve el brazo a su postura de retorno al iniciar (antes de calibrar el teléfono) y, al pulsar Ctrl+C, lo devuelve a la posición en la que se encontraba cuando comenzó el script. Los comandos de retorno mandan cada articulación del cuerpo al valor de media vuelta queset_half_turn_homings()centró durante la calibración, es decir, la postura mostrada en el diagrama de calibración, mientras que el efector final se deja donde está para que el retorno nunca lo cierre sobre algo. Esto es importante porque los objetivos se resuelven con IK desde la posición en la que se encuentra el brazo al pulsar el botón de activación: un brazo plegado o completamente extendido tiene poco margen y se topa con los límites de sus articulaciones. Los otros scripts de ejemplo (record.py,evaluate.py,replay.py) no realizan el retorno del brazo, así que colócalo en esa postura tú mismo antes de ejecutarlos.
Paso 1: Elija la plataforma
Modifique los ejemplos para que usen PhoneOS.IOS o PhoneOS.ANDROID en PhoneConfig. La API es idéntica en todas las plataformas, solo difiere la fuente de entrada. Todos los ejemplos están en examples/phone_to_so100/: teleoperate.py, record.py, replay.py, evaluate.py y rollout.py.
Ejemplo de teleoperación:
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)Paso 2: Conectar y calibrar
Cuando se crea Phone(teleop_config) y se llama a connect(), se solicita la calibración automáticamente. Mantenga el teléfono en la orientación descrita anteriormente y luego:
- iOS: mantén presionado
B1para capturar la pose de referencia. - Android: presione el botón
Moveen la página de WebXR para capturar la pose de referencia.
¿Por qué calibrar? Capturamos la pose actual para que las poses posteriores se expresen en un marco alineado con el robot. Cuando vuelves a presionar el botón para habilitar el control, la posición se vuelve a capturar para evitar el desplazamiento (drift) en caso de que el teléfono se haya reposicionado mientras el control estaba deshabilitado.
Paso 3: Ejecutar un ejemplo
Ejecuta uno de los scripts de ejemplo para teleoperar, grabar un conjunto de datos, reproducir un conjunto de datos o evaluar una política.
Todos los scripts asumen que has configurado y calibrado tu robot (p. ej., un seguidor SO-100).
Debe proporcionar el URDF del robot. Cada ejemplo resuelve la cinemática inversa, lo que requiere un modelo cinemático del brazo, y el URDF no se incluye con LeRobot.
Para el SO-100/SO-101 utilizado en este tutorial, copie la carpeta
SO101del repositorio SO-ARM100 aexamples/phone_to_so100/, de modo que el archivo quede enexamples/phone_to_so100/SO101/so101_new_calib.urdf, al estar en el repositorio 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/SO101Apunte los scripts a un archivo diferente con
--urdfsi lo guarda en otro lugar, o si está controlando otro brazo.
Ejecute este ejemplo para teleoperar, pasando el puerto serie de su brazo seguidor (encuéntrelo con
lerobot-find-port):cd examples/phone_to_so100 python teleoperate.py --port /dev/tty.usbmodem5A460814411--idselecciona qué calibración almacenada se debe usar, y--urdfapunta al URDF anterior.
Después de ejecutar el ejemplo:
- Android: después de iniciar el script, abre la URL local impresa en tu teléfono, toca Start y luego mantén presionado Move.
- iOS: abra primero HEBI Mobile I/O; mantenga presionado B1 para mover el robot. A3 controla el actuador de agarre.
Además, puedes personalizar el mapeo o los límites de seguridad editando los pasos del procesador mostrados en los ejemplos. También puedes remapear las entradas (p. ej., usar una entrada analógica diferente) o adaptar el pipeline a otros robots (p. ej., LeKiwi) modificando los pasos de entrada y cinemática. Más información al respecto en la guía Processors for Robots and Teleoperators.
Ejecute este ejemplo para registrar un conjunto de datos, que guarda las observaciones y acciones absolutas del efector final:
cd examples/phone_to_so100 python record.pyEjecute este ejemplo para reproducir los episodios grabados:
cd examples/phone_to_so100 python replay.pyEjecute este ejemplo para evaluar una política preentrenada:
cd examples/phone_to_so100 python evaluate.py
Pasos y opciones importantes del pipeline
La cinemática se utiliza en varias etapas. Utilizamos Placo, que es un envoltorio de Pinocchio para gestionar nuestra cinemática. Construimos el objeto de cinemática pasando el URDF del robot y el marco objetivo. Establecemos
target_frame_nameen el marco del agarre.kinematics_solver = RobotKinematics( urdf_path="./SO101/so101_new_calib.urdf", target_frame_name="gripper_frame_link", joint_names=list(robot.bus.motors.keys()), )El paso
MapPhoneActionToRobotActionconvierte la pose calibrada del teléfono y las entradas en deltas objetivo y comandos de pinza; a continuación se muestra lo que el paso genera como salida.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 disabledEl paso
EEReferenceAndDeltaconvierte los deltas objetivo en una pose absoluta deseada del EE, almacenando una referencia al activarse; losend_effector_step_sizesson los tamaños de paso para la pose del EE y pueden modificarse para cambiar la velocidad del movimiento.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, ),El paso
EEBoundsAndSafetylimita el movimiento del EE a un espacio de trabajo y verifica los saltos grandes en los pasos del EE para garantizar la seguridad. Losend_effector_boundsson los límites para la pose del EE y se pueden modificar para cambiar el espacio de trabajo. Losmax_ee_step_mson los límites de paso para la pose del EE y se pueden modificar para cambiar los límites de seguridad.EEBoundsAndSafety( end_effector_bounds={"min": [-1.0, -1.0, -1.0], "max": [1.0, 1.0, 1.0]}, max_ee_step_m=0.10, )El paso
GripperVelocityToJointconvierte una entrada de pinza de tipo velocidad en una posición absoluta de la pinza utilizando el estado medido actual. Elspeed_factores el factor por el cual se multiplica la velocidad.GripperVelocityToJoint(speed_factor=20.0)
Suposiciones iniciales de IK diferentes
Utilizamos diferentes estimaciones iniciales de IK en los pasos cinemáticos. Como estimación inicial se utilizan las articulaciones medidas actuales o la solución de IK anterior.
Bucle cerrado (usado en grabación/evaluación): establece
initial_guess_current_joints=Truepara que la IK comience desde las articulaciones medidas en cada fotograma.InverseKinematicsEEToJoints( kinematics=kinematics_solver, motor_names=list(robot.bus.motors.keys()), initial_guess_current_joints=True, # closed loop )Bucle abierto (usado en la reproducción): establece
initial_guess_current_joints=Falsepara que la IK continúe desde la solución de IK anterior en lugar del estado medido. Esto preserva la estabilidad de la acción cuando se reproduce sin retroalimentación.InverseKinematicsEEToJoints( kinematics=kinematics_solver, motor_names=list(robot.bus.motors.keys()), initial_guess_current_joints=False, # open loop )
Explicación de los pasos del pipeline
- MapPhoneActionToRobotAction: convierte la pose y las entradas del teléfono calibradas en deltas objetivo y un comando de pinza. El movimiento se controla mediante una señal de activación (B1 en iOS, Move en Android).
- EEReferenceAndDelta: fija una pose de referencia del EE al habilitarse y la combina con los deltas objetivo para producir una pose absoluta deseada del EE en cada fotograma. Cuando está deshabilitado, sigue enviando la última pose comandada.
- EEBoundsAndSafety: limita la pose del EE a un espacio de trabajo y limita la velocidad de los saltos por seguridad. También declara las características
action.ee.*. - InverseKinematicsEEToJoints: convierte una pose del EE en posiciones de articulaciones mediante IK. Se recomienda
initial_guess_current_joints=Truepara el control en lazo cerrado; establezcaFalsepara la reproducción en lazo abierto por estabilidad. - GripperVelocityToJoint: integra una entrada de pinza de tipo velocidad en una posición absoluta de la pinza utilizando el estado medido actual.
- ForwardKinematicsJointsToEE: calcula
observation.state.ee.*a partir de las articulaciones observadas para el registro y el entrenamiento en el estado de EE.
Solución de problemas
- iOS no detectado: asegúrate de que HEBI Mobile I/O esté abierto y de que tu portátil/teléfono estén en la misma red.
- No se puede acceder a la URL de Android: compruebe que localmente utilizó
httpsen lugar dehttp, use la IP exacta que imprime el script y permita que su navegador entre e ignore el problema del certificado. - El movimiento parece invertido: comprueba un eje a la vez y luego ajusta las inversiones de signo en
MapPhoneActionToRobotActiono intercambia los ejes para que coincidan con tu configuración. - El brazo apenas se mueve o lucha contra sus límites: reinicie desde una pose inicial de rango medio (véase arriba) — la IK se resuelve desde la configuración actual del brazo.