Create Docker images for ZED and ROS / ROS2 In this section we follow the similar recommended workflow we used in creating Docker images with OpenCV. A generic skeleton Dockerfile is made available for both ROS and ROS2 along with a configuration file-build-ros-desktop-image.sh file, by modifying this file the docker image can be built with different versions of Ubuntu, ros-distro, ZED SDK, and CUDA. Dockerfile Overview The full Dockerfile contains many instructions to install and set up ROS and ROS2 workspaces in Dockerfile.ros and Dockerfile.ros2 respectively. In the below sections we go through important parts of files to understand more. Specify the parent image In this section we first specify the parent Docker image to pull a ZED SDK Docker image. The Ubuntu release year, SDK and CUDA versions are passed as arguments # Build Arguments ARG UBUNTU_RELEASE_YEAR ARG ZED_SDK_MAJOR ARG ZED_SDK_MINOR ARG CUDA_MAJOR ARG CUDA_MINOR # Specify the parent image from which we build FROM stereolabs/zed:${ZED_SDK_MAJOR}.${ZED_SDK_MINOR}-gl-devel-cuda${CUDA_MAJOR}.${CUDA_MINOR}-ubuntu${UBUNTU_RELEASE_YEAR}.04 ARG ROS_DISTRO_ARG ENV LOGNAME root ENV ROS_DISTRO ${ROS_DISTRO_ARG} ENV LANG C.UTF-8 ENV LC_ALL C.UTF-8 The above section remains the same for both ROS and ROS2 Dockerfiles. Install ROS Once you have specified the source image, you can go ahead and decide on the ROS distribution to be installed. If you choose to install ROS2 you may skip this part and jump to Install ROS2 section Note: This Dockerfile.rosinstalls dependencies based on the versions mentioned, be careful to check the version availability and compatibility. # Setup ROS RUN apt-get update -y || true && \ DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata curl && \ sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list' && \ curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add - && \ apt-get update || true &&\ DEBIAN_FRONTEND=noninteractive apt-get install -y ros-$ROS_DISTRO-desktop-full build-essential cmake usbutils libusb-1.0-0-dev git -y --allow-unauthenticated # Install Packages depending on ROS distro RUN if [ "$ROS_DISTRO_ARG" = "noetic" ] ; then \ apt-get install -y python3-rosdep python3-rosinstall python3-rosinstall-generator python3-wstool ;\ else \ apt-get install -y python-rosdep python-rosinstall python-rosinstall-generator python-wstool ; \ fi RUN rm -rf /var/lib/apt/lists/* Setup the ROS workspace This final section lets you set up the ROS workspace and get ready to install ROS packages. RUN mkdir -p /opt/ros_ws/src WORKDIR /opt/ros_ws RUN . /opt/ros/noetic/setup.sh && \ catkin_make # setup entrypoint COPY ./ros_entrypoint.sh / ENTRYPOINT ["/ros_entrypoint.sh"] CMD ["bash"] Install ROS2 Below part of the Dockerfile.ros2 file is responsible for installing ROS2 distro Foxy Fitzroy # install packages RUN apt-get update || true && apt-get install -q -y --no-install-recommends \ bash-completion \ dirmngr \ gnupg2 \ lsb-release \ python3-pip \ && rm -rf /var/lib/apt/lists/* # setup sources.list and keys RUN echo "deb http://packages.ros.org/ros2/ubuntu focal main" > /etc/apt/sources.list.d/ros2-latest.list && \ apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 # install bootstrap tools RUN apt-get update || true && apt-get install --no-install-recommends -y \ build-essential \ git \ python3-colcon-common-extensions \ python3-colcon-mixin \ python3-rosdep \ python3-vcstool \ && rm -rf /var/lib/apt/lists/* # install python packages RUN pip3 install -U \ argcomplete \ flake8 \ flake8-blind-except \ flake8-builtins \ flake8-class-newline \ flake8-comprehensions \ flake8-deprecated \ flake8-docstrings \ flake8-import-order \ flake8-quotes \ pytest-repeat \ pytest-rerunfailures # bootstrap rosdep RUN rosdep init \ && rosdep update # setup colcon mixin and metadata RUN colcon mixin add default \ https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml && \ colcon mixin update && \ colcon metadata add default \ https://raw.githubusercontent.com/colcon/colcon-metadata-repository/master/index.yaml && \ colcon metadata update Setup the ROS2 workspace The final section of Dockerfile.ros2 sets up workspace similar to ROS1 # clone source ENV ROS2_WS /opt/ros2_ws RUN mkdir -p $ROS2_WS/src WORKDIR $ROS2_WS # build source RUN colcon \ build \ --cmake-args \ -DSECURITY=ON --no-warn-unused-cli \ --symlink-install # setup bashrc RUN cp /etc/skel/.bashrc ~/ # setup entrypoint COPY ./ros_entrypoint.sh / ENTRYPOINT ["/ros_entrypoint.sh"] CMD ["bash"] Entrypoint As you can see both Dockerfile.ros and Dockerfile.ros2 contain the command ENTRYPOINT ["/ros_entrypoint.sh"]. The ENTRYPOINT specified is the default executable of the image which runs the script ros_entrypoint.sh everytime the image is run. You can find this file along with the Dockerfiles in here. #!/bin/bash set -e # setup ros environment if [ ${ROS_DISTRO} == "foxy" ] ; then source "$ROS2_WS/install/local_setup.bash" else source "/opt/ros/$ROS_DISTRO/setup.bash" source "$ROS_WS/devel/setup.bash" fi exec "$@" ros_entrypoint.sh makes sure that the setup.bash file is sourced everytime when image is run. Make sure that this file is present along with your Dockerfile when you build and run the image. Build Script Overview Just like the build script for OpenCV dockerfiles, the build-ros-desktop-image.sh file lets you configure the versions which are passed during the build. The script is detailed below. Configure the arguments The build arguments remain the same as that of the OpenCV Dockerfile build arguments, except here instead of having the OPENCV_VERSION we have an argument ROS2_FLAG. The ROS distro are selected based on the UBUNTU_RELEASE_YEAR , when the release year is 20 ROS2_FLAG lets you choose between ROS1 or ROS2, when the flag is set to 0 ROS distro noetic is installed and when set to 1 ROS 2 Foxy Fitzroy is installed. These values are default and can be changed to the versions that you intend to build. UBUNTU_RELEASE_YEAR=20 #Specify the Ubuntu release year ZED_SDK_MAJOR=3 # ZED SDK major version ZED_SDK_MINOR=7 # ZED SDK minor version CUDA_MAJOR=11 # CUDA major version CUDA_MINOR=4 # CUDA minor version ROS2_FLAG=0 # Change it to 1 to setup ROS 2 ###Check for version compatibility In addition to checking for the versions compatibility it also assigns corresponding $ROS_DISTRO based on the UBUNTU_RELEASE_YEAR. #Check for the version compatibilities if [ ${UBUNTU_RELEASE_YEAR} == "18" ] ; then echo "Ubuntu 18.04" ROS_DISTRO_ARG="melodic" # Not compatible with CUDA <= 9 if [ ${CUDA_MAJOR} -le "9" ] ; then echo "Ubuntu 18.04 Not compatible with CUDA <= 9" exit fi elif [ ${UBUNTU_RELEASE_YEAR} == "20" ] ; then if [ ${ROS2_FLAG} == 1 ] ; then ROS_DISTRO_ARG="foxy" else ROS_DISTRO_ARG="noetic" fi # Not compatible with CUDA <= 10 if [ ${CUDA_MAJOR} -le "10" ] ; then echo "Ubuntu 20.04 is not compatible with CUDA <= 10 " exit fi else echo "UBUNTU_RELEASE_YEAR! Allowed values are 18 or 20 " exit fi if [ ${CUDA_MAJOR} -ge "11" ] ; then if [ ${ZED_SDK_MINOR} -lt "2" ] ; then # CUDA 11.0 was introduced with 3.2 echo "CUDA 11.0 was introduced with 3.2" exit fi if [ ${CUDA_MINOR} -ge "1" ] ; then if [ ${ZED_SDK_MINOR} -lt "3" ] ; then # CUDA 11.1 was introduced with 3.3 echo "CUDA 11.1 was introduced with 3.3" exit fi fi if [ ${CUDA_MINOR} == "2" ] || [ ${CUDA_MINOR} == "3" ] || [ ${CUDA_MINOR} -ge "6" ] ; then #invalid CUDA versions echo "Invalid CUDA_MINOR! Allowed values : 0,1,4,5" exit fi elif [ ${CUDA_MAJOR} == "10" ] ; then if [ ${CUDA_MINOR} != "0" ] || [ ${CUDA_MINOR} != "2" ] ; then echo "Invalid CUDA_MINOR! Allowed values are 0 or 2" exit fi else echo "Invalid CUDA_MAJOR! Allowed values are 10 or 11" fi Docker build This section of the script executes docker build for creating the Docker image, since a single script is used to build both ROS1 and ROS2 Docker images , the default tag is assigned based on the ROS2_FLAG. Accordingly, different Dockerfiles are chosen for the build. # Default Tag based on the selected versions if [ ${ROS2_FLAG} == 1 ] ; then echo "ROS2 flag == 1 " TAG="${ZED_SDK_MAJOR}.${ZED_SDK_MINOR}-ros2-gl-devel-cuda${CUDA_MAJOR}.${CUDA_MINOR}-ubuntu${UBUNTU_RELEASE_YEAR}.04" DOCKERFILE="Dockerfile.ros2" else TAG="${ZED_SDK_MAJOR}.${ZED_SDK_MINOR}-ros-gl-devel-cuda${CUDA_MAJOR}.${CUDA_MINOR}-ubuntu${UBUNTU_RELEASE_YEAR}.04" DOCKERFILE="Dockerfile.ros" fi echo "Building '${TAG}'" docker build --build-arg UBUNTU_RELEASE_YEAR=${UBUNTU_RELEASE_YEAR} \ --build-arg ZED_SDK_MAJOR=${ZED_SDK_MAJOR} \ --build-arg ZED_SDK_MINOR=${ZED_SDK_MINOR} \ --build-arg ROS_DISTRO_ARG=${ROS_DISTRO_ARG} \ --build-arg CUDA_MAJOR=${CUDA_MAJOR} \ --build-arg CUDA_MINOR=${CUDA_MINOR} \ -t "${TAG}" -f "${DOCKERFILE}" . Create your Docker Image with OpenCV All the files that are explained can be found here, Download all the files.You should have the following files: Dockerfile.ros Dockerfile.ros2 ros_entrypoint.sh build-ros-desktop-image.sh Edit the build arguments to your desired versions and simply run the script to create your Docker image. ./build-ros-desktop-image.sh Next Steps Read the next tutorial to learn how to create Docker images for Jetson with ROS and OpenCV.