LeRobot documentation

Agregar un benchmark

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Agregar un benchmark

Un benchmark es un simulador que LeRobot controla en un solo lugar, lerobot.sim, para que cada forma de usarlo se comporte de la misma manera: lerobot-eval (un entorno por lotes, --env.type=<benchmark>), rollout y grabación (un robot simulado, --robot.type=sim --robot.env.type=<benchmark>), localmente o servido por lerobot-env-server desde su propia imagen de Docker. Consulte Simulación: local o servida para ver cómo se utiliza.

Qué añadir

ComponenteUbicaciónQué añadir
Integraciónsrc/lerobot/sim/integrations/<benchmark>.pyEl gym.Env, las fábricas env_fns(), el adaptador canonical_observation() y las conventions() para ese simulador
Configsrc/lerobot/envs/configs.pyUna subclase de EnvConfig cuyo sim_settings() mapea sus opciones a los kwargs de la fábrica
Configuración del servidordocker/sim/configs/<benchmark>.yamlLos kwargs de la tarea y la fábrica que utilizan el servidor y la CI
Imagen del simuladordocker/Dockerfile.simUna etapa <benchmark>_native: dependencias nativas fijas (incluida cualquier herramienta de CUDA, ya que la base es Ubuntu sin modificaciones) y revisiones de recursos; la etapa final añade el servidor
Manifiesto de CIbenchmarks/benchmarks.yamlNombre, tareas, revisión del punto de control, cámara, rename_map y parity opcional; el resto toma valores predeterminados a partir del nombre
Dependenciaspyproject.tomlUn grupo de dependencias opcionales para uso local
Documentacióndocs/source/<benchmark>.mdx, _toctree.ymlUna página para el usuario
Origendocs/source/<benchmark>.mdxRepositorios de origen, revisiones de código y activos fijadas con sus licencias, y una tasa de éxito publicada para un punto de control que puedes ejecutar

Ambas rutas exponen el mismo comportamiento del entorno:

native simulator → LocalVectorEnv, locally or on an env server → canonical NumPy observations
  → batched env or sim robot → one-time image/tensor preparation → saved policy preprocessing
  → policy → saved action postprocessing → native simulator

Coloca la orientación de la imagen, la conversión de cuaterniones y el ordenamiento del estado en el adaptador canonical_observation() de ese simulador, y sus convenciones de control en su conventions(), para que la evaluación y el rollout coincidan. Reutiliza sim/integrations/utils.py solo para los mapeos compartidos por las integraciones; el código de entorno compartido no debe ramificarse en función de los nombres de los simuladores. Un nuevo benchmark no necesita un environment processor: las observaciones llegan a los propios procesadores de la política ya en formato canónico.

Cómo se ejecutan las evaluaciones

lerobot-eval evalúa cada benchmark de la misma manera:

  1. make_env() construye el diccionario anidado {suite: {task_id: vector env}}.
  2. eval_policy_all() ejecuta n_episodes rollouts de cada tarea, una tarea a la vez (o --env.max_parallel_tasks a la vez).
  3. Los resultados se agregan por episodio, tarea, suite y en general: pc_success (tasa de éxito), avg_sum_reward y avg_max_reward. Cada tasa de éxito incluye sus recuentos (n_success de n_episodes) y un intervalo de Wilson del 95% en porcentaje (pc_success_ci95). El intervalo cubre solo el ruido de muestreo entre episodios; no dice nada sobre la variación entre ejecuciones de entrenamiento de la misma receta.

El éxito proviene de info["is_success"], que su entorno informa en cada step(). Su entorno también puede informar números propios. Los coloca en info["metrics"], un mapa de cada nombre a un float por entorno. Llegan a la entrada de cada episodio bajo per_episode[i]["metrics"], tomados en el paso en que el episodio terminó.

Lo que su entorno debe proporcionar

Estructura del entorno

env_fns() devuelve las fábricas de entorno de cada tarea, sin construirlas:

def env_fns(
    task: str,
    n_envs: int,
    gym_kwargs: dict | None = None,
) -> dict[str, dict[int, list[Callable[[], gym.Env]]]]:
    """{suite: {task_id: [make_single_env] * n_envs}} for MyBenchmark."""

Un benchmark de una sola tarea devuelve {"<task>": {0: [...]}}; uno de varias tareas (como LIBERO) devuelve {"libero_spatial": {0: [...], 1: [...], ...}, ...}. LocalVectorEnv llama a cada factoría make_single_env en el primer uso, localmente o en el servidor y, con --eval.use_async_envs=true, en un proceso separado por entorno.

El 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)
AtributoTipoPor qué
_max_episode_stepsintFinaliza (trunca) un episodio
task_descriptionstrSe pasa a las políticas VLA como una instrucción de lenguaje
taskstrIdentificador de respaldo si task_description no está establecido

step() informa el éxito en info["is_success"], y cualquier otra cosa que mida en info["metrics"]. Las acciones son una Box continua de una dimensión.

Las observaciones son un diccionario que el adaptador canonical_observation() de la integración entiende. El adaptador predeterminado reutilizable mapea:

Salidas de tu envClave canónicaEn qué consiste
"pixels" (un solo array)observation.imageImagen de una sola cámara, HWC uint8
"pixels" (dict)observation.images.<cam>Varias cámaras, cada una HWC uint8
"agent_pos"observation.stateVector de estado propioceptivo
"environment_state"observation.environment_stateEstado completo del entorno (p. ej., PushT)

Cualquier otro array se pasa como observation.<key>. Renombra las salidas de tu simulador a estas claves dentro de gym.Env, o maneja su representación nativa en el adaptador de esa integración.

Simuladores basados en GPU (p. ej., MuJoCo con renderizado EGL): si su simulador asigna contextos de GPU/EGL durante __init__, difiera esa asignación a un auxiliar _ensure_env() que se llame en el primer reset()/step(), de modo que un entorno construido en un proceso de trabajador no herede manejos de GPU obsoletos. Consulte LiberoEnv._ensure_env() para ver el patrón.

Convenciones ( conventions() en la integración)

Devuelve la tasa de control del simulador, el controlador y los nombres de componentes ordenados desde conventions(kwargs), una función de las opciones del simulador (pueden depender de un modo de acción, como en RoboTwin). Rellenan la configuración que una configuración omite y nombran los componentes de estado y acción para robots, conjuntos de datos y puntos de control. semantics tiene por defecto <type>-<control>-v1. robot_type nombra el cuerpo simulado, registrado por un robot de simulación: el tipo que el robot real registra cuando lerobot tiene una clase para él (so_follower), de lo contrario un nombre corto (panda, sawyer); si se omite, los conjuntos de datos registran sim_robot.

La configuración ( src/lerobot/envs/configs.py )

Registra una configuración para que los usuarios puedan seleccionar tu benchmark con --env.type=<name> (y --robot.env.type=<name>). Su sim_settings() describe el simulador como la sección sim de un YAML de servidor; LocalVectorEnv se encarga del resto:

@EnvConfig.register_subclass("<benchmark_name>")
@dataclass
class MyBenchmarkEnvConfig(EnvConfig):
    task: str = "<default_task>"
    fps: int = <fps>
    obs_type: str = "pixels_agent_pos"

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

    def sim_settings(self) -> dict:
        return {"type": "<benchmark_name>", "task": self.task, "kwargs": {"gym_kwargs": self.gym_kwargs}}

Mantén sus valores predeterminados y los del YAML del servidor en concordancia: una evaluación servida rechaza un servidor que ejecuta un entorno diferente al que describe el comando. Las características provienen de la descripción del entorno cuando este se crea, por lo que la configuración no declara ninguna.

Admisión de puntos de control

--rename_map asigna alias a las claves de cámara del entorno para que coincidan con las claves entrenadas del checkpoint, igual que para cualquier robot; en CI proviene de la entrada rename_map en benchmarks/benchmarks.yaml. Las entradas del checkpoint deben existir después del renombrado, y las dimensiones de estado/acción deben coincidir; el renombrado no puede reparar los metadatos del checkpoint. El número y el orden de los canales RGB se verifican en la admisión. La altura/ancho de adquisición puede diferir de los metadatos de entrenamiento; el redimensionado corresponde a la preprocesación de la política.

Verificación y CI

  1. Comprueba el adaptador de observación de la integración frente a las salidas crudas de tu simulador, en particular la orientación de la cámara y el orden del estado, y verifica las acciones aplicadas por el envoltorio del entorno.
  2. Compare las secuencias de reinicio/paso con semilla localmente y servidas (scripts/ci/check_sim_parity.py); establezca parity: true en la entrada del manifiesto de un simulador determinista para que CI lo ejecute. Verifique el congelamiento terminal, el éxito, la longitud del episodio, la renderización y la limpieza de recursos.
  3. Ejecuta las guardas de importación con torch deshabilitado para el código del servidor y tu módulo nativo. Documenta los simuladores que requieren su propio runtime de torch, como RoboTwin y RoboMME.
  4. Ejecuta lerobot-eval --env.type=<name> --env.task=<task> --eval.n_episodes=1 --policy.path=<checkpoint> localmente y, con --env.server.endpoint, contra el servidor. Inspecciona las descripciones de las tareas y las vistas de las cámaras renderizadas.
  5. Ejecuta el trabajo de benchmark generado en el runner de GPU. Conserva el smoke de entrenamiento de LIBERO al modificar la integración compartida de evaluación/entrenamiento.

benchmarks/benchmarks.yaml genera la matriz a través de scripts/ci/benchmark_matrix.py; .github/workflows/benchmark_run.yml ejecuta cada entrada. Añada entradas al manifiesto en lugar de copiar trabajos de CI. La CI limita los episodios para verificar el pipeline de principio a fin; su metrics.json registra la revisión del checkpoint, la etiqueta de la imagen del simulador, el commit y el límite, y marca estas ejecuciones como smoke: sus tasas de éxito no son puntuaciones de política. Las imágenes del simulador tienen fijaciones y etiquetas de contenido separadas; las cachés de BuildKit solo persisten en ejecutores persistentes.

Cambiar un benchmark

La canonical_observation(), las conventions() y el envoltorio de entorno de una integración deciden qué ve la política y cómo se aplican sus acciones. Una orientación de imagen, un orden de estado o una tasa de control incorrectos no provocan un error: la política recibe entradas ligeramente incorrectas y su tasa de éxito disminuye. Un cambio en cualquiera de ellos conlleva:

  • Una prueba de regresión que compara las salidas antiguas y nuevas sobre una observación registrada o sintética. test_libero_numpy_adapter_parity en tests/sim/integrations/test_libero.py es el modelo: demuestra que el adaptador de LIBERO sin torch produce exactamente lo que hacía el procesador de LIBERO anterior.
  • El efecto esperado en las puntuaciones en la solicitud de extracción: ninguno, o qué puntuaciones deberían cambiar y por qué.

Dependencias ( pyproject.toml )

Agregue un nuevo grupo de dependencias opcionales para uso local:

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

Reglas de fijación:

  • Fija siempre los paquetes de benchmark a versiones exactas para garantizar la reproducibilidad (p. ej. metaworld==3.0.0).
  • Añade marcadores de plataforma cuando sea necesario (p. ej. ; sys_platform == 'linux').
  • Fija las dependencias transitarias frágiles si se conocen (p. ej., la imagen de Meta-World fija mujoco==3.15.0, ya que MuJoCo 3.17 rompe sus soldaduras de mocap).
  • Restricciones del documento en la página de tu documento de benchmark. Cuando las dependencias entran en conflicto con las de LeRobot, la ruta servida es la compatible.

Escribir una página de documentación de un benchmark

Añade la página a la sección “Benchmarks” de docs/source/_toctree.yml. Cada página de benchmark debe incluir:

  • Título y descripción — 1-2 párrafos sobre lo que evalúa el benchmark y por qué es importante.
  • Enlaces — artículo, repositorio de GitHub, sitio web del proyecto (si está disponible).
  • Origen y licencias — repositorios de origen, revisiones fijas de código y activos, y la licencia de cada uno. No añada un benchmark cuya licencia prohíba su uso.
  • Imagen o GIF de resumen.
  • Tareas disponibles — tabla de suites de tareas con recuentos y descripciones breves.
  • Instalación — pip install -e ".[<benchmark>]", o el comando del servidor.
  • Evaluación — comando lerobot-eval recomendado con n_episodes para resultados reproducibles.
  • Entradas y salidas de la política — claves de observación con formas, descripción del espacio de acciones.
  • Entrenamiento — ejemplo del comando lerobot-train.
  • Resultados de referencia — la tasa de éxito publicada de al menos un checkpoint preentrenado que puedas ejecutar, con su revisión y el comando lerobot-eval que lo reproduce. Una integración que no se acerque a ese valor no está terminada.

Consulte docs/source/libero.mdx y docs/source/metaworld.mdx para ejemplos completos.

Update on GitHub