Skip to content

Commit 3f9c45f

Browse files
authored
tf2 Tutorial: Timestamp and time travel tf2 tutorials (Python) (ros2#1770)
* add timestamp and time travel tf2 tutorials * links to previous tutorials * minor fixes in Learning about tf2 and time (Python) tutorial * add more explanations to the time travel tutorial * add explanation about timeout * use case for timeout * add more context and remove questions * update summary * remove trailing whitespaces
1 parent eb4251a commit 3f9c45f

File tree

5 files changed

+224
-0
lines changed

5 files changed

+224
-0
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
.. _LearningAboutTf2AndTimePy:
2+
3+
Learning about tf2 and time (Python)
4+
====================================
5+
6+
**Goal:** Learn to use the ``timeout`` in ``lookup_transform`` function to wait for a transform to be available on the tf2 tree.
7+
8+
**Tutorial level:** Intermediate
9+
10+
**Time:** 10 minutes
11+
12+
.. contents:: Contents
13+
:depth: 2
14+
:local:
15+
16+
Background
17+
----------
18+
19+
In previous tutorials, we recreated the turtle demo by writing a :ref:`tf2 broadcaster <WritingATf2BroadcasterPy>` and a :ref:`tf2 listener <WritingATf2ListenerPy>`.
20+
We also learned how to :ref:`add a new frame to the transformation tree <AddingAFramePy>`.
21+
Now we will learn more about the ``timeout`` argument which makes the ``lookup_transform`` wait for the specified transform for up to the specified duration before throwing an exception.
22+
This tool can be useful to listen for transforms that are published at varying rates or those incoming source with unreliable networking and non negligible latency.
23+
This tutorial will teach you how use the timeout in ``lookup_transform`` function to wait for a transform to be available on the tf2 tree.
24+
25+
Tasks
26+
-----
27+
28+
1 Update the listener node
29+
^^^^^^^^^^^^^^^^^^^^^^^^^^
30+
31+
Edit ``turtle_tf2_listener.py`` and remove the ``timeout=Duration(seconds=1.0)`` parameter that is passed to the ``lookup_transform()`` call on line 76.
32+
It should look like shown below:
33+
34+
.. code-block:: python
35+
36+
trans = self._tf_buffer.lookup_transform(
37+
to_frame_rel,
38+
from_frame_rel,
39+
now)
40+
41+
Moreover, import additional exceptions that we will handle in the beggining of the file:
42+
43+
.. code-block:: python
44+
45+
from tf2_ros import LookupException, ConnectivityException, ExtrapolationException
46+
47+
Edit the exception handling on line 81 by adding newly imported exceptions and ``raise`` statement to see the exception:
48+
49+
.. code-block:: python
50+
51+
except (LookupException, ConnectivityException, ExtrapolationException):
52+
self.get_logger().info('transform not ready')
53+
raise
54+
return
55+
56+
If you now try to run the launch file, you will notice that it is failing:
57+
58+
.. code-block:: console
59+
60+
ros2 launch learning_tf2_py turtle_tf2_demo.launch.py
61+
62+
2 Fix the listener node
63+
^^^^^^^^^^^^^^^^^^^^^^^
64+
65+
You now should notice that ``lookup_transform()`` is failing. It tells you that the frame does not exist or that the data is in the future.
66+
To fix this, edit your code on line 76 as shown below (return the ``timeout`` parameter):
67+
68+
.. code-block:: python
69+
70+
trans = self._tf_buffer.lookup_transform(
71+
to_frame_rel,
72+
from_frame_rel,
73+
now,
74+
timeout=Duration(seconds=1.0))
75+
76+
The ``lookup_transform`` can take four arguments, where the last one is an optional timeout.
77+
It will block for up to that duration waiting for it to timeout.
78+
79+
.. note::
80+
81+
Once this change is made, remove the ``raise`` line from the ``except()`` block that we added above or the code will continue to fail.
82+
83+
You can now run the launch file.
84+
85+
.. code-block:: console
86+
87+
ros2 launch learning_tf2_py turtle_tf2_demo.launch.py
88+
89+
You should notice that ``lookup_transform()`` will actually block until the transform between the two turtles becomes available (this will usually take a few milli-seconds).
90+
Once the timeout has been reached (one second in this case), an exception will be raised only if the transform is still not available.
91+
92+
Summary
93+
-------
94+
95+
In this tutorial you learned more about the ``lookup_transform`` function and its timeout features.
96+
You also learned how to catch and handle additional exceptions that can be thrown by tf2.

source/Tutorials/Tf2/Tf2-Main.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ once for C++ and once for Python.
2020
Writing-A-Tf2-Broadcaster-Py
2121
Writing-A-Tf2-Listener-Py
2222
Adding-A-Frame-Py
23+
Learning-About-Tf2-And-Time-Py
24+
Time-Travel-With-Tf2-Py
2325

2426
Workspace Setup
2527
---------------
@@ -51,3 +53,13 @@ Learning tf2
5153
#. :ref:`Adding a frame (Python) <AddingAFramePy>`.
5254

5355
This tutorial teaches you how to add an extra fixed frame to tf2.
56+
57+
#. :ref:`Learning about tf2 and time (Python) <LearningAboutTf2AndTimePy>`.
58+
59+
This tutorial teaches you to use the timeout in ``lookup_transform`` function to
60+
wait for a transform to be available on the tf2 tree.
61+
62+
#. :ref:`Time travel with tf2 (Python) <TimeTravelWithTf2Py>`.
63+
64+
This tutorial teaches you about advanced time travel features of tf2.
65+
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
.. _TimeTravelWithTf2Py:
2+
3+
Time travel with tf2 (Python)
4+
=============================
5+
6+
**Goal:** Learn about advanced time travel features of tf2.
7+
8+
**Tutorial level:** Advanced
9+
10+
**Time:** 10 minutes
11+
12+
.. contents:: Contents
13+
:depth: 2
14+
:local:
15+
16+
Background
17+
----------
18+
19+
In the previous tutorial, we discussed the :ref:`basics of tf2 and time <LearningAboutTf2AndTimePy>`.
20+
This tutorial will take us one step further and expose a powerful tf2 trick: the time travel.
21+
In short, one of the key features of tf2 library is that it is able to transform data in time as well as in space.
22+
23+
This tf2 time travel feature can be useful for various tasks, like monitoring the state of the robot for long period of time or building a follower robot that will follow the "steps" of the leader.
24+
We will use that time travel feature to look up for the transforms back in time and program the ``turtle1`` follow 5 seconds behind the ``turtle2``.
25+
26+
Time travel
27+
-----------
28+
29+
First, let's go back to where we ended in the previous tutorial `Learning about tf2 and time <LearningAboutTf2AndTimePy>`.
30+
Go to your ``learning_tf2_py`` package.
31+
32+
Now, instead of making the second turtle go to where the carrot is now, we will make the second turtle go to where the first carrot was 5 seconds ago.
33+
Edit the code on lines 75-80 in the ``turtle_tf2_listener.py`` file to:
34+
35+
.. code-block:: python
36+
37+
when = self.get_clock().now() - rclpy.time.Duration(seconds=5.0)
38+
trans = self._tf_buffer.lookup_transform(
39+
to_frame_rel,
40+
from_frame_rel,
41+
when,
42+
timeout=Duration(seconds=1.0))
43+
44+
Now if you run this, during the first 5 seconds, the second turtle would not know where to go because we do not yet have a 5-second history of the first turtle.
45+
But what after these 5 seconds? Let's just give it a try:
46+
47+
.. code-block:: console
48+
49+
ros2 launch learning_tf2_py turtle_tf2_demo.launch.py
50+
51+
.. image:: turtlesim_delay1.png
52+
53+
You should now notice that your turtle is driving around uncontrollably like in this screenshot. Let's try to understand reason behind that behavior.
54+
55+
#. In our code we asked tf2 the following question: "What was the pose of ``carrot1`` 5 seconds ago, relative to ``turtle2`` 5 seconds ago?". This means we are controlling the second turtle based on where it was 5 seconds ago as well as where the first turtle was 5 seconds ago.
56+
57+
#. However, what we really want to ask is: "What was the pose of ``carrot1`` 5 seconds ago, relative to the current position of the ``turtle2``?".
58+
59+
Advanced API for lookup_transform
60+
---------------------------------
61+
62+
To ask the tf2 that particular question, we will use an advanced API that gives us the power to say explicitly when to acquire the specified transformations.
63+
This is done by calling the ``lookup_transform_full`` method with additional parameters.
64+
Your code now would look like this:
65+
66+
.. code-block:: python
67+
68+
when = self.get_clock().now() - rclpy.time.Duration(seconds=5.0)
69+
trans = self._tf_buffer.lookup_transform_full(
70+
target_frame=to_frame_rel,turtle1
71+
target_time=rclpy.time.Time(),
72+
source_frame=from_frame_rel,
73+
source_time=when,
74+
fixed_frame='world',
75+
timeout=Duration(seconds=1.0))
76+
77+
The advanced API for ``lookup_transform_full()`` takes six arguments:
78+
79+
#. Target frame
80+
81+
#. The time to transform to
82+
83+
#. Source frame
84+
85+
#. The time at which source frame will be evaluated
86+
87+
#. The time at which we want to transform
88+
89+
#. Frame that does not change over time, in this case the ``world`` frame
90+
91+
#. Time to wait for the target frame to become available
92+
93+
To sum up, tf2 does the following in the background.
94+
In the past, it computes the transform from the ``carrot1`` to the ``world``.
95+
In the ``world`` frame, tf2 time travels from the past to now.
96+
And at the current time, tf2 computes the transform from the ``world`` to the ``turtle2``.
97+
98+
Checking the results
99+
--------------------
100+
101+
Let's run the simulation again, this time with the advanced time-travel API:
102+
103+
.. code-block:: console
104+
105+
ros2 launch learning_tf2_py turtle_tf2_demo.launch.py
106+
107+
.. image:: turtlesim_delay2.png
108+
109+
And yes, the second turtle is directed to where the first carrot was 5 seconds ago!
110+
111+
Summary
112+
-------
113+
114+
In this tutorial, you have seen one of the advanced features of tf2.
115+
You learned that tf2 can transform data in time and learned how to do that with turtlesim example.
116+
tf2 allowed you to go back in time and make frame transformations between old and current states of turtles by using the advanced ``lookup_transform_full`` API.
16.3 KB
Loading
11.4 KB
Loading

0 commit comments

Comments
 (0)