Docker for Gazebo-ROS Simulations

Posted on January 26, 2018 in docker

Jupyter

Have you ever spent hours on a new machine or server trying to replicate your development environment just so you can get your software to run? Do your users get frustrated trying to install your open-source software and give up on it entirely? ROS is great, but I have yet to meet a ROS user or developer who has not spent a frustrated hour or two trying to build some library with a mess of interdependencies. Docker is a tool that was invented to help alleviate this problem. If you are a software developer and have not yet heard of Docker then I highly suggest taking some time to check it out. It does not take long to learn, and your future self will thank you.

Docker is a tool that allows software developer's to bundle their application's dependencies and ship it all as one package. In this blog post, I will show an example of how I have made use of it to make the Bobble-Bot simulation more portable. In a future blog post, I plan to use this Bobble-Bot Docker container to run thousands of simulation runs simultaneously in the cloud in order to explore the potential application of learning algorithms for autonomous navigation.

By the end of this blog post, you will have learned how you can containerize your own ROS Gazebo simulation. Your user's will be able to launch your simulator using just a single command (no more struggles installing dependenices and building from source).

Creating the Bobble-Bot Simulator Docker Image

Before we can begin, you will need to install docker and nvidia-docker2 on your machine. In order to run the 3D graphics environment within a Docker container, the Bobble-Bot simulation image requires the NVidia Docker run-time. This means that an NVidia GPU is required if you want to run the graphics. If you only care about running the simulation headless (no graphics), then Docker is the only requirement.

A Bobble-Bot simulation Docker image is available over on DockerHub. DockerHub is the GitHub of Docker images. The image I am hosting on DockerHub was created by writing a Dockerfile. The Dockerfile defines the sequence of steps used by Docker to build the image. It can be thought of as the recipe for creating your image. To see this Dockerfile, run the command below:

git clone https://github.com/super-owesome/bobble_docker.git

This repository houses the Dockerfile and some supporting bash scripts to launch useful containers for various simuation analysis and development purposes. Let's first have a look at the Dockerfile:

FROM osrf/ros:melodic-desktop-full
ENV NVIDIA_VISIBLE_DEVICES \
    ${NVIDIA_VISIBLE_DEVICES:-all}

ENV NVIDIA_DRIVER_CAPABILITIES \
    ${NVIDIA_DRIVER_CAPABILITIES:+$NVIDIA_DRIVER_CAPABILITIES,}graphics

RUN apt-get update && apt-get install -y apt-utils build-essential psmisc vim-gtk
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
RUN apt-get update && apt-get install -q -y python-catkin-tools
RUN apt-get update && apt-get install -q -y ros-melodic-hector-gazebo-plugins
# Install git lfs. Necessary in order to properly clone bobble_description
RUN echo 'deb http://http.debian.net/debian wheezy-backports main' > /etc/apt/sources.list.d/wheezy-backports-main.list
RUN curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
RUN apt-get install -q -y git-lfs
RUN git lfs install
ENV BOBBLE_WS=/bobble_workspace
RUN source /opt/ros/melodic/setup.bash && \
    mkdir -p $BOBBLE_WS/src && \
    cd $BOBBLE_WS/src && \
    catkin_init_workspace && \
    git clone https://github.com/super-owesome/bobble_controllers.git && \
    git clone https://github.com/super-owesome/bobble_description.git && \
    cd $BOBBLE_WS && \
    catkin_make && \
    catkin_make install
# Required python packages for analysis
RUN \
  apt-get install -y python-pip && \
  pip install matplotlib==2.0.2 && \
  pip install numpy && \
  pip install scipy && \
  pip install jupyter && \
  pip install seaborn && \
  pip install pandas && \
  pip install bokeh && \
  pip install rosbag_pandas
EXPOSE 11345
COPY ./bobble_sim_entrypoint.sh /
ENTRYPOINT ["/bobble_sim_entrypoint.sh"]
CMD ["bash"]

The Dockerfile above captures all of the environment variable definitions (ENV) and shell commands (RUN) that must be run in sequence in order to build the Bobble-Bot simulation from source and install it. The FROM on the first line of the Dockerfile tell Docker to base this image off of the official ROS Melodic Docker image. All of the official ROS base images can be found here on DockerHub. One of the major advantages for Docker is in automated testing. Testing Bobble-Bot in ROS Kinetic, for example, could be done by simply modifying the FROM line of the Dockerfile and building a new image. This image would be based off of ROS Kinetic and would perfectly emulate a ROS Kinetic installation.

Speaking of building images from Dockerfiles, here's the command to use to build a Docker image from a Dockerfile in the working directory. This is just a simple example. See the documentation on the Docker build command by typing docker --help.

docker build -t image_tag .

The last two lines of the Dockerfile specify an entry-point script and command to run when a container is spawned from the image. Here is that entry point shell script if you're curious.

#!/bin/bash
set -e
source /opt/ros/melodic/setup.bash
source /bobble_workspace/install/setup.bash
exec "$@"

If you like, you can build the image from the Dockerfile itself in the repository that you cloned. More easily though, you can simply pull it down from DockerHub (which is the typical work-flow when using an image someone else created).

docker pull superowesome/bobble-sim:latest

Using the Image

Docker refers to instances of images as containers. Let's explore how to use the image you just pulled down in the last section. The command below is used to launch the Bobble-Bot simulation using the bobble-sim:latest image.

xhost+
./run_bobble_sim.bash

This script is found in the bobble_docker git repository. Let's take a look at it.

XAUTH=/tmp/.docker.xauth
if [ ! -f $XAUTH ]
then
    xauth_list=$(xauth nlist :0 | sed -e 's/^..../ffff/')
    if [ ! -z "$xauth_list" ]
    then
        echo $xauth_list | xauth -f $XAUTH nmerge -
    else
        touch $XAUTH
    fi
    chmod a+r $XAUTH
fi
docker run -it \
    --name="bobble_sim_container" \
    --env="DISPLAY=$DISPLAY" \
    --env="QT_X11_NO_MITSHM=1" \
    --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
    --env="XAUTHORITY=$XAUTH" \
    --volume="$XAUTH:$XAUTH" \
    --runtime=nvidia \
    superowesome/bobble-sim:latest \
    roslaunch bobble_controllers run_sim.launch

The last two lines are the most important and are hopefully self-explanatory. There's a lot of other boiler-plate nonsense in this script almost entirely dedicated to getting the graphics running within the container using the NVidia Docker run-time. It's important, but I'm not going to go into details about that here. You can read more about it on the official ROS wiki.

If all goes well, the Bobble-Bot simulation graphics will pop up. We can then enable keyboard control by connecting to the running container. To do this, run these commands in a separate terminal.

cd ~/bobble_workspace/src/bobble_docker
./run_keyboard_control.bash

The run_keyboard_control bash script is a little different than the previous one, so it's worth looking at.

docker exec -it \
    bobble_sim_container \
    sh -c "source /opt/ros/melodic/setup.bash; \
           source /bobble_workspace/install/setup.bash; \
           rosrun bobble_controllers KeyboardControl"

Notice the use of exec instead of run. This is how you execute a command on a running container. If everything works right, you should be able to drive Bobble-Bot around with the keyboard as seen below.

BobbleKeyboard

That covers the basics of using an image to spawn a container and connecting to it. Moreover, you now have an example to base your own Gazebo Docker containers off of. It should be easy to tailor the Dockerfile and bash scripts I provided to your own ROS package or Gazebo simulation.

More Information

Consult the bobble_controllers repository to learn more about the simulation. You can also visit the bobble_docker repository to read about other things you can do with the bobble-sim Docker image. Leave any comments and questions below. Thanks for reading!