From 7d1f31d399f59efabbcbe074af38823610b7960b Mon Sep 17 00:00:00 2001 From: joanvallve <jvallve@iri.upc.edu> Date: Tue, 14 Dec 2021 22:09:18 +0100 Subject: [PATCH] wip --- CMakeLists.txt | 3 ++ include/publisher_tf.h | 31 ++++++++++------ src/publisher_tf.cpp | 81 ++++++++++++++++++++++++++++-------------- 3 files changed, 78 insertions(+), 37 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9de45f7..52bf097 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,9 @@ find_package(catkin REQUIRED COMPONENTS roscpp sensor_msgs std_msgs + geometry_msgs + tf2 + tf2_ros tf tf_conversions # dynamic_reconfigure diff --git a/include/publisher_tf.h b/include/publisher_tf.h index c3e4ce7..ddc09b6 100644 --- a/include/publisher_tf.h +++ b/include/publisher_tf.h @@ -33,38 +33,49 @@ * ROS includes * **************************/ #include <ros/ros.h> -#include <tf/transform_listener.h> -#include <tf/transform_broadcaster.h> +#include <geometry_msgs/Transform.h> +#include <geometry_msgs/TransformStamped.h> +#include <tf2/utils.h> +#include <tf2_ros/transform_listener.h> +#include <tf2_ros/transform_broadcaster.h> +#include <tf2_ros/static_transform_broadcaster.h> namespace wolf { -tf::Transform stateToTfTransform(const VectorComposite& state, const int& dim) +tf2::Transform stateToTfTransform(const VectorComposite& state, const int& dim) { assert(state.includesStructure("PO")); + tf2::Transform t; + // 2D if (dim == 2) { - return tf::Transform (tf::createQuaternionFromYaw(state.at('O')(0)), - tf::Vector3(state.at('P')(0), state.at('P')(1), 0) ); + t.getRotation().setRPY(0, 0, state.at('O')(0)); + t.setOrigin( tf2::Vector3(state.at('P')(0), state.at('P')(1), 0) ); } // 3D else { - return tf::Transform (tf::Quaternion(state.at('O')(0), state.at('O')(1), state.at('O')(2), state.at('O')(3)), - tf::Vector3(state.at('P')(0), state.at('P')(1), state.at('P')(2)) ); + t.setRotation(tf2::Quaternion(state.at('O')(0), state.at('O')(1), state.at('O')(2), state.at('O')(3)) ); + t.setOrigin( tf2::Vector3(state.at('P')(0), state.at('P')(1), state.at('P')(2)) ); } + + return t; } class PublisherTf: public Publisher { protected: std::string base_frame_id_, odom_frame_id_, map_frame_id_; - tf::TransformBroadcaster tfb_; - tf::TransformListener tfl_; + tf2_ros::StaticTransformBroadcaster stfb_; + tf2_ros::TransformBroadcaster tfb_; + tf2_ros::TransformListener tfl_; + tf2_ros::Buffer tf_buffer_; - tf::StampedTransform T_odom2base_, T_map2odom_; + geometry_msgs::TransformStamped Tmsg_map2odom_, Tmsg_odom2base_; + tf2::Transform T_map2odom_, T_odom2base_; bool publish_odom_tf_; bool state_available_; // used to not repeat warnings regarding availability of state diff --git a/src/publisher_tf.cpp b/src/publisher_tf.cpp index b210ad8..1e4b748 100644 --- a/src/publisher_tf.cpp +++ b/src/publisher_tf.cpp @@ -25,8 +25,10 @@ * ROS includes * **************************/ #include <ros/ros.h> -#include "tf/transform_datatypes.h" -#include "tf_conversions/tf_eigen.h" +//#include "tf/transform_datatypes.h" +//#include "tf_conversions/tf_eigen.h" +#include "tf2_msgs/TF2Error.h" +#include "tf2_geometry_msgs/tf2_geometry_msgs.h" namespace wolf { @@ -35,6 +37,8 @@ PublisherTf::PublisherTf(const std::string& _unique_name, const ParamsServer& _server, const ProblemPtr _problem) : Publisher(_unique_name, _server, _problem), + tf_buffer_(), + tfl_(tf_buffer_), state_available_(true) { map_frame_id_ = _server.getParam<std::string>(prefix_ + "/map_frame_id"); @@ -44,13 +48,15 @@ PublisherTf::PublisherTf(const std::string& _unique_name, // initialize TF transforms T_odom2base_.setIdentity(); - T_odom2base_.frame_id_ = odom_frame_id_; - T_odom2base_.child_frame_id_ = base_frame_id_; - T_odom2base_.stamp_ = ros::Time::now(); T_map2odom_.setIdentity(); - T_map2odom_.frame_id_ = map_frame_id_; - T_map2odom_.child_frame_id_ = odom_frame_id_; - T_map2odom_.stamp_ = ros::Time::now(); + Tmsg_odom2base_.header.frame_id = odom_frame_id_; + Tmsg_odom2base_.child_frame_id = base_frame_id_; + Tmsg_odom2base_.header.stamp = ros::Time::now(); + Tmsg_odom2base_.transform = tf2::toMsg(T_odom2base_); + Tmsg_map2odom_.header.frame_id = map_frame_id_; + Tmsg_map2odom_.child_frame_id = odom_frame_id_; + Tmsg_map2odom_.header.stamp = ros::Time::now(); + Tmsg_map2odom_.transform = tf2::toMsg(T_map2odom_); } void PublisherTf::initialize(ros::NodeHandle& nh, const std::string& topic) @@ -65,7 +71,7 @@ void PublisherTf::publishDerived() // MAP - BASE //Get map2base from wolf result, and builds base2map pose - tf::Transform T_map2base; + tf2::Transform T_map2base; if (current_state.count('P') == 0 or current_state.count('O') == 0 or not current_ts.ok()) @@ -93,20 +99,29 @@ void PublisherTf::publishDerived() { ros::Time transform_time; std::string error_msg; - if (tfl_.getLatestCommonTime(odom_frame_id_, base_frame_id_, transform_time, &error_msg) == tf::ErrorValues::NO_ERROR and - transform_time != T_odom2base_.stamp_) + if (tf_buffer_._getLatestCommonTime(tf_buffer_._lookupFrameNumber(odom_frame_id_), + tf_buffer_._lookupFrameNumber(base_frame_id_), + transform_time, + &error_msg) == tf2_msgs::TF2Error::NO_ERROR and + transform_time != Tmsg_odom2base_.header.stamp) { - WOLF_ERROR("PublisherTf: option 'publish_odom_tf' enabled but a transform between ", - base_frame_id_, " and ", odom_frame_id_, - " was found published by a third party. Not publishing this transformation."); + ROS_WARN("PublisherTf: option 'publish_odom_tf' enabled but a transform between %s and %s was found published by a third party. Changing 'publish_odom_tf' to false.", + base_frame_id_.c_str(), odom_frame_id_.c_str()); + + Tmsg_odom2base_ = tf_buffer_.lookupTransform(odom_frame_id_, base_frame_id_, ros::Time(0)); + tf2::fromMsg(Tmsg_odom2base_.transform, T_odom2base_); + + publish_odom_tf_=false; } else { VectorComposite odom = problem_->getOdometry("PO"); - T_odom2base_.setData(stateToTfTransform(odom, problem_->getDim())); - T_odom2base_.stamp_ = ros::Time::now(); - tfb_.sendTransform(T_odom2base_); + T_odom2base_ = stateToTfTransform(odom, problem_->getDim()); + Tmsg_odom2base_.transform = tf2::toMsg(T_odom2base_); + Tmsg_odom2base_.header.stamp = ros::Time::now(); + + tfb_.sendTransform(Tmsg_odom2base_); } } // TF odometry @@ -114,22 +129,34 @@ void PublisherTf::publishDerived() { try { - tfl_.lookupTransform(odom_frame_id_, base_frame_id_, ros::Time(0), T_odom2base_); + Tmsg_odom2base_ = tf_buffer_.lookupTransform(odom_frame_id_, base_frame_id_, ros::Time(0)); + tf2::fromMsg(Tmsg_odom2base_.transform, T_odom2base_); } - catch(...) + catch (tf2::TransformException &ex) { - ROS_WARN("No %s to %s frame received. Assuming identity.", base_frame_id_.c_str(), odom_frame_id_.c_str()); + ROS_WARN("No tf between %s to %s received, error: %s. Assuming identity.", + base_frame_id_.c_str(), + odom_frame_id_.c_str(), + ex.what()); T_odom2base_.setIdentity(); - T_odom2base_.stamp_ = ros::Time::now(); - } + } } - // Broadcast transform --------------------------------------------------------------------------- - T_map2odom_.setData(T_map2base * T_odom2base_.inverse()); - T_map2odom_.stamp_ = ros::Time::now(); - //std::cout << "T_map2odom: " << T_map2odom.getOrigin().getX() << " " << T_map2odom.getOrigin().getY() << " " << T_map2odom.getRotation().getAngle() << std::endl; - tfb_.sendTransform(T_map2odom_); + tf2::Transform T_map2odom = T_map2base * T_odom2base_.inverse(); + + Tmsg_map2odom_.transform.translation.x = T_map2odom.getOrigin().getX(); + Tmsg_map2odom_.transform.translation.y = T_map2odom.getOrigin().getY(); + Tmsg_map2odom_.transform.translation.z = T_map2odom.getOrigin().getZ(); + + Tmsg_map2odom_.transform.rotation.x = T_map2odom.getRotation().getX(); + Tmsg_map2odom_.transform.rotation.y = T_map2odom.getRotation().getY(); + Tmsg_map2odom_.transform.rotation.z = T_map2odom.getRotation().getZ(); + Tmsg_map2odom_.transform.rotation.w = T_map2odom.getRotation().getW(); + + Tmsg_map2odom_.header.stamp = ros::Time::now(); + + stfb_.sendTransform(Tmsg_map2odom_); } } -- GitLab