Skip to content

URDFへのセンサ情報の記述方法

このドキュメントでは、Isaac Sim上で動作するセンサ(および簡単なアクチュエータ)を ロボットのURDFに記述する方法と、その記述がisaac_ros2_utilsによって どのようにIsaac Sim上のオブジェクトへ変換されるかを解説します。

Gazebo ClassicではURDFの<gazebo>タグにセンサ情報を記述しますが、 このリポジトリでは<robot>タグ直下に置いた<isaac>タグで同じことを実現します。

<robot name="diffbot">
  ... リンクとジョイント ...
  <isaac>
    <sensor name="lidar_link" type="lidar"> ... </sensor>
    <sensor name="camera_link" type="camera"> ... </sensor>
    <surface_gripper name="body_link"> ... </surface_gripper>
    <thruster name="thruster_link"/>
  </isaac>
</robot>

name属性は常に、センサ/アクチュエータを取り付けるリンク名を指します。 ロボットのスポーン時に、launch_sensor.py(センサ)とrobot_controller.py (グリッパー・スラスター)がIsaac Simのステージ上からそのリンクのプリム (=USD上のオブジェクト)を探し出し、そこへセンサを取り付けます。

トピック名について: 生成されるROS 2トピックには、リンクのプリムパスが プレフィックスとして付きます。例えばロボットdiffbotlidar_link<topic>scan</topic>を指定すると、トピック名は /diffbot/Geometry/base_link/lidar_link/scanになります (Isaac Sim 6のURDFインポーターはリンクを/<ロボット名>/Geometry/以下に 配置します)。

空のリンクでも大丈夫: センサ用リンクはvisual/collisionを持たないことが 多いですが、Isaac Sim 6のインポーターはそのようなリンクを生成しません。 そのためlaunch_sensor.pyが、URDFのジョイントで指定された位置姿勢に Xform(座標フレーム)を自動で作成します。

LiDAR

<sensor name="lidar_link" type="lidar">
  <topic>scan</topic>
  <sensor_dimension_num>3</sensor_dimension_num> <!-- 2 or 3 -->
  <config>Example_Rotary</config>
</sensor>
タグ 意味
topic トピック名(リンクのプリムパスがプレフィックスに付きます)
sensor_dimension_num 2: sensor_msgs/LaserScanを配信 / 3: sensor_msgs/PointCloud2を配信
config LiDARのセンサモデル名(下記参照)

isaac_ros2_utilsの内部処理: リンクの下にRTX LiDARセンサ(Isaac SimのGPU レイトレーシングによるLiDAR)を生成し、ROS2RtxLidarHelperノードを持つ OmniGraphが物理ステップごとにスキャンを配信します。

configについて(Isaac Sim 6)

Isaac Sim 6では従来のJSON形式のLiDARプロファイルが廃止されました。LiDARは Isaac Simに同梱されたUSDセンサアセットとなり、名前で選択します。 指定できる名前には次のようなものがあります。

  • 汎用サンプル: Example_Rotary(3D)、Example_Rotary_2D(2D)、 Example_Solid_State
  • 実在センサ: SICK_TIM781SICK_microScan3RPLIDAR_S2EOS0 / OS1 / OS2(Ouster)、HESAI_XT32_SD10ZVISION_ML30S など

configに未対応の名前(旧Hokuyo設定など)を指定した場合、isaac_ros2_utilsは 対応している全ての名前を列挙した警告を出力したうえで、 sensor_dimension_numが2ならExample_Rotary_2D、それ以外ならExample_Rotary へ自動的にフォールバックします。

LiDARトピックにデータが来ない場合: トピックは存在するのに何も配信されず、 Isaac SimのログにCUDA Driver CALL FAILED ... PTX ... unsupported toolchain と出ている場合は、ホストのNVIDIAドライバーがIsaac Sim 6に対して古すぎます。 ドライバーを575以降へ更新してください。

カメラ

<sensor name="camera_link" type="camera">
  <topic>image_raw</topic>
  <horizontal_fov_rad>1.3962634</horizontal_fov_rad>
  <horizontal_focal_length>30</horizontal_focal_length> <!-- 光学パラメータ -->
  <vertical_focal_length>30</vertical_focal_length> <!-- 光学パラメータ -->
  <focus_distance>400</focus_distance> <!-- ピントが合う距離 -->
  <projection>perspective</projection> <!-- perspective または orthgonal -->
  <image>
     <width>600</width>
     <height>600</height>
  </image>
  <clip>
    <near>0.02</near>
    <far>300</far>
  </clip>
  <update_rate>10.0</update_rate>
</sensor>

isaac_ros2_utilsの内部処理: リンクの下にUSDのCameraプリムを生成します (ROSの慣習に合わせて、カメラがリンクの+X軸方向を向くよう回転されます)。 上記タグからアパーチャ・焦点距離・フォーカス距離・クリッピング範囲などの 光学属性が計算されます。IsaacCreateRenderProductROS2CameraHelperを持つ OmniGraphがカメラ画像をレンダリングし、sensor_msgs/Imageとして配信します。

カメラのグラフは再生ティックで動作するため、画像はシミュレーション再生中 のみ配信されます。

デプスカメラ

パラメータはカメラと同じで、typeのみ異なります。

<sensor name="depth_camera_link" type="depth_camera">
  <topic>image_raw</topic>
  <horizontal_fov_rad>1.3962634</horizontal_fov_rad>
  <horizontal_focal_length>30</horizontal_focal_length>
  <vertical_focal_length>30</vertical_focal_length>
  <focus_distance>400</focus_distance>
  <projection>perspective</projection>
  <image>
    <width>320</width>
    <height>240</height>
  </image>
  <clip>
    <near>0.1</near>
    <far>100</far>
  </clip>
  <update_rate>10</update_rate>
</sensor>

配信される画像は32bit floatのデプス画像です(ROS2CameraHelpertype: depth)。

ヒント: RViz2でデプス画像が真っ黒に見える場合は、画像表示設定の "Normalize Image"のチェックを外してください。

接触センサ

<sensor name="bumper_link" type="contact">
  <topic>contact</topic>
</sensor>

リンクが何かに接触している間trueとなるstd_msgs/Bool<リンクのプリムパス>/<topic>へ配信します。

isaac_ros2_utilsの内部処理: リンクに接触レポート (PhysxContactReportAPI)を有効化し、リンクのコリジョン形状の下に Isaac Simの接触センサプリムを生成します。IsaacReadContactSensorROS2Publisherを持つOmniGraphが物理ステップごとに接触状態を配信します。

注意: 接触センサはコリジョン形状を必要とします。リンクにcollision タグが必要です。

吸着式グリッパー(surface gripper)

surface gripperは、吸着パッドのようにグリッパー面へ近づいた物体を掴む 機構です。<isaac>タグ直下に記述します。

<surface_gripper name="body_link">
  <topic>gripper_enable</topic>
  <offset_x>1.0</offset_x>
  <offset_y>0</offset_y>
  <offset_z>0</offset_z>
  <axis>1 0 0</axis>
  <grip_threshold>0.1</grip_threshold>
  <force_limit>1.0e2</force_limit>
  <torque_limit>1.0e3</torque_limit>
  <bend_angle>0.7854</bend_angle>
  <stiffness>1.0e4</stiffness>
  <damping>1.0e3</damping>
  <retry_close>False</retry_close>
</surface_gripper>
タグ 意味
offset_x/y/z リンク座標系におけるグリッパー面の位置 [m]
axis リンク座標系における吸着方向(±1 0 00 ±1 00 0 ±1のいずれか)
grip_threshold 物体を掴める最大距離 [m]
force_limit 吸着方向の最大保持力 [N]
torque_limit 最大保持(せん断)トルク [N·m]
retry_close True: 物体を掴めるまで吸着を試行し続ける
bend_anglestiffnessdamping 旧バージョンとの互換用(Isaac Sim 6では現在使用されません)

グリッパーは<リンクのプリムパス>/togglestd_msgs/Boolを配信して 操作します(true=閉じる/吸着、false=開く/解放)。

isaac_ros2_utilsの内部処理: Isaac Sim 6ではIsaac Simのロボットスキーマを 使って構築されます。robot_controller.pyIsaacSurfaceGripperプリムと アタッチメントポイント(指定オフセットの位置でaxis方向を向く、リンクに 固定されたD6ジョイント)を生成します。グリッパーを閉じると、Isaac Simが axis方向grip_threshold以内の剛体を探し、ジョイントを介してリンクに 固定します。保持力がforce_limit/torque_limitを超えると物体は外れます。 OmniGraphがtoggleトピックを購読し、グリッパーの開閉APIを呼び出します。

スラスター

スラスターはリンクの+Z軸方向へ推力を与える機構です。宇宙ロボットや 水中ロボットに使えます。

<thruster name="thruster_link"/>

推力[N]をstd_msgs/Float64として<リンクのプリムパス>/forceへ配信して ください。値が0でない間、物理ステップごとに、リンクの位置に、リンクの +Z軸方向の力が加わります(負の値で逆方向)。

isaac_ros2_utilsの内部処理: OmniGraphがforceトピックを購読し、 PhysXの力適用APIでスラスターリンクのワールド姿勢に力を加えます。 スラスターリンク自体が形状を持たない(=剛体でない)場合は、最も近い 剛体の祖先リンクに対して、スラスターリンクの位置で力を加えるため、 モーメントアームは正しく考慮されます。