LeRobot documentation

Phone

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

스마트폰(iOS 또는 Android)을 사용하여 로봇을 제어하세요.

이 가이드에서 다음을 배웁니다:

  • iOS/Android 휴대폰 연결 방법
  • 휴대폰 포즈가 로봇 엔드 이펙터(EE) 타겟으로 매핑되는 방법
  • 안전 한계, 그립퍼 제어 및 IK 설정 조정 방법

phone로 로봇을 제어하려면, 관련 종속성을 다음으로 설치하세요:

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: WebXR 페이지의 Move 버튼과 동일합니다.
  • 그리퍼 제어(활성화 버튼을 누르고 있든 아니든 작동):
    • 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단계: 플랫폼 선택

PhoneConfig에서 PhoneOS.IOS 또는 PhoneOS.ANDROID를 사용하도록 예제를 수정합니다. 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: WebXR 페이지에서 Move 버튼을 눌러 기준 포즈를 캡처합니다.

왜 보정해야 할까요? 현재 자세를 캡처하여 이후의 자세들이 로봇 정렬 프레임 기준으로 표현되도록 합니다. 컨트롤을 활성화하기 위해 버튼을 다시 누르면, 비활성화 상태 동안 휴대폰이 재배치된 경우 드래프트를 방지하기 위해 위치가 다시 캡처됩니다.

3단계: 예제 실행

원격 조작, 데이터셋 기록, 데이터셋 재생 또는 정책 평가 중 하나를 수행하려면 예제 스크립트 중 하나를 실행하세요.

모든 스크립트는 로봇(예: SO-100 팔로어)이 설정되고 보정된 것을 전제로 합니다.

로봇의 URDF를 제공해야 합니다. 모든 예제는 팔의 운동학적 모델이 필요한 역학 해석(inverse kinematics)을 수행하며, URDF는 LeRobot에 포함되지 않습니다.

이 튜토리얼에서 사용하는 SO-100/SO-101의 경우, LeRobot 저장소에서 SO-ARM100 repo의 SO101 폴더를 examples/phone_to_so100/로 복사하여 파일이 examples/phone_to_so100/SO101/so101_new_calib.urdf 위치에 있도록 합니다:

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은 그리퍼를 제어합니다.

또한 예제에 표시된 프로세서 단계를 편집하여 매핑 또는 안전 한도를 사용자 지정할 수 있습니다. 입력을 다시 매핑(예: 다른 아날로그 입력 사용)하거나 입력 및 운동학 단계를 수정하여 다른 로봇(예: LeKiwi)에 파이프라인을 적용할 수도 있습니다. 이 내용은 로봇 및 텔레오퍼레이터를 위한 프로세서 가이드에서 자세히 설명합니다.

  • 이 예제를 실행하여 데이터셋을 기록합니다. 이 데이터셋에는 절대적인 엔드 이펙터 관찰값과 동작이 저장됩니다:

    cd examples/phone_to_so100
    python record.py
  • 기록된 에피소드를 재생하려면 이 예제를 실행하세요:

    cd examples/phone_to_so100
    python replay.py
  • …

    cd examples/phone_to_so100
    python evaluate.py

중요한 파이프라인 단계 및 옵션

  • Kinematics는 여러 단계에서 사용됩니다. Placo는 Pinocchio를 래핑하여 Kinematics를 처리하는 데 사용됩니다. 로봇의 URDF와 target frame을 전달하여 Kinematics 객체를 구성합니다. target_frame_name을 gripper frame으로 설정합니다.

    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 단계는 목표 델타를 절대적인 목표 EE 포즈로 변환하며, 활성화 시 참조를 저장합니다. end_effector_step_sizes는 EE 포즈의 스텝 크기이며, 이를 수정하여 동작 속도를 변경할 수 있습니다.

    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 솔루션을 사용합니다.

  • Closed loop (record/eval에서 사용): initial_guess_current_joints=True를 설정하여 IK가 매 프레임 측정된 관절에서 시작하도록 합니다.

    InverseKinematicsEEToJoints(
        kinematics=kinematics_solver,
        motor_names=list(robot.bus.motors.keys()),
        initial_guess_current_joints=True,  # closed loop
    )
  • Open 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
    )

Pipeline 단계 설명

  • MapPhoneActionToRobotAction: 보정된 폰 자세와 입력을 목표 델타와 그리퍼 명령으로 변환합니다. 동작은 활성화 신호(iOS의 경우 B1, Android의 경우 Move)에 의해 제어됩니다.
  • EEReferenceAndDelta: 활성화 시 기준 EE 포즈를 고정(latch)하고, 이를 목표 델타와 결합하여 각 프레임마다 절대 목표 EE 포즈를 생성합니다. 비활성화 시에는 마지막으로 명령한 포즈를 계속 전송합니다.
  • EEBoundsAndSafety: EE 포즈를 워크스페이스로 클램프하고 안전을 위해 점프를 레이트 리밋합니다. 또한 action.ee.* 기능을 선언합니다.
  • InverseKinematicsEEToJoints: IK를 사용하여 EE 자세를 관절 위치로 변환합니다. 폐루프 제어에는 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