Contenido detallado
🧭 Por qué simular primero
Con el brazo real, cada intento tiene un costo: preparas la mesa, esperas el movimiento, desgastas los servos y corres el riesgo de tirar algo. En la simulación, la computadora calcula la física y ejecuta cientos de intentos mientras tomas un café. Por eso la regla del curso es sencilla: ningún plan ni política llega al brazo real sin pasar antes por la simulación.
🌱 ¿Eres nuevo aquí?
Un simulador de física es un programa que calcula, paso a paso, cómo se mueven y chocan los objetos con masa, fricción y motores. Un gemelo digital es una copia de un robot (y a veces de la sala) dentro del simulador, con las mismas medidas, articulaciones y límites que el real, para que lo que funciona en uno tenga posibilidades de funcionar en el otro.
Cómo leer: el embudo se estrecha de arriba hacia abajo. La franja ancha (simulación) filtra casi todos los errores de planificación y de código. La franja del medio (real, lentamente) detecta lo que la simulación no representa bien. Solo lo que pasa por ambas llega al uso normal.
✓ La simulación representa bien
- ✓El alcance del brazo y las colisiones con la mesa.
- ✓El orden de los pasos de un plan y los errores de lógica.
- ✓Generar muchas variaciones de posición para entrenar.
✗ La simulación suele representar mal
- ✗La fricción de la pinza y los objetos que se resbalan.
- ✗La holgura y el retraso de los servos económicos.
- ✗La luz, los reflejos y las texturas que ve la cámara.
Por qué aprender
Los robots con IA se equivocan de maneras impredecibles. La simulación es un lugar seguro para descubrir esos errores y también una fábrica de datos que reduce la cantidad de demostraciones que necesitas grabar a mano.
Conceptos clave
🦾 MuJoCo y el gemelo del SO-101
O MuJoCo es un simulador de física de código abierto y gratuito, mantenido por Google DeepMind, lo suficientemente ligero para ejecutarse en una laptop sin tarjeta gráfica dedicada. Su colección oficial de modelos, MuJoCo Menagerie, ya incluye el SO-101 listo, con las mismas 6 articulaciones que el brazo real. Lo instalas con pip y controlas todo con Python.
🌱 ¿Eres nuevo aquí?
MJCF es el archivo XML que describe el robot para MuJoCo: piezas, articulaciones, masas y motores (parecido al URDF de ROS, visto en el 4.2). El paso de física es el intervalo que avanza el simulador en cada cálculo; en el modelo del SO-101 es de 5 ms, así que 2 segundos simulados son 400 pasos.
Cómo leer: el recuadro del medio muestra la lista de articulaciones, igual en ambos lados. El mismo comando ("hombro a 0,6 rad") sirve para el brazo real y para el gemelo. Si el gemelo y el real llegan a lugares distintos con el mismo comando, acabas de medir la distancia sim2real del tema 5.
Objetivo: instalar MuJoCo en un entorno virtual, descargar solo el SO-101 de Menagerie y abrir el gemelo en una ventana 3D.
python3 -m venv .venv-sim
.venv-sim/bin/pip install mujoco numpy
# descarga solo la carpeta del SO-101 de la colección 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
# ventana 3D: arrastra para girar, haz doble clic en una pieza y usa Ctrl+arrastrar para empujar
.venv-sim/bin/python -m mujoco.viewer --mjcf=mujoco_menagerie/robotstudio_so101/scene.xml
Ahora el mismo gemelo controlado por código: envía dos articulaciones a una posición y mide dónde quedó la pinza.
# Gemelo del SO-101 en MuJoCo: carga el modelo, mueve las articulaciones y mide dónde quedó la pinza.
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} # radianes (0,6 rad = unos 34 grados)
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("error final de shoulder_pan:", round(erro, 4), "rad", "OK" if erro < 0.05 else "LEJOS DEL OBJETIVO")
Cómo verificar
- ✓.venv-sim/bin/python gemeo_so101.py enumera las 6 articulaciones y los 6 actuadores, de shoulder_pan a gripper.
- ✓En medio segundo, el pan llega a +0,600 rad y la pinza pasa de aproximadamente (+0,29; 0; +0,23) m a (+0,23; −0,13; +0,14) m. La última línea dice «OK».
- ✗¿Error de archivo no encontrado? Ejecuta el script en la carpeta donde está mujoco_menagerie, o pasa la ruta de scene.xml como argumento.
💡 Ver también: robotica-so101
El proyecto INEMA robotica-so101 lleva este gemelo más lejos: recoge un cubo, una pelota y un frasquito y los coloca en una bandeja (50 de 50 episodios en la simulación), graba con tres cámaras y ejecuta una prueba con medidas variadas antes de que se mueva el brazo real.
Por qué aprender
Con el gemelo pruebas el alcance, la posición de la cámara y la lógica del proyecto antes de imprimir una pieza. También es la forma de que todo el grupo trabaje con el brazo cuando la escuela tiene uno solo.
Conceptos clave
🖥️ Isaac Sim/Isaac Lab: cuándo conviene
O NVIDIA Isaac Sim es un simulador con imágenes casi fotográficas, sensores detallados e integración con ROS 2. El Isaac Lab, construido sobre él, ejecuta miles de copias del robot en paralelo en la GPU, lo que hace viable el aprendizaje por refuerzo (el robot aprende por ensayo y error, con una recompensa). El costo es el hardware: exige una tarjeta NVIDIA RTX con bastante memoria y una instalación mucho más pesada.
| Criterio | MuJoCo | Isaac Sim / Isaac Lab |
|---|---|---|
| Computadora | cualquier PC o laptop | GPU NVIDIA RTX con buena memoria |
| Instalación | pip install mujoco | grande, con requisitos de controladores |
| Imagen de la cámara | simple | casi fotográfica |
| Muchos robots en paralelo | sí (hay versiones para GPU) | miles, su punto fuerte |
| Ideal para | aprender, probar planes, generar episodios | refuerzo a gran escala, visión realista, humanoides |
✓ Conviene Isaac cuando
- ✓Tienes (o alquilas) una GPU RTX y vas a entrenar mediante aprendizaje por refuerzo.
- ✓La política depende mucho de la imagen y necesita escenas realistas.
- ✓El proyecto ya usa el ecosistema NVIDIA (Jetson, ROS 2).
✗ Quédate con MuJoCo cuando
- ✗La PC es de la escuela y no tiene tarjeta NVIDIA.
- ✗El objetivo es probar el plan, el alcance y la lógica.
- ✗El grupo todavía está aprendiendo qué es un gemelo.
💡 ¿Y Gazebo?
Gazebo (Trilha 4) es el simulador natural para un robot móvil con ROS 2, mapas y Nav2. Para un brazo con contacto preciso y generación de episodios para LeRobot, MuJoCo es más directo. En el proyecto final puedes usar ambos: Gazebo para la base y MuJoCo para el brazo.
Por qué aprender
Elegir el simulador según el problema, y no por su fama, ahorra semanas de instalación. La mayor parte de lo que hace este curso cabe en MuJoCo; Isaac entra cuando el proyecto requiere escala o imágenes realistas.
Conceptos clave
📷 Real2sim: una foto de la mesa se convierte en una escena
Armar una escena a mano (dónde está la caja, cuánto mide el cubo) lleva tiempo. Real2sim es el camino inverso de sim2real: partir del mundo real para construir la simulación. Un modelo de visión observa la foto de la mesa, estima los objetos, sus tamaños y posiciones en metros, y un programa construye la escena en MuJoCo. A partir de ella, la simulación genera episodios y pone a prueba el plan antes de que se mueva el brazo.
Cómo leer: la línea de arriba construye el mundo virtual; el recuadro de abajo es la puerta de entrada. El punto débil es la caja cian: el modelo de visión se equivoca al medir, así que la prueba varía los tamaños y las posiciones para no aprobar un plan que solo funciona con la medida perfecta.
Paso a paso con robotica-real2sim
Toma una foto con una hoja A4 sobre la mesa
La hoja sirve de escala. Toma 2 o 3 fotos desde distintos ángulos: las medidas son lo que más suele fallar.
Genera o escribe la escena
El proyecto usa un modelo de visión para leer la foto. Si no tienes uno, copia el ejemplo exemplos/mesa-teste/cena.json y completa las medidas con una cinta métrica.
Graba, genera episodios y prueba
Compara la grabación del gemelo con la foto. Solo después ejecuta la prueba del plan.
Objetivo: ejecutar el ejemplo listo del proyecto (con el brazo Franka Panda de la colección de MuJoCo) sin depender de ningún servicio externo.
git clone https://github.com/inematds/robotica-real2sim
cd robotica-real2sim
./instalar.sh # entorno virtual + MuJoCo + modelo del brazo + pruebas
# sin monitor (servidor, WSL): export MUJOCO_GL=egl (sin 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
Cómo verificar
- ✓ep.mp4 muestra al brazo recogiendo el cubo, con la fase escrita en pantalla, desde tres cámaras.
- ✓La generación termina con 50 de 50 episodios exitosos.
- ✓La primera prueba (sin espacios en la bandeja) resulta REPROBADA, aproximadamente 4 de 20: la pelota cae encima de la lata. La segunda, con un espacio por objeto, resulta APROBADA, aproximadamente 19 de 20.
Por qué aprender
El resultado de la prueba deja una lección: un plan que parecía obvio falló 16 veces de 20 y solo la simulación lo mostró, sin tirar nada al suelo. Construir la escena a partir de tu mesa es lo que convierte la simulación de una demostración bonita en una herramienta de verdad.
Conceptos clave
📏 Sim2real: la distancia entre lo simulado y lo real
Toda simulación es una aproximación. La diferencia entre lo que ocurre en el gemelo y en el brazo real tiene un nombre: distancia sim2real (en inglés, reality gap). Se debe a la fricción, la holgura y el retraso de los servos, la masa real de las piezas, y la luz y la textura que ve la cámara. No eliminas esa distancia; la mides y entrenas la política para que la tolere.
🌱 ¿Eres nuevo aquí?
Aleatorización de dominio consiste en sortear, en cada episodio simulado, valores un poco diferentes de fricción, masa, fuerza del motor, color y luz. La política que funciona en todas estas versiones "incorrectas" tiende a funcionar también en el mundo real, que es solo otra versión diferente.
Cómo leer: la curva verde (gemelo) sube limpiamente hasta el objetivo. La roja discontinua (real) empieza con retraso, se pasa del punto y se detiene con un pequeño error, algo típico de un servo barato con holgura. La franja azul es el conjunto de gemelos sorteados: si cubre la curva real, la política entrenada con ella ya "vio" algo parecido al mundo real.
Objetivo: ejecutar el mismo comando en 20 versiones del SO-101 con fricción, fuerza del servo y masa de la pinza sorteadas, y medir cuánto se dispersa la posición de la pinza.
# Aleatorización de dominio: el mismo comando, 20 brazos "un poco diferentes".
# Si el resultado se dispersa mucho, tu control depende de detalles que el mundo real no garantiza.
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) # fricción interna ±30%
model.actuator_gainprm[:, 0] *= rng.uniform(0.8, 1.2) # fuerza del servo ±20%
model.actuator_biasprm[:, 1] = -model.actuator_gainprm[:, 0] # mantiene coherente el servo de posición
model.body_mass[garra] = base.body_mass[garra] * rng.uniform(0.8, 1.5) # pinza más 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)): # solo 0,3 s: el brazo todavía está llegando
mujoco.mj_step(model, data)
finais.append(data.xpos[garra].copy())
finais = np.array(finais)
print("posición media de la pinza (m):", np.round(finais.mean(axis=0), 3))
print("dispersión (desviación, mm):", np.round(finais.std(axis=0) * 1000, 1))
Cómo verificar
- ✓Un resultado parecido a: posición media [0.244 -0. 0.2] y una dispersión de unos pocos milímetros (en la prueba, 0,4 mm en x y 2,5 mm en z).
- ✓Cambia 0,3 s por 2,0 s: la dispersión disminuye porque el servo de posición llega al objetivo en cualquier versión. La diferencia aparece en el recorrido, no al final.
- ✓Amplía los rangos (por ejemplo, masa de 0,5 a 3,0) y observa cómo crece la dispersión: ese es el tamaño de la incertidumbre que la política debe tolerar.
💡 La cinta métrica vale más que el modelo
En robotica-real2sim, cambiar el modelo de visión modificó el tipo de error de medición, pero no lo eliminó. Lo que lo resolvió fue medir la mesa con una cinta métrica y probar el plan en el peor caso (bandeja 15% más pequeña). La regla que queda es: solo pasa al brazo real lo que supera la prueba del peor caso plausible.
Por qué aprender
Quien ignora la distancia sim2real cree que la simulación "mintió" cuando falla el brazo real. Quien la mide sabe de antemano dónde fallará y ya entrenó para eso.
Conceptos clave
🧬 Generar datos sintéticos para entrenar
Grabar 50 demostraciones a mano cansa; generar 1.000 en la simulación lleva poco tiempo de computadora. Estos datos sintéticos aportan variedad (posiciones, tamaños, masas), y unos pocos episodios reales corrigen la física en la que se equivocó la simulación. La receta más usada hoy es la mezcla: muchos sintéticos + algunos reales.
Cómo leer: la cuadrícula verde de la izquierda (sintéticos) es mucho más grande que la línea azul (reales), pero ambos entran en el mismo entrenamiento. A la derecha están las tres políticas que comparas en el brazo real. Si "real + simulación" supera a "solo real" con los mismos episodios reales, el gemelo está ayudando.
Objetivo: generar episodios con cámaras en robotica-real2sim, exportarlos en el formato de LeRobot y entrenar una ACT directamente desde la carpeta local.
# dentro de la carpeta robotica-real2sim
./instalar.sh --lerobot # crea .venv-lerobot solo para el exportador
./r2s.py episodios exemplos/mesa-foto/cena.json sint/episodios -n 50 --imagens
./r2s.py exportar sint/episodios sint/lerobot
# entrenar leyendo la carpeta local (consulta las opciones con: 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
Cómo verificar
- ✓En la prueba del proyecto, la exportación generó 50 episodios, 4.361 cuadros a 10 cuadros por segundo, 9,7 MB, con las cámaras "cima" y "pulso".
- ✓El entrenamiento comienza y muestra cómo la loss va bajando, como en el 5.4.
- ✗Atención: en este ejemplo, el brazo simulado es un Franka Panda, con 7 articulaciones. Los datos solo sirven para el SO-101 después de cambiar el modelo de la escena por el gemelo del SO-101, que es el procedimiento del proyecto robotica-so101.
✓ Sintéticos bien hechos
- ✓Las mismas cámaras, nombres y articulaciones que el brazo real.
- ✓Solo episodios cuyo éxito confirmó la física.
- ✓Variación de posición, masa, luz y color.
✗ Sintéticos que estorban
- ✗Cámara en un ángulo diferente al del brazo real.
- ✗Todo perfecto e igual: la política se lo aprende de memoria.
- ✗Ningún episodio real para corregir la física.
Por qué aprender
Los datos son el cuello de botella de la robótica con IA. Saber generar datos en la simulación y demostrar, comparando tres versiones, que ayudan es la habilidad que distingue un proyecto de feria de uno que mejora en cada ronda.
Conceptos clave
✅ Resumen del módulo
Para profundizar
- MuJoCo — documentación y ejemplos en Python
- MuJoCo Menagerie — modelos listos para usar, incluido el SO-101
- NVIDIA Isaac — Isaac Sim e Isaac Lab, requisitos de hardware
- Documentación de LeRobot — formato del dataset y entrenamiento
- robotica-so101 (INEMA) e robotica-real2sim (INEMA) — gemelo del SO-101 y una foto de la mesa se convierte en simulación
Siguiente módulo
5.6 · Proyecto final: el robot asistente que escucha, planifica, ve y agarra, integrando todo lo aprendido en la Ruta 5.