Communitygithub.com

johannstark/GeminiRobotics-Skills

Renderiza simulaciones MuJoCo con Three.js (WASM en el navegador, proceso Python MuJoCo en streaming o logs). Útil para configurar escenas con eje Z hacia arriba, convertir geoms y mallas de MuJoCo a mallas de Three.js, sincronizar poses de cuerpos por fotograma (cuaternios wxyz), capturar instantáneas de cámara y video del lienzo para Gemini Robotics-ER, mapear puntos ER [y, x] 0-1000 a 3D mediante raycasting, proyectar 3D de vuelta a coordenadas de imagen y depurar renderizados torcidos, girados, de tamaño incorrecto o en blanco.

¿Qué es GeminiRobotics-Skills?

Este skill es una herramienta especializada para desarrolladores que trabajan con simulaciones robóticas en MuJoCo y necesitan visualizarlas en el navegador usando Three.js. Se encarga de resolver las diferencias fundamentales entre los sistemas de coordenadas de MuJoCo (Z hacia arriba, cuaternios wxyz, medios tamaños) y Three.js (Y hacia arriba, cuaternios xyzw, tamaños completos), que son la fuente de la mayoría de los errores de renderizado. El skill soporta múltiples enfoques: sincronización de grupos de cuerpos por fotograma, uso de `mjv_updateScene` para decoraciones nativas de MuJoCo, o conexión remota con un servidor Python que transmite poses por WebSocket. Incluye funcionalidades avanzadas como mapeo de puntos de interés (puntos ER) a coordenadas 3D mediante raycasting, captura de instantáneas y video del lienzo, y una guía de solución de problemas para síntomas comunes como robots acostados, eslabones torcidos o imágenes negras.

Compatible con~Claude Code~Codex CLI~Cursor✓Gemini CLI
npx skills add https://github.com/johannstark/GeminiRobotics-Skills/tree/HEAD/threejs-rendering

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Renderizado Three.js para MuJoCo

Construye geometría estática una vez, luego actualiza solo las transformaciones en cada fotograma. MuJoCo usa Z hacia arriba, medios tamaños, cilindros y cápsulas alineados con Z, y cuaternios wxyz. Three.js usa Y hacia arriba por defecto, tamaños completos, cilindros alineados con Y y cuaternios xyzw. Casi todos los errores de renderizado provienen de una de estas diferencias.

1. Configuración de escena (Z hacia arriba, lista para captura)

import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';   // ruta válida en 0.164 y 0.18x

const renderer = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer: true }); // necesario para toDataURL
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
renderer.shadowMap.enabled = true;
const camera = new THREE.PerspectiveCamera(45, w / h, 0.01, 100);
camera.up.set(0, 0, 1);                       // MuJoCo es Z hacia arriba. Con esto, no se necesita conversión de ejes en ningún lado.
camera.position.set(2, -1.5, 2.5);
const controls = new OrbitControls(camera, renderer.domElement);
const grid = new THREE.GridHelper(5, 50); grid.rotation.x = Math.PI / 2;   // coloca la cuadrícula en XY

Establece camera.up antes de crear OrbitControls, porque los controles almacenan en caché el vector hacia arriba.

2. Elige un enfoque

EnfoqueCómoCuándo usarlo
A. Un Group por cuerpo (el demo de Franka)Cada grupo de cuerpo contiene sus geoms en sus geom_pos/geom_quat locales. Copia xpos/xquat en cada fotograma.Por defecto. Selección mediante userData.bodyID. Funciona con cualquier fuente de pose.
B. mjv_updateScene (demo oficial)Sincroniza una malla agrupada por cada entrada de scene.geomsCuando quieras decoraciones propias de MuJoCo (contactos, tendones, sitios)
C. Python remotoPython avanza la simulación y transmite xpos/xquat por WebSocket. El navegador ejecuta A.Puentes con GPU, ROS o robots reales, cómputo intensivo

Conversión de geoms: references/geom-conversion.md. Streaming Python (servidor probado): references/remote-python.md. Instantáneas, cámara de percepción, video y píxel↔3D: references/perception-and-video.md.

3. Sincronización por fotograma (enfoque A)

for (let i = 0; i < model.nbody; i++) {
  bodies[i].position.set(data.xpos[3*i], data.xpos[3*i+1], data.xpos[3*i+2]);
  bodies[i].quaternion.set(data.xquat[4*i+1], data.xquat[4*i+2], data.xquat[4*i+3], data.xquat[4*i]); // wxyz -> xyzw
}
renderer.render(scene, camera);

Orden del bucle: entradas → mj_step (tantas veces como permita el presupuesto de tiempo de simulación) → sincronización → renderizado (ver MujocoSim.startLoop). La alternativa por geom usa data.geom_xpos y data.geom_xmat (matriz 3×3 por filas → Matrix4.set(r00,r01,r02,0, r10,…)), con la geometría en la pose identidad.

4. Puntos ER ↔ 3D

// ER [y, x] 0-1000 en la imagen capturada -> rayo desde la MISMA cámara que la capturó
const ndc = new THREE.Vector2((x / 1000) * 2 - 1, 1 - (y / 1000) * 2);
raycaster.setFromCamera(ndc, captureCamera);
const hit = raycaster.intersectObjects(simMeshes, false)[0];     // o raycaster.ray.intersectPlane(table, out)

// 3D -> ER-style [y, x] (para dibujar expectativas o construir prompts)
const v = p.clone().project(captureCamera);
const yx = [(1 - v.y) * 500, (v.x + 1) * 500];

Esto es válido para cualquier relación de aspecto siempre que la imagen sea exactamente el viewport completo de la cámara (sin recorte, sin letterbox) y la cámara no se haya movido entre la captura y el raycasting. Omite los impactos en el robot o el suelo recorriendo los userData.bodyID. El impacto está en la superficie superior, así que bájalo a la altura de agarre.

5. Problemas comunes

SíntomaCausa
El robot está acostado, la órbita se tambaleacamera.up no es (0,0,1), o se estableció después de crear OrbitControls
Eslabones torcidosFalta el reordenamiento wxyz→xyzw
Cajas del doble de tamañoOlvidaste que los tamaños son medios tamaños
Cilindros o cápsulas apuntan en dirección incorrectaFalta geometry.rotateX(Math.PI/2)
Instantánea en blanco o negrapreserveDrawingBuffer: false, o los píxeles se leyeron en una tarea diferente al renderizado
Imagen de percepción más oscura que la pantallaLos render targets generan color lineal (verificado en three r186). Convierte a sRGB (consulta la referencia de percepción).
Marcadores ER desplazadosLa cámara se movió, [y, x] está invertido, la imagen está recortada o con letterbox, o el lienzo de relación de píxeles del dispositivo se redimensionó de manera diferente
La memoria crece al recargargeometry.dispose(), material.dispose(), renderTarget.dispose(), y elimina el modelo y datos WASM
Tirones a alta velocidadDemasiadas llamadas mj_step por fotograma. Limita los pasos o mueve la física a un Worker.

6. En el demo de Franka

El demo de pick-and-place de Franka es la aplicación de referencia a partir de la cual se construyeron estos skills. Los nombres de archivo a continuación se refieren a ella.

  • RenderSystem.ts usa preserveDrawingBuffer: true, una PerspectiveCamera(45) con Z hacia arriba, OrbitControls amortiguados, simGroup (un grupo por cuerpo, userData.bodyID), erGroup (marcadores cónicos oscilantes), marcadores de contacto instanciados, interpolaciones de cámara (moveCameraTo), y getCanvasSnapshot(w, h, mime).
  • project2DTo3D(x, y, camPos, lookAt) clona la cámara principal, la posiciona en el punto de vista de captura ((0, -0.01, 2.0) mirando al origen), y realiza raycasting sobre las mallas de simGroup.
  • rendering/GeomBuilder.ts maneja la fábrica de geom→malla. Las geoms del grupo 3 se omiten, los planos se convierten en un suelo Reflector, y las geoms de malla leen mesh_vert/mesh_face.
  • DragStateManager.ts y SelectionManager.ts manejan la selección con el ratón y las fuerzas de arrastre a través de xfrc_applied.
  • El mapa de importación de index.html fija three 0.164.1, mientras que package.json tiene ^0.181. Mantén las importaciones de three/examples/jsm/..., que funcionan en ambas versiones.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Skills relacionados