首先看了开源操作机器人系统-ros这本书(张建伟)第五章slam导航 5.1使用tf配置机器人
还有ros navigation 教程
http://wiki.ros.org/navigation/Tutorials/RobotSetup/TF
这里需要区分两种变换
1、坐标系变换
2、坐标变换
坐标系变换就是指一个坐标系怎么变换成另外一个坐标系
坐标变换就是指一个坐标系下点怎么变换成另外一个坐标系下坐标
这两个略微有所不同
tf tree维护的是坐标系变换
base_link到base_laser坐标系变换就是[0.1,0,0.2]
而base_laser到base_link就是[-0.1,0,-0.2]
坐标变换则是转动坐标系在固定坐标系下运动描述
具体可以看这篇博客
http://blog.exbot.net/archives/1686
博客主要知识点:
这里有个巧合,当然也不是巧合,那就是从child到parent的坐标变换等于从parent到child的frame transform,等于child在parent frame的姿态描述。这里牵扯到了线性代数里的基变换、线性变换、过渡矩阵的概念。
接下来是实际操作部分
下面这段代码实现了从user_set topic读取数据,在call_back中进行tf 广播,在主程序里进行look_up
#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <nav_msgs/Odometry.h>
#include <geometry_msgs/Pose2D.h>
#include <tf/transform_listener.h>
#include <stdio.h>
class test
{
private:
ros::NodeHandle nh_;
ros::Subscriber sub_;
tf::TransformBroadcaster br_;
bool data_ready; public:
test(ros::NodeHandle& nh)
{
nh_=nh;
sub_ = nh_.subscribe("/user_set", 10, &test::call_back,this);
data_ready = false;
}
void call_back(const geometry_msgs::Pose2DPtr& msgs)
{
ROS_INFO("recive");
tf::Transform dest_transform;
dest_transform.setOrigin(tf::Vector3(msgs->x,msgs->y,0));
tf::Quaternion q;
q.setRPY(0, 0, msgs->theta);
dest_transform.setRotation(q);
br_.sendTransform(tf::StampedTransform(dest_transform, ros::Time::now(),"world","user_set_frame"));
data_ready = true;
} bool is_data_ready()
{
if(data_ready)
return true;
else
return false;
} };
int main(int argc, char** argv){
ros::init(argc, argv, "tf_broadcaster"); ros::NodeHandle node;
test Otest(node);
tf::TransformListener listener; tf::StampedTransform transform; while(ros::ok())
{
if(!Otest.is_data_ready())
{
ros::spinOnce(); continue;
}
ROS_INFO("lookup_transfoem;");
try
{
//查找的是world到user_set_frame“坐标变换”具体可以看见看教程
//http://wiki.ros.org/tf/Tutorials/Writing%20a%20tf%20listener%20%28C%2B%2B%29
//rosrun tf tf_echo求的是坐标系变换
listener.waitForTransform("world","user_set_frame",ros::Time::now(), ros::Duration(1.0));
listener.lookupTransform("world","user_set_frame",ros::Time(0),transform);
}
catch (tf::TransformException ex)
{
ROS_ERROR("%s",ex.what());
break;
}
tf::Vector3 vectortf = transform.getOrigin();
ROS_INFO("transform.x:%f,transform.y:%f,transform.z:%f",vectortf.x(),vectortf.y(),vectortf.z());
ros::spinOnce(); }
return 0;
}
Here, the real work is done, we query the listener for a specific transformation. Let's take a look at the four arguments:
- We want the transform from this frame ...
- ... to this frame.
The time at which we want to transform. Providing ros::Time(0) will just get us the latest available transform.
- The object in which we store the resulting transform.
知道tf变换后怎么进行坐标变换呢?
开源操作机器人系统-ros这本书(张建伟)第五章slam导航 5.1使用tf配置机器人