许多ROS包需要使用tf软件库发布机器人的变换树。在抽象层,变换树根据不同坐标系之间的平移和旋转来定义偏移量。为了使这更具体,考虑一个简单的机器人的例子,它具有安装在其顶部的单个激光器的移动基座。我们定义两个坐标系:一个对应于机器人底座的中心点,一个坐标系安装在基座顶部的激光中心点:“base_link”坐标系(对于导航,它重要的是将其放置在机器人的旋转中心)与“base_laser”的坐标系。我们假设激光器的一些数据以与激光中心点的距离的形式来表达。换句话说,我们在“base_laser”坐标系中有一些数据。现在假设我们想要获取这些数据并使用它来帮助机器人避免活动空间的障碍。要做到这一点,我们需要一种从“base_laser”坐标系转换成“base_link”坐标系的激光扫描的方法。实质上,我们需要定义“base_laser”和“base_link”坐标系之间的关系。
在定义这种关系时,假设我们知道激光器在移动基座的中心点之上10厘米和向前20厘米处安装。这给了我们一个将“base_link”坐标系与“base_laser”坐标系相关联的平移值和偏移值。具体来说,我们知道要从“base_link”坐标系到“base_laser”坐标系的数据,我们必须应用(x:0.1m,y:0.0m,z:0.2m)的转换,并从“ base_laser“坐标系到”base_link“坐标系,我们必须应用相反的变换(x:-0.1m,y:0.0m,z:-0.20m)。
我们将使用tf定义“base_link”和“base_laser”之间的关系,并让它管理两个坐标系之间的变换。
要使用tf定义和存储“base_link”和“base_laser”坐标系之间的关系,我们需要将它们添加到一个变换树中。在概念上,变换树中的每个节点对应于坐标系,每个方向对应于需要应用从当前节点移动到其子节点的变换。Tf使用树结构来确保只有一个遍历将任何两个坐标系连接在一起,并假设树中的所有方向都是从父节点引导到子节点。
我们简单示例创建一个变换树,创建两个节点,一个用于“base_link”坐标系,一个用于“base_laser”坐标系。为了创建它们之间的方向,我们首先需要决定哪个节点是父节点,哪些节点是子节点。记住,这种区别很重要,因为tf假定所有转换都从父对象移动到子对象。选择“base_link”坐标系作为父节点,因为随着其他传感器被添加到机器人,通过遍历“base_link”框架,它们将最有意义地与“base_laser”坐标系相关。这意味着连接“base_link”和“base_laser”的变换应为(x:0.1m,y:0.0m,z:0.2m)。使用这个变换树设置,将在“base_laser”坐标系中接收到的激光扫描转换为“base_link”坐标系就像调用tf库一样简单。我们的机器人可以使用这些信息来理解“base_link”框架中的激光扫描,并安全地计划避开环境中的障碍物。
(2)编写代码
假设我们将描述在“base_laser”坐标系中获取点将其转换为“base_link”坐标系。我们需要做的第一件事是创建一个负责在系统中发布转换的节点。接下来,我们必须创建一