系列文章目录
前言
PR2
你想看看 tf 能做什么?看看 tf 介绍演示。
一个机器人系统通常有许多随时间变化的三维坐标系,如世界坐标系、基础坐标系、抓手坐标系、头部坐标系等:
- 5 秒钟前,头部坐标系相对于世界坐标系的位置在哪里?
- 我的抓手中的物体相对于底座的姿势是什么?
- 底座坐标系在地图坐标系中的当前姿态是什么?
tf 可以在分布式系统中运行。这意味着系统中任何一台电脑上的所有 ROS 组件都能获取机器人坐标系的所有信息。没有中央转换信息服务器。
有关设计的更多信息,请参阅/设计
我们创建了一套教程,一步步指导你使用 tf。您可以从 tf 入门教程开始。要查看所有 tf 和 tf 相关教程的完整列表,请访问教程页面。
任何用户使用 tf 基本上都有两项任务:监听变换和广播变换。
任何使用 tf 的用户都需要监听变换:
- 监听变换 - 接收和缓冲系统中广播的所有坐标系,并查询坐标系间的特定变换。请查看编写 tf 监听器教程(Python)(C++)。
要扩展机器人的功能,您需要开始广播变换。
- 广播变换 - 向系统其他部分发送坐标系的相对姿态。一个系统可以有多个广播变换器,每个变换器提供机器人不同部分的信息。请查看编写 tf 广播器教程(Python)(C++)。
完成基本教程后,您可以继续学习 tf 和时间。tf 和时间教程(Python)(C++)教授 tf 和时间的基本原理。关于 tf 和时间的高级教程 (Python) (C++) 讲授使用 tf 进行时间旅行的原理。
一、tf 介绍
1.1 设置 demo
本教程的节点是为 Ubuntu 发布的,因此请安装它们:
sudo apt-get install ros-noetic-ros-tutorials ros-noetic-geometry-tutorials ros-noetic-rviz ros-noetic-rosbash ros-noetic-rqt-tf-tree
1.2 运行演示
现在我们已经完成了 turtle_tf 教程软件包的安装,让我们运行 demo 程序。
roslaunch turtle_tf turtle_tf_demo.launch
您会看到海龟仿真器,从两只海龟开始。
(如果你遇到进程死机的情况,也可以采取变通方法)。
启动海龟模拟器后,你可以使用键盘上的方向键在海龟模拟器中驱动中心海龟,选择 roslaunch 终端窗口,这样就可以捕捉到你驱动海龟的按键。
你可以看到,一只乌龟会不断移动,跟着你驾驶的乌龟转圈。
1.3发生了什么
本演示使用 tf 库创建了三个坐标系:世界坐标系、乌龟 1 坐标系和乌龟 2 坐标系。本教程使用 tf 广播器发布乌龟坐标系,并使用 tf 监听器计算乌龟坐标系的差异,然后移动一只乌龟跟随另一只乌龟。
1.4 tf 工具
现在让我们来看看如何使用 tf 制作这个演示。我们可以使用 tf 工具来查看 tf 在幕后所做的工作。
1.4.1 使用 view_frames
view_frames 可以创建 tf 通过 ROS 广播的坐标系图。
rosrun tf view_frames
将看到
Transform Listener initing Listening to /tf for 5.000000 seconds Done Listening dot - Graphviz version 2.16 (Fri Feb 8 12:52:03 UTC 2008) Detected dot version 2.16 frames.pdf generated
在这里,一个 tf 监听器正在监听通过 ROS 广播的坐标系,并绘制坐标系之间的连接树。查看树状图
evince frames.pdf
在这里,我们可以看到 tf 广播的三个坐标系:世界、turtle1 和 turtle2。我们还可以看到,world 是 turtle1 和 turtle2 两坐标系的父坐标系。为了便于调试,view_frames 还会报告一些诊断信息,如何时收到了最旧和最近的坐标系变换,以及 tf 坐标系发布到 tf 的速度。
1.4.2 使用 rqt_tf_tree
rqt_tf_tree 是一个运行时工具,用于可视化通过 ROS 广播的坐标系树。只需点击图表左上角的刷新按钮,即可刷新树形图。
使用方法
rosrun rqt_tf_tree rqt_tf_tree
或者
rqt &
然后从插件选项卡中选择 rqt_tf_tree。
1.4.3 使用 tf_echo
tf_echo 报告通过 ROS 广播的任意两个坐标系之间的变换。
使用方法:
rosrun tf tf_echo [reference_frame] [target_frame]
让我们来看看乌龟 2 坐标系相对于乌龟 1 坐标系的变换,这相当于乌龟 1 到世界的变换乘以世界到乌龟 2 坐标系的变换的乘积。
rosrun tf tf_echo turtle1 turtle2
当 tf_echo 监听器接收到通过 ROS 广播的坐标系时,就会显示变换。
At time 1416409795.450 - Translation: [0.000, 0.000, 0.000] - Rotation: in Quaternion [0.000, 0.000, 0.914, 0.405] in RPY [0.000, -0.000, 2.308] At time 1416409796.441 - Translation: [0.000, 0.000, 0.000] - Rotation: in Quaternion [0.000, 0.000, 0.914, 0.405] in RPY [0.000, -0.000, 2.308] At time 1416409797.450 - Translation: [0.000, 0.000, 0.000] - Rotation: in Quaternion [0.000, 0.000, 0.914, 0.405] in RPY [0.000, -0.000, 2.308] At time 1416409798.441 - Translation: [0.000, 0.000, 0.000] - Rotation: in Quaternion [0.000, 0.000, 0.914, 0.405] in RPY [0.000, -0.000, 2.308] At time 1416409799.433 - Translation: [0.000, 0.000, 0.000] - Rotation: in Quaternion [0.000, 0.000, 0.691, 0.723] in RPY [0.000, -0.000, 1.526]
当您驾驶乌龟四处游动时,您会看到变换随着两只乌龟的相对移动而发生变化。
1.5 rviz 和 tf
rviz 是一种可视化工具,可用于检查 tf 框架。让我们使用 rviz 来查看我们的乌龟帧。 让我们使用 rviz 的 -d 选项,通过 turtle_tf 配置文件启动 rviz:
rosrun rviz rviz -d `rospack find turtle_tf`/rviz/turtle_rviz.rviz
在侧边栏中,您将看到 tf 播放的坐标系。当你驾驶乌龟移动时,你会看到坐标系在 rviz 中移动。
既然我们已经研究了 turtle_tf_demo,那么让我们来看看如何为这个演示编写广播器(Python)(C++)。
二、编写一个 tf 广播器(Python)
注意:如果您还没有学习过编写 tf 广播员(C++)教程,请务必学习本节内容。
在接下来的两节教程中,我们将编写代码来重现 tf 入门教程中的演示。之后,下面的教程将重点使用更高级的 tf 功能来扩展演示。
在开始之前,您需要为本项目创建一个新的 ros 包。在沙盒文件夹中,创建一个名为 learning_tf 的包,该包依赖于 tf、roscpp、rospy 和 turtlesim:
cd %YOUR_CATKIN_WORKSPACE_HOME%/src catkin_create_pkg learning_tf tf roscpp rospy turtlesim
构建新软件包后,才能运行 roscd:
cd %YOUR_CATKIN_WORKSPACE_HOME%/ catkin_make source ./devel/setup.bash
2.1 如何广播变换
本教程教您如何向 tf 广播坐标框架。在本例中,我们要广播乌龟移动时不断变化的坐标系。
首先创建源文件。转到我们刚刚创建的软件包:
roscd learning_tf
2.1.1 代码
首先,让我们在 learning_tf 软件包中新建一个名为 nodes 的目录。
mkdir nodes
启动你最喜欢的编辑器,将以下代码粘贴到名为 nodes/turtle_tf_broadcaster.py 的新文件中。
#!/usr/bin/env python import roslib roslib.load_manifest('learning_tf') import rospy import tf import turtlesim.msg def handle_turtle_pose(msg, turtlename): br = tf.TransformBroadcaster() br.sendTransform((msg.x, msg.y, 0), tf.transformations.quaternion_from_euler(0, 0, msg.theta), rospy.Time.now(), turtlename, "world") if __name__ == '__main__': rospy.init_node('turtle_tf_broadcaster') turtlename = rospy.get_param('~turtle') rospy.Subscriber('/%s/pose' % turtlename, turtlesim.msg.Pose, handle_turtle_pose, turtlename) rospy.spin()
别忘了让节点可执行:
chmod +x nodes/turtle_tf_broadcaster.py
ROS - tf(二)+https://developer.aliyun.com/article/1585196