Meta QuestとIsaacSimを用いたロボットアームのテレオペレーション環境の開発事例
更新日:3 日前
こんにちは、IDXソリューション部 Y.O.です。
VRヘッドセット「Meta Quest 3」をNVIDIAのIsaacSimに接続し、シミュレーション上の産業用ロボットアームをVRコントローラーとゲームパッドの2通りで遠隔操作できる環境を構築した事例を紹介します。
キーワード:フィジカルAI デジタルツイン IsaacSim テレオペレーション VR
はじめに
テレオペレーションとは、人の操作をリアルタイムにロボットへ伝えて動かす手法です。遠隔地での作業に使えるだけでなく、ロボットに動作を教える模倣学習やVLA(Vision-Language-Action)の学習データ(人による操作のお手本)を集める手段としても注目されています。
今回の取り組みでは、VRコントローラーを使った直感的な操作と、ゲームパッドを使った操作の2通りで、シミュレーション上のロボットアームを動かせるようにしました。また、VRヘッドセットでロボットの動きを立体的に確認できるようにすることで、ロボットと対象物の位置関係を把握しやすくしています。
記事の前半では2つの構成に共通する仕組み(IsaacSimとMeta Questの接続、ロボットの制御方法)を、後半でそれぞれの構成に固有の工夫を紹介します。
使用したロボットと開発環境
使用したロボット
アームには安川電機の6軸ロボット「MOTOMAN NEXT NHC12」、グリッパーにはRobotiq社の2指グリッパー「2F-85」を使用しています。どちらもIsaacSimに標準アセットとして用意されているモデルです。アームの先端にグリッパーを固定し、1台のロボットとして扱っています。

開発環境
Meta QuestとPCの接続に使う「Meta Quest Link」がWindows向けのアプリのため、今回はWindows環境で開発しています。またIsaacSimは描画や物理演算でGPUメモリを多く使用するため、対応したGPUの用意が必要です。今回使用した環境は以下の通りです。
• CPU:Core i7-14700F
• GPU:GeForce RTX 4070
• メモリ:32.0 GB
• OS:Windows 11
• IsaacSim:6.0
• VRヘッドセット:Meta Quest 3
• ゲームパッド:ELECOM JC-GP20s
システムの全体像
ヘッドセットはMeta Quest LinkでPCと接続し、OpenXR(VR機器を扱うための共通規格)を通じてIsaacSimのシーンを表示します。どちらの構成でも、入力から手先の目標位置・姿勢を作り、逆運動学(IK)で関節角度を計算してロボットに指令するという流れは同じです。2つの構成の違いは以下の通りです。
項目 | VRコントローラー版 | ゲームパッド版 |
使用する機器 | ヘッドセット+ 左コントローラー | ヘッドセット(視点のみ)+ ゲームパッド |
アームを動かす入力 | コントローラーの位置・傾き | スティック・トリガー・ボタン |
手先の目標の動かし方 | 手を動かした量をそのまま反映 | 倒した量に応じた速さで 動かし続ける |
グリッパーの開閉 | トリガー | Aボタン(長押し) |
初期姿勢へのリセット | X/Yボタン | Yボタン |

使用したロボットと開発環境
シーンの作成
IsaacSim上に作業台、掴む対象のキューブ、コンテナなどを配置したシーンを作成し、USDファイルとして保存しています。ロボットは作業台の奥に置いた台座の上に設置し、作業台の上のキューブを掴んで持ち上げる作業を想定しています。2つの構成とも同じシーンを使用しています。

物理パラメータの設定
シミュレーション上で物を掴むには、グリッパーと対象物が接触し、摩擦で保持できる状態になっている必要があります。最初はグリッパーの指に衝突判定が設定されておらず、キューブをすり抜けてしまいました。そこでグリッパーの各部品に衝突判定を追加し、キューブに触れるグリッパーの指とキューブに、摩擦の大きいマテリアルを設定しています。
設定項目 | 内容 |
衝突判定 | グリッパーの各部品に追加 |
静止摩擦係数 | 1.5(グリッパーの指・キューブ) |
動摩擦係数 | 1.0(グリッパーの指・キューブ) |
キューブの質量 | 0.05 kg(一辺5cm) |
グリッパー関節の剛性(Stiffness) | 3(アセットの初期値のまま) |

Meta QuestとIsaacSimの接続
XR機能の確認
IsaacSimにはVR・AR機器を扱うXR機能が用意されており、Pythonからヘッドセットやコントローラーの情報を取得できます。まずはIsaacSimのScript Editor(Pythonを実行できる画面)で、VR表示の有効化と機器の認識を確認しました。
from omni.kit.xr.core import XRCore
xr = XRCore.get_singleton()
xr.get_profile("vr").request_enable_profile() # VR表示を有効化
left = xr.get_input_device("/user/hand/left") # 左コントローラー
pose = left.get_pose("grip") # 位置・姿勢(4×4の変換行列)
コントローラーからは位置と姿勢をまとめた4×4の変換行列が得られるので、ここから位置と回転(クォータニオン)を取り出して使います。
ロボット制御の共通部分
処理の流れ
スクリプトでは、毎フレーム次の処理を繰り返しています。
① 入力(VRコントローラーまたはゲームパッド)を読み取る
②入力に応じて、ロボットの手先の目標位置・姿勢を更新する
③ 差分IKで、目標に近づくための関節角度の変化量を計算する
④ アームとグリッパーに指令を送る
①・③・④は入力機器によらず共通の処理で、構成ごとに異なるのは②の目標の更新方法です。そのため、ゲームパッド版はVRコントローラー版をもとに、②の目標の更新部分を書き換えて作成しています。

差分IKによるアーム制御
手先の目標位置・姿勢から各関節の角度を求める計算を逆運動学(IK)と呼びます。
今回は、手先の目標と現在の位置・姿勢の差から、それを縮めるための関節角度の変化量を毎フレーム計算する「差分IK」を用いています。計算には減衰最小二乗法(DLS法)を使い、ロボットが特異姿勢(アームが伸び切った姿勢など、ある方向に手先を動かせなくなる姿勢)に近づいたときに、関節が急に大きく動くのを抑えています。
さらに、IKに渡す1フレームあたりの移動・回転の指令と関節の変化量に上限を設け、急な動きが起きないようにしています。
グリッパーの制御と初期姿勢へのリセット
グリッパーは、ボタン(またはトリガー)を押している間だけ閉じる角度を指令し、離すと開く角度に戻します。アームとグリッパーはどちらも関節の目標角度を与える位置制御に統一し、アームは6軸、グリッパーは指の関節と、指令先を分けています。これにより、アームを動かしながらでも安定してキューブを把持できます。
どちらの構成にも、ボタン1つでロボットを起動時の姿勢に戻す機能を用意しています。これまでは、初期姿勢からやり直すたびにヘッドセットを外してIsaacSimを再起動する必要があったため、操作性を高める目的で追加しました。
VRコントローラーによるテレオペレーション
1つ目は、Meta Questの左コントローラーを手に持ち、手の動きに合わせてアームを動かす構成です。
手の動きを手先の目標に反映する
コントローラーの位置をそのまま手先の目標にするのではなく、前のフレームからの「変化量」を手先の目標に足し込む方式にしています。こうすることで、操作する人がどこに立っていても、手を動かした分だけロボットの手先が動くようにしています。姿勢についても同様に、前のフレームからの回転の変化量を目標姿勢に掛け合わせています。また、1フレームの移動量が1mm以下のときは無視し、手の細かな震えでロボットが揺れないようにしています。
コントローラーを動かす速さに応じてロボットを動かす「速度制御」も検討しましたが、速く動かすほど遠くへ動く操作は慣れていない人には扱いにくいため、手の移動量をそのまま反映する方式を採用しました。
座標軸の合わせ込み
今回は、作業者がロボットと向かい合って操作することを前提に開発しました。
コントローラーとロボットでは上方向の軸(y軸/Z軸)が異なるうえ、作業者の手の動きとロボットの手先の動きの向きがそろうよう、座標軸の並べ替えと符号の調整を行っています。

操作の割り当て
グリップボタンは、手先が届かない位置まで目標を動かしてしまったときなど、目標と実際の手先がずれたときに使います。押した時点のコントローラーの位置を新しい基準にするため、そこから続けて操作できます。X/Yボタンでのリセット後も、その時点のコントローラーの位置を基準として取り直し、手の位置がずれていてもロボットが急に動かないようにしています。
操作 | 動作 |
左コントローラーを動かす・傾ける | 手先の位置・姿勢を動かす |
トリガー | グリッパーを閉じる(離すと開く) |
グリップボタン | 手先の目標を、実際の手先の位置に合わせ直す |
X/Yボタン | ロボットを初期姿勢に戻す |
ゲームパッドによるテレオペレーション
2つ目は、Meta Quest 3のヘッドセットを視点の確認だけに使い、アームの操作はゲームパッドで行う構成です。ヘッドセットを着けて歩いたり覗き込んだりすると、その動きに合わせて視点が変わるため、ロボットや対象物をいろいろな角度から確認しながら操作できます。
倒した量に応じて手先を動かす
ゲームパッドで得られるのはスティックやトリガーを「倒した量」だけで、手の位置そのものは得られません。そのため、倒した量に応じた速さで手先の目標を動かし続ける方式(レート制御)にしています。スティックをいっぱいに倒したときの速さは、移動が毎秒0.15m、回転が毎秒45°です。
また、スティックは手を離しても値が完全に0に戻らないことがあり、そのままでは触っていないのにロボットが少しずつ動いてしまいます。そこで倒した量が12%より小さいときは0とみなし(デッドゾーン)、それを超えた分を0〜1に引き伸ばして使うことで、デッドゾーンを抜けた瞬間に急に動き出さないようにしています。
操作の割り当て
ゲームパッドはPCの環境によって認識のされ方が異なり、ボタンの対応が変わる場合があります。そこで、ロボットを動かさずに入力値だけを表示するテストモードを用意し、事前にボタンやスティックの対応を確認できるようにしています。また、操作した向きとロボットの動く向きが逆に感じられる場合に備えて、軸ごとに向きを反転できる設定も用意しています。
ゲームパッド操作 | ロボットの動作 |
左スティック(左右/上下) | 手先を左右/上下に動かす |
右スティック(上下) | 手先を前後に動かす |
右スティック(左右) | 手先を回す(ヨー) |
LT/RT | 手先を傾ける(ピッチ) |
LB/RB | 手先をひねる(ロール) |
Aボタン(長押し) | グリッパーを閉じる(離すと開く) |
Yボタン | ロボットを初期姿勢に戻す |

開始時の視点の固定
この構成ではヘッドセットで見ることが操作の前提になるため、操作を始めるときの視点も重要です。IsaacSimのXR機能では、VRの視点の基準をデスクトップ画面のカメラに合わせる設定(anchorMode = "active camera")ができます。この設定にしたうえで、VR表示を始める前に画面のカメラを手先から0.8m手前・0.2m上に置き、ロボットの方を向けています。これにより、Meta Quest側で設定した安全範囲(ガーディアン)の位置などに左右されず、毎回同じ視点から操作を始められます。
おわりに
ここまで、Meta QuestとIsaacSimを接続し、シミュレーション上のロボットアームをVRコントローラーとゲームパッドの2通りで遠隔操作する環境を構築した事例を紹介してきました。
手の動きをそのまま伝えるVRコントローラーと、倒した量で速さを決めるゲームパッドでは、手先の目標の動かし方が大きく異なります。一方で、差分IKやグリッパーの制御、リセット処理は共通にできたため、入力機器を変えても目標の更新部分を書き換えて作成できました。
実際に使ってみると、ゲームパッドでの操作の方が、VRコントローラーでの操作よりも扱いやすいと感じました。ヘッドセットでロボットを覗き込みながら操作できるため、実際の工場でロボットに動作を教えるティーチング作業に近い形で操作できます。反対にVRコントローラーでの操作は、手のわずかな傾きもロボットの手先に反映されるため、思い通りに動かすのが難しく感じました。また、前後方向と上下方向では、手を動かした距離ほどロボットの手先が動かない(感覚的には、手を30cm動かしても20cm弱しか動かない)という現象も見られました。
今回取り組んでみて、テレオペレーションでは、ロボットを動かす仕組みだけでなく、操作する人にとっての扱いやすさ(入力機器の選び方や、視点・座標の向きの設計)が操作性を大きく左右すると感じました。
今後は、ラックに立てかけたワークを掴んで持ち上げ、運んで置くまでの一連の作業で検証を進めるとともに、テレオペレーションで集めた操作データを模倣学習やVLAモデルに活用することも視野に入れています。テレオペレーションやシミュレーションの活用を検討したい方などいらっしゃいましたら、以下のリンクよりお問い合わせください。








