![見出し画像](https://assets.st-note.com/production/uploads/images/142568872/rectangle_large_type_2_30ab9b8ea1aa67cb24f112d19335b2a7.png?width=1200)
Self Driving and ROS 2 - Learn by Doing! Odometry & Control: TF2リスナー (セクション8-3/13)
TF2ライブラリを使って、静的および動的なフレーム間の変換をブロードキャストおよびリスンする方法を学びました。
PythonとC++の両方で、サービスサーバーを作成し、特定のフレーム間の現在の変換を提供する実装例を示しました。
静的変換と動的変換の概念、TransformBroadcasterとTransformListenerの使用方法、およびサービスコールバックの実装を理解しました。
「Self Driving and ROS 2 - Learn by Doing! Odometry & Control」コースの最新セグメントでは、TF2ライブラリの複雑さに飛び込み、シンプルなTF2リスナーの実装に焦点を当てます。このセクションでは、84および85講義を通じて、フレーム変換の理解を深め、PythonとC++の実践的な例を通じて主要な概念を紹介します。
第84講義:PythonによるシンプルなTF2リスナー
概要
この講義の主な目的は、異なるフレーム間の変換を動的にブロードキャストおよびリスンするTF2リスナーを設定することです。使用される例は、静的および動的変換をブロードキャストするBumperBotです。
主要コンポーネント
静的および動的変換:
静的変換: 時間とともに変化しないフレーム間の固定変換です。例では、`bumperbot_base`と`bumperbot_top`間の変換が静的です。
動的変換: 時間とともに変化する変換です。例えば、`odom`に対する`bumperbot_base`の位置など。
TF2リスナーおよびブロードキャスター:
`StaticTransformBroadcaster`および`TransformBroadcaster`クラスを使用して、静的および動的変換をブロードキャストします。
`TransformListener`および`Buffer`クラスを使用して、変換をリスンし、それをルックアップするためにバッファリングします。
サービスサーバー:
サービスサーバーを作成し、任意の2つのフレーム間の現在の変換をリクエストに応じて提供します。これは、`GetTransform`サービスを使用して行われます。
実装ハイライト
実装には、静的および動的変換ブロードキャスターの両方を初期化するノード(`SimpleTfKinematics`)を設定し、変換リクエストを処理するサービスサーバーを設定します:
静的変換:
self.static_transform_stamped_.header.stamp = self.get_clock().now().to_msg()
self.static_transform_stamped_.header.frame_id = "bumperbot_base"
self.static_transform_stamped_.child_frame_id = "bumperbot_top"
self.static_tf_broadcaster_.sendTransform(self.static_transform_stamped_)
このコードスニペットは、`bumperbot_base`と`bumperbot_top`間の静的変換の初期化を示しています。
動的変換およびタイマーコールバック:
self.timer_ = self.create_timer(0.1, self.timerCallback)
def timerCallback(self):
self.dynamic_transform_stamped_.header.stamp = self.get_clock().now().to_msg()
self.dynamic_transform_stamped_.header.frame_id = "odom"
self.dynamic_transform_stamped_.child_frame_id = "bumperbot_base"
# 変換と回転を更新
self.dynamic_tf_broadcaster_.sendTransform(self.dynamic_transform_stamped_)
タイマーコールバックは定期的に動的変換を更新してブロードキャストします。
サービスコールバック:
def getTransformCallback(self, req, res):
try:
requested_transform = self.tf_buffer_.lookup_transform(req.frame_id, req.child_frame_id, rclpy.time.Time())
res.transform = requested_transform
res.success = True
except TransformException as e:
self.get_logger().error(f"Error: {e}")
res.success = False
return res
このサービスコールバックは変換リクエストを処理し、適切な変換を返します。
第85講義:C++によるシンプルなTF2リスナー
概要
この講義では、Pythonの例で提供された機能をC++で実装します。主な焦点は、変換とサービスサーバーを管理する方法を理解することです。
主要コンポーネント
静的および動的変換:
Pythonの実装と同様に、静的および動的変換を`StaticTransformBroadcaster`と`TransformBroadcaster`を使用して設定します。
サービスサーバー:
フレーム間の現在の変換を提供するサービスサーバーを`GetTransform`サービスインターフェースを使用して作成します。
実装ハイライト
C++の実装には、TFブロードキャスター、バッファ、リスナーの両方を初期化し、変換リクエストを処理するサービスサーバーを設定するノード(`SimpleTfKinematics`)を作成します:
コンストラクタ:
SimpleTfKinematics::SimpleTfKinematics(const std::string& name)
: Node(name),
last_x_(0.0),
x_increment_(0.05),
rotations_counter_(0) {
static_tf_broadcaster_ = std::make_shared<tf2_ros::StaticTransformBroadcaster>(this);
dynamic_tf_broadcaster_ = std::make_unique<tf2_ros::TransformBroadcaster>(*this);
tf_buffer_ = std::make_unique<tf2_ros::Buffer>(this->get_clock());
tf_listener_ = std::make_shared<tf2_ros::TransformListener>(*tf_buffer_);
// 静的変換を初期化
}
コンストラクタはTFブロードキャスター、バッファ、リスナーを初期化します。
タイマーコールバック:
void SimpleTfKinematics::timerCallback() {
// 動的変換を更新して送信
dynamic_tf_broadcaster_->sendTransform(dynamic_transform_stamped_);
}
タイマーコールバックは動的変換を更新してブロードキャストします。
サービスコールバック:
bool SimpleTfKinematics::getTransformCallback(const std::shared_ptr<bumperbot_msgs::srv::GetTransform::Request> req,
const std::shared_ptr<bumperbot_msgs::srv::GetTransform::Response> res) {
try {
requested_transform = tf_buffer_->lookupTransform(req->frame_id, req->child_frame_id, tf2::TimePointZero);
res->transform = requested_transform;
res->success = true;
} catch (tf2::TransformException &ex) {
RCLCPP_ERROR_STREAM(get_logger(), "Error: " << ex.what());
res->success = false;
}
return true;
}
このサービスコールバックは変換リクエストを処理し、適切な変換を返します。
結論
これらの講義は、ROS 2におけるTF2ライブラリの使用方法を包括的に理解するためのものです。静的および動的変換に焦点を当て、変換リクエストを処理するサービスサーバーの設定方法を紹介します。PythonとC++の両方でこれらの概念を実装することで、各言語の微妙な違いとROS 2で同じ機能を実現する方法について貴重な洞察を得ることができます。