'How to use tf_remap?
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.
Solution 1:[1]
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.
Solution 2:[2]
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()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |
