2026年7月11日土曜日

ブラウザで使えるロボットシミュレータ調査(日本語版)

 


結論

Unitree G1をブラウザ上で動かしたい場合、大きく3つの選択肢があります。

① MuJoCo WASM(最もおすすめ)

もし

  • G1のMJCFをそのまま使いたい
  • 本格的な物理シミュレーションをしたい

ならこれがベストです。

現在Google公式のMuJoCoにはJavaScript/WebAssembly版があります。

特徴

  • MJCF対応
  • URDF対応
  • STL・OBJも読める
  • G1公式MJCFをそのまま利用可能
  • ブラウザだけで動作可能

ただし、

「アップロード画面」

などは自分で少し作る必要があります。


② Three.js + URDFLoader(最も簡単)

もし

「G1をブラウザで表示したい」

だけならこれが一番簡単です。

特徴

  • URDF対応
  • ドラッグ&ドロップ対応
  • 関節スライダー
  • Three.jsだけで動く

ただし

物理シミュレーションはありません。

つまり

  • ポーズ変更
  • 可視化
  • GUI

向けです。


③ Three.js + Rapier

中間的な選択肢です。

特徴

  • WebAssembly物理
  • 軽量
  • 高速
  • Three.jsと相性が良い

しかし

URDFやMJCFを直接読む機能はありません。

自分で

  • 関節
  • 剛体
  • コライダ

を作る必要があります。


クラウド型シミュレータ

ブラウザで見えていても、

実際にはサーバで動いているものがあります。

例えば

  • Isaac Sim
  • Gazebo
  • Webots.cloud

です。

これは

ブラウザ
      ↓
GPUサーバ
      ↓
シミュレーション

という構成になります。


ONNXは動く?

結論

はい。

現在は

ONNX Runtime Web

があります。

つまり

ブラウザ
    ↓
ONNX Runtime
    ↓
推論

ができます。

対応

  • WASM
  • WebGPU
  • WebGL
  • WebNN

G1との相性

これはかなり重要です。

Unitree公式のG1には

  • URDF
  • MJCF

の両方が最初から付属しています。

つまり

G1
 ↓
MJCF
 ↓
MuJoCo WASM

という流れが非常に自然です。


比較表

システム物理URDFMJCFブラウザのみおすすめ度
MuJoCo WASM★★★★★★★★★★
Three.js + URDFLoader☆☆☆☆☆×★★★★☆
Three.js + Rapier★★★★☆★★★★☆
Ammo.js★★★★☆××★★★☆☆
PhysX WASM★★★★☆××★★★☆☆
Webots.cloud★★★★☆×クラウド★★★☆☆
Gazebo + GzWeb★★★★★×クラウド★★☆☆☆
Isaac Sim★★★★★クラウド★★★★☆

もしG1をブラウザで動かすなら

レポートでは次の順番を推奨しています。

① MuJoCo WASM

MJCFアップロード

↓

ブラウザ内FSへ保存

↓

mj_loadXML()

↓

物理開始

↓

ONNX追加

もっとも自然な構成です。


② Three.js URDFLoader

URDF読込

↓

OrbitControl

↓

スライダー

↓

ポーズ変更

完成まで数時間程度。


③ Rapier

Three.js

↓

Rapier

↓

剛体生成

↓

関節生成

↓

ONNX

物理を少し入れたいならこれ。


レポート全体の最終結論

調査では次のようにまとめられています。

本格的なG1シミュレーション
MuJoCo WASM

すぐ表示したい
Three.js + URDFLoader

軽量な物理付き
Three.js + Rapier

ヒトガタの表記法

 ヒト型モデルには、世界共通の「人体部位の書き方」が一つあるわけではありません。

実際には、次の4層が重なっています。

  1. ファイル形式:階層・座標・アニメーションをどう保存するか
  2. 骨格構造:どの骨がどの骨の子か
  3. 人体セマンティクス:その骨が「左上腕」「骨盤」など何を意味するか
  4. 命名規則LeftUpperArmupper_arm.Lなど、実際の文字列

このうち、ファイル構造は厳密ですが、骨の名前は多くの場合、暗黙知や制作会社の規約です。VRMやUnity Humanoidのように、人体部位を明示的に規定する仕組みを重ねると、初めて意味まで標準化されます。


代表的な形式

形式主な用途厳密に決まるもの人体部位名
FBXMaya、Blender、Unityなどの受け渡しノード、骨格、スキン、アニメーション原則自由
glTF/GLBWeb、ゲーム、リアルタイム表示ノード階層、関節配列、ウェイト、バインド行列原則自由
VRM人型アバターglTF構造+人体ボーンの意味規定あり
USD/UsdSkel映画・大規模制作パイプラインSkeleton、Joint、Animation、Skin binding部位の意味は原則自由
Unity Humanoidリターゲティング人体部位へのマッピング規定あり
URDFロボットlink、joint、軸、可動範囲、質量原則自由
MJCFMuJoCo物理シミュレーションbody、joint、geom、actuator、sensor原則自由

FBX

FBXは幅広い3Dデータ交換用の形式です。Autodeskも、Maya、3ds Max、MotionBuilderなどの間で3D資産を交換するための形式として位置づけています。人体専用ではないため、骨名をLeftArmにするかupper_arm.Lにするかは、作成者やツールの規約に依存します。

glTF/GLB

glTFでは、ノード階層、ローカル変換、スキンに使用する関節配列、逆バインド行列などが厳密に定義されています。関節は特別な骨オブジェクトではなく、通常のノードをskin.jointsから参照する形です。

しかし、ノードのnameは表示・アプリケーション利用向けの任意文字列であり、一意である保証さえありません。つまりLeftUpperArmと書く義務はありません。

VRM

VRMはglTFの上に、人型であるという意味情報を追加した形式です。

VRM 1.0では、少なくとも次のような人体スロットが定義されます。

hips
spine
head

leftUpperArm
leftLowerArm
leftHand

rightUpperArm
rightLowerArm
rightHand

leftUpperLeg
leftLowerLeg
leftFoot

rightUpperLeg
rightLowerLeg
rightFoot

これらには必須・任意の区別があります。したがってVRMでは、単に骨が存在するだけでなく、「このノードは左上腕である」というマッピングが必要です。

重要なのは、実際のノード名そのものが必ずleftUpperArmである必要はなく、VRMの左上腕スロットに正しく登録されていることです。

USD/UsdSkel

UsdSkelは、スケルトン、スキニングされたメッシュ、関節アニメーションをDCCツール間で交換するためのUSDスキーマです。関節順序、階層、バインド、アニメーションなどを扱えますが、「この関節は人体の左肘」という普遍的な人体辞書を強制するものではありません。

Unity Humanoid

Unity Humanoidはファイル形式ではなく、読み込んだ骨格を人体部位に割り当てる意味付けレイヤーです。

Unityは、

Hips
Spine
Chest
Neck
Head
LeftUpperArm
LeftLowerArm
LeftHand
LeftUpperLeg
LeftLowerLeg
LeftFoot

などをHumanBodyBonesとして厳密に列挙しています。指についてもLeftThumbProximalのような標準スロットがあります。

元のFBX内で骨がBip001_L_Armという名前でも、Unity上でLeftUpperArmに割り当てればHumanoidとして扱えます。


人体部位の名前はどこまで標準なのか

1. 解剖学的な語彙はかなり共通

よく使われる語はおおむね共通しています。

hips / pelvis      骨盤
spine              背骨
chest              胸部
neck               首
head                頭

shoulder            肩
upperArm            上腕
lowerArm            前腕
hand                手

upperLeg            大腿
lowerLeg            下腿
foot                足
toes                つま先

ただし、これは語彙として共通しているだけで、文字列の書式までは統一されていません。

同じ左上腕でも、次のような名前が存在します。

LeftUpperArm
left_upper_arm
upper_arm.L
L_UpperArm
Arm_L
mixamorig:LeftArm
J_Bip_L_UpperArm
DEF-upper_arm.L

意味はほぼ同じですが、別の文字列です。


左右の書き方

代表的な方式は3種類あります。

接頭辞

L_UpperArm
R_UpperArm
LeftUpperArm
RightUpperArm

接尾辞

UpperArm_L
UpperArm_R
upper_arm.L
upper_arm.R

名前空間付き

Character01:LeftArm
mixamorig:LeftArm

左右は原則として、画面を見ている人からではなく、キャラクター本人から見た左右です。


G1の命名規則

G1は人体リグというよりロボット記述なので、名前がより機械的です。

left_hip_pitch_joint

分解すると、

left   左側
hip    股関節
pitch  前後回転
joint  関節

です。

left_hip_pitch_link

なら、

left   左側
hip    股関節付近
pitch  pitch関節の先にある部品
link   剛体

となります。

G1のURDFでは、pelvisからleft_hip_pitch_jointを通ってleft_hip_pitch_linkへ接続され、その次にroll、yaw、kneeと続きます。これは人体部位だけでなく、機械的な回転軸まで名前に含める方式です。

CGリグなら、

LeftUpperLeg
LeftLowerLeg
LeftFoot

程度で済ませるところを、ロボットでは、

left_hip_pitch_joint
left_hip_roll_joint
left_hip_yaw_joint
left_knee_joint

のように、自由度ごとに分割します。


厳密さの段階

ファイル構文:厳密

JSON、XML、ノード番号、親子参照、行列の個数などは厳密です。

たとえばglTFでは、skin.jointsの順序とinverseBindMatricesの順序が一致しなければなりません。

親子構造:厳密

Hips
└─ Spine
   └─ Chest

という接続関係はデータとして明示されます。

親のワールド変換と子のローカル変換を掛け合わせて、子のワールド位置を求めます。glTFでも、子のグローバル変換は親のグローバル変換と自身のローカル変換の積として定義されています。

人体としての意味:形式による

  • FBX単体:ほぼ暗黙
  • glTF単体:ほぼ暗黙
  • USD単体:パイプライン依存
  • VRM:明示的
  • Unity Humanoid:明示的
  • URDF:人体としての意味は基本的に命名者依存

実際の名前:多くは慣習

LeftUpperArmでなければならない、という世界共通規則はありません。

したがって、実務では名前だけで判定せず、

名前
親子関係
左右の位置
骨の向き
人体マッピング

を組み合わせて判定します。


主な留意点

座標系

形式やソフトによって、上方向、前方向、右手系・左手系が異なります。

glTFは右手系で、+Yが上、+Zが前、距離単位はメートル、角度はラジアンです。

読み込み時に座標変換されると、左右反転、180度回転、巨大化・極小化などが起きます。

BoneとJointは同じではない

CGではboneが身体の区間を表すことがあります。

UpperArm bone

ロボットではjointが回転中心、linkが硬い部品です。

shoulder_joint
    ↓
upper_arm_link

したがって、

CGのbone ≒ URDFのlink

と単純に一対一対応させると、少しずれます。

RootとHipsを分ける

よくある構造は、

Root
└─ Hips
   ├─ LeftLeg
   ├─ RightLeg
   └─ Spine

です。

Rootはキャラクター全体の移動用、Hipsは身体の骨盤運動用です。これを同じノードにすると、歩行アニメーションの移動と腰の揺れを分離しにくくなります。

TポーズとAポーズ

同じ骨名でも、初期姿勢やボーン軸が違えば、アニメーションをそのまま移植できません。

リターゲティングでは、

  • 初期姿勢
  • 骨のローカル軸
  • 手足の長さ
  • 肩幅
  • 骨盤高
  • バインド行列

が重要です。名前が一致するだけでは不十分です。

補助骨

実際のリグには人体部位以外も含まれます。

upper_arm_twist
forearm_twist
breast
skirt
hair
weapon_socket
ik_hand
pole_knee

これらはVRMやUnityの基本人体スロットに割り当てられない場合があります。無理に人体ボーンとして扱わず、追加ノードとして保持します。

同名骨

glTFでは名前の一意性は保証されません。Boneという名前が複数存在することも仕様上可能です。プログラムで扱う場合は、名前だけではなくノード番号や完全な階層パスを使用した方が安全です。


実務向けの命名案

人型リグを自分で設計するなら、次の順序に統一すると読みやすくなります。

側_部位_区分_役割

例:

left_arm_upper_bone
left_arm_lower_bone
left_hand_bone

left_arm_ik_ctrl
left_elbow_pole_ctrl

left_hip_pitch_joint
left_thigh_link

CGリグなら、

root
hips
spine_01
spine_02
chest
neck
head

upper_arm.L
forearm.L
hand.L

ロボットなら、

left_shoulder_pitch_joint
left_shoulder_pitch_link
left_elbow_joint
left_forearm_link

が分かりやすいでしょう。

要するに、ファイル形式は骨格を厳密に保存するが、その骨が人体の何であるかは必ずしも保証しない。VRMやUnity Humanoidは、その空白を人体部位マッピングで埋める仕組みです。


順番には2種類あります。

1. 骨格としての順番

人体リグでは通常、中心から末端へ並べます。

Root
└─ Hips / Pelvis
   ├─ Spine
   │  └─ Chest
   │     ├─ Neck
   │     │  └─ Head
   │     ├─ LeftShoulder
   │     │  └─ LeftUpperArm
   │     │     └─ LeftLowerArm
   │     │        └─ LeftHand
   │     └─ RightShoulder
   │        └─ RightUpperArm
   │           └─ RightLowerArm
   │              └─ RightHand
   ├─ LeftUpperLeg
   │  └─ LeftLowerLeg
   │     └─ LeftFoot
   │        └─ LeftToes
   └─ RightUpperLeg
      └─ RightLowerLeg
         └─ RightFoot
            └─ RightToes

原則は、

体幹 → 近位 → 遠位

です。

つまり、

肩 → 上腕 → 前腕 → 手
股関節 → 大腿 → 下腿 → 足

という順番になります。

2. ファイルに書かれる順番

こちらは形式によって異なりますが、必ずしも人体順である必要はありません

たとえばglTFでは、ノードが配列に入っています。

{
  "nodes": [
    { "name": "Head" },
    { "name": "Hips", "children": [2] },
    { "name": "Spine", "children": [0] }
  ]
}

配列上は、

Head
Hips
Spine

の順でも、参照関係によって、

Hips
└─ Spine
   └─ Head

という階層になります。

つまり、配列順より親子参照のほうが重要です。

G1のREADMEの順番

G1の表示は、おそらく深さ優先探索の前順走査です。

簡単にいうと、

  1. 親を書く
  2. 最初の子を末端まで書く
  3. 一段戻る
  4. 次の兄弟を書く

という順番です。

pelvis
    左脚を末端まで
    右脚を末端まで
    torso
        左腕を末端まで
        右腕を末端まで

図にすると、

pelvis
├─ left leg
├─ right leg
└─ torso
   ├─ left arm
   └─ right arm

ですが、文字では、

pelvis
left leg全部
right leg全部
torso
left arm全部
right arm全部

と一直線に並びます。

左右はどちらが先か

これは世界共通ではありません。

よくあるのは、

Left → Right

ですが、

Right → Left

の形式もあります。

左右の順番は、骨格の意味には影響しません。親子関係が正しければよいからです。

ただし、次の場合は順番が重要です。

  • アニメーションのチャンネル配列
  • スキンウェイトのジョイント番号
  • 逆バインド行列
  • MuJoCoのアクチュエータ配列
  • 独自プログラムが番号を前提にしている場合

人体部位名の語順

名前の中の順番にも代表的な型があります。

Unity型

LeftUpperArm

順番は、

左右 → 位置 → 部位

です。

Left + Upper + Arm

snake_case型

left_upper_arm

同じく、

左右 → 位置 → 部位

です。

Blender型

upper_arm.L

順番は、

部位 → 左右

です。

ロボット型

left_hip_pitch_joint

順番は、

左右 → 部位 → 運動軸 → 種類

です。

分解すると、

left
hip
pitch
joint

になります。

リンクなら、

left_hip_pitch_link

です。

実務でおすすめの順番

CGリグなら、

部位_区分.左右

または、

左右_区分_部位

を一貫して使います。

例:

upper_arm.L
lower_arm.L
hand.L

あるいは、

left_upper_arm
left_lower_arm
left_hand

ロボットなら、

左右_部位_軸_種別

が分かりやすいです。

left_shoulder_pitch_joint
left_shoulder_pitch_link
left_elbow_joint
left_forearm_link

要するに、骨格の順番は中心から末端、ファイル上の順番は形式依存、名前の語順は規約依存です。特にG1の一覧は、「親から最初の枝を末端までたどる深さ優先順」と読むのが正確です。