ROS(Robot Operating System)を使う
安曇野の森から > ROS(Robot Operating System)を使う > ロボット記述言語
ROSにはロボットを3Dモデル化するための記述言語としてURDF(Unified Robot Description Format)とXacroの2つの言語が用意されています。
以下ではこれらの記述言語について説明します。
左図の3D CGはロボット記述言語のURDFとXacroで作成したKHR-3HVの3Dモデルを視覚化ツールRvizで表示したものです。
URDFはロボットのモデルをXML形式で記述したものです。
モデルの3D形状、表面の見え方、動作、動作限度、慣性等物理特性などを定義することが出来ます。また、センサーの定義も可能です。
URDFで定義したロボットのモデルはrvizで3D表示したり、Gazeboで物理シミュレーションすることが出来ます。
URDFファイルはファイル拡張子が.urdfです。
URDFファイルには日本語を入れるとエラーになるのでコメントの記載には注意が必要です。
URDFで使用する座標系と単位の定義は以下のとおりです。
位置や大きさを表現するためのデカルト座標系x, y ,zの向きは左手の親指、人差し指、中指をそれぞれ直角になるようにして親指を自分がわに向けた時、親指の向いている方向(手前向き)がx方向、人差し指の向いている方向(右向き)がy方向、中指の向いている方向(上向き)がz方向になります。
また、座標の原点は3つの指の根本になります。
回転を表現するためのオイラー角roll, pitch, yawの回転方向は軸の向いている方向を見た時に全て時計まわりで定義され、rollはx軸回りの回転、pitchはy軸回りの回転、yawはz軸回りの回転になります。
設定値の単位は以下のようになります。
設定値 | 単位 |
---|---|
長さ | m |
角度 | radian |
質量 | Kg |
力(並進) | N |
力(回転) | N・m |
速度(並進) | m/s |
速度(回転 | radian/s |
URDFではリンクとジョイントにより、ロボットのアーム等を構成します。
以下ではサンプルURDFファイルで定義している2つのリンクとそれをつなぐ1つのジョイントがあるロボットアームの例を使って説明します。
リンクは左図のような構造をしています。
リンクの原点はディフォルトでは重心位置になります。
この図ではリンクを基準平面に設置させるため、ビジュアルの原点をワールド原点に合わせています。
このリンクが親リンクとなります。
左図では上記の親リンクにつながるジョイントを示しています。
ジョイントの位置は親リンクのビジュアル原点からの相対位置で決まります。この例では親リンクのビジュアル原点から(x=0, y=0.02, z=0.045)の位置をジョイントとしています。
また、ジョイントが回転する場合、XYZのいずれかの軸を選択しなければなりません。この図の例ではジョイントはY軸まわりに回転するよう定義されています。
左図は上記ジョイントにつながる子リンクを示しています。
子リンクの原点は重心に対するジョイント原点からの相対位置によって決まります。
URDFで使えるジョイントの動作定義は以下の5つです。
これだけで、ほとんどの機構の動作は記述出来ます。
設定値 | 意味 |
---|---|
fixed | 固定 |
revolute | 動作角度制限のある回転 |
continuous | 連続回転 |
floating | |
planar |
URDFで使える3D基本形状定義は以下の4つだけです。
複雑な形状を表示するには他の3Dデザインソフトで作成したmeshを張り付けます。
設定値 | 意味 |
---|---|
cylinder | 円筒 |
box | 箱 |
sphere | 球 |
mesh | メッシュ |
URDFで使えるモデル表面定義は色とテクスチャの2つだけです。
色はr, g, b, aを0〜1の数値で定義します。ここでrgbは色の3原色、aは透過率です。
テクスチャはxxxxxxxxxxxxxxxで定義します。
設定値 | 意味 |
---|---|
color | 色 |
texture | テクスチャ |
URDFファイルは基本的にリンク定義とジョイント定義の2つから構成されます。
URDFファイルでは、これらの定義が以下のように<robot>タグで挟まれた形になります。
また、<robot>タグ内ではロボットの名称を定義します。
左図はサンプルモデルをrvizで表示したものです。
このような角棒のベースに角棒のアームが一本だけ付いたURDFモデルは以下リストで定義出来ます。
以降で、このモデルを使ってリンク定義とジョイント定義の説明をします。
後で実際に動かして見るためパッケージディレクトリ内にurdfディレクトリを作成し、その中にファイル名one_arm.urdfとして作成してください。
以下のように<link>タグで挟まれた部分がリンク定義になります。
タグ内でリンクの名称を「name="base"」のように設定します。
<link>タグ内の<visual>タグ内でリンクの大きさと見た目を定義します。
<visual>タグ内の<getometry>タグでリンクの形状と寸法を設定します。
タグ先頭に記述されるリンクの形状には前述の「box, cylinder, sphere, meshn」の4つから選べます。
以下の例では「box」が設定されています。
リンクの寸法はsizeにx, y, zの寸法をスペースで区切ってメートルで指定します。
<visual>タグ内の<origin>タグでリンクの位置と回転を定義します。
リンクの回転はrpyにroll, pitch, yawの回転角をスペースで区切ってラジアンで指定します。
リンクの位置はxyzにx, y, zの原点からの距離をスペースで区切ってメートルで指定します。
<visual>タグ内の<material>タグでリンクの見た目とmaterialの名前を定義します。
見た目には前述の「color, mesh」が選べます。
以下ではmaterialの名前としてgrayを定義し、表面色をrgbaの値で定義しています。
materialの名前を定義しておくと、それ以降はrgba値を設定せずに、material名だけで色を設定することが出来ます。
rgbaのrは赤色を0〜1の明るさ、gは緑色を0〜1の明るさ、gは青色を0〜1の明るさ、aは透明度を0〜1で設定します。
color以外にも3Dのmeshデータを設定することも出来ます。
この場合は以下のようにmeshデータのファイル名を指定します。
以下のように<joint>タグで挟まれた部分がジョイント定義になります。
タグ内でジョイントの名称を「name="base"」、ジョイントのタイプを「type="revolute"」のように設定します。
タイプには前述の「fixed, rovolute, continuous, float, planner」の5つから設定出来ます。
<joint>タグ内の<parent>タグにはジョイントの接続元(親)の名前を設定します。
<joint>タグ内の<child>タグにはジョイントの接続先(子)の名前を設定します。
<joint>タグ内の<origin>タグにはジョイントの親リンク位置からの相対位置を設定します。
<joint>タグ内の<limit>タグには
URDFファイルの記述に間違いがないかチェックするには以下のコマンドを使います。
URDFモデルをRvizで表示させるには以下のようなローンチファイルを作成し、roslaunchコマンドで実行させます。
上記ローンチファイルをパッケージディレクトリ下にlaunchディレクトリを作成し、その中にファイルdisplay.launchとして保存します。
one_arm.urdfファイルをrviz上に表示させるには、以下のコマンドを実行します。
また、「gui:=true」を引数として指定すると関節操作用スライダーが関節分だけ表示されたGUIが表示されますので、そのGUIを使ってrvizに表示されているモデルを動かしてみることが出来ます。
ローンチファイルを実行させると左図のような画面が表示されます。
また、同時に左図のようなjont_state_pubilisherのGUI画面が表示されます。この画面のスライダーを左右に動かすことによりrviz内のアームを回転させることが出来ます。
rvizに3Dモデルを表示するだけであれば、これまでの定義だけで十分です。
さらに物理シミュレーションを行うには、これまでの定義以外に衝突検出領域定義と慣性行列定義が必要になります。
以下に衝突検出領域定義と慣性行列定義の例を示します。
以降で、この例を使って衝突検出領域定義と慣性行列定義の説明をします。
<collision>タグ内が衝突領域の定義です。定義内容はリンクの定義と同じです。
この定義を使って2つ以上のリンクが互いに衝突していないかを検出します。
<inertial>タグ内が慣性行列領域の定義です。
<mass>タグでリンクの質量をKgで設定します。
<inertia>タグで慣性行列を設定します。値が0の行列要素は記載する必要はありません。
実際の慣性行列の計算は複雑なので、以下ではURDFで設定可能な標準形状についてあらかじめ求められている慣性行列の計算式ついて説明します。
関数行列の要素は左図のようになっています。
高さ:c、幅:b、奥行き:a、質量:mとした場合の慣性行列の要素計算式は以下のようになります。
以下以外の要素は0です。
ixx = 1 / 12 x m x (b^2 + c^2)
iyy = 1 / 12 x m x (a^2 + c^2)
izz = 1 / 12 x m x (a^2 + b^2)
高さ:h、半径:Rとした場合の慣性行列の要素計算式は以下のようになります。
以下以外の要素は0です。
ixx = iyy = 1 / 4 x m x R^2 + 1 / 12 x m x h^2
izz = 1 / 2 x m x R^2
半径:Rとした場合の慣性行列の要素計算式は以下のようになります。
以下以外の要素は0です。
ixx = iyy = izz = 1 / 5 x m x R^2
XacroはURDを使い易くするための一種のマクロ言語です。
最終的には変換ツールを使ってXacroをURDFに変換してからrvizやGazeboで利用します。
Xacroを使うには最初に固有の名前空間を定義する必要があります。
名前空間の定義には先頭に以下の2行が必要です。
Xacroでは定数定義してXacro内で使うことが出来ます。
Xacroでは四則演算が使えます。
ただし、四則演算が使えるのは${}内だけです。
Xacroではマクロを定義することが出来ます。このマクロによりURDFをモジュール化することが出来ます。
例えば腕は1つだけXacroファイルを作成してそれを2つのモジュールとして胴体に付けるといったことが出来ます。
同一形状のラジコン用サーボモーターを多数使用するロボットでは、このジュール定義は非常に便利です。
XacroをGazebo,やrvizで使うには一度URDFに変換する必要があります。
変換は以下のコマンドで行います。
2015年時点での変換プログラムは、まだエラー検出機能が弱くPythonのエラーを、そのまま表示してしまうこともあるので、肝心のXacroやURDFのどこに間違いがあるのかを見つけるのが大変です。
また、変換後のURDFファイルをチェックするにはURDFファイルと同様に以下のコマンドで行います。
ROSではURDFで作成したモデルをrvizに表示し、プログラムからrvizの中でモデルを動かすことが出来ます。
以下はURDFで作成したロボットモデルをrviz内で動かすためのサンプルプログラムです。
このプログラムでは一定周期(以下のプログラムでは10Hz)でジョイントの角度とロボットの位置を更新します。
ただし、以下のプログラムにはジョイントの角度やロボットの位置の初期化や更新する処理は入っていませんので、実際にプログラムを動かすにはサンプルプログラムの中で()で指定している箇所に初期化と更新の処理を追加する必要があります。
サンプルプログラムを動かすために必要なインクルードファイルは以下の4つです。
ROS用としては下の3つが重要です。
ros.hがROSの基本的な定義、JointState.hはジョイントの角度をメッセージとして発行するため、transform_broadcaster.hはロボットの位置をメッセージとして発行するために使います。
1行目でROSの初期化、2行目でノードハンドルオブジェクトnhを生成します。
ノードプログラムにお約束の2行です。
1行目でノードハンドルからジョイント角度の送信用publisherオブジェクトpubを生成します。また、2行目で位置送信用のbroadcasterオブジェクトtbcを生成します
1行目でロボットの位置を格納するTransformStampedメッセージオブジェクトtsmを生成します。
2行目でロボットのジョイント角度を格納するJointStateメッセージオブジェクトjsmを生成します。
3、4行目でtsmにロボットのベースとなるフレーム名とリンク名を設定します。、全ての変換はこのベースフレームを参照して行われます。
以降の行でジョイント数によりjsmメッセージサイズの設定とサイズ数分のジョイント名を設定します。
次に以下プログラムには具体的な処理は記載されていませんが、ロボットジョイント角度と位置用の変数を定義し、その変数の初期化を行います。
1行目でジョイントメッセージに送信時間を設定します。
以降の行で全てのジョイントの角度をメッセージに設定します。
1行目でロボット位置メッセージに送信時間を設定します。
以降の行でロボット位置XYZとYaw角をクォータニオンへ変換したものをメッセージに設定します。
ジョイントメッセージとロボット位置メッセージと送信します。
次に以下プログラムには具体的な処理は記載されていませんが、ロボットジョイント角度と位置用の変数の値を更新します。
後は上記5〜7の処理をロボットが最終姿勢・位置に移動するまで一定周期で繰り返すだけです。
上記サンプルプログラムを動作させるためにはプログラム本体に加えてrobot_state_publisherとrvizも一緒に起動する必要があります。
個別に起動するのは面倒なので以下のローンチファイルを作って、これらのノードをまとめて起動させます。
上記、ローンチファイルを以下のコマンドで実行するとrvizが起動し、rviz内でロボットが動き始めます。