Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

下面我直接把你给出的 11.1.x 扩写成教材正文风格。整体假定读者已经看过前面关于 BC、VLA、仿真平台、ROS 等章节,这里主要做“落地项目手把手”,避免重复理论。


11.1 入门项目建议

本节的目标,是让读者在不依赖真实机器人硬件 的前提下,走完几条完整的实践路线: 从最基础的行为克隆(BC),到一个玩具级 VLA,再到利用开源数据训练多任务策略,最终把模型部署在仿真机器人上完成抓取 / 放置任务。

可以把这几小节理解为四个渐进式“关卡”:

  1. 会用仿真 + BC 让机器人“照着做”
  2. 会用简单 VLA 让机器人听懂一句话再行动
  3. 会在开源多任务数据集上训练一个小“通用策略”
  4. 会把模型真正接到仿真机械臂上跑在线控制闭环

11.1.1 在仿真环境中实现简单的 BC 控制策略

这一小节的目标,是让读者完成第一条最基础的 pipeline:

仿真环境搭建 → 采集示范轨迹 → 训练行为克隆策略 → 部署回仿真验证

11.1.1.1 任务场景

为了把复杂度压到最低,建议选用单臂 + 桌面 + 单物体 的简单抓取任务,例如:

  • 机器人:Franka Panda、UR5 或仿真平台自带机械臂
  • 环境:一张桌子,桌上放一个小方块或圆柱体
  • 任务:从固定初始姿态出发,抓起桌上的物块并抬到空中

仿真引擎可以选择:

  • MuJoCo:现代机器人强化学习中最常用之一,支持 Franka、UR 系列等模型,仿真稳定,许多 benchmark 都基于它。(科学直通车)
  • Isaac Gym / Isaac Lab:适合大规模 RL,但对初学者略有上手成本。
  • Gazebo / Ignition + ROS:更贴近真实机器人系统,和 ROS 集成好,但仿真效率偏低。(GitHub)

为了让读者感到“看得见的进步”,可以建议如下约束:

  • 只使用单视角 RGB 图像 + 机械臂关节角作为输入
  • 只做二维平面内抓取(物体固定在桌上某个区域)
  • 控制指令采用关节增量(Δq)或末端位姿增量(Δpose)

图片占位建议:

【图 11-1】典型机械臂仿真环境示意图:Franka Panda 机械臂固定在桌旁,桌面上摆放单个方块,画出机器人基座坐标系与摄像头视场。

11.1.1.2 数据采集

行为克隆的核心是:有一批“好示范”,模型只要拟合它们即可 。在仿真环境中采集示范相对轻松,主要方式有两种:

  1. 遥操作(Teleoperation)方式
    • 用键盘 / 鼠标 / 手柄 或 VR 控制机械臂末端移动与夹爪开闭。
    • 在每一个控制周期记录:
      • 当前图像 \((I_t)\)(RGB 或 RGB-D)
      • 机器人状态 \((s_t)\):关节角、关节速度、夹爪状态等
      • 人类给出的动作 \((a_t)\):比如末端速度或关节角增量
    • 数据存储成轨迹:\(((I_0, s_0, a_0), \dots, (I_T, s_T, a_T))\)
  2. 脚本 / 规划器生成示范
    • 对于规则简单的任务,可以写定程序化轨迹:例如从上方垂直下降、夹紧、上抬。
    • 也可以利用轨迹规划器生成碰撞安全轨迹,然后把规划出的动作当作专家示范(RLBench 就是用规划器自动生成无限示范的代表性系统)。(arXiv)

记录格式 建议:

  • 采用统一的结构体或字典,例如:
{
    "image": <H x W x 3>,
    "q": <n_dof>,        # 关节角
    "qdot": <n_dof>,     # 关节速度(可选)
    "gripper": <1>,      # 夹爪开合
    "action": <m>,       # 控制命令
    "timestep": <int>
}
  • 保存为一系列 episode_xxx.h5npz 文件,方便后续 batch 加载和随机打乱。

小建议:

  • 尽量采集几十到上百条成功轨迹;
  • 在仿真中随机扰动若干初始条件(方块位置、小幅度初始姿态变化),为后续泛化留一点空间;
  • 记录任务是否成功,方便训练前筛掉明显失败示范。

11.1.1.3 模型训练

这一部分可以引导读者实现一个最朴素的 BC 模型

  1. 输入设计
    • 图像经一个轻量 CNN(如 ResNet18)或 ViT Tiny 提取特征向量 \(f_{\text{img}}\)。
    • 机器人的状态向量 \((s_t)\)(关节角、夹爪状态)经一个小型 MLP 转为嵌入 \(f_{\text{state}}\)。
    • 拼接两者:\(z_t = [f_{\text{img}}, f_{\text{state}}]\)。
  2. 输出设计
    • 若动作是连续值(如关节角增量 \(\Delta q\),末端速度),则使用回归头:多层感知机输出实数向量。
    • 若动作预先离散化(例如八个方向步进 + 抓/放),则使用分类头(Softmax 输出每个离散动作的概率)。
  3. 损失函数
    • 连续动作:使用均方误差(MSE)损失 \(\mathcal{L} = |a_t - \hat{a}_t|^2\)。
    • 离散动作:使用交叉熵损失。
  4. 训练流程
    • 将所有轨迹打散成样本对 \(\text{obs}_t, a_t\)。
    • 小批量训练,使用 Adam 优化器;
    • 对图像进行基础数据增强(随机裁剪、轻微颜色抖动),增强鲁棒性。

可以明确强调:BC 本质上就是监督学习,不需要奖励函数和环境交互,这一点和前面 RL 章节做一个呼应。

图片占位建议:

【图 11-2】简单 BC 网络结构示意图:左侧为图像输入经 CNN,右侧为关节状态输入经 MLP,两者拼接后输出动作向量。

11.1.1.4 验证效果

训练完模型后,需要让读者真正“看到机器人动起来”,验证步骤:

  1. 离线评估
    • 在验证集轨迹上计算:
      • 连续动作误差(MSE),
      • 或动作分类准确率。
    • 可视化几条轨迹:比较专家动作与模型动作的曲线差异。
  2. 在线回放(仿真控制)
    • 在仿真中重置环境:机器人回到初始位置,物体放在预定位置;
    • 在每一个控制周期:
      • 获取当前图像和机器人状态;
      • 前向传播得到模型动作;
      • 将动作发送给仿真控制器。
    • 重复直到终止条件(抓取成功、时间超时、仿真出界)。
  3. 指标与现象
    • 任务成功率:例如在 50 次初始化中成功抓起并抬起物体的比例;
    • 执行轨迹是否平滑、是否有明显震荡或发抖;
    • 模型错误典型场景:对物体位置略有偏差、抓取偏边缘导致滑落等。

可以引导读者思考:

  • 模型失败时,是否进入了训练数据没覆盖到的状态分布(呼应前文 BC 的分布偏移问题);
  • 若要提高表现,可以在后续章节引入 DAgger 或强化学习微调。

图片占位建议:

【图 11-3】仿真中 BC 策略成功抓取物体的动作序列截图(接近 → 抓取 → 提起),配合时间轴标注。


11.1.2 复现一个小规模“视觉 + 语言 + 动作”的玩具 VLA

在学生已经完成纯 BC 项目后,可以引导他们搭建一个最小可用的 VLA 原型——它不追求 SOTA,只追求“能跑、能看、能听话”

11.1.2.1 场景设定

场景依然建议控制在非常简单的桌面操作环境。例如:

  • 桌上有多种颜色或不同形状的积木:红色方块、蓝色圆柱、绿色长条等;
  • 摄像头固定俯视桌面;
  • 机械臂可以抓取并移动物体到左/右侧区域;
  • 自然语言指令类似:
    • “把红色方块放到右边”;
    • “把蓝色圆柱移到左上角”;
    • “把绿色积木抓起来”。

这样一来,语言主要承担两个作用:

  1. 指定目标物体(颜色 + 类别);
  2. 指定目标区域(左/右/上/下)。

图片占位建议:

【图 11-4】玩具 VLA 场景示意:桌面多个彩色积木、机械臂与摄像头视角,示意不同目标区域位置。

11.1.2.2 数据生成

这里鼓励使用完全程序化的合成数据,方便读者生成足够多样本:

  1. 程序化场景采样
    • 随机采样:
      • 积木的颜色 / 形状 / 尺寸;
      • 每个积木在桌面上的位置;
      • 要执行的任务类型(抓取 / 放置位置)。
  2. 动作自动生成
    • 使用简单几何规划:
      • 根据物体 2D 坐标,设定机械臂末端在上方某个高度对齐;
      • 垂直下降、闭合夹爪、抬起;
      • 若需要放置位置,则移动到目标区中心、下降、松爪。
    • 所有这些动作都可以由脚本生成,从而形成专家轨迹。
  3. 语言指令生成
    • 采用模板:
      • “把 {颜色} {形状} 放到 {区域}”;
      • “抓起 {颜色} 的积木”;
    • 对同一条轨迹可以生成多条同义指令,通过同义词 / 词序变化等扩充训练集;
    • 若想更真实,可在模板基础上用语言模型改写,形成更自然的多样指令表达。(OpenCV学习)
  4. 同步与对齐
    • 对每一条轨迹,记录:
      • 起始时刻的场景图像 \((I_0)\);
      • 对应语言指令文本 \(\displaystyle L\);
      • 动作序列 \(a_0, \dots, a_T\)。
    • 对于玩具级 VLA,可以简化成“指令 + 初始图像 → 整条动作序列”的离线映射,或“指令 + 当前图像 → 下一步动作”的在线决策。

11.1.2.3 模型搭建

这里的目标是一个最小 VLA,可选架构之一:

  1. 视觉编码
    • 使用一个预训练的 ResNet18 / ViT-Tiny 作为 backbone(在第 3 章已有详细介绍,在此直接引用即可);
    • 输出一个固定维度向量 \(f_{\text{img}}\)。
  2. 语言编码
    • 使用轻量 Transformer 或直接调用小型预训练文本编码器,如 MiniLM、DistilBERT 等(读者可以通过开源框架获取预训练权重)。(科学直通车)
    • 将指令 \(\displaystyle L\) 转换为子词 token 序列,经嵌入和 Transformer 层,提取 [CLS] 或平均池化得到语言向量 \(f_{\text{lang}}\)。
  3. 多模态融合
    • 最简单方法:直接拼接 \(z = [f_{\text{img}}, f_{\text{lang}}]\),输入 MLP 输出动作。
    • 稍微进阶一点,可以用一个 2 层的 Transformer,将图像特征视为一个 token、语言序列为其余 token,通过自注意力实现简单的跨模态交互。
  4. 动作解码
    • vs 11.1.1 类似,可以输出:
      • 单步动作(Δpose 或 Δq);
      • 或固定长度的动作 token 序列。
    • 为了简单起见,建议初学项目仍采用单步决策,在仿真中循环调用模型。

图片占位建议:

【图 11-5】玩具 VLA 模型结构示意:图像编码器与语言编码器分别输出特征,经过拼接与 MLP 输出动作。

11.1.2.4 训练评估

训练过程本质仍是行为克隆,只是输入多了一路语言:

  1. 训练
    • Loss 仍是动作监督损失(MSE 或交叉熵);
    • 在 batch 中混合不同指令与不同场景;
    • 适当使用 dropout 与数据增广防止过拟合。
  2. 评估方式
    • 离线正确率:在验证集上,给定图像 + 指令,统计模型选出的目标物体是否正确(例如是否接近正确颜色与位置)。
    • 在线执行成功率:在仿真中随机生成新场景和新指令,统计任务成功率。
    • 指令泛化测试
      • 在训练中只用模板 A;
      • 在测试中使用同一含义,但完全未出现过的自然表达 B(例如“请把那个红色的小方块挪到右边去”),检验语言理解泛化。
  3. 现象讨论
    • 指令缺失或模糊时(如“把它拿走”),模型会如何表现?
    • 如果场景中不存在符合指令的物体(如没有红色积木),模型是否会输出无意义动作?
    • 这为后续章节中“安全性”和“语言约束”埋下伏笔。

11.1.3 使用开源数据集训练一个简单多任务策略

在读者掌握自建数据和玩具 VLA 之后,可以把视角扩展到真正的开源机器人数据集,体会多任务学习和数据工程的味道。

11.1.3.1 选择数据

目前机器人社区已有多种开放数据集可以用于多任务策略学习,比如:

  • RLBench:CoppeliaSim 上构建的多任务操作环境,包含 100 种以上任务(开抽屉、开门、插销、放物体等),每个任务有大量示教轨迹,支持视觉 + 动作学习。(arXiv)
  • RoboNet:Berkeley 等机构联合的数据集,包含多个不同机器人平台的桌面操作数据,主要任务是物体迁移(pushing 或 grasping-and-placing),提供 1500 万帧左右的视频及状态信息。(bair.berkeley.edu)

入门阶段可以建议:

  • 从 RLBench 选取 3–5 个简单任务(如 “reach target”、“pick & place”、“open drawer”);
  • 或从 RoboNet 切出一个子集,只保留若干机器人和物体类别。

预处理步骤包括:

  • 统一图像尺寸和通道顺序;
  • 统一状态与动作向量的格式;
  • 明确每条轨迹对应的任务 id(或任务名称),为后续多任务训练提供条件标签。

11.1.3.2 模型架构

这里不强求 VLA,一种基础多任务策略可以只是视觉 + 状态 → 动作,并增加任务条件 输入,形成一个小型 generalist policy:

  1. 视觉编码器

    • 重用上一小节中的 CNN / ViT;
    • 若数据量充足,可考虑在数据集上做自监督预训练(例如 MAE 或对比学习),再用作下游策略 backbone。(科学直通车)
  2. 任务编码器

    • 将任务 id 映射为 one-hot 或 learnable embedding;

    • 任务嵌入向量 \(f_{\text{task}}\) 与视觉特征、机器人状态特征一起拼接成总特征:

      \[ z_t = [f_{\text{img}}, f_{\text{state}}, f_{\text{task}}] \]

  3. 策略头

    • MLP 输出当前动作;
    • 也可采用小型 Transformer 编码短时间窗口的历史观测与动作,实现时序建模。

图片占位建议:

【图 11-6】简单多任务策略网络结构示意:视觉特征、状态特征与任务嵌入拼接后通过 MLP 输出动作。

11.1.3.3 训练过程

多任务训练的难点在于数据不平衡与任务干扰,本节可以指导读者做几个基本设计:

  1. 采样策略
    • 按任务均匀采样:在每个 batch 内保证多任务数据均衡,避免大量数据的任务“淹没”长尾任务;
    • 或使用基于任务难度的加权采样(视为进阶内容)。
  2. 训练目标
    • 仍然是标准 BC 损失:\(\mathcal{L} = \sum_t |a_t - \hat{a}_t|^2\) 或交叉熵;
    • 可以在损失中增加任务正则项,例如鼓励同一任务的行动分布更紧凑(非必需)。
  3. 日志与监控
    • 为每个任务单独记录训练/验证误差与离线评估指标;
    • 如果某个任务一直学不好,有可能是任务数据过少或任务本身过难,可在报告中引导学生分析原因。
  4. 工程注意事项
    • 数据集可能较大,需要注意 IO 和缓存(例如提前将图像转为压缩格式,使用多进程 data loader);
    • 必要时对长轨迹进行截断或下采样,以控制训练时间。

11.1.3.4 测试泛化

多任务策略真正有趣的地方在于泛化能力测试,可以设计几类实验:

  1. 任务内泛化
    • 在与训练任务相同的任务 id 上,但使用新的初始姿态、物体位置、光照变化等,测试成功率;
    • 观察模型是否相较单任务策略更稳健。
  2. 任务间迁移
    • 在 RLBench 等系统中,选择一两个未参与训练 的任务,直接使用同一模型(或者在少量示范上做快速微调),比较其学习效率与单任务基线。(GitHub)
  3. 分布外场景
    • 对视觉输入做强扰动(不同桌布纹理、不同背景颜色);
    • 对任务组合做变化(例如在桌子另一侧重复相同任务),观察策略是否仍能执行关键步骤。

读者通过这一节,会第一次感受到:

“原来我可以用同一个模型,控制不同任务甚至不同机器人,哪怕很粗糙,也算朝‘通用策略’迈了一小步。”


11.1.4 将模型部署在仿真机器人上完成抓取 / 放置任务

前面三个项目大多停留在“训练脚本 + 离线评估”层面,本节的目标是:让模型真正以一个在线控制模块的身份,接入仿真机器人系统 。这是走向真实机器人实验的前置练习。

11.1.4.1 部署准备

部署的关键,是把模型包装成一个可在实时循环中调用的服务,与仿真平台对接。典型组合是:

  • 仿真平台:Gazebo / Ignition / Isaac Sim / MuJoCo + 外部控制程序;
  • 中间件:ROS / ROS2,负责图像、状态与控制命令的话题传输;(科学直通车)

准备步骤:

  1. 选择仿真机器人模型
    • 如 Franka Panda、UR5 等已有成熟 URDF + 控制接口的机械臂模型;许多开源项目和基准都基于这些平台。(GitHub)
  2. 定义模型接口
    • 输入:
      • 相机图像(订阅 /camera/rgb 或类似话题);
      • 关节状态(订阅 /joint_states)。
    • 输出:
      • 关节目标位置或关节速度(发布到 /arm_controller/command 之类的话题);
      • 或末端位姿目标,由下层控制器完成 IK 和轨迹跟踪。
  3. 模型打包
    • 将训练好的 PyTorch / JAX 模型保存为 checkpoint;
    • 部署脚本在 ROS 节点中加载模型,并在回调中执行前向计算。
    • 为满足实时性,可考虑使用 ONNX/TensorRT 等推理引擎进行加速(在 10 章已有详细介绍,这里只作实践提醒)。

图片占位建议:

【图 11-7】模型部署架构示意:仿真器 → ROS 话题 → VLA / BC 模型节点 → 控制器 → 仿真机械臂。

11.1.4.2 在线控制

在线控制循环通常如下:

  1. 感知
    • 以固定频率(如 5–10 Hz)从相机和关节传感读取当前状态;
    • 做必要预处理:图像 resize、归一化;状态向量拼接。
  2. 决策
    • 将当前观测(以及语言指令/任务 id 等条件)输入模型;
    • 得到动作向量(Δpose 或 Δq);
    • 做简单约束:裁剪到关节速度 / 末端位移限制。
  3. 执行
    • 将动作转为控制指令发送给仿真控制器:
      • 若用关节空间位置控制:当前关节角 + Δq 得到目标位置。
      • 若用末端速度控制:发送速度指令,由 robot controller 积分执行。
  4. 循环与终止
    • 直到检测到抓取成功 / 放置完成 / 时间超时;
    • 若失败,可回到初始状态重新尝试,计算成功率。

这里可以强调高层策略与低层控制的分工(与第 6 章呼应):VLA/BC 模型只需输出“想要往哪走”,真正的轨迹细化与电机控制由底层完成。

11.1.4.3 任务执行

最后,可以要求读者把这一套部署在一个具体任务上,比如:

“在仿真中,让机械臂根据视觉输入自动抓取桌上的物体,并将其放置到指定区域。”

建议设置的观测与评价包括:

  1. 成功率统计
    • 多次随机初始化物体位置,记录完成抓取 + 放置任务的成功率;
    • 可与手工脚本或规划器生成的基线策略进行比较。
  2. 行为可视化
    • 录制仿真视频,选取几条成功与失败案例;
    • 在视频上叠加当前模型预测的目标点、动作向量等信息,帮助分析行为逻辑。
  3. 故障模式分析
    • 例如:
      • 张开 / 闭合夹爪时机不对;
      • 接近物体路径绕来绕去,说明策略不稳定;
      • 抓取过于激进导致与桌面碰撞。
    • 这些现象为后续章节关于“安全性、鲁棒性与 RL 微调”提供直观动机。

图片占位建议:

【图 11-8】仿真抓取 / 放置任务执行结果对比图:上排为成功案例序列,下排为失败案例序列,并在图中标注关键失败原因(如偏移过大、夹爪没对准)。


综合来看,本节四个项目像是一个小型“具身智能实验通关手册”: 从最基础的单任务 BC,到加上语言组成玩具 VLA,再到利用开源多任务数据做 generalist policy,最后真正接入仿真系统跑在线闭环。 读者只要按顺序完成其中任意两三个,就已经从“纸面理解”跨到了“能把抽象 VLA 概念落成可运行系统”的阶段。