Contents
Debugging a problem with tf can be very tricky. Many tf related problems are caused by users asking tf the wrong questions. So if you're not familiar with tf, it's a good idea to first run through the tf tutorials. There is even a debugging tf problems tutorial.
These are some useful links for debugging:
This page gives a general strategy that is useful to debug tf problems:
- Understand what you are asking tf.
- Check the frames in the tf buffer.
- Check the timestamps in the tf buffer.
Finding the tf request
Before you can debug anything in tf, you need to understand what you are asking tf. You need to know:
The names of the two frames you are trying to transform between, and
The time at which to transform.
The strategy to find this out depends on what part of the tf interface you are using.
Using lookupTransform
- If you are using the lookupTransform method in tf, you have direct access to the required information. The first three parameters of the lookupTransform method will give you the two frames you are transforming between, and the timestamp at which you try to transform.
Using transformPoint, transformVector, etc.
If you are using tf to transform sensor data such as a point, a vector, a laser scan, etc, the information you need for debugging is in two places. First, look at the first argument of the transformXxxx call; this is the first frame you need. The second frame you need is in the header of the sensor you try to transform. On your data call "data.header.frame_id" to get the second frame. To get the time, call "data.header.stamp".
Checking the Frames
So now that you know the names of the two frames you want to transform between, let's check if tf knows about them. The easiest way to find out is to call:
$ rosrun tf tf_echo frameA frameB
If tf knows about both frameA and frameB, and there is a connection between frameA and frameB, you should get output that looks like this:
At time 1254169758.447 - Translation: [5.556, 5.556, 0.000] - Rotation: in Quaternion [0.000, 0.000, 0.000, 1.000] in RPY [0.000, -0.000, 0.000] At time 1254169759.134 - Translation: [5.556, 5.556, 0.000] - Rotation: in Quaternion [0.000, 0.000, 0.000, 1.000] in RPY [0.000, -0.000, 0.000]
This output shows the actual transform between frameA and frameB. You could take a look at the numbers, and see if they are somewhat close to what you would expect. If you see this, you are ready to move to the next step and check the timestamp.
If tf does not know about a connection between frameA and frameB, you will get output that looks like this:
Failure at 1254169883.148064000 Exception thrown:Frame id /frameA does not exist! When trying to transform between /frameB and /frameA. The current list of frames is: Frame /carrot2 exists with parent /turtle1. Frame /turtle1 exists with parent /world. Frame /world exists with parent NO_PARENT. Frame /turtle2 exists with parent /world. Frame /carrot1 exists with parent /turtle1.
When tf cannot find a connection between frameA and frameB, it shows you a complete list all the frames it does knows about. From this information you can check which transform is missing. If you want to see this in a graphical representation, try out the view frames tool.
Checking the Timestamp
The most tricky problems in tf are often caused by timestamps. Let's first look at the timing information of the specific transform you are looking for:
$ rosrun tf tf_monitor frameA frameB
The most important information here is in the first few lines of each block:
RESULTS: for /frameA to /frameB Chain currently is: /frameB -> /frameA Net delay avg = 0.007317: max = 0.04489
This shows that the transformation from frameA to frameB is delayed by 7 msec on average, and 44 msec maximum. The delay comes from the fact that tf needs to receive transformations from different broadcasters in the system. All this information needs some time to arrive in tf. A delay of a few miliseconds is normal. However, if you see large delays, there is something wrong with one of the broadcasters in your system.
So, if you see a normal delay of a few miliseconds, what can be the problem?
Request a transform at the current time
Since the tf buffer is delayed by a few seconds, you cannot ask tf for the transformation between frameA and frameB at time ros::Time::now(). Because tf is delayed in time, it does not know any transform "now". Check out the tutorial about f and time (C++) (Python) to learn more about this.
Request a transform too far in the past
You might also be requesting the transform between frameA and frameB at a time too far in the past. Tf only keeps a 10-second buffer (this is a setting you can change). If you ask for a transform 11 seconds in the past, tf won't know any more.