# Política π₀.₅ (Pi05)

π₀.₅ é um **modelo Vision-Language-Action com generalização em mundo aberto**, da Physical Intelligence. A implementação do LeRobot é adaptada do repositório de código aberto [OpenPI](https://github.com/Physical-Intelligence/openpi) deles.

## Visão geral do modelo

π₀.₅ representa uma evolução significativa em relação ao π₀, desenvolvido pela [Physical Intelligence](https://www.physicalintelligence.company/blog/pi05) para enfrentar um grande desafio na robótica: a **generalização em mundo aberto**. Embora os robôs possam executar tarefas impressionantes em ambientes controlados, o π₀.₅ foi projetado para se generalizar a ambientes e situações totalmente novos que nunca foram vistos durante o treinamento.

### O Desafio da Generalização

Conforme a Physical Intelligence explica, o desafio fundamental não é executar tarefas de agilidade ou destreza, mas sim a generalização, a capacidade de executar corretamente tarefas em novos ambientes com novos objetos. Considere um robô limpando casas diferentes: cada casa tem objetos diferentes em lugares diferentes. A generalização deve ocorrer em múltiplos níveis:

- **Nível físico**: Compreender como pegar uma colher (pelo cabo) ou um prato (pela borda), mesmo com objetos não vistos em ambientes desorganizados
- **Nível Semântico**: Compreensão da semântica da tarefa, como onde colocar roupas e sapatos (no cesto de roupa suja, não na cama) e quais ferramentas são apropriadas para limpar derramamentos
- **Nível ambiental**: Adaptação a ambientes reais "caóticos", como residências, supermercados, escritórios e hospitais

### Co-Training em Dados Heterogêneos

A inovação disruptiva do π₀.₅ é o **co-treinamento em fontes de dados heterogêneas**. O modelo aprende a partir de:

1. **Dados Web Multimodais**: legendagem de imagens, resposta a perguntas visuais, detecção de objetos
2. **Instruções verbais**: Humanos orientando robôs em tarefas complexas passo a passo
3. **Comandos de subtarefas**: Rótulos de comportamento semântico de alto nível (por exemplo, "pegue o travesseiro" para uma cama desfeita)
4. **Dados de robôs de múltiplas plataformas**: Dados de diversas plataformas de robôs com diferentes capacidades
5. **Dados de múltiplos ambientes**: robôs estáticos implantados em muitos lares diferentes
6. **Dados de Manipulação Móvel**: ~400 horas de demonstrações de robôs móveis

Essa mistura de treinamento diversificada cria um "currículo" que permite a generalização simultânea nos níveis físico, visual e semântico.

## Requisitos de instalação

1. Instale o LeRobot seguindo nosso [Guia de Instalação](./installation).
2. Instale as dependências do Pi0.5 executando:

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

   Se você instalou o LeRobot a partir do PyPI:

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

## Uso

Para usar π₀.₅ na sua configuração do LeRobot, especifique o tipo de política como:

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

## Treinamento

### Início rápido no LIBERO

Ajuste o modelo base do LIBERO em [lerobot/libero](https://huggingface.co/datasets/lerobot/libero), uma cópia codificada em vídeo de ~1,9 GB das demonstrações por trás dos [resultados abaixo](#libero-benchmark-results).

Ele contém as chaves que o π₀.₅ lê, que também são as produzidas pelo ambiente LIBERO no momento da avaliação:

| Recurso                     | Formato no conjunto de dados | Como o π₀.₅ o consome                                    |
| --------------------------- | -------------------- | ------------------------------------------------------- |
| `observation.images.image`  | 256×256×3, agentview | redimensionado para 224×224                                      |
| `observation.images.image2` | 256×256×3, pulso     | redimensionado para 224×224                                      |
| `observation.state`         | 8                    | discretizado em 256 bins e escrito no prompt   |
| `action`                    | 7                    | preenchido com zeros até 32 internamente; a perda usa as primeiras 7 dimensões |

**Não é necessário usar `--rename_map` aqui** — as chaves já correspondem; consulte [Rename Map and Empty Cameras](./rename_map) se as suas forem diferentes.

  π₀.₅ usa o tokenizer [google/paligemma-3b-pt-224](https://huggingface.co/google/paligemma-3b-pt-224) com licença restrita — aceite a licença no Hub e faça login com `hf auth login` antes do treinamento.

Dimensionado para uma única 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
```

**Normalização por média/desvio padrão, não o [padrão de quantil](#quantile-statistics) do π₀.₅** — correspondendo a [pi05_libero_finetuned_v044](https://huggingface.co/lerobot/pi05_libero_finetuned_v044), o checkpoint em que os resultados abaixo foram medidos.

**`--policy.n_action_steps=10` e `--policy.empty_cameras=1` são explícitos** porque `--policy.pretrained_path` carrega apenas os pesos — `lerobot/pi05_libero_base` armazena ambos, e, caso contrário, eles reverteriam para `50` e `0` (veja [Carregando um checkpoint](#loading-a-checkpoint)).

Em seguida, avalie um checkpoint com `lerobot-eval` e compare com as taxas de sucesso de referência — veja [LIBERO](./libero).

### Estatísticas de quantis

π₀.₅ normaliza `STATE` e `ACTION` com quantis, portanto o `meta/stats.json` do seu conjunto de dados precisa de `q01` e `q99`. Conjuntos de dados mais antigos contêm apenas `min`/`max`/`mean`/`std` e falham no primeiro lote:

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

Recalcule-os:

```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.

Ou mantenha o dataset como está e passe `--policy.normalization_mapping='{"ACTION": "MEAN_STD", "STATE": "MEAN_STD", "VISUAL": "IDENTITY"}'`.

Gravar, retomar e mesclar quantis agregados a partir de resumos por episódio, para que `meta/stats.json` acabe contendo um envelope conservador (`min` para `q <= 50`, `max` para `q > 50`) em vez de quantis do conjunto de dados inteiro. Para estimar estes últimos, percorra todos os episódios com um histograma incremental:

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

`--skip-images` mantém as estatísticas de imagem existentes e evita o download ou a decodificação de dados de vídeo quando apenas `STATE`/`ACTION` precisam ser recalculados, e `--root` lê um dataset local em vez do Hub. Esses valores são estimativas de histograma, sujeitas a erros de discretização e rebinning, portanto podem diferir dos conservadores — o que altera os alvos normalizados do π₀.₅ e, consequentemente, a escala de sua perda. Estatísticas já salvas dentro de um checkpoint existente não são afetadas.

### Exemplo de Comando de Treinamento

O mesmo finetune com o VLM congelado: menos memória, a um certo custo na taxa de sucesso. Substitua `--dataset.repo_id` pelo seu próprio dataset.

```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 Principais de Treinamento

- **`--policy.compile_model=true`**: Habilita a compilação do modelo para um treinamento mais rápido
- **`--policy.gradient_checkpointing=true`**: reduz significativamente o uso de memória durante o treinamento
- **`--policy.dtype=bfloat16`**: Use treinamento com precisão mista para eficiência
- **`--batch_size=64`**: Tamanho do lote para o treinamento, adapte com base na memória da sua GPU
- **`--policy.pretrained_path=lerobot/pi05_base`**: O modelo base π₀.₅ que você deseja fazer o finetuning. As opções são:
  - [lerobot/pi05_base](https://huggingface.co/lerobot/pi05_base)
  - [lerobot/pi05_libero_base](https://huggingface.co/lerobot/pi05_libero_base) (treinado especificamente no conjunto de dados Libero)
- **`--policy.optimizer_fused=true`**: Usa AdamW fundido para etapas de otimizador mais rápidas; essa flag é ignorada ao retomar uma execução

### RTC opcional em tempo de treinamento

Pi05 pode aprender opcionalmente condicionamento de prefixo de ação para [Real-Time Chunking](./rtc) eficiente, seguindo [Training-Time Action Conditioning for Efficient Real-Time Chunking](https://arxiv.org/abs/2512.05964). Defina `policy.rtc_training_max_delay` para o maior atraso de inferência esperado em passos do 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
```

O padrão é `0`, o que desativa o RTC durante o treinamento e mantém o objetivo padrão do Pi05 inalterado. O atraso configurado deve ser menor que `chunk_size`. Durante o treinamento, o Pi05 amostra um comprimento de prefixo limpo independentemente para cada exemplo e calcula a perda de fluxo apenas no sufixo restante.

Use o checkpoint resultante com o RTC treinado explicitamente:

```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
```

Defina `inference.rtc.execution_horizon` entre o `rtc_training_max_delay` do checkpoint e `chunk_size - rtc_training_max_delay`, e `inference.queue_threshold` para pelo menos `rtc_training_max_delay`. Um pico de latência isolado que ultrapasse o intervalo treinado descarta aquele chunk e tenta novamente; o rollout para com um erro explícito apenas se o atraso permanecer fora do intervalo. O padrão `--inference.rtc.mode=guided` continua disponível para checkpoints comuns.

### Carregando um checkpoint

As duas formas não são intercambiáveis:

|                                        | `--policy.path`                                | `--policy.pretrained_path`                |
| -------------------------------------- | ---------------------------------------------- | ----------------------------------------- |
| Carregamentos                                  | pesos **e** o `config.json` do checkpoint | somente pesos                              |
| Nomes de recursos                          | do checkpoint                            | do seu conjunto de dados, após `--rename_map`   |
| Configurações armazenadas, por exemplo, `n_action_steps` | herdado                                      | restaurar para os padrões                     |
| `--policy.type`                        | deve ser omitido                                | obrigatório                                  |
| `--rename_map`                         | necessário quando suas teclas de câmera diferem            | suportado para a normalização de chaves de conjuntos de dados |

Use `--rename_map` com qualquer forma de carregamento quando os nomes das features do dataset bruto diferem dos nomes das features da policy. Por exemplo, o comando de fine-tuning do RoboMME mapeia suas colunas brutas `image`, `wrist_image`, `state` e `actions` ao inicializar os pesos com `--policy.pretrained_path`.

### Parâmetros de Treinamento Explicados

| Parâmetro               | Padrão | Descrição                                 |
| ----------------------- | ------- | ------------------------------------------- |
| `freeze_vision_encoder` | `false` | Não congele o codificador de visão            |
| `train_expert_only`     | `false` | Não congele o VLM, treine todos os parâmetros |

**💡 Dica**: Definir `train_expert_only=true` congela o VLM e treina apenas o especialista de ação e as projeções, permitindo o ajuste fino com uso reduzido de memória.

## Memória de Observação de Curto Prazo (MEM)

Pi05 pode usar opcionalmente contexto visual e proprioceptivo de curto horizonte com base em [MEM](https://arxiv.org/abs/2603.03596). Ambos os caminhos estão desativados por padrão, de modo que os checkpoints e comandos de treinamento existentes mantêm o comportamento de quadro único do Pi05.

Isso implementa apenas a memória de curto prazo do MEM — o codificador de vídeo da seção III-C e a projeção proprioceptiva da seção III-D. A memória de longo prazo _linguística_ do MEM (seção III-B), na qual uma política de alto nível prevê o próximo subtarefa e um resumo em linguagem natural comprimido do que aconteceu até o momento, não está implementada. Nas ablações do artigo, a memória de vídeo sozinha recupera apenas parte do progresso de tarefa do MEM completo em tarefas de longo prazo.

Introduzir memória ao fazer fine-tuning a partir de um checkpoint pré-treinado sem ela também corresponde à ablação mais fraca do paper, `MEM-Posttrain-Only`. Os resultados principais do MEM vêm do pré-treinamento do codificador de vídeo em uma mistura diversificada de vídeos de robôs e não-robôs, o que nenhum checkpoint público do Pi05 atualmente fornece.

Ative-o durante o ajuste fino com:

```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` inclui a observação atual. `memory_stride` é medido em **frames do dataset**, não em segundos, portanto, escale-o com o `fps` do seu dataset: o pré-treino do MEM usa seis observações a um segundo de distância, o que corresponde a `memory_stride=30` para um dataset de 30 fps (o padrão), mas a `memory_stride=10` para um dataset de 10 fps, como o `lerobot/robomme`.

A cada quarta camada do SigLIP, a atenção é substituída pela atenção espaço-temporal composta do MEM: atenção temporal causal entre tokens de patch correspondentes, composta com a atenção espacial padrão e reutilizando as projeções pré-treinadas, de modo que nenhum parâmetro aprendível é adicionado à torre de visão. Os tokens de quadros anteriores são descartados assim que a última dessas camadas é executada, mantendo o comprimento do prefixo de linguagem/ação a jusante inalterado.

O histórico indisponível no início de um episódio é preenchido e mascarado. Na inferência, o Pi05 mantém internamente o mesmo histórico de imagens com passo e o limpa sempre que a política é reiniciada.

A propriocepção histórica é uma opção independente:

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

Quando habilitado, um token de estado contínuo projetado é adicionado para cada quadro retido, e o estado discretizado é removido do prompt de texto para que o estado seja representado exatamente uma vez (seção III-D de MEM). Isso altera o formato do prompt, portanto, habilite-o desde o início do treinamento, e não no meio do processo. A memória visual e a memória proprioceptiva usam as mesmas configurações de `memory_frames` e `memory_stride`, mas qualquer um dos caminhos pode ser habilitado de forma independente. Treine ou faça o ajuste fino com as opções de memória selecionadas; habilitá-las apenas na inferência não confere ao checkpoint de quadro único o comportamento de memória aprendido.

No PEFT, `proprio_history_proj` é treinado e salvo por completo via `modules_to_save`, pois não possui pesos pré-treinados para adaptar.

Na inferência, o MEM mantém uma única fila de histórico em lote e pressupõe que cada linha do lote compartilhe as fronteiras dos episódios. O `lerobot-eval` atende a isso chamando `policy.reset()` antes de cada rollout em lote e antes de redefinir o ambiente vetorial. A redefinição automática independente de linhas em um lote vetorial assíncrono não é suportada; inicie um novo rollout para que as filas completas de política e de ação sejam redefinidas juntas.

## Ações Relativas

Por padrão, o π₀.₅ prevê ações absolutas. Você pode habilitar **ações relativas** para que o modelo preveja deslocamentos em relação ao estado atual do robô. Isso pode melhorar a estabilidade do treinamento para certas configurações.

Para usar ações relativas, primeiro recalcule as estatísticas do seu conjunto de dados no espaço relativo via 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
```

Ou, equivalentemente, em 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()
```

O `chunk_size` deve corresponder ao `chunk_size` da sua política (padrão 50 para π₀.₅). `relative_exclude_joints` lista os nomes das juntas que devem permanecer no espaço absoluto (por exemplo, comandos do garra). Use `--push_to_hub true` para enviar as estatísticas atualizadas para o Hub.

Depois, treine com ações 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 Desempenho

### Resultados do Benchmark Libero

π₀.₅ demonstrou forte desempenho no conjunto de benchmarks Libero. Para comparar e testar sua implementação no LeRobot, refinamos o modelo base libero por mais 6k passos no conjunto de dados Libero e comparamos os resultados com os resultados de referência do OpenPI.

| Benchmark          | Implementação do LeRobot | Referência do OpenPI |
| ------------------ | ---------------------- | ---------------- |
| **Libero Spatial** | 97.0%                  | 98.8%            |
| **Objeto Libero**  | 99.0%                  | 98.2%            |
| **Objetivo do Libero**    | 98.0%                  | 98.0%            |
| **Libero 10**      | 96.0%                  | 92.4%            |
| **Média**        | 97.5%                  | 96.85%           |

Esses resultados demonstram as fortes capacidades de generalização do π₀.₅ em diversas tarefas de manipulação robótica. Para reproduzir esses resultados, você pode seguir as instruções na seção [Libero](https://huggingface.co/docs/lerobot/libero).

## Licença

Este modelo segue a **Apache 2.0 License**, em conformidade com o repositório original [OpenPI](https://github.com/Physical-Intelligence/openpi).

