【无标题】
文章摘要: 本文详细介绍了如何从零开始部署机器人推理系统,重点解析了record_eval.sh脚本的使用方法。主要内容包括: 环境准备:安装LeRobot及依赖,配置HuggingFace镜像 硬件连接与标定:串口权限设置、机器人标定流程 策略获取:本地checkpoint使用或SmolVLA微调训练 推理部署:脚本参数详解,包括机器人类型、相机配置、任务描述等关键设置 常见问题排查:推理速度优
lerobot so101 从零开始到部署推理(基础配置参见官方文档)
注意:以下脚本中机械臂串口号和相机idx要根据自己实际情况更改
0. 推理部署脚本(record_eval.sh)
record_eval.sh 内容如下(下面文档会逐项解释它的参数):
#!/bin/bash
sudo chmod 666 /dev/ttyACM*
rm -rf /home/g/.cache/huggingface/lerobot/seeed/eval_screwdriver
export HF_ENDPOINT=https://hf-mirror.com
#export TRANSFORMERS_OFFLINE=1
#export HF_DATASETS_OFFLINE=1
lerobot-record \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_awesome_follower_arm \
--robot.cameras="{ camera1: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, camera2: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30}}" \
--dataset.single_task="Grab the screwdriver123" \
--dataset.repo_id=seeed/eval_screwdriver \
--dataset.episode_time_s=30 \
--dataset.num_episodes=10 \
--dataset.push_to_hub=false \
--policy.path=/home/g/robot/outputs/train/my_smolvla/checkpoints/last/pretrained_model
1. 环境准备
- 安装 LeRobot(推荐直接安装当前仓库的开发依赖;如果你用的是 SmolVLA,还需要它的额外依赖)
pip install -e .
# 如果你的策略是 SmolVLA(你的 checkpoint 路径叫 my_smolvla,强烈暗示你在用 SmolVLA)
pip install -e ".[smolvla]"
- (可选)设置 Hugging Face 镜像,避免国内网络慢/不可达
export HF_ENDPOINT=https://hf-mirror.com
- (可选)离线模式
脚本里把这两行注释掉了,表示:如果没有网络、但本地缓存齐全,可以取消注释:
# export TRANSFORMERS_OFFLINE=1
# export HF_DATASETS_OFFLINE=1
2. 真实硬件连接与标定(必须尽量按“同一套 id + 同一套硬件姿态/对齐”来)
推理部署只用到了 so101_follower(跟随臂)。但在训练数据收集阶段通常需要 leader/follower 的一致性。
2.1 硬件串口端口与权限
- 脚本用
sudo chmod 666 /dev/ttyACM*来解决串口权限问题。 - 如果你换了设备/端口号,务必同步改
--robot.port=/dev/ttyACM0。
2.2 标定(建议至少在第一次部署前做)
id 用于保存标定文件;同一个机器人 setup(尤其是电机/安装方式/姿态映射)里,id 一致性会直接影响推理效果。
SO101 follower 标定命令(官方文档示例)类似:
lerobot-calibrate \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_awesome_follower_arm
3. 获取策略 checkpoint(两条路:已有就跳过)
脚本直接使用本地 checkpoint:--policy.path=/home/g/robot/outputs/train/my_smolvla/checkpoints/last/pretrained_model
因此你需要保证该目录存在且结构正确(通常包含策略配置与权重等文件)。
3.1 如果你已经训练好了
直接跳到第 4 节“部署推理”。
3.2 如果你还没训练:用 lerobot-train 微调 SmolVLA(示例)
SmolVLA 官方文档给了类似训练命令(你把 --dataset.repo_id、--output_dir、--job_name 替换成你的即可):
cd lerobot && lerobot-train \
--policy.path=lerobot/smolvla_base \
--dataset.repo_id=${HF_USER}/mydataset \
--batch_size=64 \
--steps=20000 \
--output_dir=outputs/train/my_smolvla \
--job_name=my_smolvla_training \
--policy.device=cuda \
--wandb.enable=true
训练完成后,checkpoint 一般在:outputs/train/my_smolvla/checkpoints/last/pretrained_model
4. 部署推理(关键:运行 record_eval.sh)
- 给脚本可执行权限(只需一次):
chmod +x record_eval.sh
- 直接运行(推理 + 录制评估 episodes):
bash record_eval.sh
4.1 命令行逐项含义
-
lerobot-record
在真实机器人上循环:读取观测obs-> 用--policy.path做推理 -> 下发动作到机器人 -> 把 episode 数据写入数据集(视频/帧等)。 -
--robot.type=so101_follower
表示控制对象是 SO101 的 follower 臂。 -
--robot.port=/dev/ttyACM0
follower 串口端口;硬件换线/换设备后必须改。 -
--robot.id=my_awesome_follower_arm
用于定位/读取该机器人对应的标定文件;建议与训练/记录阶段一致。 -
--robot.cameras=...
真实相机配置。这里是两个 OpenCV 摄像头:camera1:index_or_path=0camera2:index_or_path=2
同时指定了640x480和fps=30。
-
--dataset.single_task="Grab the screwdriver123"
非常关键:推理时策略会用这个自然语言任务描述作为条件。通常应与训练/数据集收集时用的single_task完全一致或至少语义一致。 -
--dataset.repo_id=seeed/eval_screwdriver
评估数据集的标识(会写到本地缓存);设置了--dataset.push_to_hub=false,所以不会上传。 -
--dataset.episode_time_s=30与--dataset.num_episodes=10
每个 episode 运行 30 秒,总共 10 个 episode。 -
--policy.path=.../pretrained_model
部署的策略权重/配置路径(可以是本地目录,也可以是 HF repo id,取决于PreTrainedConfig.from_pretrained的支持方式)。
5. 部署效果检查与常见参数调整
5.1 推理速度跟不上怎么办
常见原因:
- 相机帧率/分辨率过高
- 策略推理耗时太长
- 编码(视频/帧保存)太慢
优先尝试:
- 降低相机分辨率或
fps - 尝试开启流式编码(官方示例里会用到
--dataset.streaming_encoding=true)
5.2 任务成功率低怎么办
优先检查:
--robot.id是否和你标定时一致--dataset.single_task是否和训练时一致/足够相近- 使用的策略是否和该 robot 数据特征匹配(不同 robot/不同特征维度的策略可能无法正确推理)
附录 sh脚本(路径以及配置请自行更改)提供给大家借鉴
标定 双臂
# rm -rf ~/.cache/huggingface/lerobot/calibration/teleoperators
# rm -rf ~/.cache/huggingface/lerobot/calibration/robots
sudo chmod 666 /dev/ttyACM*
lerobot-calibrate \
--robot.type=bi_so_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=left_follower
# lerobot-calibrate \
# --teleop.type=bi_so_leader \
# --teleop.port=/dev/ttyACM1 \
# --teleop.id=left_leader
远程推理 单臂 pi05
#!/bin/bash
sudo chmod 666 /dev/ttyACM*
python -m lerobot.async_inference.robot_client \
--server_address=10.200.25.1:8080 \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_awesome_follower_arm \
--robot.cameras="{ \
handeye: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, \
front: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30} \
}" \
--task="Grab the screwdriver123" \
--policy_type=pi05 \
--pretrained_name_or_path=/home/train_pi05/outputs/pi05_training/checkpoints/last/pretrained_model \
--policy_device=cuda \
--actions_per_chunk=50 \
--chunk_size_threshold=0.5 \
--aggregate_fn_name=weighted_average \
--debug_visualize_queue_size=True
远程推理 双臂 pi05
#!/bin/bash
sudo chmod 666 /dev/ttyACM*
# 启动双臂推理客户端
python -m lerobot.async_inference.robot_client \
--server_address=10.200.25.1:8080 \
--robot.type=bi_so_follower \
--robot.left_arm_config.port=/dev/ttyACM0 \
--robot.right_arm_config.port=/dev/ttyACM1 \
--robot.left_arm_config.cameras='{
"left_wrist": {"type": "opencv", "index_or_path": 0, "width": 640, "height": 480, "fps": 30},
"top": {"type": "opencv", "index_or_path": 2, "width": 640, "height": 480, "fps": 30}
}' \
--robot.right_arm_config.cameras='{
"right_wrist": {"type": "opencv", "index_or_path": 4, "width": 640, "height": 480, "fps": 30}
}' \
--robot.id=bimanual_follower \
--task="Wipe the plates" \
--policy_type=pi05 \
--pretrained_name_or_path=/home/train_pi05/shuangbi/outputs/pi05_training_bimanual/checkpoints/last/pretrained_model \
--policy_device=cuda \
--actions_per_chunk=100 \
--chunk_size_threshold=0.5 \
--aggregate_fn_name=weighted_average \
--debug_visualize_queue_size=True
远程推理 单臂 smolvla
#!/bin/bash
sudo chmod 666 /dev/ttyACM*
python -m lerobot.async_inference.robot_client \
--server_address=10.200.25.1:8080 \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_awesome_follower_arm \
--robot.cameras="{ \
camera1: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, \
camera2: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30} \
}" \
--task="Grab the screwdriver123" \
--policy_type=smolvla \
--pretrained_name_or_path=/home/smolvla/train_smolvla/outputs/train/my_smolvla/checkpoints/last/pretrained_model \
--policy_device=cuda \
--actions_per_chunk=50 \
--chunk_size_threshold=0.5 \
--aggregate_fn_name=weighted_average \
--debug_visualize_queue_size=True
数据录制 双臂
sudo chmod 666 /dev/ttyACM*
rm -rf /home/g/.cache/huggingface/lerobot/bi_so_follower
#export CUDA_VISIBLE_DEVICES=""
unset HTTP_PROXY HTTPS_PROXY ALL_PROXY
lerobot-record \
--robot.type=bi_so_follower \
--robot.left_arm_config.port=/dev/ttyACM0 \
--robot.right_arm_config.port=/dev/ttyACM2 \
--robot.left_arm_config.cameras='{
"left_wrist": {"type": "opencv", "index_or_path": 4, "width": 640, "height": 480, "fps": 30},
"top": {"type": "opencv", "index_or_path": 2, "width": 640, "height": 480, "fps": 30}
}' \
--robot.right_arm_config.cameras='{
"right_wrist": {"type": "opencv", "index_or_path": 0, "width": 640, "height": 480, "fps": 30}
}' \
--robot.id=bimanual_follower \
--teleop.type=bi_so_leader \
--teleop.left_arm_config.port=/dev/ttyACM1 \
--teleop.right_arm_config.port=/dev/ttyACM3 \
--teleop.id=bimanual_leader \
--display_data=false \
--dataset.repo_id=bi_so_follower/bimanual \
--dataset.num_episodes=20 \
--dataset.single_task="Wipe the plates" \
--dataset.streaming_encoding=true \
--dataset.encoder_threads=2 \
--dataset.episode_time_s=30 \
--dataset.reset_time_s=12 \
--dataset.push_to_hub=false
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)