Communitygithub.com

johannstark/GeminiRobotics-Skills

將 MuJoCo 模擬以 Three.js 渲染,支援瀏覽器內 WASM、串流 Python 處理程序或日誌,專為 Z-up 場景設計,並與 Gemini Robotics-ER 整合。

GeminiRobotics-Skills 是什麼?

這項技能在瀏覽器中以 Three.js 渲染 MuJoCo 模擬(來自 WASM、串流 Python 程序或記錄檔)。它處理 Z-up 場景設定、將 MuJoCo 幾何體(geom)與網格轉換為 Three.js 網格、每幀對齊(wxyz 四元數)、捕捉相機快照與畫布影片供 Gemini Robotics-ER 使用、將 ER [y, x] 0–1000 座標透過光線投射映射到 3D、將 3D 點投影回影像座標,以及除錯側躺、扭曲、尺寸錯誤或空白畫面的渲染問題。其主要平台為網頁瀏覽器(支援 WebGL 與 WebSocket),利用 Three.js 進行渲染、MuJoCo 進行物理模擬,並透過開發者選擇的資料來源(WASM、WebSocket 串流或記錄檔)同步。該技能會因應 Z-up (MuJoCo)與 Y-up (Three.js)之間的軸向差異、不同單位慣例(半長 vs 全長)以及四元數順序(wxyz vs xyzw)進行修正,從而確保渲染結果正確。

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

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

使用 Three.js 渲染 MuJoCo

靜態幾何體只建立一次,每幀僅更新變換矩陣。 MuJoCo 使用 Z-up、半長尺寸、Z 軸對齊的圓柱與膠囊,以及 wxyz 四元數。Three.js 預設使用 Y-up、全長尺寸、Y 軸對齊的圓柱與 xyzw 四元數。幾乎所有的渲染錯誤都源於這些差異。

1. 場景設定(Z-up,可截圖)

import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';   // 在 0.164 與 0.18x 版本中此路徑有效

const renderer = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer: true }); // 為 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 使用 Z-up。設定後,任何地方都無需進行軸轉換。
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;   // 將網格平放在 XY 平面上

請在建立 OrbitControls 之前設定 camera.up,因為控制器會快取 up 向量。

2. 選擇一種方式

方式做法使用時機
A. 每個 body 一個 Group(Franka 示範)每個 body 群組在其局部 geom_pos/geom_quat 處持有其幾何體。每幀複製 xpos/xquat。預設。透過 userData.bodyID 進行選取。可與任何姿態來源搭配使用。
B. mjv_updateScene(官方示範)同步一個共用網格,對應於 scene.geoms 中的每個項目當您想要 MuJoCo 自身的裝飾(接觸點、肌腱、站點)時
C. 遠端 PythonPython 步進,並透過 WebSocket 串流 xpos/xquat。瀏覽器執行 A 方式。GPU、ROS 或真實機器人橋接、大量運算

幾何體轉換:references/geom-conversion.md。Python 串流(經過測試的伺服器):references/remote-python.md。 快照、感知相機、影片以及像素↔3D:references/perception-and-video.md。

3. 每幀同步(方式 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);

迴圈順序:輸入 → mj_step(次數取決於模擬時間預算)→ 同步 → 渲染 (參閱 MujocoSim.startLoop)。另一種方式是使用 data.geom_xpos 和 data.geom_xmat (row-major 3×3 → Matrix4.set(r00,r01,r02,0, r10,…)),幾何體位於單位姿態。

4. ER 座標 ↔ 3D

// ER [y, x] 0-1000 在擷取的影像上 -> 從拍攝該影像的 SAME 相機發射射線
const ndc = new THREE.Vector2((x / 1000) * 2 - 1, 1 - (y / 1000) * 2);
raycaster.setFromCamera(ndc, captureCamera);
const hit = raycaster.intersectObjects(simMeshes, false)[0];     // 或 raycaster.ray.intersectPlane(table, out)

// 3D -> ER 風格的 [y, x](用於繪製期望或建立提示)
const v = p.clone().project(captureCamera);
const yx = [(1 - v.y) * 500, (v.x + 1) * 500];

此方法適用於任何長寬比,前提是影像恰好是相機的完整視口(無裁切、無黑邊),且相機在擷取與光線投射之間沒有移動。透過檢查 userData.bodyID 來跳過機器人或地板上的擊中點。擊中點位於頂部表面,因此請將其降低到抓取高度。

5. 常見問題

症狀原因
機器人側躺,軌道翻轉camera.up 不是 (0,0,1),或者是在建立 OrbitControls 之後設定的
連桿扭曲遺漏 wxyz→xyzw 重新排序
盒子尺寸變成兩倍忘記尺寸是半長
圓柱或膠囊指向錯誤方向遺漏 geometry.rotateX(Math.PI/2)
空白或黑色快照preserveDrawingBuffer: false,或者像素是在與渲染不同的任務中讀取的
感知影像比螢幕暗渲染目標輸出的是線性色彩(已在 three r186 中驗證)。請轉換為 sRGB(參閱感知參考文件)。
ER 標記偏移相機移動、[y, x] 交換、影像裁切或加上黑邊,或者裝置像素比的畫布以不同方式調整大小
重新載入時記憶體增長geometry.dispose()、material.dispose()、renderTarget.dispose(),並刪除 WASM 模型與資料
高速下卡頓每幀呼叫過多 mj_step。限制步進次數,或將物理模擬移到 Worker。

6. 在 Franka 示範中

Franka 取放示範 是這些技能據以建立的參考應用程式。下面的檔案名稱參照該示範。

  • RenderSystem.ts 使用 preserveDrawingBuffer: true、Z-up 的 PerspectiveCamera(45)、帶阻尼的 OrbitControls、 simGroup(每個 body 一個群組,userData.bodyID)、erGroup(上下浮動的圓錐標記)、實例化的接觸點標記、 相機補間(moveCameraTo)以及 getCanvasSnapshot(w, h, mime)。
  • project2DTo3D(x, y, camPos, lookAt) 複製主相機,將其放置在截圖視角處 ((0, -0.01, 2.0) 看向原點),並對 simGroup 網格進行光線投射。
  • rendering/GeomBuilder.ts 處理幾何體到網格的工廠。群組 3 的幾何體會被跳過,平面會變成 Reflector 地板, 網格幾何體會讀取 mesh_vert/mesh_face。
  • DragStateManager.ts 與 SelectionManager.ts 透過 xfrc_applied 處理滑鼠選取與拖拽力。
  • index.html 的 import map 將 three 的版本固定為 0.164.1,而 package.json 則有 ^0.181。請保留 three/examples/jsm/... 的匯入,此寫法在兩個版本中皆可運作。

Individual skills in this repo

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

相關技能