├── templates
├── ros
│ ├── .gitignore
│ ├── docker
│ │ ├── .env
│ │ ├── docker-compose-nvidia.yml
│ │ ├── docker-compose-gui-nvidia.yml
│ │ ├── docker-compose-vscode.yml
│ │ ├── docker-compose-gui.yml
│ │ ├── docker-compose.yml
│ │ └── Dockerfile
│ ├── src
│ │ └── .repos
│ ├── .vscode
│ │ ├── launch.json
│ │ ├── c_cpp_properties.json
│ │ └── tasks.json
│ ├── .devcontainer
│ │ └── devcontainer.json
│ └── ReadMe.md
├── ros2
│ ├── .gitignore
│ ├── .vscode
│ │ ├── settings.json
│ │ ├── launch.json
│ │ ├── c_cpp_properties.json
│ │ └── tasks.json
│ ├── src
│ │ └── .repos
│ ├── docker
│ │ ├── .env
│ │ ├── docker-compose-nvidia.yml
│ │ ├── docker-compose-gui-nvidia.yml
│ │ ├── docker-compose-vscode.yml
│ │ ├── docker-compose-gui.yml
│ │ ├── docker-compose.yml
│ │ └── Dockerfile
│ ├── .devcontainer
│ │ └── devcontainer.json
│ ├── dds
│ │ └── cyclone.xml
│ └── ReadMe.md
└── ReadMe.md
├── media
├── glxgears.png
├── rviz_mesa_bug.png
├── windows10_rviz.png
├── nvidia_x_server.png
├── ubuntu_software_and_updates.png
├── windows10_affordance_templates.png
├── ubuntu_jammy_affordance_templates.png
├── visual_studio_code_terminal_tasks.png
├── visual_studio_code_terminal_tasks_list.png
├── visual_studio_code_dev_containers_on_start.png
├── visual_studio_code_dev_containers_terminal.png
├── visual_studio_code_dev_containers_after_install.png
├── visual_studio_code_dev_containers_before_install.png
└── visual_studio_code_dev_containers_reopen_in_container.png
├── examples
├── lpms-ros-docker
│ ├── media
│ │ └── preview.png
│ ├── docker
│ │ ├── docker-compose-nvidia.yml
│ │ ├── docker-compose.yml
│ │ ├── docker-compose-gui-nvidia.yml
│ │ ├── docker-compose-gui.yml
│ │ └── Dockerfile
│ ├── .devcontainer
│ │ └── devcontainer.json
│ └── ReadMe.md
├── affordance-templates-ros-docker
│ ├── media
│ │ └── preview.png
│ ├── docker
│ │ ├── docker-compose.yml
│ │ ├── docker-compose-gui.yml
│ │ └── Dockerfile
│ ├── .devcontainer
│ │ └── devcontainer.json
│ ├── src
│ │ └── at_r2_bringup
│ │ │ ├── CMakeLists.txt
│ │ │ ├── launch
│ │ │ └── demo.launch
│ │ │ ├── package.xml
│ │ │ └── config
│ │ │ └── at_r2_moveit.rviz
│ └── ReadMe.md
└── ReadMe.md
├── .github
└── workflows
│ ├── build-ros.yml
│ └── build-ros2.yml
├── License.md
├── .gitmodules
├── ReadMe.md
└── doc
├── VisualStudioCodeSetup.md
├── Windows.md
├── WorkingWithHardware.md
├── AdvancedTopics.md
├── Motivation.md
├── Gui.md
├── Ros.md
└── Introduction.md
/templates/ros/.gitignore:
--------------------------------------------------------------------------------
1 | src/*
2 | !src/.repos
3 |
--------------------------------------------------------------------------------
/templates/ros2/.gitignore:
--------------------------------------------------------------------------------
1 | src/*
2 | !src/.repos
3 |
--------------------------------------------------------------------------------
/media/glxgears.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2b-t/docker-for-robotics/HEAD/media/glxgears.png
--------------------------------------------------------------------------------
/media/rviz_mesa_bug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2b-t/docker-for-robotics/HEAD/media/rviz_mesa_bug.png
--------------------------------------------------------------------------------
/media/windows10_rviz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2b-t/docker-for-robotics/HEAD/media/windows10_rviz.png
--------------------------------------------------------------------------------
/media/nvidia_x_server.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2b-t/docker-for-robotics/HEAD/media/nvidia_x_server.png
--------------------------------------------------------------------------------
/media/ubuntu_software_and_updates.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2b-t/docker-for-robotics/HEAD/media/ubuntu_software_and_updates.png
--------------------------------------------------------------------------------
/media/windows10_affordance_templates.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2b-t/docker-for-robotics/HEAD/media/windows10_affordance_templates.png
--------------------------------------------------------------------------------
/examples/lpms-ros-docker/media/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2b-t/docker-for-robotics/HEAD/examples/lpms-ros-docker/media/preview.png
--------------------------------------------------------------------------------
/media/ubuntu_jammy_affordance_templates.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2b-t/docker-for-robotics/HEAD/media/ubuntu_jammy_affordance_templates.png
--------------------------------------------------------------------------------
/media/visual_studio_code_terminal_tasks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2b-t/docker-for-robotics/HEAD/media/visual_studio_code_terminal_tasks.png
--------------------------------------------------------------------------------
/templates/ros2/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "pylint.args": [
3 | ],
4 | "mypy-type-checker.args": [
5 | "--strict"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/templates/ros2/src/.repos:
--------------------------------------------------------------------------------
1 | repositories:
2 | examples:
3 | type: git
4 | url: https://github.com/ros2/examples.git
5 | version: humble
6 |
--------------------------------------------------------------------------------
/media/visual_studio_code_terminal_tasks_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2b-t/docker-for-robotics/HEAD/media/visual_studio_code_terminal_tasks_list.png
--------------------------------------------------------------------------------
/templates/ros/docker/.env:
--------------------------------------------------------------------------------
1 | CATKIN_WORKSPACE_DIR=/catkin_ws
2 | YOUR_IP=127.0.0.1
3 | ROBOT_IP=127.0.0.1
4 | ROBOT_HOSTNAME=P500
5 | UID=1000
6 | GID=1000
7 |
--------------------------------------------------------------------------------
/templates/ros/src/.repos:
--------------------------------------------------------------------------------
1 | repositories:
2 | tutorials:
3 | type: git
4 | url: https://github.com/ros/ros_tutorials.git
5 | version: noetic-devel
6 |
--------------------------------------------------------------------------------
/media/visual_studio_code_dev_containers_on_start.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2b-t/docker-for-robotics/HEAD/media/visual_studio_code_dev_containers_on_start.png
--------------------------------------------------------------------------------
/media/visual_studio_code_dev_containers_terminal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2b-t/docker-for-robotics/HEAD/media/visual_studio_code_dev_containers_terminal.png
--------------------------------------------------------------------------------
/examples/affordance-templates-ros-docker/media/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2b-t/docker-for-robotics/HEAD/examples/affordance-templates-ros-docker/media/preview.png
--------------------------------------------------------------------------------
/media/visual_studio_code_dev_containers_after_install.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2b-t/docker-for-robotics/HEAD/media/visual_studio_code_dev_containers_after_install.png
--------------------------------------------------------------------------------
/media/visual_studio_code_dev_containers_before_install.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2b-t/docker-for-robotics/HEAD/media/visual_studio_code_dev_containers_before_install.png
--------------------------------------------------------------------------------
/templates/ros2/docker/.env:
--------------------------------------------------------------------------------
1 | AMENT_WORKSPACE_DIR=/ament_ws
2 | ROS_DOMAIN_ID=0
3 | YOUR_IP=127.0.0.1
4 | ROBOT_IP=127.0.0.1
5 | ROBOT_HOSTNAME=P500
6 | UID=1000
7 | GID=1000
8 |
--------------------------------------------------------------------------------
/media/visual_studio_code_dev_containers_reopen_in_container.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2b-t/docker-for-robotics/HEAD/media/visual_studio_code_dev_containers_reopen_in_container.png
--------------------------------------------------------------------------------
/templates/ros/docker/docker-compose-nvidia.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 | services:
3 | ros_docker:
4 | extends:
5 | file: docker-compose.yml
6 | service: ros_docker
7 | environment:
8 | - NVIDIA_VISIBLE_DEVICES=all
9 | runtime: nvidia
10 |
11 |
--------------------------------------------------------------------------------
/examples/lpms-ros-docker/docker/docker-compose-nvidia.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 | services:
3 | lpms_ros:
4 | extends:
5 | file: docker-compose.yml
6 | service: lpms_ros
7 | environment:
8 | - NVIDIA_VISIBLE_DEVICES=all
9 | runtime: nvidia
10 |
--------------------------------------------------------------------------------
/templates/ros2/docker/docker-compose-nvidia.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 | services:
3 | ros2_docker:
4 | extends:
5 | file: docker-compose.yml
6 | service: ros2_docker
7 | environment:
8 | - NVIDIA_VISIBLE_DEVICES=all
9 | runtime: nvidia
10 |
11 |
--------------------------------------------------------------------------------
/examples/lpms-ros-docker/docker/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 | services:
3 | lpms_ros:
4 | build:
5 | context: ..
6 | dockerfile: docker/Dockerfile
7 | tty: true
8 | volumes:
9 | - /dev:/dev
10 | device_cgroup_rules:
11 | - 'c 188:* rmw'
12 |
13 |
--------------------------------------------------------------------------------
/examples/lpms-ros-docker/docker/docker-compose-gui-nvidia.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 | services:
3 | lpms_ros:
4 | extends:
5 | file: docker-compose-gui.yml
6 | service: lpms_ros
7 | environment:
8 | - NVIDIA_VISIBLE_DEVICES=all
9 | - NVIDIA_DRIVER_CAPABILITIES=all
10 | runtime: nvidia
11 |
--------------------------------------------------------------------------------
/templates/ros/docker/docker-compose-gui-nvidia.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 | services:
3 | ros_docker:
4 | extends:
5 | file: docker-compose-gui.yml
6 | service: ros_docker
7 | environment:
8 | - NVIDIA_VISIBLE_DEVICES=all
9 | - NVIDIA_DRIVER_CAPABILITIES=all
10 | runtime: nvidia
11 |
12 |
--------------------------------------------------------------------------------
/templates/ros2/docker/docker-compose-gui-nvidia.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 | services:
3 | ros2_docker:
4 | extends:
5 | file: docker-compose-gui.yml
6 | service: ros2_docker
7 | environment:
8 | - NVIDIA_VISIBLE_DEVICES=all
9 | - NVIDIA_DRIVER_CAPABILITIES=all
10 | runtime: nvidia
11 |
12 |
--------------------------------------------------------------------------------
/examples/affordance-templates-ros-docker/docker/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 | services:
3 | affordance_templates:
4 | build:
5 | context: ..
6 | dockerfile: docker/Dockerfile
7 | container_name: affordance_templates
8 | tty: true
9 | volumes:
10 | - ../src:/affordance_templates_ws/src
11 |
12 |
--------------------------------------------------------------------------------
/templates/ros/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "ROS: Attach",
5 | "type": "ros",
6 | "request": "attach"
7 | },
8 | {
9 | "name": "ROS: Attach to Python",
10 | "type": "ros",
11 | "request": "attach",
12 | "runtime": "Python"
13 | }
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/templates/ros2/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "ROS: Attach",
5 | "type": "ros",
6 | "request": "attach"
7 | },
8 | {
9 | "name": "ROS: Attach to Python",
10 | "type": "ros",
11 | "request": "attach",
12 | "runtime": "Python"
13 | }
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/templates/ros/docker/docker-compose-vscode.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 | services:
3 | ros_docker:
4 | extends:
5 | file: docker-compose-gui.yml
6 | service: ros_docker
7 | cap_add:
8 | # Required for GDB debugging with ROS extension
9 | - SYS_PTRACE
10 | volumes:
11 | - ../.vscode:${CATKIN_WORKSPACE_DIR}/.vscode
12 |
13 |
--------------------------------------------------------------------------------
/templates/ros2/docker/docker-compose-vscode.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 | services:
3 | ros2_docker:
4 | extends:
5 | file: docker-compose-gui.yml
6 | service: ros2_docker
7 | cap_add:
8 | # Required for GDB debugging with ROS extension
9 | - SYS_PTRACE
10 | volumes:
11 | - ../.vscode:${AMENT_WORKSPACE_DIR}/.vscode
12 |
13 |
--------------------------------------------------------------------------------
/examples/lpms-ros-docker/docker/docker-compose-gui.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 | services:
3 | lpms_ros:
4 | extends:
5 | file: docker-compose.yml
6 | service: lpms_ros
7 | environment:
8 | - DISPLAY=${DISPLAY}
9 | - QT_X11_NO_MITSHM=1
10 | volumes:
11 | - /tmp/.X11-unix:/tmp/.X11-unix:rw
12 | - /tmp/.docker.xauth:/tmp/.docker.xauth:rw
13 |
--------------------------------------------------------------------------------
/templates/ros/docker/docker-compose-gui.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 | services:
3 | ros_docker:
4 | extends:
5 | file: docker-compose.yml
6 | service: ros_docker
7 | environment:
8 | - DISPLAY=${DISPLAY}
9 | - QT_X11_NO_MITSHM=1
10 | volumes:
11 | - /tmp/.X11-unix:/tmp/.X11-unix:rw
12 | - /tmp/.docker.xauth:/tmp/.docker.xauth:rw
13 |
14 |
--------------------------------------------------------------------------------
/templates/ros2/docker/docker-compose-gui.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 | services:
3 | ros2_docker:
4 | extends:
5 | file: docker-compose.yml
6 | service: ros2_docker
7 | environment:
8 | - DISPLAY=${DISPLAY}
9 | - QT_X11_NO_MITSHM=1
10 | volumes:
11 | - /tmp/.X11-unix:/tmp/.X11-unix:rw
12 | - /tmp/.docker.xauth:/tmp/.docker.xauth:rw
13 |
14 |
--------------------------------------------------------------------------------
/examples/affordance-templates-ros-docker/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Affordance templates Docker",
3 | "dockerComposeFile": [
4 | "../docker/docker-compose-gui.yml" // Alternative: "../docker/docker-compose-gui.yml"
5 | ],
6 | "service": "affordance_templates",
7 | "workspaceFolder": "/affordance_templates_ws",
8 | "shutdownAction": "stopCompose"
9 | }
10 |
--------------------------------------------------------------------------------
/examples/lpms-ros-docker/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Docker for LPMS IMU",
3 | "dockerComposeFile": [
4 | "../docker/docker-compose-gui.yml" // Alternatives: "../docker/docker-compose-gui.yml", "../docker/docker-compose-gui-nvidia.yml"
5 | ],
6 | "service": "lpms_ros",
7 | "workspaceFolder": "/lpms_ws",
8 | "shutdownAction": "stopCompose",
9 | "extensions": [
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/examples/affordance-templates-ros-docker/docker/docker-compose-gui.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 | services:
3 | affordance_templates:
4 | extends:
5 | file: docker-compose.yml
6 | service: affordance_templates
7 | environment:
8 | - DISPLAY=${DISPLAY}
9 | - QT_X11_NO_MITSHM=1
10 | volumes:
11 | - /tmp/.X11-unix:/tmp/.X11-unix:rw
12 | - /tmp/.docker.xauth:/tmp/.docker.xauth:rw
13 |
--------------------------------------------------------------------------------
/examples/affordance-templates-ros-docker/src/at_r2_bringup/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.3)
2 | project(at_r2_bringup)
3 |
4 | find_package(catkin REQUIRED COMPONENTS
5 | )
6 |
7 | catkin_package(
8 | CATKIN_DEPENDS
9 | )
10 |
11 | install(DIRECTORY config
12 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/config
13 | )
14 |
15 | install(DIRECTORY launch
16 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
17 | )
18 |
19 |
--------------------------------------------------------------------------------
/examples/affordance-templates-ros-docker/src/at_r2_bringup/launch/demo.launch:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/templates/ros/.vscode/c_cpp_properties.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "Linux",
5 | "includePath": [
6 | "${workspaceFolder}/**",
7 | "/opt/ros/${env:ROS_DISTRO}/include/**",
8 | "/usr/include/**"
9 | ],
10 | "defines": [],
11 | "compilerPath": "/usr/bin/g++",
12 | "cStandard": "c11",
13 | "cppStandard": "c++17",
14 | "intelliSenseMode": "gcc-x64"
15 | }
16 | ],
17 | "version": 4
18 | }
19 |
--------------------------------------------------------------------------------
/templates/ros2/.vscode/c_cpp_properties.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "Linux",
5 | "includePath": [
6 | "${workspaceFolder}/**",
7 | "/opt/ros/${env:ROS_DISTRO}/include/**",
8 | "/usr/include/**"
9 | ],
10 | "defines": [],
11 | "compilerPath": "/usr/bin/g++",
12 | "cStandard": "c11",
13 | "cppStandard": "c++17",
14 | "intelliSenseMode": "gcc-x64"
15 | }
16 | ],
17 | "version": 4
18 | }
19 |
--------------------------------------------------------------------------------
/templates/ReadMe.md:
--------------------------------------------------------------------------------
1 | # ROS and ROS 2 Docker Templates
2 |
3 | Author: [Tobit Flatscher](https://github.com/2b-t) (2021 - 2025)
4 |
5 |
6 |
7 | ## Overview
8 |
9 | This directory contains a **ROS Noetic** as well as a **ROS 2 Jazzy Docker workspace** template that should allow you to get started quickly with the best practices given in the documentation of this repository. The individual subdirectories contain a read-me that explains what settings can be made to the corresponding workspaces.
10 |
--------------------------------------------------------------------------------
/templates/ros/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ROS Docker",
3 | "dockerComposeFile": [
4 | "../docker/docker-compose-vscode.yml"
5 | ],
6 | "service": "ros_docker",
7 | "workspaceFolder": "/catkin_ws",
8 | "shutdownAction": "stopCompose",
9 | "customizations": {
10 | "vscode": {
11 | "extensions": [
12 | "ms-iot.vscode-ros",
13 | "ms-python.python",
14 | "ms-vscode.cmake-tools",
15 | "ms-vscode.cpptools"
16 | ]
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/.github/workflows/build-ros.yml:
--------------------------------------------------------------------------------
1 | name: ROS Docker
2 |
3 | on:
4 | push:
5 | paths:
6 | - 'templates/ros/docker/Dockerfile'
7 | - 'templates/ros/docker/docker-compose.yml'
8 | schedule:
9 | - cron: "0 12 1 * *"
10 | workflow_dispatch:
11 |
12 | jobs:
13 | docker-compose-build:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - name: Checkout code
17 | uses: actions/checkout@v4
18 | - name: Build the Dockerfile with Docker-Compose
19 | run: docker compose -f templates/ros/docker/docker-compose.yml build
20 |
21 |
--------------------------------------------------------------------------------
/.github/workflows/build-ros2.yml:
--------------------------------------------------------------------------------
1 | name: ROS 2 Docker
2 |
3 | on:
4 | push:
5 | paths:
6 | - 'templates/ros2/docker/Dockerfile'
7 | - 'templates/ros2/docker/docker-compose.yml'
8 | schedule:
9 | - cron: "0 12 1 * *"
10 | workflow_dispatch:
11 |
12 | jobs:
13 | docker-compose-build:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - name: Checkout code
17 | uses: actions/checkout@v4
18 | - name: Build the Dockerfile with Docker-Compose
19 | run: docker compose -f templates/ros2/docker/docker-compose.yml build
20 |
21 |
--------------------------------------------------------------------------------
/templates/ros2/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ROS2 Docker",
3 | "dockerComposeFile": [
4 | "../docker/docker-compose-vscode.yml"
5 | ],
6 | "service": "ros2_docker",
7 | "workspaceFolder": "/ament_ws",
8 | "shutdownAction": "stopCompose",
9 | "customizations": {
10 | "vscode": {
11 | "extensions": [
12 | "ms-iot.vscode-ros",
13 | "ms-python.mypy-type-checker",
14 | "ms-python.pylint",
15 | "ms-python.python",
16 | "ms-vscode.cmake-tools",
17 | "ms-vscode.cpptools"
18 | ]
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/examples/affordance-templates-ros-docker/src/at_r2_bringup/package.xml:
--------------------------------------------------------------------------------
1 |
2 | at_r2_bringup
3 | 0.0.1
4 | Configuration and launch files for affordance-templates with the NASA Robonaut2
5 | Tobit Flatscher
6 | Tobit Flatscher
7 | MIT
8 |
9 | catkin
10 | affordance_template_server
11 | r2_gazebo
12 | r2_moveit_config
13 |
14 |
--------------------------------------------------------------------------------
/examples/lpms-ros-docker/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ros:noetic-robot
2 |
3 | ENV WS_DIR="/lpms_ws"
4 | WORKDIR ${WS_DIR}
5 |
6 | SHELL ["/bin/bash", "-c"]
7 |
8 | ARG DEBIAN_FRONTEND=noninteractive
9 |
10 | RUN apt-get update \
11 | && apt-get install -y \
12 | build-essential \
13 | cmake \
14 | git-all \
15 | software-properties-common \
16 | && rm -rf /var/lib/apt/lists/*
17 |
18 | RUN apt-get update \
19 | && apt-get install -y \
20 | ros-${ROS_DISTRO}-openzen-sensor \
21 | ros-${ROS_DISTRO}-rviz \
22 | ros-${ROS_DISTRO}-rviz-imu-plugin \
23 | ros-${ROS_DISTRO}-rviz-plugin-tutorials \
24 | && rm -rf /var/lib/apt/lists/*
25 |
26 | ARG DEBIAN_FRONTEND=dialog
27 |
--------------------------------------------------------------------------------
/templates/ros2/dds/cyclone.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | auto
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
16 | true
17 |
18 |
19 |
20 | default
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/templates/ros/docker/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 | services:
3 | ros_docker:
4 | build:
5 | context: ..
6 | dockerfile: docker/Dockerfile
7 | target: dev
8 | args:
9 | - CATKIN_WORKSPACE_DIR=${CATKIN_WORKSPACE_DIR}
10 | - USERNAME=${USERNAME:-developer}
11 | - UID=${UID}
12 | - GID=${GID}
13 | container_name: ros_docker
14 | environment:
15 | - ROS_MASTER_URI=http://${ROBOT_IP}:11311
16 | - ROS_IP=${YOUR_IP}
17 | extra_hosts:
18 | - "${ROBOT_HOSTNAME}:${ROBOT_IP}"
19 | # Required for communicating over the network
20 | network_mode: "host"
21 | # Required for accessing hardware
22 | #privileged: true
23 | tty: true
24 | volumes:
25 | # Required for accessing hardware
26 | #- /dev:/dev
27 | # Required for accessing storage media
28 | #- /media:/media
29 | - ../src:${CATKIN_WORKSPACE_DIR}/src
30 |
31 |
--------------------------------------------------------------------------------
/examples/affordance-templates-ros-docker/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM osrf/ros:indigo-desktop-full
2 |
3 | ENV ROS_WS_DIR="/affordance_templates_ws"
4 | WORKDIR ${ROS_WS_DIR}
5 |
6 | SHELL ["/bin/bash", "-c"]
7 |
8 | ENV DEBIAN_FRONTEND=noninteractive
9 |
10 | RUN apt-get update \
11 | && apt-get -y install \
12 | git \
13 | libboost-dev \
14 | libdw-dev \
15 | libqt5svg5-dev \
16 | libzmq3-dev \
17 | python-catkin-tools \
18 | qtbase5-dev \
19 | && rm -rf /var/lib/apt/lists/*
20 |
21 | RUN apt-get update \
22 | && apt-get -y install \
23 | ros-${ROS_DISTRO}-control* \
24 | ros-${ROS_DISTRO}-gazebo-plugins \
25 | ros-${ROS_DISTRO}-gazebo-ros-control* \
26 | ros-${ROS_DISTRO}-moveit* \
27 | ros-${ROS_DISTRO}-navigation \
28 | ros-${ROS_DISTRO}-object-recognition-ros \
29 | ros-${ROS_DISTRO}-octomap-rviz-plugins \
30 | ros-${ROS_DISTRO}-orocos-kdl \
31 | ros-${ROS_DISTRO}-ros-control* \
32 | ros-${ROS_DISTRO}-rqt \
33 | ros-${ROS_DISTRO}-simulators \
34 | ros-${ROS_DISTRO}-trac-ik* \
35 | && rm -rf /var/lib/apt/lists/*
36 |
37 | ENV DEBIAN_FRONTEND=dialog
38 |
39 |
--------------------------------------------------------------------------------
/License.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Tobit Flatscher
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "examples/docker-realtime"]
2 | path = examples/docker-realtime
3 | url = https://github.com/2b-t/docker-realtime
4 | [submodule "examples/realsense-ros2-docker"]
5 | path = examples/realsense-ros2-docker
6 | url = https://github.com/2b-t/realsense-ros2-docker
7 | [submodule "examples/velodyne-ros2-docker"]
8 | path = examples/velodyne-ros2-docker
9 | url = https://github.com/2b-t/velodyne-ros2-docker
10 | [submodule "examples/affordance-templates-ros-docker/src/affordance_templates"]
11 | path = examples/affordance-templates-ros-docker/src/affordance_templates
12 | url = https://bitbucket.org/traclabs/affordance_templates.git
13 | [submodule "examples/affordance-templates-ros-docker/src/nasa_r2_common"]
14 | path = examples/affordance-templates-ros-docker/src/nasa_r2_common
15 | url = https://bitbucket.org/traclabs/nasa_r2_common.git
16 | [submodule "examples/affordance-templates-ros-docker/src/nasa_r2_simulator"]
17 | path = examples/affordance-templates-ros-docker/src/nasa_r2_simulator
18 | url = https://bitbucket.org/traclabs/nasa_r2_simulator.git
19 | [submodule "examples/affordance-templates-ros-docker/src/robot_interaction_tools"]
20 | path = examples/affordance-templates-ros-docker/src/robot_interaction_tools
21 | url = https://bitbucket.org/traclabs/robot_interaction_tools.git
22 |
--------------------------------------------------------------------------------
/examples/ReadMe.md:
--------------------------------------------------------------------------------
1 | # Examples
2 |
3 | Author: [Tobit Flatscher](https://github.com/2b-t) (March - May 2023)
4 |
5 |
6 |
7 | ## Overview
8 |
9 | This directory contains several examples of Docker in combination with ROS:
10 |
11 | - The ROS Indigo workspace [`affordance-templates-ros-docker`](./affordance-templates-ros-docker) shows how Docker can be used to **revive an old ROS workspace** that would require an outdated operating system to run.
12 | - The repository [`docker-realtime`](./docker-realtime) explains how to **set-up a computer with a real-time-patched operating systems** ([`PREEMPT_RT`-patch](https://archive.kernel.org/oldwiki/rt.wiki.kernel.org/index.php/CONFIG_PREEMPT_RT_Patch.html)) and how to run real-time capable code from inside a Docker container.
13 | - The workspace [`lpms-ros-docker`](./lpms-ros-docker) and the repository [`realsense-ros2-docker`](./realsense-ros2-docker) show how to give access to **external hardware connected via USB** to a Docker with examples for a [**Life Performance Research IMU**](https://www.lp-research.com/) as well as [**Intel Realsense sensors**](https://www.intelrealsense.com/), such as their depth cameras.
14 | - The repository [`velodyne-ros2-docker`](./velodyne-ros2-docker) shows how to give access to **devices connected over Ethernet** to a Docker using the example of a [**Velodyne 3D lidar**](https://velodynelidar.com/).
15 |
--------------------------------------------------------------------------------
/templates/ros2/docker/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 | services:
3 | ros2_docker:
4 | build:
5 | context: ..
6 | dockerfile: docker/Dockerfile
7 | target: dev
8 | args:
9 | - AMENT_WORKSPACE_DIR=${AMENT_WORKSPACE_DIR}
10 | - USERNAME=${USERNAME:-developer}
11 | - UID=${UID}
12 | - GID=${GID}
13 | container_name: ros2_docker
14 | environment:
15 | - ROS_DOMAIN_ID=${ROS_DOMAIN_ID}
16 | # Limit ROS communication to local computer only
17 | #- ROS_LOCALHOST_ONLY=1
18 | - YOUR_IP=${YOUR_IP}
19 | - ROBOT_IP=${ROBOT_IP}
20 | - RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
21 | # Configure Cyclone with a custom configuration using the IPs above
22 | #- CYCLONEDDS_URI=${AMENT_WORKSPACE_DIR}/dds/cyclone.xml
23 | extra_hosts:
24 | - "${ROBOT_HOSTNAME}:${ROBOT_IP}"
25 | # Required for communicating over the network
26 | network_mode: "host"
27 | # Required for accessing hardware
28 | #privileged: true
29 | tty: true
30 | volumes:
31 | # Required for accessing hardware
32 | #- /dev:/dev
33 | # Required for accessing storage media
34 | #- /media:/media
35 | - ../src:${AMENT_WORKSPACE_DIR}/src
36 | - ../dds:${AMENT_WORKSPACE_DIR}/dds
37 | # Required for ROS 2 shared memory communication
38 | #- /dev/shm:/dev/shm
39 |
40 |
--------------------------------------------------------------------------------
/examples/lpms-ros-docker/ReadMe.md:
--------------------------------------------------------------------------------
1 | # Docker for LP-Research IMUs
2 |
3 | Author: [Tobit Flatscher](https://github.com/2b-t) (May 2023)
4 |
5 |
6 |
7 | ## 0. Overview
8 | This repository contains a Docker and all the documentation required to launch a RS232/USB [Life Performance Research IMU](https://www.lp-research.com/lpms-inertial-measurement-unit-imu-series/) connected over USB with the [Robot Operating System ROS](http://wiki.ros.org/noetic). It was tested with a [LPMS-IG1](https://www.lp-research.com/9-axis-imu-with-gps-receiver-series/).
9 |
10 | ## 1. Creating a Docker
11 | It is then important to mount `/dev` as a volume so that the Docker can access the hardware and allow the Docker to access the corresponding allocated devices by supplying a corresponding [`device_cgroup_rules`](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/resource_management_guide/sec-devices).
12 |
13 | In the `docker-compose.yml` this is done with the options:
14 |
15 | ```yaml
16 | volumes:
17 | - /dev:/dev
18 | device_cgroup_rules:
19 | - 'c 188:* rmw'
20 | ```
21 |
22 | ## 2. Launching
23 | Allow the container to display contents on your host machine by typing
24 |
25 | ```bash
26 | $ xhost +local:root
27 | ```
28 |
29 | Then build the Docker container with
30 |
31 | ```shell
32 | $ docker compose -f docker-compose-gui.yml build
33 | ```
34 | or directly with the [`devcontainer` in Visual Studio Code](https://code.visualstudio.com/docs/devcontainers/containers). For Nvidia graphic cards the file `docker-compose-gui-nvidia.yml` in combination with the [`nvidia-container-runtime`](https://nvidia.github.io/nvidia-container-runtime/) has to be used instead.
35 | After it is done building **connect the IMU**, start the container
36 |
37 | ```shell
38 | $ docker compose -f docker-compose-gui.yml up
39 | ```
40 | Open a new console and start a ROS master with
41 | ```shell
42 | $ source /opt/ros/noetic/setup.bash
43 | $ roscore
44 | ```
45 | Open another terminal and start the [**driver**](https://bitbucket.org/lpresearch/openzenros/src/master/) with
46 | ```shell
47 | $ source /opt/ros/noetic/setup.bash
48 | $ rosrun openzen_sensor openzen_sensor_node
49 | ```
50 | Finally start the **visualization** from yet another terminal inside the Docker
51 | ```shell
52 | $ source /opt/ros/noetic/setup.bash
53 | $ rosrun rviz rviz
54 | ```
55 | Set the fixed frame to `imu` and display the `/imu/data`:
56 |
57 | 
58 |
59 |
--------------------------------------------------------------------------------
/templates/ros/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | ##############
2 | # Base image #
3 | ##############
4 | FROM ros:noetic-robot AS base
5 |
6 | ARG CATKIN_WORKSPACE_DIR="/catkin_ws"
7 |
8 | LABEL org.opencontainers.image.authors="tobit.flatscher@outlook.com"
9 | LABEL description="ROS Noetic Docker template"
10 | LABEL version="1.0"
11 |
12 | WORKDIR ${CATKIN_WORKSPACE_DIR}
13 | SHELL ["/bin/bash", "-c"]
14 |
15 | ENV DEBIAN_FRONTEND=noninteractive
16 |
17 | RUN apt-get update \
18 | && apt-get -y install \
19 | git \
20 | python3-catkin-tools \
21 | python3-osrf-pycommon \
22 | && rm -rf /var/lib/apt/lists/*
23 |
24 | RUN apt-get update \
25 | && apt-get -y install \
26 | ros-${ROS_DISTRO}-compressed-image-transport \
27 | ros-${ROS_DISTRO}-compressed-depth-image-transport \
28 | ros-${ROS_DISTRO}-image-transport \
29 | && rm -rf /var/lib/apt/lists/*
30 |
31 | # Add additional installation instructions here...
32 |
33 | ENV DEBIAN_FRONTEND=dialog
34 |
35 |
36 | #####################
37 | # Development image #
38 | #####################
39 | FROM base AS dev
40 |
41 | ARG CATKIN_WORKSPACE_DIR="/catkin_ws"
42 | ARG USERNAME="developer"
43 | ARG UID=1000
44 | ARG GID=1000
45 |
46 | ENV DEBIAN_FRONTEND=noninteractive
47 |
48 | RUN apt-get update \
49 | && apt-get install -y \
50 | ack \
51 | bmon \
52 | cloc \
53 | gdb \
54 | htop \
55 | iperf3 \
56 | iputils-ping \
57 | mlocate \
58 | net-tools \
59 | psmisc \
60 | tmux \
61 | xterm \
62 | && rm -rf /var/lib/apt/lists/*
63 |
64 | RUN apt-get update \
65 | && apt-get install -y \
66 | python3-vcstool \
67 | ros-${ROS_DISTRO}-rqt-common-plugins \
68 | ros-${ROS_DISTRO}-rqt-robot-plugins \
69 | ros-${ROS_DISTRO}-rviz \
70 | && rm -rf /var/lib/apt/lists/*
71 |
72 | # Install additional developer tools here...
73 |
74 | RUN apt-get update \
75 | && apt-get install -y sudo \
76 | && rm -rf /var/lib/apt/lists/* \
77 | && addgroup --gid ${GID} ${USERNAME} \
78 | && adduser --disabled-password --gecos '' --uid ${GID} --gid ${GID} ${USERNAME} \
79 | && echo ${USERNAME} ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/${USERNAME} \
80 | && chown -R ${UID}:${GID} /home/${USERNAME} \
81 | && chown -R ${UID}:${GID} ${CATKIN_WORKSPACE_DIR}
82 |
83 | ENV DEBIAN_FRONTEND=dialog
84 |
85 | RUN echo "alias rsource='source ${CATKIN_WORKSPACE_DIR}/devel/setup.bash'" >> /home/${USERNAME}/.bash_aliases \
86 | && echo "alias rbuild='(cd ${CATKIN_WORKSPACE_DIR} && catkin build)'" >> /home/${USERNAME}/.bash_aliases \
87 | && echo "alias rclean='(cd ${CATKIN_WORKSPACE_DIR} && catkin clean -y)'" >> /home/${USERNAME}/.bash_aliases \
88 | && echo "rsource || source /opt/ros/${ROS_DISTRO}/setup.bash" >> /home/${USERNAME}/.bashrc
89 |
90 | USER ${USERNAME}
91 |
92 |
--------------------------------------------------------------------------------
/templates/ros2/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // Author: Tobit Flatscher - github.com/2b-t (2022)
2 | {
3 | // See https://go.microsoft.com/fwlink/?LinkId=733558
4 | // for the documentation about the tasks.json format
5 | "version": "2.0.0",
6 | "tasks": [
7 | // Import repositories with vcs tool
8 | {
9 | "label": "vcs",
10 | "detail": "Import dependencies with vcs tool.",
11 | "type": "shell",
12 | "command": "vcs import < .repos",
13 | "options": {
14 | "cwd": "${workspaceFolder}/src"
15 | },
16 | "problemMatcher": []
17 | },
18 | // Install ROS dependencies
19 | {
20 | "label": "install dependencies",
21 | "detail": "Install all dependencies specified in the workspaces package.xml files.",
22 | "type": "shell",
23 | "command": "sudo apt-get update -y && rosdep update && rosdep install --from-paths src --ignore-src -y",
24 | "options": {
25 | "cwd": "${workspaceFolder}"
26 | },
27 | "problemMatcher": []
28 | },
29 | // Build tasks
30 | {
31 | "label": "build",
32 | "detail": "Build the workspace (release).",
33 | "type": "shell",
34 | "command": "colcon build --symlink-install --cmake-args '-DCMAKE_BUILD_TYPE=Release' -Wall -Wextra -Wpedantic",
35 | "options": {
36 | "cwd": "${workspaceFolder}"
37 | },
38 | "group": {
39 | "kind": "build",
40 | "isDefault": true
41 | },
42 | "problemMatcher": "$gcc"
43 | },
44 | {
45 | "label": "build debug",
46 | "detail": "Build the workspace (debug).",
47 | "type": "shell",
48 | "command": "colcon build --symlink-install --cmake-args '-DCMAKE_BUILD_TYPE=Debug' -Wall -Wextra -Wpedantic",
49 | "options": {
50 | "cwd": "${workspaceFolder}"
51 | },
52 | "group": "build",
53 | "problemMatcher": "$gcc"
54 | },
55 | // Test tasks
56 | {
57 | "label": "test",
58 | "detail": "Run all unit tests and show results.",
59 | "type": "shell",
60 | "command": "colcon test",
61 | "options": {
62 | "cwd": "${workspaceFolder}"
63 | },
64 | "group": {
65 | "kind": "test",
66 | "isDefault": true
67 | },
68 | "problemMatcher": []
69 | },
70 | // Clean tasks
71 | {
72 | "label": "clean",
73 | "detail": "Run the clean target.",
74 | "type": "shell",
75 | "command": "colcon clean workspace --yes",
76 | "options": {
77 | "cwd": "${workspaceFolder}"
78 | },
79 | "problemMatcher": []
80 | },
81 | {
82 | "label": "purge",
83 | "detail": "Purge workspace by deleting all generated files.",
84 | "type": "shell",
85 | "command": "rm -fr build install log && py3clean .",
86 | "options": {
87 | "cwd": "${workspaceFolder}"
88 | },
89 | "problemMatcher": []
90 | }
91 | ],
92 | "inputs": [
93 | {
94 | "id": "package",
95 | "type": "promptString",
96 | "description": "Package name"
97 | }
98 | ]
99 | }
100 |
--------------------------------------------------------------------------------
/templates/ros2/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | ##############
2 | # Base image #
3 | ##############
4 | FROM ros:jazzy-ros-base AS base
5 |
6 | ARG AMENT_WORKSPACE_DIR="/ament_ws"
7 |
8 | LABEL org.opencontainers.image.authors="tobit.flatscher@outlook.com"
9 | LABEL description="ROS 2 Jazzy Docker template"
10 | LABEL version="1.0"
11 |
12 | WORKDIR ${AMENT_WORKSPACE_DIR}
13 | SHELL ["/bin/bash", "-c"]
14 |
15 | ENV DEBIAN_FRONTEND=noninteractive
16 |
17 | RUN apt-get update \
18 | && apt-get -y install \
19 | git \
20 | python3-colcon-clean \
21 | python3-osrf-pycommon \
22 | && rm -rf /var/lib/apt/lists/*
23 |
24 | RUN apt-get update \
25 | && apt-get -y install \
26 | ros-${ROS_DISTRO}-compressed-image-transport \
27 | ros-${ROS_DISTRO}-compressed-depth-image-transport \
28 | ros-${ROS_DISTRO}-image-transport \
29 | ros-${ROS_DISTRO}-point-cloud-transport \
30 | ros-${ROS_DISTRO}-point-cloud-transport-plugins \
31 | ros-${ROS_DISTRO}-rmw-cyclonedds-cpp \
32 | && rm -rf /var/lib/apt/lists/*
33 |
34 | # Add additional installation instructions here...
35 |
36 | ENV DEBIAN_FRONTEND=dialog
37 |
38 |
39 | #####################
40 | # Development image #
41 | #####################
42 | FROM base AS dev
43 |
44 | ARG AMENT_WORKSPACE_DIR="/ament_ws"
45 | ARG USERNAME="developer"
46 | ARG UID=1000
47 | ARG GID=1000
48 |
49 | ENV DEBIAN_FRONTEND=noninteractive
50 |
51 | RUN apt-get update \
52 | && apt-get install -y \
53 | ack \
54 | bmon \
55 | cloc \
56 | gdb \
57 | htop \
58 | iperf3 \
59 | iputils-ping \
60 | net-tools \
61 | plocate \
62 | psmisc \
63 | tmux \
64 | xterm \
65 | && rm -rf /var/lib/apt/lists/*
66 |
67 | RUN apt-get update \
68 | && apt-get install -y \
69 | python3-vcstool \
70 | ros-${ROS_DISTRO}-rqt-common-plugins \
71 | ros-${ROS_DISTRO}-rqt-robot-steering \
72 | ros-${ROS_DISTRO}-rqt-tf-tree \
73 | ros-${ROS_DISTRO}-rviz2 \
74 | && rm -rf /var/lib/apt/lists/*
75 |
76 | # Install additional developer tools here...
77 |
78 | RUN apt-get update \
79 | && apt-get install -y sudo \
80 | && rm -rf /var/lib/apt/lists/* \
81 | # Remove user blocking UID 1000 on Ubuntu 24.04 and onwards:
82 | # See https://bugs.launchpad.net/cloud-images/+bug/2005129 and
83 | # https://github.com/devcontainers/images/issues/1056
84 | && userdel -r ubuntu || true \
85 | && addgroup --gid ${GID} ${USERNAME} \
86 | && adduser --disabled-password --gecos '' --uid ${GID} --gid ${GID} ${USERNAME} \
87 | && echo ${USERNAME} ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/${USERNAME} \
88 | && chown -R ${UID}:${GID} /home/${USERNAME} \
89 | && chown -R ${UID}:${GID} ${AMENT_WORKSPACE_DIR}
90 |
91 | ENV DEBIAN_FRONTEND=dialog
92 |
93 | RUN echo "alias rsource='source ${AMENT_WORKSPACE_DIR}/install/setup.bash'" >> /home/${USERNAME}/.bash_aliases \
94 | && echo "alias rbuild='(cd ${AMENT_WORKSPACE_DIR} && colcon build)'" >> /home/${USERNAME}/.bash_aliases \
95 | && echo "alias rclean='(cd ${AMENT_WORKSPACE_DIR} && colcon clean workspace -y)'" >> /home/${USERNAME}/.bash_aliases \
96 | && echo "rsource || source /opt/ros/${ROS_DISTRO}/setup.bash" >> /home/${USERNAME}/.bashrc
97 |
98 | USER ${USERNAME}
99 |
100 |
--------------------------------------------------------------------------------
/templates/ros/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // Author: Tobit Flatscher - github.com/2b-t (2021)
2 | {
3 | // See https://go.microsoft.com/fwlink/?LinkId=733558
4 | // for the documentation about the tasks.json format
5 | "version": "2.0.0",
6 | "tasks": [
7 | // Import repositories with vcs tool
8 | {
9 | "label": "vcs",
10 | "detail": "Import dependencies with vcs tool.",
11 | "type": "shell",
12 | "command": "vcs import < .repos",
13 | "options": {
14 | "cwd": "${workspaceFolder}/src"
15 | },
16 | "problemMatcher": []
17 | },
18 | // Install ROS dependencies
19 | {
20 | "label": "install dependencies",
21 | "detail": "Install all dependencies specified in the workspaces package.xml files.",
22 | "type": "shell",
23 | "command": "sudo apt-get update && rosdep update && rosdep install --from-paths src --ignore-src -y",
24 | "options": {
25 | "cwd": "${workspaceFolder}"
26 | },
27 | "problemMatcher": []
28 | },
29 | // Build tasks
30 | {
31 | "label": "build",
32 | "detail": "Build the workspace (default).",
33 | "type": "shell",
34 | "command": "catkin build --cmake-args '-DCMAKE_BUILD_TYPE=Release' -Wall -Wextra -Wpedantic",
35 | "options": {
36 | "cwd": "${workspaceFolder}"
37 | },
38 | "group": {
39 | "kind": "build",
40 | "isDefault": true
41 | },
42 | "problemMatcher": "$gcc"
43 | },
44 | {
45 | "label": "build debug",
46 | "detail": "Build the workspace (debug).",
47 | "type": "shell",
48 | "command": "catkin build --cmake-args '-DCMAKE_BUILD_TYPE=Debug' -Wall -Wextra -Wpedantic",
49 | "options": {
50 | "cwd": "${workspaceFolder}"
51 | },
52 | "group": "build",
53 | "problemMatcher": "$gcc"
54 | },
55 | // Test tasks
56 | {
57 | "label": "test",
58 | "detail": "Run all unit tests and show results.",
59 | "type": "shell",
60 | "command": "catkin run_tests",
61 | "options": {
62 | "cwd": "${workspaceFolder}"
63 | },
64 | "group": {
65 | "kind": "test",
66 | "isDefault": true
67 | },
68 | "problemMatcher": []
69 | },
70 | // Clean
71 | {
72 | "label": "clean",
73 | "detail": "Run the clean target.",
74 | "type": "shell",
75 | "command": "catkin clean --yes",
76 | "options": {
77 | "cwd": "${workspaceFolder}"
78 | },
79 | "problemMatcher": []
80 | },
81 | {
82 | "label": "purge",
83 | "detail": "Purge workspace by deleting all generated files.",
84 | "type": "shell",
85 | "command": "rm -fr .catkin_tools build install log && py3clean .",
86 | "options": {
87 | "cwd": "${workspaceFolder}"
88 | },
89 | "problemMatcher": []
90 | },
91 | // Start ROS Master node
92 | {
93 | "label": "roscore",
94 | "detail": "Start the ROS master node.",
95 | "type": "shell",
96 | "command": "roscore",
97 | "options": {
98 | "cwd": "${workspaceFolder}"
99 | },
100 | "problemMatcher": []
101 | },
102 | ],
103 | "inputs": [
104 | {
105 | "id": "package",
106 | "type": "promptString",
107 | "description": "Package name"
108 | }
109 | ]
110 | }
111 |
--------------------------------------------------------------------------------
/ReadMe.md:
--------------------------------------------------------------------------------
1 | # Docker for Robotics with the Robot Operating System (ROS/ROS 2)
2 |
3 | Author: [Tobit Flatscher](https://github.com/2b-t) (2021 - 2024)
4 |
5 | [](https://github.com/2b-t/docker-for-robotics/actions/workflows/build-ros.yml) [](https://github.com/2b-t/docker-for-robotics/actions/workflows/build-ros2.yml) [](https://opensource.org/licenses/MIT)
6 |
7 |
8 |
9 | ## Overview
10 |
11 | This guide discusses best practices for **robotics development with the [Robot Operating System (ROS/ROS 2)](https://www.ros.org/) and Docker/Docker-Compose** on **Linux** as well as **Windows** operating systems. This includes displaying **graphic user interfaces**, working with hardware, **real-time capable code** and the **network set-up** for multiple machines. Additionally it walks you through the **set-up with Visual Studio Code**.
12 |
13 | This repository used to be part of [another guide](https://github.com/2b-t/docker-realtime) I have written on Docker and real-time applications. As the general Docker and ROS part has now become quite lengthy, I have decided to extract it and create a repository of its own for it.
14 |
15 | |  |  |
16 | | ------------------------------------------------------------ | ------------------------------------------------------------ |
17 | | ROS Indigo running from a Docker container on Ubuntu 22.04 | ROS Indigo running from a Docker container on Windows 10 with WSL2 |
18 |
19 |
20 |
21 | ## Structure of this guide
22 |
23 | This guide is structured in the following chapters:
24 |
25 | - [**Motivation**](./doc/Motivation.md): Tries to give you good reasons for why you should use Docker as a company or research institution.
26 | - [**Introduction to Docker and Docker-Compose**](./doc/Introduction.md): Introduces fundamental concepts of container-based development.
27 | - [**Set-up with Visual Studio Code**](./doc/VisualStudioCodeSetup.md): Walks you through the set-up of containers with Visual Studio Code.
28 | - [**Graphic user interfaces and Docker**](./doc/Gui.md): Discusses the challenges of using Docker with graphic user interfaces and presents workarounds.
29 | - [**ROS and Docker**](./doc/Ros.md): Discusses best-practices for Docker and ROS/ROS 2.
30 | - [**Docker on Windows**](./doc/Windows.md): Running Docker on Windows in WSL2 with graphic user interfaces.
31 | - [**Working with hardware**](./doc/WorkingWithHardware.md): Discusses best-practices when working with hardware.
32 |
33 | The folder [**`examples/`**](./examples) contains different ROS and ROS 2 examples (in simulation as well as with hardware access) while the folder [**`templates/`**](./templates) provides templates for ROS and ROS 2 that you can build your own workspace off. This guide is further extended by an external guide on **Docker for real-time applications with `PREEMPT_RT`** that can be found [here](https://github.com/2b-t/docker-realtime).
34 |
35 |
36 |
37 | ## Get a copy
38 |
39 | This workspace contains several other repositories as submodules. Therefore please clone it with the following command:
40 |
41 | ```bash
42 | $ git clone --recurse-submodules https://github.com/2b-t/docker-for-robotics.git
43 | ```
44 |
--------------------------------------------------------------------------------
/examples/affordance-templates-ros-docker/ReadMe.md:
--------------------------------------------------------------------------------
1 | # Example: Affordance templates workspace in ROS Indigo
2 |
3 | Author: [Tobit Flatscher](https://github.com/2b-t) (March 2023)
4 |
5 |
6 |
7 | ## Overview
8 |
9 | Sometimes you come across some interesting old work that you would like to replicate. Sometimes a publication comes with open-source code but likely your ROS version will not necessarily match the one that was used in the publication. For me that was the case when reading the publication about [Affordance Templates](https://www.researchgate.net/publication/283668215_The_Affordance_Template_ROS_package_for_robot_task_programming) published by [Traclabs](https://traclabs.com/projects/affordance-templates/) (you might know them from [trac-ik](https://traclabs.com/projects/trac-ik/)) at [ICRA 2015](https://www.ieee-ras.org/component/rseventspro/event/400-icra-2015-ieee-international-conference-on-robotics-and-automation) (see image below). And even if you had an old computer with [ROS Indigo](http://wiki.ros.org/indigo) (released in 2014!) laying around you would not want to trash that computer with all the dependencies just for trying this one workspace out. This is again where Docker as a technology comes in really handy.
10 |
11 | 
12 |
13 | The following example will shows how Docker can be useful for getting legacy code up and running on your machine. This example includes the packages from the [Traclabs Bitbucket](https://bitbucket.org/traclabs/) with the commits specified in [this workspace](https://github.com/yueyeyuniao/affordance_template). Potentially one could also get this workspace up and running in [ROS Fuerte](http://wiki.ros.org/fuerte) by following [this guide](https://bitbucket.org/nasa_ros_pkg/deprecated_misc/wiki/Home) and using the deprecated packages from the NASA Bitbucket ([`nasa_common`](https://bitbucket.org/nasa_ros_pkg/deprecated_nasa_common/src/master/), [`nasa_robodyn`](https://bitbucket.org/nasa_ros_pkg/deprecated_nasa_robodyn/src/master/), [`nasa_r2_simulator`](https://bitbucket.org/nasa_ros_pkg/deprecated_nasa_r2_simulator/src/master/) and [`nasa_r2_common`](https://bitbucket.org/nasa_ros_pkg/deprecated_nasa_r2_common/src/master/)).
14 |
15 |
16 |
17 | ## Installation
18 |
19 | Please make sure that you cloned this repository with the `--recurse-submodules` option as follows
20 |
21 | ```bash
22 | $ git clone --recurse-submodules https://github.com/2b-t/docker-for-robotics.git
23 | ```
24 |
25 | else the modules from Traclabs will be empty. In case you did not you will have to run
26 |
27 | ```bash
28 | $ git submodule update --init
29 | ```
30 |
31 |
32 |
33 | ## Running
34 |
35 | Open a terminal on your **host machine** and allow the user `root` to stream onto your display. This way the Docker (which is using `root` as a user) can open graphic user interface on your host machine:
36 |
37 | ```bash
38 | $ xhost +local:root
39 | ```
40 |
41 | **Open your Docker** either manually or by using Visual Studio code as described in the main guide. Once inside the Docker perform the following steps:
42 |
43 | ```bash
44 | $ source /opt/ros/indigo/setup.bash
45 | $ catkin build
46 | $ source devel/setup.bash
47 | $ roslaunch at_r2_bringup demo.launch
48 | ```
49 |
50 | This should open two new windows, one for the **Gazebo simulation**, the other for the **Rviz visualization** (see screenshot above). The Rviz visualization should contain two panels: The Moveit motion planning panel to the left and the affordance templates panel to the right. Crucial for the latter is the interactive marker that is displayed. Furthermore any object inserted into the scene should be visible from the Asus camera plug-in.
51 |
52 | Inside Moveit you can only plan for the head. To do so select a desired goal state from the section `Query` in the `Planning` tab. Then click `Update` and finally plan and execute the motion with `Plan and Execute`.
53 |
54 | The **affordance templates panel** on the right can be used for planning arm motions. As a first step click `Refresh All` in the `Server` tab. This should bring up all the available motion templates in the `Library` tab below. For inserting a new template double click on its icon. This will insert a virtual marker into the scene (if it does not appear make sure that you did not deactivate the interactive marker in the `Displays` panel!). You can adjust the parametrized motion by moving and rotating the interactive marker. This is crucial as the Robonaut will not be able to plan and execute a motion if it is out of reach. Finally in the `Controls` menu you can plan and execute the parametrized motion once inserted: The arrow buttons on the bottom allow you to plan the templates step by step. Click `Execute Plan` to then execute the planned motion. When activating the checkbox `Execute on Plan` stepping the motion will also result in the execution of the plan.
55 |
--------------------------------------------------------------------------------
/templates/ros/ReadMe.md:
--------------------------------------------------------------------------------
1 | # ROS Noetic Docker Template
2 |
3 | Author: [Tobit Flatscher](https://github.com/2b-t) (2021 - 2024)
4 |
5 |
6 |
7 | ## 0. Overview
8 |
9 | This repository contains a Docker workspace template for [**ROS Noetic**](http://wiki.ros.org/noetic). The idea is that a Docker is created for each project at Catkin workspace level. Dependencies that are not expected to change during the course of a project are installed from Debian packages inside the Dockerfile, while proprietary dependencies that are expected to change during a project are mounted into the container and version controlled with [**`vcstool`**](https://github.com/dirk-thomas/vcstool). Only selected folders such as `src/` are mounted into the container so that the workspace can be compiled on the host system as well as inside the container without interfering.
10 |
11 | Here is an overview of the structure of this repository:
12 |
13 | ```bash
14 | ros/
15 | ├── docker/ # Docker and Docker-Compose configuration
16 | │ ├── docker-compose.yml # Base Docker-Compose file containing all the basic Docker set-up
17 | │ ├── docker-compose-gui.yml # Extends the base Docker-Compose file by X11-forwarding for graphic user interfaces
18 | │ ├── docker-compose-gui-nvidia.yml # Extends the graphic user interface Docker-Compose file with the Nvidia runtime
19 | │ ├── docker-compose-nvidia.yml # Extends the base Docker-Compose file with the Nvidia runtime for graphic acceleration
20 | │ ├── docker-compose-vscode.yml # Extends one of the other configurations with Visual Studio Code relevant settings
21 | │ ├── Dockerfile # Dockerfile containing ROS and the base dependencies
22 | │ └── .env # Environment variables to be considered by Docker Compose
23 | ├── src/ # Source folder mounted inside the Docker container
24 | │ └── .repos # VCS tool configuration file for version control
25 | ├── .devcontainer/ # Configuration files for containers in Visual Studio Code
26 | └── .vscode/ # Configuration files for Visual Studio Code
27 | ```
28 |
29 |
30 |
31 | ## 1. Set-up
32 |
33 | After cloning this repository you will have to update the packages inside the workspace. For version control we use [`vcstool`](http://wiki.ros.org/vcstool) instead of Git submodules. In order to **pull the repositories** please import them with the following command (either inside the Docker or on the host):
34 |
35 | ```
36 | $ cd src/
37 | $ vcs import < .repos
38 | ```
39 |
40 | This should clone the desired repositories given inside `.repos` into your workspace. They are excluded in the [`.gitignore`](./.gitignore) file so that they will not be part of your commits.
41 |
42 | The **configuration** is performed inside the [`docker/.env`](./docker/.env) file:
43 |
44 | ```bash
45 | CATKIN_WORKSPACE_DIR=/catkin_ws
46 | YOUR_IP=127.0.0.1
47 | ROBOT_IP=127.0.0.1
48 | ROBOT_HOSTNAME=P500
49 | UID=1000
50 | GID=1000
51 | ```
52 |
53 | Here you can change the workspace name, network settings as well as user and group IDs.
54 |
55 | **Network set-up**: The parameter `YOUR_IP` corresponds to the IP that you are using, in case you are running a simulation set it to `127.0.0.1` while for working with a physical robot you will have to set it to the IP assigned to the network interface used for connecting to the robot shown by `$ ifconfig` from the `net-tools` package on your computer. The `ROBOT_IP` as well as the `ROBOT_HOSTNAME` are used to configure the `/etc/hosts` file as well as the `ROS_MASTER_URI`. They should correspond to the IP shown by `$ ifconfig` on the robot as well as to its `$ hostname` and can be set to `127.0.0.1` and an arbitrary hostname in case of the simulation.
56 |
57 | **User and group id**: These should be set identical to the user and group ID of the user running the container (see the output of `$ id`). On Debian system [anything below 1000 is generally reserved for system accounts](https://www.redhat.com/sysadmin/user-account-gid-uid) and the first UID `1000` is assigned to the first user of the system, which are the default values in our set-up. In case your user and group IDs differ, adjust them.
58 |
59 |
60 |
61 | ## 2. Running
62 |
63 | Either **run the Docker** manually with
64 |
65 | ```bash
66 | $ cd ros/
67 | $ docker compose -f docker/docker-compose-gui.yml up
68 | ```
69 |
70 | and then connect to the running Docker
71 |
72 | ```bash
73 | $ cd ros/
74 | $ docker exec -it ros_docker bash
75 | ```
76 |
77 | (or `docker/docker-compose-gui-nvidia.yml` in case you are running an Nvidia graphics cards and want to have hardware acceleration [with the Nvidia container runtime](https://nvidia.github.io/nvidia-container-runtime/)). Alternatively use the corresponding [**Visual Studio Code Dev Containers integration**](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) as described [here](https://github.com/2b-t/docker-for-robotics/blob/main/doc/VisualStudioCodeSetup.md). In latter case the configuration can be adjusted in `docker/docker-compose-vscode.yml`. Using the Docker through Visual Studio Code is much easier and is therefore recommended!
78 |
79 | In order to be able to run **graphical user interfaces** from inside the Docker you might have to type
80 |
81 | ```bash
82 | $ xhost +
83 | ```
84 |
85 | on the **host system**. When using a user with the same name, user and group id as the host system this should not be necessary.
86 |
--------------------------------------------------------------------------------
/templates/ros2/ReadMe.md:
--------------------------------------------------------------------------------
1 | # ROS 2 Jazzy Docker Template
2 |
3 | Author: [Tobit Flatscher](https://github.com/2b-t) (2021 - 2025)
4 |
5 |
6 |
7 | ## 0. Overview
8 |
9 | This repository contains a Docker workspace template for [**ROS 2 Jazzy**](https://docs.ros.org/en/jazzy/index.html). The idea is that a Docker is created for each project at Ament workspace level. Dependencies that are not expected to change during the course of a project are installed from Debian packages inside the Dockerfile, while proprietary dependencies that are expected to change during a project are mounted into the container and version controlled with [**`vcstool`**](https://github.com/dirk-thomas/vcstool). Only selected folders such as `dds/` and `src/` are mounted into the container so that the workspace can be compiled on the host system as well as inside the container without them interfering.
10 |
11 | Here is an overview of the structure of this repository:
12 |
13 | ```bash
14 | ros/
15 | ├── dds/ # DDS middleware configuration
16 | ├── docker/ # Docker and Docker-Compose configuration
17 | │ ├── docker-compose.yml # Base Docker-Compose file containing all the basic Docker set-up
18 | │ ├── docker-compose-gui.yml # Extends the base Docker-Compose file by X11-forwarding for graphic user interfaces
19 | │ ├── docker-compose-gui-nvidia.yml # Extends the graphic user interface Docker-Compose file with the Nvidia runtime
20 | │ ├── docker-compose-nvidia.yml # Extends the base Docker-Compose file with the Nvidia runtime for graphic acceleration
21 | │ ├── docker-compose-vscode.yml # Extends one of the other configurations with Visual Studio Code relevant settings
22 | │ ├── Dockerfile # Dockerfile containing ROS 2 and the base dependencies
23 | │ └── .env # Environment variables to be considered by Docker Compose
24 | ├── src/ # Source folder mounted inside the Docker container
25 | │ └── .repos # VCS tool configuration file for version control
26 | ├── .devcontainer/ # Configuration files for containers in Visual Studio Code
27 | └── .vscode/ # Configuration files for Visual Studio Code
28 | ```
29 |
30 |
31 |
32 | ## 1. Set-up
33 |
34 | After cloning this repository you will have to update the packages inside the workspace. For version control we use [`vcstool`](http://wiki.ros.org/vcstool) instead of Git submodules. In order to **pull the repositories** please import them with the following command (either inside the Docker or on the host):
35 |
36 | ```
37 | $ cd src/
38 | $ vcs import < .repos
39 | ```
40 |
41 | This should clone the desired repositories given inside `.repos` into your workspace. They are excluded in the [`.gitignore`](./.gitignore) file so that they will not be part of your commits.
42 |
43 | The **configuration** is performed inside the [`docker/.env`](./docker/.env) file:
44 |
45 | ```bash
46 | AMENT_WORKSPACE_DIR=/ament_ws
47 | ROS_DOMAIN_ID=0
48 | YOUR_IP=127.0.0.1
49 | ROBOT_IP=127.0.0.1
50 | ROBOT_HOSTNAME=P500
51 | UID=1000
52 | GID=1000
53 | ```
54 |
55 | Here you can change the workspace name, network settings as well as user and group IDs.
56 |
57 | **Network set-up**: The `ROS_DOMAIN_ID` is used for the ROS 2 DDS middleware configuration. The parameter `YOUR_IP` corresponds to the IP that you are using, in case you are running a simulation set it to `127.0.0.1` while for working with a physical robot you will have to set it to the IP assigned to the network interface used for connecting to the robot shown by `$ ifconfig` from the `net-tools` package on your computer. We use it for the DDS middleware configuration. The `ROBOT_IP` as well as the `ROBOT_HOSTNAME` are used to configure the `/etc/hosts` file as well as configuring the DDS middleware by IP. They should correspond to the IP shown by `$ ifconfig` on the robot as well as to its `$ hostname` and can be set to `127.0.0.1` and an arbitrary hostname in case of the simulation.
58 |
59 | **User and group id**: These should be set identical to the user and group ID of the user running the container (see the output of `$ id`). On Debian system [anything below 1000 is generally reserved for system accounts](https://www.redhat.com/sysadmin/user-account-gid-uid) and the first UID `1000` is assigned to the first user of the system, which are the default values in our set-up. In case your user and group IDs differ, adjust them.
60 |
61 |
62 |
63 | ## 2. Running
64 |
65 | Either **run the Docker** manually with
66 |
67 | ```bash
68 | $ cd ros2/
69 | $ docker compose -f docker/docker-compose-gui.yml up
70 | ```
71 |
72 | and then connect to the running Docker
73 |
74 | ```bash
75 | $ cd ros2/
76 | $ docker exec -it ros2_docker bash
77 | ```
78 |
79 | (or `docker/docker-compose-gui-nvidia.yml` in case you are running an Nvidia graphics cards and want to have hardware acceleration [with the Nvidia container runtime](https://nvidia.github.io/nvidia-container-runtime/)). Alternatively use the corresponding [**Visual Studio Code Dev Containers integration**](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) as described [here](https://github.com/2b-t/docker-for-robotics/blob/main/doc/VisualStudioCodeSetup.md). In latter case the configuration can be adjusted in `docker/docker-compose-vscode.yml`. Using the Docker through Visual Studio Code is much easier and is therefore recommended!
80 |
81 | In order to be able to run **graphical user interfaces** from inside the Docker you might have to type
82 |
83 | ```bash
84 | $ xhost +
85 | ```
86 |
87 | on the **host system**. When using a user with the same name, user and group id as the host system this should not be necessary.
88 |
--------------------------------------------------------------------------------
/doc/VisualStudioCodeSetup.md:
--------------------------------------------------------------------------------
1 | # Docker and Visual Studio Code
2 |
3 | Author: [Tobit Flatscher](https://github.com/2b-t) (2021 - 2023)
4 |
5 |
6 |
7 | ## 1. Docker in Visual Studio Code
8 |
9 | The following guide will walk you through the set-up for Docker inside Visual Studio Code. The integration of Docker with Visual Studio Code is excellent. I can only warmly recommend it for working with Visual Studio Code.
10 |
11 | ### 1.1 Installation
12 |
13 | If you do not have Visual Studio Code installed on your system then [install it](https://code.visualstudio.com/download) and follow the Docker post-installation steps given [here](https://docs.docker.com/engine/install/linux-postinstall/) so that you can run Docker without `sudo`. Finally install [Docker](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker) and [**Remote - Containers**](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) plugins inside Visual Studio Code and you should be ready to go. For installing the Remote Containers plug-in go the market place through the activity bar, browse the plug-in and install it as displayed in the screenshot below:
14 |
15 | 
16 |
17 | After the successful installation you should see a small **green icon on the bottom left of your window** as displayed in the following screenshot:
18 |
19 | 
20 |
21 | ### 1.2 Configuration
22 |
23 | Visual Studio Code generates two folders for your project, one called **`.devcontainer`** contains the Docker settings while the other, **`.vscode`**, contains the Visual Studio code preferences:
24 |
25 | ```
26 | repository
27 | ├─ .devcontainer # Docker settings
28 | | └─ devcontainer.json
29 | └─ .vscode
30 | ```
31 |
32 | #### 1.2.1 Devcontainer configuration
33 |
34 | The `.devcontainer` file let's Visual Studio Code know if it is dealing with [Docker](https://github.com/athackst/vscode_ros2_workspace/blob/foxy/.devcontainer/devcontainer.json) or [Docker Compose](https://github.com/devrt/ros-devcontainer-vscode/blob/master/.devcontainer/devcontainer.json). The contents of the Json configuration file `.devcontainer/devcontainers.json` might look as follows:
35 |
36 | ```json
37 | {
38 | "name": "ROS Docker",
39 | "dockerComposeFile": [
40 | "../docker/docker-compose.yml"
41 | ],
42 | "service": "ros_docker",
43 | "workspaceFolder": "/benchmark",
44 | "shutdownAction": "stopCompose",
45 | "extensions": [
46 | ]
47 | }
48 | ```
49 |
50 | You can also [access local variables on the host system with `${localEnv:SOME_HOST_VAR}`](https://code.visualstudio.com/remote/advancedcontainers/environment-variables).
51 |
52 | #### 1.2.2 Configuring tasks
53 |
54 | The contents of `.vscode` depend on the programming language and the additional plug-ins you want to use, e.g. for Linting/static code analysis. One can configure for example tasks that can be executed with key shortcuts.
55 |
56 | Furthermore you can add a `tasks.json` that defines certain useful tasks that VS Code can run. My configurations for ROS and ROS 2 can be found in the corresponding folders [`/templates/ros/.vscode/tasks.json`](../templates/ros/.vscode/tasks.json) as well as [`/templates/ros2/.vscode/tasks.json`](../templates/ros2/.vscode/tasks.json). I configure tasks for importing repositories with [`vcs`](https://github.com/dirk-thomas/vcstool), installing dependencies with `rosdep`, building a workspace with `catkin` or `colcon`, running tests and finally cleaning the workspace.
57 |
58 | You can run these tasks by selecting `Terminal/Run Tasks...` and then selecting the desired task. This will open a subterminal and run this task in the corresponding subterminal.
59 |
60 | |  |  |
61 | | ------------------------------------------------------------ | ------------------------------------------------------------ |
62 |
63 | ### 1.3 Usage
64 |
65 | After opening Visual Studio Code you can open the repository with **`File/Open Folder`**. When asked if you want to **`Reopen in container`** (see the left screenshot below) confirm. If this dialog does not appear click on the green symbol on the very left bottom of your window and select `Remote containers: Reopen in container` from the top center as shown in the bottom right picture). Depending on how many layers the Docker has, if they are already pre-cached and how good your internet connection is, it might take seconds or minutes to prepare your container for you.
66 |
67 | |  |  |
68 | | ------------------------------------------------------------ | ------------------------------------------------------------ |
69 |
70 | In case you are terminated with the error message "Current user does not have permission to run 'docker'. Try adding the user to the 'docker' group." follow the advice given [here](https://stackoverflow.com/questions/57840395/permission-issue-using-remote-development-extension-to-attach-to-a-docker-image). Open a new terminal on your host machine, enter `$ sudo usermod -aG docker $USER`, reboot and then retry opening the container inside Visual Studio Code.
71 |
72 | As soon as you have entered the Docker you should be greeted by a terminal inside it and the green icon on the bottom left should state **`Dev Container`**. You can open a new terminal by selecting **`Terminal/New Terminal`** any time. You can now browse the Docker container just like a regular terminal and access the folders inside it as if they were on the host system (see the screenshot below).
73 |
74 | 
75 |
76 | In case you want to rebuild the image press **`Ctrl` + `Shift` + `P`**, type Rebuild and then select either **`DevContainers: Rebuild`** or `DevContainers: Rebuild without Cache`. Former will rebuild the image re-using existing layers while the latter will discard all the existing layers and rebuild the image from scratch.
77 |
78 | ### 1.4 Debugging
79 |
80 | It might happen that the Visual Studio Code integration might terminate and does not output much useful information. This might be the case if you are asking it to run a container with the `nvidia-container-runtime` but it is not installed on your system or your `devcontainer.json` mentions the wrong service and/or workspace. Similarly it happened in the past that the Visual Studio Code extension was not compatible with Docker itself. In this case you might have to up- or downgrade the Docker version you are using (see e.g. [here](https://github.com/microsoft/vscode-remote-release/issues/7958)). In case this emerges it is worth **checking the [VSC remote container issues on Github](https://github.com/microsoft/vscode-remote-release/issues)** and trying to **build your image without cache** as described in the section above. If all of this does not work it can be helpful to go back to the **Docker command line commands** and launch them manually to see if there are any issues with the Docker engine itself.
81 |
--------------------------------------------------------------------------------
/doc/Windows.md:
--------------------------------------------------------------------------------
1 | # Docker on Windows
2 |
3 | Author: [Tobit Flatscher](https://github.com/2b-t) (2024)
4 |
5 |
6 |
7 | ## 0. Overview
8 |
9 | Docker can also be installed on Windows (with a WSL 2 backend) as is described in more detail [here](https://docs.docker.com/desktop/install/windows-install/). After installing Docker you can use the `docker` as well as `docker compose` commands from within PowerShell. Currently this standard approach does not allow you though to stream graphic user interfaces to the host system while using WSL directly does.
10 |
11 | [Since Windows 10 Build 19044+ or Windows 11 (January 2024) **Windows Subsystem for Linux 2 (WSL2)** supports Linux GUI applications](https://learn.microsoft.com/en-us/windows/wsl/tutorials/gui-apps). This enables us to use Docker in the same way as we do on Ubuntu including our **graphic user interfaces**. If you want to check if your operating system supports it, check the version of your operating system as discussed [here](https://support.microsoft.com/en-us/windows/which-version-of-windows-operating-system-am-i-running-628bec99-476a-2c13-5296-9dd081cdd808). Potentially you will have to follow the following steps to [update](https://support.microsoft.com/en-us/windows/get-the-latest-windows-update-7d20e88c-0568-483a-37bc-c3885390d212) (Windows 10 to the corresponding build version) or [upgrade your operating system](https://support.microsoft.com/en-us/windows/upgrade-to-windows-10-faq-cce52341-7943-594e-72ce-e1cf00382445) (to either Windows 10 or 11). The following paragraphs describe how your Windows 10 or 11 system can then be configured so that you can use graphic user interfaces in the same way as on a Ubuntu system.
12 |
13 | As hardware (such as network interfaces) has to be shared between the Windows and the Linux subsystem WSL makes heavy use of virtualization that differs in between WSL and WSL 2 as discussed [here](https://learn.microsoft.com/en-us/windows/wsl/faq#can-wsl-2-use-networking-applications-). This can lead to **problems with hardware** such as e.g. [here](https://github.com/OpenEtherCATsociety/SOEM/issues/630). This makes WSL not very favourable for development or deployment (for ROS 2 it might be better to install it on the host system directly as described [here](https://docs.ros.org/en/humble/Installation/Windows-Install-Binary.html) and run at least the nodes that interface the hardware on the operating system without a container). In my opinion the main use cases for Docker on Windows are therefore the following:
14 |
15 | - **Getting started with robotics**: You do not have a Linux system but want to try ROS on your system. WSL allows you to work with ROS as well as ROS 2 at least in **simulation**.
16 | - **Data sharing**: You might need to interact with clients, partner companies and share holders that are either not familiar with Linux or are not allowed to use Linux due to security restructions (most companies strangely enough still allow WSL to be used though). They can then either work in simulation or from recorded ROS bag data.
17 |
18 | 
19 |
20 | ## 1. Windows Subsystem for Linux (WSL) Configuration
21 |
22 | The following paragraph will quickly walk you through the installation of [Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/install) as well as the [Windows Subsystem for Linux GUI (WSLg) extension](https://github.com/microsoft/wslg). The basic steps are listed [here](https://learn.microsoft.com/en-us/windows/wsl/tutorials/gui-apps) but I will elaborate them in more detail. First of all follow the steps to install WSL as outlined [here](https://learn.microsoft.com/en-us/windows/wsl/install). This basically involves opening a PowerShell and either typing `$ wsl --install` or
23 |
24 | ```powershell
25 | $ wsl --install -d Ubuntu
26 | ```
27 |
28 | where the distribution `Ubuntu` can be replaced by any of the choices given by `$ wsl --list --online`.
29 |
30 | If you already had WSL installed you might need to update it as follows:
31 |
32 | ```powershell
33 | $ wsl --update
34 | $ wsl --shutdown
35 | ```
36 |
37 | In the PowerShell check the version of WSL of your subsystem. There are two versions `1` and `2` which are different in a few relevant aspects (as discussed e.g. [here](https://learn.microsoft.com/en-gb/windows/wsl/compare-versions)). Make sure your subsystem is running **version 2** and switch as follows if necessary:
38 |
39 | ```powershell
40 | $ wsl -l -v
41 | NAME STATE VERSION
42 | * Ubuntu Running 1
43 | $ wsl —set-version Ubuntu 2
44 | For information on key differences with WSL 2 please visit https://aka.ms/wsl2
45 | Conversion in progress, this may take a few minutes...
46 | The operation completed successfully.
47 | ```
48 |
49 | You can then open the Windows Subsystem for Linux by searching for **WSL** or Ubuntu inside the installed programs and running it. This will open a terminal that can be used like any other **Linux terminal**.
50 |
51 | Inside WSL check the `DISPLAY` variable:
52 |
53 | ```bash
54 | $ echo $DISPLAY
55 | :0
56 | ```
57 |
58 | It should be set to `:0`. If it is not, make sure that you are using WSL 2 as discussed above and follow the debugging guide [here](https://github.com/microsoft/wslg/wiki/Diagnosing-%22cannot-open-display%22-type-issues-with-WSLg).
59 |
60 | Proceed to install and run any GUI-based program such as `gedit`:
61 |
62 | ```bash
63 | $ sudo apt install gedit
64 | $ gedit
65 | ```
66 |
67 | This should bring up the graphic user interface on your host system.
68 |
69 | ### 1.1 Hardware acceleration
70 |
71 | Make sure you have graphics drivers for your graphics card installed. This is not strictly necessary but is useful for hardware acceleration (e.g. OpenGL). The Nvidia drivers can be downloaded [here](https://www.nvidia.com/Download/index.aspx?lang=en-us) by selecting your graphics card and the operating system. To see if the hardware acceleration is working in WSL, launch WSL and make sure that `$ nvidia-smi` detects your graphics card.
72 |
73 | ## 2. Running Docker with graphic user interfaces inside WSL 2
74 |
75 | **Graphic user interfaces in WSL 2 then work in the very same way as on Linux operating systems.** Follow the installation of Docker and Docker-Compose as discussed in [`Introduction.md`](./Introduction.md) as well as the set-up for graphic user interfaces in [`Gui.md`](./Gui.md), including the Nvidia container toolkit in case you want to run hardware acceleration. You can then use the regular `docker` and `docker compose` commands inside the WSL in combination with the templates found in [`templates/`](../templates).
76 |
77 | In the figure below you can see the output of running the [Affordance Templates workspace example](../examples/affordance-templates-ros-docker) on a Windows 10 operating system. For this purpose just clone this repository inside the subsystem for Linux
78 |
79 | ```bash
80 | $ git clone https://github.com/2b-t/docker-for-robotics.git
81 | $ cd docker-for-robotics/examples/affordance-templates-ros-docker
82 | $ docker compose -f docker/docker-compose-gui.yml up
83 | ```
84 |
85 | Then open another terminal and attach to the container with
86 |
87 | ```bash
88 | $ docker exec -it affordance_templates bash
89 | ```
90 |
91 | and there continue to build the workspace and run the main launch file of this example as discussed [here](../examples/affordance-templates-ros-docker/ReadMe.md).
92 |
93 | 
94 |
--------------------------------------------------------------------------------
/doc/WorkingWithHardware.md:
--------------------------------------------------------------------------------
1 | # Accessing hardware inside a container
2 |
3 | Author: [Tobit Flatscher](https://github.com/2b-t) (2021 - 2023)
4 |
5 |
6 |
7 | ## 1. Working with hardware
8 |
9 | When working with **hardware that use the network interface** such as EtherCAT slaves one might have to **share the network** with the host or remap the individual ports manually. One can automate the generation of the entries in the `/etc/hosts` file inside the container as follows:
10 |
11 | ```yaml
12 | 9 network_mode: "host"
13 | 10 extra_hosts:
14 | 11 - "${REMOTE_HOSTNAME}:${REMOTE_IP}"
15 | ```
16 |
17 | In this case the two environment variables are defined inside a `.env` file that is automatically passed to Docker Compose.
18 |
19 | When sharing **external devices** such as USB devices one will have to **share the `/dev` directory** with the host system as well as use [**device whitelisting**](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/resource_management_guide/sec-devices) as follows (for some applications Docker's [`--device`](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities) flag might be sufficient). An overview over the IDs of the Linux allocated devices can be found [here](https://www.kernel.org/doc/html/v4.15/admin-guide/devices.html). You will have to specify the [Linux device drivers major and minor number](https://www.oreilly.com/library/view/linux-device-drivers/0596000081/ch03s02.html). Inserting a `*` will give it access to all major/minor numbers. See e.g. what this would look like for the Intel Realsense depth cameras:
20 |
21 | ```yaml
22 | 9 volumes:
23 | 10 - /dev:/dev
24 | 11 device_cgroup_rules:
25 | 12 - 'c 81:* rmw'
26 | 13 - 'c 189:* rmw'
27 | ```
28 |
29 | The association of these numbers and the devices is given in [`/proc/devices`](https://unix.stackexchange.com/questions/198950/how-to-get-a-list-of-major-number-driver-associations).
30 |
31 | You might also selectively mount only some USB devices:
32 |
33 | ```yaml
34 | 9 volumes:
35 | 10 - /dev/some_device:/dev/some_device
36 | 11 - /dev/another_device:/dev/another_device
37 | ```
38 |
39 | In case you are not quite sure which group a device belongs to you might also run the container with extended privileges as [**`privileged`**](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities). Note that this is in **generally not recommended** as this basically removes all types of isolation and as such might pose a security risk in particular when being `root` inside the container. In some rare cases this can't be avoided though (e.g. in the case of a Realsense camera with IMU that currently needs [write access to `/sys` which is not possible in an unprivileged container](https://forums.docker.com/t/unable-to-mount-sys-inside-the-container-with-rw-access-in-unprivileged-mode/97043)).
40 |
41 | ### 1.1 Determining `device_cgroup_rules` for connected devices
42 |
43 | If we have no idea what `device_cgroup_rules` we might need for a particular device but we have the device at hand we might do the following to find out.
44 |
45 | In Linux differentiates between **busses** (the busses on the motherboard that a device is attached to, e.g. the output of `$ lsusb`) and **device files** (located inside `/dev` that are used to abstract standard devices and communicate with the corresponding physical or virtual devices). Depending on the type of the data that is exchange one differentiates between block `b` and character `c` devices (for more information see e.g. [here](https://www.baeldung.com/linux/dev-directory)). For the busses there exist readily available tools like `lsusb` that are able to translate the vendor and product codes into human-readable strings while I am not aware of such a tool for device files.
46 |
47 | So in order for finding out which device files (and as a consequence which device drivers major and minor numbers) belong to a device, you either have to plug the device in an out comparing the changes in device files or find out which device files belong to which bus.
48 |
49 | #### 1.1.1 Manually unplugging devices
50 |
51 | The easier way (that also works in some corner cases like virtual devices) is to simply read all devices files, plug the device in or out and read again all devices files and compare them to the ones prior:
52 |
53 | ```bash
54 | $ ls -l /dev > before.txt # After this command plug the device in
55 | $ ls -l /dev > after.txt
56 | $ diff before.txt after.txt
57 | ...
58 | crw-rw---- 1 root dialout 188, 0 Feb 4 16:00 ttyUSB0
59 | ...
60 | ```
61 |
62 | This outputs directly the major (in this case 188) and minor (in this case 0) device driver numbers (in this case for a [Life Performance Research LPMS-IG1 IMU](https://www.lp-research.com/9-axis-imu-with-gps-receiver-series/)).
63 |
64 | Sometimes you can already guess from the given date which of the device files belong to your device.
65 |
66 | This means I will add a `device_cgroup_rule` that looks as follows:
67 |
68 | ```yaml
69 | 9 volumes:
70 | 10 - /dev:/dev
71 | 11 device_cgroup_rules:
72 | 12 - 'c 188:* rmw'
73 | ```
74 |
75 | Do not consider the minor version as it might change depending on what other devices are connected.
76 |
77 | #### 1.2.1 Through `lsusb`
78 |
79 | Another way of doing so is to connect the information from `lsusb` to the device file using the vendor and product information. There are a couple of ways to associate a given device and its `/dev` path.
80 |
81 | The probably easiest way is to simply run [the following script](https://unix.stackexchange.com/a/144735)
82 |
83 | ```bash
84 | #!/bin/bash
85 |
86 | for sysdevpath in $(find /sys/bus/usb/devices/usb*/ -name dev); do
87 | (
88 | syspath="${sysdevpath%/dev}"
89 | devname="$(udevadm info -q name -p $syspath)"
90 | [[ "$devname" == "bus/"* ]] && exit
91 | eval "$(udevadm info -q property --export -p $syspath)"
92 | [[ -z "$ID_SERIAL" ]] && exit
93 | echo "/dev/$devname - $ID_SERIAL"
94 | )
95 | done
96 | ```
97 |
98 | This should already output something like
99 |
100 | ```bash
101 | ...
102 | /dev/ttyUSB0 - Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_IG1232600680056
103 | ...
104 | ```
105 |
106 | I normally do [the following](https://unix.stackexchange.com/questions/81754/how-to-match-a-ttyusbx-device-to-a-usb-serial-device) manually: I first check the connected devices with `lsusb`, potentially unplugging and plugging it in again to see which is which:
107 |
108 | ```bash
109 | $ lsusb -tvv
110 | ...
111 | /: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/15p, 480M
112 | ID 1d6b:0002 Linux Foundation 2.0 root hub
113 | /sys/bus/usb/devices/usb3 /dev/bus/usb/003/001
114 | |__ Port 5: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
115 | ID 17aa:1034
116 | /sys/bus/usb/devices/3-5 /dev/bus/usb/003/002
117 | |__ Port 4: Dev 8, If 0, Class=Vendor Specific Class, Driver=cp210x, 12M
118 | ID 10c4:ea60 Silicon Labs CP210x UART Bridge
119 | /sys/bus/usb/devices/3-5.4 /dev/bus/usb/003/008
120 | ...
121 | ```
122 |
123 | You might be interested in more details about the device `$ lsusb -d 10c4:ea60 -v`.
124 |
125 | To see which `/dev` path is associated with it I will check the output of:
126 |
127 | ```bash
128 | $ ls -l /sys/bus/usb-serial/devices # And /sys/bus/usb/devices
129 | total 0
130 | lrwxrwxrwx 1 root root 0 Feb 4 16:00 ttyUSB0 -> ../../../devices/pci0000:00/0000:00:14.0/usb3/3-5/3-5.4/3-5.4:1.0/ttyUSB0
131 | $ grep PRODUCT= /sys/bus/usb-serial/devices/ttyUSB0/../uevent
132 | PRODUCT=10c4/ea60/100
133 | ```
134 |
135 | This means that `ttyUSB0` is assocated to `10c4:ea60` which is the device we are looking for.
136 |
137 | Now I will check the associated major and minor number with:
138 |
139 | ```bash
140 | $ ls -l /dev
141 | ...
142 | crw-rw---- 1 root dialout 188, 0 Feb 4 16:00 ttyUSB0
143 | ...
144 | ```
145 |
146 | In my case major `188`, minor `0` for `ttyUSB0`, which is my device `10c4:ea60`. Then proceed to add the major number to your `docker-compose.yml` like outlined above.
147 |
148 | ## 2. Storage devices
149 |
150 | For mounting storage devices such as USBs and external hard drives it is sufficient to **mount `/media` or one of its specific subfolders as a volume**:
151 |
152 | ```yaml
153 | 9 volumes:
154 | 10 - /media:/media
155 | ```
156 |
--------------------------------------------------------------------------------
/doc/AdvancedTopics.md:
--------------------------------------------------------------------------------
1 | # Advanced topics
2 |
3 | Author: [Tobit Flatscher](https://github.com/2b-t) (2021 - 2024)
4 |
5 |
6 |
7 | ## Overview
8 |
9 | If you have followed this guide so far, then you should have understood the basics of Docker. There are still some topics I would like to discuss that might be helpful. This section links to the corresponding external documentation or accompanying documents.
10 |
11 | ## 1. Setting up Visual Studio Code
12 |
13 | In the last few years [Microsoft Visual Studio Code has become the most used editor](https://insights.stackoverflow.com/survey/2021), becoming the first Microsoft product to be widely accepted by programmers (which is quite remarkable as they have a history of developing toolchains highly criticized by developers :). The guide [`VisualStudioCodeSetup.md`](./VisualStudioCodeSetup.md) walks you through the set-up of a Docker with Visual Studio Code.
14 |
15 | ## 2. Graphic user interfaces
16 |
17 | As pointed out earlier Docker was never intended for graphic user interfaces and integrating them is slightly tricky as graphic user-interfaces are not part of the kernel but that does not mean that it can't be done. Graphic user interfaces are particularly vital when developing with ROS. The main disadvantage of graphic user interfaces with Docker is though that there is no real portable way of doing so. It highly depends on the operating system that you are using and the manufacturer of your graphics card. The document [`Gui.md`](./Gui.md) discusses a simple way of doing so for Linux operating systems.
18 |
19 | ## 3. ROS inside Docker
20 |
21 | Working with the Robot Operating System (ROS) or its successor ROS 2 might pose particular challenges, such as working with hardware and network discovery of other nodes. I have written down some notes of how I generally structure my Dockers in [`Ros.md`](./Ros.md). In particular this is concerned with working with hardware, multiple machines and time synchronization between them.
22 |
23 | ## 4. Docker on Windows
24 |
25 | Docker as a technology builds on the Linux operating system but can be run on other operating systems as well with a lightweight virtual machine in between. An interesting option is running it on Windows with WSL 2 which allows you also to visualize graphic user interfaces. This is discussed in more detail in [`Windows.md`](./Windows.md).
26 |
27 | ## 5. Users and safety
28 |
29 | A few problems emerge with user rights and shared volumes when working from a Docker as discussed [in this Stackoverflow post](https://stackoverflow.com/questions/68155641/should-i-run-things-inside-a-docker-container-as-non-root-for-safety) and in more detail [in this blog post](https://jtreminio.com/blog/running-docker-containers-as-current-host-user/). In particular it might be that the container might not be able to write to the shared volume or vice versa the host user can only delete folders created by the Docker user when being a super-user. As outlined in the latter, there are ways to work around this, passing the current user id and group as input arguments to the container. In analogy with Docker-Compose one might default to the root user or change to the current user if [arguments are supplied](https://stackoverflow.com/questions/34322631/how-to-pass-arguments-within-docker-compose).
30 |
31 | I personally use Dockers in particular for developing and I am not too bothered about being super-user inside the container. If you are, and depending on your use case you should be (in particular for security reasons), then have a look at the linked posts as well as the [Visual Studio Code guide on this](https://code.visualstudio.com/remote/advancedcontainers/add-nonroot-user).
32 |
33 | What I generally do is use the **environment variables `${USER}` or `${USERNAME}`**, if provided or else assume reasonable default values, pass them into the container as arguments. Most users will have a user id and a group id corresponding to `1000` as these values are given to the first user account.
34 |
35 | ```yaml
36 | version: "3.9"
37 | services:
38 | ros2_docker:
39 | build:
40 | context: ..
41 | dockerfile: docker/Dockerfile
42 | args:
43 | - USERNAME=${USERNAME:-developer}
44 | - UID=1000
45 | - GID=1000
46 | ```
47 |
48 | and then create a corresponding user inside the Docker
49 |
50 | ```dockerfile
51 | RUN apt-get update \
52 | && apt-get install -y \
53 | sudo \
54 | && rm -rf /var/lib/apt/lists/*
55 | RUN addgroup --gid ${GID} ${USERNAME} \
56 | && adduser --disabled-password --gecos '' --uid ${GID} --gid ${GID} ${USERNAME} \
57 | && echo ${USERNAME} ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/${USERNAME} \
58 | && chown -R ${UID}:${GID} /home/${USERNAME}
59 |
60 | USER ${USERNAME}
61 | ```
62 |
63 | This results in the same user being used inside the Docker than on a Linux-based host system.
64 |
65 | You can also put the values for `UID` and `GID` into the environment file so that the user can modify them easily.
66 |
67 | ## 6. Multi-stage builds
68 |
69 | Another interesting topic for **slimming down the resulting containers** as mentioned before are [multi-stage builds](https://docs.docker.com/build/building/multi-stage/) where only the files necessary for running are kept and every unnecessary ballast is removed. It is one of those things that you might have a look at when trying to mastering [Docker best practices](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/).
70 |
71 | What I generally use multi-stage builds for is stopping at a specific build stage. Inside my Dockerfile I have a base image for the basic ROS set-up as well as a developer image that adds developer tools on top of it:
72 |
73 | ```dockerfile
74 | ##############
75 | # Base image #
76 | ##############
77 | FROM ros:humble-ros-base as base
78 |
79 | # Here I install my basic packages, ROS packages and set up the middleware
80 |
81 | #####################
82 | # Development image #
83 | #####################
84 | FROM base as dev
85 |
86 | # Here I install developer tools for monitoring and visualization as well as create users
87 | ```
88 |
89 | Then inside my `docker-compose` file I can stop either at the `base` or the `dev` stage as follows:
90 |
91 | ```yaml
92 | version: "3.9"
93 | services:
94 | ros2_docker:
95 | build:
96 | context: ..
97 | dockerfile: docker/Dockerfile
98 | target: dev
99 | ```
100 |
101 | ## 7. Real-time code
102 |
103 | As mentioned another point that is often not discussed is what steps are necessary for running real-time code from inside a Docker. As outlined in [this IBM research report](https://domino.research.ibm.com/library/cyberdig.nsf/papers/0929052195DD819C85257D2300681E7B/$File/rc25482.pdf), the impact of Docker on the performance can be very low if launched with the correct options. After all you are using the kernel of the host system and the same scheduler. I have discussed this also in more detail in a [dedicated repository](https://github.com/2b-t/docker-realtime), in particular focussing on `PREEMPT_RT` which is likely the most relevant for robotics.
104 |
105 | ## 8. Deployment
106 |
107 | One might develop inside a container by mounting all necessary directories into the container. For simplicity one might be `root` inside the container. When deploying a container commonly a dedicated release image named e.g. `Dockerfile.release` will be created. This container might use the development image and instead of mounting the corresponding source code into the container the **required dependencies will be installed from Debian packages**. Ideally we have a CI-pipeline that produces these Debian packages (e.g. a Github Action in each repository such as [this](https://github.com/arkane-systems/apt-repo-update)) and another CI-pipeline that pushes the development image to our Docker registry (e.g. for Github Actions see [here](https://docs.github.com/en/actions/publishing-packages/publishing-docker-images)). Both of these can then trigger the generation of the release Dockerfile located in a different repository (e.g. for Github Actions see [here](https://github.com/marketplace/actions/trigger-external-workflow)). Additionally we will use another non-root user inside the Docker.
108 |
109 | ```dockerfile
110 | # We start from the development image or from the base stage if using multi-stage builds
111 | FROM some_user/some_repo:devel
112 |
113 | # We will install now packages as Debians instead of mounting the source code
114 | RUN echo "deb http://packages.awesome-robot.org/robot/ubuntu focal main" > /etc/apt/sources.list.d/awesome-latest.list
115 | RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 00000000000000000000000000000000
116 | RUN apt-get update \
117 | && apt-get install -y --no-install-recommends \
118 | some-awesome-robot-full=1.0.0 \
119 | && rm -rf /var/lib/apt/lists/*
120 |
121 | # Set-up a new user without password inside the Docker (see also the dedicated section above)
122 | ARG USERNAME=some_user
123 | ARG UID=1000
124 | ARG GID=1000
125 |
126 | RUN apt-get update \
127 | && apt-get install -y \
128 | sudo \
129 | && rm -rf /var/lib/apt/lists/*
130 | RUN addgroup --gid ${GID} ${USERNAME} \
131 | && adduser --disabled-password --gecos '' --uid ${GID} --gid ${GID} ${USERNAME} \
132 | && chown -R ${UID}:${GID} /home/${USERNAME}
133 |
134 | USER ${USERNAME}
135 |
136 | # Entrypoint script sources our workspace and launch the main launch file
137 | ENTRYPOINT["entrypoint.sh"]
138 | ```
139 |
140 |
--------------------------------------------------------------------------------
/doc/Motivation.md:
--------------------------------------------------------------------------------
1 | # Motivation
2 |
3 | Author: [Tobit Flatscher](https://github.com/2b-t) (2021 - 2023)
4 |
5 |
6 |
7 | ## 1. Overview
8 |
9 | When I (as a robotics developer) tell people that none of my computers have ROS installed on them, at least not on the host system, I mostly get puzzled looks. But **using Docker as an isolated development environment is a strategy that is shared by most leading companies and research institutions in robotics**. First and foremost we have **PickNik robotics** (they have customers including Google, Amazon, Samsung, Intel and NASA), a consulting agency for robotics that employs arguably some of the most brilliant and respected robotics engineers, that recommend using Docker for development as well as deployment as [outlined in this presentation of theirs](https://picknik.ai/ros/robotics/docker/2021/07/20/Vatan-Aksoy-Tezer-Docker.html). **Open Robotics** (OSRF), the main driver behind ROS has been using Docker as the backbone of their [build infrastructure](https://github.com/ros-infrastructure/ros_buildfarm) almost ever since Docker came out in 2013. They also provide the [official ROS images on Dockerhub](https://github.com/osrf/docker_images) as well as tools such as [Rocker](https://github.com/osrf/rocker) for working with graphic user interfaces from inside a Docker in a portable way. The ROS Industrial industrial training uses Docker in certain parts of its tutorials such as for [cloud computing](https://industrial-training-master.readthedocs.io/en/melodic/_source/session6/Docker-AWS.html). [Pal Robotics](https://github.com/pal-robotics/pal_docker_utils) and [Stogl robotics](https://rtw.stoglrobotics.de/master/docker/index.html) offer utilities for developing robotic applications with Docker. Furthermore you will find workflows and tools for leading research Institutions like [**Fraunhofer IPA**](https://github.com/ct2034/dockeros), [**DFKI**](https://github.com/dfki-ric/docker_image_development), **IIT** [[1]](https://github.com/diegoferigo/development-iit) [[2]](https://github.com/diegoferigo/ros-kubernetes), [**INRIA**](https://gitlab.inria.fr/locolearn/public/docker_inria_wbc) and [**MIT CSAIL**](https://roboticseabass.com/2021/04/21/docker-and-ros/) online. And finally leading companies like **Boston Dynamics** [[3]](https://dev.bostondynamics.com/docs/payload/docker_containers#) [[4]](https://dev.bostondynamics.com/docs/payload/spot_core_portainer) and [**Sony**](https://github.com/fujitatomoya/ros_k8s) use it for deployment on commercial products.
10 |
11 | Over the last couple of years I have collaborated professionally with different companies and robotics research institutions and met quite a lot of people that would not understand the benefits or even worse would oppose the technology per se without actually having used it. But I managed convince most people so far to give it a go and they immediately see the advantages of Docker for robotics and implement it in their workflow as well. I have not yet quite understood why Docker as a technology has such a negative connotation. Maybe it is simply a lack of understanding (people have tried it and have failed in one way or the other), maybe this is historically grown. Anyways, my goal of this guide is to show best practices that I have found over the last couple of years (working with Docker for robotic software development and by examing workflows of people I worked with or what I could find online). In my opinion Docker as a technology is essential for developing robotics in an efficient and reliable manner.
12 |
13 | As said I do not have ROS installed on my development computers and do not plan to do so. Instead of running a **vanilla system with Docker and my Visual Studio Code IDE installed**. There are a few tools for power management and networking installed on my host machine but all project related-code is put inside a Docker. **Every single workspace has its own dedicated Docker**, I have Dockers for testing particular sensors and robot stacks, some in ROS1, others in ROS2, that all can be run on my host system (currently Ubuntu 22.04). This way I can continue to keep up with the most recent host system and might revive an old retired project at any point (e.g. I have used it to test [traclabs' Affordance Templates stack](https://traclabs.com/projects/affordance-templates/) for ROS Indigo) or try a different distribution. If I need a new container that uses this sensor or robot I either copy the relevant parts from the corresponding Dockerfile or I leverage multi-layer builds to generate the new image starting from the sensor and robot images. Furthermore I might [overlay different workspaces on top of each other](http://wiki.ros.org/catkin/Tutorials/workspace_overlaying) or orchestrate multiple workspaces with Docker-Compose.
14 |
15 |
16 |
17 | ## 2. Why should I use Docker when developing robotics software?
18 |
19 | - **Compatability**:
20 | - Working with robots in ROS generally requires working with **different Ubuntu distributions**. With Docker one can avoid having multiple partitions on the same system and instead **start different distributions from the same host system**. This way for example a ROS Indigo stack can still be run on a Ubuntu 22.04. This is very important as sooner or later robotic stacks have to be retired as they are not state-of-the-art anymore (sensors change, ROS gets replaced by ROS2) but nonetheless one should still be able to run this legacy code without having a legacy computer for every single distribution laying around.
21 | - Furthermore you can have a **non-Debian-based Linux host system** and nonetheless work with ROS if you prefer another Linux distribution over Ubuntu as your daily driver, yet have the convenience of working with Ubuntu when dealing with ROS.
22 | - **Replicability**:
23 | - Robotic stacks often involve a large amount of packages. A single person often won't accomplish much if the application is complex and/or should be deployed commercially. **Multiple people** working on the same workspace should have an **identical set-up with the same software versions**. At the same time each contributor should have a central point were IPs and other parameters can be modified (which do not have to be commited to the common repository everybody is working on together).
24 | - Working with **multiple robotic stacks** even on the same Ubuntu distribution often requires working with **different versions of the same library** for different projects. With Docker this is no issue. One can further perform version pinning, meaning enforce a certain version of a package to increase replicability on another computer.
25 | - As software engineers and researcher develop on a machine they will install an immense amount of software that often is not needed at all but is never uninstalled when not needed anymore. Even an experienced programmer under stress will simply search for a solution on Stackoverflow, take the post with the most upvotes - even if they do not fully understand it - and give it a go. This means no developers system is actually clean, most of them actually contain a lot of useless garbage that gets worse and worse over time. This useless software might impact other code, that might break it or is required to install other packages without the developer knowing, or is incompatible with other packages or certain versions. Working without a fresh system means always carrying this installation history across projects. This leads to situation where code compiles on one computer but does not compile for another person with a slightly different set-up ("But it compiles on my computer..."-situations). From my experience most of the time the reason for these situations are **implicit dependencies and restrictions** that the developer is not aware of and not the fault of the person trying to replicate the set-up. Therefore you as a programmer (or researcher) should be interested in using technologies such as Docker: After all it is your responsability to make your software project and research as replicable as possible, and isolate any previous modifications from your current project.
26 | - **Isolation**:
27 | - Working with different robotic stacks generally also means working on **different networks**. This means robotic developers will generally add new robots they need to communicate with inside their **`/etc/hosts`** configuration. This might lead to collision of IPs and results in different entries having to be commented or uncommented in order to be able to work with a particular robot. Similarly most people add certain definitions and aliases inside their **`.bashrc`** that they will comment and uncomment depending on the project they are currently working on. This is very inconvenient, cumbersome and error-prone. When working with a Docker these **configuration files are specific to a project** and do not leak into workspaces of other robots.
28 | - This isolation can also be very useful for parallelizing simulations. With Docker multiple ROS cores can be run in parallel on the same host system by letting each container have its own network and not exposing it to the other containers.
29 | - **Continuous integration**: Docker is an essential building stone of most continuous integration pipelines. Maintaining a description of the environment that code should be run in is essential for testing your code on a remote server.
30 | - **Fast deployment**: Instead of installing your code from source on a system, installing multiple Debian packages and configuring the network manually you can encapsulate all this in a Docker container and deploy the Docker container as a whole or orchestrate multiple Docker containers (e.g. one container for each node or group of nodes) on the same computer. This means that deploying might only reduce to pulling a single Docker image with the size of a couple of dozen megabytes.
31 |
32 | As guarantueeing these characteristics without the use of Docker is close to impossible, there are many companies and institutions where a robotic software stack only runs only on a particular computer. Nobody is allowed to touch (or at least make significant changes to) that system as if it breaks that robotic system would be rendered useless (or at least inoperable for some time). In my opinion such thing should never happen and is a strategic failure per se. Any robot should be replicable just from a set-up that can be found online in your version control system in a semi-automated fashion without having to go through a long manual set-up routine. A pipeline based on Docker can help with that. **Even if you do not deploy a robot with Docker you should maintain one as a back-up solution** because you never know, it is software.
33 |
34 | ## 3. Why is Docker important in particular for academic and research institutions?
35 |
36 | In particular research institutions are in desperate need for container-based solutions such as Docker - even more than companies in my opinion:
37 |
38 | A company usually is made of a **stable** workforce of **experienced** engineers that work together on a **few** homogeneous products. Any decent company will work towards **common tools** and will have **mechanisms** in place that should **guarantee code quality**. These products will be maintained until they reach their lifecycle after several year and are either retired or replaced, resulting in an overall small variability.
39 |
40 | Academic and research institutions are the complete opposite: Workers and students generally are **fluctuating**, might be motivated and brilliant but are at a start of their career, generally **lacking the experience** and might have very interdisciplinary backgrounds (which is in particular true for robotics where people might come from software, mechanical, electrical or biomedical engineering or might have an even more interdisciplinary background). Furthermore there are close to **no mechanisms in place that guarantee code quality**. The tools the students and research engineers will use are very **heterogeneous**. A large part of the developed code will **not be actively maintained** for an extended period as there are no resources for doing so after a project (and funding) ends. At a certain point projects have to be **retired** nonetheless they should be left **in a replicable state**. Many universities and research institutions fail to have mechanisms in place that help with this. I have already seen many projects die because the main developer left not only taking with themselves the know-how but also any chance of replicating his/her work as the code only worked on their machine. This is a fatal loss for any institution in my opinion as they lost the know-how and significantly reduced their chance of replicating the work (which means after all filling the gap and continuing in that research direction). Many research institutions I had to deal with suffer from a significant slow down due to this which significantly slows down their daily business and growth.
41 |
42 | If you start on a new project it is incredibly frustrating to take over a complex robotic project from somebody that lacks documentation. Even if you have access to their working computer you will likely have to modify their `.bashrc` and network set-up. If you further have to start over with another computer you will have to search for dependencies, fiddling with different versions of libraries and implicit undocumented dependencies. This **slows down and demotivates**. This is particularly true for Bachelor and Master students that are only with these institutions for a limited amount of time. Some might have certain constraints and want to finish their work in a certain limited time frame. This means if you are not able to get them started quickly with a project they will not only lose motivation but also lose valuable time that they could do on research for fixing set-up problems that are structural and actually none of their business. PhD students in robotics might have different backgrounds and might not be familiar with best-practices. Generally they leave after some time without anybody having a complete overview of what they did: After all their supervisor is mainly interested in the scientific output and might not have the time to have a look in detail at the state of the documentation. It is essential to familiarize them with a standard workflow that allows to replicate their work. After all one of the core idea of any research is making findings **replicable** and not only making findings. This is in particular important for medical research where [paradoxically most research findings are actually false](https://journals.plos.org/plosmedicine/article?id=10.1371/journal.pmed.0020124)!
43 |
44 | After all the time effort for setting up and maintaining a Docker is not bigger than installing the libraries by hand but it only works if you immediately introduce your students and junior researchers to these technologies and not only in the middle or towards the end of the project (nobody remembers what they installed half a year, let alone three or four years ago). Furthermore Docker allows you to reset quickly, go back to a previous state. This quickly pays off in particular if more than a single computer has to be used. And the gained time can be spent on research.
45 |
46 | Building this infrastructure and workflows also as an academic institution is a long-term investment, of similar importance to building frameworks rather than single purpose code for a project.
47 |
48 |
49 |
50 | ## 4. What are the drawbacks of Docker?
51 |
52 | For robotics **software development I do not see any drawbacks with using Docker**. After all Docker is a mature technology that is used successfully in many other fields. From my experience there are many prejudices surrounding Docker as a technology but graphic user interfaces, real-time capable code, working with hardware can all be worked around in a reliable and portable manner. This guide will explain how this can be done.
53 |
54 | The only messy thing that one has to watch out for is actually user rights. Giving root privileges to a Docker user is probably not a good idea if you deploy the container, as an intruder might gain access to the host system in particular when running a container as `privileged`. On the other hand using another user might result in problems when sharing volumes as pointed out later on.
55 |
--------------------------------------------------------------------------------
/doc/Gui.md:
--------------------------------------------------------------------------------
1 | # Graphic user interfaces inside Docker
2 |
3 | Author: [Tobit Flatscher](https://github.com/2b-t) (2021 - 2023)
4 |
5 |
6 |
7 | ## 1. Different approaches
8 |
9 | Running user interfaces from inside a Docker might not be its intended usage but as of now there are several options available. The problem with all of them is that most of them are specific to **Linux** operating systems (but can also be used in Windows under the **Windows Subsystem for Linux** (WSL 2). On the the [ROS Wiki](http://wiki.ros.org/docker/Tutorials/GUI) the different options are discussed in more detail:
10 |
11 | - In Linux there are several ways of connecting a containers output to a host's **X server** resulting in an output which is indistinguishable from a program running on the host directly. This is the approach chosen for this guide. It is quite portable but requires additional steps for graphics cards running with nVidia hardware acceleration rather than the Linux Nouveau display driver. OSRF has also released [Rocker](https://github.com/osrf/rocker) as a tool to support mounting folders and launching graphic user interfaces. I did not use it as I try to avoid introducing unnecessary dependencies.
12 | - Other common approaches are less elegant and often use some sort of **Virtual Network Computing (VNC)** which streams the entire desktop to the host over a dedicated window similar to connecting virtually to a remote machine. This is usually the approach chosen for other operating systems such as Windows and Macintosh but requires additional software and does not integrate as seemlessly.
13 |
14 | The rest of the guide will focus on graphic user interfaces on Linux by exploiting X-Server. This won't work with native Windows (but works with WSL 2 under Windows as discussed in [`Windows.md`](./Windows.md)) and Mac but I would not encourage using Docker on other operating systems other than Linux anyways.
15 |
16 |
17 |
18 | ## 2. Using X-Server
19 |
20 | As pointed out before this guide uses the Ubuntu X-Server for outputting dialogs from a Docker. The Docker-Compose file with and without Nvidia hardware acceleration look differently and Nvidia hardware acceleration requires a few additional setup steps. These differences are briefly outlined in the sections below. It is worth mentioning that **just having an Nvidia card does not necessitate the Nvidia setup** but instead what matters is the **driver** used for the graphics card. If you are using a Nouveau driver for an Nvidia card then a Docker-Compose file written for hardware acceleration won't work and instead you will have to turn to the Docker-Compose file without it. And vice versa, if your card is managed by the Nvidia driver then the first approach won't work for you. This fact is in particular important for the `PREEMPT_RT` patch: You won't be able to use your Nvidia driver when running the patch. Your operating system might mistakenly tell you that it is using the Nvidia driver but it might not. It is therefore important to check the output of `$ nvidia-smi`. If it outputs a managed graphics card, then you will have to go for the second approach with hardware acceleration. If it does not output anything or is not even installed go for the Nouveau driver setup.
21 |
22 | You can check in Software and Updates which graphics driver is currently used:
23 |
24 | 
25 |
26 |
27 |
28 | In any case before being able to **stream to the X-Server on the host system** you will have to run the following command inside the **host system**:
29 |
30 | ```bash
31 | $ xhost +local:root
32 | ```
33 |
34 | where `root` corresponds to the user-name of the user used inside the Docker container. This command has to be **repeated after each restart** of the host system.
35 |
36 | If you do not execute this command before launching a graphic user interface the application will not be able to connect to the display. For Rviz for example this might look as follows:
37 |
38 | ```bash
39 | $ root@P500:/ros_ws# rosrun rviz rviz
40 | Authorization required, but no authorization protocol specified
41 | qt.qpa.xcb: could not connect to display :0
42 | qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
43 | This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
44 |
45 | Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, xcb.
46 |
47 | Aborted (core dumped)
48 | ```
49 |
50 | In case graphic user interfaces do not open up correctly be sure to check the `DISPLAY` variable is set correctly. Output `$ echo ${DISPLAY}` on both, the host system as well as inside the container, and make sure they correspond.
51 |
52 |
53 |
54 | ### 2.1 Nouveau and AMD driver
55 |
56 | As pointed out in the second before this type of setup applies to any card that is not managed by an Nvidia driver, even if the card is an Nvidia card. In such a case it is sufficient to share the following few folders with the host system. The `docker-compose.yml` might look as follows:
57 |
58 | ```yaml
59 | version: "3.9"
60 | services:
61 | some_name:
62 | build:
63 | context: .
64 | dockerfile: Dockerfile
65 | tty: true
66 | environment:
67 | - DISPLAY=${DISPLAY} # Option for sharing the display
68 | - QT_X11_NO_MITSHM=1 # For Qt
69 | volumes:
70 | - /tmp/.X11-unix:/tmp/.X11-unix:rw # Share system folder
71 | - /tmp/.docker.xauth:/tmp/.docker.xauth:rw # Share system folder
72 | ```
73 |
74 | ### 2.2 Hardware acceleration with Nvidia cards
75 |
76 | This section is only relevant for Nvidia graphic cards managed by the Nvidia driver or if you want to have hardware acceleration inside the Docker, e.g. for using CUDA or OpenGL. Graphic user interfaces that do not require it will work fine in any case. As also pointed out [in the ROS tutorial](http://wiki.ros.org/docker/Tutorials/Hardware%20Acceleration) having hardware acceleration is actually more tricky! Nvidia offers a dedicated [`nvidia-docker`](https://github.com/NVIDIA/nvidia-docker) (with two different options `nvidia-docker-1` and `nvidia-docker-2` which sightly differ) as well as the [`nvidia-container-runtime`](https://nvidia.github.io/nvidia-container-runtime/). Latter was chosen for this guide as it seems to be the way from now onwards and will be discussed below.
77 |
78 | #### 2.2.1 Installing the `nvidia-container-toolkit`
79 |
80 | The [`nvidia-container-runtime`](https://nvidia.github.io/nvidia-container-runtime/) (see installation instructions [here](https://stackoverflow.com/a/59008360)) is now deprecated and you should install the [`nvidia-container-toolkit`](https://github.com/NVIDIA/nvidia-container-toolkit) instead. Before following through with the installation make sure it is not already set-up on your system. For this check the `runtime` field from the output of `$ docker info`. If `nvidia` is available as an option already you should be already good to go.
81 |
82 | If it is not available you should be able to install it with the [following steps](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html):
83 |
84 | ```bash
85 | $ curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
86 | && curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
87 | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
88 | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
89 | $ sudo apt-get update
90 | $ sudo apt-get install -y nvidia-container-toolkit
91 | ```
92 |
93 | and then [set-up the Docker runtime](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#configuration):
94 |
95 | ```bash
96 | $ sudo nvidia-ctk runtime configure --runtime=docker
97 | ```
98 |
99 | After these steps you might will have to restart the system or at least the Docker daemon with `$ sudo systemctl daemon-reload` and `$ sudo systemctl restart docker`. Then `$ docker info` should output at least two different runtimes, the default `runc` as well as `nvidia`. This runtime can be set in the Docker-Compose file and one might have to set the `environment variables` `NVIDIA_VISIBLE_DEVICES=all` and `NVIDIA_DRIVER_CAPABILITIES=all`. Be aware that this will fail when launching it on other system without that runtime. You will need another dedicated Docker-Compose file for non-nVidia graphic cards!
100 |
101 | A Docker-Compose configuration for the Nvidia graphics cards with the Nvidia graphics driver looks as follows:
102 |
103 | ```yaml
104 | version: "3.9"
105 | services:
106 | some_name:
107 | build:
108 | context: .
109 | dockerfile: Dockerfile
110 | tty: true
111 | environment:
112 | - DISPLAY=${DISPLAY}
113 | - QT_X11_NO_MITSHM=1
114 | - NVIDIA_VISIBLE_DEVICES=all # Share devices of host system
115 | - NVIDIA_DRIVER_CAPABILITIES=all # This allows the guest system to use the GPU also for visualization
116 | runtime: nvidia # Specify runtime for container
117 | volumes:
118 | - /tmp/.X11-unix:/tmp/.X11-unix:rw
119 | - /tmp/.docker.xauth:/tmp/.docker.xauth:rw
120 | ```
121 |
122 | Depending on how your system is configured your computer might still decide to use the integrated Intel Graphics instead of your Nvidia card in order to save power. In this case I'd recommend you to switch the Nvidia X Server (that is automatically installed with the driver) to performance mode instead of on-demand as shown in the screenshot below. This way the Nvidia card should always be used instead of the Intel Graphics.
123 |
124 | 
125 |
126 |
127 |
128 | #### 2.2.2 Testing the graphic acceleration inside your container
129 |
130 | After following above steps **make sure that inside your container you can use `nvidia-smi`** and it finds your card:
131 |
132 | ```bash
133 | $ nvidia-smi
134 | Wed Jun 21 00:01:46 2023
135 | +---------------------------------------------------------------------------------------+
136 | | NVIDIA-SMI 530.41.03 Driver Version: 530.41.03 CUDA Version: 12.1 |
137 | |-----------------------------------------+----------------------+----------------------+
138 | | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
139 | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
140 | | | | MIG M. |
141 | |=========================================+======================+======================|
142 | | 0 Quadro K2200 Off| 00000000:03:00.0 On | N/A |
143 | | 42% 39C P8 1W / 39W| 430MiB / 4096MiB | 10% Default |
144 | | | | N/A |
145 | +-----------------------------------------+----------------------+----------------------+
146 |
147 | +---------------------------------------------------------------------------------------+
148 | | Processes: |
149 | | GPU GI CI PID Type Process name GPU Memory |
150 | | ID ID Usage |
151 | |=======================================================================================|
152 | +---------------------------------------------------------------------------------------+
153 | ```
154 |
155 | In case the command is not recognized, make sure that you can run it successfully outside the Docker. In case it does not even work outside the Nvidia driver you are currently using is likely incompatible with your graphics card. In case it just does not work inside the Docker likely you made a mistake in your Docker-Compose file.
156 |
157 | Just seeing the card with `nvidia-smi` is though not sufficient. If you do not **set the environment variable `NVIDIA_DRIVER_CAPABILITIES`**, e.g. to `NVIDIA_DRIVER_CAPABILITIES=graphics,utility,compute` or **`NVIDIA_DRIVER_CAPABILITIES=all`** the graphic acceleration will not work properly.
158 |
159 | For testing if the graphic acceleration actually works inside the Docker you can use the **`glxgears`** application. Install it with
160 |
161 | ```bash
162 | $ sudo apt-get install mesa-utils
163 | ```
164 |
165 | on your host system as well as inside the container and compare the two.
166 |
167 | Then run it with
168 |
169 | ```bash
170 | $ glxgears -info
171 | ```
172 |
173 | This should visualize the following window and output the following information:
174 |
175 | 
176 |
177 | ```
178 | GL_RENDERER = Quadro K2200/PCIe/SSE2
179 | GL_VERSION = 4.6.0 NVIDIA 530.41.03
180 | GL_VENDOR = NVIDIA Corporation
181 | ```
182 |
183 | as well as the current frames per second `8579 frames in 5.0 seconds = 1715.776 FPS` every couple of seconds. On a laptop with an additional integrated graphics card this already should tell you which of the two, the dedicated or the integrated one, is being used.
184 |
185 | In case you did not set `NVIDIA_DRIVER_CAPABILITIES` inside the container the output from `glxgears` will look as follows and you might observe stuttering in applications such as Gazebo:
186 |
187 | ```
188 | GL_RENDERER = llvmpipe (LLVM 12.0.0, 256 bits)
189 | GL_VERSION = 3.1 Mesa 21.2.6
190 | GL_VENDOR = Mesa/X.org
191 | ```
192 |
193 |
194 |
195 | #### 2.2.3 Hybrid graphics cards and power management
196 |
197 | On computers with an integrated graphics card (e.g. notebooks), you might run into issues where graphic acceleration might not work as power management will choose the integrated graphics card over the dedicated one. Run [`$ prime-select query`](https://github.com/linuxmint/nvidia-prime/blob/master/prime-select) to see what the output is (`nvidia`, `intel` or `on-demand`). Depending on the output the open-source or Nvidia version of libGL will be used. You can switch between them by executing `$ prime-select nvidia`. Similarly you can output the available graphic processors with `$ xrandr --listproviders`. In case you have an integrated and dedicated graphic card there should be two entries: `0` and `1` where the order depends on the setting of `prime-select`.
198 |
199 | You should be able to switch between the two with [**PRIME offloading**](https://wiki.archlinux.org/title/PRIME). Defining the environment variable `DRI_PRIME` allows you to use the discrete graphics card e.g. `DRI_PRIME=1 glxinfo`. Similarly Nvidia exposes the environment variable [`__NV_PRIME_RENDER_OFFLOAD`](https://download.nvidia.com/XFree86/Linux-x86_64/435.17/README/primerenderoffload.html) for this purpose, e.g. `$ __NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia glxinfo`. Finally you can use `prime-run` to force a program to offload to the dedicated Nvidia GPU:
200 |
201 | ```bash
202 | $ prime-run some_program
203 | ```
204 |
205 |
206 |
207 | #### 2.2.4 Running containers as `privileged`
208 |
209 | In some rare instances with hybrid graphics cards, **hardware acceleration might not work correctly** resulting in e.g. [Rviz outputting the following](https://github.com/moby/moby/issues/38442):
210 |
211 | ```bash
212 | $ rviz
213 | dbus[97]: The last reference on a connection was dropped without closing the connection. This is a bug in an application. See dbus_connection_unref() documentation for details.
214 | Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.
215 | D-Bus not built with -rdynamic so unable to print a backtrace
216 | Aborted (core dumped)
217 | ```
218 |
219 | In this case what might help is **running the container as `privileged`**.
220 |
221 |
222 |
223 | ### 2.3 Avoiding duplicate configurations
224 |
225 | You can already see that there are quite a few common options between the two configurations. While sadly Docker-Compose does not have conditional execution (yet) one might [override or extend an existing configuration file](https://github.com/Yelp/docker-compose/blob/master/docs/extends.md) (see also [`extends`](https://docs.docker.com/compose/extends/) as well this [Visual Studio Code guide](https://code.visualstudio.com/docs/remote/create-dev-container#_extend-your-docker-compose-file-for-development)).
226 |
227 | I normally start by creating a base Docker-Compose file `docker-compose.yml` that does not support graphic cards
228 |
229 | ```yaml
230 | version: "3.9"
231 | services:
232 | some_name:
233 | build:
234 | context: .
235 | dockerfile: Dockerfile
236 | tty: true
237 | ```
238 |
239 | that is then extended for graphic user interfaces without Nvidia driver `docker-compose-gui.yml`,
240 |
241 | ```yaml
242 | version: "3.9"
243 | services:
244 | some_name:
245 | extends:
246 | file: docker-compose.yml
247 | service: some_name
248 | environment:
249 | - DISPLAY=${DISPLAY}
250 | - QT_X11_NO_MITSHM=1
251 | volumes:
252 | - /tmp/.X11-unix:/tmp/.X11-unix:rw
253 | - /tmp/.docker.xauth:/tmp/.docker.xauth:rw
254 | ```
255 |
256 | on top of that goes another Docker-Compose file with Nvidia acceleration `docker-compose-gui-nvidia.yml`
257 |
258 | ```yaml
259 | version: "3.9"
260 | services:
261 | some_name:
262 | extends:
263 | file: docker-compose-gui.yml
264 | service: some_name
265 | environment:
266 | - NVIDIA_VISIBLE_DEVICES=all
267 | - NVIDIA_DRIVER_CAPABILITIES=all
268 | runtime: nvidia
269 | ```
270 |
271 | and finally I have yet another file which can be launched for hardware acceleration without graphic user interfaces `docker-compose-nvidia.yml` which might be used for computations and machine learning containers.
272 |
273 | ```yaml
274 | version: "3.9"
275 | services:
276 | some_name:
277 | extends:
278 | file: docker-compose.yml
279 | service: some_name
280 | environment:
281 | - NVIDIA_VISIBLE_DEVICES=all
282 | runtime: nvidia
283 | ```
284 |
285 | This way if I need to add additional options, I only have to modify the base Docker-Compose file `docker-compose.yml` and the others will simply adapt.
286 |
287 | I can then specify which file should be launched to Docker-Compose with e.g.
288 |
289 | ```bash
290 | $ docker-compose -f docker-compose-gui-nvidia.yml up
291 | ```
292 |
293 |
294 |
295 | ### 2.4 Known issues
296 |
297 | In certain versions of Linux you might run into the problem that **certain applications using hardware acceleration (e.g. Rviz and Gazebo) might not be displayed correctly**, instead black windows are displayed similar to the screenshot below:
298 |
299 | 
300 |
301 | This is a [known bug in the Mesa implementation of OpenGL present on e.g. Ubuntu 22.04](https://github.com/ros2/rviz/issues/948#issuecomment-1427569107) and can be resolved by **upgrading Mesa or by switching to Nvidia's implementation by using the Nvidia container runtime** (in case you have an Nvidia grapics card).
302 |
303 | The update can be performed by running the following commands inside the Docker container
304 |
305 | ```bash
306 | $ apt-get install software-properties-common
307 | $ add-apt-repository ppa:kisak/kisak-mesa
308 | $ apt-get update
309 | $ apt-get upgrade
310 | ```
311 |
312 | or by adding an additional layer to your Dockerfile:
313 |
314 | ```dockerfile
315 | RUN apt-get update \
316 | && apt-get install -y \
317 | install software-properties-common \
318 | && add-apt-repository ppa:kisak/kisak-mesa \
319 | && apt-get update \
320 | && apt-get upgrade -y \
321 | && rm -rf /var/lib/apt/lists/*
322 | ```
323 |
--------------------------------------------------------------------------------
/doc/Ros.md:
--------------------------------------------------------------------------------
1 | # ROS inside Docker
2 |
3 | Author: [Tobit Flatscher](https://github.com/2b-t) (2021 - 2023)
4 |
5 |
6 |
7 | ## 1. ROS/ROS 2 with Docker
8 |
9 | I personally think that Docker is a good choice for **developing** robotic applications as it allows you to quickly switch between different projects but **less so for deploying** software. Refer to [this Canonical article](https://ubuntu.com/blog/ros-docker) to more details about the drawbacks of deploying software with Docker, in particular regarding security. For the deployment I personally would rather turn to Debian or Snap packages (see e.g. [Bloom](http://wiki.ros.org/bloom/Tutorials/FirstTimeRelease)). But there are actually quite a few companies that I am aware of that actually use Docker for deployment as well, first and foremost [Boston Dynamics](https://dev.bostondynamics.com/docs/payload/docker_containers#).
10 |
11 | The ROS Wiki offers tutorials on ROS and Docker [here](http://wiki.ros.org/docker/Tutorials), there is also a very useful [tutorial paper](https://www.researchgate.net/publication/317751755_ROS_and_Docker) out there and another interesting article can be found [here](https://roboticseabass.com/2021/04/21/docker-and-ros/). Furthermore a list of important commands can be found [here](https://tuw-cpsg.github.io/tutorials/docker-ros/). After installing Docker one simply pulls an image of ROS, specifying the version tag:
12 |
13 | ```bash
14 | $ sudo docker pull ros
15 | ```
16 |
17 | gives you the latest ROS 2 version whereas
18 |
19 | ```bash
20 | $ sudo docker pull ros:noetic-robot
21 | ```
22 |
23 | will pull the latest version of ROS1.
24 |
25 | Finally you can run it with
26 |
27 | ```bash
28 | $ sudo docker run -it ros
29 | ```
30 |
31 | (where `ros` should be replaced by the precise version tag e.g. `ros:noetic-robot`).
32 |
33 | The OSRF ROS Docker provides a readily available entrypoint script `ros_entrypoint.sh` that automatically sources `/opt/ros//setup.bash`.
34 |
35 | ### 1.1 Folder structure
36 |
37 | I generally structure Dockers for ROS in the following way:
38 |
39 | ```
40 | ros_ws
41 | ├─ docker
42 | | ├─ Dockerfile
43 | | └─ docker-compose.yml # Context is chosen as ..
44 | └─ src # Only this folder is mounted into the Docker
45 | ├─ .repos # Configuration file for VCS tool
46 | └─ packages_as_submodules
47 | ```
48 |
49 | Each ROS-package or a set of ROS packages are bundled together in a Git repository. These are then included as submodules in the `src` folder or even better by using [VCS tool](https://github.com/dirk-thomas/vcstool). Inside the `docker-compose.yml` file one then **mounts only the `src` folder as volume** so that it can be also accessed from within the container. This way the build and devel folders remain inside the Docker container and you can compile the code inside the Docker as well as outside (e.g. having two version of Ubuntu and ROS for testing in with different distributions).
50 |
51 | Generally I have more than a single `docker-compose.yml` as discussed in [`Gui.md`](./Gui.md) and I will add configuration folders for Visual Studio Code and a configuration for the Docker itself, as well as dedicated tasks. I usually work inside the container and install new software there first. I will keep then track of the installed software manually and add it to the Dockerfile as soon as it has proved useful.
52 |
53 | ### 1.2 Docker configurations
54 |
55 | You will find quite a few Docker configurations for ROS online, in particular [this one](https://github.com/athackst/vscode_ros2_workspace) for ROS 2 is quite well made. Another one for ROS comes with this repository.
56 |
57 | ### 1.4 Larger software stacks
58 |
59 | When working with larger software stacks tools like [Docker-Compose](https://docs.docker.com/compose/) and [Docker Swarm](https://docs.docker.com/engine/swarm/stack-deploy/) might be useful for **orchestration**, in particular when deploying with Docker. This is discussed in several separate repositories such as [this one](https://github.com/fujitatomoya/ros_k8s) by Tomoya Fujita, member of the Technical Steering Committee of ROS 2.
60 |
61 | ## 2. ROS
62 |
63 | This section will got into how selected ROS 1 configuration settings can be simplified with Docker, in particular the network set-up.
64 |
65 | ### 2.1 External ROS master
66 |
67 | Sometimes you want to run nodes inside the Docker and communicate with a ROS master outside of it. This can be done by adding the following **environment variables** to the `docker-compose.yml` file
68 |
69 | ```bash
70 | 9 environment:
71 | 10 - ROS_MASTER_URI=http://localhost:11311
72 | 11 - ROS_HOSTNAME=localhost
73 | ```
74 |
75 | where in this case `localhost` stands for your local machine (the loop-back device `127.0.0.1`).
76 |
77 | #### 2.1.1 Multiple machines
78 |
79 | In case you want the Docker to communicate with another device on the network be sure to activate the option
80 |
81 | ```bash
82 | 15 network_mode: host
83 | 16 extra_hosts:
84 | 17 - "my_device:192.168.100.1"
85 | ```
86 |
87 | as well, where `my_device` corresponds to the host name followed by its IP. The **`extra_hosts`** option basically adds another entry to your **`/etc/hosts` file inside the container**, similar to what you would do manually normally in the [ROS network setup guide](https://wiki.ros.org/ROS/NetworkSetup). This way the network set-up inside the Docker does not pollute the host system.
88 |
89 | Now make sure that pinging works **in both directions**. In case there was an issue with a firewall (or VPN) pinging might only work in one direction. If you would continue with your set-up you might be able to receive information (e.g. visualize the robot and its sensors) but not send it (e.g. command the robot). Furthermore ROS relies on the correct host name being set: If it does not correspond to the name of the remote computer the communication might also only work in one direction. For time synchronization of multiple machines it should be possible to run [`chrony`](https://robofoundry.medium.com/how-to-sync-time-between-robot-and-host-machine-for-ros2-ecbcff8aadc4) from inside a container without any issues. For how this can be done please refer to [cturra/ntp](https://github.com/cturra/docker-ntp) or alternatively to [this guide](http://www.freekb.net/Article?id=3292). After setting it up use `$ chronyc sources` as well as `$ chronyc tracking` to verify the correct set-up.
90 |
91 | You can test the communication between the two machines by sourcing the environment, launching a `roscore` on your local or remote computer, then launch the Docker source the local environment and see if you can see any topics inside `$ rostopic list`. Then you can start publishing a topic `$ rostopic pub /testing std_msgs/String "Testing..." -r 10` on one side (either Docker or host) and check if you receive the messages on the other side with `$ rostopic echo /testing`. If that works fine in both directions you should be ready to go. If it only works in one direction check your host configuration and your `ROS_MASTER_URI` and `ROS_HOSTNAME` environement variables.
92 |
93 | As a best practice I normally use a [`.env` file](https://vsupalov.com/docker-arg-env-variable-guide/) that I place in the same folder as the `Dockerfile` and the `docker-compose.yaml` containing the IPs:
94 |
95 | ```bash
96 | CATKIN_WORKSPACE_DIR="/catkin_ws"
97 | YOUR_IP="192.168.100.2"
98 | ROBOT_IP="192.168.100.1"
99 | ROBOT_HOSTNAME="some_host"
100 | ```
101 |
102 | The IPs inside this file can then be modified and are used inside the Docker-Compose file to set-up the container: The `/etc/hosts` file as well as the `ROS_MASTER_URI` and the `ROS_HOSTNAME`:
103 |
104 | ```yaml
105 | version: "3.9"
106 | services:
107 | ros_docker:
108 | build:
109 | context: ..
110 | dockerfile: docker/Dockerfile
111 | environment:
112 | - ROS_MASTER_URI=http://${ROBOT_IP}:11311
113 | - ROS_IP=${YOUR_IP}
114 | network_mode: "host"
115 | extra_hosts:
116 | - "${ROBOT_HOSTNAME}:${ROBOT_IP}"
117 | tty: true
118 | volumes:
119 | - ../src:/${CATKIN_WORKSPACE_DIR}/src
120 | ```
121 |
122 | In order to update the IPs though with this approach you will have to rebuild the container. As long as you did not make any modifications to the Dockerfile it should though use the cached layers and should be very quick. But any progress inside the container will be lost when switching IP!
123 |
124 | An example configuration can be found [here](../templates/ros/docker).
125 |
126 | #### 2.1.2 Combining different package and ROS versions
127 |
128 | Combining different ROS 1 versions is not officially supported but largely works as long as message definitions have not changed. This is problematic with constantly evolving packages such as [Moveit](https://moveit.ros.org/). The interface between the containers in this case has to be chosen wisely such that the used messages do not change across between the involved distributions. You can use [`rosmsg md5 `](https://wiki.ros.org/rosmsg#rosmsg_md5) in order to verify quickly if the message definitions have changed: If the two `md5` hashes are the same then the two distributions should be able to communicate via this message. And even if the message hashes are different you might go ahead and compile the message, as well as packages depending on it, from source (do not forget to uninstall the ones installed through Debian packages). This way both distributions will have again the same message definitions.
129 |
130 | ### 2.3 Healthcheck
131 |
132 | Docker gives you the possibility to [add a custom healthcheck to your container](https://docs.docker.com/engine/reference/builder/#healthcheck). This test should tell Docker whether your container is working correctly or not. Such a healthcheck can be defined from inside the Dockerfile or from a Docker-Compose file.
133 |
134 | In a Dockerfile it might look as follows:
135 |
136 | ```dockerfile
137 | HEALTHCHECK [OPTIONS] CMD command
138 | ```
139 |
140 | such as
141 |
142 | ```dockerfile
143 | HEALTHCHECK CMD /ros_entrypoint.sh rostopic list || exit 1
144 | ```
145 |
146 | or anything similar.
147 |
148 | While for [Docker-Compose](https://docs.docker.com/compose/compose-file/compose-file-v3/#healthcheck) you might add something like:
149 |
150 | ```yaml
151 | 9 healthcheck:
152 | 10 test: /ros_entrypoint.sh rostopic list || exit 1
153 | 11 interval: 1m30s
154 | 12 timeout: 10s
155 | 13 retries: 3
156 | 14 start_period: 1m
157 | ```
158 |
159 | ## 3. ROS 2
160 |
161 | [ROS 2](https://docs.ros.org/en/humble/index.html) was an important update to ROS that makes it much more suitable for industrial applications. It broke backwards compatability to fix some of the limitations of ROS and for this purpose followed a more thorough and structured code design that is largely documented [here](https://design.ros2.org/). One of the important changes was going away from a custom middleware for communication that is tightly integrated, such as is the case with ROS' [TCP](https://wiki.ros.org/ROS/TCPROS)/[UDP](https://wiki.ros.org/ROS/UDPROS) communication, towards an abstraction of the communication layer (see [here](https://design.ros2.org/articles/ros_middleware_interface.html)) and the introduction of [DDS](https://design.ros2.org/articles/ros_on_dds.html) as the primary communication layer in ROS 2. ROS 2 is primary intended to be used with DDS but also allows other middleware to be used, in particular [Zenoh in ROS 2 Iron](https://github.com/ros2/rmw_zenoh). Another example of such a custom middleware is `rmw_email` (see [here](https://christophebedard.com/ros-2-over-email/) and [here](https://github.com/christophebedard/rmw_email)). For wrapping a custom middleware one has to provide a wrapper for it, `rmw_*` that respects the [API](https://design.ros2.org/articles/ros_middleware_interface.html), and set the environment variable `RMW_IMPLEMENTATION` to the corresponding implementation.
162 |
163 | ### 3.1 DDS middleware configuration
164 |
165 | When using DDS as the middleware in ROS 2 the [`ROS_DOMAIN_ID`](https://docs.ros.org/en/humble/Concepts/About-Domain-ID.html) replaces the IP-based set-up. For a container this means one would create a `ROS_DOMAIN_ID` environment variable that again might be controlled by an [`.env` file](https://vsupalov.com/docker-arg-env-variable-guide/):
166 |
167 | ```yaml
168 | 9 environment:
169 | 10 - ROS_DOMAIN_ID=1 # Any number in the range of 0 and 101; 0 by default
170 | ```
171 |
172 | Choosing a safe range for the Domain ID largely depends on the operating system and is described in more details in the [corresponding article](https://docs.ros.org/en/humble/Concepts/About-Domain-ID.html). There might be [additional settings for a DDS client such as telling it which interfaces to use](https://iroboteducation.github.io/create3_docs/setup/xml-config/). For this purpose it might make sense to mount the corresponding DDS configuration file into the Docker.
173 |
174 | When working on a network with several participats that use ROS (e.g. a company or research institution), you will have to make sure that people are using different `ROS_DOMAIN_ID`s. When only using ROS 2 locally, e.g. in simulation [set the variable `ROS_LOCALHOST_ONLY=1`](https://docs.ros.org/en/humble/Tutorials/Beginner-CLI-Tools/Configuring-ROS2-Environment.html#the-ros-localhost-only-variable). This restricts the network traffic to your local PC only.
175 |
176 | Another thing you might want to configure is the **DDS middleware** to be used. In ROS 2 one might choose between different (free or payment) middleware implementations such as FastDDS and CycloneDDS. This will be outlined in more detail in the next section.
177 |
178 | What I generally do is define the corresponding environment variables such as [`RMW_IMPLEMENTATION`](https://docs.ros.org/en/humble/How-To-Guides/Working-with-multiple-RMW-implementations.html) and [`CYCLONEDDS_URI`](https://cyclonedds.io/docs/cyclonedds/latest/config/index.html) in the case of cyclone and mount the dds configuration as a volume inside the container.
179 |
180 | ```yaml
181 | 9 environment:
182 | 10 - RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
183 | 11 - CYCLONEDDS_URI=${AMENT_WORKSPACE_DIR}/dds/cyclone.xml
184 | 12 network_mode: "host"
185 | 13 volumes:
186 | 14 - ../dds:${AMENT_WORKSPACE_DIR}/dds
187 | ```
188 |
189 | For an example of what this configuration might look like have a look at [this folder](../templates/ros2/docker).
190 |
191 | #### 3.1.1 Intra-process communication over shared memory
192 |
193 | ROS 2 introduced some design changes that are aiming at drastically improving the communication speed in between nodes on the same computational unit. One such optimization is that [**intra-process communication** is left to the underlying middleware](https://design.ros2.org/articles/intraprocess_communications.html). This means it is down to the chosen middleware to use mechanisms like shared memory communication for nodes on the same computer. E.g. [FastDDS uses shared memory communication](https://fast-dds.docs.eprosima.com/en/v3.0.0/fastdds/transport/shared_memory/shared_memory.html) by default in case the environment variable [`ROS_LOCALHOST_ONLY`](https://docs.ros.org/en/humble/Tutorials/Beginner-CLI-Tools/Configuring-ROS2-Environment.html#the-ros-localhost-only-variable) is set to `1` and [CycloneDDS](https://cyclonedds.io/docs/cyclonedds/latest/shared_memory/shared_mem_config.html) lets you configure it through manually as described [here](https://github.com/ros2/rmw_cyclonedds/blob/humble/shared_memory_support.md). In Linux `/dev/shm` is used for **shared memory communication**. Therefore when communicating in between containers that set `ROS_LOCALHOST_ONLY` (or use shared memory explicitly) one might have to **mount `/dev/shm` into the containers**. For more information about shared memory and Docker refer to [this post](https://datawookie.dev/blog/2021/11/shared-memory-docker/).
194 |
195 | ### 3.2 Zenoh middleware configuration
196 |
197 | A new alternative to DDS-based communication in ROS 2 Iron is [Zenoh](https://zenoh.io/), implemented in [`rmw_zenoh`](https://github.com/ros2/rmw_zenoh). Similar to the `roscore` in ROS it relies on at least a single router that establishes the connection between different nodes running on different computers (it is also possible to do so without but this is not recommended). A good introduction to this can be found in this [video](https://www.youtube.com/watch?v=fS0_rbQ6KKA). I will add this configuration once `rmw_zenoh` becomes installable from Debian packages.
198 |
199 | ## 4. Bridging ROS 1 and ROS 2
200 |
201 | Setting the DDS middleware as described above is in particular important for cross-distro communication as **different ROS distros** ship with [**different default DDS implementations**](https://docs.ros.org/en/humble/Installation/DDS-Implementations.html). Neither communication between different DDS implementations nor different ROS 2 distributions is currently officially supported (generally it works but there can be problems with lower frequency etc., for more details see [here](https://github.com/ros2/ros2_documentation/issues/3288)) but similarly to ROS 1 if the **messages have not changed** (or you compile the messages as well as the packages using them from source) and you are **using the same DDS vendor across all involved distros** generally communication between the different distros can be achieved. This can also be useful for **bridging ROS 1 to ROS 2**. The last Ubuntu version to support both ROS 1 (Noetic) and ROS 2 (Galactic) is Ubuntu 20.04. You can use the corresponding [**Galactic ROS 1 bridge Docker**](https://hub.docker.com/layers/library/ros/galactic-ros1-bridge/images/sha256-a2f06953930b0a209295138745d606b1936f0b0564106df9230e2a6612b8b9a2?context=explore). In case message definitions have changed from Galactic to the distro that you are using (the ROS 2 API is not stable yet!) you might have to compile the corresponding messages from source. The main advantage over other solutions for having the two run alongside is that unlike to other solutions ([here](https://docs.ros.org/en/humble/How-To-Guides/Using-ros1_bridge-Jammy-upstream.html) or [here](https://github.com/TommyChangUMD/ros-humble-ros1-bridge-builder/tree/main)) you will have none or only very few repositories that have to be compiled from source and can't be installed from a Debian package.
202 |
203 | ## 5. CUDA and ROS
204 |
205 | When running CUDA inside a container make sure you are setting `runtime: nvidia`, as well as the environment variables `NVIDIA_VISIBLE_DEVICES=all` as well as `NVIDIA_DRIVER_CAPABILITIES=all` inside your Docker Compose file.
206 |
207 | For the image to use, you might find some online, e.g. [here](https://github.com/ika-rwth-aachen/docker-ros-ml-images) or for the Nvidia Jetson edge computing platforms [here](https://hub.docker.com/r/dustynv/ros/tags) and their Dockerfiles [here](https://github.com/dusty-nv/jetson-containers/tree/master/packages/ros). If you are not able to find an image that contains what you want, it is generally easier to start from an existing [`nvidia/cuda` image on the Dockerhub](https://hub.docker.com/r/nvidia/cuda) that uses the right version of Ubuntu (e.g. 20.04 for ROS Noetic or 22.04 for ROS 2 Humble) and install ROS on top of it by [copying the instructions from the official ROS Docker images](https://github.com/osrf/docker_images/blob/master/ros/noetic/ubuntu/focal/ros-base/Dockerfile). The other way around, starting from a ROS image and installing CUDA on top of it, is generally way more tricky! For the available Nvidia CUDA images browse the tags [here](https://hub.docker.com/r/nvidia/cuda/tags). By combining the two we can generate a custom image containing ROS and Nvidia as follows:
208 |
209 | ```dockerfile
210 | ARG UBUNTU_VERSION=20.04
211 | ARG NVIDIA_CUDA_VERSION=11.8.0
212 |
213 | ##############
214 | # Base image #
215 | ##############
216 | FROM nvidia/cuda:${NVIDIA_CUDA_VERSION}-devel-ubuntu${UBUNTU_VERSION} as base
217 |
218 | ARG ROS_DISTRO=noetic
219 |
220 | ENV DEBIAN_FRONTEND=noninteractive
221 |
222 | ENV ROS_DISTRO=${ROS_DISTRO}
223 | RUN apt-get update \
224 | && apt-get install -y \
225 | curl \
226 | lsb-release \
227 | && sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list' \
228 | && curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | apt-key add - \
229 | && apt-get update \
230 | && apt-get install -y --no-install-recommends \
231 | ros-${ROS_DISTRO}-ros-base \
232 | && rm -rf /var/lib/apt/lists/*
233 | ```
234 |
235 |
--------------------------------------------------------------------------------
/doc/Introduction.md:
--------------------------------------------------------------------------------
1 | # Introduction to Docker
2 |
3 | Author: [Tobit Flatscher](https://github.com/2b-t) (2021 - 2023)
4 |
5 |
6 |
7 | ## 1. Challenges in software deployment
8 |
9 | Deploying a piece of software in a portable manner is a non-trivial task. Clearly there are different operating system and different software architectures which require different binary code, but even if these match you have to make sure that the compiled code can be executed on another machine by supplying all its **dependencies**.
10 |
11 | Over the years several different packaging systems for different operating systems have emerged that provide methods for installing new dependencies and managing existing ones in an coherent manner. The low-level package manager for Debian-based Linux operating systems is [`dpkg`](https://wiki.debian.org/Teams/Dpkg), while for high-level package management, fetching packages from remote locations and resolving complex package relations, generally [`apt`](https://wiki.debian.org/Apt) is chosen. `apt` handles retrieving, configuring, installing as well as removing packages in an automated manner. When installing an `apt` package it checks the existing dependencies and installs only those that are not available yet on the system. The dependencies are shared, making the packages smaller but not allowing for multiple installations of the same library and potentially causing issues between applications requiring different versions of the same library. Contrary to this the popular package manager [`snap`](https://snapcraft.io/) uses self-contained packages which pack all the dependencies that a program requires to run, allowing for multiple installations of the same library. **Self-contained** boxes like these are called **containers**, as they do not pollute the rest of the system and might only have limited access to the host system. The main advantage of containers is that they provide clean and conistent environments as well as isolation from the hardware.
12 |
13 |
14 |
15 | ## 2. Docker to the rescue
16 |
17 | [**Docker**](https://www.docker.com/) is another **framework** for working with **containers**. A [Docker - contrary to `snap`](https://www.youtube.com/watch?v=0z3yusiCOCk) - is not integrated in terms of hardware and networking but instead has its own IP address, adding an extra layer of abstraction. A Docker container is similar to a virtual machine but the containers share the same kernel like the host system: Docker does not **virtualise** on a hardware level but on an **app level** (OS-level virtualisation). For this Docker builds on a virtualization feature of the Linux kernel, [namespaces](https://en.wikipedia.org/wiki/Linux_namespaces), that allows to selectivelty grant processes access to kernel resources. As such Docker has its own namespaces for `mnt`, `pid`, `net`, `ipc` as well as `usr` and its own root file system. As a Docker container uses the same kernel, and as a result also the same scheduler one might achieve native performance. At the same time this results in issues with graphic user interfaces as these are not part of the kernel itself and thus not shared between the container and the host system. These problems can be worked around though mostly.
18 |
19 | Using Docker brings a couple of advantages as it strongly leverages on the decoupling of the kernel and the rest of the operating system:
20 |
21 | - **Portability**: You can run code not intended for your particular Linux distribution (e.g packages for Ubuntu 20.04 on Ubuntu 18.04 and vice versa) and you can mix them, launching several containers with different requirements on the same host system by means of dedicated [orchestration tools](https://docs.docker.com/get-started/orchestration/) such as [Kubernetes](https://kubernetes.io/) or [Docker Swarm](https://docs.docker.com/engine/swarm/). This is a huge advantage for robotics applications as one can mix containers with different ROS distributions on the same computer running in parallel, all running on the same kernel of the host operating system, governed by the same scheduler.
22 | - **Performance**: Contrary to a virtual machine the performance penalty is very small and for most applications is indistinguishable from running code on the host system: After all it uses same kernel and scheduler as the host system.
23 | - Furthermore one can also run a **Linux container on a Windows or MacOS operating system**. This way you lose though a couple of advantages of Docker such as being able to run real-time code as there will be a light-weight virtual machine underneath emulating a Linux kernel. Furthermore you can also use it from the **Windows Subsystem for Linux** which allows you to stream graphic user interfaces onto the host system through X-Server.
24 |
25 | This way one can guarantee a **clean, consistent and standardised build environment** while maintaining encapsulation and achieving native performance.
26 |
27 | The core component of Docker are so called **images**, *immutable read-only templates*, that hold source code, libraries and dependencies. These can be layered over each other to form more complex images. **Containers** on the other hand are the *writable layer* on top of the read-only images. By starting an image you obtain a container: Images and containers are not opposing objects but they should rather be seen as different phases of building a containerised application.
28 |
29 | The Docker **daemon** software manages the different containers that are available on the system: The generation of an image can be described by a so called **`Dockerfile`**. A Dockerfile is like a recipe describing how an image can be created from scratch. This file might help also somebody reconstruct the steps required to get a code up and running on a vanilla host system without Docker. It is so to speak self-documenting and does not result in an additional burden like a wiki. Similarly one can recover the steps performed to generate an image with [`$ docker history --no-trunc `](https://docs.docker.com/engine/reference/commandline/history/). Dedicated servers, so calle **Docker registries** (such as the [Docker Hub](https://hub.docker.com/) or [Github's GHCR](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry)), allow you to store and distribute your Docker images. These image repositories hold different images so that one does not have to go through the build process but instead can upload and download them directly, speeding up deployment. Uploads might also be triggered by a continuous integration workflow like outlined [here](https://docs.github.com/en/actions/publishing-packages/publishing-docker-images).
30 |
31 | On top of this there go other toolchains for managing the lifetime of containers and orchestration multiple of them such as [Docker-Compose](https://docs.docker.com/compose/), [Swarm](https://docs.docker.com/engine/swarm/) or [Kubernetes](https://kubernetes.io/).
32 |
33 | This makes Docker in particular suitable for **deploying source code in a replicable manner** and will likely speed-up your development workflow. Furthermore one can use the description to perform tests or compile the code on a remote machine in terms of [continuous integration](https://en.wikipedia.org/wiki/Continuous_integration). This means for most people working professional on code development it comes at virtually no cost.
34 |
35 |
36 |
37 | ## 3. Installing Docker
38 |
39 | Docker is installed pretty easily. The installation guide for **Ubuntu** can be found [here](https://docs.docker.com/engine/install/ubuntu/). It basically boils down to a five steps:
40 |
41 | ```bash
42 | $ sudo mkdir -m 0755 -p /etc/apt/keyrings
43 | $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
44 | $ echo \
45 | "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
46 | $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
47 | $ sudo apt-get update
48 | $ sudo apt-get install docker-ce docker-ce-cli containerd.io
49 | ```
50 |
51 | After installation you will want to make sure that Docker can be **run without `sudo`** as described [here](https://docs.docker.com/engine/install/linux-postinstall/):
52 |
53 | ```bash
54 | $ sudo groupadd docker
55 | $ sudo usermod -aG docker $USER
56 | ```
57 |
58 | Finally log out and log back in again.
59 |
60 |
61 |
62 | ## 4. Usage
63 |
64 | Similarly the usage is very simple, you need a few simple commands to get a Docker up and running which are discussed in the file below.
65 |
66 | ### 4.1 Launching a container from an image
67 |
68 | As discussed above you can pull an image from the [Dockerhub](https://hub.docker.com/) and launch it as a container. This can be done by opening a console and typing:
69 |
70 | ```bash
71 | $ docker run hello-world
72 | ```
73 |
74 | `hello-world` is an image intended for testing purposes. After executing the command you should see some output to the console that does not contain any error messages. In case you are not able to run the command above, prepend it with `sudo` and retry. If this works please go back to the previous section and enable `sudo`less Docker as this will be crucial for e.g. the Visual Studio Code set-up.
75 |
76 | If you want to find out what other images you could start from just [browse the Dockerhub](https://hub.docker.com/), e.g. for [Ubuntu](https://hub.docker.com/_/ubuntu). You will see that there are different versions with corresponding tags available. For example to run a Docker with Ubuntu 20.04 installed you could use the tag `20.04` or `focal` resulting e.g. in the command
77 |
78 | ```bash
79 | $ docker run ubuntu:focal
80 | ```
81 |
82 | This should not output anything and should immediately return. The reason for this is that each container has an [entrypoint](https://docs.docker.com/engine/reference/builder/#entrypoint). This script will be run and as soon as it terminates the container will return to the command line. This is actually the basic idea of a Docker container: A container should be responsible for a single service. Once this service stops it should return again.
83 |
84 | If you want to keep the container open you have to open it in **interactive** mode by specifying the flag `-i` and the `-t` for opening a terminal
85 |
86 | ```bash
87 | $ docker run -it ubuntu:focal
88 | ```
89 |
90 | In case you need to run another command in parallel you might have to open a second terminal and connect to this Docker. In this case it is more convenient to relaunch the container with a specified `name` (or use the default one displayed by `docker run`)
91 |
92 | ```bash
93 | $ docker run -it --name ubuntu_test ubuntu:focal
94 | ```
95 |
96 | Now we can connect to it from another console with
97 |
98 | ```bash
99 | $ docker exec -it ubuntu_test sh
100 | ```
101 |
102 | The last command `sh` corresponds to the type of connection, in our case `shell`.
103 |
104 | With the `$ exit` command the Docker can be shut down.
105 |
106 | ### 4.2 Setting-up a `Dockerfile`
107 |
108 | Now that we have seen how to start a container from an existing image let us build a `Dockerfile` that defines steps that should be executed on the image:
109 |
110 | ```dockerfile
111 | # Base image
112 | FROM ubuntu:focal
113 |
114 | # Define the workspace folder (e.g. where to place your code)
115 | # We define a variable so that we can re-use it
116 | ENV WS_DIR="/code"
117 | WORKDIR ${WS_DIR}
118 |
119 | # Copy your code into the folder (see later for better alternatives!)
120 | COPY . WORKDIR
121 |
122 | # Use Bourne Again Shell as default shell
123 | SHELL ["/bin/bash", "-c"]
124 |
125 | # Disable user dialogs in apt installation messages
126 | ARG DEBIAN_FRONTEND=noninteractive
127 |
128 | # Commands to perform on base image
129 | RUN apt-get -y update \
130 | && apt-get -y install some_package \
131 | && git clone https://github.com/some_user/some_repository some_repo \
132 | && cd some_repo \
133 | && mkdir build \
134 | && cd build \
135 | && cmake .. \
136 | && make -j$(nproc) \
137 | && make install \
138 | && rm -rf /var/lib/apt/lists/*
139 |
140 | # Enable apt user dialogs again
141 | ARG DEBIAN_FRONTEND=dialog
142 |
143 | # Define the script that should be launched upon start of the container
144 | ENTRYPOINT ["/code/src/my_script.sh"]
145 | ```
146 |
147 | When saving this as `Dockerfile` (without a file ending) and type:
148 |
149 | ```bash
150 | $ docker build -f Dockerfile .
151 | ```
152 |
153 | Then read the available images with
154 |
155 | ```
156 | $ docker image ls
157 | REPOSITORY TAG IMAGE ID CREATED SIZE
158 | latest ... ...
159 | ```
160 |
161 | You should see your newly created image.
162 |
163 | You can launch it with
164 |
165 | ```bash
166 | $ docker run -it
167 | ```
168 |
169 | As soon as you starting building complex containers you will see that the compilation might be quite slow as a lot of data might have be to installed. If you want to execute it again though or you add a command to the `Dockerfile` the container will start pretty quickly. Docker itself caches the compiled images and re-uses them if possible. In fact each individual `RUN` etc. command forms a layer of its own that might be re-used. It is therefore crucial to avoid conflicts between different layers, e.g. by [introducing each `apt-get -y install` with an `apt-get update`](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run). They have to be combined in the same `RUN` command though to be effective. Similarly you can benefit from this caching by [ordering the different layers from less frequent to most frequently changed](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#use-multi-stage-builds). This way you might reduce the time you spend re-compiling significantly.
170 |
171 | At the same time it is also important to make the images as slim as possible removing all undesired artifacts from the images that are not necessary. For `apt` this means deleting the `apt` list after each layer again
172 |
173 | ```bash
174 | rm -rf /var/lib/apt/lists/*
175 | ```
176 |
177 | A simple solution to this are [multi-stage builds](https://docs.docker.com/build/building/multi-stage/) where multiple `FROM` statements are used within the same Dockerfile and parts are selectively copied between the different stages. This way everything that is not needed can be left behind.
178 |
179 | Additionally one should set the `DEBIAN_FRONTEND` environment variable to `noninteractive` before installing any packages with `apt`. Else building the Dockerfile might fail!
180 |
181 | ### 4.3 Managing data
182 |
183 | As you have seen above we copied the data of the current directory into the container with the `COPY` command. This means though that our changes will not affect the local code, instead we are working on a copy of it. This is often not desirable. Most f the time you actually want to mount your folders and shared them between the host system and the container.
184 |
185 | There are several approaches for [managing data](https://docs.docker.com/storage/) with a Docker container. Generally one stores the relevant code outside the Docker on the host system, mounting files and directories into the container, while leaving any built files inside it. This way the files relevant to both systems can be accessed inside and outside the Docker. This is generally done with [volumes](https://docs.docker.com/storage/volumes/). This results in [additional flags](https://docs.docker.com/storage/volumes/) that have to be supplied when running the Docker:
186 |
187 | ```bash
188 | $ docker run -it --volume::
189 | ```
190 |
191 | ### 4.4 Build and run scripts
192 |
193 | As you can imagine when specifying start-up options like `-it`, mounting volumes, setting up the network configuration, display settings for graphic user interfaces, passing a user name to be used inside the Docker etc. the commands for building and running Docker containers can get pretty lengthy and complicated such as the one below:
194 |
195 | ```bash
196 | $ docker run -it --volume=../src:/code/src --name=my_container --env=DISPLAY \
197 | --env=QT_X11_NO_MITSHM=1 --volume=/tmp/.X11-unix:/tmp/.X11-unix:rw \
198 | --volume=/tmp/.docker.xauth:/tmp/.docker.xauth:rw --entrypoint='/bin/bash'
199 | ```
200 |
201 | To simplify this process people often create bash scripts that store these arguments for them. Instead of typing a long command commonly one just call scripts like `build_image.bash` and `container_start.bash`. This can though be quite unintuitive for other users as there does not exist a common convention for doing so. Therefore tools like Docker-Compose, which is discussed in the next section, try to simplify this process by providing standardized configuration files for it.
202 |
203 | In any case try to avoid the `privileged` flag. If you run into any issue with not being able to do something, running the container as `privileged` will almost always solve it but there will be a more clean way. The `privileged` option breaks encapsulation and as such might pose a security risk.
204 |
205 | At the same time it makes sense to pass crucial information into the container by means of environment variables.
206 |
207 | ### 4.5 Using a Docker registry: Dockerhub
208 |
209 | Instead of creating our Docker image from a Docker file we might want to use a more complex existing one from a Docker registry. For this we will use the official one in the following example, the [Dockerhub](https://hub.docker.com/).
210 |
211 | Let's begin by logging in and pulling an existing image from an existing repository that you might have found [browsing the Dockerhub](https://hub.docker.com/search).
212 |
213 | ```bash
214 | $ docker login --username= --email= # If it is public we can pull also without logging in
215 | $ docker pull : # Pull an image from the server
216 | ```
217 |
218 | This should give as a new image on our local computer that we can run
219 |
220 | ```bash
221 | $ docker images # List all locally available images
222 | REPOSITORY TAG IMAGE ID CREATED SIZE
223 | ... ...
224 | $ docker run -it : bin/bash # Run the image as a container
225 | @:/#
226 | ```
227 |
228 | Now we can make changes to the container and finally exit it with `exit`. We should be able to see it with the following command:
229 |
230 | ```bash
231 | $ docker ps -a # Show all containers
232 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
233 | : ... ... ... ... ...
234 | ```
235 |
236 | Finally we can commit our changes to a new image and push this image to the Dockerhub as follows:
237 |
238 | ```bash
239 | $ docker commit : # Commit container to new image
240 | $ docker images # List all available images
241 | REPOSITORY TAG IMAGE ID CREATED SIZE
242 | ... ...
243 | ... ... ... ...
244 | $ docker tag /: # Tag the image
245 | $ docker push / # Push the image to the server
246 | ```
247 |
248 | ### 4.6 Exporting a Docker image to file
249 |
250 | Accessing most Docker registries will require internet access. Therefore when dealing with a slow network connection or an offline computer, sometimes it might be convenient to save a Docker image to the disk, copy them to the machine without internet access and load them onto that system:
251 |
252 | ```bash
253 | $ docker save : > # Save Docker to file
254 | $ docker load --input # Load Docker on other computer without internet access
255 | ```
256 |
257 |
258 |
259 | ## 5. Docker-Compose
260 |
261 | There are different tools available that simplify the management and the orchestration of these Docker containers, such as [Docker-Compose](https://docs.docker.com/compose/reference/up/). As said supplying arguments to Docker for building and running a `Dockerfile` often results in lengthy `shell` scripts. One way of decreasing complexity and [tidying up the process](https://docs.docker.com/compose/) is by using [**Docker-Compose**](https://docs.docker.com/compose/). It is a tool that can be used for defining and running multi-container Docker applications but is also very useful for a single container. In a Yaml file such as **`docker-compose.yml`** one describes the services that an app consists of (see [here](https://github.com/compose-spec/compose-spec/blob/master/spec.md) for the syntax) and which options it should be started with. There are though a few corner cases where Docker-Compose is not powerful enough. For example it can't execute commands on the host system in order to obtain parameters that are then passed to the Docker. Parameters have to be supplied in the form of text or in the form of an environment file.
262 |
263 | ### 5.1 Installation
264 |
265 | Prior to Ubuntu 20.04 Docker-Compose had to be installed separately like described [here](https://docs.docker.com/compose/install/). For Ubuntu 20.04 onwards it should come with Docker directly. Depending on the version you will have to call it with
266 |
267 | ```bash
268 | $ docker compose --version
269 | ```
270 |
271 | or `$ docker-compose --version`.
272 |
273 | ### 5.2 Writing and launching a Docker-Compose file
274 |
275 | For example the rather complicated Docker run command given before could be expressed in Docker-Compose with the hierarchical `yml` file, generally named `docker-compose.yml`:
276 |
277 | ```yaml
278 | version: "3.9"
279 | services:
280 | my_service:
281 | build:
282 | context: ..
283 | dockerfile: docker/Dockerfile
284 | container_name: my_container
285 | tty: true
286 | environment:
287 | - DISPLAY=${DISPLAY}
288 | - QT_X11_NO_MITSHM=1
289 | volumes:
290 | - ../src:/code/src
291 | - /tmp/.X11-unix:/tmp/.X11-unix:rw
292 | - /tmp/.docker.xauth:/tmp/.docker.xauth:rw
293 | command: '/bin/bash'
294 | ```
295 |
296 | After having created both a `Dockerfile` as well as a `docker-compose.yml` you can launch them with:
297 |
298 | ```bash
299 | $ docker compose -f docker-compose.yml build
300 | $ docker compose -f docker-compose.yml up
301 | ```
302 |
303 | where with the option `-f` a Docker-Compose file with a different filename can be provided. If not given it will default to `docker-compose.yml`.
304 |
305 | More generally such a file might hold multiple services:
306 |
307 | ```yaml
308 | version: "3.9"
309 | services:
310 | some_service: # Name of the particular service (Equivalent to the Docker --name option)
311 | build: # Use Dockerfile to build image
312 | context: . # The folder that should be used as a reference for the Dockerfile and mounting volumes
313 | dockerfile: Dockerfile # The name of the Dockerfile
314 | container_name: some_container
315 | stdin_open: true # Equivalent to the Docker -i option
316 | tty: true # Equivalent to the Docker docker run -t option
317 | volumes:
318 | - /a_folder_on_the_host:/a_folder_inside_the_container # Source folder on host : Destination folder inside the container
319 | another_service:
320 | image: ubuntu/20.04 # Use a Docker image from Dockerhub
321 | container_name: another_container
322 | volumes:
323 | - /another_folder_on_the_host:/another_folder_inside_the_container
324 | volumes:
325 | - ../yet_another_folder_on_host:/a_folder_inside_both_containers # Another folder to be accessed by both images
326 | ```
327 |
328 | If instead you wanted only to run a particular service you could do so with:
329 |
330 | ```bash
331 | $ docker compose -f docker-compose.yml run my_service
332 | ```
333 |
334 | Then similarly to the previous section one is able to connect to the container from another console with
335 |
336 | ```bash
337 | $ docker compose exec sh
338 | ```
339 |
340 | where `` is given by the name specified in the `docker-compose.yml` file and `sh` stands for the type of comand to be execute, in this case we open a `shell`.
341 |
--------------------------------------------------------------------------------
/examples/affordance-templates-ros-docker/src/at_r2_bringup/config/at_r2_moveit.rviz:
--------------------------------------------------------------------------------
1 | Panels:
2 | - Class: rviz/Displays
3 | Help Height: 84
4 | Name: Displays
5 | Property Tree Widget:
6 | Expanded:
7 | - /Global Options1
8 | - /MotionPlanning1/Scene Robot1
9 | - /MotionPlanning1/Planning Request1
10 | - /MotionPlanning1/Planning Metrics1
11 | - /MotionPlanning1/Planned Path1
12 | - /Asus Camera1/Visibility1
13 | Splitter Ratio: 0.467146
14 | Tree Height: 143
15 | - Class: rviz/Help
16 | Name: Help
17 | - Class: rviz/Views
18 | Expanded:
19 | - /Current View1
20 | Name: Views
21 | Splitter Ratio: 0.5
22 | - Class: RVizInteractiveControlsPanel/RVizInteractiveControlsPanel
23 | Name: RVizInteractiveControlsPanel
24 | - Class: rviz_affordance_template_panel/RVizAffordanceTemplatePanel
25 | Name: RVizAffordanceTemplatePanel
26 | Visualization Manager:
27 | Class: ""
28 | Displays:
29 | - Alpha: 0.5
30 | Cell Size: 1
31 | Class: rviz/Grid
32 | Color: 160; 160; 164
33 | Enabled: true
34 | Line Style:
35 | Line Width: 0.03
36 | Value: Lines
37 | Name: Grid
38 | Normal Cell Count: 0
39 | Offset:
40 | X: 0
41 | Y: 0
42 | Z: 0
43 | Plane: XY
44 | Plane Cell Count: 10
45 | Reference Frame:
46 | Value: true
47 | - Class: moveit_rviz_plugin/MotionPlanning
48 | Enabled: true
49 | Move Group Namespace: ""
50 | MoveIt_Goal_Tolerance: 4
51 | MoveIt_Planning_Attempts: 10
52 | MoveIt_Planning_Time: 5
53 | MoveIt_Use_Constraint_Aware_IK: true
54 | MoveIt_Warehouse_Host: 127.0.0.1
55 | MoveIt_Warehouse_Port: 33829
56 | MoveIt_Workspace:
57 | Center:
58 | X: 0
59 | Y: 0
60 | Z: 0
61 | Size:
62 | X: 2
63 | Y: 2
64 | Z: 2
65 | Name: MotionPlanning
66 | Planned Path:
67 | Color Enabled: false
68 | Interrupt Display: false
69 | Links:
70 | All Links Enabled: true
71 | Expand Joint Details: false
72 | Expand Link Details: false
73 | Expand Tree: false
74 | Link Tree Style: Links in Alphabetic Order
75 | r2/asus_frame:
76 | Alpha: 1
77 | Show Axes: false
78 | Show Trail: false
79 | r2/backpack:
80 | Alpha: 1
81 | Show Axes: false
82 | Show Trail: false
83 | Value: true
84 | r2/baseplate:
85 | Alpha: 1
86 | Show Axes: false
87 | Show Trail: false
88 | Value: true
89 | r2/body_cover:
90 | Alpha: 1
91 | Show Axes: false
92 | Show Trail: false
93 | Value: true
94 | r2/chest_base:
95 | Alpha: 1
96 | Show Axes: false
97 | Show Trail: false
98 | r2/chest_center:
99 | Alpha: 1
100 | Show Axes: false
101 | Show Trail: false
102 | r2/left_camera_frame:
103 | Alpha: 1
104 | Show Axes: false
105 | Show Trail: false
106 | r2/left_camera_optical_frame:
107 | Alpha: 1
108 | Show Axes: false
109 | Show Trail: false
110 | r2/left_elbow:
111 | Alpha: 1
112 | Show Axes: false
113 | Show Trail: false
114 | Value: true
115 | r2/left_index_base:
116 | Alpha: 1
117 | Show Axes: false
118 | Show Trail: false
119 | r2/left_index_distal:
120 | Alpha: 1
121 | Show Axes: false
122 | Show Trail: false
123 | Value: true
124 | r2/left_index_medial:
125 | Alpha: 1
126 | Show Axes: false
127 | Show Trail: false
128 | Value: true
129 | r2/left_index_proximal:
130 | Alpha: 1
131 | Show Axes: false
132 | Show Trail: false
133 | Value: true
134 | r2/left_index_tip:
135 | Alpha: 1
136 | Show Axes: false
137 | Show Trail: false
138 | r2/left_index_yaw:
139 | Alpha: 1
140 | Show Axes: false
141 | Show Trail: false
142 | r2/left_little_distal:
143 | Alpha: 1
144 | Show Axes: false
145 | Show Trail: false
146 | Value: true
147 | r2/left_little_medial:
148 | Alpha: 1
149 | Show Axes: false
150 | Show Trail: false
151 | Value: true
152 | r2/left_little_proximal:
153 | Alpha: 1
154 | Show Axes: false
155 | Show Trail: false
156 | Value: true
157 | r2/left_little_tip:
158 | Alpha: 1
159 | Show Axes: false
160 | Show Trail: false
161 | r2/left_lower_arm:
162 | Alpha: 1
163 | Show Axes: false
164 | Show Trail: false
165 | Value: true
166 | r2/left_middle_base:
167 | Alpha: 1
168 | Show Axes: false
169 | Show Trail: false
170 | r2/left_middle_distal:
171 | Alpha: 1
172 | Show Axes: false
173 | Show Trail: false
174 | Value: true
175 | r2/left_middle_medial:
176 | Alpha: 1
177 | Show Axes: false
178 | Show Trail: false
179 | Value: true
180 | r2/left_middle_proximal:
181 | Alpha: 1
182 | Show Axes: false
183 | Show Trail: false
184 | Value: true
185 | r2/left_middle_tip:
186 | Alpha: 1
187 | Show Axes: false
188 | Show Trail: false
189 | r2/left_middle_yaw:
190 | Alpha: 1
191 | Show Axes: false
192 | Show Trail: false
193 | r2/left_palm:
194 | Alpha: 1
195 | Show Axes: false
196 | Show Trail: false
197 | Value: true
198 | r2/left_ring_distal:
199 | Alpha: 1
200 | Show Axes: false
201 | Show Trail: false
202 | Value: true
203 | r2/left_ring_medial:
204 | Alpha: 1
205 | Show Axes: false
206 | Show Trail: false
207 | Value: true
208 | r2/left_ring_proximal:
209 | Alpha: 1
210 | Show Axes: false
211 | Show Trail: false
212 | Value: true
213 | r2/left_ring_tip:
214 | Alpha: 1
215 | Show Axes: false
216 | Show Trail: false
217 | r2/left_shoulder_pitch:
218 | Alpha: 1
219 | Show Axes: false
220 | Show Trail: false
221 | Value: true
222 | r2/left_shoulder_roll:
223 | Alpha: 1
224 | Show Axes: false
225 | Show Trail: false
226 | Value: true
227 | r2/left_thumb_base:
228 | Alpha: 1
229 | Show Axes: false
230 | Show Trail: false
231 | r2/left_thumb_distal:
232 | Alpha: 1
233 | Show Axes: false
234 | Show Trail: false
235 | Value: true
236 | r2/left_thumb_medial:
237 | Alpha: 1
238 | Show Axes: false
239 | Show Trail: false
240 | Value: true
241 | r2/left_thumb_medial_prime:
242 | Alpha: 1
243 | Show Axes: false
244 | Show Trail: false
245 | Value: true
246 | r2/left_thumb_proximal:
247 | Alpha: 1
248 | Show Axes: false
249 | Show Trail: false
250 | Value: true
251 | r2/left_thumb_tip:
252 | Alpha: 1
253 | Show Axes: false
254 | Show Trail: false
255 | r2/left_upper_arm:
256 | Alpha: 1
257 | Show Axes: false
258 | Show Trail: false
259 | Value: true
260 | r2/left_wrist_pitch:
261 | Alpha: 1
262 | Show Axes: false
263 | Show Trail: false
264 | r2/left_wrist_yaw:
265 | Alpha: 1
266 | Show Axes: false
267 | Show Trail: false
268 | r2/neck_base:
269 | Alpha: 1
270 | Show Axes: false
271 | Show Trail: false
272 | Value: true
273 | r2/neck_lower_pitch:
274 | Alpha: 1
275 | Show Axes: false
276 | Show Trail: false
277 | Value: true
278 | r2/neck_roll:
279 | Alpha: 1
280 | Show Axes: false
281 | Show Trail: false
282 | Value: true
283 | r2/neck_upper_pitch:
284 | Alpha: 1
285 | Show Axes: false
286 | Show Trail: false
287 | r2/openni_depth_frame:
288 | Alpha: 1
289 | Show Axes: false
290 | Show Trail: false
291 | r2/right_camera_frame:
292 | Alpha: 1
293 | Show Axes: false
294 | Show Trail: false
295 | r2/right_camera_optical_frame:
296 | Alpha: 1
297 | Show Axes: false
298 | Show Trail: false
299 | r2/right_elbow:
300 | Alpha: 1
301 | Show Axes: false
302 | Show Trail: false
303 | Value: true
304 | r2/right_index_base:
305 | Alpha: 1
306 | Show Axes: false
307 | Show Trail: false
308 | r2/right_index_distal:
309 | Alpha: 1
310 | Show Axes: false
311 | Show Trail: false
312 | Value: true
313 | r2/right_index_medial:
314 | Alpha: 1
315 | Show Axes: false
316 | Show Trail: false
317 | Value: true
318 | r2/right_index_proximal:
319 | Alpha: 1
320 | Show Axes: false
321 | Show Trail: false
322 | Value: true
323 | r2/right_index_tip:
324 | Alpha: 1
325 | Show Axes: false
326 | Show Trail: false
327 | r2/right_index_yaw:
328 | Alpha: 1
329 | Show Axes: false
330 | Show Trail: false
331 | r2/right_little_distal:
332 | Alpha: 1
333 | Show Axes: false
334 | Show Trail: false
335 | Value: true
336 | r2/right_little_medial:
337 | Alpha: 1
338 | Show Axes: false
339 | Show Trail: false
340 | Value: true
341 | r2/right_little_proximal:
342 | Alpha: 1
343 | Show Axes: false
344 | Show Trail: false
345 | Value: true
346 | r2/right_little_tip:
347 | Alpha: 1
348 | Show Axes: false
349 | Show Trail: false
350 | r2/right_lower_arm:
351 | Alpha: 1
352 | Show Axes: false
353 | Show Trail: false
354 | Value: true
355 | r2/right_middle_base:
356 | Alpha: 1
357 | Show Axes: false
358 | Show Trail: false
359 | r2/right_middle_distal:
360 | Alpha: 1
361 | Show Axes: false
362 | Show Trail: false
363 | Value: true
364 | r2/right_middle_medial:
365 | Alpha: 1
366 | Show Axes: false
367 | Show Trail: false
368 | Value: true
369 | r2/right_middle_proximal:
370 | Alpha: 1
371 | Show Axes: false
372 | Show Trail: false
373 | Value: true
374 | r2/right_middle_tip:
375 | Alpha: 1
376 | Show Axes: false
377 | Show Trail: false
378 | r2/right_middle_yaw:
379 | Alpha: 1
380 | Show Axes: false
381 | Show Trail: false
382 | r2/right_palm:
383 | Alpha: 1
384 | Show Axes: false
385 | Show Trail: false
386 | Value: true
387 | r2/right_ring_distal:
388 | Alpha: 1
389 | Show Axes: false
390 | Show Trail: false
391 | Value: true
392 | r2/right_ring_medial:
393 | Alpha: 1
394 | Show Axes: false
395 | Show Trail: false
396 | Value: true
397 | r2/right_ring_proximal:
398 | Alpha: 1
399 | Show Axes: false
400 | Show Trail: false
401 | Value: true
402 | r2/right_ring_tip:
403 | Alpha: 1
404 | Show Axes: false
405 | Show Trail: false
406 | r2/right_shoulder_pitch:
407 | Alpha: 1
408 | Show Axes: false
409 | Show Trail: false
410 | Value: true
411 | r2/right_shoulder_roll:
412 | Alpha: 1
413 | Show Axes: false
414 | Show Trail: false
415 | Value: true
416 | r2/right_thumb_base:
417 | Alpha: 1
418 | Show Axes: false
419 | Show Trail: false
420 | r2/right_thumb_distal:
421 | Alpha: 1
422 | Show Axes: false
423 | Show Trail: false
424 | Value: true
425 | r2/right_thumb_medial:
426 | Alpha: 1
427 | Show Axes: false
428 | Show Trail: false
429 | Value: true
430 | r2/right_thumb_medial_prime:
431 | Alpha: 1
432 | Show Axes: false
433 | Show Trail: false
434 | Value: true
435 | r2/right_thumb_proximal:
436 | Alpha: 1
437 | Show Axes: false
438 | Show Trail: false
439 | Value: true
440 | r2/right_thumb_tip:
441 | Alpha: 1
442 | Show Axes: false
443 | Show Trail: false
444 | r2/right_upper_arm:
445 | Alpha: 1
446 | Show Axes: false
447 | Show Trail: false
448 | Value: true
449 | r2/right_wrist_pitch:
450 | Alpha: 1
451 | Show Axes: false
452 | Show Trail: false
453 | r2/right_wrist_yaw:
454 | Alpha: 1
455 | Show Axes: false
456 | Show Trail: false
457 | r2/robot_base:
458 | Alpha: 1
459 | Show Axes: false
460 | Show Trail: false
461 | r2/robot_reference:
462 | Alpha: 1
463 | Show Axes: false
464 | Show Trail: false
465 | r2/robot_world:
466 | Alpha: 1
467 | Show Axes: false
468 | Show Trail: false
469 | r2/simulated_asus_camera_frame:
470 | Alpha: 1
471 | Show Axes: false
472 | Show Trail: false
473 | r2/simulated_asus_depth_frame:
474 | Alpha: 1
475 | Show Axes: false
476 | Show Trail: false
477 | r2/stanchion:
478 | Alpha: 1
479 | Show Axes: false
480 | Show Trail: false
481 | Value: true
482 | r2/vision_center_frame:
483 | Alpha: 1
484 | Show Axes: false
485 | Show Trail: false
486 | r2/waist_center:
487 | Alpha: 1
488 | Show Axes: false
489 | Show Trail: false
490 | Value: true
491 | world:
492 | Alpha: 1
493 | Show Axes: false
494 | Show Trail: false
495 | Loop Animation: false
496 | Robot Alpha: 0.25
497 | Robot Color: 150; 50; 150
498 | Show Robot Collision: false
499 | Show Robot Visual: true
500 | Show Trail: false
501 | State Display Time: 0.05 s
502 | Trail Step Size: 1
503 | Trajectory Topic: /move_group/display_planned_path
504 | Planning Metrics:
505 | Payload: 1
506 | Show Joint Torques: false
507 | Show Manipulability: false
508 | Show Manipulability Index: false
509 | Show Weight Limit: false
510 | TextHeight: 0.08
511 | Planning Request:
512 | Colliding Link Color: 255; 0; 0
513 | Goal State Alpha: 1
514 | Goal State Color: 250; 128; 0
515 | Interactive Marker Size: 0.25
516 | Joint Violation Color: 255; 0; 255
517 | Planning Group: head
518 | Query Goal State: true
519 | Query Start State: false
520 | Show Workspace: false
521 | Start State Alpha: 1
522 | Start State Color: 0; 255; 0
523 | Planning Scene Topic: /move_group/monitored_planning_scene
524 | Robot Description: robot_description
525 | Scene Geometry:
526 | Scene Alpha: 1
527 | Scene Color: 50; 230; 50
528 | Scene Display Time: 0.2
529 | Show Scene Geometry: true
530 | Voxel Coloring: Z-Axis
531 | Voxel Rendering: Occupied Voxels
532 | Scene Robot:
533 | Attached Body Color: 150; 50; 150
534 | Links:
535 | All Links Enabled: true
536 | Expand Joint Details: false
537 | Expand Link Details: false
538 | Expand Tree: false
539 | Link Tree Style: Links in Alphabetic Order
540 | r2/asus_frame:
541 | Alpha: 1
542 | Show Axes: false
543 | Show Trail: false
544 | r2/backpack:
545 | Alpha: 1
546 | Show Axes: false
547 | Show Trail: false
548 | Value: true
549 | r2/baseplate:
550 | Alpha: 1
551 | Show Axes: false
552 | Show Trail: false
553 | Value: true
554 | r2/body_cover:
555 | Alpha: 1
556 | Show Axes: false
557 | Show Trail: false
558 | Value: true
559 | r2/chest_base:
560 | Alpha: 1
561 | Show Axes: false
562 | Show Trail: false
563 | r2/chest_center:
564 | Alpha: 1
565 | Show Axes: false
566 | Show Trail: false
567 | r2/left_camera_frame:
568 | Alpha: 1
569 | Show Axes: false
570 | Show Trail: false
571 | r2/left_camera_optical_frame:
572 | Alpha: 1
573 | Show Axes: false
574 | Show Trail: false
575 | r2/left_elbow:
576 | Alpha: 1
577 | Show Axes: false
578 | Show Trail: false
579 | Value: true
580 | r2/left_index_base:
581 | Alpha: 1
582 | Show Axes: false
583 | Show Trail: false
584 | r2/left_index_distal:
585 | Alpha: 1
586 | Show Axes: false
587 | Show Trail: false
588 | Value: true
589 | r2/left_index_medial:
590 | Alpha: 1
591 | Show Axes: false
592 | Show Trail: false
593 | Value: true
594 | r2/left_index_proximal:
595 | Alpha: 1
596 | Show Axes: false
597 | Show Trail: false
598 | Value: true
599 | r2/left_index_tip:
600 | Alpha: 1
601 | Show Axes: false
602 | Show Trail: false
603 | r2/left_index_yaw:
604 | Alpha: 1
605 | Show Axes: false
606 | Show Trail: false
607 | r2/left_little_distal:
608 | Alpha: 1
609 | Show Axes: false
610 | Show Trail: false
611 | Value: true
612 | r2/left_little_medial:
613 | Alpha: 1
614 | Show Axes: false
615 | Show Trail: false
616 | Value: true
617 | r2/left_little_proximal:
618 | Alpha: 1
619 | Show Axes: false
620 | Show Trail: false
621 | Value: true
622 | r2/left_little_tip:
623 | Alpha: 1
624 | Show Axes: false
625 | Show Trail: false
626 | r2/left_lower_arm:
627 | Alpha: 1
628 | Show Axes: false
629 | Show Trail: false
630 | Value: true
631 | r2/left_middle_base:
632 | Alpha: 1
633 | Show Axes: false
634 | Show Trail: false
635 | r2/left_middle_distal:
636 | Alpha: 1
637 | Show Axes: false
638 | Show Trail: false
639 | Value: true
640 | r2/left_middle_medial:
641 | Alpha: 1
642 | Show Axes: false
643 | Show Trail: false
644 | Value: true
645 | r2/left_middle_proximal:
646 | Alpha: 1
647 | Show Axes: false
648 | Show Trail: false
649 | Value: true
650 | r2/left_middle_tip:
651 | Alpha: 1
652 | Show Axes: false
653 | Show Trail: false
654 | r2/left_middle_yaw:
655 | Alpha: 1
656 | Show Axes: false
657 | Show Trail: false
658 | r2/left_palm:
659 | Alpha: 1
660 | Show Axes: false
661 | Show Trail: false
662 | Value: true
663 | r2/left_ring_distal:
664 | Alpha: 1
665 | Show Axes: false
666 | Show Trail: false
667 | Value: true
668 | r2/left_ring_medial:
669 | Alpha: 1
670 | Show Axes: false
671 | Show Trail: false
672 | Value: true
673 | r2/left_ring_proximal:
674 | Alpha: 1
675 | Show Axes: false
676 | Show Trail: false
677 | Value: true
678 | r2/left_ring_tip:
679 | Alpha: 1
680 | Show Axes: false
681 | Show Trail: false
682 | r2/left_shoulder_pitch:
683 | Alpha: 1
684 | Show Axes: false
685 | Show Trail: false
686 | Value: true
687 | r2/left_shoulder_roll:
688 | Alpha: 1
689 | Show Axes: false
690 | Show Trail: false
691 | Value: true
692 | r2/left_thumb_base:
693 | Alpha: 1
694 | Show Axes: false
695 | Show Trail: false
696 | r2/left_thumb_distal:
697 | Alpha: 1
698 | Show Axes: false
699 | Show Trail: false
700 | Value: true
701 | r2/left_thumb_medial:
702 | Alpha: 1
703 | Show Axes: false
704 | Show Trail: false
705 | Value: true
706 | r2/left_thumb_medial_prime:
707 | Alpha: 1
708 | Show Axes: false
709 | Show Trail: false
710 | Value: true
711 | r2/left_thumb_proximal:
712 | Alpha: 1
713 | Show Axes: false
714 | Show Trail: false
715 | Value: true
716 | r2/left_thumb_tip:
717 | Alpha: 1
718 | Show Axes: false
719 | Show Trail: false
720 | r2/left_upper_arm:
721 | Alpha: 1
722 | Show Axes: false
723 | Show Trail: false
724 | Value: true
725 | r2/left_wrist_pitch:
726 | Alpha: 1
727 | Show Axes: false
728 | Show Trail: false
729 | r2/left_wrist_yaw:
730 | Alpha: 1
731 | Show Axes: false
732 | Show Trail: false
733 | r2/neck_base:
734 | Alpha: 1
735 | Show Axes: false
736 | Show Trail: false
737 | Value: true
738 | r2/neck_lower_pitch:
739 | Alpha: 1
740 | Show Axes: false
741 | Show Trail: false
742 | Value: true
743 | r2/neck_roll:
744 | Alpha: 1
745 | Show Axes: false
746 | Show Trail: false
747 | Value: true
748 | r2/neck_upper_pitch:
749 | Alpha: 1
750 | Show Axes: false
751 | Show Trail: false
752 | r2/openni_depth_frame:
753 | Alpha: 1
754 | Show Axes: false
755 | Show Trail: false
756 | r2/right_camera_frame:
757 | Alpha: 1
758 | Show Axes: false
759 | Show Trail: false
760 | r2/right_camera_optical_frame:
761 | Alpha: 1
762 | Show Axes: false
763 | Show Trail: false
764 | r2/right_elbow:
765 | Alpha: 1
766 | Show Axes: false
767 | Show Trail: false
768 | Value: true
769 | r2/right_index_base:
770 | Alpha: 1
771 | Show Axes: false
772 | Show Trail: false
773 | r2/right_index_distal:
774 | Alpha: 1
775 | Show Axes: false
776 | Show Trail: false
777 | Value: true
778 | r2/right_index_medial:
779 | Alpha: 1
780 | Show Axes: false
781 | Show Trail: false
782 | Value: true
783 | r2/right_index_proximal:
784 | Alpha: 1
785 | Show Axes: false
786 | Show Trail: false
787 | Value: true
788 | r2/right_index_tip:
789 | Alpha: 1
790 | Show Axes: false
791 | Show Trail: false
792 | r2/right_index_yaw:
793 | Alpha: 1
794 | Show Axes: false
795 | Show Trail: false
796 | r2/right_little_distal:
797 | Alpha: 1
798 | Show Axes: false
799 | Show Trail: false
800 | Value: true
801 | r2/right_little_medial:
802 | Alpha: 1
803 | Show Axes: false
804 | Show Trail: false
805 | Value: true
806 | r2/right_little_proximal:
807 | Alpha: 1
808 | Show Axes: false
809 | Show Trail: false
810 | Value: true
811 | r2/right_little_tip:
812 | Alpha: 1
813 | Show Axes: false
814 | Show Trail: false
815 | r2/right_lower_arm:
816 | Alpha: 1
817 | Show Axes: false
818 | Show Trail: false
819 | Value: true
820 | r2/right_middle_base:
821 | Alpha: 1
822 | Show Axes: false
823 | Show Trail: false
824 | r2/right_middle_distal:
825 | Alpha: 1
826 | Show Axes: false
827 | Show Trail: false
828 | Value: true
829 | r2/right_middle_medial:
830 | Alpha: 1
831 | Show Axes: false
832 | Show Trail: false
833 | Value: true
834 | r2/right_middle_proximal:
835 | Alpha: 1
836 | Show Axes: false
837 | Show Trail: false
838 | Value: true
839 | r2/right_middle_tip:
840 | Alpha: 1
841 | Show Axes: false
842 | Show Trail: false
843 | r2/right_middle_yaw:
844 | Alpha: 1
845 | Show Axes: false
846 | Show Trail: false
847 | r2/right_palm:
848 | Alpha: 1
849 | Show Axes: false
850 | Show Trail: false
851 | Value: true
852 | r2/right_ring_distal:
853 | Alpha: 1
854 | Show Axes: false
855 | Show Trail: false
856 | Value: true
857 | r2/right_ring_medial:
858 | Alpha: 1
859 | Show Axes: false
860 | Show Trail: false
861 | Value: true
862 | r2/right_ring_proximal:
863 | Alpha: 1
864 | Show Axes: false
865 | Show Trail: false
866 | Value: true
867 | r2/right_ring_tip:
868 | Alpha: 1
869 | Show Axes: false
870 | Show Trail: false
871 | r2/right_shoulder_pitch:
872 | Alpha: 1
873 | Show Axes: false
874 | Show Trail: false
875 | Value: true
876 | r2/right_shoulder_roll:
877 | Alpha: 1
878 | Show Axes: false
879 | Show Trail: false
880 | Value: true
881 | r2/right_thumb_base:
882 | Alpha: 1
883 | Show Axes: false
884 | Show Trail: false
885 | r2/right_thumb_distal:
886 | Alpha: 1
887 | Show Axes: false
888 | Show Trail: false
889 | Value: true
890 | r2/right_thumb_medial:
891 | Alpha: 1
892 | Show Axes: false
893 | Show Trail: false
894 | Value: true
895 | r2/right_thumb_medial_prime:
896 | Alpha: 1
897 | Show Axes: false
898 | Show Trail: false
899 | Value: true
900 | r2/right_thumb_proximal:
901 | Alpha: 1
902 | Show Axes: false
903 | Show Trail: false
904 | Value: true
905 | r2/right_thumb_tip:
906 | Alpha: 1
907 | Show Axes: false
908 | Show Trail: false
909 | r2/right_upper_arm:
910 | Alpha: 1
911 | Show Axes: false
912 | Show Trail: false
913 | Value: true
914 | r2/right_wrist_pitch:
915 | Alpha: 1
916 | Show Axes: false
917 | Show Trail: false
918 | r2/right_wrist_yaw:
919 | Alpha: 1
920 | Show Axes: false
921 | Show Trail: false
922 | r2/robot_base:
923 | Alpha: 1
924 | Show Axes: false
925 | Show Trail: false
926 | r2/robot_reference:
927 | Alpha: 1
928 | Show Axes: false
929 | Show Trail: false
930 | r2/robot_world:
931 | Alpha: 1
932 | Show Axes: false
933 | Show Trail: false
934 | r2/simulated_asus_camera_frame:
935 | Alpha: 1
936 | Show Axes: false
937 | Show Trail: false
938 | r2/simulated_asus_depth_frame:
939 | Alpha: 1
940 | Show Axes: false
941 | Show Trail: false
942 | r2/stanchion:
943 | Alpha: 1
944 | Show Axes: false
945 | Show Trail: false
946 | Value: true
947 | r2/vision_center_frame:
948 | Alpha: 1
949 | Show Axes: false
950 | Show Trail: false
951 | r2/waist_center:
952 | Alpha: 1
953 | Show Axes: false
954 | Show Trail: false
955 | Value: true
956 | world:
957 | Alpha: 1
958 | Show Axes: false
959 | Show Trail: false
960 | Robot Alpha: 0.5
961 | Show Robot Collision: false
962 | Show Robot Visual: true
963 | Value: true
964 | - Alpha: 1
965 | Class: rviz/RobotModel
966 | Collision Enabled: false
967 | Enabled: true
968 | Links:
969 | All Links Enabled: true
970 | Expand Joint Details: false
971 | Expand Link Details: false
972 | Expand Tree: false
973 | Link Tree Style: Links in Alphabetic Order
974 | r2/asus_frame:
975 | Alpha: 1
976 | Show Axes: false
977 | Show Trail: false
978 | r2/backpack:
979 | Alpha: 1
980 | Show Axes: false
981 | Show Trail: false
982 | Value: true
983 | r2/baseplate:
984 | Alpha: 1
985 | Show Axes: false
986 | Show Trail: false
987 | Value: true
988 | r2/body_cover:
989 | Alpha: 1
990 | Show Axes: false
991 | Show Trail: false
992 | Value: true
993 | r2/chest_base:
994 | Alpha: 1
995 | Show Axes: false
996 | Show Trail: false
997 | r2/chest_center:
998 | Alpha: 1
999 | Show Axes: false
1000 | Show Trail: false
1001 | r2/left_camera_frame:
1002 | Alpha: 1
1003 | Show Axes: false
1004 | Show Trail: false
1005 | r2/left_camera_optical_frame:
1006 | Alpha: 1
1007 | Show Axes: false
1008 | Show Trail: false
1009 | r2/left_elbow:
1010 | Alpha: 1
1011 | Show Axes: false
1012 | Show Trail: false
1013 | Value: true
1014 | r2/left_index_base:
1015 | Alpha: 1
1016 | Show Axes: false
1017 | Show Trail: false
1018 | r2/left_index_distal:
1019 | Alpha: 1
1020 | Show Axes: false
1021 | Show Trail: false
1022 | Value: true
1023 | r2/left_index_medial:
1024 | Alpha: 1
1025 | Show Axes: false
1026 | Show Trail: false
1027 | Value: true
1028 | r2/left_index_proximal:
1029 | Alpha: 1
1030 | Show Axes: false
1031 | Show Trail: false
1032 | Value: true
1033 | r2/left_index_tip:
1034 | Alpha: 1
1035 | Show Axes: false
1036 | Show Trail: false
1037 | r2/left_index_yaw:
1038 | Alpha: 1
1039 | Show Axes: false
1040 | Show Trail: false
1041 | r2/left_little_distal:
1042 | Alpha: 1
1043 | Show Axes: false
1044 | Show Trail: false
1045 | Value: true
1046 | r2/left_little_medial:
1047 | Alpha: 1
1048 | Show Axes: false
1049 | Show Trail: false
1050 | Value: true
1051 | r2/left_little_proximal:
1052 | Alpha: 1
1053 | Show Axes: false
1054 | Show Trail: false
1055 | Value: true
1056 | r2/left_little_tip:
1057 | Alpha: 1
1058 | Show Axes: false
1059 | Show Trail: false
1060 | r2/left_lower_arm:
1061 | Alpha: 1
1062 | Show Axes: false
1063 | Show Trail: false
1064 | Value: true
1065 | r2/left_middle_base:
1066 | Alpha: 1
1067 | Show Axes: false
1068 | Show Trail: false
1069 | r2/left_middle_distal:
1070 | Alpha: 1
1071 | Show Axes: false
1072 | Show Trail: false
1073 | Value: true
1074 | r2/left_middle_medial:
1075 | Alpha: 1
1076 | Show Axes: false
1077 | Show Trail: false
1078 | Value: true
1079 | r2/left_middle_proximal:
1080 | Alpha: 1
1081 | Show Axes: false
1082 | Show Trail: false
1083 | Value: true
1084 | r2/left_middle_tip:
1085 | Alpha: 1
1086 | Show Axes: false
1087 | Show Trail: false
1088 | r2/left_middle_yaw:
1089 | Alpha: 1
1090 | Show Axes: false
1091 | Show Trail: false
1092 | r2/left_palm:
1093 | Alpha: 1
1094 | Show Axes: false
1095 | Show Trail: false
1096 | Value: true
1097 | r2/left_ring_distal:
1098 | Alpha: 1
1099 | Show Axes: false
1100 | Show Trail: false
1101 | Value: true
1102 | r2/left_ring_medial:
1103 | Alpha: 1
1104 | Show Axes: false
1105 | Show Trail: false
1106 | Value: true
1107 | r2/left_ring_proximal:
1108 | Alpha: 1
1109 | Show Axes: false
1110 | Show Trail: false
1111 | Value: true
1112 | r2/left_ring_tip:
1113 | Alpha: 1
1114 | Show Axes: false
1115 | Show Trail: false
1116 | r2/left_shoulder_pitch:
1117 | Alpha: 1
1118 | Show Axes: false
1119 | Show Trail: false
1120 | Value: true
1121 | r2/left_shoulder_roll:
1122 | Alpha: 1
1123 | Show Axes: false
1124 | Show Trail: false
1125 | Value: true
1126 | r2/left_thumb_base:
1127 | Alpha: 1
1128 | Show Axes: false
1129 | Show Trail: false
1130 | r2/left_thumb_distal:
1131 | Alpha: 1
1132 | Show Axes: false
1133 | Show Trail: false
1134 | Value: true
1135 | r2/left_thumb_medial:
1136 | Alpha: 1
1137 | Show Axes: false
1138 | Show Trail: false
1139 | Value: true
1140 | r2/left_thumb_medial_prime:
1141 | Alpha: 1
1142 | Show Axes: false
1143 | Show Trail: false
1144 | Value: true
1145 | r2/left_thumb_proximal:
1146 | Alpha: 1
1147 | Show Axes: false
1148 | Show Trail: false
1149 | Value: true
1150 | r2/left_thumb_tip:
1151 | Alpha: 1
1152 | Show Axes: false
1153 | Show Trail: false
1154 | r2/left_upper_arm:
1155 | Alpha: 1
1156 | Show Axes: false
1157 | Show Trail: false
1158 | Value: true
1159 | r2/left_wrist_pitch:
1160 | Alpha: 1
1161 | Show Axes: false
1162 | Show Trail: false
1163 | r2/left_wrist_yaw:
1164 | Alpha: 1
1165 | Show Axes: false
1166 | Show Trail: false
1167 | r2/neck_base:
1168 | Alpha: 1
1169 | Show Axes: false
1170 | Show Trail: false
1171 | Value: true
1172 | r2/neck_lower_pitch:
1173 | Alpha: 1
1174 | Show Axes: false
1175 | Show Trail: false
1176 | Value: true
1177 | r2/neck_roll:
1178 | Alpha: 1
1179 | Show Axes: false
1180 | Show Trail: false
1181 | Value: true
1182 | r2/neck_upper_pitch:
1183 | Alpha: 1
1184 | Show Axes: false
1185 | Show Trail: false
1186 | r2/openni_depth_frame:
1187 | Alpha: 1
1188 | Show Axes: false
1189 | Show Trail: false
1190 | r2/right_camera_frame:
1191 | Alpha: 1
1192 | Show Axes: false
1193 | Show Trail: false
1194 | r2/right_camera_optical_frame:
1195 | Alpha: 1
1196 | Show Axes: false
1197 | Show Trail: false
1198 | r2/right_elbow:
1199 | Alpha: 1
1200 | Show Axes: false
1201 | Show Trail: false
1202 | Value: true
1203 | r2/right_index_base:
1204 | Alpha: 1
1205 | Show Axes: false
1206 | Show Trail: false
1207 | r2/right_index_distal:
1208 | Alpha: 1
1209 | Show Axes: false
1210 | Show Trail: false
1211 | Value: true
1212 | r2/right_index_medial:
1213 | Alpha: 1
1214 | Show Axes: false
1215 | Show Trail: false
1216 | Value: true
1217 | r2/right_index_proximal:
1218 | Alpha: 1
1219 | Show Axes: false
1220 | Show Trail: false
1221 | Value: true
1222 | r2/right_index_tip:
1223 | Alpha: 1
1224 | Show Axes: false
1225 | Show Trail: false
1226 | r2/right_index_yaw:
1227 | Alpha: 1
1228 | Show Axes: false
1229 | Show Trail: false
1230 | r2/right_little_distal:
1231 | Alpha: 1
1232 | Show Axes: false
1233 | Show Trail: false
1234 | Value: true
1235 | r2/right_little_medial:
1236 | Alpha: 1
1237 | Show Axes: false
1238 | Show Trail: false
1239 | Value: true
1240 | r2/right_little_proximal:
1241 | Alpha: 1
1242 | Show Axes: false
1243 | Show Trail: false
1244 | Value: true
1245 | r2/right_little_tip:
1246 | Alpha: 1
1247 | Show Axes: false
1248 | Show Trail: false
1249 | r2/right_lower_arm:
1250 | Alpha: 1
1251 | Show Axes: false
1252 | Show Trail: false
1253 | Value: true
1254 | r2/right_middle_base:
1255 | Alpha: 1
1256 | Show Axes: false
1257 | Show Trail: false
1258 | r2/right_middle_distal:
1259 | Alpha: 1
1260 | Show Axes: false
1261 | Show Trail: false
1262 | Value: true
1263 | r2/right_middle_medial:
1264 | Alpha: 1
1265 | Show Axes: false
1266 | Show Trail: false
1267 | Value: true
1268 | r2/right_middle_proximal:
1269 | Alpha: 1
1270 | Show Axes: false
1271 | Show Trail: false
1272 | Value: true
1273 | r2/right_middle_tip:
1274 | Alpha: 1
1275 | Show Axes: false
1276 | Show Trail: false
1277 | r2/right_middle_yaw:
1278 | Alpha: 1
1279 | Show Axes: false
1280 | Show Trail: false
1281 | r2/right_palm:
1282 | Alpha: 1
1283 | Show Axes: false
1284 | Show Trail: false
1285 | Value: true
1286 | r2/right_ring_distal:
1287 | Alpha: 1
1288 | Show Axes: false
1289 | Show Trail: false
1290 | Value: true
1291 | r2/right_ring_medial:
1292 | Alpha: 1
1293 | Show Axes: false
1294 | Show Trail: false
1295 | Value: true
1296 | r2/right_ring_proximal:
1297 | Alpha: 1
1298 | Show Axes: false
1299 | Show Trail: false
1300 | Value: true
1301 | r2/right_ring_tip:
1302 | Alpha: 1
1303 | Show Axes: false
1304 | Show Trail: false
1305 | r2/right_shoulder_pitch:
1306 | Alpha: 1
1307 | Show Axes: false
1308 | Show Trail: false
1309 | Value: true
1310 | r2/right_shoulder_roll:
1311 | Alpha: 1
1312 | Show Axes: false
1313 | Show Trail: false
1314 | Value: true
1315 | r2/right_thumb_base:
1316 | Alpha: 1
1317 | Show Axes: false
1318 | Show Trail: false
1319 | r2/right_thumb_distal:
1320 | Alpha: 1
1321 | Show Axes: false
1322 | Show Trail: false
1323 | Value: true
1324 | r2/right_thumb_medial:
1325 | Alpha: 1
1326 | Show Axes: false
1327 | Show Trail: false
1328 | Value: true
1329 | r2/right_thumb_medial_prime:
1330 | Alpha: 1
1331 | Show Axes: false
1332 | Show Trail: false
1333 | Value: true
1334 | r2/right_thumb_proximal:
1335 | Alpha: 1
1336 | Show Axes: false
1337 | Show Trail: false
1338 | Value: true
1339 | r2/right_thumb_tip:
1340 | Alpha: 1
1341 | Show Axes: false
1342 | Show Trail: false
1343 | r2/right_upper_arm:
1344 | Alpha: 1
1345 | Show Axes: false
1346 | Show Trail: false
1347 | Value: true
1348 | r2/right_wrist_pitch:
1349 | Alpha: 1
1350 | Show Axes: false
1351 | Show Trail: false
1352 | r2/right_wrist_yaw:
1353 | Alpha: 1
1354 | Show Axes: false
1355 | Show Trail: false
1356 | r2/robot_base:
1357 | Alpha: 1
1358 | Show Axes: false
1359 | Show Trail: false
1360 | r2/robot_reference:
1361 | Alpha: 1
1362 | Show Axes: false
1363 | Show Trail: false
1364 | r2/robot_world:
1365 | Alpha: 1
1366 | Show Axes: false
1367 | Show Trail: false
1368 | r2/simulated_asus_camera_frame:
1369 | Alpha: 1
1370 | Show Axes: false
1371 | Show Trail: false
1372 | r2/simulated_asus_depth_frame:
1373 | Alpha: 1
1374 | Show Axes: false
1375 | Show Trail: false
1376 | r2/stanchion:
1377 | Alpha: 1
1378 | Show Axes: false
1379 | Show Trail: false
1380 | Value: true
1381 | r2/vision_center_frame:
1382 | Alpha: 1
1383 | Show Axes: false
1384 | Show Trail: false
1385 | r2/waist_center:
1386 | Alpha: 1
1387 | Show Axes: false
1388 | Show Trail: false
1389 | Value: true
1390 | world:
1391 | Alpha: 1
1392 | Show Axes: false
1393 | Show Trail: false
1394 | Name: RobotModel
1395 | Robot Description: robot_description
1396 | TF Prefix: ""
1397 | Update Interval: 0
1398 | Value: true
1399 | Visual Enabled: true
1400 | - Class: rviz/InteractiveMarkers
1401 | Enable Transparency: true
1402 | Enabled: true
1403 | Name: Teleop Markers
1404 | Show Axes: false
1405 | Show Descriptions: true
1406 | Show Visual Aids: false
1407 | Update Topic: /r2_teleop/update
1408 | Value: true
1409 | - Class: rviz/MarkerArray
1410 | Enabled: true
1411 | Marker Topic: /r2/move_group/planned_path_visualization
1412 | Name: Path Visualization
1413 | Namespaces:
1414 | {}
1415 | Queue Size: 100
1416 | Value: true
1417 | - Class: rviz/Camera
1418 | Enabled: false
1419 | Image Rendering: background and overlay
1420 | Image Topic: /r2/asus/rgb/image_raw
1421 | Name: Asus Camera
1422 | Overlay Alpha: 0.5
1423 | Queue Size: 2
1424 | Transport Hint: raw
1425 | Unreliable: false
1426 | Value: false
1427 | Visibility:
1428 | "": true
1429 | Asus: true
1430 | Grid: false
1431 | MotionPlanning: true
1432 | OccupancyGrid: true
1433 | Path Visualization: true
1434 | RobotModel: false
1435 | Teleop Markers: true
1436 | Value: true
1437 | Zoom Factor: 1
1438 | - Class: octomap_rviz_plugin/OccupancyGrid
1439 | Enabled: false
1440 | Max. Octree Depth: 16
1441 | Name: OccupancyGrid
1442 | Octomap Topic: /octomap_full
1443 | Queue Size: 5
1444 | Value: false
1445 | Voxel Coloring: Z-Axis
1446 | Voxel Rendering: Occupied Voxels
1447 | - Alpha: 1
1448 | Autocompute Intensity Bounds: true
1449 | Autocompute Value Bounds:
1450 | Max Value: 10
1451 | Min Value: -10
1452 | Value: true
1453 | Axis: Z
1454 | Channel Name: intensity
1455 | Class: rviz/PointCloud2
1456 | Color: 255; 255; 255
1457 | Color Transformer: RGB8
1458 | Decay Time: 0
1459 | Enabled: true
1460 | Invert Rainbow: false
1461 | Max Color: 255; 255; 255
1462 | Max Intensity: 4096
1463 | Min Color: 0; 0; 0
1464 | Min Intensity: 0
1465 | Name: Asus
1466 | Position Transformer: XYZ
1467 | Queue Size: 10
1468 | Selectable: true
1469 | Size (Pixels): 3
1470 | Size (m): 0.01
1471 | Style: Points
1472 | Topic: /r2/asus/depth/points
1473 | Unreliable: false
1474 | Use Fixed Frame: true
1475 | Use rainbow: true
1476 | Value: true
1477 | - Class: rviz/InteractiveMarkers
1478 | Enable Transparency: true
1479 | Enabled: true
1480 | Name: InteractiveMarkers
1481 | Show Axes: false
1482 | Show Descriptions: true
1483 | Show Visual Aids: false
1484 | Update Topic: /affordance_template_interactive_marker_server/update
1485 | Value: true
1486 | Enabled: true
1487 | Global Options:
1488 | Background Color: 0; 0; 0
1489 | Fixed Frame: world
1490 | Frame Rate: 30
1491 | Name: root
1492 | Tools:
1493 | - Class: rviz/Interact
1494 | Hide Inactive Objects: true
1495 | - Class: rviz/MoveCamera
1496 | - Class: rviz/Select
1497 | Value: true
1498 | Views:
1499 | Current:
1500 | Class: rviz/XYOrbit
1501 | Distance: 3.38274
1502 | Enable Stereo Rendering:
1503 | Stereo Eye Separation: 0.06
1504 | Stereo Focal Distance: 1
1505 | Swap Stereo Eyes: false
1506 | Value: false
1507 | Focal Point:
1508 | X: -0.140022
1509 | Y: -0.3995
1510 | Z: 2.19047e-06
1511 | Name: Current View
1512 | Near Clip Distance: 0.01
1513 | Pitch: 0.394796
1514 | Target Frame: world
1515 | Value: XYOrbit (rviz)
1516 | Yaw: 6.00102
1517 | Saved: ~
1518 | Window Geometry:
1519 | Asus Camera:
1520 | collapsed: false
1521 | Displays:
1522 | collapsed: false
1523 | Height: 1016
1524 | Help:
1525 | collapsed: false
1526 | Hide Left Dock: false
1527 | Hide Right Dock: false
1528 | MotionPlanning:
1529 | collapsed: false
1530 | MotionPlanning - Slider:
1531 | collapsed: false
1532 | QMainWindow State: 000000ff00000000fd000000020000000000000258000003a8fc0200000007fb000000100044006900730070006c006100790073010000003600000120000000b700fffffffb0000001c004d006f00740069006f006e0050006c0061006e006e0069006e0067010000015c000002820000019800fffffffb0000000a0049006d00610067006500000002b7000001c00000000000000000fb0000000a0056006900650077007300000003b0000000b00000009b00fffffffb000000160041007300750073002000430061006d00650072006102000000a40000008f000003f900000302fc00000461000000160000000000fffffffa000000000100000002fb0000000c00430061006d0065007200610100000000ffffffff0000000000000000fb0000001e004d006f00740069006f006e00200050006c0061006e006e0069006e006700000000000000026f0000000000000000fb0000002e004d006f00740069006f006e0050006c0061006e006e0069006e00670020002d00200053006c00690064006500720000000000ffffffff0000004100ffffff0000000100000193000003a8fc0200000002fc00000036000003a80000030a00fffffffa000000000100000002fb00000036005200560069007a004100660066006f007200640061006e0063006500540065006d0070006c00610074006500500061006e0065006c0100000000ffffffff0000019300fffffffb0000000800480065006c007000000006fe000002b80000004f00fffffffb00000038005200560069007a0049006e0074006500720061006300740069007600650043006f006e00740072006f006c007300500061006e0065006c0000000036000002400000024000ffffff000005bf000003a800000001000000020000000100000002fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
1533 | RVizAffordanceTemplatePanel:
1534 | collapsed: false
1535 | RVizInteractiveControlsPanel:
1536 | collapsed: false
1537 | Views:
1538 | collapsed: false
1539 | Width: 2486
1540 | X: 73
1541 | Y: 26
1542 |
--------------------------------------------------------------------------------