In this tutorial I’ll show you how to remap a ROS topic.
Remapping a topic means that you’ll change the topic name at run-time. If a node publishes on “topic1”, then you can make it publish on “topic2” instead, without having to change the code of the node.
First things first, let’s understand why.
Why remapping a ROS topic?
Yes, why should we even think about that?
A certain publisher publishes on topicA, and subscribers then subscribe to this topicA. There’s no reason to do any remapping.
But, imagine you’re working with an image processing package you installed with apt or apt-get. The node you run receives images over the /abc_images topic. Problem: in your application, with another package, images are published on the /my_images topic!
To solve this problem, you can remap /my_images to /abc_images with the ROS remap functionality (and of course, be sure that if you remap a topic on another topic, both topics have the same data type!).
Also, remapping topics could be a great way to aggregate several sources (topics) into one. Let’s say you have 5 publishers from 5 sensors (in different namespaces) and you want the data to go on only one topic. What you could do is create an intermediate node which listens to all 5 topics, and when receiving some data, publish it on the global topic. But this is quite an overkill. Instead, you can use ROS remap.
To show you how to remap a ROS topic, I’ll use this simple publisher node.
#!/usr/bin/env python import rospy from std_msgs.msg import String if __name__ == "__main__": rospy.init_node("publisher_node") pub = rospy.Publisher("topic1", String, queue_size=10) rate = rospy.Rate(2) while not rospy.is_shutdown(): pub.publish("Hello") rate.sleep()
The node will publish a message on the topic “topic1” at 2 Hz.
roscore and then start the node with
rosrun my_robot_tutorials publisher.py (replace package and executable names with what you have created).
Then you can see the data published on “topic1”.
$ rostopic echo /topic1 data: "Hello" --- data: "Hello" ---
Now we want to remap the “topic1” to “topic2”. Let’s see how to do that.
Remap the ROS topic
With command line
When you start a node on the terminal with
rosrun, you can pass some arguments to it. You can also ask the node to remap a name to another name (this also applies to parameters and services, not only topics).
$ rosrun my_robot_tutorials publisher.py topic1:=topic2
If we check the topic list on another terminal:
$ rostopic list /rosout /rosout_agg /topic2
“topic1” has disappeared! Instead, we’re seeing a new topic, named “topic2”. Just what we asked for. And we didn’t change anything in the code.
Now you can listen to “topic2” and get the data.
$ rostopic echo /topic2 data: "Hello" --- data: "Hello" ---
In a launch file
Of course, starting each node from the terminal is not scalable. As your application grows, you’ll use launch files to start all nodes and parameters in your application. This is also a good place to set your topic redirection rules.
<remap from="" to="" /> tag to remap a topic.
<launch> <remap from="topic1" to="topic2" /> <node name="publisher_node" pkg="my_robot_tutorials" type="publisher.py" /> </launch>
If you run the launch file –
roslaunch my_robot_tutorials remap_test.launch – you’ll have the same result as with the rosrun argument. The “topic1” won’t be here anymore, instead you’ll get the messages from “topic2”.
Important note: the line order in launch files for remapping is very important.
If you write this instead:
<launch> <node name="publisher_node" pkg="my_robot_tutorials" type="publisher.py" /> <remap from="topic1" to="topic2" /> </launch>
The remapping on “topic1” won’t work. When you use the
<remap from="" to="" /> tag, it will remap any topic after the tag. Everything before this tag won’t be taken into account.
If you start this launch file you’ll still see “topic1”, and “topic2” won’t be here.
Of course you can also remap topics from/to different namespaces.
If you run
rosrun my_robot_tutorials publisher.py topic1:=/ns1/another_namespace/topic2, or use
<remap from="topic1" to="/ns1/another_namespace/topic2" /> in your launch file, then “topic1” will be remapped to “/ns1/another_namespace/topic2”.
This can be very handy if you have several pieces of hardware (multiple robots, cameras, sensors, …) in different namespaces, and want to aggregate some data. For example, you could remap “/robot1/camera2/my_images” and “/robot4/camera3/my_images” to “/face_recognition/my_images”.
Remap a topic from a ROS bag
It’s also possible to remap a topic played by a ROS bag. Let’s see this with an example.
First, we record data from our initial node which is publishing on “topic1”.
$ rosbag record -O data.bag topic1 [ INFO] [1572532320.536117633]: Subscribing to topic1 [ INFO] [1572532320.540384442]: Recording to data.bag.
Then, if we replay the bag with
rosbag play data.bag, it will send messages to “topic1” again. Let’s replay it on “topic2” instead.
$ rosbag play data.bag topic1:=topic2
Then on another terminal, check that you see “topic2” instead of “topic1” with
As simple as that!
ROS topic remap – Conclusion
Remapping a ROS topic can be very handy when you don’t have full control over which node is publishing on what, and which node is subscribing from what. You can also aggregate data from various nodes into a common topic.
As you could see during this tutorial, it’s really easy to remap a topic. If you pay attention to the following points you should be fine:
- Make sure you use the
<remap from="" to="" />tag in the right order.
- Know your namespaces (global, relative, …).
- Make sure both topics (if you’re remapping on an existing topic with already existing subscribers) have the same data type.