在上一个教程中,我们讨论了tf和time的基本概念。本教程将更进一步,并展示一个最强大的技巧。
1 时间旅行
那么让我们回到上一个教程中我们结束的地方。转到您的教程包:
$ roscd learning_tf
并打开文件src / turtle_tf_listener.cpp。看一下第25-30行:
try{
ros::Time now = ros::Time::now();
listener.waitForTransform("/turtle2", "/turtle1",
now, ros::Duration(1.0));
listener.lookupTransform("/turtle2", "/turtle1",
now, transform);
现在,不要让第二只乌龟去第一只龟现在的地方,让第二只乌龟去第一只乌龟5秒前的地方:
try{
ros::Time past = ros::Time::now() - ros::Duration(5.0);
listener.waitForTransform("/turtle2", "/turtle1",
past, ros::Duration(1.0));
listener.lookupTransform("/turtle2", "/turtle1",
past, transform);
那么现在,如果你想运行这个,你期望看到什么?绝对在前5秒内,第二只乌龟不知道去哪里,因为我们还没有第一只乌龟的5秒历史。但这5秒后呢?我们试试吧:
$ make or catkin_make
$ roslaunch learning_tf start_demo.launch
你的乌龟是不是像这个屏幕截图那样无法控制地驾驶?那么发生了什么?
-
问过tf,“ 5秒前/ turtle1的姿势相对于/ turtle2 5秒前是什么?” 。这意味着我们根据5秒前第二只龟的位置以及第一只龟在5秒前的位置控制第二只乌龟。
-
我们真正要问的是,"What was the pose of /turtle1 5 seconds ago, relative to the current position of the /turtle2?".
2 lookupTransform的高级API
So how can we ask tf a question like that?
此API使我们能够明确说明每个坐标的转换时间。这就是代码的样子:
try{
ros::Time now = ros::Time::now();
ros::Time past = now - ros::Duration(5.0);
listener.waitForTransform("/turtle2", now,
"/turtle1", past,
"/world", ros::Duration(1.0));
listener.lookupTransform("/turtle2", now,
"/turtle1", past,
"/world", transform);
lookupTransform()的高级API 有六个参数:
- 将转换的坐标,
- 时间
- 转换目的坐标
- 时间
- 指定不随时间变化的帧,在本例中为“/ world”坐标,
- 用于存储结果的变量。
请注意,waitForTransform()也有一个基本的和高级的API,就像lookupTransform()一样。
此图显示了tf在后台执行的操作。在过去,它计算从第一只乌龟到世界的转变。
在世界框架中,时间从过去到现在。
现在,tf计算从世界到第二只乌龟的转变。
3 检查结果
让我们再次运行模拟器,这次使用高级时间旅行API:
$ make or catkin_make
$ roslaunch learning_tf start_demo.launch
是的,第二只乌龟被引导到5秒前第一只乌龟的位置!