5.4.2 坐标系变换(C++)
1.坐标系变换实现
功能包 cpp04_tf_listener 的 src 目录下,新建 C++ 文件 demo01_tf_listener.cpp,并编辑文件,输入如下内容:
/*
需求:订阅 laser 到 base_link 以及 camera 到 base_link 的坐标系关系,
并生成 laser 到 camera 的坐标变换。
步骤:
1.包含头文件;
2.初始化 ROS 客户端;
3.定义节点类;
3-1.创建tf缓存对象指针;
3-2.创建tf监听器;
3-3.按照条件查找符合条件的坐标系并生成变换后的坐标帧。
4.调用 spin 函数,并传入对象指针;
5.释放资源。
*/
#include "rclcpp/rclcpp.hpp"
#include "tf2_ros/transform_listener.h"
#include "tf2_ros/buffer.h"
#include "tf2/LinearMath/Quaternion.h"
using namespace std::chrono_literals;
// 3.定义节点类;
class MinimalFrameListener : public rclcpp::Node {
public:
MinimalFrameListener():Node("minimal_frame_listener"){
tf_buffer_ = std::make_unique<tf2_ros::Buffer>(this->get_clock());
transform_listener_ = std::make_shared<tf2_ros::TransformListener>(*tf_buffer_);
timer_ = this->create_wall_timer(1s, std::bind(&MinimalFrameListener::on_timer,this));
}
private:
void on_timer(){
try
{
auto transformStamped = tf_buffer_->lookupTransform("camera","laser",tf2::TimePointZero);
RCLCPP_INFO(this->get_logger(),"----------------------转换结果----------------------");
RCLCPP_INFO(this->get_logger(),"frame_id:%s",transformStamped.header.frame_id.c_str());
RCLCPP_INFO(this->get_logger(),"child_frame_id:%s",transformStamped.child_frame_id.c_str());
RCLCPP_INFO(this->get_logger(),"坐标:(%.2f,%.2f,%.2f)",
transformStamped.transform.translation.x,
transformStamped.transform.translation.y,
transformStamped.transform.translation.z);
}
catch(const tf2::LookupException& e)
{
RCLCPP_INFO(this->get_logger(),"坐标变换异常:%s",e.what());
}
}
rclcpp::TimerBase::SharedPtr timer_;
std::shared_ptr<tf2_ros::TransformListener> transform_listener_;
std::unique_ptr<tf2_ros::Buffer> tf_buffer_;
};
int main(int argc, char const *argv[])
{
// 2.初始化 ROS 客户端;
rclcpp::init(argc,argv);
// 4.调用 spin 函数,并传入对象指针;
rclcpp::spin(std::make_shared<MinimalFrameListener>());
// 5.释放资源。
rclcpp::shutdown();
return 0;
}
2.编辑配置文件
1.package.xml
在创建功能包时,所依赖的功能包已经自动配置了,配置内容如下:
<depend>rclcpp</depend>
<depend>tf2</depend>
<depend>tf2_ros</depend>
<depend>geometry_msgs</depend>
2.CMakeLists.txt
CMakeLists.txt 中发布和订阅程序核心配置如下:
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(tf2 REQUIRED)
find_package(tf2_ros REQUIRED)
find_package(geometry_msgs REQUIRED)
find_package(turtlesim REQUIRED)
add_executable(demo01_tf_listener src/demo01_tf_listener.cpp)
ament_target_dependencies(
demo01_tf_listener
"rclcpp"
"tf2"
"tf2_ros"
"geometry_msgs"
)
install(TARGETS demo01_tf_listener
DESTINATION lib/${PROJECT_NAME})
3.编译
终端中进入当前工作空间,编译功能包:
colcon build --packages-select cpp04_tf_listener
4.执行
当前工作空间下,启动三个终端,终端1输入如下命令发布雷达(laser)相对于底盘(base_link)的静态坐标变换:
. install/setup.bash
ros2 run cpp03_tf_broadcaster demo01_static_tf_broadcaster 0.4 0 0.2 0 0 0 base_link laser
终端2输入如下命令发布摄像头(camera)相对于底盘(base_link)的静态坐标变换:
. install/setup.bash
ros2 run cpp03_tf_broadcaster demo01_static_tf_broadcaster -0.5 0 0.4 0 0 0 base_link camera
终端3输入如下命令执行坐标系变换:
. install/setup.bash
ros2 run cpp04_tf_listener demo01_tf_listener
终端3将输出 laser 相对于 camera 的坐标,具体结果请参考案例1。