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의 벤치마크는 Gymnasium 환경의 집합으로, 서드파티 시뮬레이터(LIBERO, Meta-World 등)를 표준 gym.Env 인터페이스 뒤에 래핑합니다. lerobot-eval CLI은 모든 벤치마크에 걸쳐 균일하게 평가를 실행합니다.

기존 벤치마크 한눈에 보기

시작하기 전에, 이미 통합된 몇 가지 벤치마크를 소개합니다(모든 항목은 문서 사이드바의 Benchmarks 섹션에 나열되어 있습니다):

벤치마크Env 파일Config 클래스작업액션 차원프로세서
LIBEROenvs/libero.pyLiberoEnv5개 스위트에 걸친 130개7LiberoProcessorStep
Meta-Worldenvs/metaworld.pyMetaworldEnv50 (MT50)4None
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단계(env-specific 변환이 필요한 경우)만 처리하면 됩니다.

환경 구조

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()은 모든 suite와 task를 순회합니다.
  3. 각 작업마다 rollout()을 통해 n_episodes개의 롤아웃을 실행합니다.
  4. 결과는 에피소드, 태스크, 스위트, 전체 순으로 계층적으로 집계됩니다.
  5. Metrics에는 pc_success(성공률), avg_sum_reward, avg_max_reward가 포함됩니다. 모든 성공률은 해당 카운트(n_episodes 중 n_success)와 퍼센트 단위의 95% Wilson 구간(pc_success_ci95)과 함께 보고되며, 이는 task, suite, 전체 수준에서 적용됩니다. 해당 구간은 에피소드 간 샘플링 노이즈만을 반영하며, 동일한 레시피의 학습 실행 간 변동성에 대해서는 아무런 정보를 제공하지 않습니다.

핵심 부분: env는 모든 step() 호출 시 info["is_success"]를 반환해야 합니다. eval 루프가 작업이 완료되었는지 여부를 파악하는 방식입니다.

환경에서 제공해야 하는 것

LeRobot은 엄격한 관찰 스키마를 강제하지 않습니다. 대신 모든 벤치마크가 따르는 일련의 관례에 의존합니다.

Env 속성

gym.Env에는 다음 속성을 설정해야 합니다:

속성유형왜
_max_episode_stepsintrollout()은 에피소드 길이를 제한하는 데 이 값을 사용합니다
task_descriptionstrVLA 정책에 언어 지시문으로 전달됩니다
taskstrtask_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" (dict)observation.images.<cam>HWC uint8 형식의 여러 카메라
"agent_pos"observation.state고유수용성 상태 벡터
"environment_state"observation.env_state전체 환경 상태 (예: PushT)
"robot_state"observation.robot_state중첩된 로봇 상태 dict (예: LIBERO)

시뮬레이터가 다른 키 이름을 사용하는 경우 두 가지 옵션이 있습니다:

  1. 권장 사항: gym.Env 래퍼 내부에서 표준 키로 이름을 변경하세요.
  2. 대안: preprocess_observation() 실행 후 관측값을 변환하는 env 프로세서를 작성합니다(아래 3단계 참조).

Actions

Actions은 gym.spaces.Box의 연속형 numpy 배열입니다. 차원은 벤치마크에 따라 달라지며(LIBERO는 7, Meta-World는 4 등), 정책은 input_features / output_features 설정을 통해 서로 다른 action 차원에 적응합니다.

기능 선언

각 EnvConfig 하위 클래스는 정책이 무엇을 기대해야 하는지를 알려주는 두 개의 딕셔너리를 선언합니다:

  • features — 특징 이름을 PolicyFeature(type, shape) (예: action dim, image 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예벤치마크와 create_envs()를 CLI에 등록합니다
src/lerobot/processor/env_processor.py선택 사항사용자 정의 관찰/행동 변환
src/lerobot/envs/utils.py선택 사항새로운 원시 관찰 키가 필요한 경우에만
pyproject.toml보통벤치마크별 종속성을 선언합니다
docs/source/<benchmark>.mdx예사용자 대상 문서 페이지
docs/source/_toctree.yml예docs 사이드바에 페이지를 추가합니다

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()를 참고하세요.

중첩된 dict 구조를 반환하는 팩토리 함수도 제공합니다:

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>를 통해 사용자가 벤치마크를 선택할 수 있도록 config dataclass를 등록합니다. 각 config는 두 가지 메서드를 통해 환경 생성 및 프로세서 로직을 관리합니다:

  • create_envs(n_envs, use_async_envs) — {suite: {task_id: VectorEnv}}를 반환합니다. 기본 클래스의 기본값은 단일 작업 환경에 gym.make()를 사용합니다. 다중 작업 벤치마크는 이 메서드를 오버라이드합니다.
  • get_env_processors() — (preprocessor, postprocessor)를 반환합니다. 기본 클래스의 기본값은 identity(no-op) 파이프라인을 반환합니다. 벤치마크에 관찰/행동 변환이 필요한 경우 오버라이드하세요.
@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 이름은 사용자가 CLI(--env.type=<name>)에서 전달하는 값입니다.
  • features는 정책(policy)에 환경이 무엇을 생성하는지를 알려줍니다.
  • features_map은 원시 관찰 키를 LeRobot 규약 키로 매핑합니다.
  • factory.py에 변경 사항이 필요하지 않습니다 — 팩토리가 자동으로 cfg.create_envs()와 cfg.get_env_processors()에 위임합니다.

3. Env 프로세서 (선택 사항 — 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]"]

고정 규칙:

  • Always pin benchmark packages to exact versions for reproducibility (e.g. 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. Smoke test 환경 생성 — Python에서 설정을 사용하여 make_env()를 호출하고, 반환된 dict가 예상된 {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로 전환되는지 확인합니다. 이는 eval 루프가 성공률을 계산하는 데 사용하는 값입니다.

벤치마크 문서 페이지 작성

각 벤치마크 .mdx 페이지에는 다음을 포함해야 합니다:

  • 제목 및 설명 — 벤치마크가 무엇을 테스트하는지, 그리고 왜 중요한지에 대한 1~2단락 분량의 내용.
  • 링크 — 논문, GitHub 저장소, 프로젝트 웹사이트(사용 가능한 경우).
  • 개요 이미지 또는 GIF.
  • 사용 가능한 작업 — 작업 스위트의 개수와 간단한 설명이 포함된 표.
  • 설치 — pip install -e ".[<benchmark>]" 및 추가 단계(환경 변수, 시스템 패키지).
  • 평가 — 재현 가능한 결과를 위해 n_episodes를 사용하는 lerobot-eval 명령을 권장합니다. batch_size는 기본적으로 auto로 설정되며, 필요한 경우에만 명시하세요. 해당되는 경우 단일 작업 및 다중 작업 예시를 포함하세요.
  • 정책 입력 및 출력 — 형태가 포함된 관찰 키, 액션 공간 설명.
  • 권장 평가 에피소드 — 각 작업당 표준으로 사용되는 에피소드 수.
  • 학습 — lerobot-train 명령어 예시.
  • 공개된 결과 재현 — 사전 학습된 모델 링크, 평가 명령어, 결과 테이블(사용 가능한 경우).

완전한 예제는 docs/source/libero.mdx 및 docs/source/metaworld.mdx를 참고하세요.

Update on GitHub