ROS development with Visual Studio Code inside a Docker container

In this post I am going to extend my previously discussed approach for developing ROS packages with Visual Studio Code by utilising the new remote extensions from Microsoft that enable development in a sandboxed environment inside a Docker container.

To follow along you will need to install Docker CE on your system. The official documentation offers detailed installation instructions for every operating system.

I will base this post on my panda_simulation GitHub repository where I integrated the FRANKA EMIKA Panda robot into the Gazebo simulation environment. I will not provide instructions for displaying the user interfaces through Docker containers. This will be discussed in a separate post.

This guide is for developing and running ROS nodes that do not require a user interface for running the Gazebo simulation without gzclient, the program that is responsible for exposing the simulation to a user interface. This can be useful for automated tests inside a docker container where the sensor information is read automatically from ROS topics instead of manual inspection through gzclient by the developer.

In the following we will combine panda_simulation with my previous Visual-Studio-Code-ROS as a basis for integration with a Docker container.

Create configuration files

For integration with Docker we will create two files and put them inside the .devcontainer directory:

  • Dockerfile: The container configuration that will be used to create a container instance
  • devcontainer.json: VS Code specific configuration for development inside a container

devcontainer.json

VS Code provides numerous configuration options. I will first display my configuration and then discuss the important parts. Some parameters are taken over from the official Visual Studio Code – Docker documentation.

{
    "name": "panda_simulation-dev",
    "dockerFile": "Dockerfile",
    "extensions": [
        "ms-vscode.cpptools",
        "ms-iot.vscode-ros"
    ],
    "runArgs": [
        "--cap-add=SYS_PTRACE",
        "--security-opt",
        "seccomp=unconfined",
        "-v",
        "${env:HOME}${env:USERPROFILE}/.ssh:/root/.ssh"
    ],
    "settings": {
        "terminal.integrated.shell.linux": "/bin/bash"
    },
    "postCreateCommand": "bash /catkin_ws/src/panda_simulation/scripts/docker-setup.sh",
    "workspaceMount": "src=/Users/pekel/code/ros/panda_simulation,dst=/catkin_ws/src/panda_simulation,type=bind,consistency=cached",
    "workspaceFolder": "/catkin_ws"
}
  • dockerFile: Path to the Dockerfile that we are going to base our container on. We will add an additional instruction to a ROS base image in order to use the VS Code tasks with shortcuts.
  • extensions: The VS Code extensions that will be installed within the container for development.
  • runArgs: Docker container run arguments. We will bind our ssh key directory as Docker volume with the -v paramter. This is optional and can be left out.
  • postCreateCommand: Run additional commands after creating the container. In our case the post installation script is executed (see section below).
  • workspaceMount: The destination path that our repository will be copied to. This is critical as we can create a ROS workspace and copy our repository to the src/ subdirectory using this setting.
  • workspaceFolder: The directory within the container that should be opened by VS Code on launch. Allows us to open the workspace instead of just opening the project which means that we get code completion, tasks and other functionality without modifying the directory structure on the host.

Dockerfile

FROM osrf/ros:melodic-desktop-full-bionic

RUN apt-get update && apt-get install -q -y \
    openssh-client

RUN echo 'source /opt/ros/melodic/setup.bash' >> /root/.bashrc
  1. Use a ROS base image
  2. Install the OpenSSH client in order to use SSH based communication with GitHub
  3. Append a source instruction to ~/.bashrc file for catkin_make command usage in bash

Modify bash mode

In order to use catkin_make with Visual Studio Code build tasks we need to make sure that bash runs in the interactive mode (-i) and as the user for whom we have modified the .bashrc file in the Dockerfile (-l). For this we will need to add a workspace specific configuration for the bash terminal with a settings.json file. This file will be part of our Visual-Studio-Code-ROS repository.

{
    "terminal.integrated.shellArgs.linux": [
        "-l",
        "-i"
    ]
}

Post installation script

In order to finish the remaining steps we will create the bash script scripts/docker-setup.sh:

#!/bin/bash

REPOSITORY_DIR=$(pwd)
WORKSPACE_DIR=/catkin_ws
DEPENDENCIES_DIR=$WORKSPACE_DIR/dependencies
APP_DIR=/root/.panda_simulation

# Install libfranka
mkdir $DEPENDENCIES_DIR && cd $DEPENDENCIES_DIR
git clone --recursive https://github.com/frankaemika/libfranka
cd libfranka
git checkout 0.5.0
git submodule update
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=0 ..
cmake --build . -- -j$(nproc)

# Clone the franka_ros and panda_moveit_config repositories for simulating Panda robot
cd $WORKSPACE_DIR/src
git clone https://github.com/erdalpekel/panda_moveit_config.git
git clone --branch simulation https://github.com/erdalpekel/franka_ros.git

# Install package dependencies with rosdep
cd $WORKSPACE_DIR
rosdep install --from-paths src --ignore-src -y --skip-keys libfranka --skip-keys moveit_perception

# Clone the Visual-Studio-Code-ROS repository into the workspace directory /catkin_ws
cd $WORKSPACE_DIR
git clone git@github.com:erdalpekel/Visual-Studio-Code-ROS.git
mv Visual-Studio-Code-ROS .vscode

# create app directory for config files
mkdir $APP_DIR

The bash script handles the following steps:

Add libfranka dir to tasks.json

The last step is to add the compile directory from the scripts/docker-setup.sh script to the build task in tasks.json from the Visual-Studio-Code-ROS repository:

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "catkin_make",
            "type": "shell",
            "command": "catkin_make",
            "args": [
                "-j$(nproc)",
                # Add libfranka build dir for docker dev environment
                "-DFranka_DIR:PATH=${workspaceFolder}/dependencies/libfranka/build",
                "-DCMAKE_BUILD_TYPE=Release",
                "-DCMAKE_EXPORT_COMPILE_COMMANDS=1",
                "-DCMAKE_CXX_STANDARD=14"
            ],
            "problemMatcher": [],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        },
        {
            "label": "panda_simulation",
            "type": "shell",
            "command": "roslaunch panda_simulation simulation.launch",
            "problemMatcher": [],
            "group": {
                "kind": "test",
                "isDefault": true
            }
        }
    ]
}

Results

After installing the Visual Studio Code remote extensions clone the panda_simulation repository and the IDE will prompt a dialog to ask you if you would like to reopen the repository in a container – confirm this dialog.

The initial setup process might take up to 10 minutes depending on your internet connection but this is only done once. The Docker images will be downloaded and the initial setup script will run in order to set the workspace up.

The workspace can be built with the shortcut Ctrl + Shift + B after the startup script has finished.

After the build process finishes, source your environment and start the simulation (without a user interface):

source /catkin_ws/devel/setup.bash
roslaunch panda_simulation simulation.launch gui:=false

The gui paramter ensures that the Gazebo client gzclient and the RViz user interface are not started.

I have also added a VS Code task to the tasks.json file mentioned above, but you need to manually add the source instruction from above to the file /root/.bashrc inside the container.

The repositories Visual-Studio-Code-ROS and panda_simulation can be found on my GitHub page.

The next part of this VS Code with ROS series will be about adding user interface support to our Docker development container.