手机遥操作
使用你的手机(iOS 或 Android)控制你的机器人。
在本指南中你将学到:
- 如何连接 iOS/Android 手机
- 手机姿态如何映射到机器人末端执行器(EE)目标
- 如何调整安全限制、夹爪控制和 IK 设置
要使用手机控制你的机器人,请使用以下命令安装相关依赖项:
pip install lerobot[phone]
入门
支持的平台
- iOS:使用 HEBI Mobile I/O 应用(ARKit 姿态 + 按钮)。首先下载应用,打开它,示例将在你的网络上发现它并流式传输手机姿态和输入。
- Android:使用
teleop包(WebXR)。当你启动 Python 进程时,它会打印一个本地 URL。在手机上打开链接,点击 Start,然后使用 Move 流式传输姿态。
链接:
- Android WebXR 库:PyPI 上的
teleop - iOS 应用:HEBI Mobile I/O
手机方向和控制
- 方向:握住手机,屏幕朝上,顶部边缘指向与机器人夹爪相同的方向。这确保校准将手机的坐标系与机器人坐标系对齐,使运动感觉自然,参见下图以供参考。
- 启用/禁用:
- iOS:按住
B1启用遥操作,释放以停止。第一次按下会捕获参考姿态。 - Android:按住
Move按钮,释放以停止。第一次按下会捕获参考姿态。 - 夹爪控制:
- iOS:模拟输入
A3控制夹爪作为速度输入。 - Android:按钮
A和B充当增量/减量(A 打开,B 关闭)。你可以在GripperVelocityToJoint步骤中调整速度。

步骤 1:选择平台
修改示例以在 PhoneConfig 中使用 PhoneOS.IOS 或 PhoneOS.ANDROID。API 在各平台上是相同的,只有输入源不同。所有示例都在 examples/ 下,并有 phone_so100_*.py 变体。
遥操作示例:
from lerobot.teleoperators.phone import Phone, PhoneConfig
from lerobot.teleoperators.phone.config_phone import PhoneOS
teleop_config = PhoneConfig(phone_os=PhoneOS.IOS) # 或 PhoneOS.ANDROID
teleop_device = Phone(teleop_config)
步骤 2:连接和校准
当创建 Phone(teleop_config) 并调用 connect() 时,会自动提示校准。按照上述方向握住手机,然后:
- iOS:按住
B1捕获参考姿态。 - Android:按 WebXR 页面上的
Move按钮捕获参考姿态。
为什么要校准?我们捕获当前姿态,以便后续姿态在机器人对齐的坐标系中表达。当你再次按下按钮启用控制时,会重新捕获位置,以避免在手机被重新定位时出现漂移。
步骤 3:运行示例
运行其中一个示例脚本进行遥操作、记录数据集、重放数据集或评估策略。
所有脚本都假设你配置了机器人(例如,SO-100 follower)并设置了正确的串行端口。
此外,你需要将机器人的 URDF 复制到示例文件夹中。对于本教程中的示例(使用 SO100/SO101),将 SO101 文件夹从 SO-ARM100 仓库复制到 examples/phone_to_so100/ 目录,使 URDF 文件路径变为 examples/phone_to_so100/SO101/so101_new_calib.urdf。
- 运行此示例进行遥操作:
cd examples/phone_to_so100
python teleoperate.py
运行示例后:
- 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
重要的管道步骤和选项
- 运动学在多个步骤中使用。我们使用 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 # 禁用时仍发送夹爪动作
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 解。
- 闭环(用于记录/评估):设置
initial_guess_current_joints=True,以便 IK 从每帧测量的关节开始。
InverseKinematicsEEToJoints(
kinematics=kinematics_solver,
motor_names=list(robot.bus.motors.keys()),
initial_guess_current_joints=True, # 闭环
)
- 开环(用于重放):设置
initial_guess_current_joints=False,以便 IK 从先前的 IK 解继续,而不是从测量状态继续。这在我们无反馈重放时保持动作稳定性。
InverseKinematicsEEToJoints(
kinematics=kinematics_solver,
motor_names=list(robot.bus.motors.keys()),
initial_guess_current_joints=False, # 开环
)
管道步骤说明
- MapPhoneActionToRobotAction:将校准的手机姿态和输入转换为目标增量和夹爪命令。运动由启用信号控制(iOS 上的 B1,Android 上的 Move)。
- EEReferenceAndDelta:在启用时锁存参考 EE 姿态,并将其与目标增量组合以产生每帧的绝对期望 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中的符号翻转或交换轴以匹配你的设置。