ROS1学习笔记--tf变换

一、tf变换简介

         机器人系统通常具有许多随时间变化的3D坐标系,例如世界坐标系(world frame),基准坐标系(base frame),夹具坐标系(gripper frame),头部坐标系(head frame)等。tf包可以随时记录所有这些坐标系,并可以解决如下问题:

  • 5秒前,机器人头部坐标系相对于世界(全局)坐标系的关系是什么样的?
  • 机器人夹取的物体相对于机器人的中心坐标的位置是什么?
  • 机器人中心坐标系相对于全局坐标系的位置在哪里?
TF变换可以广播tf变换(broadcaster)和监听tf变换(lisenter)来实现。

二、tf变换实例

1.实现一个tf广播器

  • 定义一个tf广播器(TransformBroadcaster)
  • 创建坐标变换值
  • 发布坐标变换(sendTransform)

代码实现:src/turtle_tf_broadcaster.cpp.

#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <turtlesim/Pose.h>

std::string turrtle_name;

void poseCallback(const turtlesim::PoseConstPtr& msg)
{
//创建一个tf广播器
  static tf::TransformBroadcaster br;

 //创建一个Transform对象,根据当前海龟的位置,设置相对与世界坐标系的坐标变换
  tf::Transform transform;
  transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );
  tf::Quaternion q;
  q.setRPY(0, 0, msg->theta);
  transform.setRotation(q);  //设置旋转

//发布坐标变换,(transform,发布时间戳,父坐标系,子坐标系)
  br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name));
}

int main(int argc, char** argv){
  ros::init(argc, argv, "my_tf_broadcaster");
  if (argc != 2){ROS_ERROR("need turtle name as argument"); return -1;};
  turtle_name = argv[1];

//订阅turtle的位置(pose)信息
  ros::NodeHandle node;
  ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback);

 //循环等待
  ros::spin();
  return 0;
};

参考网站:小海龟例程broadcaster

2.实现一个TF监听器

  • 定义一个tf监听器(TransformListener)
  • 查找坐标变换(waitTransform.lookupTransform)

代码实现:src/turtle_tf_listener.cpp

#include <ros/ros.h>
#include <tf/transform_listener.h>
#include <geometry_msgs/Twist.h>
#include <turtlesim/Spawn.h>

int main(int argc, char** argv)
{
//初始化节点
   ros::init(argc, argv, "my_tf_listener");
//创建句柄,如果一个节点没有启动,节点句柄会自动启动该节点
  ros::NodeHandle node;

 //通过服务调用,产生第二只海龟
  ros::service::waitForService("spawn");
  ros::ServiceClient add_turtle =
    node.serviceClient<turtlesim::Spawn>("spawn");
  turtlesim::Spawn srv;
  add_turtle.call(srv);

//定义第二只海龟的速度发布器,发布频率为10hz
   ros::Publisher turtle_vel =
    node.advertise<geometry_msgs::Twist>("turtle2/cmd_vel", 10);

//创建一个tf监听器
 tf::TransformListener listener;

  ros::Rate rate(10.0);
  while (node.ok()){
    tf::StampedTransform transform;
    try{
//查找两个海龟间的坐标变换
       listener.lookupTransform("/turtle2", "/turtle1",
                               ros::Time(0), transform);
    }
    catch (tf::TransformException &ex) {
      ROS_ERROR("%s",ex.what());
      ros::Duration(1.0).sleep();
      continue;
    }

//基于两个海龟之间的坐标变换,计算turtle2的新的线性和角速度
//新速度发布在主题“turtle2 / cmd_vel”中,sim将使用它来更新turtle2的移动。
     geometry_msgs::Twist vel_msg;
    vel_msg.angular.z = 4.0 * atan2(transform.getOrigin().y(),
                                    transform.getOrigin().x());
    vel_msg.linear.x = 0.5 * sqrt(pow(transform.getOrigin().x(), 2) +
                                  pow(transform.getOrigin().y(), 2));
    turtle_vel.publish(vel_msg);

    rate.sleep();
  }
  return 0;
};

三、添加一个额外的固定坐标系

参考网站:Tutorials

四、学会使用waitTranform

参考网站:Tutorials

五、高级时间历史功能

参考网站:Tutorials


还有很多没有详细看,有时间再添加


参考网站:

官方wiki:tf_ROS.wik

海龟跟随小例程  :tf_demo

官方Tutorials:http://wiki.ros.org/tf/Tutorials

古月居tf:重读tf


listener参考网站:小海龟例程listener

猜你喜欢

转载自blog.csdn.net/weixin_40863346/article/details/80491955