/px4-realsense-ros2-docker

Dockerfile for Intel Realsense camera in ROS 2

Primary LanguageDockerfileMIT LicenseMIT

Docker for Intel Realsense cameras on ROS 2

Author: Tobit Flatscher (2022 - 2024)

Build License: MIT

0. Overview

This repository contains a Docker and all the documentation required to launch an Intel Realsense camera with the Robot Operating System ROS 2.

1. Creating a Docker

There are two different approaches for creating a Docker for a Realsense camera, one uses existing Debian packages while the other performs a full compilation from source. It is then important to mount /dev as a volume so that the Docker can access the hardware.

In the docker-compose.yml this is done with the options:

    volumes:
      - /dev:/dev
    device_cgroup_rules:
      - 'c 81:* rmw'
      - 'c 189:* rmw'

For more information on how to obtain these device cgroup rules see here. For running the IMU as well you will have to add privileged: true.

1.1 Installation from Debian packages

The relevant packages for amd64 and most distributions can be installed from Debian packages. This is significantly simpler and less error prone than a full compilation from source but corresponding Debian packages might not be available for all Ubuntu versions and are sadly currently not available for arm64. In the case of an arm64 architecture you will have to go for a compilation from source as described in the next section. The corresponding Dockerfile for amd64 can be found below. It is based on the installation guides for librealsense and its ROS wrapper.

FROM ros:humble-perception

ENV WS_DIR="/ros2_ws"
WORKDIR ${WS_DIR}

SHELL ["/bin/bash", "-c"]

ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get update \
 && apt-get install -y \
    build-essential \
    cmake \
    git-all \
    software-properties-common \
 && rm -rf /var/lib/apt/lists/*

RUN apt-get update \
 && apt-get install -y \
    ros-${ROS_DISTRO}-librealsense2* \
    ros-${ROS_DISTRO}-realsense2-* \
 && rm -rf /var/lib/apt/lists/*

RUN apt-get update \
 && apt-get install -y \
    ros-${ROS_DISTRO}-rviz2 \
 && rm -rf /var/lib/apt/lists/*

ARG DEBIAN_FRONTEND=dialog

1.2 Installation from source

The installation from source is slightly more involved but more general: It might work with ROS 2 distributions before the support is officially added (as used to be the case for ROS Humble for quite a while). In order to optimise memory usage a multi-stage build is performed. The Dockerfile is inspired by the Dockerfile of librealsense contributed by community members:

ARG BASE_IMAGE=ros:humble-perception

# The following steps are based on the offical multi-stage build: https://github.com/IntelRealSense/librealsense/blob/master/scripts/Docker/Dockerfile
#################################
#   Librealsense Builder Stage  #
#################################
FROM $BASE_IMAGE as librealsense-builder

SHELL ["/bin/bash", "-c"]

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update \
 && apt-get install -qq -y --no-install-recommends \
    build-essential \
    cmake \
    git \
    libssl-dev \
    libusb-1.0-0-dev \
    pkg-config \
    libgtk-3-dev \
    libglfw3-dev \
    libgl1-mesa-dev \
    libglu1-mesa-dev \    
    curl \
    python3 \
    python3-dev \
    ca-certificates \
 && rm -rf /var/lib/apt/lists/*

WORKDIR /usr/src
# Get the latest tag of remote repository: https://stackoverflow.com/a/12704727
# Needs to be a single command as ENV can't be set from Bash command: https://stackoverflow.com/questions/34911622/dockerfile-set-env-to-result-of-command
RUN export LIBRS_GIT_TAG=`git -c 'versionsort.suffix=-' \
                         ls-remote --exit-code --refs --sort='version:refname' --tags https://github.com/IntelRealSense/librealsense '*.*.*' \
                         | tail --lines=1 \
                         | cut --delimiter='/' --fields=3`; \
    export LIBRS_VERSION=${LIBRS_VERSION:-${LIBRS_GIT_TAG#"v"}}; \
    curl https://codeload.github.com/IntelRealSense/librealsense/tar.gz/refs/tags/v${LIBRS_VERSION} -o librealsense.tar.gz; \
    tar -zxf librealsense.tar.gz; \
    rm librealsense.tar.gz; \
    ln -s /usr/src/librealsense-${LIBRS_VERSION} /usr/src/librealsense

RUN cd /usr/src/librealsense \
 && mkdir build && cd build \
 && cmake \
    -DCMAKE_C_FLAGS_RELEASE="${CMAKE_C_FLAGS_RELEASE} -s" \
    -DCMAKE_CXX_FLAGS_RELEASE="${CMAKE_CXX_FLAGS_RELEASE} -s" \
    -DCMAKE_INSTALL_PREFIX=/opt/librealsense \    
    -DBUILD_GRAPHICAL_EXAMPLES=OFF \
    -DBUILD_PYTHON_BINDINGS:bool=true \
    -DCMAKE_BUILD_TYPE=Release ../ \
 && make -j$(($(nproc)-1)) all \
 && make install
 
 ENV DEBIAN_FRONTEND=dialog

######################################
#   librealsense Base Image Stage    #
######################################
FROM ${BASE_IMAGE} as librealsense

SHELL ["/bin/bash", "-c"]

COPY --from=librealsense-builder /opt/librealsense /usr/local/
COPY --from=librealsense-builder /usr/lib/python3/dist-packages/pyrealsense2 /usr/lib/python3/dist-packages/pyrealsense2
COPY --from=librealsense-builder /usr/src/librealsense/config/99-realsense-libusb.rules /etc/udev/rules.d/
ENV PYTHONPATH=${PYTHONPATH}:/usr/local/lib

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update \
 && apt-get install -y --no-install-recommends \	
    libusb-1.0-0 \
    udev \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common \
 && rm -rf /var/lib/apt/lists/*

# The following steps are based on: https://github.com/IntelRealSense/realsense-ros/tree/ros2-development
ENV WS_DIR="/ros2_ws"
WORKDIR ${WS_DIR}
RUN apt-get update -y \
 && apt-get install -y \
    ros-${ROS_DISTRO}-rviz2 \
 && mkdir src \
 && cd src \
 && git clone https://github.com/IntelRealSense/realsense-ros.git -b ros2-development \
 && cd .. \
 && apt-get install -y python3-rosdep \
 && source /opt/ros/${ROS_DISTRO}/setup.bash \
 && rm /etc/ros/rosdep/sources.list.d/20-default.list \
 && rosdep init \
 && rosdep update \
 && rosdep install -i --from-path src --rosdistro ${ROS_DISTRO} --skip-keys=librealsense2 -y \
 && colcon build

ENV DEBIAN_FRONTEND=dialog

CMD [ "rs-enumerate-devices", "--compact" ]

2. Launching

Allow the container to display contents on your host machine by typing

$ xhost +local:root

Then build the Docker container with

$ docker compose -f docker-compose-gui.yml build

or directly with the devcontainer in Visual Studio Code. For Nvidia graphic cards the file docker-compose-gui-nvidia.yml in combination with the nvidia-container-runtime has to be used instead. After it is done building connect the Realsense, start the container

$ docker compose -f docker-compose-gui.yml up

and see if you can detect it from inside the Docker by typing inside the Docker

$ rs-enumerate-devices --compact

Turn on the camera inside the application, see if you can see a three-dimensional image. Finally we can launch the ROS 2 wrapper

$ ros2 launch realsense2_camera rs_launch.py pointcloud.enable:=true

and in another terminal the ROS visualiser Rviz

$ ros2 run rviz2 rviz2

In Rviz you can then display the topics published by the Realsense. For the list of available topics use

$ ros2 topic list

in combination with

$ ros2 topic info <topic_name>

to find out what display type has to be selected in Rviz.

Rviz2 preview

3. Debugging

The Intel Realsense driver has several serious flaws/bugs. In case this Docker image does not work for you please have a look at the issues on realsense-ros to see if somebody has encountered the same issue already. Issues you might encounter are likely related to the underlying fragile library itself.

  • The driver is closely connected to the kernel version of the Linux operating system. If the Dockerfile above do not work then you are likely unlucky and it is an incompatible version of the kernel of your host system and you will either have to downgrade your kernel or switch to another Ubuntu version that is officially supported.

  • The Realsense is pretty picky about USB 3.x cables. If your camera is detected via rs-enumerate-devices, you can see it realsense-viewer but can't output its video stream, then it might be that your cable lacks the bandwidth. Either you can try to turn down the resolution of the camera in the realsense-viewer or switch cable (preferably to one that is already known to work).

  • The Realsense ROS driver itself is known for struggling with Nvidia Jetson embedded computers and Raspberry Pi single-board computers. Some users seem to have had success by up- or downgrading the versions of librealsense and/or the camera firmware but it might as well be that you find exactly the issue that you are encountering but it was never solved and closed due to inactivity (see also the issues #2 and #4).

  • A useful tool to check if the Realsense is working properly without ROS is the Realsense viewer. It can be installed as discussed in issue #3 and launched with:

    $ realsense-viewer
  • In case you want to also use the IMU present in some Realsense models such as the D435i with e.g.

    $ ros2 launch realsense2_camera rs_launch.py pointcloud.enable:=true enable_gyro:=true enable_accel:=true unite_imu_method:=2
    

    it seems like the only way for this is to run the container with the privileged flag. For more details see issue #5.