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:
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!
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”:
<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.
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
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