5

I have a rosbag in which a /tf topic is recorded.

I need to remap all tf frames in that bag which refer to the frame named /world to refer to a new frame named /vision. I tried the following but it's unfortunately not working:

rosrun tf tf_remap _mappings:='[{old: /world, new: /vision}]'

Am I missing something?

I have also tried to do it from a launch file:

    <launch>
      <node pkg="tf" type="tf_remap" name="tf_remapper" output="screen">
        <rosparam param="mappings">
          - {old: "/world",
             new: "/vision"}
        </rosparam>
      </node>
    </launch>

Same result...

I found people saying that, in addition to running the tf_remap node, rosbag should be run as follows:

rosbag play x.bag /tf:=/tf_old

Also did that... still not working.

The tf_frames are still referring to /world rather than /vision.

Any help would be highly appreciated!


Edit

This is to clarify more what I am trying to achieve:

What I want is to remap all the frames recorded in the bag and referring to /world, and make them refer to /vision instead. There should be no /world frame in the remapped output of the bag. Somewhere else in the code, I will define the frame named /world and its relation to /vision.

davidmesalpz
  • 133
  • 6
Beginner
  • 325
  • 5
  • 16

2 Answers2

0

You could edit the contents of the bag file using the rosbag python/c++ API. Here is an example with python that would just replace any instance of /world with /vision in your bag's recorded /tf msgs.

import rosbag
from copy import deepcopy
import tf

bagInName = '___.bag'
bagIn = rosbag.Bag(bagInName)
bagOutName = '___fixed.bag'
bagOut = rosbag.Bag(bagOutName,'w')
with bagOut as outbag:
    for topic, msg, t in bagIn.read_messages():
        if topic == '/tf':
            new_msg = deepcopy(msg)
            for i,m in enumerate(msg.transforms): # go through each frame->frame tf within the msg.transforms
                if m.header.frame_id == "/world":
                    m.header.frame_id = "/vision"
                    new_msg.transforms[i] = m
                if m.child_frame_id == "/world":
                    m.child_frame_id = "/vision"
                    new_msg.transforms[i] = m

            outbag.write(topic, new_msg, t)
        else:
            outbag.write(topic, msg, t)

bagIn.close()
bagOut.close()
0

Your tf_remap command seems correct. However, you're one step away from the solution: Briefly described, tf_remap listens to a tf topic, makes your desired changes, and then publishes the transformation to a new tf topic. These topics default to tf_oldand/tf`, respectively.

So, you first start your tf_remap node as you did in your question.

rosrun tf tf_remap _mappings:='[{old: /world, new: /vision}]'

Then, you start playing your rosbag, remapping the /tf topic to /tf_old

rosbag play ... /tf:=/tf_old

Now, rosbag play publishes the messages via the /tf_old topic. The tf_remap node subscribes to the /tf_old topic and publishes the altered transformations (with the replaced frames) on the /tf topic.

J.P.S.
  • 485
  • 4
  • 11