原文地址:http://wiki.ros.org/tf/Tutorials/Adding a frame (Python)

Adding a frame (Python)

描述:本教程教您如何向tf添加额外的固定坐标系。
在前面的教程中,我们通过添加tf广播器和tf监听器来重新创建turtle demo。本教程将教您如何向tf树中添加额外的坐标系。这与创建tf广播非常相似,并且将展示tf的一些能力。

1 Why adding frames

对于许多任务来说,在本地坐标系内进行思考更容易,例如,在激光扫描器的中心处的坐标系中推断激光扫描更容易。tf允许您为系统中的每个传感器、链接等定义本地坐标系。而且,tf将负责所有引入的额外坐标系转换。

2 Where to add frames

tf建立坐标系的树结构;它不允许坐标系结构中的闭环。这意味着一个坐标系只有一个父节点,但是它可以有多个子节点。目前,我们的tf树包含三个坐标系:world、turtle1和turtle2。这两只turtle是world的子坐标系。如果我们想向tf添加新坐标系,三个现有坐标系中的一个需要是父坐标系,并且新坐标系将成为子坐标系。
三 tf / Tutorials / Adding a frame (Python)

3 How to add a frame

在我们的turtle 示例中,我们将为turtle1添加一个新坐标系。这个坐标系将是turtle2的“胡萝卜”。
让我们首先创建源文件。转到我们为前面的教程创建的包:

 $ roscd learning_tf

3.1 The Code

启动您喜欢的编辑器,并将以下代码粘贴到一个名为src/frame_tf_broadcaster.cpp的新文件中。

   1 #!/usr/bin/env python  
   2 import roslib
   3 roslib.load_manifest('learning_tf')
   4 
   5 import rospy
   6 import tf
   7 
   8 if __name__ == '__main__':
   9     rospy.init_node('fixed_tf_broadcaster')
  10     br = tf.TransformBroadcaster()
  11     rate = rospy.Rate(10.0)
  12     while not rospy.is_shutdown():
  13         br.sendTransform((0.0, 2.0, 0.0),
  14                          (0.0, 0.0, 0.0, 1.0),
  15                          rospy.Time.now(),
  16                          "carrot1",
  17                          "turtle1")
  18         rate.sleep()

不要忘记使节点可执行:

chmod +x nodes/fixed_tf_broadcaster.py

代码非常类似于tf broadcaster 教程中的示例。只是这里,transform不会随时间而改变。

3.2 The Code Explained

让我们看看这段代码中的关键行:

  13         br.sendTransform((0.0, 2.0, 0.0),
  14                          (0.0, 0.0, 0.0, 1.0),
  15                          rospy.Time.now(),
  16                          "carrot1",
  17                          "turtle1")

在这里,我们创建一个新的transform,从父turtle1到新的子carrot1。carrot1坐标系与turtle1坐标系向左偏移2米。

4 Running the frame broadcaster

编辑start_demo.launch 启动文件,只简单添加以下几行:

  <launch>
    ...
    <node pkg="learning_tf" type="fixed_tf_broadcaster.py"
          name="broadcaster_fixed" />
  </launch>

首先,确保您停止了前一个教程中的启动文件(使用Ctrl-c)。现在你已经准备好开始播放turtle broadcaster的demo了:

 $ roslaunch learning_tf start_demo.launch

5 Checking the results

因此,如果您驱动turtle1四处游荡,您会发现即使我们添加了一个新坐标系,该行为与前一个教程没有改变。这是因为添加额外的坐标系不会影响其他坐标系,并且我们的listener仍然使用之前定义的坐标系。所以,让我们改变listener的行为。
打开 nodes/turtle_tf_listener.py文件,用“/carrot1”简单替换“/turtle1”:

   1 (trans,rot) = listener.lookupTransform("/turtle2", "/carrot1", rospy.Time(0))

现在好的部分是:重新编译并重新启动turtle demo,您将看到turtle2跟随carrot而不是turtle1!记住,carrot离turtle1左边2米。carrot没有视觉上的表示,但是您应该看到turtle2移动到该点。

 $ roslaunch learning_tf start_demo.launch

6 Broadcasting a moving frame

在本教程中我们发布的额外坐标系是一个固定的坐标系,它不会随着时间而相对于父坐标系发生变化。然而,如果你想发布一个移动坐标系,你可以改变broadcaster让它随时间改变。让我们修改/carrot1坐标系以相对于/turtle1随时间更改。
Create the file nodes/dynamic_tf_broadcaster.py containing the following (and make it executable with chmod +x as we did above):

   1 #!/usr/bin/env python  
   2 import roslib
   3 roslib.load_manifest('learning_tf')
   4 
   5 import rospy
   6 import tf
   7 import math
   8 
   9 if __name__ == '__main__':
  10     rospy.init_node('dynamic_tf_broadcaster')
  11     br = tf.TransformBroadcaster()
  12     rate = rospy.Rate(10.0)
  13     while not rospy.is_shutdown():
  14         t = rospy.Time.now().to_sec() * math.pi
  15         br.sendTransform((2.0 * math.sin(t), 2.0 * math.cos(t), 0.0),
  16                          (0.0, 0.0, 0.0, 1.0),
  17                          rospy.Time.now(),
  18                          "carrot1",
  19                          "turtle1")
  20         rate.sleep()

注意,我们没有定义来自turtle1的固定偏移,而是使用基于当前时间的sin和cos函数来定义坐标系的偏移。
要测试此代码,请记住将启动文件更改为指向我们新的、动态广播器来定义carrot1,而不是上面的固定广播器:

  <launch>
    ...
    <node pkg="learning_tf" type="dynamic_tf_broadcaster.py"
          name="broadcaster_dynamic" />
  </launch>

现在可以转到下一篇关于tf和time的教程了。

相关文章: