LeRobot documentation

添加新基准

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.6.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

添加新基准

本指南将指导您向 LeRobot 添加新的仿真基准测试。请按顺序执行以下步骤,并参考现有的基准测试作为模板。

LeRobot 中的基准测试(benchmark)是一组 Gymnasium 环境,它们通过标准的 gym.Env 接口封装第三方模拟器(如 LIBERO 或 Meta-World)。随后,lerobot-eval CLI 会在所有基准测试上统一执行评估。

现有基准测试一览

在开始之前,这里列出了一些已经集成的基准测试(它们全部列在文档侧边栏的 Benchmarks 下):

基准测试Env 文件配置类任务动作维度处理器
LIBEROenvs/libero.pyLiberoEnv5 个测试套件中的 130 个7LiberoProcessorStep
Meta-Worldenvs/metaworld.pyMetaworldEnv50 (MT50)4无
IsaacLab ArenaHub 托管IsaaclabArenaEnv可配置可配置IsaaclabArenaProcessorStep

请参考 src/lerobot/envs/libero.py 和 src/lerobot/envs/metaworld.py 作为参考实现。

各部分如何协同工作

数据流

在评估过程中,数据会经历四个阶段:

1. gym.Env  ──→  raw observations (numpy dicts)

2. Preprocessing  ──→  standard LeRobot keys + task description
   (preprocess_observation in envs/utils.py, env.call("task_description"))

3. Processors  ──→  env-specific then policy-specific transforms
   (env_preprocessor, policy_preprocessor)

4. Policy  ──→  select_action()  ──→  action tensor
   then reverse: policy_postprocessor → env_postprocessor → numpy action → env.step()

大多数基准测试只需关注阶段 1(以正确的格式生成观测值),并可选地关注阶段 3(如果需要针对特定环境的转换)。

环境结构

make_env() 返回一个包含向量化环境的嵌套字典:

dict[str, dict[int, gym.vector.VectorEnv]]
#    ^suite       ^task_id

单任务环境(例如 PushT)的结构为 {"pusht": {0: vec_env}}。 多任务基准(例如 LIBERO)的结构为 {"libero_spatial": {0: vec0, 1: vec1, ...}, ...}。

评估的运行方式

所有基准测试均由 lerobot-eval 以相同方式评估:

  1. make_env() 会构建嵌套的 {suite: {task_id: VectorEnv}} 字典。
  2. eval_policy_all() 会遍历所有套件和任务。
  3. 对于每个任务,它通过 rollout() 运行 n_episodes 次 rollout。
  4. 结果按层级进行汇总:episode、task、suite、overall。
  5. 指标包括 pc_success(成功率)、avg_sum_reward 和 avg_max_reward。每个成功率都会附带其计数(n_episodes 中的 n_success)以及以百分比表示的 95% Wilson 区间(pc_success_ci95),并分别在任务、套件和总体层面进行报告。该区间仅涵盖回合间的采样噪声,并不反映同一配方在不同训练运行之间的差异。

关键部分:你的 env 必须在每次 step() 调用时返回 info["is_success"]。评估循环正是通过它来判断任务是否已完成。

您的环境必须提供的内容

LeRobot 不强制要求严格的观测模式。相反,它依赖于一套所有基准测试都遵循的约定。

Env 属性

您的 gym.Env 必须设置以下属性:

属性类型为什么
_max_episode_stepsintrollout() 使用此参数来限制回合长度
task_descriptionstr作为语言指令传递给 VLA 策略
taskstr如果未设置 task_description,则使用此回退标识符

成功报告

您的 step() 和 reset() 必须在 info 字典中包含 "is_success":

info = {"is_success": True}   # or False
return observation, reward, terminated, truncated, info

观察

最简单的方法是将模拟器的输出映射到 preprocess_observation() 已经能够识别的标准键。请在你的 gym.Env 中执行此操作(例如,在 _format_raw_obs() 辅助函数中):

您的 env 应输出LeRobot 将其映射到它是什么
"pixels"(单个数组)observation.image单摄像头图像,HWC uint8
"pixels"(字典)observation.images.<cam>多个摄像头,每个均为 HWC uint8
"agent_pos"observation.state本体感觉状态向量
"environment_state"observation.env_state完整的环境状态(例如 PushT)
"robot_state"observation.robot_state嵌套的机器人状态字典(例如 LIBERO)

如果您的模拟器使用了不同的键名,您有两个选择:

  1. 推荐:在您的 gym.Env 包装器中,将它们重命名为标准键。
  2. 替代方案:编写一个 env 处理器,在 preprocess_observation() 运行后对观测值进行转换(参见下文第 3 步)。

操作

动作是 gym.spaces.Box 中的连续 numpy 数组。其维度取决于所使用的基准测试(例如 LIBERO 为 7,Meta-World 为 4 等)。策略通过其 input_features / output_features 配置来适应不同的动作维度。

功能声明

每个 EnvConfig 子类都声明了两个字典,用于告知策略预期接收的内容:

  • features — 将特征名称映射到 PolicyFeature(type, shape)(例如动作维度、图像形状)。
  • features_map — 将原始观测键映射到 LeRobot 约定键(例如,将 "agent_pos" 映射到 "observation.state")。

逐步

At minimum, you need two files: a **gym.Env wrapper** and an **EnvConfig subclass** with a `create_envs()` override. Everything else is optional or documentation. No changes to `factory.py` are needed.

检查清单

文件必需为什么
src/lerobot/envs/<benchmark>.py是的将模拟器封装为标准的 gym.Env
src/lerobot/envs/configs.py是的在 CLI 中注册你的基准测试及其 create_envs()
src/lerobot/processor/env_processor.py可选自定义观察/动作转换
src/lerobot/envs/utils.py可选仅当您需要新的原始观测键时
pyproject.toml通常声明基准测试特定的依赖项
docs/source/<benchmark>.mdx是的面向用户的文档页面
docs/source/_toctree.yml是的将您的页面添加到文档侧边栏

1. gym.Env 包装器(src/lerobot/envs/<benchmark>.py)

创建一个 gym.Env 子类,用于封装第三方模拟器:

class MyBenchmarkEnv(gym.Env):
    metadata = {"render_modes": ["rgb_array"], "render_fps": <fps>}

    def __init__(self, task_suite, task_id, ...):
        super().__init__()
        self.task = <task_name_string>
        self.task_description = <natural_language_instruction>
        self._max_episode_steps = <max_steps>
        self.observation_space = spaces.Dict({...})
        self.action_space = spaces.Box(low=..., high=..., shape=(...,), dtype=np.float32)

    def reset(self, seed=None, **kwargs):
        ...  # return (observation, info) — info must contain {"is_success": False}

    def step(self, action: np.ndarray):
        ...  # return (obs, reward, terminated, truncated, info) — info must contain {"is_success": <bool>}

    def render(self):
        ...  # return RGB image as numpy array

    def close(self):
        ...

基于 GPU 的模拟器(例如使用 EGL 渲染的 MuJoCo): 如果你的模拟器在 __init__ 期间分配 GPU/EGL 上下文,请将此分配延迟到在首次调用 reset()/step() 时执行的 _ensure_env() 辅助函数中。这可以避免在 AsyncVectorEnv 生成工作进程时继承过期的 GPU 句柄。有关该模式的示例,请参阅 LiberoEnv._ensure_env()。

同时提供一个工厂函数,返回嵌套的字典结构:

def create_mybenchmark_envs(
    task: str,
    n_envs: int,
    gym_kwargs: dict | None = None,
    env_cls: type | None = None,
) -> dict[str, dict[int, Any]]:
    """Create {suite_name: {task_id: VectorEnv}} for MyBenchmark."""
    ...

请参阅 create_libero_envs()(多套件、多任务)和 create_metaworld_envs()(按难度分组的任务)作为参考。

2. 配置文件(src/lerobot/envs/configs.py)

注册一个配置数据类,以便用户可以使用 --env.type=<name> 选择您的基准测试。每个配置通过两个方法拥有其环境创建和处理器逻辑:

  • create_envs(n_envs, use_async_envs) — 返回 {suite: {task_id: VectorEnv}}。基类的默认实现使用 gym.make() 创建单任务环境。多任务基准测试会重写此方法。
  • get_env_processors() — 返回 (preprocessor, postprocessor)。基类的默认实现返回恒等(无操作)流水线。如果您的基准测试需要对观测/动作进行转换,请重写此方法。
@EnvConfig.register_subclass("<benchmark_name>")
@dataclass
class MyBenchmarkEnvConfig(EnvConfig):
    task: str = "<default_task>"
    fps: int = <fps>
    obs_type: str = "pixels_agent_pos"

    features: dict[str, PolicyFeature] = field(default_factory=lambda: {
        ACTION: PolicyFeature(type=FeatureType.ACTION, shape=(<action_dim>,)),
    })
    features_map: dict[str, str] = field(default_factory=lambda: {
        ACTION: ACTION,
        "agent_pos": OBS_STATE,
        "pixels": OBS_IMAGE,
    })

    def __post_init__(self):
        ...  # populate features based on obs_type

    @property
    def gym_kwargs(self) -> dict:
        return {"obs_type": self.obs_type, "render_mode": self.render_mode}

    def create_envs(self, n_envs: int, use_async_envs: bool = True):
        """Override for multi-task benchmarks or custom env creation."""
        from lerobot.envs.<benchmark> import create_<benchmark>_envs
        return create_<benchmark>_envs(task=self.task, n_envs=n_envs, ...)

    def get_env_processors(self):
        """Override if your benchmark needs observation/action transforms."""
        from lerobot.processor import PolicyProcessorPipeline
        from lerobot.processor.env_processor import MyBenchmarkProcessorStep
        return (
            PolicyProcessorPipeline(steps=[MyBenchmarkProcessorStep()]),
            PolicyProcessorPipeline(steps=[]),
        )

要点:

  • register_subclass 名称是用户在命令行中传入的内容(--env.type=<name>)。
  • features 告知策略环境会产生什么。
  • features_map 将原始观测键映射到 LeRobot 约定键。
  • 无需对 factory.py 进行任何更改 — 工厂会自动委托给 cfg.create_envs() 和 cfg.get_env_processors()。

3. 环境处理器(可选 — src/lerobot/processor/env_processor.py)

仅当您的基准测试需要 preprocess_observation() 无法处理的观察转换(例如图像翻转、坐标转换)时才需要此步骤。在此处定义处理器步骤,并在您的配置中从 get_env_processors() 返回它(参见步骤 2):

@dataclass
@ProcessorStepRegistry.register(name="<benchmark>_processor")
class MyBenchmarkProcessorStep(ObservationProcessorStep):
    def _process_observation(self, observation):
        processed = observation.copy()
        # your transforms here
        return processed

    def transform_features(self, features):
        return features  # update if shapes change

    def observation(self, observation):
        return self._process_observation(observation)

有关完整示例(图像旋转、四元数到轴角转换),请参阅 LiberoProcessorStep。

4. 依赖项(pyproject.toml)

添加一个新的可选依赖组:

mybenchmark = ["my-benchmark-pkg==1.2.3", "lerobot[scipy-dep]"]

固定规则:

  • 始终将基准测试包固定到确切版本以确保可复现性(例如 metaworld==3.0.0)。
  • 在需要时(例如 ; sys_platform == 'linux')添加平台标记。
  • 如果已知,请固定脆弱的传递依赖(例如,对于 Meta-World 使用 gymnasium==1.1.0)。
  • 在您的基准测试文档页面中记录约束条件。

用户通过以下方式安装:

pip install -e ".[mybenchmark]"

5. 文档(docs/source/<benchmark>.mdx)

按照下一节的模板编写面向用户的页面。完整的示例请参见 docs/source/libero.mdx 和 docs/source/metaworld.mdx。

6. 目录(docs/source/_toctree.yml)

将您的基准测试添加到“Benchmarks”部分:

- sections:
    - local: libero
      title: LIBERO
    - local: metaworld
      title: Meta-World
    - local: envhub_isaaclab_arena
      title: NVIDIA IsaacLab Arena Environments
    - local: <your_benchmark>
      title: <Your Benchmark Name>
  title: "Benchmarks"

验证您的集成

完成上述步骤后,确认一切正常运行:

  1. 安装 — pip install -e ".[mybenchmark]" 并验证依赖组是否干净地安装。
  2. 创建冒烟测试环境 — 在 Python 中调用 make_env() 并传入你的配置,检查返回的字典是否具有预期的 {suite: {task_id: VectorEnv}} 结构,并且 reset() 返回的观察值包含正确的键。
  3. 运行完整评估 — 使用 lerobot-eval --env.type=<name> --env.task=<task> --eval.n_episodes=1 --policy.path=<any_compatible_policy> 来端到端地测试完整流程。(batch_size 默认根据 CPU 核心数自动调整;传入 --eval.batch_size=1 可强制使用单个环境。)
  4. 检查成功检测 — 验证当任务实际完成时,info["is_success"] 是否变为 True。评估循环使用此值来计算成功率。

编写基准测试文档页面

每个基准测试的 .mdx 页面应包含:

  • 标题和描述 — 1-2 段文字,说明该基准测试的内容及其重要性。
  • 链接 — 论文、GitHub 仓库、项目网站(如有)。
  • 概览图片或 GIF。
  • 可用任务 — 任务套件表格,包含数量及简要描述。
  • 安装 — pip install -e ".[<benchmark>]" 以及任何额外步骤(环境变量、系统软件包)。
  • 评估 — 推荐用于可复现结果的 lerobot-eval 命令,并指定 n_episodes。batch_size 默认为自动;仅在需要时指定。如适用,请包含单任务和多任务示例。
  • 策略的输入和输出 — 带有形状的观测键,动作空间描述。
  • 推荐的评估回合数 — 每个任务的标准回合数。
  • 训练 — lerobot-train 命令示例。
  • 复现已发表的结果 — 预训练模型的链接、评估命令、结果表格(如有)。

请参阅 docs/source/libero.mdx 和 docs/source/metaworld.mdx 以获取完整示例。

Update on GitHub