ROS tf变换

TF是ROS中的坐标转换工具,用于管理不同坐标系之间的关系。它维护了一个树形结构,通过TransformStamped.msg消息更新坐标转换信息。tf::TransformBroadcaster用于发布坐标变换,而tf::TransformListener则用于接收和查询变换。文章介绍了TF数据类型、转换以及C++中相关类的使用方法。
摘要由CSDN通过智能技术生成

简介

所谓TF(TransForm), 就是坐标转换,坐标变换包括了位置和姿态两个方面的变换, ROS中的tf是一个可以让用户随时记录多个坐标系的软件包。 tf保持缓存的树形结构中的坐标系之间的关系, 并且允许用户在任何期望的时间点在任何两个坐标系之间转换点, 矢量等。

tf的可以被当做是一种标准规范, 这套标准定义了坐标转换的数据格式和数据结构, tf本质是树状的数据结构,tf也可以看成是一个topic: /tf , 话题中的message保存的就是tf tree的数据结构格式. 维护了整个机器人的甚至是地图的坐标转换关系。
在这里插入图片描述观察上图,可以看到ROS数据结构的一个抽象图, ROS中机器人模型包含大量的部件,这些部件统称之为link,每一个link上面对应着一个frame, 即一个坐标系, link和frame概念是绑定在一起的,像上图可以看到又很多的frame,错综复杂的铺置在机器人的各个link上, 维护各个坐标系之间的关系, 就要靠着tf tree来处理。

每两个frame之间都会有一个Node来发布消息来broadcaster,来发布消息维系坐标转换,进而维护着各个坐标系之间的联通。

TF消息

TransformStamped.msg的格式规范如下:

std_mags/Header header
		uint32 seq
		time stamp
		string frame_id
string child_frame_id
geometry_msgs/Transform transform
		geometry_msgs/Vector3 translation
				float64 x
				float64 y
				float64 z
		geometry_msgs/Quaternion rotation
				float64 x
				float64 y
				flaot64 z
				float64 w

   
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

许多的TransformStamped.msg发向tf, 形成了TF树

TF树的数据类型

TF tree是由很多的frame之间TF拼接而成

  • tf/tfMessage.msg
  • tf2_msgs/TFMessage.msg
    TF的数据类型有两个, 主要的原因是版本的迭代。 自ROS Hydro以来, tf第一代已被“弃
    用”, 转而支持tf2。 tf2相比tf更加简单高效

使用命令 rostopic info /tf 查看tf版本

格式定义

tf/tfMessage.msg或tf2_msgs/TFMessage标准格式规范如下:

geometry_msgs/TransformStamped[] transforms
std_msgs/Header header
		uint32 seq
				time stamp
				string frame_id
				string child_frame_id
		geometry_msgs/Transform transform
		geometry_msgs/Vector3 translation
				float64 x
				float64 y
				float64 z
		geometry_msgs/Quaternion rotation
				float64 x
				float64 y
				flaot64 z
				float64 w

   
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

一个TransformStamped数组就是一个TF tree。

tf in c++

TF不仅仅是一个标准、 话题, 它还是一个接口。

数据类型

C++中给我们提供了很多TF的数据类型,如下:
在这里插入图片描述tf::StampedTransform只能用在C++里, 只是C++的一个类, 一种数据格式, 并不是一个消息。而geometry_msgs/TransformStamped.msg是一个message,它依赖于ROS, 与语言无关,

数据转换

在这里插入图片描述

TF里有可能会遇到各种各样数据的转换, 常见的四元数、 旋转矩阵、 欧拉角这三种数据之间的转换

定义空间点和空间向量

//计算两个向量的点积
tfScalar::tfDot(const Vector3 &v1, const Vector3 &v2)

//计算向量的模
tfScalar length()

//求与已知向量同方向的单位向量
Vector3 &normalize()

//计算两个向量的夹角
tfScalar::tfAngle(const Vector3 &v1, const Vector3 &v2)

//计算两个向量的距离
tfScale::tfDistance(const Vector3 &v1, const Vector3 &v2)

//计算两个向量的乘积
tfScale::tfCross(const Vector3 &v1,const Vector3 &v2)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

定义四元数

//由欧拉角计算四元数
setRPY(const tfScalar& yaw, const stScalar &pitch, const tfScalar &roll)

//由四元数得到旋转轴
Vector3 getAxis

ROS中实现tf变换需要以下两个步骤: 1. 发布tf变换信息:需要创建一个tf广播器,通过该广播器发布机器人各个坐标系之间的tf变换信息。在ROS中,可以使用`tf::TransformBroadcaster`类来实现tf变换信息的发布,具体步骤如下: - 创建一个`tf::TransformBroadcaster`对象。 - 构造一个`tf::Transform`对象,表示需要发布的tf变换信息。 - 调用`sendTransform()`函数发布tf变换信息。 2. 订阅tf变换信息:需要创建一个tf监听器,通过该监听器订阅机器人各个坐标系之间的tf变换信息。在ROS中,可以使用`tf::TransformListener`类来实现tf变换信息的订阅,具体步骤如下: - 创建一个`tf::TransformListener`对象。 - 调用`lookupTransform()`函数获取需要订阅的tf变换信息。 下面是一个简单的例子,演示如何通过tf广播器发布机器人的tf变换信息: ```cpp #include <ros/ros.h> #include <tf/transform_broadcaster.h> int main(int argc, char** argv){ ros::init(argc, argv, "robot_tf_publisher"); ros::NodeHandle n; tf::TransformBroadcaster broadcaster; ros::Rate loop_rate(10.0); while (n.ok()){ tf::Transform transform; transform.setOrigin( tf::Vector3(0.0, 2.0, 0.0) ); tf::Quaternion q; q.setRPY(0, 0, 1.57); transform.setRotation(q); broadcaster.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "base_link", "laser")); loop_rate.sleep(); } return 0; }; ``` 上述代码中,创建了一个tf广播器`broadcaster`,并在每个循环周期中发布机器人的tf变换信息,其中`setOrigin()`函数和`setRotation()`函数用于设置机器人的坐标系之间的变换关系。在本例中,机器人的激光雷达坐标系"laser"相对于机器人底盘坐标系"base_link"沿着z轴平移了2米,并绕z轴旋转了90度(即1.57弧度)。 如果需要订阅机器人的tf变换信息,可以通过如下代码实现: ```cpp #include <ros/ros.h> #include <tf/transform_listener.h> int main(int argc, char** argv){ ros::init(argc, argv, "robot_tf_listener"); ros::NodeHandle n; tf::TransformListener listener; ros::Rate loop_rate(10.0); while (n.ok()){ tf::StampedTransform transform; try{ listener.lookupTransform("base_link", "laser", ros::Time(0), transform); } catch (tf::TransformException &ex) { ROS_ERROR("%s",ex.what()); ros::Duration(1.0).sleep(); continue; } ROS_INFO("Translation: [%f, %f, %f]", transform.getOrigin().x(), transform.getOrigin().y(), transform.getOrigin().z()); ROS_INFO("Rotation: [%f, %f, %f, %f]", transform.getRotation().x(), transform.getRotation().y(), transform.getRotation().z(), transform.getRotation().w()); loop_rate.sleep(); } return 0; }; ``` 上述代码中,创建了一个tf监听器`listener`,并在每个循环周期中获取机器人的tf变换信息,其中`lookupTransform()`函数用于获取机器人底盘坐标系"base_link"到激光雷达坐标系"laser"之间的tf变换信息,`getOrigin()`函数和`getRotation()`函数用于获取tf变换信息中的平移和旋转部分。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

October407

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值