具身操作 Benchmark 深度教程长文版 · 一章一页 · CALVIN · D50a

总览 / CALVIN · D50a

CALVIN:语言长时序的链式成功率协议

语言条件连续操作:数据集、PyBullet 仿真、MCIL 基线与 LH-MTLC 评估全文。

接近原文长文版仅排版加工 · 未删减压缩CALVIN · D50a

What this is

CALVIN 是一个面向语言条件机器人操作策略的仿真基准和训练框架,目标是评估机器人是否能根据自然语言,在视觉/本体感知输入下连续完成多个长时序操作任务。项目由数据集、PyBullet 仿真环境、MCIL 基线策略以及标准化评估脚本组成。

技术栈主要是 Python、PyTorch 1.13.1、PyTorch Lightning、Hydra、Gym 和 PyBullet;环境部分通过 Git submodule 引入 mees/calvin_env


1. 任务集:从单一操作到五步长时序组合

1.1 基础任务类型

任务定义位于 new_playtable_tasks.yaml,目前可以归纳为:

类别示例
旋转rotate_red_block_left/right
推动push_blue_block_left/right
开关门/抽屉move_slider_left/rightopen_drawerclose_drawer
抬升将红、蓝、粉色方块从桌面、滑轨或抽屉中抬起
放置place_in_sliderplace_in_drawer
堆叠stack_blockunstack_block
灯光控制turn_on_lightbulbturn_off_led
推入抽屉push_into_drawer

这些任务不是依靠人工标签直接判断,而是由 Tasks 类根据动作前后的环境状态变化进行判定。例如:

  • 物体位移是否超过阈值;
  • 物体是否与机器人或目标表面发生正确接触;
  • 抽屉/滑轨的关节状态是否发生指定方向的变化;
  • 灯的逻辑状态是否从 0 变为 1;
  • 物体是否完成堆叠且速度低于阈值。

具体实现见 calvin_env/envs/tasks.py

1.2 数据集与环境划分

每个环境包含约 6 小时的遥操作数据,数据集提供四类环境组合:

  • D -> D:在 D 环境训练,在 D 环境测试;
  • ABC -> D:在 A、B、C 环境训练,在 D 环境测试;
  • ABCD -> D:在 A、B、C、D 环境训练,在 D 环境测试;
  • debug:约 1.3 GB 的小型调试数据集。

数据下载和规模说明位于 dataset/README.md

Split数据规模
D → D166 GB
ABC → D517 GB
ABCD → D656 GB
Debug1.3 GB

因此,CALVIN 不只是测“是否会做某个动作”,还测试:

  1. 能否跨环境泛化;
  2. 能否理解语言指令;
  3. 能否在完成一个任务后继续完成下一个任务;
  4. 能否处理任务之间的状态依赖。

1.3 输入与动作空间

环境支持的主要观测包括:

  • 静态 RGB 相机:200 × 200 × 3
  • 夹爪 RGB 相机:84 × 84 × 3
  • 静态和夹爪深度图;
  • 视觉触觉图像;
  • 机器人本体状态,包括 TCP 位姿、夹爪宽度、7 个关节位置和夹爪动作;
  • 语言指令及预计算语言 embedding。

动作空间包括:

  • 绝对笛卡尔位姿:位置 3 维 + 欧拉角 3 维 + 夹爪 1 维;
  • 相对笛卡尔位移:同样为 7 维;
  • 关节动作:7 个关节位置 + 夹爪动作。

数据结构和动作缩放方式见 dataset/README.md


2. 引擎与本体:PyBullet + PlayTable + 7-DoF 机械臂

2.1 仿真引擎

CALVIN 使用 PyBullet 作为物理仿真和渲染基础。核心环境类是 PlayTableSimEnv

它负责:

  • 初始化 PyBullet physics client;
  • 加载机器人和场景;
  • 执行机器人动作;
  • 获取 RGB、Depth、状态和场景信息;
  • 支持 GUI、DIRECT 和 EGL 渲染模式;
  • 提供 Gym 风格的 reset()step()render() 接口。

环境的执行链路大致是:

语言指令 + 当前观测
        ↓
策略模型
        ↓
连续机器人动作
        ↓
PyBullet 仿真
        ↓
新的相机/本体观测
        ↓
任务状态判定

2.2 EGL GPU 渲染

项目特别使用了 EGL 渲染,把 PyBullet 的渲染从 CPU 转移到 GPU:

elif self.use_egl:
    cid = self.p.connect(p.DIRECT, options=options)
    plugin = p.loadPlugin(..., "_eglRendererPlugin")

这带来两个效果:

  1. 可以在训练过程中并行执行 rollout;
  2. 在多 GPU 或集群环境下,渲染速度更高。

项目还处理了 CUDA GPU ID 与 EGL GPU ID 可能不一致的问题。需要注意,EGL 渲染得到的纹理与 CPU 渲染可能略有差异,所以用预训练模型复现实验时,渲染后端最好保持一致。

2.3 机器人本体与传感器

CALVIN 使用桌面操作场景中的 7 自由度机械臂和夹爪作为统一 embodiment。其核心观测是:

TCP position       3
TCP orientation    3
gripper width      1
arm joint states   7
gripper action     1

此外还支持:

  • 静态相机;
  • 夹爪相机;
  • 深度相机;
  • Tacto 视觉触觉传感器;
  • VR 遥操作数据采集。

安装脚本会安装 calvin_env 以及其中的 tacto 子项目:

cd calvin_env/tacto
pip install -e .
cd ..
pip install -e .

install.sh


3. 评估指标与分数基线

3.1 主要指标:长时序链式成功率

CALVIN 的核心评估模式是 Long-horizon Multi-task Language Control,LH-MTLC

每个评估 episode:

  1. 将机器人和场景重置到指定初始状态;
  2. 给策略连续 5 条语言指令;
  3. 当前任务成功后才进入下一条指令;
  4. 一旦某个子任务失败,整个 sequence 停止。

评估代码中的关键设置是:

EP_LEN = 360
NUM_SEQUENCES = 1000

evaluate_policy.py

3.2 五个核心分数

代码会统计:

  • SR_1:至少完成 1 个子任务的比例;
  • SR_2:连续完成至少 2 个子任务的比例;
  • SR_3:连续完成至少 3 个子任务的比例;
  • SR_4:连续完成至少 4 个子任务的比例;
  • SR_5:连续完成全部 5 个子任务的比例;
  • Average successful sequence length:平均连续成功任务数。

实现见 count_success()print_and_save()

它不是简单的单任务平均成功率,而是更强调错误累积和长时序执行能力。例如,一个策略如果单任务成功率很高,但第二步经常失败,那么 SR_5 仍然会很低。

3.3 单任务指标

项目还提供 MTLC,即不要求连续完成长链,而是逐个任务评估:

python evaluation/evaluate_policy_singlestep.py \
  --dataset_path <DATASET> \
  --train_folder <TRAIN_FOLDER>

该模式会输出类似:

task_name: successful / total
SR: xx.x%

实现见 evaluate_policy_singlestep.py

3.4 基线模型:MCIL

仓库提供的主要基线是 MCIL,模型定义在 mcil.py

其结构包含:

  • 感知编码器 perceptual_encoder
  • 语言目标编码器 language_goal
  • 视觉目标编码器 visual_goal
  • plan proposal;
  • plan recognition;
  • action decoder;
  • KL loss;
  • 周期性重新规划。

默认配置见 conf/model/default.yaml,默认:

_target_: calvin_agent.models.mcil.MCIL
kl_beta: ${loss.kl_beta}
replan_freq: 30

也就是说,策略不是每一步都从头规划,而是默认每 30 个控制 step 重新规划一次 latent plan。

3.5 分数基线的边界

这里需要特别区分:

  • 仓库提供了 MCIL 基线代码和预训练权重下载入口
  • 仓库 README 提供了外部 CALVIN leaderboard 链接;
  • 但在当前仓库代码和 README 中,并没有完整内嵌一张带有所有 split、传感器配置和具体数值的 baseline score 表。

因此,比较严谨的说法是:

CALVIN 的官方比较单位是 D→DABC→DABCD→D 等 split 下的 SR_1...SR_5 和平均成功链长度;MCIL 是仓库内置基线,具体历史分数应以论文和官方 leaderboard 为准,而不应仅从当前仓库代码推断。

仓库同时列出了一批超过 MCIL baseline 的方法,例如 HULC/HULC2、RoboFlamingo、3D Diffuser Actor、MDT、FLOWER 等。


4. 对 harness 的支持与优化

如果这里的 “harness” 指的是评测 harness / benchmark runner,CALVIN 做的优化主要不是增加一个叫 harness 的独立模块,而是把评测流程标准化、可插拔化和工程化。

4.1 统一模型接口

评测脚本定义了 CustomModel 接口,外部模型只需要实现:

class CustomModel(CalvinBaseModel):
    def __init__(self):
        ...

    def reset(self):
        ...

    def step(self, obs, goal):
        ...

评估器负责:

  • 创建环境;
  • 设置初始状态;
  • 加载任务 oracle;
  • 提供语言 goal;
  • 循环调用 model.step()
  • 判断任务是否成功;
  • 汇总长时序指标。

这样,外部模型不需要重写 CALVIN 的环境初始化和评估逻辑,只需要适配 reset/step

4.2 评估模型与环境解耦

get_default_model_and_env() 会根据训练目录下保存的 Hydra 配置恢复:

  • 模型结构;
  • 数据集配置;
  • 语言 embedding 路径;
  • action bounds;
  • 环境配置;
  • checkpoint。

因此评估时不依赖当前命令行重新手工拼装模型参数,减少了训练配置和评估配置不一致的问题。

同时,评估会刻意禁用 shared-memory dataset loader:

# we don't want to use shm dataset for evaluation
datasets_cfg = hydra.compose("vision_lang.yaml", ...)

这说明项目把训练阶段的数据加载优化和评估阶段的可复现性分开处理。

4.3 确定性的初始状态生成

评估不是直接随机 reset,而是由 get_env_state_for_initial_condition() 根据 initial condition 构造机器人和场景状态。

对于方块位置,还通过基于初始条件的 hash 设置随机种子,使相同 initial condition 得到稳定的方块排列。这有助于:

  • 减少每次评测的随机差异;
  • 方便复现实验;
  • 避免模型因为某个随机初始摆放而获得或失去优势。

4.4 任务 oracle 与策略解耦

任务成功由 Tasks.get_task_info_for_set() 判断,而不是由策略自己返回 reward 或 success flag:

current_task_info = task_oracle.get_task_info_for_set(
    start_info,
    current_info,
    {subtask}
)

这样可以保证不同模型使用同一套成功标准,避免模型作者通过自定义 success 判断造成评测偏差。

4.5 多 checkpoint 和多 GPU 支持

评测 harness 支持:

  • 最新 checkpoint;
  • 指定 checkpoint;
  • 指定 epoch 列表;
  • 最近 K 个 checkpoint;
  • CUDA device 选择;
  • 训练期间 rollout;
  • 多 GPU DDP 训练;
  • Slurm 调度。

训练入口 training.py 会:

  • 自动恢复当前目录下的最新 checkpoint;
  • 保存 Hydra 配置和 Git commit hash;
  • 使用 PyTorch Lightning;
  • 多 GPU 时启用 DDPStrategy
  • 对 shared-memory 加载设置更长的 timeout。

4.6 训练阶段的数据与 rollout 优化

README 和代码中比较明确的优化包括:

  1. Shared-memory dataset loader
   python training.py \
     datamodule.root_data_dir=/path/to/dataset/ \
     datamodule/datasets=vision_lang_shm

把数据预加载到共享内存,减少训练时磁盘读取开销。

  1. EGL GPU rendering

允许训练过程中进行 GPU rollout,而不是完全依赖 CPU 渲染。

  1. 可关闭 rollout callback

调试或纯训练时可以关闭:

   ~callbacks/rollout
   ~callbacks/rollout_lh
  1. Slurm 可复现提交

Slurm 脚本会在提交时复制当前仓库状态,并生成:

  • resume_training.sh
  • evaluate.sh

这样后续训练不会受到仓库继续变化的影响。

  1. 评估结果持久化

评估器会把结果保存到 results.json,内容包括:

  • 平均成功链长度;
  • SR_1...SR_5
  • 每个任务的成功次数和总次数;
  • 最佳 checkpoint。
  1. 可选的可视化与 latent plan 分析

支持:

  • debug rollout;
  • 在画面中显示语言指令;
  • 保存 rollout video;
  • 导出 latent plan 的 t-SNE 数据。

总结

可以把 CALVIN 理解为四层:

任务集
  └─ 34 类左右的原子操作 + 多任务语言序列

仿真与本体
  └─ PyBullet + PlayTable + 7-DoF 机械臂 + 多模态传感器

评估与基线
  └─ MCIL + 1000 条评估序列 + SR_1...SR_5 + 平均成功链长度

Harness 与工程优化
  └─ 统一 CustomModel 接口、任务 oracle、确定性 reset、
     checkpoint 管理、EGL、shared memory、DDP、Slurm 和结果持久化

它的核心价值不只是提供一个机器人仿真环境,而是提供了一套可复现、可横向比较、专门针对语言条件长时序操作的评测协议