基于LeRobot框架在SO-101机器人上训练ACT模仿学习策略的完整实践指南

📅 2026/7/18 6:00:30
基于LeRobot框架在SO-101机器人上训练ACT模仿学习策略的完整实践指南
1. 从零到一为什么要在SO-101机器人上训练ACT策略如果你正在研究机器人模仿学习尤其是想把那些酷炫的算法从论文搬到真实的机械臂上那么“在SO-101机器人上训练ACT策略”这个标题很可能就是你正在寻找的“最后一公里”指南。我花了相当长的时间从仿真环境搭建、数据采集、模型训练到最后的真实部署把整个流程完整地走了一遍。这个过程远不止是跑通一个Demo它涉及到对算法原理的深刻理解、对硬件接口的熟悉以及对各种“坑”的预判和规避。ACT全称Action Chunking with Transformers是近年来在机器人模仿学习领域非常受关注的一种策略架构。它的核心思想很直观人类在执行复杂任务时比如泡茶并不是一个动作接一个动作地僵硬执行而是会预先规划好一连串的动作拿起水壶、走到饮水机、按下开关…然后流畅地执行这一“动作块”。ACT策略借鉴了Transformer模型强大的序列建模能力让机器人也能学会这种“瞻前顾后”的规划方式。它接收当前的环境观测比如相机图像、关节角度然后直接输出未来一段时间内一个“块”的一系列动作指令。这种方式比传统的单步策略更高效动作也更连贯平滑。那么为什么是SO-101机器人呢SO-101或者更常见的称呼是SO-Arm101是一款在研究和教育领域非常流行的桌面级协作机械臂。它价格相对亲民开源程度高并且有成熟的ROSRobot Operating System驱动和仿真支持。这意味着你完全可以在个人电脑上用LeRobot这样的开源机器人学习框架搭建一个从仿真训练到真机验证的完整闭环。这对于个人研究者、学生团队或者想快速验证算法原型的工程师来说是一个极具性价比和可行性的选择。LeRobot则是这个拼图中的关键软件框架。它由Meta AI前Facebook AI团队开源旨在降低机器人学习的门槛。你可以把它理解为一个“工具箱”里面集成了数据管理、模型训练、策略部署等一整套工具并且对ACT等前沿算法提供了官方支持。使用LeRobot你不需要从零开始写数据加载器、训练循环和评估脚本可以更专注于算法本身和任务设计。所以这篇内容的目标就是带你深入这个具体的技术栈使用LeRobot框架为SO-101机器人训练一个ACT策略。我会假设你具备基本的Python编程和深度学习知识但对机器人或LeRobot可能并不熟悉。我们将从最基础的环境搭建讲起一步步深入到数据、模型、训练和部署的每一个细节并分享那些在官方文档里可能找不到的实操经验和避坑要点。2. 环境搭建打造你的机器人学习工作站万事开头难一个稳定、兼容的环境是后续所有工作的基石。这里的环境分为两部分机器人仿真环境和LeRobot算法框架环境。我们的目标是让这两者在你的电脑上和谐共处。2.1 仿真环境搭建让SO-101在虚拟世界中动起来在真机上反复试错成本高昂且危险因此我们首先需要在仿真环境中进行开发和初步验证。对于SO-101最常用的仿真平台是MuJoCo配合Franka Emika Panda的模型因为SO-101的动力学模型与Panda高度相似社区通常直接使用Panda的模型进行仿真或者使用PyBullet。LeRobot官方示例更倾向于使用MuJoCo。第一步安装MuJoCoMuJoCo现在已对个人免费但安装步骤稍显繁琐。获取许可证访问MuJoCo官网用邮箱注册并下载mjkey.txt许可证文件。下载MuJoCo本体从同一页面下载适用于你操作系统Linux/macOS/Windows的MuJoCo二进制包例如mujoco-3.0.0-linux-x86_64.tar.gz。安装与配置# 解压到用户目录下 mkdir -p ~/.mujoco tar -xzf mujoco-3.0.0-linux-x86_64.tar.gz -C ~/.mujoco mv ~/.mujoco/mujoco-3.0.0 ~/.mujoco/mujoco210 # 重命名为一个固定名称便于管理 # 将许可证文件复制过去 cp mjkey.txt ~/.mujoco/ # 设置环境变量将以下行添加到你的 ~/.bashrc 或 ~/.zshrc 文件末尾 export MUJOCO_PY_MUJOCO_PATH~/.mujoco/mujoco210 export LD_LIBRARY_PATH$LD_LIBRARY_PATH:~/.mujoco/mujoco210/bin保存后执行source ~/.bashrc使环境变量生效。第二步安装机器人仿真环境LeRobot通常与robosuite或gymnasium原OpenAI Gym环境集成。我们需要一个包含SO-101Panda模型的任务环境。# 创建并激活一个独立的Python虚拟环境强烈推荐 python -m venv lerobot_venv source lerobot_venv/bin/activate # Linux/macOS # lerobot_venv\Scripts\activate # Windows # 安装基础依赖 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 根据你的CUDA版本调整 pip install mujoco # 安装包含Panda机械臂的仿真环境例如 robosuite pip install robosuite注意mujoco-pyMuJoCo的Python绑定的安装可能会因系统而异如果遇到编译错误通常需要安装一些系统级的开发工具如gcc,cmake。在Ubuntu上可以尝试sudo apt-get install build-essential libgl1-mesa-dev libgl1-mesa-glx。验证仿真环境你可以写一个简单的脚本测试是否能成功创建一个Panda机械臂的环境并渲染。import robosuite as suite # 创建一个简单的拾取任务环境 env suite.make( “PickPlace”, robots“Panda”, has_rendererTrue, has_offscreen_rendererFalse, use_camera_obsFalse, control_freq20, ) env.reset() for _ in range(100): action env.action_space.sample() # 随机动作 obs, reward, done, info env.step(action) env.render()如果能看到一个窗口里面的机械臂在随机运动说明仿真环境搭建成功。2.2 LeRobot框架安装与配置有了仿真环境接下来安装我们的核心工具——LeRobot。安装LeRobot 官方推荐使用源码安装以便于修改和调试。# 克隆仓库 git clone https://github.com/facebookresearch/lerobot.git cd lerobot # 安装依赖LeRobot会安装自己的依赖可能与之前的环境有重叠在虚拟环境中安装可避免冲突 pip install -e .-e参数代表“可编辑模式安装”这样你修改源码后无需重新安装即可生效。安装特定任务依赖 LeRobot将不同数据集、环境和模型实现为可选的“额外依赖”。对于ACT策略和我们的仿真环境可能需要安装pip install “lerobot[simulation]” # 安装仿真相关依赖 pip install “lerobot[act]” # 安装ACT模型相关依赖安装完成后在Python中尝试import lerobot如果没有报错则框架安装成功。实操心得环境搭建是劝退第一关。我强烈建议使用conda或venv创建独立的虚拟环境并为MuJoCo、PyTorch、LeRobot分别记录其版本号。不同版本库之间的兼容性问题非常常见。一个可行的版本组合是Python 3.10, PyTorch 2.1, MuJoCo 2.3, LeRobot最新main分支。如果遇到无法解决的依赖冲突考虑使用Docker容器来获得一个完全一致的环境。3. 数据模仿学习的“燃料”没有数据再好的算法也是巧妇难为无米之炊。对于模仿学习我们需要的是“状态-动作”对序列数据。对于SO-101机器人执行某个任务比如“推方块到目标位置”的数据我们可以通过两种方式获取在仿真中录制演示或者使用已有的开源数据集。3.1 在仿真环境中录制演示数据这是最灵活的方式你可以为任何自定义任务生成数据。LeRobot提供了simulation模块来辅助这个过程。设计你的任务首先你需要在仿真环境中定义任务。例如在robosuite中你可以定义一个PickPlace任务目标是将红色方块放到绿色目标区域内。编写数据采集脚本 核心思路是人工或通过一个简单脚本控制机械臂完成一次成功的任务演示同时记录下每一步的观测图像、关节状态等和采取的动作。人工控制可以通过键盘、鼠标或游戏手柄映射到机械臂的末端执行器或关节空间来“手把手”教机器人。记录数据每一步你需要保存observation: 一个字典可能包含image相机画面、joint_pos关节位置、ee_pos末端执行器位置等。action: 当前执行的动作向量例如末端执行器的相对位移和夹爪开合。reward(可选): 如果环境提供了奖励信号。done: 是否回合结束。LeRobot期望的数据格式是HDF5文件并遵循特定的结构。一个简化的采集脚本框架如下import h5py import numpy as np import robosuite as suite from lerobot.common.datasets.utils import format_observation env suite.make(“PickPlace”, robots“Panda”, ...) obs env.reset() dataset_path “my_pickplace_demo.hdf5” with h5py.File(dataset_path, ‘w’) as f: # 创建数据集 obs_group f.create_group(“observation”) act_dataset f.create_dataset(“action”, (0, env.action_space.shape[0]), maxshape(None, env.action_space.shape[0]), chunksTrue) # 初始化索引 ep_ptr 0 ep_start_idx [0] for episode in range(num_demos): # 采集N次演示 obs env.reset() done False while not done: # 1. 获取当前观测并格式化 formatted_obs format_observation(obs) # 将obs字典转换为LeRobot格式 # 2. 人工或脚本生成动作 (这里用随机动作示例) action env.action_space.sample() # 3. 执行动作 next_obs, reward, done, info env.step(action) # 4. 存储数据 # 存储观测的各个部分到obs_group下对应的dataset for key, val in formatted_obs.items(): if key not in obs_group: maxshape (None,) val.shape[1:] obs_group.create_dataset(key, (0,) val.shape[1:], maxshapemaxshape, chunksTrue, dtypeval.dtype) # 扩展数据集并写入 dset obs_group[key] dset.resize((dset.shape[0] 1,) dset.shape[1:]) dset[-1] val # 存储动作 act_dataset.resize((act_dataset.shape[0] 1,) act_dataset.shape[1:]) act_dataset[-1] action obs next_obs ep_ptr steps_in_episode ep_start_idx.append(ep_ptr) # 保存episode边界索引 f.create_dataset(“episode_index”, dataep_start_idx)这个脚本提供了核心逻辑实际应用中需要完善错误处理、更自然的人工控制接口以及可能的多相机视角支持。3.2 使用与处理现有数据集如果你不想从头采集LeRobot官方和社区提供了一些预录制的数据集。你可以使用lerobot-cli工具轻松下载。# 列出可用数据集 lerobot-cli list-datasets # 下载一个示例数据集例如 pusht 数据集虽然可能不是Panda机械臂但格式一致 lerobot-cli download-dataset pusht --repo-name lerobot/pusht下载的数据集已经是LeRobot标准的HDF5格式可以直接用于训练。关键在于你需要确保数据集的动作空间action space和观测空间observation space与你为SO-101定义的环境相匹配。例如如果数据集中的动作是7维关节扭矩而你的仿真环境接受的是末端执行器的6维位姿增量1维夹爪那么你就需要对动作进行转换或重新训练一个适配的策略。注意事项数据质量决定性能上限。在采集或选择数据时要特别注意1)演示的成功率尽量保证每一条演示轨迹都是成功完成任务的。2)动作频率确保动作的采样频率与控制频率一致避免出现时域上的错位。3)观测对齐确保相机图像、关节状态等观测信息与动作在时间上是严格对齐的。一个常见的坑是由于渲染延迟图像观测可能比关节状态晚几毫秒这需要在数据采集时进行同步或补偿。4. ACT策略模型详解理解其内部运作机制在准备好数据之后我们需要深入理解将要训练的模型——ACT。知其然更要知其所以然这能帮助你在模型不收敛时进行有效调试。4.1 ACT的核心思想与架构ACT的出发点很明确模仿人类动作的“块状”特性。传统策略网络如MLP在每个时间步t根据当前观测o_t输出单个动作a_t。而ACT则输出一个长度为K的动作序列块[a_t, a_{t1}, ..., a_{tK-1}]。在推理时我们执行这个块里的第一个动作a_t然后根据新的观测让模型重新预测一个新的动作块如此循环。这种“重规划”机制使得策略对误差有一定的鲁棒性。那么ACT如何实现这一点的呢它本质上是一个条件变分自编码器CVAE与Transformer解码器的结合体。编码器Encoder接收当前的观测序列例如最近几帧的图像和状态o_t以及任务目标g如果有的话将其编码为一个潜在的上下文向量z。这个z捕捉了当前完成任务所需的所有相关信息。解码器Decoder一个Transformer解码器。它以潜在变量z和一组可学习的“动作查询Action Queries”作为输入。这些动作查询可以理解为K个不同的“位置”每个位置负责预测动作序列块中对应时间步的动作。Transformer解码器利用自注意力机制和交叉注意力机制关注z为每个查询位置输出一个动作。最终K个查询就对应了K个未来的动作。为什么用Transformer因为Transformer擅长处理序列数据并且其自注意力机制能让模型在预测a_{t2}时不仅考虑z还能考虑到它已经“计划”好的a_t和a_{t1}从而保证整个动作块的内部协调性和物理合理性。4.2 LeRobot中ACT的实现要点在LeRobot的代码库中ACT模型通常定义在lerobot/models/act/modeling_act.py这样的文件中。理解几个关键配置对于训练至关重要action_horizon(K)动作块的长度。这是最重要的超参数之一。太短如K4则重规划频繁可能不够平滑太长如K20则预测难度大且容易累积误差。对于SO-101这类机械臂的中等速度任务K8到16是一个不错的起点。observation_horizon用于编码的过去观测帧数。模型不是只看当前一帧而是看最近几帧的历史这有助于感知物体的运动速度等信息。通常设为1或2。latent_dim潜在变量z的维度。决定了模型表达能力的上限但过大也会增加训练难度和过拟合风险。128或256是常见值。hidden_dimTransformer内部的前馈网络维度。num_encoder_layers/num_decoder_layersTransformer编码器/解码器的层数。层数越多模型能力越强但也越难训练。在LeRobot的配置文件中通常是config.yaml你会看到类似这样的模型定义部分model: _target_: lerobot.models.act.act.ACT action_horizon: 16 observation_horizon: 2 latent_dim: 256 hidden_dim: 512 num_encoder_layers: 4 num_decoder_layers: 4 ...理解这些参数的含义是进行有效调参的基础。5. 训练流程与配置让模型从数据中学习有了数据和模型定义接下来就是训练环节。LeRobot通过Hydra配置管理系统来组织训练这使得实验管理变得非常清晰。5.1 准备训练配置文件LeRobot的训练入口通常是一个Python脚本如train.py它读取一个YAML配置文件。你需要为你的SO-101任务创建一个配置文件。最简单的方法是复制一个现有的ACT配置文件并修改。cp lerobot/configs/act/pusht.yaml lerobot/configs/act/so101_pickplace.yaml然后编辑so101_pickplace.yaml关键部分需要修改# 数据配置 dataset: name: “my_pickplace” # 你数据集的名字对应你HDF5文件的命名或下载的数据集ID repo: null # 如果是本地文件设为null path: “/path/to/your/my_pickplace_demo.hdf5” # 本地数据集的绝对路径 # 环境配置用于评估 env: name: “robosuite/PickPlace-v0” # 你的仿真环境名称 # 需要指定动作空间和观测空间使其与你的数据集匹配 action_space: type: “continuous” shape: [8] # 例如7维关节位置/速度 1维夹爪 observation_space: images: [“agentview_image”] # 相机视角名称 state: [“joint_pos”, “gripper_qpos”] # 状态键名 # 模型配置如前所述 model: action_horizon: 16 ... # 训练配置 train: batch_size: 32 num_epochs: 1000 learning_rate: 1.0e-4 optimizer: “adamw” ... eval_every: 50 # 每50个epoch评估一次 save_every: 100 # 每100个epoch保存一次检查点 # 日志与输出 logging: project: “so101-act-pickplace” # 用于WandB等日志平台的项目名 name: “exp1” # 本次实验的名称5.2 启动训练与监控使用LeRobot提供的训练脚本启动训练python scripts/train.py \ --config-name so101_pickplace \ --config-dir lerobot/configs/act--config-name指定配置文件名不含.yaml--config-dir指定配置文件夹。训练开始后你需要密切关注以下几个方面损失曲线ACT的损失通常包含几部分动作重建损失预测动作与真实动作的均方误差MSE、KL散度损失约束潜在变量z的分布接近标准正态分布。总损失应该总体呈下降趋势。如果KL散度损失过早降至0说明模型可能忽略了潜在变量发生了“后验坍塌”可以尝试降低KL损失的权重系数beta。验证成功率更重要的指标是在仿真环境中的任务成功率。LeRobot会在评估周期内用训练好的策略在仿真环境中运行多个回合计算成功完成任务的比率。这个指标比损失函数更能反映策略的真实性能。硬件资源训练ACT模型尤其是处理图像输入时对GPU显存要求较高。如果遇到CUDA out of memory错误可以尝试减小batch_size、使用更小的图像分辨率、或者使用梯度累积技术。实操心得训练初期损失可能波动很大。除了调整学习率一个有效的技巧是课程学习Curriculum Learning。例如可以先在简单任务如仅移动末端不涉及抓取或噪声较小的数据上预训练模型然后再在复杂任务上微调。另一个关键点是数据标准化Normalization。确保输入模型的观测如图像像素值和动作都进行了适当的标准化如缩放到[-1, 1]区间这能极大提升训练的稳定性和速度。LeRobot的数据加载器通常会自动处理这一点但你需要确认它处理的方式是否符合你的数据分布。6. 评估、调试与真机部署模型训练完成后工作只完成了一半。评估其真实性能并部署到真机SO-101上才是最终的考验。6.1 在仿真环境中系统性评估不要只看最终的平均成功率要进行细致的分析可视化轨迹在仿真中运行策略并录制视频。观察机械臂的运动是否平滑、自然是否存在不必要的抖动或卡顿抓取动作是否精准鲁棒性测试稍微改变任务的初始条件比如方块的位置偏移几厘米目标区域移动一下。策略还能成功吗这测试了模型的泛化能力。消融实验如果你修改了模型结构如改变了action_horizon与其他配置的模型进行对比实验用数据说明你的修改为何有效。LeRobot通常提供评估脚本例如python scripts/eval.py \ policy.checkpoint_path“outputs/your_experiment/checkpoints/latest.pt” \ env.name“robosuite/PickPlace-v0” \ eval.n_episodes20 # 评估20个回合6.2 常见问题与调试策略训练过程很少一帆风顺以下是一些典型问题及排查思路问题1策略完全不动或者输出接近零的常数动作。可能原因A数据动作量纲问题。检查你的数据集中动作值的范围。如果原始动作是很大的数值如关节位置弧度值而模型输出层使用了tanh激活函数输出范围[-1,1]那么模型可能永远学不会。解决方案在数据预处理时对动作进行标准化。可能原因BKL散度权重beta过大。在CVAE中过大的beta会迫使潜在变量z的分布严格接近标准正态分布可能压垮了重建损失导致模型无法从z中解码出有意义的动作。解决方案尝试使用“KL退火KL Annealing”策略在训练初期让beta从0逐渐增加到一个固定值。可能原因C观测信息不足。模型仅凭图像可能难以精确推断物体的深度和绝对位置。解决方案在观测中加入机器人的本体感知状态如关节角度、末端执行器位姿通过正向运动学计算得到。问题2策略动作抖动剧烈不流畅。可能原因A动作频率不匹配。训练数据中动作的采样频率如20Hz与部署时策略的执行频率如50Hz不一致。解决方案确保训练和部署时使用相同的控制频率。或者在数据采集时以更高的频率采集然后在训练前进行下采样。可能原因Baction_horizon太小。重规划过于频繁导致动作缺乏连贯性。解决方案适当增大action_horizon。可能原因C没有对输出动作进行平滑滤波。解决方案在策略输出和执行器之间加入一个低通滤波器如指数移动平均滤波器平滑高频噪声。问题3仿真表现良好但真机表现差。可能原因“仿真到真实Sim2Real”的鸿沟。仿真中的动力学摩擦、阻尼、惯性、传感器相机噪声、色彩、畸变与真实世界存在差异。解决方案域随机化Domain Randomization在仿真训练时随机化纹理、光照、物体质量、摩擦系数等参数让模型见识更多的“可能性”从而提高泛化能力。在真机数据上微调在真机上采集少量成功数据对仿真训练好的模型进行微调。系统辨识校准仿真模型的物理参数使其更接近真机。6.3 部署到真实SO-101机器人这是最后也是最激动人心的一步。你需要搭建一个“桥梁”让LeRobot训练出的策略能够控制真实的硬件。步骤一建立通信SO-101机器人通常通过ROS进行控制。你需要一个运行ROS的机器可以是机器人自带的工控机也可以是通过网络连接的PC。在ROS机器上启动SO-101的驱动节点它会发布关节状态话题如/joint_states并订阅关节位置/速度控制话题如/joint_trajectory。在你的策略运行机器上可能和ROS机器是同一台需要运行一个策略服务器。这个服务器的职责是订阅ROS的/joint_states话题获取当前机器人状态。将状态关节角、可能还有来自真实相机的图像格式化为LeRobot策略所需的观测格式。调用加载好的ACT模型输入观测得到预测的动作序列块。将动作块中的第一个或前几个动作转换为ROS控制消息如trajectory_msgs/JointTrajectory。发布控制消息到ROS的对应控制话题。步骤二处理感知仿真中我们可能使用了完美的RGB图像。在真机上你需要连接真实的相机如USB摄像头或RGB-D相机如Intel Realsense。使用cv_bridge将ROS的图像话题sensor_msgs/Image转换为OpenCV格式。对图像进行预处理裁剪、缩放、归一化使其与训练时使用的图像格式一致。这一点至关重要如果预处理不一致策略的性能会严重下降。步骤三控制循环与安全性频率同步确保你的策略服务器运行在一个固定的频率如20Hz并与机器人的控制频率匹配。安全性这是真机实验的生命线。务必加入关节限位检查在发送指令前检查指令是否超出机器人的物理限位。碰撞检测如果机器人有内置的碰撞检测确保启用。也可以基于关节电流或外部传感器进行简单判断。急停开关手边必须有物理急停按钮。仿真先行任何新的策略或参数务必在仿真中充分测试后再上真机。一个简化的策略服务器伪代码框架如下import rospy from sensor_msgs.msg import Image, JointState from trajectory_msgs.msg import JointTrajectory, JointTrajectoryPoint import torch from lerobot.models.act.act import ACT class ACTPolicyServer: def __init__(self): # 加载训练好的模型 self.policy ACT.from_pretrained(“path/to/checkpoint”) self.policy.eval() # ROS初始化 rospy.init_node(‘act_policy_server’) # 订阅者 self.joint_state_sub rospy.Subscriber(‘/joint_states’, JointState, self.state_callback) self.image_sub rospy.Subscriber(‘/camera/rgb/image_raw’, Image, self.image_callback) # 发布者 self.cmd_pub rospy.Publisher(‘/joint_trajectory’, JointTrajectory, queue_size10) # 状态缓存 self.current_joint_pos None self.current_image None self.rate rospy.Rate(20) # 20Hz def state_callback(self, msg): # 更新关节状态 self.current_joint_pos list(msg.position) # 假设顺序匹配 def image_callback(self, msg): # 转换并预处理图像 cv_image cv_bridge.imgmsg_to_cv2(msg, “bgr8”) self.current_image preprocess(cv_image) # 缩放、归一化等 def run(self): while not rospy.is_shutdown(): if self.current_joint_pos is not None and self.current_image is not None: # 1. 组装观测 observation { “image”: self.current_image, “joint_pos”: self.current_joint_pos, } # 2. 模型推理 with torch.no_grad(): action self.policy.predict_action(observation) # 假设有这个方法 # 3. 安全检查 (例如限位检查) if not self.check_safety(action): rospy.logerr(“Unsafe action detected! Stopping.”) self.send_stop_command() break # 4. 转换为ROS消息并发布 traj_msg self.action_to_trajectory(action) self.cmd_pub.publish(traj_msg) self.rate.sleep()这个过程涉及大量的工程细节包括消息同步、坐标系转换、错误处理等需要耐心调试。从在仿真中训练一个ACT策略到让真实的SO-101机械臂流畅地完成任务是一条充满挑战但回报丰厚的路径。它要求你不仅理解算法还要熟悉机器人软件栈ROS、硬件接口以及系统集成中的各种“坑”。希望这篇详尽的指南能为你提供一张清晰的地图。记住每一次失败都是通往成功的必经之路耐心调试大胆尝试你一定能让这台机械臂在你的指令下灵活舞动。