ROS navigation tutorial ros

This tutorial shows how to use the ROS navigation stack to build a map and make your robot navigate in MORSE.


All the scripts, nodes and launch files mentioned in this tutorial are available in $MORSE_PREFIX/share/morse/examples/tutorials/ros_navigation. If you wish to directly reuse the ROS nodes, do not forget to add this path to your $ROS_PACKAGE_PATH.


You should be familiar with the basic usage of ROS and how to use TF and the ROS navigation stack. You should also know about launchfiles and topic remapping as well as the robot state publisher. Also experience with RVIZ is also useful. Tutorials on all of those topics can be found on

We also assume you know how to use the MORSE Builder API to equip your robot with components. If not, please follow first the ROS and MORSE tutorial.

Environment setup

You need to have a working installation of ROS and also have the python3-compatible stacks for MORSE-ROS installed. You can find information about this in the installation notes


We base the tutorial on ROS Indigo. The tutorial has also been successfully tested with previous ROS versions down to ROS Fuerte. You may however need to adapt some of the instructions.

If you are running Ubuntu, you can simply install the packages ros-indigo-pr2-navigation, ros-indigo-pr2-common, ros-indigo-control-msgs and ros-indigo-viz. They will install all required dependencies.

You also need MORSE installed with ROS support: check that the BUILD_ROS_SUPPORT CMake option is enabled when building MORSE.

Bringing up your robot in RVIZ

Our first step is to get a robot to show up in RVIZ. In this tutorial, we will use the PR2 robot, but any robot (with an URDF file to describe it to RVIZ) would do.

Let’s create a first simple scenario script: a PR2 in a kitchen environment, a keyboard actuator to move it around, and an Odometry sensor to get some odometry feedback. First:

$ morse create nav_tutorial
$ cd nav_tutorial

And edit

from morse.builder import *

# A 'naked' PR2 robot to the scene
robot = BarePR2()
robot.translate(x=2.5, y=3.2, z=0.0)

# An odometry sensor to get odometry information
odometry = Odometry()
odometry.add_interface('ros', topic="/odom")

# Keyboard control
keyboard = Keyboard()

# Set the environment
env = Environment('tum_kitchen/tum_kitchen')
env.set_camera_rotation([1.0470, 0, 0.7854])


odometry.add_interface('ros', topic='/odom') tells MORSE to stream the odometry information on the /odom topic, using the default serialization method for the pair (odometry, ROS), as defined in Builder If you do not specify a topic name, one is created automatically (here, it would be /robot/odometry).

If you like, you can also add a odometry.add_interface('socket') to add another output on a socket.

Run it by first starting a ROS core (roscore) and then morse run nav_tutorial.


You can move the camera around with WASD + RF (up-down). To rotate it, press Ctrl while moving the mouse.

The odometry sensor automatically publishes the TF transformation between the /odom and /base_footprint frames, so you actually do not need anything more to display than the /base_footprint of your robot in RVIZ. Launch RVIZ (rosrun rviz rviz), select /odom as Fixed frame, and add a TF display. You should see the frames /odom and /base_footprint connected together, on a black background. Move the robot within MORSE with the arrow keys: the transform should update accordingly in RVIZ.

We will soon build and add a map, but in the meantime, we want to display the full robot TF tree (it is required by the ROS localization stack to know where the laser scanner is).

To do that, we need to publish the TF tree with the robot_state_publisher module. This module takes the robot joint state (exported by the armature_pose sensors of the arms, head and torso in our case) and the URDF file of our robot as input.

First complete the script by replacing the BarePR2 by the BasePR2:

from morse.builder import *

# A PR2 robot to the scene
robot = BasePR2()
robot.translate(x=2.5, y=3.2, z=0.0)



The BasePR2 PR2 model has predefined actuators and sensors for the arms, torso and head. These are needed to export the full robot joint state. Check the PR2 Builder script source to know how it is done, or read the PR2 documentation to know which other PR2 models are available.

Then, to make our lives easier, we create a new ROS package and a launch file that will start the robot_state_publisher for us:

$ mkdir morse_2dnav && cd morse_2dnav
$ touch manifest.xml
$ touch nav.launch

Edit manifest.xml and copy-paste the code below:

    <description brief="morse_2dnav">
        morse_2dnav is a sample ROS node used to demo
        2D planar navigation in the MORSE simulator.
    <author>MORSE Team</author>
    <review status="unreviewed" notes=""/>
    <depend package="move_base"/>
    <depend package="map_server"/>
    <depend package="robot_state_publisher"/>

Edit nav.launch and copy-paste this code:

    <param name="robot_description" command="cat $(find morse_2dnav)/pr2.urdf"/>
    <node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />

Lastly, build the pr2.urdf file in your node by running:

rosrun xacro `rospack find pr2_description`/robots/pr2.urdf.xacro > pr2.urdf

Restart the MORSE simulation and launch your new ROS node with roslaunch morse_2dnav nav.launch.

In RVIZ, set the Fixed frame to /odom. You should now see the full PR2 TF tree.



You can display the robot geometry by adding a Robot Model display in RVIZ.

Creating a map

The ROS navigation stacks include the powerful gmapping module that allows us to easily build 2D maps using SLAM techniques.

To do so, we first need to add a laser scanner to our PR2 model.

Edit to add a SICK sensor, configured to approximate the PR2 Hokuyo laser scanners:

scan = Hokuyo()
scan.translate(x=0.275, z=0.252)
robot.append(scan) = False) = 30.0) = 1.0) = 180.0)

scan.add_interface('ros', topic='/base_scan')

We can now build a first map of our environment. Restart the simulation with morse run nav_tutorial.

Start your launch file: roslaunch morse_2dnav nav.launch.

You can now run the ROS GMapping stack:

rosrun gmapping slam_gmapping scan:=/base_scan _odom_frame:=/odom

Move around the robot in the simulation using the keyboard to fill the map (displayed in RVIZ).


When you are satisfied, save it with rosrun map_server map_saver.

This will create a pair map.pgm and map.yaml in your home directory that should be similar to the one provided with the tutorial in $MORSE_PREFIX/share/morse/examples/tutorials/ros_navigation/maps/

Copy the map you have just recorded in your morse_2dnav node and add the following line to your launch file to start a map server with your map:

<node name="map_server" pkg="map_server" type="map_server" args="$(find morse_2dnav)/map.yaml"/>

You do not need the gmapping node anymore; you can kill it.

Using ROS localization

The ROS navigation stacks provide a Monte-Carlo based module for localisation estimation called amcl.

We can use it to localize our robot in the map.

Restart the simulation with the map server enabled.

Start the AMCL estimator, passing the laser scans topic as paramter:

$ rosrun amcl amcl scan:=/base_scan

Now, open RVIZ. Set the Fixed Frame to /map, enable the laser scan display (topic name is /base_scan) to see the simulated laser scans and set an initial pose estimate (ie an estimate of the pose of the robot in MORSE) by clicking on the 2D Pose Estimate button in RVIZ interface.

Now, move the robot in the simulator with the arrow keys. You should see the localization of the robot in RVIZ improving with time and displacements.