※本記事は継続的に最新情報へアップデートしています。
SO-101の行動ログが録れた。しかしシミュレーターはまだ、そのロボットの存在を知らない。
これは単なるファイル変換の話ではない。シミュレーターに「正しい身体」を与えられなければ、どれだけ丁寧にAIを学習させても、実機に戻した瞬間に動きは崩れてしまう。
「ロボット仕様書(URDF)」をIsaac Simで扱える標準的なシーン表現(USD)へ変換し、物理的な動きを実機に合わせて調整するまでは、学習を始めてはならない。
本記事では、ファイルの場所の確認からIsaac Simへの取り込み、実機との誤差をゼロに近づけるStiffness/Dampingゲイン調整まで、3ステップで順番に解説する。
✅ 先に結論
URDF→USD変換・動作確認・ゲイン調整の3ステップを順番に完了させることで、Isaac Sim上でSO-101が正しい物理特性を持って動く状態が整います。
- ポイント1:SO-101のロボット仕様書(URDF)はGitHubに公開済み。
so101_new_calib.urdfが推奨ファイル - ポイント2:変換はGUI(File > Import)とCLI(convert_urdf.py)の2経路。順序は変換→確認→調整の一方通行
- ポイント3:Stiffness/Dampingのゲイン調整なしに学習を始めると、実機に戻した際にアームが発振する可能性がある
このシリーズについて
本記事はSO-101 Physical AI開発「詳細編」の第2回。第1回でBCデータを採取済みであることが前提だ。
📚 SO-101 Physical AI開発シリーズ(詳細編)
- 第1回:Behavior Cloning入門|SO-101×LeRobotで行動ログを採取する
- ▶ 第2回(本記事):ロボット仕様書(URDF)の変換 〜 Stiffness/Dampingゲイン調整
概要編は「SO-101で学ぶPhysical AI|全工程概要」をご覧ください。
まずは記事の内容を直感的にとらえよう。
「ロボット仕様書」と「Isaac Sim語ファイル」とは何か
URDFはロボットの設計図、USDはIsaac Sim / Omniverseの標準的なシーン表現。SO-101でSim2Realを成立させるには、Isaac Labの学習より先にこの変換が必要になる。
この記事では、難しい用語に迷わないよう、2つの呼び名を最初に定義します。
ロボットのパーツ構成・重さ・関節の動き方をすべて記述したXMLファイルです。人間でいえば「健康診断書+身体測定記録」のようなものです。USD(Universal Scene Description)=「Isaac Sim語ファイル」
NVIDIA Isaac Sim / Omniverseの中核となる3Dシーン記述形式です。Isaac SimはURDFやMJCFなどもImporter経由で取り込めますが、シミュレーションで安定して編集・再利用するには、最終的にUSD表現へ変換して扱うのが基本です。
ロボット仕様書(URDF)には、以下のような情報が書かれています。
- どのパーツ(リンク)がどの関節(ジョイント)でつながっているか
- 各パーツの重さ・重心・形
- 関節がどの方向に、どこまで動けるか(可動域)
- 3Dモデルのファイルがどこに保存されているか
ロボット仕様書をIsaac Simで扱えるUSD表現に変換する作業が「翻訳」であり、これをしないとSO-101はシミュレーター上で正しく物理的な身体を持てません。この変換→確認→調整を順番に行うのが、本記事で解説する3ステップです。
SO-101のロボット仕様書(URDF)の場所と構成
公式URDFはGitHubに無料公開済み。ファイルの種類と役割を事前に把握しておくことが、後の作業ミスを防ぐ。
ファイルの場所(GitHub)
以下のURLにアクセスすると、シミュレーション用ファイルが一式入ったフォルダを確認できます。
📁 https://github.com/TheRobotStudio/SO-ARM100/tree/main/Simulation/SO101
このリポジトリはTheRobotStudioが公開しているSO-100 / SO-101の公式ハードウェアリポジトリです。SO-101はThe Robot StudioがHugging Faceと共同で設計したロボットアームであり、LeRobotとの連携を前提に、ハードウェア設計・シミュレーション用ファイル・組み立て手順が整理されています。
フォルダの中身一覧
| ファイル名 | 形式 | 用途 | Isaac Simで使う? |
|---|---|---|---|
so101_new_calib.urdf |
URDF | 推奨。関節ゼロ点を可動域の中央に設定 | ✅ 使う |
so101_old_calib.urdf |
URDF | 旧バージョン。過去データとの互換性用 | ⛔ 新規では使わない |
so101_new_calib.xml |
MJCF | MuJoCo(別のシミュレーター)用 | ⛔ 本記事では使わない |
scene.xml |
MJCF | MuJoCo用のシーン設定ファイル | ⛔ 本記事では使わない |
joints_properties.xml |
XML | STS3215モーターの物理特性定義 | 参照用 |
assets/ |
フォルダ | 各パーツの3D形状データ(メッシュ) | ✅ URDFと一緒に必要 |
| ※ 出典:TheRobotStudio/SO-ARM100 GitHub リポジトリ(2026年5月時点) | |||
このURDFに加えられた2つの修正点
このURDFはOnshapeのCAD設計を自動変換ツール(onshape-to-robot)で書き出したものです。自動変換のままでは不都合があったため、2か所が手動で修正されています。
① メッシュファイルの参照先を相対パスに修正済み
自動変換では「package://」というROS専用の書き方になります。Isaac SimはROSなしでも動作するよう、相対パスに書き換えてあるため、そのまま使えます。
② ベース部分のコリジョン(当たり判定)を意図的に削除済み
底面に当たり判定を設定すると、地面と干渉してロボットが暴れる問題が発生しました。STEP 2の確認でベース底面の緑色が表示されなくてもバグではなく仕様です。
フォロワーアームのモーター構成
SO-101フォロワーアームは全6軸すべてに同じモーター(STS3215、ギア比1/345)を使っています。なおリーダーアームは関節ごとに異なるギア比のモーターを使っていますが、現行URDFには未反映です。フォロワーアームをシミュレート対象にする本記事の範囲では問題ありません。
STEP 1|ロボット仕様書をIsaac Sim語ファイルに翻訳する
変換方法はGUIとCLIの2経路。しかしここでassets/フォルダの置き場を間違えると、SO-101は「骨格だけの幽霊」としてシミュレーターに現れる。
まず:ロボット仕様書(URDF)をローカルに取得する
# GitHubからリポジトリをまるごとダウンロード(クローン) git clone https://github.com/TheRobotStudio/SO-ARM100.git # URDFが入っているフォルダに移動 cd SO-ARM100/Simulation/SO101 # ファイルが揃っているか確認 ls # → so101_new_calib.urdf と assets/ フォルダが見えればOK
方法A:GUIでインポートする(まず動かして確認したいとき)
Isaac SimのURDF Importer Extensionはデフォルトで有効になっており、追加インストールは不要です。ロボット仕様書(URDF)をIsaac Sim語ファイル(USD)にその場で翻訳してくれます。
- メニューバーの File > Import をクリックします
- ファイルブラウザで
so101_new_calib.urdfを選択します - インポート設定画面で以下の通りに設定します
| 設定項目 | 設定値 | 理由 |
|---|---|---|
| USD Output(保存先) | ~/robots/so101/ など任意 |
後から読み込みやすい場所ならどこでも可 |
| Merge Fixed Joints | ON | 動かない関節をまとめて処理を軽量化する |
| Create Physics Scene | ON | 重力・地面などの物理環境を自動セットアップ |
| Self Collision | OFF(初期値のまま) | 調整段階では計算負荷を増やすだけなのでOFF |
| ※ 出典:Isaac Sim URDF Importer Extension 公式ドキュメント(2026年5月時点)。Isaac Sim 5.1以降は固定関節の統合挙動が変わっているため、表示されるリンク構造や関節数が想定と異なる場合は、使用中のIsaac Sim / Isaac Labのバージョンを確認してください。 | ||
- Import ボタンをクリックします
- 画面下部の「Output Log」に赤字のエラーがないことを確認します
- Viewport(3D表示画面)にSO-101が出現すれば変換成功です
⚠️ よくある失敗:メッシュが読み込まれない
assets/フォルダをURDFと別の場所に置くと3D形状が表示されません。URDFファイルとassets/フォルダは必ず同じフォルダ内に置いてください。
方法B:コマンドラインで変換する(学習パイプラインに組み込むとき)
Isaac Labには convert_urdf.py というスクリプトが用意されています。設定をコードで管理できるため、チームで共有したり再変換したりするときに便利です。
Isaac Labの公式例では、URDF→USD変換時に
--joint-stiffness 0.0、--joint-damping 0.0、--joint-target-type none を使う例が示されています。本記事でも、STEP 3でGain Tunerにより実機に近い値を決めるため、変換段階ではゲインを固定しない設計にします。# IsaacLabのルートフォルダで実行する cd ~/IsaacLab ./isaaclab.sh -p scripts/tools/convert_urdf.py \ ~/SO-ARM100/Simulation/SO101/so101_new_calib.urdf \ ~/robots/so101/so101.usd \ --merge-joints \ --fix-base \ --joint-stiffness 0.0 \ --joint-damping 0.0 \ --joint-target-type none
変換が完了すると so101.usd が生成されます。これがIsaac Simで読み込めるSO-101の「仮想身体」——Isaac Sim語ファイル(USD)の完成です。
最初の確認はGUIが直感的でわかりやすいです。本番の学習パイプラインに組み込む場合はCLIで設定をスクリプト化しておくと、チームで再現性を保てます。
STEP 2|変換結果を3点確認する
変換が終わった瞬間、SO-101はシミュレーターの中に「存在」したように見える。しかし、関節数・コリジョン・回転方向が1つでもズレていれば、AIは最初から別の身体を前提に学習してしまう。
チェック1:関節の数と名前が正しいか
SO-101フォロワーアームは6本の動く関節を持ちます。Isaac Simのコンソールで以下を実行してください。
# 使用中のIsaac Simバージョンに応じて、importパスは適宜読み替えてください。
from isaacsim.core.robots import Robot
my_so101 = Robot(prim_path="/World/so101", name="so101")
my_so101.initialize()
print("関節数:", my_so101.num_dof)
print("関節名:", my_so101.dof_names)
# 正常な出力例(SO-101公式URDFをそのまま使った場合)
# 関節数: 6
# 関節名: ['Rotation', 'Pitch', 'Elbow', 'Wrist_Pitch', 'Wrist_Roll', 'Jaw']
isaacsim.core.api 系へ整理されている場合があります。上記コードでimportエラーになる場合は、使用中のIsaac SimのAPIドキュメントに合わせてimportパスを確認してください。「関節数:1」「関節数:0」と表示された場合は、GUIに戻り Merge Fixed Joints の設定を見直してください。
チェック2:当たり判定(コリジョン)がついているか
当たり判定がないと、ロボットの手先がキューブや机をすり抜けてしまいます。Viewportの目のアイコン(Show by type)→ Physics → Colliders → All を有効にすると、当たり判定の範囲が緑色で表示されます。各リンクに概ね緑色が表示されていれば問題ありません。
ベースリンクの底面だけ緑色がない場合は、URDF構成の項で説明した通り意図的な削除なので問題ありません。
チェック3:関節が正しい方向に動くか(最重要)
Playボタン(▶)でシミュレーションを開始し、以下のコードで第1関節だけを動かしてみます。
import numpy as np zero_pos = np.zeros(my_so101.num_dof) my_so101.set_joint_positions(zero_pos) # 第1関節(水平回転)を45度動かす test_pos = np.zeros(my_so101.num_dof) test_pos[0] = np.deg2rad(45) my_so101.set_joint_positions(test_pos)
アームが右方向に約45度回転すれば正しい状態です。左に回った、または全く動かなかった場合は、URDFの関節軸(axis)の定義とIsaac Simの座標系が食い違っています。この問題を放置してSTEP 3に進むと、ゲインをどれだけ調整しても実機と一致しません。
3点すべて問題がなければ、STEP 3に進む準備完了です。
STEP 3|Stiffness/Dampingを実機の動きに合わせる
デフォルトのゲイン値は「とりあえず動く」設定に過ぎない。このまま学習を始めると、AIは現実のSO-101ではなく、シミュレーター内の“別の身体”を前提に育ってしまう。
変換が終わって関節が動いても、そのままでは「シミュレーターの中のSO-101」と「現実のSO-101」は別物の動き方をしています。
第1回で録った人間のデモは、このギャップを埋めてはじめて「意味のある教師信号」になります。ここをサボると、学習済みAIを実機に乗せた瞬間にアームが激しく震えたり、ぐにゃぐにゃ動いて目標に届かなかったりする——いわば「別のロボットを育ててしまう」ことになります。
Physical AIの核心は、仮想空間で鍛えた知能を、現実の身体へ破綻なく戻すことにあります。URDF変換で「身体の形」はできました。しかし、まだ「筋肉の硬さ」や「関節の粘り」は現実と一致していません。Stiffness/Dampingの調整とは、仮想SO-101に現実のSO-101らしい動き方を教え込む作業です。
なぜシミュレーターと実機はズレるのか
現実のサーボモーター(STS3215)には、理想的なシミュレーターにはない「不完全さ」があります。
- 電気的な反応の遅れ(コマンドを送ってから実際に動くまでのタイムラグ)
- ギア内部の「遊び」(バックラッシュ)による動き始めのずれ
- 関節内部の摩擦による動き止まり
- 急に動かすと行き過ぎてしまうオーバーシュート
これらをシミュレーターに再現するための設定が、Stiffness(剛性)とDamping(減衰)の2つのパラメーターです。
StiffnessとDampingを「バネとダンパー」で理解する
| パラメーター | 身近な例え | 値を上げると | 値を下げると |
|---|---|---|---|
| Stiffness(剛性) Kp・Pゲインとも呼ぶ |
固いバネ。目標位置に引き戻す力の強さ | キビキビ反応するが行き過ぎて震えやすい | 重さに負けて目標に届かない |
| Damping(減衰) Kd・Dゲインとも呼ぶ |
ドアクローザーのような油の抵抗。行き過ぎを抑制する | オーバーシュートなし。ゆっくり止まる | 素早く動くが行き過ぎて振動しやすい |
| ※ 出典:Isaac Sim Joint Drive Gain Tuning Tutorial(NVIDIA、2026年5月時点) | |||
方法A:Gain Tuner Extension(GUI)でリアルタイムに調整する
Isaac SimにはGain Tunerという専用のGUIツールが内蔵されています。スライダーを動かしながらリアルタイムで関節の挙動を確認できます。なお、バージョンによってメニュー配置や表示名が変わる場合があるため、公式ドキュメントの「Joint Drive Gain Tuning」節も併せて確認してください。
- メニューバーから Tools > Robotics > Asset Editors > Gain Tuner を開きます
- シミュレーションを必ず一度Playしてから、SO-101のRobot assetを選択します
- 調整したい関節を選び、StiffnessとDampingのスライダーを動かします
⚠️ 「SET STIFF GAINS」ボタンは絶対に押さないこと
このボタンは各関節にStiffness=1e15・Damping=1e5という極端な数値を同時設定します。工場用ロボットのような高剛性アームでは近似として使える場合がありますが、SO-101のような小型ロボットアームでは、実機の柔らかさ・遊び・遅れとの対応が失われます。
ゲイン調整の進め方(NVIDIA公式チュートリアルに沿った手順)
- まずDampingを0にして、Stiffnessだけを少しずつ上げていきます。関節が目標値に追従し始める最小値を探します
- その値を10分の1にスケールダウンして仮のStiffnessとします
- 次にDampingをStiffnessの10分の1程度から足していきます。オーバーシュートが消えたところを基準値にします
- 実機の行動ログ(第1回で録った動作データ)と比べて、「動き始めのタイミング」「止まるまでの時間」が近くなるよう微調整します
方法B:Pythonスクリプトに書き出してIsaac Labに引き継ぐ
GUI調整で決定した値をPythonコードに書き出しておきます。Isaac Labの学習スクリプトに直接渡せるようになり、毎回GUIで調整する手間がなくなります。
from isaaclab.actuators import ImplicitActuatorCfg
SO101_ACTUATOR_CFG = ImplicitActuatorCfg(
joint_names_expr=["Rotation", "Pitch", "Elbow",
"Wrist_Pitch", "Wrist_Roll", "Jaw"],
# Gain Tunerで見つけた値をここに入力する
stiffness=400.0, # 初期値の一例。実機ログに合わせて調整する
damping=40.0, # 初期値の一例。発振や遅れを見ながら調整する
# STS3215モーターのカタログ値をもとにした上限例
# 実機の電源電圧・個体差・安全マージンに応じて調整してください。
effort_limit=8.4, # 参考:データシート上の最大トルク(Nm)
velocity_limit=3.14, # 参考:最大角速度(rad/s)≒ 180度/秒
)
「調整完了」の判断基準
- ✅ 本記事の初期検証では、指令後おおむね0.2〜0.5秒程度で目標位置に近づき、震えずに停止することを目安にする
- ✅ 実機の行動ログの関節角度グラフと、シミュレーターの追従グラフが形状として一致している
- ✅ シミュレーションをPlayしたまま10秒以上放置しても発振・ドリフトが起きない
まとめ
3ステップを順番に完了させることで、「実機に転送できる学習基盤」が初めて整う。
| ステップ | やること | 完了の証拠 | よくある失敗 |
|---|---|---|---|
| STEP 1:翻訳 | ロボット仕様書(URDF)を取得し、GUIまたはCLIでIsaac Sim語ファイル(USD)に変換する | so101.usd生成、Output Logにエラーなし |
assets/フォルダをURDFと別の場所に置く |
| STEP 2:確認 | 関節数・コリジョン・動く方向の3点を確認する | 6関節が正しい方向に動く。緑のコリジョンが表示される | ベースのコリジョンがないのをバグと勘違いする |
| STEP 3:調整 | Gain TunerでStiffness/Dampingを調整し、実機の動きに近づける | 10秒間発振なし、行動ログと追従グラフが一致 | 「SET STIFF GAINS」ボタンで剛体化してしまう |
| ※ Arpable Tech Team 作成(2026年5月) | |||
この3ステップを通して「仮想のSO-101」と「現実のSO-101」の身体を揃えることができてはじめて、本当の意味でのSim2Real——シミュレーターで学んだ行動が、そのまま実機でも機能する世界——を目指す準備が整います。
この3ステップが完了した状態が、Sim2Real環境構築の「身体情報」定義の完成です。ロボットが仮想空間で正しい物理特性を持って動く状態になって初めて、AIはシミュレーターの中で「自分で動いてみる ➔ 審判に採点される ➔ 失敗してリセットされる」というサイクルを、実機だけでは試せない速度と回数で回せるようになります。
URDF変換とゲイン調整を丁寧に行ったかどうかが、Sim2Realの成否を根本から左右します。次のフェーズでは、この仮想身体の上に「タスク定義(キューブの配置とランダム化)」と「成功基準(報酬関数)」を積み上げていきます。ここからが本当に面白いところです。SO-101は失敗して、採点され、リセットされ、また試す。その反復の先で、AIは少しずつ「物体を掴む」という行動を自分のものにしていきます。
専門用語まとめ
- URDF(Unified Robot Description Format)/ロボット仕様書
- ロボットのパーツ構成・関節の種類・可動域・重量・3Dモデルのファイルパスを記述したXML形式のファイルです。ROS(Robot Operating System)の標準フォーマットですが、Isaac Simなど他のツールでも広く使われます。SO-101の公式URDFは
so101_new_calib.urdfが推奨版です。
- USD(Universal Scene Description)/Isaac Sim語ファイル
- Pixarが開発した3Dシーン記述の共通フォーマットです。NVIDIA OmniverseおよびIsaac Simの基盤フォーマットであり、URDFやMJCFなどのロボット記述ファイルも、最終的にはUSD表現へ変換して扱うのが基本です。物理エンジン(PhysX)はこの形式を通じてロボットの質量・慣性・関節特性を認識します。
- PhysX
- NVIDIAが開発したリアルタイム物理エンジンです。Isaac Simの物理演算基盤として使われており、重力・衝突・摩擦・関節の動きをシミュレートします。USDに変換されたロボットモデルを読み込み、Stiffness/Dampingの設定値をもとに関節の応答を計算する役割を担います。
- Stiffness(剛性)/Kpゲイン
- 関節が目標位置に向かって戻ろうとするバネの硬さを表すパラメーターです。PDコントローラーのP(比例)ゲインに相当します。値を上げると指令への追従が速くなる一方、過剰に上げるとオーバーシュートや発振が起きます。単位はN-m/rad(トルク÷角度)です。
- Damping(減衰)/Kdゲイン
- 関節の動きに対して速度に比例した制動力をかけるパラメーターです。PDコントローラーのD(微分)ゲインに相当し、オーバーシュートや振動を抑制する役割を持ちます。ドアクローザーのような「行き過ぎを止める油の抵抗」をイメージするとわかりやすいです。単位はN-m-s/radです。
参考文献 / 出典
一次情報
- TheRobotStudio/SO-ARM100 – Simulation/SO101ディレクトリ(GitHub)
- TheRobotStudio/SO-ARM100 – 公式ハードウェアリポジトリ(GitHub)
- Hugging Face LeRobot – SO-101 Documentation
- NVIDIA – Isaac Sim URDF Importer Extension 公式ドキュメント
- NVIDIA – Joint Drive Gain Tuning Tutorial(Isaac Sim)
- NVIDIA – Gain Tuner Extension 公式ドキュメント(Isaac Sim)
二次情報
次に読むならこの3本
補足Q&A
Q1. URDFとMJCF(.xmlファイル)は何が違いますか?
A1. どちらもロボットの仕様を記述するファイルですが、主に使われるエコシステムが異なります。
URDFはROSエコシステムやIsaac Sim / Isaac Labで広く使われるロボット記述形式です。MJCF(MuJoCo XML Format)は、主にMuJoCo向けのロボット記述形式です。Isaac SimにはMJCF Importerも用意されていますが、本シリーズのIsaac LabベースのパイプラインはURDFを前提にしています。本記事の範囲では、必ずURDF(so101_new_calib.urdf)を選択してください。
Q2. Gain Tunerで調整した値はどこに保存されますか?
A2. GUIでの変更はUSDファイル内に一時保存されますが、Isaac Labに引き継ぐにはPythonコードへの書き出しが必要です。
Gain TunerはIsaac Simのステージ上での一時的な設定変更ツールです。Isaac Labで学習を回す際は、調整した数値をImplicitActuatorCfgのstiffness・dampingパラメーターとしてPythonファイルに明示的に書き出す必要があります。GUIだけで完結するわけではない点に注意してください。
Q3. Stiffness/Dampingは全関節に同じ値を使っていいですか?
A3. 最初は全関節同じ値で試し、発振や追従不足が出た関節だけ個別に調整するのが現実的です。
SO-101フォロワーアームは全6軸が同じSTS3215モーター(ギア比1/345)で統一されているため、初期値として全関節に同じStiffness/Dampingを適用しても大きく外れることは少ないです。ただし、重力の影響を直接受けるショルダー関節(Pitch・Elbow)は負荷が大きく、他の関節より高いStiffnessが必要になるケースがあります。行動ログの追従グラフを関節ごとに確認しながら微調整してください。
Q4. URDF変換やゲイン調整を雑にやると、どんな失敗が起きますか?
A4. もっとも多いのは「シミュレーターではうまく動くのに、実機に戻した瞬間に外す」というパターンです。
URDFの関節軸がズレている、あるいはStiffness/Dampingが実機よりも強すぎる/弱すぎる状態で学習してしまうと、AIは「現実のSO-101」ではなく「シミュレーター内の別のSO-101」を前提にした方策を覚えてしまいます。Sim2Realで重要なのは、シミュレーターを派手に動かすことではなく、現実のロボットが持つ遅れ・摩擦・遊びをどこまで正直に再現できるかです。
Q5. WindowsとLinuxで挙動に差はありますか?
A5. 基本的な考え方は同じですが、パス表記・シェル構文・GPUドライバの違いで細部が変わる場合があります。
Isaac Sim / Isaac Labは環境依存の影響を受けやすいため、公式のリリースノートと推奨ドライババージョンを確認してください。本記事のコマンド例はLinux系のパス表記を前提にしているため、Windows環境ではパスや実行方法をご自身の環境に合わせて読み替えてください。
更新履歴
- 2026年5月26日:初版公開