Transform 対応#
基本的な挙動#
Broadcaster側#
- broadcaster側は、sendTransformを実行したスレッドがそのままpublishしている
- TransformBroadcasterのコンストラクタに与えたノードで 新規にpublisherが作られる(該当コード)
- sendTransformに入力するメッセージの型はgeometry_msgs::msg::TransformStamped。
- 内部では、tf2_msgs::msg::TFMessageへ変換して/tfトピックへpublishしている。
#geometry_msgs/TransformStamped.msg
std_msgs/Header header
string child_frame_id
geometry_msgs/Transform transform
#tf2_msgs::msg::TFMessage
geometry_msgs/TransformStamped[] transforms
listener側#
最新の座標データを保持した座標データのバッファを介して以下が行われる
- /tfトピックから受け取ったメッセージの保存 (常にバッファを最新にさせるため、別スレッドで処理を行わせるのが基本。)
- チュートリアル通りにtf2ros::TransformListener(buf) と使った場合: /tfのsubscribe、バッファの更新は非同期に行われる。(非同期に行いたかったという旨が論文にかかれている) 新規スレッド&新規エグゼキュータ&新規ノードが作成させる Listener毎に transform_listener_impl** 名前を持ったノードが作成される(だから量産されてる) 対応するコンストラクタ
新規スレッドを立ち上げさせず、アプリケーション側で制御する方法もある。(動作未確認)
ノードも引数に与え、こっちのコンストラクタでListenerを構築すること。 スレッドやエグゼキュータの生成も行われず、引数に与えたノードで/tfのsubscribe&バッファの更新が行われる
lookupTransformなどを受け付け、指定された時刻の座標変換を取得 (こちらはアプリケーション側が呼ぶAPI)
デフォルトだと、10秒前まで座標を遡れるようになっている。 https://github.com/ros2/geometry2/blob/16562cee8694c11f1f82b2bdbde2814fca1c7954/tf2/include/tf2/buffer_core.h#L70
tfの動作シーケンス図#
トレースポイントの挿入箇所 https://github.com/ros2/geometry2
※ シーケンス図は説明のために簡略化しています。
TransformBroadcasterがrclcpp::publishするまで
メッセージ受信からBufferに格納するまで
lookupTransformを実行してBufferから取得するまで
waitForTransformを実行
TransformStampedFuture使用ケース
中身はC++のFuture。そのまま使うことができる。 その他、rclcpp.spin_until_future_complete()なども使用できる。
using TransformStampedFuture =
std::shared_future<geometry_msgs::msg::TransformStamped>;
using TransformReadyCallback =
std::function<void (const TransformStampedFuture &)>;
waitForTransformの引数であるTransformReadyCallbackを使用するケース