ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

How to get list of all tf frames programatically?

asked 2020-03-30 04:15:04 -0600

rfn123 gravatar image

updated 2020-03-30 05:34:00 -0600

Hi all,

I have a question on how to obtain tf frames in a ros node (preferrably Python). I am aware of the method tf2_ros.Buffer.lookup_transform(), however, one has to specify source and target frame for that.

Lets say I have an array of known markers, but only a subset of them are detected by the camera. I want to know which of these markers are detected by looking at the existing tf frames. Is there a more elegant way to do so instead of looping over all possible markers and try to lookup the transform in a try catch block?

Thanks in advance!

P.S I am using kinetic on Ubuntu 16.04


EDIT:
In the tutorial TfUsingPython I found the method allFramesAsString() but it seems to use tf, not tf2. would there be an equivalence in tf2? Or is it generally a bad practice to mix the use of tf and tf2?

edit retag flag offensive close merge delete

4 Answers

Sort by ยป oldest newest most voted
2

answered 2020-03-30 05:38:26 -0600

gvdhoorn gravatar image

It seems #q261460 is at least a partial duplicate of your question.

In the tutorial TfUsingPython I found the method allFramesAsString() but it seems to use tf, not tf2. would there be an equivalence in tf2? Or is it generally a bad practice to mix the use of tf and tf2?

TF has been implemented on-top of TF2 for quite some time now, so you cannot really "mix" them: it would all be using TF2 in the end.

As to the method you found: there is tf2::BufferCore::allFramesAsYAML(double current_time) const in TF2 (and allFramesAsStringNoLock() is available as well).

The Python API of TF2 is essentially a mirror of the C++ API, so you should be able to call that from Python as well (I have not verified this).

edit flag offensive delete link more

Comments

Since the Python API is rather poorly documented, here is sth if someone has the same problem as me: After some further research I found some example usage of the Python API here: examples_tf2_py. Probably this still does not contain all methods of the C++ API, but imo it's a good start.

rfn123 gravatar image rfn123  ( 2020-03-30 07:30:21 -0600 )edit
2

answered 2020-03-30 07:50:44 -0600

rfn123 gravatar image

I ended up searching alternative to native tf library functions to solve my problem. The reason was that after getting allFramesAsYAML() (or in Python tfBuffer_ros.all_frames_as_yaml()) to work i found out that it will return _all_ frames that have been in the tf buffer, regardless of whether the frame is in the current tf topic or not. The output was:

marker1: 
  parent: 'camera'
  broadcaster: '/marker_tracker'
  rate: 30.401
  most_recent_transform: 1585572193.003
  oldest_transform: 1585572190.503
  buffer_length: 2.500
marker2: 
  parent: 'camera'
  broadcaster: '/marker_tracker'
  rate: 30.457
  most_recent_transform: 1585572192.703
  oldest_transform: 1585572190.503
  buffer_length: 2.200
marker3: 
  parent: 'camera'
  broadcaster: '/marker_tracker'
  rate: 27.709
  most_recent_transform: 1585572195.538
  oldest_transform: 1585572191.568
  buffer_length: 3.970

I occluded marker2 after a while, and it still appeared in the output. The only difference is that "most_recent_transform" stopped updating.

edit flag offensive delete link more

Comments

The only difference is that "most_recent_transform" stopped updating.

doesn't that align with what you were trying to achieve? You wrote:

I want to know which of these markers are detected by looking at the existing tf frames

Thing is: TF frames "don't exist", so seeing whether they "still exist" is not really something you can do.

Even TF itself (ie: the internals of the provided libraries) will look at most_recent_transform to determine whether a transform is still up-to-date and relevant.

In your case you could see how long ago the transform was updated and determine -- based on some threshold -- whether the last detected pose for a marker is "too old".

gvdhoorn gravatar image gvdhoorn  ( 2020-03-30 07:54:25 -0600 )edit

You are right, by looking at the update time I can filter the tfs. I was just rather looking for sth. simpler (e.g. boolean) that shows if a certain tf frame is updated or not, i.e. "existing", but I was not aware that the internal libraries use the mechanics of update time. Thanks for clarifying that!

rfn123 gravatar image rfn123  ( 2020-03-30 13:32:48 -0600 )edit

I was just rather looking for sth. simpler (e.g. boolean) that shows if a certain tf frame is updated or not

well, think about it: what would it mean for a frame to "be updated or not"? How would TF determine this to set that boolean true or false?

Probably be comparing the time at which a frame was last updated to some sort of maximum allowable age .. :)

gvdhoorn gravatar image gvdhoorn  ( 2020-03-30 14:38:27 -0600 )edit
1

answered 2022-07-06 22:32:21 -0600

lindzey gravatar image

updated 2022-07-06 22:32:44 -0600

Building off the other answers, here's a snippet of runnable code that I wound up with:

import rospy
import tf2_ros
import time
import yaml

rospy.init_node('ipython')

tf_buffer = tf2_ros.Buffer()
tf_listener = tf2_ros.TransformListener(tf_buffer)
time.sleep(5.0)

frames_dict = yaml.safe_load(tf_buffer.all_frames_as_yaml())
frames_list = list(frames_dict.keys())

(Tested on Ubuntu 20.04, running noetic)

edit flag offensive delete link more

Comments

I tried porting your snippet into ROS2 but haven't had success so far. Spun off a new question https://robotics.stackexchange.com/qu... FYI.

130s gravatar image 130s  ( 2023-05-04 03:57:53 -0600 )edit
0

answered 2023-05-04 03:51:37 -0600

130s gravatar image

updated 2023-05-04 11:30:53 -0600

CLI though, this returns the list of frames and some associated data (the Service type is what rqt_tf_tree uses. Related #q349175). Since it's ROS2 Service you should be able to write in Python or C++ in standard way (I just haven't had time to do that yet).

ros2 service call /tf2_frames tf2_msgs/srv/FrameGraph

In my case I got:

response:                                                             
tf2_msgs.srv.FrameGraph_Response(frame_yaml="breakbeam_0_frame: \n  parent: 'world'\n  broadcaster: 'default_authority'\n  rate: 10000.000\n  most_recent_transform: 0.000000\n  oldest_transform: 0.000000\n  buffer_length: 0.000\nadvanced_logical_camera_0_frame: \n  parent: 'world'\n  broadcaster: 'default_authority'\n  ...

Btw I also tried in Python tf_buffer.all_frames_as_yaml() way, but no success. Opened a separate question robotics.stackexchange.com#24731.


Update. Hm, the output of ROS2 service cmd above looks the same as what ros2 run tf2_tools view_frames, which is introduced in the very beginning of tf tutorial, returns, so nothing new to anyone :/

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2020-03-30 04:15:04 -0600

Seen: 7,723 times

Last updated: May 04 '23