Intermediate-实现一个静态广播器

目标:学习怎样广播一个静态坐标系到tf2

背景
发布静态tf对定义机器人底盘和它上面不动的传感器之间的transform是很有用的。

任务
1.创建一个包
本包名字为learning_tf2_cpp依赖包geometry_msgs, rclcpp, tf2, tf2_ros以及turtlesim。

ros2 pkg create --build-type ament_cmake --dependencies geometry_msgs rclcpp tf2 tf2_ros turtlesim -- learning_tf2_cpp

2.实现一个静态broadcaster 节点

#include <memory>
//头文件用于访问类型TransformStamped
#include "geometry_msgs/msg/transform_stamped.hpp"
#include "rclcpp/rclcpp.hpp"
//tf2::Quaternion头文件提供了欧拉角与四元素之间的相互转换 #include "tf2/LinearMath/Quaternion.h" #include "tf2_ros/static_transform_broadcaster.h" class StaticFramePublisher : public rclcpp::Node { public: explicit StaticFramePublisher(char * transformation[]) : Node("static_turtle_tf2_broadcaster") { tf_static_broadcaster_ = std::make_shared<tf2_ros::StaticTransformBroadcaster>(this); // Publish static transforms once at startup this->make_transforms(transformation); } private: void make_transforms(char * transformation[]) { geometry_msgs::msg::TransformStamped t; //获得当前的时间戳 t.header.stamp = this->get_clock()->now(); t.header.frame_id = "world"; t.child_frame_id = transformation[1]; t.transform.translation.x = atof(transformation[2]); t.transform.translation.y = atof(transformation[3]); t.transform.translation.z = atof(transformation[4]); tf2::Quaternion q; q.setRPY( atof(transformation[5]), atof(transformation[6]), atof(transformation[7])); t.transform.rotation.x = q.x(); t.transform.rotation.y = q.y(); t.transform.rotation.z = q.z(); t.transform.rotation.w = q.w(); tf_static_broadcaster_->sendTransform(t); } std::shared_ptr<tf2_ros::StaticTransformBroadcaster> tf_static_broadcaster_; }; int main(int argc, char * argv[]) { auto logger = rclcpp::get_logger("logger"); // Obtain parameters from command line arguments if (argc != 8) { RCLCPP_INFO( logger, "Invalid number of parameters\nusage: " "$ ros2 run learning_tf2_cpp static_turtle_tf2_broadcaster " "child_frame_name x y z roll pitch yaw"); return 1; } // As the parent frame of the transform is `world`, it is // necessary to check that the frame name passed is different if (strcmp(argv[1], "world") == 0) { RCLCPP_INFO(logger, "Your static turtle name cannot be 'world'"); return 1; } // Pass parameters and initialize node rclcpp::init(argc, argv); rclcpp::spin(std::make_shared<StaticFramePublisher>(argv)); rclcpp::shutdown(); return 0; }

package.xml添加依赖

由于在新建包的时候已经创建了。所以package.xml里面就不需要了

CMakeLists.txt

add_executable(static_turtle_tf2_broadcaster src/static_turtle_tf2_broadcaster.cpp)
ament_target_dependencies(
   static_turtle_tf2_broadcaster
   geometry_msgs
   rclcpp
   tf2
   tf2_ros
)


install(TARGETS
   static_turtle_tf2_broadcaster
   DESTINATION lib/${PROJECT_NAME})

 

编译并运行

colcon build --packages-select learning_tf2_cpp

source  install/setup.bash

ros2 run learning_tf2_cpp static_turtle_tf2_broadcaster mystaticturtle 0 0 1 0 0 0

显示结果ros2 topic echo /tf_static

更适合发布静态tf的方法

tf2_ros提供了一个可执行程序名字为static_transform_publisher来发布静态tf
有两种发布方式,如下
欧拉角:
ros2 run tf2_ros static_transform_publisher --x x --y y --z z --yaw yaw --pitch pitch --roll roll --frame-id frame_id --child-frame-id child_frame_id
四元素:
ros2 run tf2_ros static_transform_publisher --x x --y y --z z --qx qx --qy qy --qz qz --qw qw --frame-id frame_id --child-frame-id child_frame_id

在launch文件里面发布如下:
from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription([
        Node(
             package='tf2_ros',
             executable='static_transform_publisher',
             arguments = ['--x', '0', '--y', '0', '--z', '1', '--yaw', '0', '--pitch', '0', '--roll', '0', '--frame-id', 'world', '--child-frame-id', 'mystaticturtle']
        ),
    ])

 

posted on 2023-06-08 16:37  gary_123  阅读(20)  评论(0编辑  收藏  举报

导航