Nomenclature of tf_echo and tf_listener

I did an issue in ROS documentation 2 weeks ago, but I got no answer. Yesterday, in the ROS Meetup Barcelona, I commented it with my colleagues and I did not get any consensus. It is a question of nomenclature and probably the ROS documentation is written by people from different areas (Vision, classic robotics, etc.) that have a different background.

Let me put this question here, and maybe we can clarify the concept.

The tool tf2_echo help says:

tf2_echo source_frame target_frame [echo_rate]

This will echo the transform from the coordinate frame of the source_frame
to the coordinate frame of the target_frame.
Note: This is the transform to get data from target_frame into the source_frame.

For me is clear, if I have a frame, for instance, “grasp_01”, and another frame “base”, and I execute:

ros2 run tf2_ros tf2_echo base grasp_01

I would obtain the transformation that comes from base to grasp_01. Easily, I can see the distance between the origin of “base” to the origin of “grasp_01” expressed in the “base” frame.

But, in the documentation, for example the turtle, the sentence says:

Let’s look at the transform of the turtle2 frame with respect to turtle1 frame which is equivalent to:
ros2 run tf2_ros tf2_echo turtle2 turtle1

To me is the opposite, I got the transformation from turtle2 to turtle1, that is the same the frame turtle1 w.r.t. turtle2, not the opposite as claims the documentation.

Also, I got another issue, the tf_buffer class has the method

lookupTransform (const std::string &target_frame, const std::string &source_frame, const tf2::TimePoint &time, const tf2::Duration timeout) const override

where you gets the transform between two frames by frame ID. With:

  • target_frame = The frame to which data should be transformed
  • source_frame = The frame where the data originated
    …

If I create a listener in C++, and I call the function with:

tfs = tf_buffer_->lookupTransform(“base”, “grasp_01”, tf2::TimePointZero);

I would obtain the same value as using tf2_echo.

It is curious, because I asked several people and many times I got the answer: “First, I try it with tfA and after tfB, but if I don’t get the data I want, I change to tfB and later tfA”.

So, please, could you explain what should I understand as source_frame, target_frame in the ROS context?

I remembered a Q&A on ROS Answers about this:

Quote from @tfoote’s answer (from 2014):

The lookup API is named with respect to transforming data from the source frame into the target frame.

When referring to transform between coordinate frames (transforming the frames, it is the inverse of the transform of data between the two frames)

Depending on the documentation if you’re referring to the transform value for the data, or the transform value of the coordinate frames you get the inverse value.

and the tf_echo vs lookupTransform(..) discrepancy:

Seeing as he posted the answer to the first one, and there were some follow-up comments/questions on that one, perhaps @tfoote can clarify things some more here?

1 Like

Hi @lepalom,

I’m sorry we couldn’t get to your issue right away. Things are quite busy as it is release season.

I agree that the CLI documentation could be better, and it times it is downright confusing. I actually proposed using our Google Summer of Docs student this year to step through the ROS 2 CLI and improve the documentation and include examples. Since some word choices can be ambiguous, or unclear for those who speak English as a second language, I would really like to see more concrete examples in the CLI docs and in the API documentation. I am also sure some of our documentation writers have even gotten things wrong in a few spots, and including worked examples usually leaves little room for error.

One other thing to consider is convention; we’re really reticent to change a CLI command’s order of operation, or the order of API call, once it is out in the world. Such changes can impact scripts written by downstream users. What we should be concerned with is that the documentation makes the convention crystal clear.

Honestly, I don’t want to lead you astray, and I am not going to comment on the correct nomenclature for these commands until I run each and every command for myself and confirm how they work. What I would like to suggest is that once we converge on a consensus, that the results, and a worked example of those results, get included in the docs for all the relevant resources (the API docs, the CLI help file, and docs.ros.org). In particular, I would like to see more contributions going towards the ROS 2 CLI. Users’s shouldn’t need to leave the terminal to find this kind of information.

Hi @Katherine_Scott . Nothing to apologize, I understand the situation.

Please, don’t take my issue as a complaint of the documentation. Obviously, the documentation can always be better and it is a constant WIP.

I do not pretend to change the CLI command’s order of operation, neither the order of API call. On the contrary, please don’t do it. I would like to just make a note about the nomenclature and what is referring exactly to.

Also, discussing it with my colleagues, we found that depends on your background, you see the nomenclature of the transformations in a different form. Think, that coming from the same area of robotics), the Craig’s book put the indexes and supra indexes of the transforms in a different place than the Siciliano’s book.

My point was (and it seems that some people also) to define in a clear way of what do you refer of source, target, and so on.

thanks for the reply. It is a good historical resume of the topic. It seems that it is an old topic.

Hey @lepalom I’ve been working on increasing documentation within tf2, specifically with CLI tools in this pull request. If you could either build the documentation with these instructions or checkout the cli_tools.rst file, it would be nice to make sure the language is easily understandable that way it can resolve things like this.

If you follow the given geometry_tutorials it might a bit more visibile, from what I understand the target frame (the second argument) changes with respect to the source frame (the first argument). So, during the example as you drive around turtle1, turtle2 will follow turtle1 around. With tf2_echo, the translation x value will continue to be negative, but getting a smaller absolute value as turtle2 gets close to turtle1, that is because turtle2 will pass turtle1, which would allow positive movement. An easier way to look at it would be localization with some flying robot (our source) and a flag (our frame). Say that the flag is 10ft tall and the robot starts on the ground, then the starting translation y value that tf2_echo puts out is going to be positive, since the flag (with respect to the robot) is above the robot. As the robot begins to float upwards, that translation y value will decrease towards 0, since the height of the flying robot nears the height of the flag. Finally when the flying robot floats to say 11 ft, the flag is respectively lower than the robot so, the translation would be negative. I hope these examples didn’t make it more confusing.

Also this happens:

If I create a listener in C++, and I call the function with:
tfs = tf_buffer_->lookupTransform(“base”, “grasp_01”, tf2::TimePointZero);
I would obtain the same value as using tf2_echo.

Since tf2_echo calls lookup_transform here

There are also multiple issues on Github about this: