# Política π₀.₅ (Pi05)

π₀.₅ es un **modelo Vision-Language-Action con generalización en el mundo abierto**, de Physical Intelligence. La implementación de LeRobot se adapta de su repositorio de código abierto [OpenPI](https://github.com/Physical-Intelligence/openpi).

## Resumen del modelo

π₀.₅ representa una evolución significativa de π₀, desarrollado por [Physical Intelligence](https://www.physicalintelligence.company/blog/pi05) para abordar un gran desafío en robótica: la **generalización en entornos abiertos**. Si bien los robots pueden realizar tareas impresionantes en entornos controlados, π₀.₅ está diseñado para generalizar a entornos y situaciones completamente nuevos que nunca se vieron durante el entrenamiento.

### El desafío de la generalización

Como explica Physical Intelligence, el desafío fundamental no es realizar tareas de agilidad o destreza, sino la generalización, es decir, la capacidad de realizar correctamente tareas en entornos nuevos con objetos nuevos. Considere un robot que limpia diferentes hogares: cada hogar tiene objetos diferentes en lugares diferentes. La generalización debe ocurrir en múltiples niveles:

- **Nivel físico**: comprender cómo agarrar una cuchara (por el mango) o un plato (por el borde), incluso con objetos no vistos en entornos desordenados
- **Nivel semántico**: comprender la semántica de la tarea, dónde colocar la ropa y los zapatos (en la cesta de la ropa, no en la cama) y qué herramientas son apropiadas para limpiar derrames
- **Nivel ambiental**: Adaptarse a entornos reales "caóticos" como hogares, supermercados, oficinas y hospitales

### Co-entrenamiento en datos heterogéneos

La innovación rompedora de π₀.₅ es el **entrenamiento conjunto con fuentes de datos heterogéneas**. El modelo aprende de:

1. **Datos web multimodales**: Descripción de imágenes, respuesta a preguntas visuales, detección de objetos
2. **Instrucciones verbales**: Humanos que guían a robots a través de tareas complejas paso a paso
3. **Comandos de subtareas**: Etiquetas de comportamiento semántico de alto nivel (p. ej., "recoger la almohada" para una cama deshecha)
4. **Datos de robots de encarnación cruzada**: Datos de diversas plataformas de robots con diferentes capacidades
5. **Datos de multi-entorno**: Robots estáticos desplegados en muchos hogares diferentes
6. **Datos de manipulación móvil**: ~400 horas de demostraciones de robots móviles

Esta mezcla de entrenamiento diversa crea un "currículo" que permite la generalización simultánea en los niveles físico, visual y semántico.

## Requisitos de instalación

1. Instala LeRobot siguiendo nuestra [Guía de instalación](./installation).
2. Instale las dependencias de Pi0.5 ejecutando:

   ```bash
   pip install -e ".[pi]"
   ```

   Si instalaste LeRobot desde PyPI:

   ```bash
   pip install 'lerobot[pi]'
   ```

## Uso

Para usar π₀.₅ en tu configuración de LeRobot, especifica el tipo de política como:

```python
policy.type=pi05
```

## Entrenamiento

### Introducción rápida a LIBERO

Ajusta el modelo base de LIBERO en [lerobot/libero](https://huggingface.co/datasets/lerobot/libero), una copia codificada en video de aproximadamente 1,9 GB de las demostraciones detrás de los [resultados siguientes](#libero-benchmark-results).

Contiene las claves que lee π₀.₅, que son las mismas que produce el entorno LIBERO en el momento de la evaluación:

| Característica                     | Forma en el conjunto de datos | Cómo lo consume π₀.₅                                    |
| --------------------------- | -------------------- | ------------------------------------------------------- |
| `observation.images.image`  | 256×256×3, agentview | redimensionado a 224×224                                      |
| `observation.images.image2` | 256×256×3, muñeca     | redimensionado a 224×224                                      |
| `observation.state`         | 8                    | discretizado en 256 intervalos y escrito en el prompt   |
| `action`                    | 7                    | relleno a 32 internamente; la pérdida utiliza las primeras 7 dimensiones |

**No se necesita `--rename_map` aquí** — las claves ya coinciden; consulte [Rename Map and Empty Cameras](./rename_map) si las suyas difieren.

  π₀.₅ utiliza el tokenizador [google/paligemma-3b-pt-224](https://huggingface.co/google/paligemma-3b-pt-224) con licencia restringida: acepta su licencia en el Hub e inicia sesión con `hf auth login` antes de entrenar.

Dimensionado para una sola GPU de 80 GB:

```bash
lerobot-train \
    --dataset.repo_id=lerobot/libero \
    --policy.type=pi05 \
    --policy.pretrained_path=lerobot/pi05_libero_base \
    --policy.normalization_mapping='{"ACTION": "MEAN_STD", "STATE": "MEAN_STD", "VISUAL": "IDENTITY"}' \
    --policy.n_action_steps=10 \
    --policy.empty_cameras=1 \
    --policy.freeze_vision_encoder=false \
    --policy.train_expert_only=false \
    --policy.gradient_checkpointing=true \
    --policy.dtype=bfloat16 \
    --policy.device=cuda \
    --policy.push_to_hub=false \
    --output_dir=./outputs/pi05_libero \
    --job_name=pi05_libero \
    --batch_size=64 \
    --num_workers=8 \
    --steps=30000 \
    --save_freq=5000 \
    --seed=1000
```

**Normalización media/desviación estándar, no el [valor por defecto de cuantiles](#quantile-statistics) de π₀.₅** — coincide con [pi05_libero_finetuned_v044](https://huggingface.co/lerobot/pi05_libero_finetuned_v044), el checkpoint sobre el que se midieron los resultados siguientes.

**`--policy.n_action_steps=10` y `--policy.empty_cameras=1` son explícitos** porque `--policy.pretrained_path` solo carga los pesos: `lerobot/pi05_libero_base` almacena ambos, y de lo contrario caerían en `50` y `0` (ver [Carga de un checkpoint](#loading-a-checkpoint)).

Luego, evalúa un punto de control con `lerobot-eval` y compáralo con las tasas de éxito de referencia; consulta [LIBERO](./libero).

### Estadísticas de cuantiles

π₀.₅ normaliza `STATE` y `ACTION` con cuantiles, por lo que el `meta/stats.json` de tu conjunto de datos necesita `q01` y `q99`. Los conjuntos de datos más antiguos solo incluyen `min`/`max`/`mean`/`std` y fallan en el primer lote:

```
ValueError: QUANTILES normalization mode requires q01 and q99 stats
```

Recalcularlos:

```bash
lerobot-edit-dataset \
    --repo_id your_dataset \
    --new_repo_id your_dataset \
    --operation.type recompute_stats \
    --operation.overwrite true
```

**The result lands in `$HF_LEROBOT_HOME/your_dataset`**, not the cache `--dataset.repo_id` reads — so train with `--dataset.root=$HF_LEROBOT_HOME/your_dataset`, or add `--push_to_hub true` above.

O mantenga el conjunto de datos tal cual y pase `--policy.normalization_mapping='{"ACTION": "MEAN_STD", "STATE": "MEAN_STD", "VISUAL": "IDENTITY"}'`.

Grabación, reanudación y fusión de cuantiles agregados a partir de resúmenes por episodio, de modo que `meta/stats.json` contenga un sobre envolvente conservador (`min` para `q <= 50`, `max` para `q > 50`) en lugar de cuantiles de todo el conjunto de datos. Para estimar estos últimos, recorra cada episodio con un histograma en ejecución:

```bash
python src/lerobot/scripts/augment_dataset_quantile_stats.py \
    --repo-id=your_dataset \
    --overwrite \
    --skip-images
```

`--skip-images` conserva las estadísticas de imagen existentes y evita descargar o decodificar datos de video cuando solo se necesitan recalcular `STATE`/`ACTION`, y `--root` lee un conjunto de datos local en lugar del Hub. Estos valores son estimaciones de histograma, sujetas a errores de discretización y rebinning, por lo que pueden diferir de los conservadores, lo que cambia los objetivos normalizados de π₀.₅ y, por tanto, su escala de pérdida. Las estadísticas ya guardadas dentro de un checkpoint existente no se ven afectadas.

### Ejemplo de comando de entrenamiento

El mismo ajuste con el VLM congelado: menos memoria, a costa de una tasa de éxito menor. Sustituye `--dataset.repo_id` por tu propio conjunto de datos.

```bash
lerobot-train \
    --dataset.repo_id=lerobot/libero \
    --policy.type=pi05 \
    --policy.pretrained_path=lerobot/pi05_libero_base \
    --policy.normalization_mapping='{"ACTION": "MEAN_STD", "STATE": "MEAN_STD", "VISUAL": "IDENTITY"}' \
    --policy.n_action_steps=10 \
    --policy.empty_cameras=1 \
    --policy.freeze_vision_encoder=true \
    --policy.train_expert_only=true \
    --policy.gradient_checkpointing=true \
    --policy.dtype=bfloat16 \
    --policy.device=cuda \
    --policy.push_to_hub=false \
    --output_dir=./outputs/pi05_libero_expert \
    --job_name=pi05_libero_expert \
    --batch_size=64 \
    --num_workers=8 \
    --steps=30000 \
    --save_freq=5000 \
    --seed=1000
```

### Parámetros clave de entrenamiento

- **`--policy.compile_model=true`**: Habilita la compilación del modelo para un entrenamiento más rápido
- **`--policy.gradient_checkpointing=true`**: Reduce significativamente el uso de memoria durante el entrenamiento
- **`--policy.dtype=bfloat16`**: Utiliza el entrenamiento con precisión mixta para mejorar la eficiencia
- **`--batch_size=64`**: Tamaño del lote para el entrenamiento, adáptalo según la memoria de tu GPU
- **`--policy.pretrained_path=lerobot/pi05_base`**: el modelo base π₀.₅ que desea ajustar, las opciones son:
  - [lerobot/pi05_base](https://huggingface.co/lerobot/pi05_base)
  - [lerobot/pi05_libero_base](https://huggingface.co/lerobot/pi05_libero_base) (entrenado específicamente en el conjunto de datos Libero)
- **`--policy.optimizer_fused=true`**: Utiliza AdamW fusionado para pasos de optimizador más rápidos; esta bandera se ignora al reanudar una ejecución

### RTC opcional en tiempo de entrenamiento

Pi05 puede aprender opcionalmente una condición de prefijo de acciones para un [Real-Time Chunking](./rtc) eficiente, siguiendo [Training-Time Action Conditioning for Efficient Real-Time Chunking](https://arxiv.org/abs/2512.05964). Establezca `policy.rtc_training_max_delay` en el mayor retardo de inferencia esperado en pasos del controlador:

```bash
lerobot-train \
    --dataset.repo_id=${HF_USER}/my_dataset \
    --policy.type=pi05 \
    --policy.pretrained_path=lerobot/pi05_base \
    --policy.rtc_training_max_delay=10 \
    --policy.dtype=bfloat16 \
    --policy.device=cuda \
    --batch_size=8 \
    --steps=30000 \
    --output_dir=outputs/pi05_rtc \
    --job_name=pi05_rtc
```

El valor predeterminado es `0`, lo que desactiva el RTC durante el entrenamiento y deja el objetivo estándar de Pi05 sin cambios. El retraso configurado debe ser menor que `chunk_size`. Durante el entrenamiento, Pi05 muestrea una longitud de prefijo limpio de forma independiente para cada ejemplo y calcula la pérdida de flujo solo en el sufijo restante.

Use el checkpoint resultante con RTC entrenado de forma explícita:

```bash
lerobot-rollout \
    --strategy.type=base \
    --policy.path=outputs/pi05_rtc/checkpoints/last/pretrained_model \
    --inference.type=rtc \
    --inference.rtc.mode=trained \
    --inference.rtc.execution_horizon=10 \
    --robot.type=so100_follower \
    --robot.port=/dev/ttyACM0 \
    --task="pick up the cube" \
    --fps=50 \
    --device=cuda
```

Establezca `inference.rtc.execution_horizon` entre `rtc_training_max_delay` del checkpoint y `chunk_size - rtc_training_max_delay`, y `inference.queue_threshold` al menos a `rtc_training_max_delay`. Un pico de latencia puntual que supere el rango entrenado descarta ese chunk y reintenta; el rollout se detiene con un error explícito solo si el retardo se mantiene fuera de rango. El modo predeterminado `--inference.rtc.mode=guided` sigue disponible para checkpoints ordinarios.

### Cargar un punto de control

Las dos formas no son intercambiables:

|                                        | `--policy.path`                                | `--policy.pretrained_path`                |
| -------------------------------------- | ---------------------------------------------- | ----------------------------------------- |
| Cargas                                  | pesos **y** el `config.json` del checkpoint | solo pesos                              |
| Nombres de características                          | del checkpoint                            | de su conjunto de datos, después de `--rename_map`   |
| Ajustes almacenados, p. ej. `n_action_steps` | heredado                                      | restablecer los valores predeterminados                     |
| `--policy.type`                        | debe omitirse                                | obligatorio                                  |
| `--rename_map`                         | necesario cuando tus teclas de cámara difieren            | soportado para normalizar las claves de los conjuntos de datos |

Use `--rename_map` con cualquiera de las formas de carga cuando los nombres de las características del conjunto de datos en bruto difieran de los nombres de las características de la política. Por ejemplo, el comando de ajuste fino de RoboMME mapea sus columnas en bruto `image`, `wrist_image`, `state` y `actions` mientras inicializa los pesos con `--policy.pretrained_path`.

### Parámetros de entrenamiento explicados

| Parámetro               | Predeterminado | Descripción                                 |
| ----------------------- | ------- | ------------------------------------------- |
| `freeze_vision_encoder` | `false` | No congeles el codificador de visión            |
| `train_expert_only`     | `false` | No congeles el VLM, entrena todos los parámetros |

**💡 Consejo**: Establecer `train_expert_only=true` congela el VLM y entrena solo el experto de acción y las proyecciones, lo que permite el ajuste fino con un uso reducido de memoria.

## Memoria de observación de corto horizonte (MEM)

Pi05 puede usar opcionalmente un contexto visual y propioceptivo de corto horizonte basado en [MEM](https://arxiv.org/abs/2603.03596). Ambas rutas están deshabilitadas de forma predeterminada, por lo que los puntos de control y los comandos de entrenamiento existentes conservan el comportamiento de cuadro único de Pi05.

Esto implementa únicamente la memoria de corto plazo de MEM: el codificador de video de la sección III-C y la proyección propioceptiva de la sección III-D. La memoria de _lenguaje_ de largo plazo de MEM (sección III-B), en la que una política de alto nivel predice el siguiente subtarea y un resumen en lenguaje natural comprimido de lo ocurrido hasta el momento, no está implementada. En las ablaciones del artículo, la memoria de video por sí sola recupera solo parte del progreso de tareas de MEM completo en tareas de largo plazo.

Introducir memoria al hacer finetuning desde un checkpoint que fue preentrenado sin ella también corresponde a la ablation más débil del paper, `MEM-Posttrain-Only`. Los resultados destacados de MEM provienen de preentrenar el codificador de video en una mezcla diversa de video de robots y no robots, algo que ningún checkpoint público de Pi05 proporciona actualmente.

Actívalo durante el ajuste fino con:

```bash
lerobot-train \
    --dataset.repo_id=your_dataset \
    --policy.type=pi05 \
    --policy.pretrained_path=lerobot/pi05_base \
    --policy.use_visual_memory=true \
    --policy.memory_frames=6 \
    --policy.memory_stride=30 \
    --policy.memory_temporal_attention_every=4 \
    ...
```

`memory_frames` incluye la observación actual. `memory_stride` se mide en **frames del dataset**, no en segundos, por lo que debe escalarse con el `fps` de su dataset: MEM se preentrena con seis observaciones separadas por un segundo, lo que equivale a `memory_stride=30` para un dataset de 30 fps (el valor predeterminado) pero a `memory_stride=10` para un dataset de 10 fps como `lerobot/robomme`.

Cada cuarta capa de SigLIP reemplaza su atención con la atención espacio-temporal compuesta de MEM: atención temporal causal entre tokens de parche coincidentes, compuesta con la atención espacial estándar y reutilizando las proyecciones preentrenadas, de modo que no se añaden parámetros aprendibles a la torre de visión. Los tokens de fotogramas anteriores se descartan una vez que se ha ejecutado la última capa de este tipo, manteniendo sin cambios la longitud del prefijo de lenguaje/acción aguas abajo.

El historial no disponible al inicio de un episodio se rellena y se enmascara. Durante la inferencia, Pi05 mantiene internamente el mismo historial de imágenes con saltos y lo limpia cada vez que se restablece la política.

La propiocepción histórica es una opción independiente:

```bash
--policy.use_proprioceptive_memory=true
```

Cuando está habilitado, se añade un token de estado continuo proyectado para cada cuadro retenido, y el estado discretizado se elimina del prompt de texto para que el estado se represente exactamente una vez (sección III-D de MEM). Esto cambia el formato del prompt, por lo que debe habilitarse desde el inicio del entrenamiento y no a mitad del proceso. La memoria visual y la memoria propioceptiva utilizan las mismas configuraciones de `memory_frames` y `memory_stride`, pero cada ruta puede habilitarse de forma independiente. Entrene o ajuste el modelo con las opciones de memoria seleccionadas; habilitarlas solo en la inferencia no proporciona un comportamiento de memoria aprendido en un checkpoint de un solo cuadro.

Bajo PEFT, `proprio_history_proj` se entrena y se guarda por completo mediante `modules_to_save`, ya que no tiene pesos preentrenados a los que adaptarse.

En la inferencia, MEM mantiene una cola de historial por lotes y asume que cada fila del lote comparte los límites de episodio. `lerobot-eval` cumple esto llamando a `policy.reset()` antes de cada despliegue por lotes y antes de reiniciar el entorno vectorial. No se admite el autoreset independiente de filas en un lote vectorial asíncrono; inicie un nuevo despliegue para que las colas completas de política y de acciones se reinicien juntas.

## Acciones relativas

Por defecto, π₀.₅ predice acciones absolutas. Puedes habilitar **acciones relativas** para que el modelo prediga desplazamientos relativos al estado actual del robot. Esto puede mejorar la estabilidad del entrenamiento en ciertas configuraciones.

Para usar acciones relativas, primero recalcula las estadísticas de tu conjunto de datos en el espacio relativo mediante la CLI:

```bash
lerobot-edit-dataset \
    --repo_id your_dataset \
    --new_repo_id your_dataset \
    --operation.type recompute_stats \
    --operation.overwrite true \
    --operation.relative_action true \
    --operation.chunk_size 50 \
    --operation.relative_exclude_joints "['gripper']" \
    --push_to_hub true
```

O equivalentemente en Python:

```python
from lerobot.datasets import LeRobotDataset, recompute_stats

dataset = LeRobotDataset("your_dataset")
recompute_stats(dataset, relative_action=True, chunk_size=50, relative_exclude_joints=["gripper"])
dataset.push_to_hub()
```

El `chunk_size` debe coincidir con el `chunk_size` de su política (50 por defecto para π₀.₅). `relative_exclude_joints` enumera los nombres de articulaciones que deben permanecer en el espacio absoluto (p. ej., comandos del agarre). Use `--push_to_hub true` para subir las estadísticas actualizadas al Hub.

Luego, entrena con acciones relativas habilitadas:

```bash
lerobot-train \
    --dataset.repo_id=your_dataset \
    --policy.type=pi05 \
    --policy.use_relative_actions=true \
    --policy.relative_exclude_joints='["gripper"]' \
    ...
```

## Resultados de rendimiento

### Resultados del benchmark Libero

π₀.₅ ha demostrado un rendimiento sólido en la suite de benchmarks Libero. Para comparar y probar su implementación en LeRobot, ajustamos el modelo base de libero durante 6k pasos adicionales en el conjunto de datos Libero y comparamos los resultados con los resultados de referencia de OpenPI.

| Benchmark          | Implementación de LeRobot | Referencia de OpenPI |
| ------------------ | ---------------------- | ---------------- |
| **Libero Spatial** | 97.0%                  | 98.8%            |
| **Libero Object**  | 99.0%                  | 98.2%            |
| **Objetivo de Libero**    | 98.0%                  | 98.0%            |
| **Libero 10**      | 96.0%                  | 92.4%            |
| **Promedio**        | 97.5%                  | 96.85%           |

Estos resultados demuestran las sólidas capacidades de generalización de π₀.₅ en diversas tareas de manipulación robótica. Para reproducir estos resultados, puede seguir las instrucciones de la sección [Libero](https://huggingface.co/docs/lerobot/libero).

## Licencia

Este modelo sigue la **Apache 2.0 License**, en línea con el repositorio original [OpenPI](https://github.com/Physical-Intelligence/openpi).

