2026年1月6日
Ken Suzuki
技術

NVIDIA Isaac Sim 環境上のロボットをROS 2 Jazzyから動かす

一般に公開されているロボットアームの挙動をRViz2上でプランニングし、稼働をIsaac Sim上で確認する環境を構成する手順の記録です。希望通りの動きになるまで、数時間試行錯誤しました。

Isaac SimROS2OmniverseTechman Robot
NVIDIA Isaac Sim 環境上のロボットをROS 2 Jazzyから動かす

イントロダクション

Techman Robot (TM5-700) を最新環境で動かす過程で、数多くのエラーに遭遇しました。特に ROS 2 Jazzy に合わせて提供されているコードを調整したり、Isaac Sim のバージョンアップに伴って説明と異なる挙動を埋め合わせたりしなければいけませんでした。その中で比較的試行錯誤が必要になった点をいくつか公開します。


開発環境

  • OS: Ubuntu 24.04 LTS
  • ROS 2: Jazzy Jalisco
  • Simulator: Isaac Sim 5.1.0
  • Robot: Techman Robot (TM5-700) リポジトリはこちら
  • Tool: MoveIt 2
  • Python 3.11 (Isaac Sim 5.1.0はこのバージョンが必要とのことで、Minicondaで環境を作っています)

大きな流れ

  1. ロボットデータをクローンして colcon build
  2. ros2 launch で、ロボットが配置されたRViz2を起動
  3. Isaac Simを開いて、ロボットを配置
  4. RViz2上で、動きのプランニングをして"Execute"を押すと
  5. Isaac Simで実際の動作を確認できる

とはいえ、実際の動作確認までにはいくつかのエラーに遭遇しました。以下にそれらの解決策を記録します。

🛠 トラブルシューティング:エラーと解決策

1. ビルド時の Python モジュール不足

【エラーメッセージ】 ModuleNotFoundError: No module named 'catkin_pkg'No module named 'yaml'

【原因】 Conda 仮想環境(env_isaacsim)内に、ROS 2 のビルドや実行に必要な Python ライブラリが入っていない。

【対処法】 仮想環境をアクティブにした状態で、不足しているライブラリを直接 pip インストールします。

pip install catkin_pkg PyYAML lark empy==3.3.4

2. ROS 2 と Python バージョンの不整合

【エラーメッセージ】 ModuleNotFoundError: No module named 'rclpy._rclpy_pybind11'

【原因】 ROS 2 Jazzy は Python 3.12 を想定していますが、仮想環境が Python 3.11 などの異なるバージョンだと、バイナリの互換性がなくなり読み込めません。

【対処法】

  • チュートリアル中は conda deactivate してシステム Python を使うか、conda create -n env_name python=3.12 で OS と同じバージョンの環境を作り直す。
  • Isaac Simはこれまで通りcondaのPython 3.11仮想環境で動かす。

3. MoveIt 2 がコントローラーを見つけられない

【エラーメッセージ】 Returned 0 controllers. Check that the controller manager is up and running.

【原因】 ROS 2 Jazzy から YAML ファイルのパースが厳格化され、以前の Humble 向けなどの書き方では読み込まれなくなった。

【対処法】 moveit_controllers.yaml の階層構造を、最新の形式(/**ros__parameters を含む構造)に修正します。


4. ジョイント名の不一致(名前の不一致)

【現象・エラー】 Articulation Controller 側でジョイント名が見つからないという警告が出る。

【原因】 Isaac Sim 内のロボットモデルのジョイント名(例:shoulder_1_joint)と、MoveIt 側の設定(例:joint_1)が一致していない。

【対処法】

シミュレーション環境が本体に合わせるというのが自然の流れですので、Isaac Sim 側の各 Joint プロパティの ROS2 Subscribe Joint State ノード等で Name Override を使用して名前を MoveIt に合わせるのが望ましいです。


5. ファイル構成

今回の作業で以下のファイルを編集しました。

  • CMakeLists.txt
  • package.xml
  • config/kinematics.yaml
  • config/moveit_controllers.yaml
  • config/ompl_planning.yaml
  • config/pilz_cartesian_limits.yaml
  • config/ros2_controllers.yaml
  • config/tm5-700.srdf
  • launch/demo.launch.py
tm5-700_moveit_config/
├── CMakeLists.txt           # ビルド設定
├── package.xml              # パッケージメタデータと依存関係
├── .setup_assistant         # MoveIt Setup Assistant設定
├── config/                  # 各種設定ファイル
│   ├── tm5-700.urdf.xacro      # ロボットモデル定義
│   ├── tm5-700.srdf            # セマンティック記述(グループ、姿勢など)
│   ├── tm5-700.ros2_control.xacro  # ROS2 Control設定
│   ├── moveit_controllers.yaml  # MoveItコントローラー設定
│   ├── ros2_controllers.yaml    # ROS2コントローラー設定
│   ├── controllers.yaml         # コントローラーパラメータ
│   ├── kinematics.yaml          # 運動学ソルバー設定(KDL)
│   ├── joint_limits.yaml        # 関節制限
│   ├── initial_positions.yaml   # 初期姿勢
│   ├── ompl_planning.yaml       # OMPLプランナー設定
│   ├── chomp_planning.yaml      # CHOMPプランナー設定
│   ├── stomp_planning.yaml      # STOMPプランナー設定
│   ├── trajopt_planning.yaml    # TrajOptプランナー設定
│   ├── pilz_cartesian_limits.yaml  # Pilzカーテシアン制限
│   ├── sensors_3d.yaml          # 3Dセンサー設定
│   └── moveit.rviz              # RViz設定ファイル
└── launch/                  # 起動ファイル
    ├── demo.launch.py           # デモ起動
    ├── move_group.launch.py     # move_groupノード起動
    ├── moveit_rviz.launch.py    # RViz起動
    ├── rsp.launch.py            # robot_state_publisher起動
    ├── spawn_controllers.launch.py  # コントローラー起動
    ├── static_virtual_joint_tfs.launch.py  # 仮想ジョイントTF
    ├── warehouse_db.launch.py   # データベース起動
    └── setup_assistant.launch.py # Setup Assistant起動

6. Isaac Sim 5.x 世代の注意点

同様のことを行おうとして、いろいろな文献を調べると Action GraphROS2 Follow Joint Trajectory ノードを多用しているのですが、私の使っているIsaac Sim 5.1ではこのノードが搭載されていませんでした。 同じ動作を実現させるために、現在は ROS2 Context -> ROS2 Subscribe Joint State -> Articulation Controller と繋ぐのが正攻法です。

その上で、Pythonでブリッジを作成します。

import rclpy
from rclpy.node import Node
from rclpy.action import ActionServer
from control_msgs.action import FollowJointTrajectory
from sensor_msgs.msg import JointState

class IsaacActionBridge(Node):
    def __init__(self):
        super().__init__('isaac_action_bridge')
        self._action_server = ActionServer(
            self,
            FollowJointTrajectory,
            '/tmr_arm_controller/follow_joint_trajectory', # MoveItの設定と一致させる必要がある
            self.execute_callback)
        self.publisher_ = self.create_publisher(JointState, '/joint_command', 10)
        self.get_logger().info('Action Server Bridge started. Waiting for MoveIt...')

    def execute_callback(self, goal_handle):
        self.get_logger().info('Executing trajectory...')
        trajectory = goal_handle.request.trajectory
        
        # Send the points to Isaac Sim
        for point in trajectory.points:
            msg = JointState()
            msg.header = trajectory.header
            msg.name = trajectory.joint_names
            msg.position = point.positions
            self.publisher_.publish(msg)
            # Small sleep to simulate motion (Optional)
            # time.sleep(0.01)

        goal_handle.succeed()
        result = FollowJointTrajectory.Result()
        return result

def main(args=None):
    rclpy.init(args=args)
    node = IsaacActionBridge()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

まとめ

これでRViz2で動作のプランニングと実行をすると、Isaac Sim上でアームがその通りにシミュレーションしてくれるという流れを作ることができます。

TM Robotはソースコードを出してくれたのがとても助かりましたが、手取り足取りのドキュメントがあるわけではないので、読み解くのに少し時間がかかってしまいました。

RViz2上でExecuteを押した時にIsaac Simが動作した時は、これまでの努力が報われた瞬間でした。この情報が何かの役に立てば幸いです。

NVIDIA Isaac Sim 環境上のロボットをROS 2 Jazzyから動かす | Shirokuma.online