# low frequency transformations

Hi all,

We have a situation where two coordinate frames very rarely change relative to each other and we need the transformation between them. (Rarely: think once in many minutes.)

Since they do change every once in a while this would be a dynamic transform, but logic dictates that in only needs to be published when there is a change, as opposed to regularly. The lookupTransform family allows entering 0 for the timestamp and according to the documentation it should give us the last available transform.

Unfortunately this is not what happens. We get error messages like the ones below.

[ERROR] [1629904648.075921759]: Lookup would require extrapolation at time 1629904648.065789219, but only time 1629904648.013724875 is in the buffer, hen looking up transform from frame [base_link] to frame [soft_odom]
[ERROR] [1629904648.086088862]: Lookup would require extrapolation at time 1629904648.076000771, but only time 1629904648.013724875 is in the buffer, when looking up transform from frame [base_link] to frame [soft_odom]


This is weird, because lookupTransform should give me that transform if I enter a 0 timestamp param.

What gives? Do I need to publish this mostly constant transform in my main loop?

Thanks.

edit retag close merge delete

Sort by » oldest newest most voted

From the comments of @tfoote, @gvdhoorn and @mike-scheutzow I think I understand what is going on.

1. Published transforms don't live forever: the default period when they get purged is 10 seconds.

2. Since my two frames are not directly connected in the tf tree, this comment made by @tfoote and re-emphasized by @gvdhoorn is important: "Using a timestamp of zero asks for the latest available data which is consistent across the full spanning set." which means that my rarely changing transform is chained together with some fast changing ones, hence "latest consistent" did not exist.

Thanks for the help guys.

more

Using a timestamp of zero asks for the latest available data which is consistent across the full spanning set. It will not allow extrapolation into the future like you seem to be expecting. This will be gated by the slowest updating content which seems to be your specific transform.

When you say "logic dictates that it only needs to be published when there is a change" that is making the assumption that I know/expect that the data is going to be the same in the future. However tf does not make that assumption. For some coordinate frames an assumption that it's the same as the past is valid. But for any moving coordinate frame this is an invalid assumption. And we found that allowing people to ask tf to extrapolate into the future actually caused more errors than providing benefits.

In general you personallyl know that this frame should not be changing much, but the system doesn't have that semantic understanding. And you need to keep telling it that the coordinate frame is still in the same place as it used to be. If you think about this as a car. If it's stopped at a stop light odds are that at some point it's going to start driving, so i want to keep checking where it is. If it starts driving and I assume that it's still in place I could easily drive right into it. This is the same for your transform. No data, does not imply that the status quo has not changed. It could easily be that your observer fell asleep or otherwise stopped making the observation.

more

Thanks tfoote.

The funny thing is I don't ask for extrapolation to the future. (Even if I did, "last available" _is_ well defined.) I ask for some timestamp that comes with a message, so is slightly in the past. Of course, it's later than the last available tf, but that is pretty much always the case.

Tf obviously does not know what I do about these frames, i.e. that they don't change, but it does not need to know. Again, the documentation says, passing zero will give you the latest available.

But I do see your point about ROS making this safer by forcing us to update regularly, I just haven't seen it anywhere.

( 2021-08-26 02:17:06 -0500 )edit

This is the important part in @tfoote's answer:

Using a timestamp of zero asks for the latest available data which is consistent across the full spanning set

So if there is any frame between base_link and soft_odom which is not available in the buffer, or not consistent, asking for "the latest" is going to result in extrapolation with the current implementation.

I agree with @gbohus that this nuance should probably be added to the documentation.

( 2021-08-26 02:21:24 -0500 )edit

Thanks @gvdhoorn and @tfoote, the qualification "consistent across the full spanning set" is crucial and makes everything clear now. I'll summarize the discussion into an answer.

( 2021-08-26 04:36:28 -0500 )edit

What you are missing is that the tf_listener in a ros node only buffers /tf messages for a limited time - 5 to 10 seconds is typical. In addition to this issue, some nodes have a concept of "transform tolerance", and assume that messages with a timestamp too far in the past are no longer valid.

In my own code, I publish slow-changing transform data every few seconds. That tends to keep everyone happy.

more

Thanks Mike. I did not realize the tf buffer was limited to such a short period even when there are no new tf's coming.

( 2021-08-26 02:10:28 -0500 )edit

The buffer length is time-based, not on the number of elements in it.

And the 10 seconds @Mike Scheutzow mentions is the default. It can be overridden, but that would have to be done by the developer of the node.

( 2021-08-26 02:14:09 -0500 )edit

Got it, thanks.

( 2021-08-26 02:18:01 -0500 )edit