tf学习

1 tf简介

1.1 什么是tf

        tf是一个让用户随时间跟踪多个参考系的功能包,它使用一种树型数据结构,根据时间缓冲并维护多个参考系之间的坐标变换关系,可以帮助用户在任意时间,将点、向量等数据的坐标,在两个参考系中完成坐标变换。

        tf的相关设计思想,可以参见:tf设计

1.2 tf可以做什么

        一个机器人系统通常有很多三维的参考系,而且会随着时间的推移发生变化,例如全局参考系(world frame),机器人中心参考系(base frame),机械夹参考系(gripper frame),机器人头参考系(head frame)等等。tf可以以时间为轴,跟踪这些参考系(默认是10秒之内的),并且允许用户提出如下的申请:

  • 五秒钟之前,机器人头参考系相对于全局参考系的关系是什么样的?
  • 机器人夹取的物体相对于机器人中心参考系的位置在哪里?
  • 机器人中心参考系相对于全局参考系的位置在哪里?
        tf可以在分布式系统中进行操作,也就是说一个机器人系统中所有的参考系变换关系,对于所有节点组件,都是可用的,所有订阅tf消息的节点都会缓冲一份所有参考系的变换关系数据,所以这种结构不需要中心服务器来存储任何数据。
 

1.3 tf的使用流程

        想要使用tf功能包,总体来讲可以分为以下两个步骤:

      (1)   监听tf变换

        接收并缓存系统中发布的所有参考系变换,并从中查询所需要的参考系变换。

      (2)   广播tf变换

        向系统中广播参考系之间的坐标变换关系。系统中更可能会存在多个不同部分的tf变换广播,每个广播都可以直接将参考系变换关系直接插入tf树中,不需要再进行同步。
2 tf 功能包的API说明
这些数据类型定义在文件tf/transform_datatypes.h
1.1基本数据类型(Quaternion, Vector,Point, Pose, Transform)
类型                                                   tf
Quaternion(四元素)           tf::Quaternion
Vector             tf::Vector3
Point               tf::Point
Pose                  tf::Pose
Transform             tf::Transform
1.2 tf::Stamped<T>
tf::Stamped<T>是以上数据类型的模板(除了类型tf::Transform以外)并带有元素坐标系frame_id_以及时间戳stamp_
复制代码
template <typename T>
class Stamped:public T
{
 public: 
      ros::Time   stamp_;
      std::string frame_id_;

     Stamped() :frame_id_("NO_ID_STAMPED_DEFAULT_CONSTRUCTION"){};// 默认构造器仅仅是用于预分配
     Stamped(const T& input, const ros::Time& timestamp, const std::string & frame_id);
     void setData(const T& input);     
}
复制代码

1.3 tf::StampedTransform

tf::StampedTransform 是一个tf::Transforms的特殊例子,它包含了坐标系frame_id,时间戳stamp以及子坐标系child_frame_id.

复制代码
/*由tf使用的时间戳的transform类型*/
class StampedTransform : public tf::Transform
{
public:
    ros::Time stamp_;//与变换transform相关的时间戳   
    std::string  frame_id_;//坐标系的frame_id,transform被定义在该坐标系里面
    StampedTransform(const tf::Transform& input, const ros::Time& timestamp, const std::string & frame_id, const std::string & child_frame_id):
    tf::Transform ( input ), stamp_ ( timestamp ), frame_id_ (frame_id), child_frame_id_(child_frame_id) { };
    //默认的构造器只用于预分配
   StampedTransform() {}
   //设置继承的Transform数据
   void setData(const tf::Transform& input){*static_cast<tf::Transform*>(this) = input;}    
};
复制代码

1.4)帮助函数

tf::Quaternion createIdentityQuaternion()

    Return an identity quaternion.

tf::Quaternion createQuaternionFromRPY(double roll , double pitch, double yaw)

   Return a tf::Quaternion constructed from Fixed-Axis Roll, Pitch and Yaw

geometry_msgs::Quaternion createQuaternionMsgFromRollPitchYaw(double roll, double pitch, double yaw)

  Return a geometry_msgs::Quaternion constructed from Fixed-Axis Roll,Pitch and Yaw.

1.5)数据类型转换Data type conversions

http://docs.ros.org/api/tf/html/c++/transform__datatypes_8h.html

2)变换与参考系

坐标系,变换,以及TF

1.参考

2.坐标系和点

一个frame是一个坐标系统。在ROS中的坐标系统总是以3D的形式,右手坐标系,X向前,Y左,Z向上。

在坐标系中的点用tf::Point来表示,它等同于bullet type btVector3。在坐标系W中的点p的坐标被写为Wp.

3.坐标系的位姿

在两个坐标系之间的关系用一个6DOF的相对位姿来表示,一个平移加上一个旋转。如果W和A是两个坐标系,在W坐标系中A的位姿用从W的原点到A的原点的平移和A坐标轴在W中的旋转来表示。

在W坐标系当中,平移是一个向量,WtA.它由tf::Vector3来表示,它等同于btVector3。

A的旋转由一个旋转矩阵来表示,表示为WAR,读的方式:“坐标系A在W坐标系中的旋转。”R的列是在W中由A的三个轴的单位向量组成:WXA, WYA, and WZA.

没有tf类型用于旋转矩阵;而是,tf表示旋转通过tf::Quaternion来表示,等同于btQuaternion。bullet quaternion类型有函数用于创建四元素从旋转矩阵当中,反之,也有。

在齐次坐标系当中,表达平移和旋转是很方便的,用一个4*4的矩阵WAT。可以读作:“A坐标系相对于W坐标系的位姿”,相对位姿由以下来构造:

WAR

WtA

0

1

在tf中,相对位姿由tf::Pose表示,它等同于bullet type btTransform。成员函数是getRotation()或者getBasis()用于旋转,另外getOffset()用于位姿的平移。See the bullet btTransform class reference.

4.坐标系位姿作为点映射Frame poses as Point Mappings

在位姿和映射点之间存在二元性,当从一个坐标系到另一个坐标系的时候。位姿WAT可以被读作,“把A坐标系中的点转换到W坐标系当中”

,当p点在A坐标系中的位置已知,且A坐标系在W坐标系中的变换已知,要求p点在W坐标系中的位置,可以通过
WATAp = Wp.
映射或者变换有他们自己的类型,tf::Transform.这等同于bullet btTransform,因此本质上位姿偏移和变换是一样的类型。
变换可以用旋转矩阵(或者表示旋转的四元素),以及表示平移的向量来表示变换。查看See the bullet btTransform class reference.
5.逆变换
一个变换WAT的逆是表示为变换AWT.可以通过求逆的方式来完成。
1广播变换
在一个节点内广播变换,我们推荐使用tf::TransformBroadcaster。
1.1构造器
tf::TransformBroadcaster 有一个无参数的构造器:
tf::TransformBroadcaster();
1.2发送变换
为了发送变换可以调用sendTransform()用一个填充了的变换。
void sendTransform(const StampedTransform & transform);
void sendTransform(const geometry_msgs::TransformStamped & transform);

4)接收并使用tf广播

1.TransformListener

对于使用tf的大部分情况,通过tf::TransformListener就可以完成。它从tf::Transform中继承了一些方法,以下是一些主要的方法:

1.1构造器

TransformListener(const ros::NodeHandle &nh, ros::Duration max_cache_time = ros::Duration(DEFAULT_CACHE_TIME), bool spin_thread = true);
TransformListener(ros::Duration max_cache_time=ros::Duration(DEFAULT_CACHE_TIME), bool spin_thread=true);

1.2帮助函数

std::string tf::TransformListener::resolve (const std::string &frame_id)

遵循tf_prefix规则来解析frame_id。See geometry/CoordinateFrameConventions.

1.3 canTransform()

该方法返回一个bool,是否该变换可以被评估。它不会throw。如果你传递了一个非NULL的字符串指针,它将会填充字符串error_msgs以免错误。

NOTE: this takes notably more resources to generate the error message.

1.3.1 基本的API

bool tf::TransformListener::canTransform (const std::string &target_frame, const std::string & source_frame, const ros::Time &time, std::string *error_msg=NULL) const

测试是否源frame可以被转换到目标frame在规定的时间内

1.3.2 高级 API

bool tf::TransformListener::canTransform (const std::string &target_frame,const ros::Time &target_time,const std::string & source_frame, const ros::Time &source_time, const std::string &fixed_frame,std::string *error_msg=NULL) const

Test if source_frame can be transformed to fixed_frame at time source_time, and from there can be tranformed into target_frame at target_time.

1.4 waitForTransform

1.4.1 基本API

bool tf::TransformListener::waitForTransform (const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration &timeout, const ros::Duration &polling_sleep_duration=ros::Duration(0.01), std::string *error_msg=NULL) const

Test if source_frame can be transformed to target_frame at time time.

The waitForTransform() methods return a bool whether the transform can be evaluated. It will sleep and retry every polling_duration until the duration of timeout has been passed. It will not throw. If you pass a non NULL string pointer it will fill the string error_msg in the case of an error.

1.4.2 高级API

bool tf::TransformListener::waitForTransform (const std::string &target_frame, const ros::Time &target_time, const std::string &source_frame, const ros::Time &source_time, const std::string &fixed_frame, const ros::Duration &timeout, const ros::Duration &polling_sleep_duration=ros::Duration(0.01), std::string *error_msg=NULL) const 

Test if source_frame can be transformed to fixed_frame at time source_time, and from there can be transformed into target_frame at target_time.

1.5 lookupTransform

lookupTransform()是一个更底层的方法,它将返回两个坐标系之间的transform。该方法是tf库的核心功能,然而,常见的transform * 方法将被终端用户使用。该方法被设计于在transform*()中使用。

返回的变换的方向是从目标坐标系到源坐标系。如果将之应用到数据,将会转换源坐标系中的数据到目标坐标系当中。See geometry/CoordinateFrameConventions#Transform_Direction。This may throw any tf exception。

1.5.1 基本的API

void tf::TransformListener::lookupTransform (const std::string &target_frame, const std::string &source_frame, const ros::Time &time, StampedTransform &transform) const

Fill transform with the transform from source_frame to target_frame at time.

1.5.2 高级API

void tf::TransformListener::lookupTransform (const std::string &target_frame, const ros::Time &target_time, const std::string &source_frame, const ros::Time &source_time, const std::string &fixed_frame, StampedTransform &transform) const 

Fill transform with the transform from source_frame to fixed_frame at source_time, chained with the transform from fixed_frame to target_frame at target_time

C++ Tutorial Python Tutorial

1.6 transformDATA Methods

tf::TransformListener的主要目的是在两个坐标系之间变换数据,以下是两个主要的原型

1.6.1 支持的数据类型

C++ Method Name

Python Method Name

Full Datatype

transformQuaternion()

none

tf::Stamped<tf::Quaternion>

transformVector()

none

tf::Stamped<tf::Vector3>

transformPoint()

none

tf::Stamped<tf::Point>

transformPose()

none

tf::Stamped<tf::Pose>

transformQuaternion()

transformQuaternion()

geometry_msgs/QuaternionStamped

transformVector()

transformVector3()

geometry_msgs/Vector3Stamped

transformPoint()

transformPoint()

geometry_msgs/PointStamped

transformPose()

transformPose()

geometry_msgs/PoseStamped

transformPointCloud()

transformPointCloud()

sensor_msgs/PointCloud

1.6.2 基本的API

c++

void tf::TransformListener::transformDATATYPE (const std::string &target_frame, const geometry_msgs::DATATYPEStamped &stamped_in, geometry_msgs::DATATYPEStamped &stamped_out) const 

Transform the data stamped_in into the target_frame, using the frame_id and stamp inside the stamped datatype as the source.

1.6.3 高级API

 void tf::TransformListener::transformDATATYPE (const std::string &target_frame, const ros::Time &target_time, const geometry_msgs::DATATYPEStamped &pin, const std::string &fixed_frame, geometry_msgs::DATATYPEStamped &pout) const 

Transform the data stamped_in into the fixed_frame. Using the frame_id and stamp inside the stamped datatype as the source. Then transform from the fixed_frame into the target_frame at the target_time.

5)异常
1.在tf包中使用的异常
在tf中的所有异常都继承自tf::TransformExceptiontf::TransformException继承自std::runtime_error。
tf::ConnectivityException
Thrown if the request cannot be completed due to the two frame ids not being in the same connected tree.
tf::ExtrapolationException(外推异常)
Thrown if there is a connection between the frame ids requested but one or more of the transforms are out of date.
tf::InvalidArgument
 
 
Thrown if an argument is invalid. The most common case is an unnormalized quaternion.
tf::LookupException
 
Thrown if an unpublished frame id is referenced.
 
 
 
 
 
 
 
 
 
 

posted on   gary_123  阅读(228)  评论(0编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示