Setting Up a Simulated Environment for the Robot Operating System (ROS)

by Gazza

As a follow up to the article titled "Introduction to the Robot Operating System (ROS)" (41:3), this article focuses on setting up an environment that can simulate a robot.  Specifically, we will use ROS Noetic, which is supported until May of 2025.  If there is sufficient interest, I am willing to continue this series in ROS 2, so please write in if these articles interest you.  There are three different ways we can proceed at this point: bare-bones, VM, or Docker.

Our preferred way, and the focus of this article, is to use a Docker image.  However, notes and references on the other approaches are provided below.

Bare-Bones or VM Setup

The first approach is bare-bones (or dual-boot) installation.

This is feasible if you have a spare laptop laying around.  Alternatively, you could also spin up a Virtual Machine (VM).  However, unless you dedicate significant resources to the VM, the simulation may be a bit laggy or freeze1.  Note that if you choose to continue with a bare-bones or VM approach, the next step is installing Ubuntu 20.04.  Installing Ubuntu is outside the scope of this article, but an ISO can be found online2.  With Ubuntu Focal installed, the next step is to install ROS Noetic.  Instructions for installing ROS Noetic can also be found online3.

It is highly recommended that you set up a catkin workspace if you have any interest in pursuing ROS after this article.  It is not needed for this exercise, but will save some time down the road.  The directions for installing the catkin workspace can be found online4.  We will get more into the catkin workspace later, but in short it allows you to add ROS packages that are not located in the repository.

Docker Setup

There are a few advantages of using docker for ROS development.

First, it resolves the "... well it worked on my computer" issue.  ROS has a lot of dependencies and keeping track of which version's installed can be a hassle.

Second, it allows for multiple ROS containers to exist on the same host OS.  For example, my host OS is Ubuntu 24.04; however, I have ROS containers for Noetic (requires Ubuntu 20.04), Humble (requires Ubuntu 22.04), and Jazzy (requires Ubuntu 24.04).

Third, when I end up breaking things and I often do, I can relaunch the container and I am back to coding in minutes.

Do you have Docker installed already?  If not, instructions can be found online5.  I chose to install Docker using the APT repository.  For convenience the steps are provided below:

# Add Docker's official GPG key:
$ sudo apt-get update
$ sudo apt-get install ca-certificates curl
$ sudo install -m 0755 -d /etc/apt/keyrings
$ sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
$ sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to apt sources:
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt-get update

# Install the latest version:
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# Test docker installation:
$ sudo docker run hello-world

To make life more convenient, which is often inversely proportional to security, I typically also do the post-install steps: "Manage Docker as a nonroot user" and "Configure Docker to start on boot with systemd".  If this interests you, then this link will help with either or both of those steps6.

There are different ways to interact with Docker.  While the command line is one way, Visual Studio Code also has an extension called "Dev Containers."  This link provides instructions to install VSCode in Linux7.  However, the following command typically works for me:

$ sudo apt install code

The next step is to install the "Dev Container" extension within VSCode.

Pressing Ctrl+Shift+X will pull up the Extensions Marketplace.  Search and install "Dev Containers" by Microsoft.

With "Dev Containers" installed, the next step is to download the files Dockerfile and devcontainer.json from the 2600 code repository8 (or copy from below).  Both of these files should be copied to: ~/Noetic/.devcontainer

Now this is where using Docker really pays off.  After opening the "Noetic" folder in VSCode, click the bottom left Open a Remote Window button (it looks like ><) and click Reopen in a Container.

The first time you do this, it will download everything that you need; so grab that copy of 2600 and get caught up on the latest issue.  After it is finished downloading (~3-4 GB of data) and compiling everything, VSCode will drop you inside a terminal in the container.  Now let's have some fun!

ROS

Step 1: Spawning a Robot in a Virtual World

Once you are at the terminal inside the container, you can confirm this by checking that the bottom-left corner says "Dev Container: noetic desktop-full".  The next step is typing the following command:

$ export TURTLEBOT3_MODEL=waffle

There are three different versions of TurtleBots: Burger, Waffle, and Waffle Pi.  Personally, I prefer the Waffle model since it is equipped with an RGB-D camera (think Xbox Kinect).  This command needs to be entered into each new terminal window or you will get an error.

The next step is to run the following command, which spawns a virtual world and robot. One thing to keep in mind is that roslaunch also runs the command roscore, if it isn't already running.  This is not true for rosrun commands which need to have a terminal running roscore to execute.

$ roslaunch turtlebot3_gazebo turtlebot3_world.launch

Step 2: Making The Robot Move

With the virtual robot and world loaded, the next step is to make it move.

The easiest way to get the robot to move is to use the package turtlebot3_teleop.  The turtlebot3_teleop package converts key presses to the cmd_vel topic.  The cmd_vel topic is a "geometry/Twist" message type that directs the movement of the TurtleBot3 robot.

To launch the turtlebot3_teleop package we need to first open a new terminal.  Do you remember what we have to do when opening a new terminal?  I hope you said run: export TURTLEBOT3_MODEL=waffle

With the new terminal open, and the export command executed, then next step is to run the command below:

$ roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch

At this point, I recommend overlaying the terminal window onto the Gazebo world window.

For turtlebot3_teleop_key to work it needs to have focus when making key presses.  Each tap of the w key will move the TurtleBot3 forwarded faster and faster.  The s key is used to stop the robot and the x will slow forward velocity or cause the TurtleBot3 robot to back up.  The a and d keys are used to rotate the TurtleBot3 counterclockwise and clockwise respectively.

Step 3: Making a Map

Now that we have the virtual robot and world loaded from Step 1 and the ability to move the robot from Step 2, the next step is to have the robot map the virtual world.

To make a map, we are going to use the Simultaneous Localization And Mapping (SLAM) approach.  There are quite a few SLAM approaches available for us to use out of the box including: gmapping, cartographer, hector and karto.

For now, we will be using the gmapping package.  Open a new terminal window and launch the gmapping package using the command below.  I hope you remembered to run the export command before launching the SLAM file.

$ roslaunch turtlebot3_slam turtlebot3_slam.launch slam_methods:=gmapping

Note that this launch file opens a new window called RViz.  The RViz window allows you to view ROS topics in 3D.

In this use case, it will draw a 2D map as the robot explores the virtual world.  You can save the map with the command below.  The map is in the PGM file format and can be opened with most drawing programs.  The 2D map is called an "occupancy grid."

The occupancy grid is typically trinary in nature using three colors.  Black is used to designate "obstacles" such as walls.  Light gray is used to represent "free space."  The "free space" is defined as areas the TurtleBot3 can safely traverse and is accomplished by ray-tracing to an obstacle.  The dark gray areas are "unknown" and if possible, gets converted to either "obstacles" or "free space" as the TurtleBot3 explores.

$ rosrun map_server map_saver -f ~/map

How does gmapping work?

In short, it uses the 2D lidar on the TurtleBot3 robot.  The 2D lidar produces a laser_scan topic.  The laser_scan topic is used to localize the robot in the virtual world and generate the 2D map as it explores.

Step 4: An Easier Way to Navigate

While moving the robot with the keyboard is fun at first, it quickly gets tiresome.  Thus, an easier way to navigate the robot is to use "waypoints."  This can be done in the RViz window using the move_base package.  The move_base package is quite complex and this article is already getting on the longer side, so I will save the explanation for the next article.  The condensed version is open a new terminal window and enter the command below:

$ roslaunch turtlebot3_navigation move_base.launch

It is recommended to close the turtlebot3_teleop_key terminal by pressing Ctrl+C (in the terminal window that you want to close) so there is only one node publishing the cmd_vel topic.

While it is possible to use a node called cmd_vel_mux to run multiple navigation methods such as a joystick and move_base, I will save that discussion for later too.

With move_base running in the new terminal window, click on the RViz window.  Along the top banner is a button called 2D nav goal.  This will convert your cursor to an arrow.

On the "free space" (or light gray) area of the map, click and drag where you want the robot to go.  The "click" sets the "X" and "Y' position of the goal and the "drag" sets the "yaw" or orientation of the TurtleBot3 at the goal.

If everything worked as intended, the TurtleBot3 should start navigating to the goal.

One last thing that I would like to point out is if you plan to use move_base in the future, the following sequence of launch files should be used.  The main reason is that move_base expects the "map" frame to be published and will complain until it is provided by gmapping.

# Terminal 1:
$ roslaunch turtlebot3_gazebo turtlebot3_world.launch

# Terminal 2:
$ roslaunch turtlebot3_slam turtlebot3_slam.launch slam_methods:=gmapping

# Terminal 3:
$ roslaunch turtlebot3_navigation move_base.launch

Summary

In summary, I hope this article has helped to set up a ROS environment.  Also, we launched a virtual robot and world.  We demonstrated two different methods to drive the robot, namely turtlebot3_teleop_key and move_base.  We also used gmapping to generate a 2D occupancy grid of the virtual world.

The next article will explain in more detail what is happening here and explore localization with the occupancy grid saved in Step 3.

If you get tired of mapping the TurtleBot World waiting on the next article, try mapping the TurtleBot House:

$ roslaunch turtlebot3_gazebo turtlebot3_house.launch

References

  1. Gazebo Freezes on VM After Running roscore
  2. Ubuntu 20.04.6 LTS (Focal Fossa)
  3. Ubuntu Install of ROS Noetic
  4. Installing and Configuring Your ROS Environment
  5. Install Docker Engine on Ubuntu
  6. Linux Post-Installation Steps for Docker Engine
  7. Visual Studio Code on Linux
  8. 2600 Code Repository
  9. Gazebo Simulation Uses the ROS Gazebo Package

Dockerfile:

FROM osrf/ros:noetic-desktop-full

# Add vscode user with same UID and GID as your host system
# (copied from https://code.visualstudio.com/remote/advancedcontainers/add-nonroot-user#_creating-a-nonroot-user)
ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID
RUN groupadd --gid $USER_GID $USERNAME && useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME && apt-get update && apt-get install -y sudo && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME && chmod 0440 /etc/sudoers.d/$USERNAME

# Switch from root to user
USER $USERNAME

# Add user to video group to allow access to webcam
RUN sudo usermod --append --groups video $USERNAME

# Update all packages
RUN sudo apt update && sudo apt upgrade -y

# Install Git
RUN sudo apt install -y git nano wget ros-noetic-turtlebot3 ros-noetic-turtlebot3-gazebo

# Rosdep update
RUN rosdep update

# Source the ROS setup file
RUN echo "source /opt/ros/${ROS_DISTRO}/setup.bash" >> ~/.bashrc
RUN echo "export ROS_HOSTNAME=127.0.0.1" >> ~/.bashrc
RUN echo "export ROS_MASTER_URI=http://127.0.0.1:11311" >> ~/.bashrc

devcontainer.json:

{
  "name": "noetic desktop-full",
  "dockerFile": "Dockerfile",
  "runArgs": [
    "--privileged",
    "--network=host",
    "--volume=/tmp/.X11-unix:/tmp/.X11-unix",
    "--volume=/dev:/dev",
    "--env=DISPLAY=${localEnv:DISPLAY}"
  ],
  "workspaceMount": "source=${localWorkspaceFolder},target=/${localWorkspaceFolderBasename},type=bind",
  "workspaceFolder": "/${localWorkspaceFolderBasename}",
  "mounts": [
    "source=${localEnv:HOME}${localEnv:USERPROFILE}/.bash_history,target=/home/vscode/.bash_history,type=bind"
  ]
}

Code: Dockerfile

Code: devcontainer.json

Return to $2600 Index