This shouldn’t be rocket science, but up until just this moment I never comprehended the <remap> tag.
However, due to a problem I was having I had the opportunity to track it down, in action, and also to see the result.
First, this is documented, but the documentation never made sense to me: http://wiki.ros.org/roslaunch/XML/remap
or for more confusion: http://wiki.ros.org/Remapping%20Arguments
So here is my explanation to myself:
If you look inside of my ArloBot propellerbot_node.py you will see that it listens to the topic cmd_vel:
rospy.Subscriber("cmd_vel", Twist, self._handle_velocity_command)
However, if you start up my ArloBot:
roslaunch arlobot_bringup minimal.launch --screen
and start driving it around with TeleOp:
roslaunch arlobot_teleop keyboard_teleop.launch
You will see NO cmd_vel topic!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
chrisl8@ArloBot (master *) scripts $ rostopic list /arlo_status /arlobot/pirState /arlobot_safety/safetyStatus /arlobot_usbrelay/usbRelayStatus /cmd_vel_mux/active /cmd_vel_mux/input/navi /cmd_vel_mux/input/safety_controller /cmd_vel_mux/input/teleop /cmd_vel_mux/input/web /cmd_vel_mux/parameter_descriptions /cmd_vel_mux/parameter_updates /infrared_scan /joint_states /mobile_base/commands/velocity /mobile_base_nodelet_manager/bond /odom /rosout /rosout_agg /serial /tf /ultrasonic_scan |
In ROS there is so much going on that it is easy to chalk things up to “magic”, but when you actually write the Python code to listen to cmd_vel, and there is no cmd_vel topic, no amount of “magic” suffices. Obviously something is wrong!
The solution is <remap>, and the lesson is that this tag works on an individual node at the time we run it!
We called propeller_node.py with minimal.launch, and it includes the file mobile_base.launch.xml:
<include file=”$(find arlobot_bringup)/launch/mobile_base.launch.xml” />
and inside of this file is the “magic”:
1 2 3 4 5 6 7 8 9 |
<node pkg="arlobot_bringup" type="propellerbot_node.py" name="arlobot" respawn="true" args="--respawnable"> <param name="bonus" value="false" /> <param name="update_rate" value="30.0" /> <remap from="cmd_vel" to="mobile_base/commands/velocity" /> <remap from="arlobot/sensor_state" to="mobile_base/sensors/core" /> <remap from="imu/data" to="mobile_base/sensors/imu_data" /> <remap from="imu/raw" to="mobile_base/sensors/imu_data_raw" /> <rosparam file="$(find arlobot_bringup)/param/arlobot.yaml" command="load" /> </node> |
The exciting line is this one:
<remap from="cmd_vel" to="mobile_base/commands/velocity" />
This says that when the node we are calling (propellerbot_node.py) tries to subscribe to “cmd_vel” give it “mobile_base/commands/velocity” instead!
Mystery solved, because that topic does exist!
Furthermore, if you run or create a node that sends data on the “cmd_vel” topic, nobody is going to listen to it!
I don’t know why these remaps were so confusing to me before. Probably because a lot of them are only used in the TurtleBot code that I borrowed from. Only when I had a clear situation where a third party node was talking on cmd_vel and nothing was happening did I realize that there IS NO cmd_vel topic in my normal setup, and yet it worked.
Question 2:
If I have a launch file that I want to start, and I know the node it starts will broadcast to a topic I don’t listen to, either directly or due to remapping, what can I do about this?
Based on this now less confusing documentation of argument remapping: http://wiki.ros.org/Remapping%20Arguments
You can also use remap when you runĀ a node directly, so that this:
(This is based on a command from the great ROS by Example INDIGO book that you really should buy!)
rosrun rbx1_nav calibrate_linear.py
becomes:
rosrun rbx1_nav calibrate_linear.py cmd_vel:=mobile_base/commands/velocity
Because I know from experience (run the command and then run “rostopic list” to get that same experience) that this node broadcasts on “cmd_vel”, and from my previous discussion based on launch files and the output of “rostopic list” that my robot’s controller node listens on mobile_base/sensors/core