ROSのTFとは?簡単に説明(サンプルコード付き)

はじめに

ROSの便利機能にして基本機能TF(Transform、トランスフォーム)について、出来るだけ難しい言葉を使わずに説明していきたいと思います。

static transformの書き方

TFとは?

TF(transform)とは「ある座標系」と「他の座標系」の位置関係を表すものです。

座標系とは基準点のことで、例えば部屋の基準点なら部屋の隅、ロボットの基準点なら重心、センサの基準点ならセンサ底面などです。

例として次のような車輪ロボットを考えてみます。

車輪ロボットとセンサ

このとき、ロボットの重心位置においたbase_link座標系からセンサのlaser座標系に行くには「x方向に20cm、z方向に10cm」と表現できます。これが「TF」です。

※ 正確には、2つの座標系の関係を3次元で表すには、位置(x,y,z)と姿勢(ロール、ピッチ、ヨー)の6つのパラメータが必要です。また、姿勢を4つのパラメータで表す方法(4元数、クォータニオン)もあります。

TFの特徴

複数のTFをつなげることが出来る

TFは2つの座標系の位置関係を表すものですが、普通ロボットや自動車は沢山の部品で出来ています。それらを1つの基準点(たとえば上の図のロボット座標系)からすべて表すのは大変です。
したがってTFは数珠つなぎに記述することが一般的です。例えば先程のロボットの例で、車体の上面の中心にtop_center座標系を作るとレーザセンサやカメラまでの位置を計測しやすくなるため便利になります。base_link座標系→top_center座標系→laser、camera座標系と数珠つなぎになっているのが分かります。

ロボットの座標系

ROSでは座標系のことを「frame(フレーム)」と呼びます。rvizに表示される黄色の線は「あるフレーム」から「他のフレーム」へのTF、つまり一方のフレームから見たもう一方のフレームの位置と姿勢がROSに登録されている事を示しています。元になるフレームを「parent frame(親フレーム)」または単に「frame」、目的のフレームを「child frame(子フレーム)」と呼びます。

2フレーム間のTFをROSに登録する

ROSで利用するすべてのTFはROSシステムに登録されます。親フレーム名、子フレーム名、位置関係、タイムスタンプ等の情報をメッセージにまとめてROSに送信します。またTFには有効期限があるため、1度登録したら終わりではなく10ms毎など定期的に登録し直す必要があります。(例外として、有効期限が無いstatic_transformというものもあります)

つながっているTF同士の位置関係は自動計算される

すべてのフレーム間の位置関係をROSに登録しておくことで、任意の2フレーム間のTFをROSが自動計算してくれます。例えば上の例でbase_linkフレームとcameraフレームは直接繋がっていませんが、これを自動計算できる仕組みがROSに備わっています。

逆に、TFが途中で切れていると、2フレーム間のTFが取得できず、エラーになります。

ROSに登録されてから一定時間経つと無効になる

TFは一度誰かが発信してROSシステムに登録された後、一定時間経つと無効になります。ずっと表示させたければすべてのTFを定期的に再発信する必要があります。

静的TFと動的TF

TFには例えばロボットのセンサのように位置関係が永久に変わらないものと、部屋からみたロボットの位置のように変わり続けるものがあります。前者を静的TF、後者を単にTFと言います。

TFを発信する

静的TFを発信するコードを書いてみます。最も簡単なのは次のようなlaunchファイルを作ることです。

<launch>

  <node pkg="tf" type="static_transform_publisher" name="robot_to_sensor" args="0.2 0 0.1 0 0 0 robot sensor 10" />

</launch>

「<node」 から 「/>」までがTFを発信するプログラムを実行する部分です。それぞれの引数の意味は次のとおりです。

引数値の例備考
pkg“tf” (固定)パッケージの名前
type“static_transform_publisher” (固定)プログラムの名前
name“(任意の名前)”実行時の名前。同名のプログラムがあると実行できないので適宜変更。
args(例)”0.2 0 0.1 0 0 0 robot sensor 10″
“[x] [y] [z] [yaw] [pitch] [roll] [parent_frame] [child_frame] [Hz]”
x方向、y方向、z方向、ヨー、ピッチ、ロール、親フレーム、子フレーム、発信の間隔[Hz]

nameが同じプログラムを同時に作るとエラーになります。これを自分のパッケージ→lanchフォルダの中に入れて実行すると、argsで指定したTFが発信されます。

roslaunch my_package static_tf.launch

発信されているTFをrvizで見てみましょう。rvizを起動して、左下部あたりにある「Add」をクリック、「By display type」から「TF」を追加して下さい。

静的TFが表示された!

2つの座標軸が表示されていれば成功です!
rvizの左側の「Fixed Frame」を「robot」や「sensor」に切り替えることで、どのフレームを中心に据えるか選ぶ事が出来ます。lanchファイルで複数のプログラムを起動すれば、TFの数珠つなぎも簡単に実現できます。

<launch>

  <node pkg="tf" type="static_transform_publisher" name="robot_to_sensor" args="0.2 0 0.1 0 0 0 robot sensor 10" />
 <node pkg="tf" type="static_transform_publisher" name="map_to_robot" args="1.0 0.5 0 0 0 0 map robot 10" />

</launch>

しかし、これだと常に同じTFしか発信できません。
次回は常に変化する位置関係の発信方法をご紹介したいと思います。

ROS初心者の方はまずはこちらの本がオススメです。

動的TFの書き方>>

「ROSのTFとは?簡単に説明(サンプルコード付き)」への2件のフィードバック

  1. 指摘が間違っていたらすみません。
    static_transform_publisherの引数ですが、yaw pitch rollの順だと思います。

    1. その通りです、間違っていました。該当箇所を修正しました。
      ご指摘ありがとうございます。

ppdr へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA