Conteúdo detalhado
🧭 Por que simular antes
No braço real, cada tentativa custa: você arruma a mesa, espera o movimento, desgasta os servos e corre o risco de derrubar algo. Na simulação, o computador calcula a física e roda centenas de tentativas enquanto você toma um café. Por isso a regra do curso é simples: nenhum plano ou política vai ao braço real sem passar antes pela simulação.
🌱 Novo aqui?
Um simulador de física é um programa que calcula, passo a passo, como objetos com massa, atrito e motores se movem e se chocam. Um gêmeo digital é a cópia de um robô (e às vezes da sala) dentro do simulador, com as mesmas medidas, juntas e limites do real, para que o que funciona num tenha chance de funcionar no outro.
Como ler: o funil afunila de cima para baixo. A faixa larga (simulação) filtra quase todos os erros de plano e de código. A faixa do meio (real devagar) pega o que a simulação não representa bem. Só o que passa pelas duas chega ao uso normal.
✓ A simulação acerta bem
- ✓Alcance do braço e colisão com a mesa.
- ✓Ordem dos passos de um plano e erros de lógica.
- ✓Gerar muitas variações de posição para treino.
✗ A simulação costuma errar
- ✗Atrito da garra e objetos que escorregam.
- ✗Folga e atraso dos servos baratos.
- ✗Luz, reflexo e textura vistos pela câmera.
Por que aprender
Robôs com IA erram de jeitos imprevisíveis. A simulação é o lugar seguro para descobrir esses erros e também a fábrica de dados que reduz quantas demonstrações você precisa gravar à mão.
Conceitos-chave
🦾 MuJoCo e o gêmeo do SO-101
O MuJoCo é um simulador de física aberto e gratuito, mantido pelo Google DeepMind, leve o suficiente para rodar num notebook sem placa de vídeo dedicada. A coleção oficial de modelos dele, o MuJoCo Menagerie, já traz o SO-101 pronto, com as mesmas 6 juntas do braço real. Você instala com pip e controla tudo em Python.
🌱 Novo aqui?
MJCF é o arquivo XML que descreve o robô para o MuJoCo: peças, juntas, massas e motores (parecido com o URDF do ROS, visto no 4.2). O passo de física é o intervalo que o simulador avança a cada cálculo; no modelo do SO-101 são 5 ms, então 2 segundos simulados são 400 passos.
Como ler: a caixa do meio é a lista de juntas, igual nos dois lados. O mesmo comando ("ombro a 0,6 rad") vale para o braço real e para o gêmeo. Se o gêmeo e o real chegam a lugares diferentes com o mesmo comando, você acabou de medir a distância sim2real do tópico 5.
Objetivo: instalar o MuJoCo num ambiente virtual, baixar só o SO-101 do Menagerie e abrir o gêmeo numa janela 3D.
python3 -m venv .venv-sim
.venv-sim/bin/pip install mujoco numpy
# baixa só a pasta do SO-101 da coleção oficial de modelos
git clone --depth 1 --filter=blob:none --sparse \
https://github.com/google-deepmind/mujoco_menagerie.git
git -C mujoco_menagerie sparse-checkout set robotstudio_so101
# janela 3D: arraste para girar, clique duplo numa peça e Ctrl+arrastar para empurrar
.venv-sim/bin/python -m mujoco.viewer --mjcf=mujoco_menagerie/robotstudio_so101/scene.xml
Agora o mesmo gêmeo controlado por código: mandar duas juntas para uma posição e medir onde a garra parou.
# Gêmeo do SO-101 no MuJoCo: carrega o modelo, move juntas e mede onde a garra foi parar.
import sys
import mujoco
CENA = sys.argv[1] if len(sys.argv) > 1 else "mujoco_menagerie/robotstudio_so101/scene.xml"
model = mujoco.MjModel.from_xml_path(CENA)
data = mujoco.MjData(model)
print("juntas:", [model.joint(i).name for i in range(model.njnt)])
print("atuadores:", [model.actuator(i).name for i in range(model.nu)])
mujoco.mj_resetData(model, data)
alvo = {"shoulder_pan": 0.6, "elbow_flex": 0.5} # radianos (0,6 rad = uns 34 graus)
for nome, valor in alvo.items():
data.ctrl[model.actuator(nome).id] = valor
garra = model.body("gripper").id
for passo in range(int(2.0 / model.opt.timestep)): # 2 segundos de física
mujoco.mj_step(model, data)
if passo % int(0.5 / model.opt.timestep) == 0:
x, y, z = data.xpos[garra]
pan = data.qpos[model.joint("shoulder_pan").qposadr[0]]
print(f"t={data.time:4.1f}s pan={pan:+.3f} rad garra=({x:+.3f}, {y:+.3f}, {z:+.3f}) m")
erro = abs(data.qpos[model.joint("shoulder_pan").qposadr[0]] - alvo["shoulder_pan"])
print("erro final do shoulder_pan:", round(erro, 4), "rad", "OK" if erro < 0.05 else "LONGE DO ALVO")
Como verificar
- ✓.venv-sim/bin/python gemeo_so101.py lista as 6 juntas e os 6 atuadores, de shoulder_pan a gripper.
- ✓Em meio segundo o pan chega a +0,600 rad e a garra sai de cerca de (+0,29; 0; +0,23) m para (+0,23; −0,13; +0,14) m. A última linha diz "OK".
- ✗Erro de arquivo não encontrado? Rode o script na pasta onde está mujoco_menagerie, ou passe o caminho do scene.xml como argumento.
💡 Veja também: robotica-so101
O projeto INEMA robotica-so101 leva este gêmeo mais longe: pega cubo, bola e potinho e os põe numa bandeja (50 de 50 episódios na simulação), filma por três câmeras e roda uma prova com medidas variadas antes de o braço real se mexer.
Por que aprender
Com o gêmeo você testa alcance, posição da câmera e lógica do projeto antes de imprimir uma peça. É também a forma de a turma inteira trabalhar no braço quando a escola tem um só.
Conceitos-chave
🖥️ Isaac Sim/Isaac Lab: quando vale
O NVIDIA Isaac Sim é um simulador com imagem quase fotográfica, sensores detalhados e integração com ROS 2. O Isaac Lab, construído sobre ele, roda milhares de cópias do robô em paralelo na GPU, o que torna viável o aprendizado por reforço (o robô aprende por tentativa e erro, com recompensa). O preço é o hardware: exige placa NVIDIA RTX com bastante memória e uma instalação bem mais pesada.
| Critério | MuJoCo | Isaac Sim / Isaac Lab |
|---|---|---|
| Computador | qualquer PC ou notebook | GPU NVIDIA RTX com boa memória |
| Instalação | pip install mujoco | grande, com requisitos de driver |
| Imagem da câmera | simples | quase fotográfica |
| Muitos robôs em paralelo | sim (há versões em GPU) | milhares, ponto forte |
| Melhor para | aprender, testar planos, gerar episódios | reforço em escala, visão realista, humanoides |
✓ Vale o Isaac quando
- ✓Você tem (ou aluga) GPU RTX e vai treinar por reforço.
- ✓A política depende muito da imagem e precisa de cenas realistas.
- ✓O projeto já usa o ecossistema NVIDIA (Jetson, ROS 2).
✗ Fique no MuJoCo quando
- ✗O PC é de escola, sem placa NVIDIA.
- ✗O objetivo é testar plano, alcance e lógica.
- ✗A turma ainda está aprendendo o que é um gêmeo.
💡 E o Gazebo?
O Gazebo (Trilha 4) é o simulador natural para robô móvel com ROS 2, mapas e Nav2. Para braço com contato fino e geração de episódios para o LeRobot, o MuJoCo é mais direto. No projeto final você pode usar os dois: Gazebo para a base, MuJoCo para o braço.
Por que aprender
Escolher o simulador pelo problema, e não pela fama, economiza semanas de instalação. A maior parte do que este curso faz cabe no MuJoCo; o Isaac entra quando o projeto pede escala ou imagem realista.
Conceitos-chave
📷 Real2sim: foto da mesa vira cena
Montar uma cena à mão (onde está a caixa, quanto mede o cubo) dá trabalho. Real2sim é o caminho inverso do sim2real: partir do mundo real para montar a simulação. Um modelo de visão olha a foto da mesa, estima objetos, tamanhos e posições em metros, e um programa monta a cena no MuJoCo. A partir dela, a simulação gera episódios e prova o plano antes do braço se mexer.
Como ler: a linha de cima monta o mundo virtual; a caixa de baixo é o portão. O ponto fraco é a caixa ciano: o modelo de visão erra medidas, então a prova varia os tamanhos e posições para não aprovar um plano que só funciona na medida perfeita.
Passo a passo com o robotica-real2sim
Fotografe com uma folha A4 na mesa
A folha dá a escala. Tire 2 ou 3 fotos de ângulos diferentes: a medida é o que mais erra.
Gere ou escreva a cena
O projeto usa um modelo de visão para ler a foto. Sem ele, copie o exemplo exemplos/mesa-teste/cena.json e preencha as medidas com uma trena.
Filme, gere episódios e prove
Compare o filme do gêmeo com a foto. Só depois rode a prova do plano.
Objetivo: rodar o exemplo pronto do projeto (com o braço Franka Panda da coleção do MuJoCo) sem depender de nenhum serviço externo.
git clone https://github.com/inematds/robotica-real2sim
cd robotica-real2sim
./instalar.sh # venv + MuJoCo + modelo do braço + testes
# sem monitor (servidor, WSL): export MUJOCO_GL=egl (sem GPU: osmesa)
./r2s.py filmar exemplos/mesa-teste/cena.json ep.mp4 --cameras geral,cima,pulso
./r2s.py episodios exemplos/mesa-teste/cena.json saida/ -n 50
./r2s.py provar exemplos/mesa-foto/cena.json resultados/mesa-foto/plano.json --sem-vagas
./r2s.py provar exemplos/mesa-foto/cena.json resultados/mesa-foto/plano.json
Como verificar
- ✓ep.mp4 mostra o braço pegando o cubo, com a fase escrita na tela, por três câmeras.
- ✓A geração termina com 50 de 50 episódios bem-sucedidos.
- ✓A primeira prova (sem vagas na bandeja) sai REPROVADO, cerca de 4 em 20: a bola cai em cima da lata. A segunda, com uma vaga por objeto, sai APROVADO, cerca de 19 em 20.
Por que aprender
O resultado da prova é a lição: um plano que parecia óbvio falhou 16 vezes em 20 e só a simulação mostrou isso, sem derrubar nada. Montar a cena a partir da sua mesa é o que transforma a simulação de demonstração bonita em ferramenta de verdade.
Conceitos-chave
📏 Sim2real: a distância entre simulado e real
Toda simulação é uma aproximação. A diferença entre o que acontece no gêmeo e no braço real tem nome: distância sim2real (em inglês, reality gap). Ela vem de atrito, folga e atraso dos servos, massa real das peças, luz e textura que a câmera vê. Você não elimina essa distância; você a mede e treina a política para aguentá-la.
🌱 Novo aqui?
Randomização de domínio é sortear, a cada episódio simulado, valores um pouco diferentes de atrito, massa, força do motor, cor e luz. A política que funciona em todas essas versões "erradas" tende a funcionar também no real, que é só mais uma versão diferente.
Como ler: a curva verde (gêmeo) sobe limpa até o alvo. A vermelha tracejada (real) começa atrasada, passa do ponto e para com um pequeno erro, típico de servo barato com folga. A faixa azul é o conjunto de gêmeos sorteados: se ela cobre a curva real, a política treinada nela já "viu" algo parecido com o real.
Objetivo: rodar o mesmo comando em 20 versões do SO-101 com atrito, força do servo e massa da garra sorteados, e medir quanto a posição da garra se espalha.
# Randomização de domínio: o mesmo comando, 20 braços "um pouco diferentes".
# Se o resultado espalha muito, o seu controle depende de detalhes que o real não garante.
import sys
import numpy as np
import mujoco
CENA = sys.argv[1] if len(sys.argv) > 1 else "mujoco_menagerie/robotstudio_so101/scene.xml"
base = mujoco.MjModel.from_xml_path(CENA)
rng = np.random.default_rng(42)
garra = base.body("gripper").id
finais = []
for k in range(20):
model = mujoco.MjModel.from_xml_path(CENA)
model.dof_damping[:] = base.dof_damping * rng.uniform(0.7, 1.3) # atrito interno ±30%
model.actuator_gainprm[:, 0] *= rng.uniform(0.8, 1.2) # força do servo ±20%
model.actuator_biasprm[:, 1] = -model.actuator_gainprm[:, 0] # mantém o servo de posição coerente
model.body_mass[garra] = base.body_mass[garra] * rng.uniform(0.8, 1.5) # garra mais pesada
data = mujoco.MjData(model)
data.ctrl[model.actuator("shoulder_lift").id] = -0.4
data.ctrl[model.actuator("elbow_flex").id] = 0.6
for _ in range(int(0.3 / model.opt.timestep)): # só 0,3 s: o braço ainda está chegando
mujoco.mj_step(model, data)
finais.append(data.xpos[garra].copy())
finais = np.array(finais)
print("posição média da garra (m):", np.round(finais.mean(axis=0), 3))
print("espalhamento (desvio, mm):", np.round(finais.std(axis=0) * 1000, 1))
Como verificar
- ✓Saída parecida com: posição média [0.244 -0. 0.2] e espalhamento de poucos milímetros (no teste, 0,4 mm em x e 2,5 mm em z).
- ✓Troque 0,3 s por 2,0 s: o espalhamento cai, porque o servo de posição chega ao alvo em qualquer versão. A diferença aparece no caminho, não no fim.
- ✓Aumente as faixas (por exemplo, massa 0,5 a 3,0) e veja o espalhamento crescer: esse é o tamanho da incerteza que a política precisa aguentar.
💡 A trena vale mais que o modelo
No robotica-real2sim, trocar o modelo de visão mudou o tipo de erro de medida, mas não acabou com ele. O que resolveu foi medir a mesa com trena e provar o plano no pior caso (bandeja 15% menor). Regra que fica: só vai ao braço real o que passa no pior caso plausível.
Por que aprender
Quem ignora a distância sim2real acha que a simulação "mentiu" quando o braço real falha. Quem a mede sabe antes onde vai falhar e já treinou para isso.
Conceitos-chave
🧬 Gerar dados sintéticos para treinar
Gravar 50 demonstrações à mão cansa; gerar 1.000 na simulação leva pouco tempo de computador. Esses dados sintéticos dão variedade (posições, tamanhos, massas), e poucos episódios reais corrigem a física que a simulação errou. A receita mais usada hoje é a mistura: muitos sintéticos + alguns reais.
Como ler: a grade verde à esquerda (sintéticos) é muito maior que a linha azul (reais), mas os dois entram no mesmo treino. À direita estão as três políticas que você compara no braço real. Se "real + simulação" vencer "só real" com os mesmos episódios reais, o gêmeo está ajudando.
Objetivo: gerar episódios com câmeras no robotica-real2sim, exportar no formato do LeRobot e treinar uma ACT direto da pasta local.
# dentro da pasta robotica-real2sim
./instalar.sh --lerobot # cria .venv-lerobot só para o exportador
./r2s.py episodios exemplos/mesa-foto/cena.json sint/episodios -n 50 --imagens
./r2s.py exportar sint/episodios sint/lerobot
# treinar lendo a pasta local (confira as flags com: lerobot-train --help)
.venv-lerobot/bin/lerobot-train \
--dataset.repo_id=local/real2sim --dataset.root=sint/lerobot \
--policy.type=act --policy.device=cuda \
--output_dir=outputs/train/act-sint --policy.push_to_hub=false
Como verificar
- ✓No teste do projeto, a exportação gerou 50 episódios, 4.361 quadros a 10 quadros por segundo, 9,7 MB, com as câmeras "cima" e "pulso".
- ✓O treino começa e mostra a loss caindo, como no 5.4.
- ✗Atenção: nesse exemplo o braço simulado é um Franka Panda, com 7 juntas. O dado só serve ao SO-101 depois de trocar o modelo da cena pelo gêmeo do SO-101, que é o roteiro do projeto robotica-so101.
✓ Sintético bem feito
- ✓Mesmas câmeras, nomes e juntas do braço real.
- ✓Só episódios com sucesso conferido pela física.
- ✓Variação de posição, massa, luz e cor.
✗ Sintético que atrapalha
- ✗Câmera em outro ângulo que a do real.
- ✗Tudo perfeito e igual: a política decora.
- ✗Nenhum episódio real para corrigir a física.
Por que aprender
Dado é o gargalo da robótica com IA. Saber fabricar dados na simulação, e provar com a comparação de três versões que eles ajudam, é a habilidade que separa um projeto de feira de um projeto que melhora a cada rodada.
Conceitos-chave
✅ Resumo do módulo
Para ir além
- MuJoCo — documentação e exemplos em Python
- MuJoCo Menagerie — modelos prontos, incluindo o SO-101
- NVIDIA Isaac — Isaac Sim e Isaac Lab, requisitos de hardware
- Documentação do LeRobot — formato do dataset e treino
- robotica-so101 (INEMA) e robotica-real2sim (INEMA) — gêmeo do SO-101 e foto da mesa vira simulação
Próximo módulo
5.6 · Projeto final: o robô assistente que ouve, planeja, enxerga e pega, juntando tudo da Trilha 5.