How to Create a Simulated Mobile Robot in ROS 2 Using URDF

In this tutorial, I will show you how to create a simulated mobile robot using the Universal Robot Description Format (URDF), the standard ROS format for robot modeling. This tutorial is the first tutorial in my Ultimate Guide to the ROS 2 Navigation Stack (also known as Nav2). Here is what you will create:

2-basic-mobile-robot-rviz

Roboticists like to simulate robots before building them in order to test out different algorithms. You can imagine the cost of making mistakes with a physical robot can be high (e.g. crashing a mobile robot into a wall at high speed means lost money).

You can get the entire code for this project here.

Let’s get started!

Prerequisites

  • ROS 2 Foxy Fitzroy installed on Ubuntu Linux 20.04
    • If you are using another ROS 2 distribution, you will need to replace ‘foxy’ with the name of your distribution everywhere I mention ‘foxy’ in this tutorial. 
    • I highly recommend you get the newest version of ROS 2. If you are using a newer version of ROS 2, you can still follow all the steps in this tutorial. Everything will work just fine.
  • You have already created a ROS 2 workspace. The name of our workspace is “dev_ws”, which stands for “development workspace.” 

What is URDF?

A URDF (Universal Robot Description Format) file is an XML file that describes what a robot should look like in real life. It contains the complete physical description of the robot. Building the body of the robot is the first step when getting started with Nav2.

The body of a robot consists of two components:

  1. Links
  2. Joints

Links are the rigid pieces of a robot. They are the “bones”. 

Links are connected to each other by joints. Joints are the pieces of the robot that move, enabling motion between connected links.

Consider the human arm below as an example. The shoulder, elbow, and wrist are joints. The upper arm, forearm and palm of the hand are links.

link_joint

For a robotic arm, links and joints look like this.

link-joint-robotic-arm

You can see that a robotic arm is made of rigid pieces (links) and non-rigid pieces (joints). Servo motors at the joints cause the links of a robotic arm to move.

For a mobile robot with LIDAR, links and joints look like this:

mobile-robot-joints-links

The wheel joints are revolute joints. Revolute joints cause rotational motion. The wheel joints in the photo connect the wheel link to the base link.

Fixed joints have no motion at all. You can see that the LIDAR is connected to the base of the robot via a fixed joint (i.e. this could be a simple screw that connects the LIDAR to the base of the robot).

You can also have prismatic joints. The SCARA robot in this post has a prismatic joint. Prismatic joints cause linear motion between links (as opposed to rotational motion).

Install the ROS 2 Navigation Stack (Nav2)

Now that you know what a URDF file is, let’s get to work.

Right now, I want you to complete this tutorial to install the ROS 2 Navigation Stack. Once you complete that tutorial, return to this page.

Don’t worry, setting up the ROS 2 Navigation Stack doesn’t take very long. Make sure to complete the entire tutorial before you come back here.

Install Important ROS 2 Packages

Now we need to install some important ROS 2 packages that we will use in this tutorial. Open a new terminal window, and type the following commands, one right after the other.

sudo apt install ros-foxy-joint-state-publisher-gui
sudo apt install ros-foxy-xacro

The format of the commands above is:

sudo apt install ros-<ros2-distro>-joint-state-publisher-gui
sudo apt install ros-<ros2-distro>-xacro

You will need to replace <ros2-distro> with the ROS 2 distribution you are using. In this case, I am using ROS 2 Foxy Fitzroy, which is ‘foxy’ for short.

Create a ROS 2 Package

Let’s create a ROS 2 package inside our workspace.

In a new terminal window, move to the src (source) folder of your workspace.

cd ~/dev_ws/src

Now create the package using the following command.

ros2 pkg create --build-type ament_cmake basic_mobile_robot

Create Extra Folders

Move inside the package.

cd ~/dev_ws/src/basic_mobile_robot

Create some extra folders with the following names.

mkdir config launch maps meshes models params rviz worlds

Type the following command to verify the folders were created.

dir
1-create-folders-with-names

Now build the package by typing the following command:

cd ~/dev_ws
colcon build

Let’s add a script to our bashrc file which enables us to use the following command to move to the package from any directory inside our terminal window.

colcon_cd basic_mobile_robot

Where ‘cd’ means “change directory”.

Note that in ROS 1, we typed roscd to change directories. In ROS 2, we use the colcon_cd command instead of roscd.

Open a terminal window, and type the following commands, one right after the other:

echo "source /usr/share/colcon_cd/function/colcon_cd.sh" >> ~/.bashrc
echo "export _colcon_cd_root=~/dev_ws" >> ~/.bashrc

Now open a new terminal window.

To go directly to the basic_mobile_robot ROS 2 package, type:

colcon_cd basic_mobile_robot

This command above will get you straight to the basic_mobile_robot package from within any directory in your Linux system. The format is:

colcon_cd [ROS 2 package name]

Create the URDF File

In this section, we will build our mobile robot step-by-step. Our robot will be defined in a Universal Robot Descriptor File (URDF), the XML file that represents a robot model.

Open a new terminal window, and type:

colcon_cd basic_mobile_robot
cd models

Make sure you have the Gedit text editor installed.

sudo apt-get install gedit

Create a new file named basic_mobile_bot_v1.urdf.

gedit basic_mobile_bot_v1.urdf

Inside this file, we define what our robot will look like (i.e. visual properties), how the robot will behave when it bumps into stuff (i.e. collision properties), and its mass (i.e. inertial properties). 

Type this code inside the URDF file.

Save and close the file.

All robots are made up of links and joints. If you go through the URDF file, you will see that we have defined each link and each joint of our two-wheeled robot. 

The links of the mobile robot include the robot base (often called “chassis”), the two drive wheels, the front caster wheel, the IMU, and the GPS. We also have a virtual link known as the base footprint. The base footprint (as shown on this post) is the link directly under the center of the robot.

Each link of the robot is connected by a joint. The only two joints that move are the revolute joints for the left and right wheels that rotate, causing the wheel links to turn.

I use xacro in this file, which stands for XML macro language. Xacro helps avoid clutter in the URDF file by enabling us to define string constants that we can reuse throughout the URDF file (e.g. “wheel_radius”).

To learn more about URDF files, check out the official documentation

Now go to the meshes folder.

cd ~/dev_ws/src/basic_mobile_robot/meshes

Add the following STL files to your meshes folder. A mesh is a file that allows your robot to look more realistic (rather than just using basic shapes like boxes and spheres).

Rather than use the STL files I provided, you can use a program like SolidWorks to generate your own STL files. You can also use a program called Blender to create DAE files. URDF files support meshes in either STL or DAE format.

Add Dependencies

Let’s add some packages that our project will depend on. Go to the package.xml file.

cd ~/dev_ws/src/basic_mobile_robot
gedit package.xml

After the <buildtool_depend> tag, add the following lines:

<exec_depend>joint_state_publisher</exec_depend>
<exec_depend>robot_state_publisher</exec_depend>
<exec_depend>rviz</exec_depend>
<exec_depend>xacro</exec_depend>

Save the file, and close it.

We will be using the Joint State Publisher and the Robot State Publisher. We will also be using RViz to visualize our robot model.

Create the Launch File

Let’s create a launch file. This launch file will be used by ROS 2 to load the necessary nodes for our package. 

colcon_cd basic_mobile_robot
cd launch
cd ~/dev_ws/src/basic_mobile_robot/launch/
gedit basic_mobile_bot_v1.launch.py

Copy and paste this code into the file.

Save the file, and close it.

If you go through the launch file, you will see that we first set the path to the important files and folders our robot needs in order to launch properly.

After we set the paths to the files and folders, we set our LaunchConfiguration variables. You can think of these variables as our options for how we want to launch our robot simulation. 

For example, imagine we want to launch our robot using the ROS 2 launch file, but we want to make sure that RViz (the robot visualization tool provided by ROS) remains turned OFF. We can create a flag called ‘use_rviz’. When we set ‘use_rviz’ to True, RViz launches, and when we set it to False, RViz does not launch.

In order for us to be able to set the value of this flag from a terminal window (i.e. outside the launch file), we have to do two things:

  1. Turn the string ‘use_rviz’ into a LaunchConfiguration variable since we can’t assign boolean values like True and False to a string like ‘use_rviz’. By using the LaunchConfiguration command, use_rviz == ‘use_rviz’.
  2. We also need to set the default value for this flag so that our system knows what to do if we don’t set its value from a terminal window as an argument when we launch our launch file. The DeclareLaunchArgument command sets the default value of the string ‘use_rviz’, which is True in the case of our launch file…and therefore, the LaunchConfiguration variable use_rviz also has a default value of True.

After we set and declare our launch arguments, we launch our ROS 2 nodes (e.g. the robot state publisher, RViz, etc.)

Add the RViz Configuration File

Let’s add a configuration file that will initialize RViz with the proper settings so we can view the robot as soon as RViz launches.

Open a new terminal window. Type:

colcon_cd basic_mobile_robot
cd rviz
gedit urdf_config.rviz

Add this code.

Save the file, and close it.

Build the Package

Now we need to build the package. Open a new terminal window, and type:

cd ~/dev_ws/src/basic_mobile_robot/
gedit CMakeLists.txt

Add the following snippet to CMakeLists.txt file above the if(BUILD_TESTING) line.

install(
  DIRECTORY config launch maps meshes models params rviz src worlds
  DESTINATION share/${PROJECT_NAME}
)

Save the file and close it.

Build the project.

cd ~/dev_ws/
colcon build

In the future, if you would like to build the basic_mobile_robot package only, you can type:

colcon build --packages-select basic_mobile_robot

Launch the Robot in RViz

Open a new terminal, and launch the robot.

cd ~/dev_ws/
ros2 launch basic_mobile_robot basic_mobile_bot_v1.launch.py

——

By the way, if you want to see the available arguments you can pass to the launch file from the terminal window, type:

ros2 launch -s basic_mobile_robot basic_mobile_bot_v1.launch.py
1b-pass-launch-arguments

And if you want to set the value of an argument (e.g. launch the robot without RViz), you can do something like this (this is a single command):

ros2 launch basic_mobile_robot basic_mobile_bot_v1.launch.py use_rviz:='False'

——

Here is the output after we launch the robot in RViz:

2-basic-mobile-robot-rviz-1
2-basic-mobile-robot-rviz-2

The joint state publisher GUI has sliders that enable you to move the wheels.

3-joint-state-publisher

If something goes wrong with the launch, close everything down, restart Linux, and launch again.

Check whether you have properly set up the collision properties by enabling Collision Enabled under RobotModel on the left pane.

4-collision-enabled-1

You can see in the image that I have modeled the base_link as a box for collisions. I could have just as easily used the STL model itself (which was used for visualization) as the collision geometry, but I decided to go with the simpler box representation to give me more flexibility to alter the collision areas if necessary. Also, Gazebo (a popular robotics simulator) recommends using simpler collision geometry to increase performance.

View the Coordinate Frames

Let’s see the coordinate frames. We first need to install the necessary software.

sudo apt install ros-foxy-tf2-tools

Again, if you have a different distribution of ROS 2, you will need to repalace ‘foxy’ in the command above with the name of your distribution.

Check out the coordinate frames.

ros2 run tf2_tools view_frames.py

In the current working directory, you will have a file called frames.pdf. Open that file.

evince frames.pdf

Here is what my coordinate transform (i.e. tf) tree looks like:

5-frames-pdf

If we want to see the coordinate transformation from one link to another, we can type the following command. For example, what is the position and orientation of the front caster wheel relative to the base_link of the robot?

The syntax is:

ros2 run tf2_ros tf2_echo <parent frame> <child frame>

We open a terminal window, and type:

ros2 run tf2_ros tf2_echo base_link front_caster

Here is the output. With respect to the base_link reference frame, the front caster wheel is located at (x=0.217 meters, y=0 meters, and z=-0.1 meters). 

6-tf2-ros-base-link-front-caster

The rotation value is in quaternion format. You can see that the rotation values are all 0s, indicating that the orientation of both coordinate frames is equivalent (i.e. the x, y, and z axes of both coordinate frames point in the same direction).

7-base-link-front-caster-wheel
8-base-link-front-caster-wheel

Remember that, by convention:

  • x-axis is red
  • y-axis is green
  • z-axis is blue 

To see an image of the architecture of our ROS system, open a new terminal window, and type the following command:

rqt_graph

Select the “Nodes/Topics (all)” option in the upper-left part of the screen, and then click the refresh arrow right next to it.

9-refresh-arrow

You can see how the joint state publisher GUI manipulates the joint states (i.e. the angle of each wheel joint). This data feeds into the robot state publisher. The robot state publisher publishes the coordinate frame relationships to tf, and the updated robot model feeds into RViz, the robot model visualization program.

10-rosgraph

That’s it! 

When you’re done, press CTRL+C in all terminal windows to shut everything down.

In the next tutorial, we will set up the odometry for our robot so that we can make the robot move and answer questions like “where is my robot located as it moves around in the world?”. Stay tuned!

How to Send a Simulated Robot to Goal Locations Using ROS

In this tutorial, I will show you how to send a simulated robot (in Gazebo) to goal locations using ROS.

Real-World Applications

This project has a number of real-world applications: 

  • Indoor and Outdoor Delivery Robots
  • Room Service Robots
  • Robot Vacuums
  • Order Fulfillment
  • Manufacturing
  • Factories

Our robot will exist in a world that contains a post office and three houses. The use case for this simulated robot would be picking up packages at a post office and delivering them to houses in a neighborhood. 

Let’s get started!

Prerequisites

Getting Started

In our Gazebo environment, we have four main goal locations we would like to send our robot.

  • 1 – House 1
  • 2 – House 2
  • 3 – House 3
  • 4 – Post Office

Open a new terminal window, and launch the robot in Gazebo.

roslaunch mobile_manipulator mobile_manipulator_gazebo.launch

Then in another terminal window, type:

roslaunch mobile_manipulator mobile_manipulator_move_base.launch

Make a note of the X and Y coordinates of each desired goal location. I use the RViz Point Publish button to accomplish this. When you click that button, you can see the coordinate values by typing the following command in a terminal:

ros topic echo /clicked_point 

I want to have an X, Y coordinate for the following four goal locations in the world.

1 = House 1 (-15.04, -7.42, 0.0)

2 = House 2 (-14.25, 20.02, 0.0)

3 = House 3 (7.35, 20.17, 0.0)

4 = Post Office (12.12, -8.41, 0.0)

You notice how I numbered the goal locations above. That was intentional. I want to be able to type a number into a terminal window and have the robot navigate to that location.

For example, if I type 4, the robot will move to the post office. If I type 2, the robot will go to house 2.

Write the Code

Now let’s write some C++.

Open a terminal window.

roscd mobile_manipulator/src
gedit send_goals.cpp

Add this code.

Save the file, and close it.

Compile the Code

Now open a new terminal window, and type the following command:

roscd mobile_manipulator
gedit CMakeLists.txt

Go to the bottom of the file.

Add the following lines.

INCLUDE_DIRECTORIES(/usr/local/lib)
LINK_DIRECTORIES(/usr/local/lib)
 
add_executable(send_goals src/send_goals.cpp)
target_link_libraries(send_goals ${catkin_LIBRARIES})
cd ~/catkin_ws/

Compile the package.

catkin_make --only-pkg-with-deps mobile_manipulator

Run the Code

Open a new terminal window, and launch the robot in Gazebo.

roslaunch mobile_manipulator mobile_manipulator_gazebo.launch

Then in another terminal window, type:

roslaunch mobile_manipulator mobile_manipulator_move_base.launch

Open another terminal to launch the send_goals node.

rosrun mobile_manipulator send_goals
16b-send-goals

Follow the prompt to send your goal to the ROS Navigation Stack.

16c-post-office
16d-post-office-goal
16e-post-office-2
16f-reached-goal

To see the node graph (which shows what ROS nodes are running to make all this magic happen), type:

rqt_graph

If the robot is having trouble reaching the goal, you can adjust the xy_goal_tolerance (in meters) and the yaw_goal_tolerance (in radians) parameters inside the base_local_planner_params.yaml file, which is located in my ~/catkin_ws/src/mobile_manipulator/param folder.

That’s it. Keep building!

Setting Up the ROS Navigation Stack for a Simulated Robot

In this tutorial, I will show you how to set up the ROS Navigation Stack for a robot in simulation.

Credit to Ramkumar Gandhinathan and Lentin Joseph’s awesome book ROS Robotics Projects Second Edition (Disclosure: As an Amazon Associate I earn from qualifying purchases). I highly recommend it if you want to learn ROS 1. Many of the files in this tutorial (URDF, configuration, and STL files), come from their book’s public GitHub page.

What is the ROS Navigation Stack?

The ROS Navigation Stack is a collection of software packages that you can use to help your robot move from a starting location to a goal location safely.

The official steps for setup and configuration are at this link on the ROS website, but we will walk through everything together, step-by-step, because those instructions leave out a lot of detail. 

IMPORTANT: For your reference, all our code will be located in this folder, which I named simulated_home_delivery_robot.

Real-World Applications

This project has a number of real-world applications: 

  • Indoor and Outdoor Delivery Robots
  • Room Service Robots
  • Robot Vacuums
  • Order Fulfillment
  • Manufacturing
  • Factories

We will create a robot that will exist in a world that contains a post office and three houses. The use case for this simulated robot would be picking up packages at a post office and delivering them to houses in a neighborhood. 

Let’s get started!

Prerequisites

Create a ROS Package

Let’s create a ROS package.

In a new terminal window, move to the src (source) folder of your workspace.

cd ~/catkin_ws/src

Now create the package.

catkin_create_pkg mobile_manipulator actionlib roscpp rospy std_msgs
cd ~/catkin_ws/
catkin_make --only-pkg-with-deps mobile_manipulator

Set Up the World

Create a new folder called worlds inside the mobile_manipulator package.

roscd mobile_manipulator
mkdir worlds
cd worlds

Open a new file called postoffice.world.

gedit postoffice.world

Download, and then add this code.

Save the file and close it.

Let’s visualize this world using Gazebo.

gazebo postoffice.world

On my computer, this file took five minutes to load, so be patient. 

2-simulated-post-office-world-gazebo

When you want to close Gazebo, type CTRL + C in all terminal windows to close everything down.

Make a note of the location of this world file. We’ll need it later. Type:

pwd

The path on my computer is:

/home/focalfossa/catkin_ws/src/mobile_manipulator/worlds/postoffice.world

Now open a new terminal window, and type:

roscd mobile_manipulator
mkdir launch

Now, go get your launch file from this tutorial. The name of my launch file is mobile_manipulator_gazebo.launch. I can access this file by opening a new terminal window, and typing:

roscd mobile_manipulator_body/launch/

Take that launch file and put it in the following directory:

roscd mobile_manipulator/launch/

Within the ~/mobile_manipulator/launch/ directory, open the launch file.

gedit mobile_manipulator_gazebo.launch

Your launch file should look like the following. You will notice that we added the post office world file.

Save the file, and close it.

Launch the Robot in the Gazebo World

Now let’s launch the robot in Gazebo.

Move to your catkin workspace.

cd ~/catkin_ws/
roslaunch mobile_manipulator mobile_manipulator_gazebo.launch

Here is my output:

4-robot-launched-in-the-world

Add a LIDAR

Create the Code

Now that we have set up the environment, let’s add a LIDAR to our robot so that it can perform SLAM (Simultaneous Localization And Mapping) within the post office world.

Open a new terminal window. Type the following command.

roscd mobile_manipulator_body/urdf/

Open mobile_manipulator.urdf.

gedit mobile_manipulator.urdf

Make sure your file has this code. Add the code between the ARM block and the BASE TRANSMISSIONS block.

You will see that we have added the LIDAR (i.e. laser_link), and we have also added a Gazebo plugin for it. 

Save and close the file.

Test the LIDAR

Now let’s launch the robot in Gazebo.

Open a new terminal window, and move to your catkin workspace.

cd ~/catkin_ws/
roslaunch mobile_manipulator mobile_manipulator_gazebo.launch

Here is my output:

8-add-lidar-sensor

To see the active coordinate frames, type the following command:

rosrun tf2_tools view_frames.py

To open the pdf file that shows the coordinate frames, type the following command:

evince frames.pdf

Configure the ROS Navigation Stack Parameters

Now that we have set up the world and added a LIDAR to our robot, we can set up and configure the ROS Navigation Stack so that our simulated robot can move autonomously through the environment. 

Open a new terminal window.

Move to your package.

roscd mobile_manipulator

Create a new folder. We want this folder to hold the configuration parameters. 

mkdir param
cd param

The ROS Navigation Stack uses two costmaps to store information about obstacles in the world. 

  1. Global costmap: This costmap is used to generate long term plans over the entire environment….for example, to calculate the shortest path from point A to point B on a map.
  2. Local costmap: This costmap is used to generate short term plans over the environment….for example, to avoid obstacles.

We have to configure these costmaps for our project. We set the configurations in .yaml files.

Common Configuration (Global and Local Costmap)

Let’s create a configuration file that will house parameters that are common to both the global and the local costmap. The name of this file will be costmap_common_params.yaml.

gedit costmap_common_params.yaml

Add the costmap_common_params.yaml code to this file.

Save and close the file.

To learn more about each of the parameters and what they mean, check out this link.

Global Configuration (Global Costmap)

Let’s create a configuration file that will house parameters for the global costmap. The name of this file will be global_costmap_params.yaml.

gedit global_costmap_params.yaml

Add the global_costmap_params.yaml code to this file.

Save and close the file.

Local Configuration (Local Costmap)

Let’s create a configuration file that will house parameters for the local costmap. The name of this file will be local_costmap_params.yaml.

gedit local_costmap_params.yaml

Add the local_costmap_params.yaml code to this file.

Save and close the file.

Base Local Planner Configuration

In addition to the costmap configurations we did in the previous section, we need to configure ROS Navigation Stack’s base local planner. The base_local_planner computes velocity commands that are sent to the robot base controller. The values that you use for your base_local_planner will depend on your robot.

gedit base_local_planner_params.yaml

Add the base_local_planner_params.yaml code to this file.

Save and close the file.

Configure RViz Settings

Add this file named mobile_manipulator.rviz to the param folder of your package.

roscd mobile_manipulator/param

Install the ROS Navigation Stack

Open a terminal window, and type the following command:

sudo apt-get install ros-noetic-navigation

To see if it installed correctly, type:

rospack find amcl

You should see the following output:

/opt/ros/noetic/share/amcl

Tune the AMCL Parameters

Open up your AMCL node.

roscd amcl/examples

Open the amcl_diff.launch file.

sudo gedit amcl_diff.launch

Here is my amcl_diff.launch file.

Set the following parameters, save the file, and close it.

<param name="odom_model_type" value="diff-corrected"/> <param name="odom_alpha1" value="0.005"/> <param name="odom_alpha2" value="0.005"/> <param name="odom_alpha3" value="0.010"/> <param name="odom_alpha4" value="0.005"/> <param name="odom_alpha5" value="0.003"/> 

Press CTRL + C in all windows to close everything down.

Create a Map Using the ROS Hector-SLAM Package

Let’s create a map using the ROS Hector-SLAM package. For more information on this package, check this post.

Install Qt4

Install Qt4. Qt4 is a software that is used to generate graphical user interfaces.

sudo add-apt-repository ppa:rock-core/qt4
sudo apt update
sudo apt-get install qt4-qmake qt4-dev-tools

Type Y and press Enter to complete the installation. The whole process should take a while, so just be patient.

Download the Hector-SLAM Package

Move to your catkin workspace’s source folder.

cd ~/catkin_ws/src

Clone the Hector-SLAM package into your workspace.

git clone https://github.com/tu-darmstadt-ros-pkg/hector_slam.git

Set the Coordinate Frame Parameters

We need to set the frame names and options correctly.

Go to the launch file for Hector-SLAM. All of this below is a single command, so you can just copy and paste.

sudo gedit ~/catkin_ws/src/hector_slam/hector_mapping/launch/mapping_default.launch

Search for these lines (lines 5 and 6 in my code).

<arg name="base_frame" default="base_footprint"/> <arg name="odom_frame" default="nav"/> 

Change those lines to this:

<arg name="base_frame" default="base_link"/> 
<arg name="odom_frame" default="odom"/> 

Now go to the end of this file, and find these lines (line 54 in my code).

<node pkg="tf" type="static_transform_publisher" name="base_to_laser_broadcaster" args="0 0 0 0 0 0 base_link laser_link 100"/> 

Save the file, and return to the terminal window.

Open a new terminal window, and type this command:

cd ~/catkin_ws/

Build the packages.

catkin_make --only-pkg-with-deps hector_slam

If you see this error message…

Project ‘cv_bridge’ specifies ‘/usr/include/opencv’ as an include dir, which is not found. It does neither exist as an absolute directory nor in…

Type:

cd /usr/include
sudo ln -s opencv4/ opencv

Build the packages again.

catkin_make --only-pkg-with-deps hector_slam

Wait a minute or two while the Hector-SLAM package builds.

Launch Mapping

Open a new terminal, and type the following command:

roslaunch mobile_manipulator mobile_manipulator_gazebo.launch

Now launch the mapping process.

roslaunch hector_slam_launch tutorial.launch

You can steer the robot by opening a new window and typing:

rosrun rqt_robot_steering rqt_robot_steering

Move the robot around the environment slowly. Map-making works best at slow (EXTREMELY slow) speeds. 

I recommend the following sequence of actions:

  • Move the robot backwards at 0.03 meters per second (i.e. -0.03 m/s). 
  • Turn the robot 90 degrees in-place at a rate of -0.24 radians per second.
  • Move the robot forward at a rate of 0.03 meters per second. 
  • Move the robot backwards at 0.03 meters per second.

Let’s save the map using a package called map_server. This package will save map data to a yaml and pgm formatted file.

Install map_server.

roscd mobile_manipulator/maps
sudo apt-get install ros-noetic-map-server

When you are happy with the map that you see in rviz, you can save the map as test.yaml and test.pgm. Open a new terminal, and type:

roscd mobile_manipulator/maps
rosrun map_server map_saver -f test

Maps will save to the ~…mobile_manipulator/maps directory.

Press CTRL + C on all terminal windows to shut everything down.

Load a Saved Map

To view the map, you can run the following command in a new terminal window to get the ROS Master started.

roscd mobile_manipulator/maps
roscore

Now load the map. In a new terminal window, type:

rosrun map_server map_server test.yaml

Open rviz in another terminal.

rviz

Click Add in the bottom left, and add the Map display.

Under Topic under the Map section, select /map.

You should see the saved map on your screen.

9d-create-a-map-hector-slam

Create a Preliminary Launch File

At this stage, we want to create a preliminary ROS launch file. This file will enable us to launch our mobile manipulator with the necessary mapping software as well as the move base and Adaptive Monte Carlo Localization (AMCL) nodes. You can learn more about the move base and AMCL nodes in this tutorial.

Type the following command.

roscd mobile_manipulator/launch

Create the following launch file.

gedit mobile_manipulator_move_base.launch

Add this code to the file.

Save the file, and close it. 

Add an Inertial Measurement Unit (IMU) to the Robot

Let’s add an IMU sensor to our robot. IMUs can help us get more accurate localization.

Open a new terminal window. Type the following command.

roscd mobile_manipulator_body/urdf/

Open mobile_manipulator.urdf.

gedit mobile_manipulator.urdf

Make sure your file has the IMU code inside the SENSORS block right after the code for the laser_link.

Save and close the file.

Test the IMU

Now let’s launch the robot in Gazebo.

Open a new terminal window, and move to your catkin workspace.

cd ~/catkin_ws/
roslaunch mobile_manipulator mobile_manipulator_gazebo.launch

Open a new terminal, and type:

rostopic list

You should see a topic named /imu_data.

Set Up the robot_pose_ekf Package

Now we will install the robot_pose_ekf package. This package uses an extended Kalman filter to help us estimate the position and orientation of the robot from sensor data. 

Getting Started

Open a new terminal window, and type:

sudo apt-get install ros-noetic-robot-pose-ekf

Now move to your workspace.

cd ~/catkin_ws

Build the package.

catkin_make

Add the the robot_pose_ekf node to a ROS Launch File

To launch the robot_pose_ekf node, you will need to add it to a launch file. Before we do that, let’s talk about the robot_pose_ekf node.

About the robot_pose_ekf Node

The robot_pose_ekf node will subscribe to the following topics (ROS message types are in parentheses):

This node will publish data to the following topics:

You might now be asking, how do we give the robot_ekf_pose node the data it needs? 

The data for /odom will come from the /base_truth_odom topic which is declared inside the URDF file for the robot.

The data for /imu_data  will come from the /imu_data topic which is also declared inside the URDF file for the robot. However, in this simulation, I will not use the IMU data since we are using Gazebo ground truth for the odometry. If you want to use the IMU data, you will set that parameter to true inside the launch file section for the robot_pose_ekf code.

In the launch file, we need to remap the data coming from the /base_truth_odom topic since the robot_pose_ekf node needs the topic name to be /odom.

Update the Launch File

Here is my full launch file. You will see that I have added static transform publishers at the top to get the data from base_footprint to base_link. 

Launch the Autonomous Mobile Robot!

Let’s test to see if autonomous navigation is working.

Now, open a new terminal window, and type:

roslaunch mobile_manipulator mobile_manipulator_gazebo.launch

Then in another terminal window, type:

roslaunch mobile_manipulator mobile_manipulator_move_base.launch

You set a pose estimate inside the map by clicking the 2D Pose Estimate button in Rviz and placing the estimate somewhere in line with where the robot currently is on the map.

10-2d-pose-estimate

Then you set the goal by clicking the Nav Goal button in Rviz and placing the goal in an empty space on the map. 

15-testing-autonomous-navigation-2

The path will be drawn as a red line, and the robot will attempt to move to the goal location due to the velocity commands published by the move_base node.

16e-post-office

To see the active coordinate frames, type the following command:

rosrun tf2_tools view_frames.py

To open the pdf file that shows the coordinate frames, type the following command:

evince frames.pdf

If you have difficulties, check out the differential drive control parameters in your control.yaml file. You can tweak the wheel_separation,  wheel_radius, and velocity parameters inside this file by typing the following command:

roscd mobile_manipulator_body/config
gedit control.yaml

You can also tweak the velocity settings in your base_local_planner_params.yaml file and the footprint in the costmap_common_params.yaml file.

That’s it. Keep building!