答案是不行的,那为什么提出要用一个文件实现坐标变换呢?因为我们实现坐标变换时,只需要获知坐标系相对位置关系和坐标点在源坐标系中的坐标即可实现坐标变换。因此我们想在一个CPP文件中声明坐标系的关系和坐标点在源坐标系中的坐标,然后再使用tfs_ros::buffer中的transform函数一气呵成计算出坐标点基于目标坐标系的坐标。理论上来说还挺行得通,但是真的如此吗?
错误代码示例:
#include "ros/ros.h"
#include "geometry_msgs/TransformStamped.h"
#include "geometry_msgs/PointStamped.h"
#include "tf2_geometry_msgs/tf2_geometry_msgs.h"
#include "tf2/LinearMath/Quaternion.h"
#include "tf2_ros/buffer.h"
int main(int argc,char* argv[])
{
setlocale(LC_ALL,"");
ros::init(argc,argv,"static_tf2");
geometry_msgs::TransformStamped transform;
transform.child_frame_id = "son1";
transform.header.frame_id = "son2";
transform.header.stamp = ros::Time::now();
transform.transform.translation.x = 10;
transform.transform.translation.y = 10;
// 二维平面无Z轴偏移
transform.transform.translation.z = 0;
// 在XOY平面上的旋转均是围绕垂直于XOY平面的轴进行的
tf2::Quaternion qtn(0,0,90);
transform.transform.rotation.w = qtn.getW();
transform.transform.rotation.x = qtn.getX();
transform.transform.rotation.y = qtn.getY();
transform.transform.rotation.z = qtn.getZ();
geometry_msgs::PointStamped PointOnSon1;
PointOnSon1.header.frame_id = "son1";
PointOnSon1.header.stamp = ros::Time();
PointOnSon1.point.x = 10;
PointOnSon1.point.y = 10;
PointOnSon1.point.z = 10;
// 错误使用buffer
geometry_msgs::PointStamped PointOnSon2;
tf2_ros::Buffer buffer;
PointOnSon2 = buffer.transform(PointOnSon1,"son2");
ROS_INFO("PointOnSon2:%d,%d,%d\n\t",PointOnSon2.point.x,PointOnSon2.point.y,PointOnSon2.point.z);
}
这段代码看起来挺顺眼的没有语法错误,那怎么错了呢?出错位置如下所示:
// 错误使用buffer
geometry_msgs::PointStamped PointOnSon2;
tf2_ros::Buffer buffer;
PointOnSon2 = buffer.transform(PointOnSon1,"son2");
我们的本意是“使用存在buffer中坐标系相对位置关系将坐标点在son1坐标系下的坐标转换至基于son2坐标系的坐标”,但我们忽略了一点“坐标系相对位置关系存入buffer了吗?”
还记得我们在使用话题通信传递坐标关系时,发布端/订阅端的发布/订阅实现分别如下:
发布端发布坐标关系:
geometry_msgs::TransformStamped transform;
transform.child_frame_id = "son1";
transform.header.frame_id = "son2";
transform.header.stamp = ros::Time::now();
transform.transform.translation.x = 10;
transform.transform.translation.y = 10;
// 二维平面无Z轴偏移
transform.transform.translation.z = 0;
// 在XOY平面上的旋转均是围绕垂直于XOY平面的轴进行的
tf2::Quaternion qtn(0,0,90);
transform.transform.rotation.w = qtn.getW();
transform.transform.rotation.x = qtn.getX();
transform.transform.rotation.y = qtn.getY();
transform.transform.rotation.z = qtn.getZ();
tf2_ros::StaticTransformBroadcaster pub;
pub.sendTransform(transform);
订阅端订阅坐标关系并存入属于对象自己的buffer当中去:
tf2_ros::Buffer buffer;
tf2_ros::TransformListener listen(buffer);
PointOnSon2 = buffer.transform(PointOnSon1,"son2");
ROS_INFO("PointOnSon2:%d,%d,%d\n\t",PointOnSon2.point.x,PointOnSon2.point.y,PointOnSon2.point.z);
在订阅端中我们通过传入buffer对象,构建了属于listener对象的缓冲区,该缓冲区用于保存通过tf2_static话题传来的坐标系相对位置关系。最上面那个代码错误的原因就是“我们根本没有任何途径将坐标系相对位置关系传入buffer当中去,还谈何使用buffer中的位置关系呀”!现在,我们可以知道为何不可以使用一个CPP文件去进行坐标变换了吧。