当前位置:网站首页>ROS2知识(6):坐标对象TF原理和实践

ROS2知识(6):坐标对象TF原理和实践

2022-06-23 11:53:00 无水先生

https://articulatedrobotics.xyz/ready-for-ros-6-tf/

一、变换的重要性?

        坐标变换(或变换)在机器人数学中发挥着巨大的作用。它们是一种数学工具,用于获取从一个角度表示的点或测量值,并以更有用的不同角度表示它们。如果不使用转换,我们将需要使用三角函数来执行计算,这对于更大的问题会很快变得非常复杂,尤其是在 3D 中。

        本教程是关于 ROS 如何使使用转换变得简单的全部内容。如果您对更复杂和有趣的基础数学特别感兴趣,我已经编写了(大部分)关于它们的一系列教程,可在此处获得。

        下面显示了两个有助于转换的机器人系统示例。首先,两个移动机器人正在探索,其中一个发现了一个感兴趣的对象。另一个机器人如何知道如何到达它?在第二个中,安装的摄像头发现了一个目标,机械手需要将抓手移到目标上。我们如何知道从夹具到目标的正确运动?

        注意:上图的两种情况中,一种是两个动态Frame在world坐标的关系;另一个是base-link与world相对静止的其概况。

        为了解决这些问题,我们需要首先将坐标系或框架分配给我们系统的适当组件。接下来,我们需要定义Frame之间的转换。变换告诉我们将一帧转换为另一帧所需的平移和旋转,并且可以很容易地反转到另一种方式。

        如果我们有一个系统,其中每一帧都由它与一个(并且只有一个)其他帧的关系来定义,这将创建一个树结构,我们将能够将一个帧中的已知点转换为树中的任何其他帧.

        弄清楚这背后的所有数学和代码可能非常棘手,因此 ROS 为我们提供了一个完整的子系统,只是为了让转换工作更容易。在本教程中,我们将学习如何为一些示例设置转换树。

二、变换Frame

        ROS 提供了一个名为 tf2(TransForm 版本 2)的系统来为我们处理这些转换。任何节点都可以使用 tf2 库将转换从一帧广播到另一帧。如上所述,这些变换将需要形成一个树结构,其中每一帧由另一个帧的一个(并且只有一个)变换定义,但可以有任意数量的帧依赖于它。下图显示了我们稍后将探索的树的一部分。在这棵树中,base 和 camera 是相对于 world 定义的,l3 是相对于 base 定义的。

        任何节点也可以使用 tf2 库来监听变换,然后使用变换将点从任何帧转换到任何其他帧,只要它们在树中连接即可。

        当一个节点广播一个特定的变换时,它可以是静态的(不随时间变化),也可以是动态的(可能随时间变化,但不是必须的)。这种区别的原因是强大的系统需要知道他们的信息是否过时,并且如果广播公司有一段时间没有更新动态转换,则可以标记错误。另一方面,静态变换可以广播一次,并且在广播新的变换之前假定是正确的。

        在下面,tf2 库仍在使用主题(/tf 和 /tf_static)来处理所有这些通信,但是因为我们自己实际上并不发布到主题,所以我们将其称为广播和侦听而不是发布和订阅。

        如果我们正在编写自己的节点,我们可以对它们进行编码以广播我们喜欢的任何变换,但我们大多数人刚开始时还没有准备好编写自定义节点或计算变换。为了解决这个问题,ROS 附带了一些内置节点来执行一些常见的广播任务。

三、单个Frame广播

        第一种方法是使用 static_transform_publisher 手动广播它们。正如你可能猜到的,这个工具不能广播动态变换,只能广播静态变换。这可能看起来有点没用,但它对于学习转换、进行快速测试以及在更大的系统中充当“粘合剂”非常有帮助(例如,如果两个不同的节点期望一个帧具有不同的名称,或者位于稍微不同的位置)。

        下面的命令将广播静态变换,并提供从 parent_frame 到 child_frame 的平移和旋转。请注意,旋转以弧度为单位,并在平移之后处理,按顺序相对于局部坐标系。

1
ros2 run tf2_ros static_transform_publisher x y z yaw pitch roll parent_frame child_frame

例如,我们可能想要一个框架 robot_1 以 45°(0.785 弧度)的角度与世界框架交叉并向上。为此,我们将使用以下命令:

1
ros2 run tf2_ros static_transform_publisher 2 1 0 0.785 0 0 world robot_1

        假设我们有第二个机器人,它总是坐在我们第一个机器人的右侧(就像一个边车)。使用第二个终端,我们可以使用以下命令创建另一个静态变换来创建一个新框架,robot_2,它位于robot_1 的正 x 方向 1m 处。

1
ros2 run tf2_ros static_transform_publisher 1 0 0 0 0 0 robot_1 robot_2

为了检查这些是否有效,我们将使用 ROS 可视化工具 RViz。

四、在RVIZ上看Frame和转换

在 ROS 2 中,RViz(ROS 可视化工具)称为 rviz2,位于同名包中。所以我们只需要运行:

1
ros2 run rviz2 rviz2
请注意,您可以直接运行 rviz2 作为快捷方式,而不是使用 ros2 run。
RViz可以展示各种不同的数据。要显示 TF 数据,我们单击左下角的“添加”按钮,然后选择“TF”。

我们的变换还不会出现,因为我们还没有告诉 RViz 使用哪个帧作为参考(它默认为地图,现在不存在)。在左上角,我们可以选择世界作为我们的固定框架。

“全局状态”应该变得健康,我们的两个框架应该出现,它们之间有一条线表示转换。

请注意,RViz 将转换表示为从子到父的箭头,而不是在下面的介绍和 view_frames 中的父到子。

        我们可以使用左侧面板配置 RViz 中显示的数据。例如,我们可以打开 TF 可视化设置并启用显示frame名称。

        如果我们回到我们的第一个终端,并以 90°(1.57 rad)的更大旋转重新运行命令,我们应该在 RViz 中看到第一个机器人的标记旋转,并且第二个机器人也移动,因为它的框架是相对于定义的第一个机器人。

1
ros2 run tf2_ros static_transform_publisher 2 1 0 1.57 0 0 world robot_1

        玩转这个并了解转换的工作原理是件好事。尝试将固定框架(左上角)更改为机器人之一而不是世界,将框架调整为新的位置和旋转,或添加一些新的。

        在进行下一部分之前,我们需要确保停止所有 static_transform_publishers 并关闭 RViz,否则它们会干扰。

五、广播一个移动机器人

        到目前为止,我们已经学到了一些很酷的技巧,但我们仍然坚持发布静态帧。我们希望我们的机器人移动!在我们解决这个问题之前,我们需要安装几个额外的包:

1
sudo apt install ros-foxy-xacro ros-foxy-joint-state-publisher-gui

        这样做的第一步是确保我们有一个机器人的 URDF 文件。这是一种配置文件,我们可以在其中指定机器人组件的各种物理特性,例如它们的大小、形状、颜色等。有很多教程可用于编写 URDF 文件,但现在我们可以使用这个示例文件,它用于类似于介绍中的操纵器。

在 URDF 中,机器人由一系列称为链接的刚性组件组成,这些链接以父子树结构连接在一起,其中不同链接之间的关系称为关节。似曾相识?

        不难看出链接/关节模式与框架/变换模式非常相似。因为它们关系密切,所以有一个名为 robot_state_publisher 的 ROS 节点,它可以接收一个 URDF 文件并自动广播其中的所有转换。它还会将 URDF 文件的完整内容发布到主题 /robot_description,以便任何其他需要它的节点都可以使用相同的文件。

        在 URDF 文件中,每个关节都可以定义为“固定的”,或者是多种可移动类型中的一种(例如,连续旋转、有限旋转、线性滑动)。对于固定的关节,robot_state_publisher 可以只发布静态变换,但对于移动的关节,它需要一个外部值(例如角度或距离)来计算该时间点的动态变换。为了获取这些值,它订阅了一个名为 /joint_states 的主题,该主题将包含 JointState 消息。这些消息可以包含有关关节的位置、速度或努力的信息(但现在我们只使用位置)。

        突然间,我们的工作变得轻松多了!无需广播整个转换,我们需要做的就是发布 JointState 消息。通常,这些数据将来自机器人上的执行器反馈传感器,例如编码器或电位计(以及在模拟环境中可以模拟的那些)。现在,我们将使用名为joint_state_publisher_gui 的工具来伪造联合状态。该节点将查看由 robot_state_publisher 发布的 /robot_description 主题,找到任何可以移动的关节,并为它们显示一个滑块。它从这些滑块中读取值,并将它们发布到 /joint_states。

让我们开始运行这一切。

首先,我们将运行 robot_state_publisher,第一次运行时可能会有点混乱,因为传入 URDF 文件有点棘手。 URDF 采用参数 robot_description,因此该命令将类似于:

1
ros2 run robot_state_publisher robot_state_publisher --ros-args -p robot_description:=(something here)

        您可能希望 robot_description 参数是 URDF 文件的路径,但它实际上希望 URDF 文件的完整内容在命令行中传递。为了实现这一点,我们需要使用 URDF 上的 xacro 软件对其进行预处理,在子 shell ($(...)) 中运行它,并将其括在引号 ("...") 中,这样空格就不会出现打破一切。所以我们的运行命令看起来更像:

1
ros2 run robot_state_publisher robot_state_publisher --ros-args -p robot_description:="$(xacro path/to/my/xacro/file.urdf.xacro)"

请注意,因为以这种方式运行 robot_state_publisher 非常痛苦,所以通常最容易创建一个启动文件来为我们执行此操作。此处提供了一个示例。​
 

然后,要发布关节状态,我们可以运行

1
ros2 run joint_state_publisher_gui joint_state_publisher_gui

        最后,我们可以再次启动 RViz,添加 TF 可视化,并在调整滑块时看到我们的帧移动。我们还可以在 RViz 中添加“RobotModel”可视化。使用选项选择 /robot_description 作为主题,应该会出现链接的可视化表示。

 请注意,对于移动平台,事情会变得有点复杂。 robot_state_publisher 可以广播机器人内的所有变换,但您需要其他节点来发布变换,例如机器人在环境中的位置。有现有的节点来处理这种事情,但它们将在后面的教程中介绍。

六、在引擎盖下

        希望上面的例子有效,但有时当我们使用转换时,事情不能正常工作,我们需要找出原因。

        如前所述,转换数据跨两个主题发布,/tf 和 /tf_static。我们可以尝试使用 ros2 主题回声直接收听这些主题,但这有时很难解释。为了提供帮助,ROS 提供了一个名为 view_frames 的工具(我们需要安装 tf2_tools 吗?),它可以让我们可视化转换树,以及有关它如何被广播的信息。

请注意,在ROS 1中有一个名为rqt\u tf\u tree的有用工具,它可以做到这一点,但麻烦较少。然而,在撰写本文时,这还没有移植到ROS 2,因此我们必须使用view\u框架。

        view\u frames工具实际上是一个Python脚本,它会监听转换几秒钟,然后生成一个名为frames的文件。pdf(以及frames.gv)在执行脚本时终端所在的任何目录中(对于新终端,这将是您的主目录)。

该脚本是tf2\u tools包的一部分,因此我们只需运行:

1
ros2 run tf2_tools view_frames.py

        如果我们查看生成的文件(在文件浏览器中打开,或从带有atril frames.pdf的终端打开),我们可以看到可视化的树。请注意,此处的箭头与RViz相反(与引言中的箭头相同)。我们现在不会太担心显示的其余信息。

如果您不熟悉它,那么以“16314……”开头的大数字是时间,用Linux系统中常用的“Unix时间”表示,在机器人平台中也是如此。有关Unix时间(也称为Epoch时间)的更多信息,请查看Epoch转换器。运行模拟时,Gazebo将生成自己的时间源,数字将以Gazebo启动后的秒为单位。

七 结论

        ROS转换系统是一个功能强大的工具,我们只是初步了解了如何使用它。我们如何使用TF的细节将取决于许多因素,例如我们的机器人是移动的,还是操纵器(或移动操纵器),以及我们是在运行仿真还是在物理硬件上。在未来的教程中,我们将更仔细地研究TF如何用于特定项目。

参看, we’ll see how to write our own URDF files.

原网站

版权声明
本文为[无水先生]所创,转载请带上原文链接,感谢
https://blog.csdn.net/gongdiwudu/article/details/124914278