LeRobot documentation
Telefone
Telefone
Use seu celular (iOS ou Android) para controlar seu robô.
Neste guia, você aprenderá:
- Como conectar um celular iOS/Android
- Como a pose do telefone é mapeada para os alvos do efetuor final (EE) do robô
- Como ajustar limites de segurança, controle do garfo e configurações de IK
Para usar o telefone para controlar seu robô, instale as dependências relevantes com:
pip install 'lerobot[phone,kinematics,feetech,core_scripts]'kinematics fornece a cinemática inversa usada nos exemplos, feetech os motores SO-100/SO-101 e core_scripts as ferramentas de gravação e visualização.
Comece
Plataformas suportadas
- iOS: usa o aplicativo HEBI Mobile I/O (pose ARKit + botões). Baixe o aplicativo primeiro, abra-o e os exemplos o descobrirão na sua rede e transmitirão a pose do celular e as entradas.
- Android: usa o pacote
teleop(WebXR). Ao iniciar o processo Python, ele imprime uma URL local. Abra o link no seu celular, toque em Start e, em seguida, use Move para transmitir a pose.
Links:
- Biblioteca WebXR para Android:
teleopno PyPI - Aplicativo iOS: HEBI Mobile I/O
Orientação do telefone e controles
- Orientação: segure o celular com a tela voltada para cima e a borda superior apontando na mesma direção do garfo do robô. Isso garante que a calibração alinhe o referencial do celular com o referencial do robô, para que o movimento pareça natural. Veja a imagem abaixo como referência.
- Ativar/desativar — este é um interruptor de segurança, você precisa mantê-lo pressionado durante todo o movimento:
- iOS: Segure
B1para mover o robô e solte para congelar o braço na posição em que ele estiver. Cada pressionamento reancora o celular à pose atual do braço, permitindo que você solte, leve a mão de volta para uma posição confortável, pressione novamente e continue — o robô não dá um salto. - Android: O mesmo com o botão
Movena página WebXR.
- iOS: Segure
- Controle do garfo (funciona independentemente de o botão de ativação estar pressionado):
- iOS: O controle deslizante analógico
A3controla a garra como uma entrada de velocidade — empurre para cima para abrir, puxe para baixo para fechar e solte no centro para manter. - Android: Os botões
AeBfuncionam como incremento/decremento (A abre, B fecha). Você pode ajustar a velocidade na etapaGripperVelocityToJoint.
- iOS: O controle deslizante analógico
- Grip: segure o telefone com as duas mãos, um polegar no botão de ativação (
B1) e o outro no controle deslizante do garra (A3), para que você possa controlar o braço e a garra ao mesmo tempo sem mudar a pegada. Mantenha o telefone plano enquanto faz isso — sua posição é o comando, então mudar a pegada no meio do movimento desloca o robô. - Pose inicial do robô:
teleoperate.pymove o braço para sua pose de retorno na inicialização (antes da calibração do telefone) e, ao pressionar Ctrl+C, o devolve à posição em que estava quando o script começou. Os comandos de retorno mandam cada junta do corpo para o valor de meia-volta centralizado porset_half_turn_homings()durante a calibração — a pose mantida no diagrama de calibração —, enquanto a garra é deixada onde está, para que o retorno nunca a feche sobre algo. Isso é importante porque os alvos são resolvidos com IK a partir da posição em que o braço está quando você pressiona o botão de habilitação — um braço dobrado ou totalmente esticado tem pouco espaço restante e atinge seus limites de junta. Os outros scripts de exemplo (record.py,evaluate.py,replay.py) não fazem o retorno do braço, então posicione-o lá você mesmo antes de iniciá-los.
Etapa 1: Escolha a plataforma
Modifique os exemplos para usar PhoneOS.IOS ou PhoneOS.ANDROID em PhoneConfig. A API é idêntica entre as plataformas, apenas a fonte de entrada difere. Todos os exemplos estão em examples/phone_to_so100/: teleoperate.py, record.py, replay.py, evaluate.py e rollout.py.
Exemplo de teleoperação:
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)Etapa 2: Conectar e calibrar
Quando Phone(teleop_config) é criado e connect() é chamado, a calibração é solicitada automaticamente. Segure o celular na orientação descrita acima e, em seguida:
- iOS: pressione e segure
B1para capturar a pose de referência. - Android: pressione o botão
Movena página WebXR para capturar a pose de referência.
Por que calibrar? Capturamos a pose atual para que as poses subsequentes sejam expressas em um referencial alinhado ao robô. Quando você pressionar o botão novamente para habilitar o controle, a posição será recapturada para evitar deriva caso o celular seja reposicionado enquanto o controle estava desabilitado.
Etapa 3: Executar um exemplo
Execute um dos scripts de exemplo para teleoperar, gravar um conjunto de dados, reproduzir um conjunto de dados ou avaliar uma política.
Todos os scripts pressupõem que você configurou e calibrou seu robô (por exemplo, um seguidor SO-100).
Você deve fornecer o URDF do robô. Cada exemplo resolve a cinemática inversa, que requer um modelo cinemático do braço, e o URDF não é distribuído com o LeRobot.
Para o SO-100/SO-101 usado neste tutorial, copie a pasta
SO101do repositório SO-ARM100 paraexamples/phone_to_so100/, para que o arquivo fique emexamples/phone_to_so100/SO101/so101_new_calib.urdf, estando no repositório 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/SO101Aponte os scripts para um arquivo diferente com
--urdfse você o armazenar em outro local, ou se estiver controlando outro braço.
Execute este exemplo para teleoperar, passando a porta serial do seu braço seguidor (encontre-a com
lerobot-find-port):cd examples/phone_to_so100 python teleoperate.py --port /dev/tty.usbmodem5A460814411--idseleciona qual calibração armazenada usar, e--urdfaponta para o URDF acima.
Após executar o exemplo:
- Android: após iniciar o script, abra a URL local impressa no seu celular, toque em Start e, em seguida, pressione e segure Move.
- iOS: abra primeiro o HEBI Mobile I/O; mantenha B1 pressionado para mover o robô. A3 controla o garra.
Além disso, você pode personalizar o mapeamento ou os limites de segurança editando as etapas do processador mostradas nos exemplos. Você também pode remapear as entradas (por exemplo, usar uma entrada analógica diferente) ou adaptar o pipeline para outros robôs (por exemplo, LeKiwi) modificando as etapas de entrada e cinemática. Mais sobre isso no guia Processadores para Robôs e Teleoperadores.
Execute este exemplo para gravar um conjunto de dados, que salva observações e ações absolutas do efetuador final:
cd examples/phone_to_so100 python record.pyExecute este exemplo para reproduzir episódios gravados:
cd examples/phone_to_so100 python replay.pyExecute este exemplo para avaliar uma política pré-treinada:
cd examples/phone_to_so100 python evaluate.py
Etapas e opções importantes do pipeline
A cinemática é utilizada em múltiplas etapas. Utilizamos o Placo, que é um wrapper em torno do Pinocchio para lidar com a nossa cinemática. Construímos o objeto de cinemática passando o URDF do robô e o frame de destino. Definimos
target_frame_namecomo o frame do gripper.kinematics_solver = RobotKinematics( urdf_path="./SO101/so101_new_calib.urdf", target_frame_name="gripper_frame_link", joint_names=list(robot.bus.motors.keys()), )A etapa
MapPhoneActionToRobotActionconverte a pose calibrada do telefone e as entradas em deltas de destino e comandos de garra; abaixo é mostrado o que a etapa produz.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 disabledA etapa
EEReferenceAndDeltaconverte os deltas do alvo em uma pose absoluta desejada do EE, armazenando uma referência na ativação; osend_effector_step_sizessão os tamanhos de passo para a pose do EE e podem ser modificados para alterar a velocidade do movimento.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, ),A etapa
EEBoundsAndSafetylimita o movimento do EE a um espaço de trabalho e verifica saltos grandes na etapa do EE para garantir a segurança. Osend_effector_boundssão os limites para a pose do EE e podem ser modificados para alterar o espaço de trabalho. Osmax_ee_step_msão os limites de etapa para a pose do EE e podem ser modificados para alterar os limites de segurança.EEBoundsAndSafety( end_effector_bounds={"min": [-1.0, -1.0, -1.0], "max": [1.0, 1.0, 1.0]}, max_ee_step_m=0.10, )A etapa
GripperVelocityToJointconverte uma entrada de garra semelhante a velocidade em posição absoluta da garra usando o estado medido atual. Ospeed_factoré o fator pelo qual a velocidade é multiplicada.GripperVelocityToJoint(speed_factor=20.0)
Diferentes estimativas iniciais de IK
Utilizamos diferentes estimativas iniciais de IK nas etapas cinemáticas. Como estimativa inicial, são utilizados as juntas medidas atuais ou a solução de IK anterior.
Loop fechado (usado em gravação/avaliação): define
initial_guess_current_joints=Truepara que o IK comece das juntas medidas em cada quadro.InverseKinematicsEEToJoints( kinematics=kinematics_solver, motor_names=list(robot.bus.motors.keys()), initial_guess_current_joints=True, # closed loop )Loop aberto (usado em replay): define
initial_guess_current_joints=Falsepara que a IK continue a partir da solução de IK anterior, em vez do estado medido. Isso preserva a estabilidade da ação quando fazemos replay sem feedback.InverseKinematicsEEToJoints( kinematics=kinematics_solver, motor_names=list(robot.bus.motors.keys()), initial_guess_current_joints=False, # open loop )
Etapas do Pipeline explicadas
- MapPhoneActionToRobotAction: converte a pose calibrada do telefone e as entradas em deltas de destino e um comando de garra. O movimento é controlado por um sinal de habilitação (B1 no iOS, Move no Android).
- EEReferenceAndDelta: fixa uma pose de referência do EE ao ser habilitado e a combina com os deltas do alvo para produzir uma pose absoluta desejada do EE a cada quadro. Quando desabilitado, continua enviando a última pose comandada.
- EEBoundsAndSafety: limita a pose do EE a um espaço de trabalho e aplica limites de taxa aos saltos por segurança. Também declara os recursos
action.ee.*. - InverseKinematicsEEToJoints: converte uma pose do EE em posições de juntas com IK.
initial_guess_current_joints=Trueé recomendado para controle em malha fechada; definaFalsepara reprodução em malha aberta para estabilidade. - GripperVelocityToJoint: integra uma entrada de garra semelhante a velocidade em uma posição absoluta da garra usando o estado medido atual.
- ForwardKinematicsJointsToEE: calcula
observation.state.ee.*a partir das juntas observadas para registro e treinamento no estado do EE.
Solução de problemas
- iOS não detectado: verifique se o HEBI Mobile I/O está aberto e se seu laptop/celular estão na mesma rede.
- URL do Android inacessível: verifique se você usou
httpsem vez dehttp, use o IP exato impresso pelo script e permita que o navegador entre e ignore o problema do certificado. - O movimento parece invertido: verifique um eixo de cada vez e, em seguida, ajuste as inversões de sinal em
MapPhoneActionToRobotActionou troque os eixos para corresponder à sua configuração. - O braço mal se move ou luta contra seus limites: reinicie a partir de uma pose inicial de faixa média (veja acima) — o IK é resolvido a partir da configuração atual do braço.