URDFとは

URDF (Unified Robot Description Format)は、ロボットの構造を記述するためのXMLのフォーマットです。

ROSでは、URDFで記述されたロボットの情報をもとに、ロボットの状態をわかりやすい3D画像で表示したり、動作シミュレーションを行うことができます。

このページの後方にあるURDFの例を見ると、リンクと関節の情報などが記述されていることがわかります。また、URDFのチュートリアルにも Create your ownurdf file の分かりやすい例があり、イメージはつかめると思います。

詳しくは、ROSのurdfページをご覧いただくとして、ここでは私が設計したパンチルト・カメラのURDFを記述してみます。

まず覚えておくこと

ROSでは、MKS単位、右手系を使用します。

(単位は、メートル、秒、ラジアンを使い、座標軸は右手の親指、人差し指、中指を広げ、それぞれX,Y,Zとなる向き、回転の向きは右ネジを締める方向)

なお、RVizなどで座標軸を表示する際には、X軸:R(赤) Y軸:G(緑) Z軸:B(青)で表します。

ロボット記述パッケージの新規作成

ロボットの情報は、URDFファイルだけで完結するわけでなく、部品の外観を表す3Dのメッシュ情報も必要だったりします。また、作成したロボットのモデルを表示させるために、起動ファイル(launchファイル)を用意したりします。

これらのファイルなどもまとめて、ロボットを記述するパッケージを作成します。

ROSでは、ロボット記述のパッケージは慣例で"ロボット名_description"と銘々しているので、ここでは"ptcam_description"パッケージを作成します。

cd catkin_ws/src
mkdir ptcam
cd ptcam
catkin_create_pkg ptcam_description roscpp rospy urdf
cd ptcam_description
mkdir urdf
mkdir meshes
mkdir launch
cd ~/catkin_ws
catkin_make
rospack profile
		

最も簡単なURDFを作成する

上で作成したurdfフォルダに、pan_tilt_camera.urdfを以下の通り作成します。


<?xml version="1.0"?>

<robot name="pan_tilt_camera">
  <link name="base_link">
    <visual>
      <geometry>
        <cylinder length="0.6" radius="0.2"/>
      </geometry>
    </visual>
  </link>
</robot>
		

これは、1つのリンク"base_link"だけからなる"pan_tilt_camera"ロボットを記述したURDFです。

base_linkは、長さ0.6m, 半径0.2mの円筒形です。

launchファイルを作成してRVizで表示してみる

作成したURDFを表示するためのlaunchファイル、ここでは"launch/display.launch"を作成します。


<launch>
	<arg name="model" />
	<arg name="gui" default="True" />
	<param name="robot_description" textfile="$(arg model)" />
	<param name="use_gui" value="$(arg gui)"/>
	<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />
	<node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />
<!--	<node name="rviz" pkg="rviz" type="rviz" args="-d $(find ptcam_description)/urdf.rviz" required="true" />  -->
</launch>
		

これを次のようにroslaunchで起動し、RVizを起動します。

$roslaunch ptcam_description display.launch model:=`(rospack find ptcam_description)`/urdf/pan_tilt_camera.urdf
$rosrun rviz rviz
		

RVizで[Add]をクリック、[RobotModel]を選択して"Displays"にRobotModelを追加します。

次に"Global Option"の"Fixed Frame"でbase_linkを選択すると、表示の基準座標系がbase_linkになり、base_linkが表示されます。

RVizの画面には、URDFで記述した”ロボット”が表示されます。

RViz中央画面でマウススクロールで拡大/縮小、ドラッグで回転、Shift+ドラッグで移動できます。

3D CADからメッシュデータを出力する

3Dのメッシュデータ(STLやCOLLADAの.daeファイル)を用意すれば、それをリンクの部品としてRVizの画面に表示することができます。

そのために、設計したロボットのメッシュデータを3D CADを用いて出力します。

まずは、どの部分をURDFの"リンク"で表現するのか、決定しなければなりません。 今回は、ベース部分、モータが載った回転台の部分(パンする部分)、カメラをつけた腕の部分(チルトする部分)の 3つの部分に分け、これらをそれぞれリンクで表すこととしました。

それぞれの部分(Assembly)ごとに、STLを出力するだけ、なのですが、注意すべきことがあります。それは、ROSの座標系と単位に合ったSTLを出力するということです。

私の使用する3D CAD、Autodesk Inventorでは、右、上、前がそれぞれX,Y,Zに対応します。 これらの向きに部品を拘束するとともに、関節となる軸もX/Y/Z軸のいずれかに拘束します。また、単位はメートルを指定します。

URDFでもメッシュデータの回転やサイズ、関節の位置と向きの指定ができるので、どんなSTLでも読み込んで使うことはできるのですが、三次元の回転を考えるのは難しく間違いやすいので、3D CADで確認しながらSTLの座標を合わせてしまった方が楽です。

メッシュデータを読み込み、部品を3Dで表示する

上で作成したURDFを変更し、ベース部分を表示してみます。 次のようにURDFを変更します。


  <geometry>
    <mesh filename="package://ptcam_description/meshes/BaseUnit.stl"/>
  </geometry>
	

これをRVizで表示してみます。前にroslounchで起動したノードを終了(Ctrl+C)し、再び起動します。次にRVizのRobotModelのチェックボックスをOff->Onすると更新されたURDFのロボットが表示されます。

きちんとベース部分を読み込んで表示することができました。 単位と座標系が合っていることを確認します。

ジョイントとリンクを追加してURDFを完成させる

ベース部分にパンする部分とチルトする部分を追加してロボット全体を完成させます。

先のURDFにリンク2つとそれらを結合する関節2つを追加します。以下のURDFができました。


<?xml version="1.0"?>


<robot name="pan_tilt_camera">

  <link name="base_link">
    <visual>
      <geometry>
        <mesh filename="package://ptcam_description/meshes/BaseUnit.stl"/>
      </geometry>
      <material name="red">
        <color rgba="0.5 0 0 1"/>
      </material>
    </visual>
  </link>

  <link name="pantbl_link">
    <visual>
      <geometry>
        <mesh filename="package://ptcam_description/meshes/PanUnit3.stl"/>
      </geometry>
      <material name="green">
        <color rgba="0 0.7 0 1"/>
      </material>
    </visual>
  </link>

  <link name="cam_link">
    <visual>
      <geometry>
        <mesh filename="package://ptcam_description/meshes/CamUnit3.stl"/>
      </geometry>
      <material name="blue">
        <color rgba="0 0 0.7 1"/>
      </material>
    </visual>
  </link>

  <joint name="base_to_pantbl" type="revolute">
    <parent link="base_link"/>
    <child link="pantbl_link"/>
    <origin xyz="0 0 0.00197" rpy="0 0 0"/>
    <axis xyz="0 0 1"/>
    <limit effort="1000.0" lower="-1.5" upper="1.5" velocity="0.5"/>
  </joint>

  <joint name="pantbl_to_cam" type="revolute">
    <parent link="pantbl_link"/>
    <child link="cam_link"/>
    <origin xyz="0.01195 -0.01223 0.0168" rpy="0 0 0"/>
    <axis xyz="0 1 0"/>
    <limit effort="1000.0" lower="-1.5" upper="1.5" velocity="0.5"/>
  </joint>

</robot>
		

ベース部分からいきなり2つの関節を追加したのではなく、リンクと関節を1つずつ追加していきました。

なお、関節は位置と回転軸を指定する必要がありますが、先ずは関節タイプを"fixed"にしておいて位置を確認し、その後関節タイプを"revolute"にして軸を指定すると簡単で確実です。

関節位置は、3D CADで計測します。

RViz画面上で動かしてみる

できあがったURDFをRVizで表示します。

jointのtypeを"revolute"にしているので、JointStatePublisherノード(これは.launchファイルで起動される)のGUIに2つの関節のスライドバーが現れます。これをスライドすると、RViz画面上のロボットが動きます。

もっと複雑・多機能なURDFでは

今回は、2関節の簡単なロボットを記述しましたが、複雑なロボットになるとURDFがとんでもない長さになって編集が大変になることは容易に想像できます。

そのために、xacroがあります。xacroを利用すれば、パラメータやマクロを使ってもっと見やすく、階層構造をもった記述もできます。

例題のロボットの構造が簡単であることだけでなく、xacroを使わないでURDFを直接書いた方が仕組みがわかりやすいため、以上の説明にしました。

また、URDFはシミュレーションなどで利用できる、情報をさらに多く書き込むことができます。例えば慣性モーメント(inertia)や衝突検出(collision)などがありますが、ここではそれらも記述していません。 また機会があればそれらについても書いてみたいと思います。