Author: Tobit Flatscher (2022 - 2024)
This repository contains a Docker and all the documentation required to launch an Intel Realsense camera with the Robot Operating System ROS 2.
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
.
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
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" ]
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.
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 itrealsense-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 therealsense-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.