Simulate a differential drive robot with ROS

In this post we will use ROS to simulate a differential drive robot.  We will discuss the following

The robot that we will be simulating is called Odisseus. You can find all the files used in this post on Odisseus GitHub repository.

Odisseus package structure

Let’s see how the Odisseus package is structured so that we can navigate in it easily. Overall, the Odisseus package comprises of the following directories:

  • launch
  • include
  • maps
  • msg
  • navigation
  • src
  • urdf

The launch directory only contains a .launch file which we use to launch the simulation. The include directory contains header files needed for the simulation. The maps directory contains various maps that can be used to simulate various environments. The msg directory contains the type of messages that specifically Odisseus uses. The naviagtion directory contains files describing various parameters needed for local and global localization. The urdf directory contains the URDF description for Odisseus. Finally, the src directory contains functionality used by the mission_planner node.

Note that we need a model in order to be able to visualize our robot. You can checkout construct a robot model with urdf I post to see how to represent Odisseus using URDF.

Odisseus nodes

Odisseus simulation is using four nodes. Namely:

  • map_server
  • amcl
  • move_base
  • mission_planner

The first three nodes are required by the ROS navigation stack in order to function properly. Concretely, the map_server node provides a static map that is required by the navigation and mission planer nodes in order to be able to localize and devise plans.

The amcl node localizes the robot against the static map using an adaptive Monte Carlo localization technique (see Wikipedia article here for Monte Carlo localization).

The move_base node handles global planning and local control for the robot.

The mission_planner node devises a goal for the robot given a map and odometry data and publishes this goal using actionlib. Another way to supply goals to the robot is via rviz, the 3D GUI that ROS comes with.

Now that we have taken some of the required logistics out of the way, let’s discuss in more detail what is happening. Let’s start with the map_server node.

The map_server node

To run map_server, we need a static map. We use the maps in the /maps directory. The map that is used is declared in the map_server XML node in the /launch/odisseus.launch.
In this post we will use an empty_world.yaml for simplicity.

Note that we also need to put Odisseus in a simulated 3D world that matches the 2D map we are using.

The amcl node

We use the amcl package, to localize the robot within the world, using the map. amcl is extremely configurable and generally does need to be tuned for good performance. In our case, we will use the example configuration for differential-drive robots, which is provided as a launch file in the amcl package; amcl_diff.launch.

The move_base node

The next node we have is move_base. The move_base is a complex node, with plenty of room for configuration. Fortunately,  its default configuration is pretty close to what we need, leaving just a handful of things for us to change. First, we need to set the parameters that will be common to both the global and local costmaps that are used by move_base. For the move_base node to work we need to setup the following files:

  • costmap_common_params.yaml
  • global_costmap_params.yaml
  • local_costmap_params.yaml
  • base_local_planer_params.yaml

You can find these files in the navigation directory.

The mission_planner

The mission_planner node is responsible for creating goals for the robot and publishing them. Let’s see how both these tasks are done.

Establishing a goal

Sending the goal

Once the goal has been established by the MissionPlanner it must be published. We do this with the help of actionlib. We wrap the message into a move_base_msgs::MoveBaseGoal. The message has to specify the following:

  • The x,y position of the goal
  • The orientation of the goal
  • The frame id
  • A time stamp

Once these are established, the node simply sends the goal by using the member function sendGoal.

Launching the simulation

We can launch the simulation and observe Odisseus by typing on a terminal

roslaunch odisseus odisseus.launch

This should launch, among others things,  Gazebo showing Odisseus in the middle of an empty world. Furthermore, you can open another terminal and bring up rviz by typing


Once you have the simulation launched you can view the topics that are used by typing, in another terminal,

rostopic list

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s