Help us understand the problem. What is going on with this article?

ROSのtf2で位置姿勢を計算する

More than 1 year has passed since last update.

位置姿勢計算にtfを使う

ROSには位置姿勢を表現するためにtfという便利な仕組みがあります.
チュートリアルやサンプルを見ていても,すでに発行されている複数のtfからtfを取得したりする例はよく見るのですが,プログラム内の計算でもtfが使えるのでここにまとめます.
ただし,自分はkineticしか使っていないので,その範囲でしか確認していません.

ちなみに,こういう計算の例とかが載っているチュートリアルがあったら教えてください…
Class referenceあれば十分だろ,って姿勢ですかね…

tfとtf2

tfには,tfとtf2が存在し,チュートリアルなんかも未だにtfで書かれているものが多いんですが,tfのwikiをみると

Migration: Since ROS Hydro, tf has been "deprecated" in favor of tf2. tf2 is an iteration on tf providing generally the same feature set more efficiently. As well as adding a few new features.

なんて書かれています.
なので,なにか理由がない限りはtf2を使うことにしましょう.

ただ,面倒なので,このページではこのあともtf2をさしてtfと書くことにします.

tf2の準備

インストール

sudo apt install ros-kinetic-geometry2

geometry2がメタパッケージになっていて,tf2関連をまとめてインストールできます.

実際に使うパッケージ類

上記でインストールすると,次のパッケージ群がインストールされるはずです.

  • tf2
  • tf2_bullet
  • tf2_eigen
  • tf2_geometry_msgs
  • tf2_kdl
  • tf2_msgs
  • tf2_py
  • tf2_ros
  • tf2_sensor_msgs
  • tf2_tools

この中から必要なものを依存関係に書いてコンパイルします.
基本的にはtf2とtf2_geometry_msgsとtf2_rosがあればいいかと思います.
構成としては,tf2が基本で,それ以外がtf2の拡張パッケージという感じです.
特に各型の変換が必要な場合には,使う型によって依存パッケージを追加します.

計算してみる

メッセージとtfの変換

便利にtfで計算するためには,tfで使われるクラスになっていると楽です.
そのため,まずはROSでやり取りされるメッセージをtfで使われるクラスに変換します.

各種定義は,公式ドキュメントを参照しましょう.
convert,fromMsg, toMsg などが見どころです.
基本的にどの関数もテンプレートとオーバーロードを使いまくって定義されているので,いろいろな型の間で変換が可能です.
(それゆえ何が何に変換できるのか見通しが悪いともいう)
tf2以外のパッケージ(tf2_geometry_msgsとか)にも各変換関数が定義されているので,そちらも要確認です.

メッセージからtfに変換

#include <tf2/convert.h>
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>

//geometry_msgs::Transform msg を受け取るコールバックだとして.
tf2::Transform tf;
tf2::convert(msg, tf);    // msg から tf に変換される

tfからメッセージに変換

なんでかこれはconvertがうまくできない.ヒントを渡してもダメ.教えて偉い人.

#include <tf2/convert.h>
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>

geometry_msgs::Transform msg;
tf2::Transform tf;
tf2::toMsg(tf, msg);    // tf から msg に変換される

stampedなんちゃらへの変換

tfの各型にはタイムスタンプを持つ機能がないので,タイムスタンプだけ持つ型がその他の位置姿勢等のデータ型をもてる仕組みになっています.

たとえば,タイムスタンプありのtransformは次のように定義できます.

tf2::Stamped<tf2::Transform> stamped_transform;

これを使うと,次のような変換もできます.

geometry_msgs::TransformStamped msg = tf2::toMsg(tf2::Stamped<tf2::Transform>(tf, ros::Time::now(), frame_id));
msg.child_frame_id = child_frame_id;

sendTransformをするときなんかに便利です.が,child_frame_idの設定をし忘れないように.

tfを使った計算

Transform 同士の計算

表現したいものがtfになったら勝ちです.
あとはひたすら計算するだけです.

例えば,2つのtfの姿勢の差をとりたいときはこんな感じです.

tf2::Transform tf1, tf2, tf_delta;
tf_delta = tf2.inverse() * tf1;

tfの差なんてlookupTransformすればいいじゃん,となるかもしれませんが,先述の通り,geometry_msgsから変換したtfでこの計算ができるので,まだtfになっていないもので計算ができます.

quaternion の線形補間

tfのそれぞれの型は,演算子のオーバーロードも多くされているので,スカラーとの計算も楽です.

2つのquaternionを補間する例は次のようにかけます.

double d = 0.1;
tf2::Quaternion q1, q2;  // 入力のQuaternion
tf2::Quaternion q = q1 * d + d2 * (1.0 - d);

Vector3のほうも同様にスカラーと計算できるので,前述のtfの差の位置と姿勢をそれぞれ線形補間する,なんてこともできます.

まとめ

ロボットの位置姿勢の計算には必須な同次変換が簡単に表現できるうえ,内部はQuaternionで実装されているので,ジンバルロック問題もありません.
ROSでプログラムを書くときにわざわざ自分で位置姿勢の計算を要素ベースでしなくてはならないことはほぼないでしょう.
2次元の場合でも,tfを使ってやると便利だと思います.

strv
ロボットつくるひと.ソフトは苦手.ロボットベンチャーで働いてるよ
http://strv.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした