現実と仮想を繋ぐ:TM RobotとIsaac SimをROS2で連携させる
こんにちは!今回は、ロボットアーム(Techman Robot)モデルを、NVIDIA Isaac Sim内に配置し、連携させ、リアルタイムに動作を同期させる「デジタルツイン」環境の構築に挑戦しました。
最終的な目標は
- シミュレーション上のTM Robot を、別マシンにインストールした制御ソフト(TMFlow)を使って操作し、その動きをIsaac Sim上でリアルタイムに再現
- さらにIsaac Sim内のカメラ映像をWebブラウザで確認する
ことです。
この記事では、その構築プロセス全体と、途中で直面した問題、そしてその解決策について解説します。
⚠️ セキュリティ注意: この記事で使用されているIPアドレスやポート番号は例示です。本番環境では適切なセキュリティ設定を行い、必要最小限のポートのみ開放してください。
システム構成
今回のシステムの全体像は以下の通りです。
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Windows PC │ │ Ubuntu PC │ │ Isaac Sim │
│ TMFlow │ ◄─────► │ ROS2 Jazzy │ ◄─────► │ Visualization │
│ Version 2.20 │ TCP │ w/ tm_driver │ Topics │ + Camera │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │
└────────────────────────────┘
HTTP MJPEG
http://PC_IP:5000
│
▼
┌────────────────────────┐
│ Web Browser (TMFlow) │
│ View Camera Feed │
└────────────────────────┘
データの流れは以下のようになります。
- Windows PC上にインストールしたTMFlowが、ロボットの脳として自身の関節角度などの状態を公開します。
- Ubuntu PC上のROS2ノード(tm_driver)がその情報を参照し、ROS2トピックとして配信します。
- Isaac SimがそのROS2トピックを参照し、シミュレーション内のロボットモデルを動かします。
- Isaac Sim内のカメラが見ている映像を、別のROS2ノードがWebストリームに変換します。
- TMFlowや他のPCのWebブラウザからそのストリームにアクセスし、デジタルツインの視点を確認します。
Step 1: TM Robot側の設定
まず、TMFlowが外部(ROS2)と通信できるように設定します。
1. ネットワーク設定
TM RobotとUbuntu PCが同じネットワーク上にいることを確認してください。私の環境では5890番ポートを使っていたので、ファイヤーウォールを解放しておきます。
2. TMflow Data Tableの準備
TMflowで公開するデータセットを設定します。
-
TMflowでプロジェクトを開き、 Settings → Configuratoin → Communication に移動します。

-
一度Ethernet Slaveを無効にします。無効にしないと次の項目を編集できません。
-
Data Table Setting をクリックし、関節角度、速度、TCP座標、エラー状態など通信に必要なデータ項目が右側の欄に追加されるようにします。基本、全部選択して構いません。

-
設定を保存し、再度Ethernet Slaveを有効にします。
Step 2: ROS2ドライバの設定と修正
次に、Ubuntu PC側でTM RobotをROS2で制御するためのドライバを設定します。
問題点:TMflow 2.20とtm_driverの非互換性
公式のtm_driverは、TMflowの新しいバージョン(2.20)が送信しない一部のデータ項目(MA_Mode, Safeguard_A)を必須としており、そのままではエラーで起動しませんでした。
解決策:ドライバのソースコードを修正
これらの項目を必須(REQUIRE)から任意(NOT_REQUIRE)に変更することで、この問題を回避します。
修正ファイル1: tm_driver/src/tm_robot_state.cpp
// Line 42: Safeguard_Aを任意に変更
_item_map["Safeguard_A"] = { &rs->tmRobotStateDataFromEthernet.is_safeguard_A_triggered, Item::NOT_REQUIRE};
// Line 59: MA_Modeを任意に変更
_item_map["MA_Mode"] = { &rs->tmRobotStateDataFromEthernet.ma_mode, Item::NOT_REQUIRE };
修正ファイル2: tm_driver/src/tm_packet.cpp (警告メッセージの調整)
// Line 207: 頻繁に出る警告をデバッグメッセージに変更
print_debug("package length not valid...");
修正後、colcon buildでワークスペースを再ビルドします。
ドライバの起動
ビルドが完了したら、以下のコマンドでドライバを起動します。
ros2 launch tm_driver tm_bringup.launch.py robot_ip:=<TMFlowのIPアドレス>
コンソールにdata table is correct!と表示されれば接続成功です。
Step 3: Isaac Simでのロボットミラーリング
いよいよIsaac Sim側で、現実のロボットの動きを再現します。Ros2からのデータを受け取るため、Action Graphを設置しました。データを受け取り、ロボットモデルに反映するミニマルな構成にします。
アームを動かすのに必要なノード
- On Playback Tick
- ROS2 Subscribe Joint State
- Topicは
/joint_states
- Topicは
- Articulation Controller
- Target Primはロボットを指すようにしてください。私の場合は
/World/tm5sでした。
- Target Primはロボットを指すようにしてください。私の場合は
問題点:ロボットがブルブル震える
最初、Isaac Simのロボットが小刻みに震える現象に悩まされました。原因は、/joint_statesというトピックに対して、2つのノードが同時にデータを書き込んでいたためでした。
- tm_driver: 現実のロボットの高精度な関節角度をPublish
- Isaac Sim: シミュレーター内の低精度な関節角度をPublish
この2つが競合し、ロボットが震える原因となっていました。
解決策:Isaac SimからのPublishを停止
Isaac Simは現実のロボットの動きを**受け取るだけ(Subscribe)**に徹するべきです。
- Isaac Simで [Window] → [Visual Scripting] → [Action Graph] を開きます。
- "ROS2 Publish Joint State" ノードを削除または無効化します。
- "ROS2 Subscribe Joint State" ノードは残します。
これにより、データの流れが一方通行になり、ロボットの動きが安定しました。
Step 4: Isaac Simカメラ映像のWebストリーミング
最後に、Isaac Simが見ている光景をWebブラウザで確認できるようにします。
問題点:TMflowはROS2トピックを直接表示できない
Isaac Simはカメラ映像をROS2トピック(/camera/image_raw)として配信しますが、TMflowのWebブラウザ機能はこれを直接表示できません。
解決策:ROS2トピックをHTTP MJPEGストリームに変換
Pythonスクリプトを作成し、ROS2のカメラトピックを購読し、Webフレームワーク(Flask)を使ってHTTP上でMJPEGストリームとして配信するノードを作成しました。
アーキテクチャ:
Isaac Simのカメラ (/camera/image_raw)
↓ (ROS2トピック)
Pythonスクリプト (cv_bridgeで画像変換)
↓ (FlaskでWebサーバー化)
HTTP MJPEGストリーム (http://PC_IP:5000)
↓
Webブラウザで表示
このスクリプトを起動することで、ネットワーク上のどのデバイスからでも http://<Ubuntu PCのIP>:5000 にアクセスすれば、Isaac Simからのライブ映像が見られるようになります。
全体のワークフロー
今回の作業では3つのターミナルを起動しました。
- ターミナル1: TM Robotドライバ
ros2 launch tm_driver tm_bringup.launch.py robot_ip:=<TMFlowのIPアドレス> - ターミナル2: Joint状況の確認
ros2 topic echo /joint_states - ターミナル 3: カメラWebストリーミング
./stream_isaac_camera.sh
これで、TMflowでロボットを動かすと、Isaac Sim内のロボットがリアルタイムで追従し、その様子をWebブラウザでどこからでも確認できるようになりました。

トラブルシューティングのヒント
- ドライバが接続できない: TMflowのListenノードが実行中か、Ethernet Slaveが有効になっているかを確認してください。
- ロボットが震える: Isaac SimのAction Graphで
ROS2 Publish Joint Stateノードを無効にしてください。 - カメラストリームにアクセスできない: ファイアウォールがポート
5000をブロックしていないか確認してください。(sudo ufw allow 5000/tcp)
まとめと今後の展望
今回の連携により、物理的なロボットの遠隔監視、シミュレーション上での事前検証、カメラを使ったアプリケーション開発などが、TMflowのネイティブな操作感を維持したまま可能になりました。
さすがPhyXがしっかりしているので、Isaac Sim上でアームが障害物にぶつかるとぶつかったアクションになっていました。
今後は、
- Isaac Sim側からロボットを制御する双方向通信
- MoveItと連携した高度なパスプランニング
- 複数のカメラアングルへの対応
など、さらなる機能拡張に挑戦していきたいと考えています。
この記事が、同じように現実と仮想の融合に挑戦する方々の助けになれば幸いです。
