# YAM

[YAM](https://doc.i2rt.com/products/yam) é um braço de 6-DOF da [I2RT Robotics](https://i2rt.com/) para aprendizado por imitação e IA incorporada. No LeRobot, `yam_follower` controla um braço YAM v1 padrão com o garra linear DM4310, e `bi_yam_follower` controla dois. Use-os com `lerobot-calibrate`, `lerobot-rollout` e `lerobot-replay`. O LeRobot ainda não possui um braço líder YAM, portanto um YAM é controlado por uma política ou pela reprodução de um dataset.

Monte e conecte os braços seguindo os guias da I2RT; esta página aborda a parte do LeRobot.

| Guia                                                           | O que ele abrange                                  |
| --------------------------------------------------------------- | ----------------------------------------------- |
| [Série YAM Arm](https://doc.i2rt.com/products/yam)             | Desembalagem, montagem, fiação, motores e pinças |
| [Configuração de software](https://doc.i2rt.com/getting-started/sw-setup) | Adaptadores CAN, taxa de transmissão e nomes de interface fixos |
| [Célula YAM](https://doc.i2rt.com/products/yam-cell)              | Estação bimanual com dois seguidores e líderes |

  <img
    src="https://doc.i2rt.com/images/yam-standard/YAM-ST-GP-1.webp"
    alt="YAM follower arm with the linear gripper"
    width="48%"
  />
  <img
    src="https://doc.i2rt.com/images/yam-station/DS-ST-1.webp"
    alt="YAM Cell bimanual station"
    width="48%"
  />

_Seguidor YAM (esquerda) e estação bimanual YAM Cell (direita). O LeRobot controla os seguidores. Imagens cortesia da I2RT Robotics._

## Hardware e segurança

Cada braço possui sete motores com IDs de 1 a 7: DM4340 para as juntas 1 a 3, e DM4310 para as juntas 4 a 6 e o garra. YAM Pro, Ultra, BIG YAM e as outras garras ainda não são suportados.

Você precisa de:

- Linux e um adaptador USB-CAN por braço (SocketCAN, CAN clássico a 1 Mbit/s).
- O timeout CAN de cada motor definido para no máximo 400 ms (`8000` ticks, valor do I2RT), por exemplo com `set_timeout.py --timeout` do [I2RT SDK](https://github.com/i2rt-robotics/i2rt). O timeout é a última salvaguarda caso o LeRobot pare de enviar comandos, portanto o LeRobot não habilitará o torque sem ele.
- Acesso à internet na primeira conexão: a compensação de gravidade baixa o modelo YAM do bucket [`lerobot/robot-urdfs`](https://huggingface.co/buckets/lerobot/robot-urdfs/tree/yam/v1) e o faz cache em `HF_LEROBOT_HOME/robot-urdfs/yam/v1`.

> [!WARNING]
> Fixe o braço em uma superfície estável e mantenha sua área de trabalho livre. A desconexão desativa o torque e o braço cai pela gravidade: apoie-o primeiro. Se a alimentação ou um adaptador CAN for desconectado durante a execução, pare o programa, apoie o braço e, em seguida, reconecte.

## Instale o LeRobot 🤗

Siga o [Guia de Instalação](./installation) e, em seguida, instale o suporte a YAM:

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

Isso instala `motorbridge` e `python-can` para o braço, e `placo` para a compensação de gravidade.

## Conecte o hardware

Cada braço precisa de sua própria interface CAN, pois ambos os braços usam os mesmos IDs de motor.

```bash
lerobot-setup-can --mode=setup --interfaces=can0 --use_fd=false
```

Use `--interfaces=can0,can1` para dois braços. O comando configura as interfaces Linux com `sudo ip link` e não envia comandos de motor. Com dois braços, `can0` e `can1` podem ser trocados após uma reinicialização: verifique qual braço cada interface controla, ou atribua nomes fixos, como `can_follower_l`, com o [software setup](https://doc.i2rt.com/getting-started/sw-setup) do I2RT, e use esses nomes como porta.

## Tipos de dispositivo

| Tipo              | Dispositivo            |
| ----------------- | ----------------- |
| `yam_follower`    | Seguidor único   |
| `bi_yam_follower` | Seguidor bimanual |

Com dois braços, defina as opções de cada braço com `--robot.left_arm_config.<option>` e `--robot.right_arm_config.<option>`.

## Calibração

A calibração mede apenas os limites do garrote, totalmente fechado e totalmente aberto: as juntas mantêm seus zeros de fábrica. Dobre o braço primeiro, conforme mostrado abaixo. O torque está desligado durante a medição: suporte o braço, mova apenas o garrote manualmente e pressione Enter em cada prompt. Se uma calibração já existir, a conexão inicia o controle: pressione Enter para reutilizá-la ou digite `c` para medir novamente, e o LeRobot pedirá que você suporte o braço antes de desligar o torque.

  <img
    src="https://doc.i2rt.com/images/yam-standard/YAM-ST-GP-2.webp"
    alt="YAM arm in its folded position"
    width="48%"
  />
  <img
    src="https://doc.i2rt.com/images/linear-gripper-4310/GP-4310-CTR-1.webp"
    alt="Linear DM4310 gripper"
    width="48%"
  />

_Posição dobrada, com todas as juntas em zero (esquerda), e o garrote linear DM4310 (direita). Imagens cortesia da I2RT Robotics._

```bash
lerobot-calibrate --robot.type=yam_follower --robot.port=can0 --robot.id=yam
```

O garfo esquerdo é medido primeiro, seguido pelo direito, nos arquivos `<id>_left` e `<id>_right`.

```bash
lerobot-calibrate --robot.type=bi_yam_follower --robot.id=bimanual_yam \
  --robot.left_arm_config.port=can0 --robot.right_arm_config.port=can1
```

Use o mesmo `--robot.id` nos comandos subsequentes para que o LeRobot carregue o arquivo salvo.

## Observações e ações

Um braço possui `joint_1.pos` até `joint_6.pos`, seguido de `gripper.pos`, tanto para observações quanto para ações. As juntas são ângulos absolutos em graus, e o manipulador varia de 0 (fechado) a 100 (aberto). `use_degrees=false` alterna para radianos e de 0 a 1, conforme usado nos dados de I2RT e MolmoAct2. `use_velocity_and_torque=true` adiciona observações de `.vel` e `.torque`. As ações são alvos absolutos das juntas, limitados aos limites das juntas.

Os dois braços usam os mesmos nomes com os prefixos `left_` e `right_`. As câmeras definidas em um braço também recebem prefixo, enquanto as `--robot.cameras` de nível superior mantêm seus nomes.

## Executar uma política

Coloque o braço na posição dobrada, com todas as articulações em zero, antes de conectar: o LeRobot verifica se cada articulação está dentro de 11,5° dessa posição e, em seguida, inicia o controle a partir da posição medida. Nada se move até que a política envie uma ação.

```bash
lerobot-rollout \
  --robot.type=yam_follower --robot.port=can0 --robot.id=yam \
  --robot.cameras='{"wrist": {"type": "opencv", "index_or_path": 0, "width": 640, "height": 480, "fps": 30}}' \
  --policy.path=<user>/<policy> \
  --task="Pick up the cube"
```

Para dois braços, use `--robot.type=bi_yam_follower --robot.id=bimanual_yam --robot.left_arm_config.port=can0 --robot.right_arm_config.port=can1`. Adicione `--dataset.repo_id=<user>/rollout_<name>` para gravar o rollout; consulte [Executar inferência e avaliar sua política](./il_robots#run-inference-and-evaluate-your-policy). `lerobot-replay` reproduz um episódio gravado com as mesmas opções `--robot.*`.

Antes da primeira ação, e quando nenhuma ação chega por `command_timeout_s` (1 s), o braço mantém sua posição. Com `idle_mode=float`, as juntas são compensadas pela gravidade e levemente amortecidas, permitindo que você mova o braço manualmente, enquanto o garrote mantém sua abertura; o rastreamento retoma de onde você o moveu.

## Segurança

- Uma falha no motor ou a ausência de feedback interrompe todos os comandos. Com dois braços, uma falha em qualquer um deles interrompe ambos. Desconecte e reconecte para continuar.
- O modelo de gravidade cobre o braço padrão sem câmeras ou cargas úteis. Após adicionar qualquer um deles, verifique se o braço não deriva no modo flutuante e ajuste `gravity_factors` se isso ocorrer.

## Opções de configuração

| Opção                    | Padrão                          | Descrição                                                |
| ------------------------- | -------------------------------- | ---------------------------------------------------------- |
| `port`                    | obrigatório                         | Interface SocketCAN, por exemplo `can0`                    |
| `use_degrees`             | `true`                           | Graus e um garra de 0 a 100; `false` fornece radianos e 0 a 1 |
| `use_velocity_and_torque` | `false`                          | Adicione as observações `.vel` e `.torque`                      |
| `idle_mode`               | `hold`                           | `hold` a posição ou `float` quando nenhuma ação chegar      |
| `command_timeout_s`       | `1.0`                            | Segundos sem uma ação antes do modo ocioso             |
| `initial_position_deg`    | todos zeros                        | Posição inicial obrigatória; `None` ignora a verificação          |
| `initial_tolerance_deg`   | `11.5`                           | Distância permitida a partir da posição inicial                 |
| `gripper_force_limit_n`   | `50.0`                           | Força dos dedos quando o garfo está bloqueado em um objeto      |
| `gravity_factors`         | `[1.0, 1.1, 1.1, 1.2, 1.0, 1.0]` | Multiplicadores por articulação da compensação da gravidade          |
| `cameras`                 | `{}`                             | Câmeras acopladas ao braço                                |

## Exemplo: MolmoAct2

[`lerobot/MolmoAct2-BimanualYAM-LeRobot`](https://huggingface.co/lerobot/MolmoAct2-BimanualYAM-LeRobot) é `allenai/MolmoAct2-BimanualYAM` no formato LeRobot, com suas estatísticas de normalização publicadas. Ele foi treinado em dois braços YAM com radianos e um gripper de 0–1, e com três câmeras na ordem superior, esquerda, direita; veja [MolmoAct2](./molmoact2).

```bash
pip install -e ".[yam,molmoact2,dataset]"

lerobot-rollout \
  --robot.type=bi_yam_follower --robot.id=bimanual_yam \
  --robot.left_arm_config.port=can0 --robot.right_arm_config.port=can1 \
  --robot.left_arm_config.use_degrees=false --robot.right_arm_config.use_degrees=false \
  --robot.cameras='{
    "top": {"type": "opencv", "index_or_path": "/dev/v4l/by-id/TOP_CAMERA", "width": 640, "height": 480, "fps": 30},
    "left": {"type": "opencv", "index_or_path": "/dev/v4l/by-id/LEFT_CAMERA", "width": 640, "height": 480, "fps": 30, "fourcc": "MJPG"},
    "right": {"type": "opencv", "index_or_path": "/dev/v4l/by-id/RIGHT_CAMERA", "width": 640, "height": 480, "fps": 30, "fourcc": "MJPG"}
  }' \
  --policy.path=lerobot/MolmoAct2-BimanualYAM-LeRobot \
  --inference.type=rtc --inference.rtc.execution_horizon=20 --inference.queue_threshold=20 \
  --device=cuda --interpolation_multiplier=2 \
  --interactive=true --play_sounds=false \
  --task="Pick up the red block and place it in the green bin"
```

Digite `/start` para executar a política, `/subtask <text>` para alterar a instrução, `/reset` para retornar à posição inicial e `/stop` para sair. O retorno dura um tempo fixo e o limite de velocidade do YAM ainda se aplica, portanto, um braço muito distante de sua posição inicial pode parar antes do tempo.

O modo Float permite iniciar a política a partir de qualquer posição: adicione `--robot.left_arm_config.idle_mode=float --robot.right_arm_config.idle_mode=float`. Antes do primeiro `/start` e 1 s após o término de um `/reset`, mova os braços manualmente para onde desejar e, em seguida, digite `/start` para executar a política a partir dali. Não use `/stop` para isso: ele encerra a sessão e desativa o torque.

## Solução de problemas

| Problema                                         | Verificar                                                                                                        |
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| A interface CAN está ausente ou desativada            | Verifique a alimentação do adaptador e o cabo USB, e `ip link show`. Execute `lerobot-setup-can` novamente.                  |
| `missing or stale motor feedback`               | Verifique a alimentação de 24 V, a fiação e a terminação do CAN, os IDs dos motores de 1 a 7 e se `port` é a interface deste braço. |
| O braço errado se move                             | Verifique qual braço cada interface controla ou atribua nomes fixos às interfaces.                                   |
| `unsafe motor CAN timeout`                      | Defina o tempo limite de CAN de cada motor para no máximo 400 ms com o SDK I2RT.                                           |
| `not within initial_tolerance_deg`              | Dobre o braço, com todas as articulações em zero, antes de conectar.                                                   |
| Conectar pede que você calibre novamente          | Use o mesmo `--robot.id` que durante a calibração.                                                             |
| O braço deriva no modo flutuante                    | Ajuste `gravity_factors` para as câmeras ou a carga no braço.                                              |
| MolmoAct2 move os braços para as posições erradas | Defina `use_degrees=false` em ambos os braços: o modelo usa radianos e um garra de 0–1.                              |

## Referências

- [Série YAM Arm](https://doc.i2rt.com/products/yam): hardware, motores e garras
- [Configuração de software](https://doc.i2rt.com/getting-started/sw-setup): taxa de bits do CAN e nomes de interface fixos
- [Célula YAM](https://doc.i2rt.com/products/yam-cell): estação bimanual
- [I2RT SDK](https://github.com/i2rt-robotics/i2rt): ferramentas de motor, modelo URDF e MuJoCo
- [Página do produto YAM](https://i2rt.com/products/yam-6-dof-arm)
- [MolmoAct2](./molmoact2): carregamento de política no LeRobot

