17#include <rclcpp/rclcpp.hpp>
19#include <tf2_ros/transform_listener.h>
20#include <tf2_ros/buffer.h>
21#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
23#include <mrs_msgs/msg/reference_stamped.hpp>
24#include <geometry_msgs/msg/pose_stamped.hpp>
25#include <geometry_msgs/msg/vector3_stamped.hpp>
27#include <std_msgs/msg/header.hpp>
31#ifdef PCL_SPECIALIZATION
32#include <pcl_ros/point_cloud.hpp>
33#include <pcl_ros/transforms.hpp>
34#include <pcl_conversions/pcl_conversions.h>
38#include <experimental/type_traits>
42#ifdef PCL_SPECIALIZATION
47template <
typename pt_t>
48void doTransform(
const pcl::PointCloud<pt_t>& cloud_in, pcl::PointCloud<pt_t>& cloud_out,
const geometry_msgs::msg::TransformStamped& transform) {
49 pcl_ros::transformPointCloud(cloud_in, cloud_out, transform.transform);
50 pcl_conversions::toPCL(transform.header.stamp, cloud_out.header.stamp);
51 cloud_out.header.frame_id = transform.header.frame_id;
61static const std::string UTM_ORIGIN =
"utm_origin";
62static const std::string LATLON_ORIGIN =
"latlon_origin";
115 Transformer(
const rclcpp::Node::SharedPtr& node,
const rclcpp::Clock::SharedPtr& clock,
116 const rclcpp::Duration& cache_time = rclcpp::Duration(tf2::BUFFER_CORE_DEFAULT_CACHE_TIME),
const rclcpp::QoS& qos = rclcpp::ServicesQoS());
144 std::scoped_lock lck(mutex_);
145 default_frame_id_ = frame_id;
166 std::scoped_lock lck(mutex_);
170 prefix_ = prefix +
"/";
187 void setLatLon(
const double lat,
const double lon);
203 std::scoped_lock lck(mutex_);
204 lookup_timeout_ = timeout;
222 std::scoped_lock lck(mutex_);
223 retry_lookup_newest_ = retry;
238 std::scoped_lock lck(mutex_);
257 std::scoped_lock lck(mutex_);
258 return resolveFrameImpl(frame_id);
273 [[nodiscard]] std::optional<T>
transformSingle(
const T& what,
const std::string& to_frame);
286 [[nodiscard]] std::optional<std::shared_ptr<T>>
transformSingle(
const std::shared_ptr<T>& what,
const std::string& to_frame) {
301 [[nodiscard]] std::optional<std::shared_ptr<T>>
transformSingle(
const std::shared_ptr<const T>& what,
const std::string& to_frame) {
303 if (ret == std::nullopt)
306 return std::make_shared<T>(std::move(ret.value()));
322 [[nodiscard]] std::optional<T>
transformSingle(
const std::string& from_frame,
const T& what,
const std::string& to_frame,
323 const rclcpp::Time& time_stamp = rclcpp::Time(0));
338 [[nodiscard]] std::optional<std::shared_ptr<T>>
transformSingle(
const std::string& from_frame,
const std::shared_ptr<T>& what,
const std::string& to_frame,
339 const rclcpp::Time& time_stamp = rclcpp::Time(0)) {
340 return transformSingle(from_frame, std::shared_ptr<const T>(what), to_frame, time_stamp);
356 [[nodiscard]] std::optional<std::shared_ptr<T>>
transformSingle(
const std::string& from_frame,
const std::shared_ptr<const T>& what,
357 const std::string& to_frame,
const rclcpp::Time& time_stamp = rclcpp::Time(0)) {
359 if (ret == std::nullopt)
362 return std::make_shared<T>(std::move(ret.value()));
378 [[nodiscard]] std::optional<T>
transform(
const T& what,
const geometry_msgs::msg::TransformStamped& tf);
391 [[nodiscard]] std::optional<std::shared_ptr<T>>
transform(
const std::shared_ptr<const T>& what,
const geometry_msgs::msg::TransformStamped& tf) {
393 if (ret == std::nullopt)
396 return std::make_shared<T>(std::move(ret.value()));
410 [[nodiscard]] std::optional<std::shared_ptr<T>>
transform(
const std::shared_ptr<T>& what,
const geometry_msgs::msg::TransformStamped& tf) {
411 return transform(std::shared_ptr<const T>(what), tf);
427 [[nodiscard]] std::optional<Eigen::Vector3d>
transformAsVector(
const Eigen::Vector3d& what,
const geometry_msgs::msg::TransformStamped& tf);
441 [[nodiscard]] std::optional<Eigen::Vector3d>
transformAsVector(
const std::string& from_frame,
const Eigen::Vector3d& what,
const std::string& to_frame,
442 const rclcpp::Time& time_stamp = rclcpp::Time(0));
456 [[nodiscard]] std::optional<Eigen::Vector3d>
transformAsPoint(
const Eigen::Vector3d& what,
const geometry_msgs::msg::TransformStamped& tf);
470 [[nodiscard]] std::optional<Eigen::Vector3d>
transformAsPoint(
const std::string& from_frame,
const Eigen::Vector3d& what,
const std::string& to_frame,
471 const rclcpp::Time& time_stamp = rclcpp::Time(0));
485 [[nodiscard]] std::optional<geometry_msgs::msg::TransformStamped>
getTransform(
const std::string& from_frame,
const std::string& to_frame,
486 const rclcpp::Time& time_stamp = rclcpp::Time(0));
503 [[nodiscard]] std::optional<geometry_msgs::msg::TransformStamped>
getTransform(
const std::string& from_frame,
const rclcpp::Time& from_stamp,
504 const std::string& to_frame,
const rclcpp::Time& to_stamp,
505 const std::string& fixed_frame);
515 bool initialized_ =
false;
516 rclcpp::Node::SharedPtr node_;
518 std::unique_ptr<tf2_ros::Buffer> tf_buffer_;
519 std::unique_ptr<tf2_ros::TransformListener> tf_listener_ptr_;
522 std::string default_frame_id_ =
"";
523 std::string prefix_ =
"";
525 rclcpp::Duration lookup_timeout_ = rclcpp::Duration(0, 0);
526 bool retry_lookup_newest_ =
false;
528 bool got_utm_zone_ =
false;
529 std::array<char, 10> utm_zone_ = {};
532 std::string getFramePrefix(
const std::string& frame_id);
535 std::optional<T> transformImpl(
const geometry_msgs::msg::TransformStamped& tf,
const T& what);
536 std::optional<mrs_msgs::msg::ReferenceStamped> transformImpl(
const geometry_msgs::msg::TransformStamped& tf,
const mrs_msgs::msg::ReferenceStamped& what);
537 std::optional<Eigen::Vector3d> transformImpl(
const geometry_msgs::msg::TransformStamped& tf,
const Eigen::Vector3d& what);
539 [[nodiscard]] std::optional<geometry_msgs::msg::TransformStamped> getTransformImpl(
const std::string& from_frame,
const std::string& to_frame,
540 const rclcpp::Time& time_stamp,
const std::string& latlon_frame);
542 [[nodiscard]] std::optional<geometry_msgs::msg::TransformStamped> getTransformImpl(
const std::string& from_frame,
const rclcpp::Time& from_stamp,
543 const std::string& to_frame,
const rclcpp::Time& to_stamp,
544 const std::string& fixed_frame,
const std::string& latlon_frame);
546 std::string resolveFrameImpl(
const std::string& frame_id);
549 std::optional<T> doTransform(
const T& what,
const geometry_msgs::msg::TransformStamped& tf);
563 static constexpr const std::string&
frame_from(
const geometry_msgs::msg::TransformStamped& msg) {
564 return msg.child_frame_id;
575 static constexpr std::string&
frame_from(geometry_msgs::msg::TransformStamped& msg) {
576 return msg.child_frame_id;
585 static constexpr const std::string&
frame_to(
const geometry_msgs::msg::TransformStamped& msg) {
586 return msg.header.frame_id;
597 static constexpr std::string&
frame_to(geometry_msgs::msg::TransformStamped& msg) {
598 return msg.header.frame_id;
607 static geometry_msgs::msg::TransformStamped
inverse(
const geometry_msgs::msg::TransformStamped& msg) {
609 tf2::fromMsg(msg.transform, tf2);
611 return create_transform(
frame_to(msg),
frame_from(msg), msg.header.stamp, tf2::toMsg(tf2));
617 static geometry_msgs::msg::TransformStamped create_transform(
const std::string& from_frame,
const std::string& to_frame,
const rclcpp::Time& time_stamp) {
618 geometry_msgs::msg::TransformStamped ret;
621 ret.header.stamp = time_stamp;
625 static geometry_msgs::msg::TransformStamped create_transform(
const std::string& from_frame,
const std::string& to_frame,
const rclcpp::Time& time_stamp,
626 const geometry_msgs::msg::Transform& tf) {
627 geometry_msgs::msg::TransformStamped ret;
630 ret.header.stamp = time_stamp;
639 template <
typename T>
640 using has_header_member_chk =
decltype(std::declval<T&>().header);
642 template <
typename T>
643 static constexpr bool has_header_member_v = std::experimental::is_detected<has_header_member_chk, T>::value;
645 template <
typename msg_t>
646 std_msgs::msg::Header getHeader(
const msg_t& msg);
648#ifdef PCL_SPECIALIZATION
649 template <
typename pt_t>
650 std_msgs::msg::Header getHeader(
const pcl::PointCloud<pt_t>& cloud);
652 template <
typename pt_t>
653 void setHeader(pcl::PointCloud<pt_t>& cloud,
const std_msgs::msg::Header& header);
656 template <
typename msg_t>
657 void setHeader(msg_t& msg,
const std_msgs::msg::Header& header);
659 template <
typename T>
660 T copyChangeFrame(
const T& what,
const std::string& frame_id);
665 geometry_msgs::msg::Point LLtoUTM(
const geometry_msgs::msg::Point& what,
const std::string& prefix);
666 geometry_msgs::msg::PointStamped LLtoUTM(
const geometry_msgs::msg::PointStamped& what,
const std::string& prefix);
667 geometry_msgs::msg::Pose LLtoUTM(
const geometry_msgs::msg::Pose& what,
const std::string& prefix);
668 geometry_msgs::msg::PoseStamped LLtoUTM(
const geometry_msgs::msg::PoseStamped& what,
const std::string& prefix);
670 std::optional<geometry_msgs::msg::Point> UTMtoLL(
const geometry_msgs::msg::Point& what,
const std::string& prefix);
671 std::optional<geometry_msgs::msg::PointStamped> UTMtoLL(
const geometry_msgs::msg::PointStamped& what,
const std::string& prefix);
672 std::optional<geometry_msgs::msg::Pose> UTMtoLL(
const geometry_msgs::msg::Pose& what,
const std::string& prefix);
673 std::optional<geometry_msgs::msg::PoseStamped> UTMtoLL(
const geometry_msgs::msg::PoseStamped& what,
const std::string& prefix);
676 template <
class Class,
typename Message>
677 using UTMLL_method_chk =
decltype(std::declval<Class>().UTMtoLL(std::declval<const Message&>(),
""));
679 template <
class Class,
typename Message>
680 using LLUTM_method_chk =
decltype(std::declval<Class>().LLtoUTM(std::declval<const Message&>(),
""));
682 template <
class Class,
typename Message>
683 static constexpr bool UTMLL_exists_v =
684 std::experimental::is_detected<UTMLL_method_chk, Class, Message>::value && std::experimental::is_detected<LLUTM_method_chk, Class, Message>::value;
692#ifndef TRANSFORMER_HPP
693#include <mrs_lib/impl/transformer.hpp>
Defines useful geometry utilities and functions.
All mrs_lib functions, classes, variables and definitions are contained in this namespace.
Definition attitude_converter.h:24