基于SoArm100的SmolVLA应用-Lerobot v0.4.4
目录
0.参考
Lerobot 中使用 SO100/101Arm 机器人手臂 | Seeed Studio Wiki
https://huggingface.co/blog/smolvla
SmolVLAを転移学習してLeRobot SO-101へ実機デプロイしたい! #基盤モデル - Qiita
![]()
本项目使用Lerobot v0.4.4,其他版本指令可能不一致。
概述
- 仅使用开源社区共享的数据集进行预训练,数据集标签为lerobot。
- SmolVLA-450M的表现优于许多更大的 VLA 模型,并且在仿真任务(LIBERO,Meta-World)和实际任务(SO100, SO101)上超过了强基线模型,如ACT。
- 支持异步推理,可提供30% 更快的响应和2 倍的任务吞吐量。
- 足够小,可以在 CPU 上运行,单个消费级 GPU 上训练,甚至可以在 MacBook 上运行!
- 训练使用的是公开的、社区共享的机器人数据
- 发布时附带完整的训练和推理方案
- 可以在非常经济的硬件上进行测试和部署(如 SO-100、SO-101、LeKiwi 等)

1.安装 LeRobot
conda create -y -n lerobot_vla python=3.10 && conda activate lerobot_vla
git clone https://github.com/Seeed-Projects/lerobot.git
# 安装带有 feetech 电机依赖的 LeRobot:
cd lerobot
pip install -e ".[feetech]"
# 安装smolvla相关的库
pip install -e ".[smolvla]"
2.校准机械臂
首先,您需要授予接口权限,运行以下命令:
sudo chmod 666 /dev/ttyACM*
从动臂
拔掉其他的相机和机械臂,第一个插入从动臂,端口号就是 ttyACM0
第一步:移动到中间姿态
第二步:动态移动到最大值和最小值位置
lerobot-calibrate \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_awesome_follower_arm
![]()
注意:新版的校准和之前不一样了,新版是把机器人移动到中间位置和最大最小,这点需要格外注意。建议参考 Seeed的B站视频。
【SO-ARM机械臂Lerobot超详细上手教程:5校准及遥操作】 SO-ARM机械臂Lerobot超详细上手教程:5校准及遥操作_哔哩哔哩_bilibili
主动臂
继续插入主动臂的控制板,端口号为ttyACM1.
lerobot-calibrate \
--teleop.type=so101_leader \
--teleop.port=/dev/ttyACM1 \
--teleop.id=my_awesome_leader_arm
遥操作
先对串口给予权限:
sudo chmod 666 /dev/ttyACM*
运行遥操作:
lerobot-teleoperate \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_awesome_follower_arm \
--teleop.type=so101_leader \
--teleop.port=/dev/ttyACM1 \
--teleop.id=my_awesome_leader_arm
遥控操作命令将自动执行以下步骤:
- 识别任何缺失的校准文件并启动校准程序。
- 连接机器人和遥控设备,并开始遥控操作。
3.添加摄像头
要查找连接到您系统的摄像头的摄像头索引,请运行以下脚本:
lerobot-find-cameras opencv
- 带摄像头的遥操作,只有这个运行成功之后,才能进行后续采集数据的实验。
- 在正式采集之前,可以根据这个来调整相机的视角,确保正式采集时视角合理,机器人和物块在视野内。
lerobot-teleoperate \
--robot.type=so100_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_awesome_follower_arm \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30, fourcc: "MJPG"}, side: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30, fourcc: "MJPG"}}" \
--teleop.type=so100_leader \
--teleop.port=/dev/ttyACM1 \
--teleop.id=my_awesome_leader_arm \
--display_data=tru
4.采集数据
采集数据的相关指令如下,但是需要注意的是:
- 这是VLA模型,所以
single_task任务描述就是作为训练的自然语言,需要和实际任务匹配。需要针对你的应用进行修改。 - 每次采集需要换不同的数据集名称
repo_id,否则会报错。
lerobot-record \
--robot.type=so100_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_awesome_follower_arm \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30, fourcc: "MJPG"}, side: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30, fourcc: "MJPG"}}" \
--teleop.type=so100_leader \
--teleop.port=/dev/ttyACM1 \
--teleop.id=my_awesome_leader_arm \
--display_data=true \
--dataset.repo_id=smolvla/greenbook \
--dataset.num_episodes=10 \
--dataset.single_task="put the cup on the green book" \
--dataset.push_to_hub=false \
--dataset.episode_time_s=30 \
--dataset.reset_time_s=10
lerobot-record \
--robot.type=so100_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_awesome_follower_arm \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30, fourcc: "MJPG"}, side: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30, fourcc: "MJPG"}}" \
--teleop.type=so100_leader \
--teleop.port=/dev/ttyACM1 \
--teleop.id=my_awesome_leader_arm \
--display_data=true \
--dataset.repo_id=smolvla/redbook \
--dataset.num_episodes=10 \
--dataset.single_task="put the cup on the red book" \
--dataset.push_to_hub=false \
--dataset.episode_time_s=30 \
--dataset.reset_time_s=10
这里提供一个测试场景:
- 把杯子放在红色的书上。put the cup on the red book
- 把杯子放在绿色的书上。put the cup on the green book

5.训练
- 训练的时候,会从huggingface拉取smolVLA的基础模型资源,但是国内访问huggingface会有问题,所以需要设置镜像站,以便于下载smolvla预训练模型。
export HF_ENDPOINT=https://hf-mirror.com
单一任务
- 单一任务表现和模仿学习很类似,仅训练20k步效果还不错,也可以选择更大的步数。
lerobot-train \
--policy.path=lerobot/smolvla_base \
--policy.push_to_hub=false \
--dataset.repo_id=smolvla/redbook \
--batch_size=64 \
--steps=20000 \
--output_dir=outputs/train/redbook \
--job_name=my_smolvla_training \
--policy.device=cuda \
--wandb.enable=false \
--rename_map='{"observation.images.front": "observation.images.camera1", "observation.images.side": "observation.images.camera2"}'
多个任务
![]()
注意:顺序训练的灾难性遗忘问题
我之前的训练方法是顺序微调,也就是先在数据集A上训练,然后在数据集B上训练,这样会导致B训练结束之后,把A全忘记了,也就是“灾难性遗忘”问题。对于多个数据集,需要先合并数据集,再训练。
具体可以查看附录。
- 假如之前采集了两组数据集,smolvla/redbook和smolvla/greenbook ,可以通过以下指令进行数据集的合并。
lerobot-edit-dataset \
--repo_id smolvla/mixed_book \
--operation.type merge \
--operation.repo_ids "['smolvla/redbook', 'smolvla/greenbook']"
- 然后利用合并的数据集训练,这里的
dataset.repo_id指向 smolvla/mixed_book 。
lerobot-train \
--policy.path=lerobot/smolvla_base \
--dataset.repo_id=smolvla/mixed_book \
--policy.push_to_hub=false \
--batch_size=64 \
--steps=100000 \
--output_dir=outputs/train/joint_books \
--job_name=smolvla_joint_training \
--policy.device=cuda \
--wandb.enable=false \
--rename_map='{"observation.images.front": "observation.images.camera1", "observation.images.side": "observation.images.camera2"}'
6.推理
- 注意这里的
--policy.path选择你之前训练输出的地址,需要指向模型文件所在的文件夹。 - 由于每隔20k步,都会保存一个checkpoints,所以也可以选择中间训练得到的模型。
lerobot-record \
--robot.type=so100_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, "fourcc": "MJPG"}, "camera2": {"type": "opencv", "index_or_path": 2, "width": 640, "height": 480, "fps": 30, "fourcc": "MJPG"}}' \
--dataset.single_task="put the cup on the green book" \
--dataset.repo_id=smolvla/eval_1 \
--dataset.episode_time_s=60 \
--dataset.reset_time_s=10 \
--dataset.push_to_hub=false \
--dataset.num_episodes=10 \
--policy.path=outputs/train/joint_books/checkpoints/040000/pretrained_model \
--teleop.type=so100_leader \
--teleop.port=/dev/ttyACM1 \
--teleop.id=my_awesome_leader_arm
7.实验结果
-
我把A、B数据集先合并起来,再训练,它就会同时从A、B数据集中学习经验。 最后的推理结果表示,机器人可以区分我的指令中的“on the red book” 和 “ on the green book”,能够把杯子放在正确颜色的书上。
-
如果我用白纸替换书本,把指令换成“put the cup on the white paper”,机器人也可以正确放置,表明它对于颜色有一定的泛化能力。
-
如果我放置一个棕色的快递盒,把指令换成 “put the cup on the brown box”,机器人就不能正确放置了。因为快递盒比书本厚的多,机器人并不会抬升到足够高的高度,而是直接撞上去。 也可能是侧面相机视角的原因,它对于高度的感知并不强。
-
如果从被抓取物体入手,把杯子换成一个红色的立方体,把指令换成“put the red cube on the green book”,机器人虽然有相应的抓取放置动作,但是并不能抓到方块,只是在空中执行动作。
附录
问题记录
1.灾难性遗忘
我在Lerobot中使用SmolVLA模型,我采集了两组数据,第一组将杯子放在红色的书上 数据集叫redbook,第二组将杯子放在绿色的书上,数据集叫greenbook。
我在smolvla_base的基础模型上训练 ,使用redbook数据集,训练20k次,得到预训练模型,然后再在预训练的基础上使用greenbook数据集训练,得到最终的模型。但是推理的时候,无论我给的指令是“put the cup on the red book ”还是“put the cup on the green book” ,都只会把杯子放在绿色的书上。 可能是什么原因?
这是一个经典的灾难性遗忘(Catastrophic Forgetting)问题,结合你的训练流程来分析:
你的训练流程是顺序微调(Sequential Fine-tuning):
smolvla_base → 训练redbook 20k → 预训练模型 → 训练greenbook → 最终模型
当你在greenbook上继续训练时,神经网络的权重被大幅更新以适应新任务,覆盖了之前学到的redbook相关知识。最终模型几乎"忘记"了如何响应red book指令,只记得最近训练的green book行为。
为什么语言指令没有起作用?
SmolVLA是视觉-语言-动作模型,语言指令理论上应该区分两个任务。但问题在于:
- 语言条件没有被充分学习:如果base模型本身对语言条件的动作控制较弱,微调时模型可能走了"捷径"——直接学习视觉特征→动作的映射,而忽略语言输入
- greenbook训练覆盖了语言-动作绑定:第二阶段训练让模型将所有动作都与"放书"场景绑定,无论指令内容
- 数据量不平衡:如果greenbook数据量远大于redbook,模型会强烈偏向green
什么是灾难性遗忘
灾难性遗忘是机器学习,尤其是神经网络领域的一个核心难题。
简单来说,它指的是:当一个神经网络在学习新任务时,会急剧、彻底地遗忘之前学过的旧任务。
这就像一个学生,为了通过周一的数学考试,把之前背熟的英语单词全忘光了。更麻烦的是,这种遗忘不是渐进式的,而是断崖式的——一旦开始学新东西,旧知识的准确率会从很高直接跌落到近乎随机猜测的水平。
这源于人工神经网络与生物大脑的本质不同。
- 参数共享:神经网络的同一个“参数”(可以理解为神经连接的强度)必须同时服务于所有任务。学习新任务时,网络会调整这些参数来适应新数据,但这往往会覆盖掉原先对旧任务有用的参数配置。
- 缺乏巩固机制:人脑在睡眠时,会通过重放白天的经历,将重要记忆从海马体(临时存储)转移到新皮层(长期存储),从而巩固记忆。而标准神经网络没有这种主动保护重要知识的能力。
- 任务边界模糊:网络在学习新任务的数据时,无法自动识别“现在学的和以前是不同任务”,只会一味地降低当前任务的损失(即预测误差),从而无差别地修改参数。
这个问题严重限制了深度学习在现实世界中的应用:
- 无法持续学习:AI不能像人类一样,通过终身学习不断积累技能。想让一个已训练好的AI学点新东西,往往需要用新旧数据混合起来重新训练整个模型,计算成本极高。
- 多任务能力差:很难训练一个单一的、能同时完成数十上百个不同任务的通用模型。通常只能为每个任务单独训练模型。
- 在线学习失效:在自动驾驶、机器人等需要根据新数据流不断实时更新模型的场景中,模型可能会因为学到新场景(如雪地)而突然忘记如何应对旧场景(如晴天)。
如果我有多个数据集,是不是不能采用顺序微调的方式,让它学习?
是的,如果你直接对同一个模型进行“顺序微调”(先在一个数据集上训练好,再在下一个数据集上继续训练),几乎必然会导致灾难性遗忘——模型会迅速丢失前一个数据集上学到的知识。
如果你确实有多个数据集,且希望模型最终能同时掌握所有任务,请避免简单的顺序微调,改用以下方法:
| 方案 | 做法 | 优点 | 缺点 |
|---|---|---|---|
| 联合训练 | 将所有数据集合并,打乱后一次性训练模型 | 无遗忘问题,效果通常最好 | 需要同时访问所有数据;内存和计算可能过大 |
| 持续学习方法 | 使用弹性权重巩固(EWC)、记忆重放等技术,在顺序学习时保护旧知识 | 可以顺序学习,无需同时存储所有数据 | 实现复杂;仍有轻微遗忘;需要调参 |
| 多任务学习架构 | 设计共享主干 + 任务特定分支(如多头输出层) | 隔离任务,互不干扰 | 需要知道任务身份;模型参数随任务数增加 |
具体建议:
- 如果所有数据可以同时加载:直接联合训练。这是最安全、最简单的方法。
- 如果数据不能同时加载(比如隐私、存储限制):使用经验重放(保留一小部分旧数据的样本,混在新数据中一起训练)或 EWC。
方案:合并数据集
Dataset Manipulation Tools - LeRobot
https://github.com/huggingface/lerobot/blob/main/docs/source/using_dataset_tools.mdx
数据集必须包含:
- 相同的帧率
- 兼容功能(相同的键、数据类型、形状)
- 同类型机器人(推荐)
- 使用脚本合并
from lerobot.datasets.lerobot_dataset import LeRobotDataset
from lerobot.datasets.dataset_tools import merge_datasets
# 加载两个数据集
dataset1 = LeRobotDataset("smolvla/redbook")
dataset2 = LeRobotDataset("smolvla/greenbook")
# 合并数据集到本地
merged = merge_datasets(
datasets=[dataset1, dataset2],
output_repo_id="smolvla/mixed_book",
output_dir="/home/imc/.cache/huggingface/lerobot/smolvla/mixed_book"
)
print(f"Merged dataset: {merged.num_episodes} episodes")
print(f"Total frames: {merged.num_frames}")
- 使用命令行合并
lerobot-edit-dataset \
--repo_id smolvla/mixed_book \
--operation.type merge \
--operation.repo_ids "['smolvla/redbook', 'smolvla/greenbook']"

- 查看数据集meta文件,可以发现数据集按顺序排列了。

使用合并数据集训练
lerobot-train \
--policy.path=lerobot/smolvla_base \
--dataset.repo_id=smolvla/mixed_book \
--policy.push_to_hub=false \
--batch_size=64 \
--steps=100000 \
--output_dir=outputs/train/joint_books \
--job_name=smolvla_joint_training \
--policy.device=cuda \
--wandb.enable=false \
--rename_map='{"observation.images.front": "observation.images.camera1", "observation.images.side": "observation.images.camera2"}'
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)