Sim Env Builder (Creador de Entornos de Simulación)
Objetivo: a partir de una descripción, entregar un entorno de simulación funcional, físicamente sólido y de buen aspecto en la menor cantidad de interacciones posible (idealmente: petición -> una confirmación -> terminado). Estándar de calidad: todas las pruebas de humo pasan, has MIRADO los renders y coinciden con la solicitud.
SKILL_DIR a continuación = el directorio de este archivo. Los ayudantes de Python viven en SKILL_DIR/scripts/simkit.
Fase 0 - Configuración (1 minuto)
PY=$(bash SKILL_DIR/scripts/setup_env.sh) # python con mujoco, trimesh, usd-core, gymnasium
$PY SKILL_DIR/scripts/check_platform.py # SO, GPU, disponibilidad de Isaac
Elegir la carpeta del entorno: ./<nombre_corto_snake_case>/ en el directorio actual a menos que el usuario haya nombrado una.
Fase 1 - Elegir el backend (leer reference/backend_choice.md)
Isaac Sim necesita una GPU NVIDIA RTX en Linux/Windows. MuJoCo funciona en cualquier lugar.
- MuJoCo: por defecto. Manipulación y locomoción con contacto intensivo, iteración rápida, CPU/portátil/macOS, escenas pequeñas a medianas, control basado en modelos, investigación reproducible, MJX/Warp para GPU RL.
- Isaac Sim: renderizado fotorrealista RTX o datos sintéticos (Replicator), realismo de sensores RTX lidar/cámara, miles de entornos paralelos en Isaac Lab, escenas grandes de USD/Omniverse, el usuario ya está en Isaac.
- Si Isaac es la mejor opción pero
isaac_runnable_herees falso, dilo en la confirmación y ofrece: construir + probar completamente en MuJoCo aquí Y exportar una escena USD + script de prueba de Isaac para la máquina GPU (reference/isaac.md). Nunca afirmes resultados de Isaac que no hayas ejecutado.
Fase 2 - Confirmar con el usuario ANTES de construir (reference/confirmation.md)
- Primero haz un escaneo rápido de activos para que el resumen sea concreto: una llamada
find_assets(polypizza MCP) que enumere cada rol de objeto, 1-3 consultas cada uno. - Envía UN resumen breve (plantilla en reference/confirmation.md): backend + por qué, qué habrá en la escena, el robot/agente y su interfaz de control, qué activos vienen de Poly Pizza vs procedimental, física clave (gravedad, fricción, paso de tiempo), entregables, y 2-4 preguntas que cada una lleve tu recomendación predeterminada.
- Pregunta con AskUserQuestion si esa herramienta existe. De lo contrario, termina tu turno con el resumen como tu mensaje y espera. No construyas antes de que el usuario responda. Excepción: el usuario dijo que no preguntes / "solo constrúyelo" -> escribe las suposiciones en SPEC.md, procede.
- Registra las decisiones confirmadas en
<env>/SPEC.md(plantilla en reference/confirmation.md).
Fase 3 - Activos: Poly Pizza primero, fallback procedimental (reference/assets.md)
Para cada rol de objeto:
find_assets/search_models-> lee el veredicto (encontrado / débil / no_encontrado).- encontrado o débil ->
preview_models([...ids])y MIRA: ¿objeto correcto? ¿estilo consistente? rechaza juguetes, caricaturas en escenas realistas, paquetes de múltiples objetos, clase de escala incorrecta. - Aceptar ->
download_model(id, "<ruta_abs_env>/assets/polypizza", "<rol>")(los créditos se registran automáticamente enassets/polypizza/CREDITS.md). - no_encontrado, rechazado o error de descarga -> procedimental: recetas de
simkit.procedural(árboles, edificios, muebles, accesorios de calle, puertas, vajilla, terreno...) o compón las tuyas propias a partir de primitivas /lathe/extrude/rock. Nunca dejes fuera un objeto solicitado. - Escribe
<env>/assets/ASSETS.md: rol | fuente (id de Poly Pizza + título + licencia, o receta procedimental) | tamaño real | por qué. Si el título de un modelo difiere del rol ("Banco de Parque" usado como una mesa de picnic), dilo y explica por qué aún encaja - o busca de nuevo / ve a procedimental. También enumera los candidatos RECHAZADOS (id + razón: "estilo caricatura", "paquete de 12 objetos") para que la búsqueda sea rastreable incluso cuando todo termine siendo procedimental. Los modelos de Poly Pizza son mallas estáticas: los robots articulados y vehículos provienen desimkit.robots(puedes recubrirlos con una malla de Poly Pizza como geoms visuales).
Fase 4 - Construir (reference/robots.md, templates/)
mkdir -p <env> && cp -r SKILL_DIR/scripts/simkit <env>/simkit # vendido: el entorno es autocontenido
cp SKILL_DIR/templates/build_env.py SKILL_DIR/templates/env.py SKILL_DIR/templates/view.py <env>/ # edita los dos primeros
build_env.pyregenera todo determinísticamente (con semilla) ->scene.xml. Usasimkit.scene.Scene(cielo, suelo, luces, cámaras de observación, secciones para MJCF crudo),simkit.assets.glb_to_mujoco(glb, env, name, target={"height": m}, yaw_deg=..)para modelos de Poly Pizza (tamaño del mundo real, Z hacia arriba, partes por color, colisión de caja/casco/partes),simkit.proceduralpara fallbacks y terreno,simkit.robotspara robots probados (quadrotor, coche, diff_drive, brazo- pinza, cuadrúpedo) y sus controladores.
- La escala del mundo real es obligatoria (tabla de tamaños en reference/assets.md). Las cosas descansan sobre su soporte.
- Cada clase de objeto que el usuario nombró debe ser claramente visible a un tamaño legible en la vista general
(un "sendero rocoso" necesita rocas que se puedan ver, no motas de 7 cm; "terreno accidentado" necesita bultos visibles
a escala de robot). La prueba de humo enumera las motas bajo
hints. - Al menos 2 cámaras con nombre: una general y una enfocada en el sujeto (el robot/objeto de la tarea llena aproximadamente el 30-50% del encuadre; montada en el robot si la hay). Las cámaras de sensor fijas no deben ser bloqueadas por la pose inicial del robot (el humo marca > 15% de cobertura).
world.py(cuando la escena tiene su propia dinámica):make_world(model)->world(model, data), llamado ANTES de cada paso de física por el humo, examinador, showcase, env.py, view.py y el panel. Flotabilidad/arrastre, viento, cintas transportadoras, ciclos de semáforos, peatones programados y NPC en coches viven aquí, nunca dentro de controller.py (una prueba pasiva o una política de RL ejecutarían un mundo donde los barcos se hunden y las luces nunca cambian). Las comprobaciones de tareas que avanzan la simulación también deben llamarlo.controller.py: una política de demostración programada (make_controller(model)->ctrl(model, data)) que muestra el entorno haciendo su trabajo (el dron vuela las puertas, el coche conduce la ruta, el brazo alcanza el objeto...). EstableceDEMO_SECONDS = <duración de la demostración completa>a nivel de módulo: la prueba de humo luego filma y comprueba TODA la demostración (recoger, levantar, colocar / cada puerta), no solo los primeros 4 segundos.task_checks.py: funcionescheck_<nombre>(model, data) -> {"status", "value", "expect", "details"}para la física a nivel de tarea. Una comprobación por cada criterio de éxito que el usuario haya indicado o confirmado (nómbralo después de sus palabras: "pies en contacto" ->check_feet_in_contact), más la cordura de generación (el robot comienza en su soporte). Al menos 2. Escribe los umbrales Y la definición exacta de cada métrica (punto de referencia, unidades: "centro de la base del rover al centro del aterrizador, metros") en SPEC.md ANTES de la primera ejecución y mantenlas: un fallo por poco significa arreglar el controlador/escena, nunca aflojar la comprobación (cualquier cambio de umbral debe aparecer bajo "Cambios del plan confirmado"). Una comprobación que pasa dentro del 15% de su límite se informa con su margen ("inclinación 25.8 grados vs límite 30 grados"). Cualquier comportamiento que afirmes (desaceleración por obstáculo, ciclo de semáforo, flotabilidad, sujeción de pinza) necesita una comprobación que lo ejercite, p.ej., coloca un obstáculo en el camino y afirma que el robot se detiene. Cada propiedad física clave de la escena obtiene una comprobación medida con un objetivo físico: la desaceleración de rodadura de una pelota, la línea de flotación de un barco, la escalada de pendiente de un rover, el tiempo de caída con baja gravedad, la fuerza de sujeción de la pinza. Un sensor requerido también obtiene una comprobación: renderiza la cámara del robot durante la demo y afirma una imagen no en blanco que muestre la tarea (p.ej., filas de árboles adelante); para lidar, afirma rangos sensatos. Ejecuta cada comprobación de tarea en el rollout programado Y en 2-3 perturbados (otra semilla, pose inicial, velocidad inicial, fase de luz) - una comprobación que solo se cumple para un rollout exacto prueba poco. Las comprobaciones de agarre requieren contacto entre AMBAS almohadillas de los dedos y el objeto durante la elevación y el transporte (leedata.contact), no solo "el objeto subió".- Colisionadores: simples y honestos. Árboles: colisionador de tronco, dosel solo visual a menos que el usuario quiera
impactos en el dosel. Multirotores: cápsulas de brazo o un casco, no una caja que se trague las hélices.
Accesorios no convexos (microscopio, silla, arco, estante) obtienen
collision="parts"o unas pocas primitivas; un casco convexo a su alrededor bloquea espacio que está visiblemente vacío (revisa collision_sheet.png). env.py: Gymnasium-stylereset/step/rendercon observación de tarea, recompensa preliminar, terminación. Su__main__autotest impulsa el entorno A TRAVÉS de la API del entorno con el controlador de demostración (o una política de referencia) e imprime si se alcanzó el objetivo de la tarea - prueba de que el objetivo es alcanzable.- Cuerpos y marcadores de depuración/rig de cámara: grupo de geom 4-5 (nunca renderizado), no en las cámaras de datos.
- Cosas suspendidas (luces de techo, carteles colgantes, estantes de pared): nómbralos
mounted_*ohanging_*para que la comprobación de objeto flotante los omita. - Iluminación: blanco neutro (sin luces teñidas); como máximo 2-3 luces extra; comprueba que una pared blanca se mantenga blanca-gris en los renders.
- Sin decoración no solicitada más allá de lo que hace que la escena se lea correctamente; enumera los extras opcionales en el resumen para que el usuario pueda optar por ellos.
- Tiempo límite: anota la hora cuando empieces a construir (
date). Los elementos extra/ampliados ("plegar es un extra") vienen solo después de que todo lo imprescindible pase, y se dejan caer primero. Alrededor de 60 minutos después de la construcción, deja de ajustar lo que quede: haz que REPORT.md y README sean los resultados finales e informa (elementos eliminados enumerados). Una construcción que nunca informa es peor que una con una brecha conocida. - Presupuesto: una vez que todo lo imprescindible existe y todas las comprobaciones pasan, deja de añadir extras - termina la comprobación visual, README y el informe. Los extras van en el README como ideas.
- Ejecuta
$PY build_env.pydespués de cada cambio; los errores de compilación llevan números de línea.
Fase 5 - Pruebas de humo (reference/smoke_tests.md). Las tres son obligatorias.
cd <env> && $PY -m simkit.smoke scene.xml --out smoke --controller controller.py --task-checks task_checks.py
- Prueba de renderizado - cada cámara con nombre + vistas automáticas renderizan fotogramas no en blanco, iluminados y detallados; la segmentación muestra qué objetos son visibles (los objetos no vistos se marcan).
- Examinador de física - sondas de solucionador/contactos/fricción/gravedad con la configuración propia de la escena, estabilidad de rollout, penetración, caída, asentamiento, respuestas de paso del actuador, determinismo, sensibilidad al paso de tiempo, factor de tiempo real, diseño (accesorios flotantes / hundidos / interpenetrados), más tus comprobaciones de tarea.
- Comprobación visual - DEBES abrir y mirar
smoke/contact_sheet.png,smoke/filmstrip.png,smoke/collision_sheet.pngy los primeros planos ensmoke/renders/(herramienta Leer), luego llenar la lista de verificación ensmoke/visual_check.mdcon observaciones concretas. Arregla cada FALLO. Investiga cada ADVERTENCIA (arréglalo, o explica en README por qué es esperado). Vuelve a construir y vuelve a ejecutar hasta que el veredicto sea APROBADO / APROBADO_CON_ADVERTENCIAS-explicado Y la comprobación visual sea honestamente todo "sí". Espera 2-3 iteraciones; el primer render rara vez es correcto. También ejecuta$PY env.py(acciones aleatorias, observaciones finitas).
Fase 6 - Entregable de Isaac Sim (solo si se eligió Isaac; reference/isaac.md)
$PY -m simkit.usd_export scene.xml isaac/scene.usda (exportación + validación local), copia
SKILL_DIR/templates/isaac_smoke.py a isaac/, documenta cómo ejecutarlo en la máquina GPU.
Indica claramente qué se ejecutó y qué no.
Fase 7 - Entrega
<env>/README.md: qué hay en la escena, cómo ejecutar (construir, humo, entorno, visor:
$PY view.py, que ejecuta el controlador de demostración en vivo; mujoco.viewer simple muestra física pasiva solamente), cámaras, actuadores, controlador, comprobaciones de tarea, créditos de activos, limitaciones conocidas. Mensaje final al usuario: línea de veredicto, qué se construyó, qué activos
vinieron de Poly Pizza vs procedimental, resultados de humo, rutas a smoke/showcase.mp4 (el video que la gente ve), hoja de contactos y tira de fotogramas, cualquier cosa no hecha o no verificada, y una lista de "Cambios del plan confirmado" (activos o licencias intercambiados, tamaños/cantidades cambiados, extras eliminados) - vacía
si no hay ninguno, pero siempre presente. Copia cada número (comprobaciones pasadas, puntuaciones, errores) de
smoke/smoke_report.json y physics_report.json; pega su summary_line textualmente
("HUMO APROBADO: examinador 19 pasan / 0 advierten / 0 fallan; comprobaciones de tarea 9/9 pasan; render ok") y nunca escribas
cantidades de memoria.
Comienza <env>/REPORT.md tan pronto como la primera ejecución de humo esté terminada y actualízalo después de cada arreglo, para que una
sesión interrumpida aún deje un informe; el mensaje final es su última versión.
Diseño del entregable (mantén exactamente; las herramientas y paneles dependen de ello)
<env>/
SPEC.md README.md REPORT.md build_env.py scene.xml env.py view.py controller.py task_checks.py
world.py (solo si la escena tiene su propia dinámica)
simkit/ ayudantes vendidos
assets/polypizza/*.glb assets/polypizza/CREDITS.md assets/polypizza/polypizza_assets.json
assets/meshes/ assets/procedural/ assets/ASSETS.md
smoke/ (showcase.mp4 contact_sheet.png filmstrip.png collision_sheet.png renders/ rollout.mp4
physics_report.json render_report.json smoke_report.json env_manifest.json
SMOKE.md visual_check.md)
isaac/ (solo para Isaac: scene.usda, isaac_smoke.py, sección README)
Reglas ganadas con esfuerzo (cada una ha roto una construcción real)
-
Mantente dentro del alcance confirmado. La demo muestra lo que el usuario acordó (p.ej., "estar de pie es suficiente" significa una postura estable, no un nuevo controlador de locomoción). Dedica el tiempo a la escena, los activos, las comprobaciones y la revisión visual en su lugar; enumera las ideas adicionales en el README.
-
Configuraciones
<visual>:sc.set_visual("map", znear=.., zfar=..)etc. Cada elemento puede aparecer una vez. -
Nunca calcules manualmente las
xyaxesde la cámara: usaScene.camera(name, pos, target)/simkit.scene.lookat. -
Nunca escribas manualmente listas de qpos de fotogramas clave: establece
scene.home[articulación] = valor(los robots lo hacen por ti);Scene.writeconstruye el fotograma clavehomepor nombre de articulación y establece el ctrl del actuador de posición para que coincida. -
Las mallas planas/delgadas necesitan
inertia="shell"(glb_to_mujoco lo hace). Geoms visuales:contype=0 conaffinity=0 group=2 mass=0; proxies de colisión en el grupo 3. -
Un robot soldado al mundo choca con su propia base: añade
<exclude>para la base/primer eslabón. -
Positivamente, asegúrate de que...