{"id":219,"date":"2019-07-14T12:30:02","date_gmt":"2019-07-14T12:30:02","guid":{"rendered":"http:\/\/erdalpekel.de\/?p=219"},"modified":"2019-07-15T09:31:31","modified_gmt":"2019-07-15T09:31:31","slug":"ros-development-with-visual-studio-code-inside-a-docker-container","status":"publish","type":"post","link":"https:\/\/erdalpekel.de\/?p=219","title":{"rendered":"ROS development with Visual Studio Code inside a Docker container"},"content":{"rendered":"\n<p>In this post I am going to extend my previously discussed approach for developing ROS packages with Visual Studio Code by utilising the new <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=ms-vscode-remote.vscode-remote-extensionpack\">remote extensions<\/a> from Microsoft that enable development in a sandboxed environment inside a Docker container.<\/p>\n\n\n\n<p>To follow along you will need to install Docker CE on your system. The official documentation offers detailed <a href=\"https:\/\/docs.docker.com\/install\/\">installation instructions<\/a> for every operating system.<\/p>\n\n\n\n<p>I will base this post on my <a href=\"https:\/\/github.com\/erdalpekel\/panda_simulation\">panda_simulation<\/a> 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.<\/p>\n\n\n\n<p>This guide is for developing and running ROS nodes that do not require a user interface for running the Gazebo simulation without <em>gzclient<\/em>, 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.<\/p>\n\n\n\n<p>In the following we will combine <a href=\"https:\/\/github.com\/erdalpekel\/panda_simulation\">panda_simulation<\/a> with my previous <a href=\"https:\/\/github.com\/erdalpekel\/Visual-Studio-Code-ROS\">Visual-Studio-Code-ROS<\/a> as a basis for integration with a Docker container.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Create configuration files<\/h2>\n\n\n\n<p>For integration with Docker we will create two files and put them inside the <strong>.devcontainer<\/strong> directory:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Dockerfile<\/strong>: The container configuration that will be used to create a container instance<\/li><li><strong>devcontainer.json<\/strong>: VS Code specific configuration for development inside a container<\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">devcontainer.json<\/h3>\n\n\n\n<p>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 <a href=\"https:\/\/code.visualstudio.com\/docs\/remote\/containers\">Visual Studio Code &#8211; Docker documentation<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"json\" class=\"language-json\">{\n    \"name\": \"panda_simulation-dev\",\n    \"dockerFile\": \"Dockerfile\",\n    \"extensions\": [\n        \"ms-vscode.cpptools\",\n        \"ms-iot.vscode-ros\"\n    ],\n    \"runArgs\": [\n        \"--cap-add=SYS_PTRACE\",\n        \"--security-opt\",\n        \"seccomp=unconfined\",\n        \"-v\",\n        \"${env:HOME}${env:USERPROFILE}\/.ssh:\/root\/.ssh\"\n    ],\n    \"settings\": {\n        \"terminal.integrated.shell.linux\": \"\/bin\/bash\"\n    },\n    \"postCreateCommand\": \"bash \/catkin_ws\/src\/panda_simulation\/scripts\/docker-setup.sh\",\n    \"workspaceMount\": \"src=\/Users\/pekel\/code\/ros\/panda_simulation,dst=\/catkin_ws\/src\/panda_simulation,type=bind,consistency=cached\",\n    \"workspaceFolder\": \"\/catkin_ws\"\n}<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>dockerFile<\/strong>: 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.<\/li><li><strong>extensions<\/strong>: The VS Code extensions that will be installed within the container for development.<\/li><li><strong>runArgs<\/strong>: Docker container run arguments. We will bind our ssh key directory as Docker volume with the <strong>-v<\/strong> paramter. This is optional and can be left out.<\/li><li><strong>postCreateCommand<\/strong>: Run additional commands after creating the container. In our case the post installation script is executed (see section below).<\/li><li><strong>workspaceMount<\/strong>: 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.<\/li><li><strong>workspaceFolder<\/strong>: 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.<\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Dockerfile<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"docker\" class=\"language-docker\">FROM osrf\/ros:melodic-desktop-full-bionic\n\nRUN apt-get update &amp;&amp; apt-get install -q -y \\\n    openssh-client\n\nRUN echo 'source \/opt\/ros\/melodic\/setup.bash' >> \/root\/.bashrc<\/code><\/pre>\n\n\n\n<ol class=\"wp-block-list\"><li>Use a ROS base image<\/li><li>Install the OpenSSH client in order to use SSH based communication with GitHub<\/li><li>Append a source instruction to <strong>~\/.bashrc<\/strong> file for <strong>catkin_make<\/strong> command usage in bash<\/li><\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Modify bash mode<\/h3>\n\n\n\n<p>In order to use catkin_make with Visual Studio Code build tasks we need to make sure that bash runs in the interactive mode (<strong>-i<\/strong>) and as the user for whom we have modified the <strong>.bashrc<\/strong> file in the <strong>Dockerfile<\/strong> (<strong>-l<\/strong>). For this we will need to add a workspace specific configuration for the bash terminal with a <strong>settings.json<\/strong> file. This file will be part of our <a href=\"https:\/\/github.com\/erdalpekel\/Visual-Studio-Code-ROS\">Visual-Studio-Code-ROS<\/a> repository.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"json\" class=\"language-json\">{\n    \"terminal.integrated.shellArgs.linux\": [\n        \"-l\",\n        \"-i\"\n    ]\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Post installation script<\/h2>\n\n\n\n<p>In order to finish the remaining steps we will create the bash script <strong>scripts\/docker-setup.sh<\/strong>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">#!\/bin\/bash\n\nREPOSITORY_DIR=$(pwd)\nWORKSPACE_DIR=\/catkin_ws\nDEPENDENCIES_DIR=$WORKSPACE_DIR\/dependencies\nAPP_DIR=\/root\/.panda_simulation\n\n# Install libfranka\nmkdir $DEPENDENCIES_DIR &amp;&amp; cd $DEPENDENCIES_DIR\ngit clone --recursive https:\/\/github.com\/frankaemika\/libfranka\ncd libfranka\ngit checkout 0.5.0\ngit submodule update\nmkdir build &amp;&amp; cd build\ncmake -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=0 ..\ncmake --build . -- -j$(nproc)\n\n# Clone the franka_ros and panda_moveit_config repositories for simulating Panda robot\ncd $WORKSPACE_DIR\/src\ngit clone https:\/\/github.com\/erdalpekel\/panda_moveit_config.git\ngit clone --branch simulation https:\/\/github.com\/erdalpekel\/franka_ros.git\n\n# Install package dependencies with rosdep\ncd $WORKSPACE_DIR\nrosdep install --from-paths src --ignore-src -y --skip-keys libfranka --skip-keys moveit_perception\n\n# Clone the Visual-Studio-Code-ROS repository into the workspace directory \/catkin_ws\ncd $WORKSPACE_DIR\ngit clone git@github.com:erdalpekel\/Visual-Studio-Code-ROS.git\nmv Visual-Studio-Code-ROS .vscode\n\n# create app directory for config files\nmkdir $APP_DIR<\/code><\/pre>\n\n\n\n<p>The bash script handles the following steps:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Install <a href=\"https:\/\/github.com\/frankaemika\/libfranka\">libfranka<\/a><\/li><li>Clone the <a href=\"https:\/\/github.com\/erdalpekel\/franka_ros.git\">franka_ros<\/a> and <a href=\"https:\/\/github.com\/erdalpekel\/panda_moveit_config.git\">panda_moveit_config<\/a> repositories for simulating Panda robot<\/li><li>Install package dependencies with <strong>rosdep<\/strong><\/li><li>Clone the <a href=\"https:\/\/github.com\/erdalpekel\/Visual-Studio-Code-ROS\">Visual-Studio-Code-ROS<\/a> repository into the workspace directory <em>\/catkin_ws<\/em><\/li><li>Create the app directory <strong>\/root\/.panda_simulation\/<\/strong> for configuration files<\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Add libfranka dir to tasks.json<\/h3>\n\n\n\n<p>The last step is to add the compile directory from the <strong>scripts\/docker-setup.sh<\/strong> script to the build task in <strong>tasks.json<\/strong> from the <a href=\"https:\/\/github.com\/erdalpekel\/Visual-Studio-Code-ROS\">Visual-Studio-Code-ROS<\/a> repository:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"json\" class=\"language-json\">{\n    \/\/ See https:\/\/go.microsoft.com\/fwlink\/?LinkId=733558\n    \/\/ for the documentation about the tasks.json format\n    \"version\": \"2.0.0\",\n    \"tasks\": [\n        {\n            \"label\": \"catkin_make\",\n            \"type\": \"shell\",\n            \"command\": \"catkin_make\",\n            \"args\": [\n                \"-j$(nproc)\",\n                # Add libfranka build dir for docker dev environment\n                \"-DFranka_DIR:PATH=${workspaceFolder}\/dependencies\/libfranka\/build\",\n                \"-DCMAKE_BUILD_TYPE=Release\",\n                \"-DCMAKE_EXPORT_COMPILE_COMMANDS=1\",\n                \"-DCMAKE_CXX_STANDARD=14\"\n            ],\n            \"problemMatcher\": [],\n            \"group\": {\n                \"kind\": \"build\",\n                \"isDefault\": true\n            }\n        },\n        {\n            \"label\": \"panda_simulation\",\n            \"type\": \"shell\",\n            \"command\": \"roslaunch panda_simulation simulation.launch\",\n            \"problemMatcher\": [],\n            \"group\": {\n                \"kind\": \"test\",\n                \"isDefault\": true\n            }\n        }\n    ]\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Results<\/h2>\n\n\n\n<p>After installing the Visual Studio Code <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=ms-vscode-remote.vscode-remote-extensionpack\">remote extensions<\/a> clone the <a href=\"https:\/\/github.com\/erdalpekel\/panda_simulation\">panda_simulation<\/a> repository and the IDE will prompt a dialog to ask you if you would like to reopen the repository in a container &#8211; confirm this dialog.<\/p>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>The workspace can be built with the shortcut <code>Ctrl + Shift + B<\/code> after the startup script has finished.<\/p>\n\n\n\n<p>After the build process finishes, source your environment and start the simulation (without a user interface):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">source \/catkin_ws\/devel\/setup.bash\nroslaunch panda_simulation simulation.launch gui:=false<\/code><\/pre>\n\n\n\n<p>The <em>gui<\/em> paramter ensures that the Gazebo client <em>gzclient<\/em> and the RViz user interface are not started.<\/p>\n\n\n\n<p>I have also added a VS Code task to the <strong>tasks.json<\/strong> file mentioned above, but you need to manually add the source instruction from above to the file <strong>\/root\/.bashrc<\/strong> inside the container.<\/p>\n\n\n\n<p>The repositories <a href=\"https:\/\/github.com\/erdalpekel\/Visual-Studio-Code-ROS\">Visual-Studio-Code-ROS<\/a> and <a href=\"https:\/\/github.com\/erdalpekel\/panda_simulation\">panda_simulation<\/a> can be found on my GitHub <a href=\"https:\/\/github.com\/erdalpekel\">page<\/a>.<\/p>\n\n\n\n<p>The next part of this <em>VS Code with ROS<\/em> series will be about adding user interface support to our Docker development container.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this post I am going to share my workflow for using Visual Studio Code as a development environment for ROS within a Docker container.<\/p>\n","protected":false},"author":1,"featured_media":220,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21,20,8],"tags":[],"class_list":["post-219","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-docker","category-ide","category-ros"],"_links":{"self":[{"href":"https:\/\/erdalpekel.de\/index.php?rest_route=\/wp\/v2\/posts\/219","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/erdalpekel.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/erdalpekel.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/erdalpekel.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/erdalpekel.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=219"}],"version-history":[{"count":39,"href":"https:\/\/erdalpekel.de\/index.php?rest_route=\/wp\/v2\/posts\/219\/revisions"}],"predecessor-version":[{"id":264,"href":"https:\/\/erdalpekel.de\/index.php?rest_route=\/wp\/v2\/posts\/219\/revisions\/264"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/erdalpekel.de\/index.php?rest_route=\/wp\/v2\/media\/220"}],"wp:attachment":[{"href":"https:\/\/erdalpekel.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=219"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/erdalpekel.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=219"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/erdalpekel.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=219"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}