Ask Your Question
9

How to remove a TF from a ROS bag? [closed]

asked 2013-03-03 22:13:08 -0600

Benoit Larochelle gravatar image

updated 2013-03-03 22:49:13 -0600

I have a bag that contains a large TF tree where one TF (base_link->virtual_cam) was calculated based on several TFs and parameters. I would like to replay this bag without this generated TF in order to interactively re-generate it as a play the bag.

Hence the question, how do I remove this TF from the bag? Alternatively, can I play the bag without outputting this TF?

Specs: Ubuntu 12.04, Fuerte

edit retag flag offensive reopen merge delete

Closed for the following reason the question is answered, right answer was accepted by Miquel Massot
close date 2015-06-25 02:51:13.094676

4 Answers

Sort by » oldest newest most voted
28

answered 2013-03-03 22:34:31 -0600

Procópio gravatar image

updated 2019-01-30 06:58:18 -0600

You can use the rosbag filter command to generate a new bag file filtering out the topics you do not want. For example, I used this command

rosbag filter input.bag output.bag 'topic == "/camera/image_raw/compressed" or topic == "/scan" or topic == "/timetag" or  topic == "/tf" and m.transforms[0].header.frame_id != "/odom" and m.transforms[0].child_frame_id != "/odom"'

here I want to keep the topics /camera/image_raw/compressed , /scan and /timetag and also the /tf EXCEPT the ones that had /odom either as a frame_id or as a child_frame_id, effectively removing only some /tf messages instead of all of them.

in your case you can use adapt the above example to fit your needs:

rosbag filter input.bag output.bag 'topic == "ALL THE TOPICS YOU WANT TO KEEP" or topic == "/tf" and m.transforms[0].header.frame_id != "/base_link" and m.transforms[0].child_frame_id != "/virtual_cam"'

EDIT: as pointed by @Ben_S, this is a more concise form, with the same results (from this answer):

rosbag filter input.bag output.bag 'topic != "/tf" or topic == "/tf" and m.transforms[0].header.frame_id != "/base_link" and m.transforms[0].child_frame_id != "/virtual_cam"'
edit flag offensive delete link more

Comments

1

This tool seems really useful (it could have its own page with many examples), but I don't see how to remove a particular TF. All TFs were published to /tf.

Benoit Larochelle gravatar imageBenoit Larochelle ( 2013-03-03 22:39:24 -0600 )edit

check my first example code, there you have to play with the last two conditions to fit your case, meaning you remove tf messages where your frame_id is base_link and the child_frame_id is virtual_cam.

Procópio gravatar imageProcópio ( 2013-03-03 22:54:23 -0600 )edit

I think that this alone should work, but I did not try it: rosbag filter input.bag output.bag 'm.transforms[0].child_frame_id != "/virtual_cam"'. I'm working with a recording of 30+ GB in several bags, so the other solution was more practical. I would mark this as correct if I could choose two. :-)

Benoit Larochelle gravatar imageBenoit Larochelle ( 2013-03-04 00:59:48 -0600 )edit
2

You'll need the more complex commands given in the answer as the condition will be evaluated for every message, not only tf. So accessing m.transforms will give you an assertion.

dornhege gravatar imagedornhege ( 2013-03-04 01:04:48 -0600 )edit

This will only work if you are sure that only one transformation is sent in every message (i.e. there is only one element in m.transforms).

hitzg gravatar imagehitzg ( 2014-01-08 05:18:03 -0600 )edit

I know that what it looks like, due to the [0] index, but actually I tested it with many transformations in each message and it works. Have you tried it?

Procópio gravatar imageProcópio ( 2014-01-08 23:48:51 -0600 )edit
1

This should work for up to five transforms being broadcast in a single message, and it can be extended:

https://gist.github.com/ayrton04/6629...

Tom Moore gravatar imageTom Moore ( 2015-05-14 20:11:30 -0600 )edit
1

@Procópio there's a typo in the edited solution. It's 'topic != "tf" or ...' but it should be 'topic != "/tf" or ...'

littlelordy2 gravatar imagelittlelordy2 ( 2019-01-30 06:08:02 -0600 )edit
3

answered 2013-03-04 23:55:06 -0600

Miquel Massot gravatar image

updated 2014-01-08 10:49:52 -0600

You could try a script we did to do exactly the same. It is located in our public repo srv_tools, which is not fully documented yet on ROS. The script you look for is this one.

edit flag offensive delete link more

Comments

Thanks, the script is short and simple! Just the way I like it! ;-)

Benoit Larochelle gravatar imageBenoit Larochelle ( 2013-03-05 00:06:15 -0600 )edit

Works like a charm! The direct link does not work anymore, here's one to the file on github: remove_tf

hitzg gravatar imagehitzg ( 2014-01-08 05:19:56 -0600 )edit

404 on the link for "this one" : remove_tf.py

benabruzzo gravatar imagebenabruzzo ( 2015-03-19 15:48:25 -0600 )edit

A quick search finds what I think is the content here: http://docs.ros.org/hydro/api/bag_too...

tfoote gravatar imagetfoote ( 2015-03-19 16:20:28 -0600 )edit
1

answered 2013-03-03 22:59:44 -0600

Ben_S gravatar image

I dont know of any solution to completely remove only one TF from a bag, but if the transform you want to remove is to a leaf of the tree, you could try remapping it to an unused frame.

Have a look at tf_remap and the description of the node. You could leave all frames unchanged except for the one you want to have removed. But i think this will only work for leafs of the tree. (Or you would have to remap the whole branch of the tree and redefine it while playing back the bag)

edit flag offensive delete link more

Comments

1

you can remove only one specific tf creating a condition in the rosbag filter (check my code example). there I kept all the tf except the ones that had /odom either as the frame_id or the child_frame_id. of course your remap alternative also should do the job.

Procópio gravatar imageProcópio ( 2013-03-03 23:04:04 -0600 )edit
2

Yes, you wrote your comment just while i was typing this answer. In the meantime i also found this answer http://answers.ros.org/question/12285/gmapping-simulation/?answer=18124#post-id-18124 where brian gave the same solution. :) A use case that i also stumbled across some weeks ago.

Ben_S gravatar imageBen_S ( 2013-03-03 23:16:12 -0600 )edit

I tried rosrun tf tf_remap _mappings:='[{old: /ptz, new: /ptz_original}]' and rosrun tf tf_remap _mappings:='[{old: /map/odom/base_link/omnicam/ptz, new: /map/odom/base_link/omnicam/ptz_original}]' but both have no effect. I get no errors, but I get only the old frames, not the new ones.

Benoit Larochelle gravatar imageBenoit Larochelle ( 2013-03-03 23:39:10 -0600 )edit
1

Using your first commandline works for me: rosrun tf tf_remap _mappings:='[{old: /imu_link, new: /imu_link_old}]' Applying the following mappings to incoming tf frame ids {'/imu_link': '/imu_link_old'} Remember to play the bag with rosbag play x.bag /tf:=/tf_old

Ben_S gravatar imageBen_S ( 2013-03-03 23:51:01 -0600 )edit

Yes, you're right! I had not read the part about remapping the tf topic, and was I wondering what kind of black magic would make this work. Now it makes sense. Also to confirm, I have to use the short TF names and not the fully qualified names.

Benoit Larochelle gravatar imageBenoit Larochelle ( 2013-03-04 00:34:17 -0600 )edit
-1

answered 2013-03-03 22:19:18 -0600

davinci gravatar image

You could record it again and record only the topics you need. rosbag record -O subset /turtle1/command_velocity /turtle1/pose http://www.ros.org/wiki/rosbag/Tutorials/Recording%20and%20playing%20back%20data

edit flag offensive delete link more

Comments

I don't see how to remove a particular TF. All TFs were published to /tf.

Benoit Larochelle gravatar imageBenoit Larochelle ( 2013-03-03 22:23:05 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2013-03-03 22:13:08 -0600

Seen: 8,928 times

Last updated: Jan 30