How to Load a New Map for Multi-Floor Navigation Using ROS 2

1-hospital-world

In this tutorial, I will show you how to load a new map at runtime using the command line. We will work with ROS 2. The use case for this tutorial is a robot that needs to navigate between floors of a multi-floor building.

Update: There is a new way to load a new map for navigation at runtime. You can use the changeMap() method provided by the Nav 2 Simple Commander API.

Prerequisites

You can find the files for this post here on my Google Drive.

Directions

Suppose you have a room service robot that is running on ROS 2. The robot is moving around the 5th floor of a hospital.

A hospital patient on the 5th floor has finished his meal and summons the robot to his room so the robot can carry the dirty dishes down to the kitchen of the hotel’s cafe. Suppose the hotel cafe is located on the 2nd floor of the building.

We want our robot to navigate from the 5th floor of the hospital –> elevator –> hospital cafe (2nd floor).

The process for performing multi-floor navigation might look something like this:

  1. Navigate to the Patient’s Room
  2. Pick up the Dirty Dishes
  3. Navigate to the Elevator Door
  4. Press the Down Button
  5. Wait for the Elevator to Open
  6. Enter the Elevator
  7. Press the Elevator Button for the 2nd Floor
  8. Wait for the Elevator to Reach the 2nd Floor
  9. Exit the Elevator
  10. Load a New Map of the 2nd Floor Hospital Cafe

Let’s take a look at how to do step 11.

Load the hospital world by opening a new terminal window and typing:

cd ~/dev_ws/
ros2 launch two_wheeled_robot hospital_world_v1.launch.py

Here is what the 5th floor of the hospital looks like:

1-hospital-world-2

Now, let’s assume the robot has done steps 1-10 in the list I posted earlier. It is now on the 2nd floor where the cafe is.

Let’s load a map of the cafe. We need to make a ROS 2 service call to the LoadMap service. ROS 2 services work well when you want a request-response interaction.

Let’s see what services we have.

ros2 service list

We could also have used the following command to see the type of each service.

ros2 service list -t

We can see that we have a service called /map_server/load_map. Let’s see the service type.

ros2 service type /map_server/load_map

The output is:

nav2_msgs/srv/LoadMap

Let’s see the structure of the input arguments for this service.

ros2 interface show nav2_msgs/srv/LoadMap

You will see the variable string map_url. Since this is above the —, this piece is the request structure. Everything below the —, is the response structure.

For a ros2 service call, everything above the — are the arguments needed to call the service.

Now we need to call the /map_server/load_map service. The syntax is as follows:

ros2 service call <service_name> <service_type> <arguments>

All of this below is a single command.

ros2 service call /map_server/load_map nav2_msgs/srv/LoadMap "{map_url: /home/focalfossa/dev_ws/src/two_wheeled_robot/maps/cafe_world/cafe_world.yaml}"

…where cafe_world.yaml is the new map file. Notice you need to provide the full path to the map file.

Here is what RViz looks like after running the command.

2-what-rviz-looks-like

You can go in RViz and uncheck the local costmap.

3-uncheck

The outline of the reception desk is due to the fact that the robot is still in the hospital world inside Gazebo, so its global costmap is updating accordingly.

4-new-map

Below is what the cafe world actually looks like in Gazebo. You will see that the new map above comes from this cafe world.

5-cafe-world

That’s how you load a new map at runtime using ROS 2. That’s it. Keep building!