How to build ZED 2i Camera x ROS2 Foxy x Nvidia Jetson x Ubuntu 18.04 via Docker
Tags: ros2, l4t, zed2i, docker
Published: 2021-09-15 09:37:55

Hi robotics dudes,

## TL;DR
Use this Dockerfile, I will later make it a github repo.
```docker
# Based on https://gitlab.com/nvidia/container-images/l4t-base/-/blob/master/Dockerfile.l4t
# https://github.com/dusty-nv/jetson-containers/blob/master/Dockerfile.ros.foxy
# https://github.com/codustry/jetson-containers/blob/master/Dockerfile.ros.foxy
ARG L4T_MINOR_VERSION=5.0
FROM codustry/ros:foxy-ros-base-l4t-r32.${L4T_MINOR_VERSION}

#
# ZED Jetson
# https://github.com/stereolabs/zed-docker/blob/master/3.X/jetpack_4.X/devel/Dockerfile
#
ARG ZED_SDK_MAJOR=3
ARG ZED_SDK_MINOR=5
ARG JETPACK_MAJOR=4
ARG JETPACK_MINOR=5

#This environment variable is needed to use the streaming features on Jetson inside a container
ENV LOGNAME root
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update -y && apt-get install --no-install-recommends  lsb-release wget less udev sudo apt-transport-https build-essential cmake openssh-server libv4l-0 libv4l-dev v4l-utils binutils xz-utils bzip2 lbzip2 curl ca-certificates libegl1 python3 -y && \
    echo "# R32 (release), REVISION: 5.0" > /etc/nv_tegra_release ; \
    wget -q --no-check-certificate -O ZED_SDK_Linux_JP.run https://download.stereolabs.com/zedsdk/${ZED_SDK_MAJOR}.${ZED_SDK_MINOR}/jp${JETPACK_MAJOR}${JETPACK_MINOR}/jetsons && \
    chmod +x ZED_SDK_Linux_JP.run ; ./ZED_SDK_Linux_JP.run silent skip_tools && \
    rm -rf /usr/local/zed/resources/* \
    rm -rf ZED_SDK_Linux_JP.run && \
    rm -rf /var/lib/apt/lists/*

#This symbolic link is needed to use the streaming features on Jetson inside a container
RUN ln -sf /usr/lib/aarch64-linux-gnu/tegra/libv4l2.so.0 /usr/lib/aarch64-linux-gnu/libv4l2.so


# # Configure Enviroment for ROS
RUN echo 'source /opt/ros/foxy/install/setup.bash' >> ~/.bashrc
# RUN echo "source /opt/ros/eloquent/setup.bash" >> ~/.bashrc
RUN echo 'source /usr/share/colcon_cd/function/colcon_cd.sh' >> ~/.bashrc
# RUN echo "export _colcon_cd_root=~/ros2_install" >> ~/.bashrc

# echo $LD_LIBRARY_PATH
RUN echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda-10.2/targets/aarch64-linux/lib/stubs:/opt/ros/foxy/install/lib' >> ~/.bashrc

WORKDIR /root/Downloads
RUN wget https://developer.nvidia.com/embedded/L4T/r32_Release_v5.0/T186/Tegra186_Linux_R32.5.0_aarch64.tbz2
RUN tar xf Tegra186_Linux_R32.5.0_aarch64.tbz2
RUN cd Linux_for_Tegra && \
    sed -i 's/config.tbz2\"/config.tbz2\" --exclude=etc\/hosts --exclude=etc\/hostname/g' apply_binaries.sh && \
    sed -i 's/install --owner=root --group=root \"${QEMU_BIN}\" \"${L4T_ROOTFS_DIR}\/usr\/bin\/\"/#install --owner=root --group=root \"${QEMU_BIN}\" \"${L4T_ROOTFS_DIR}\/usr\/bin\/\"/g' nv_tegra/nv-apply-debs.sh && \
    sed -i 's/LC_ALL=C chroot . mount -t proc none \/proc/ /g' nv_tegra/nv-apply-debs.sh && \
    sed -i 's/umount ${L4T_ROOTFS_DIR}\/proc/ /g' nv_tegra/nv-apply-debs.sh && \
    sed -i 's/chroot . \//  /g' nv_tegra/nv-apply-debs.sh && \
    ./apply_binaries.sh -r / --target-overlay
RUN rm -rf Tegra210_Linux_R32.4.4_aarch64.tbz2 && \
    rm -rf Linux_for_Tegra && \
    echo "/usr/lib/aarch64-linux-gnu/tegra" > /etc/ld.so.conf.d/nvidia-tegra.conf && ldconfig

WORKDIR /usr/local/zed
ENV CUDA_HOME=/usr/local/cuda
WORKDIR /root/ros2_ws/src/
RUN source /opt/ros/foxy/install/setup.bash && cd ../ && colcon build --symlink-install
RUN git clone https://github.com/stereolabs/zed-ros2-wrapper.git
RUN git clone https://github.com/ros/diagnostics.git && cd diagnostics && git checkout foxy
WORKDIR /root/ros2_ws
RUN source /opt/ros/foxy/install/setup.bash && source $(pwd)/install/local_setup.bash && rosdep update && \
    rosdep install --from-paths src --ignore-src -r --rosdistro ${ROS_DISTRO}  -y && \
    colcon build --symlink-install --cmake-args " -DCMAKE_BUILD_TYPE=Release" " -DCMAKE_LIBRARY_PATH=/usr/local/cuda/lib64/stubs" " -DCUDA_CUDART_LIBRARY=/usr/local/cuda/lib64/stubs" " -DCMAKE_CXX_FLAGS='-Wl,--allow-shlib-undefined'" && \
    echo source $(pwd)/install/local_setup.bash >> ~/.bashrc && \
    source ~/.bashrc


```


I wrote this in Sept, 2021. So, decision are made at this point in time.

After a painstaking week of making, this combination finally worked.  I decided to share my journey in a compact way so that it saves humanity's time.

## Why it is matter? 
1. ROS2 Eloquent is out of LTS. ROS2 Foxy is the way to go.
2. [Officially, ZED 2i has no launch file at Eloquent branch.](https://github.com/stereolabs/zed-ros2-wrapper/issues/52)

## Why it is hard?
1. Lack of resources long the way
2. ROS2 Foxy is officially for Ubuntu 20.04 not 18.04
3. L4T Base image from NVIDIA is miss some `.so` that shouldn't be missed.
4. Internet examples are misleading.


## Possible Solutions 
There are 2 main ways of doing using docker and not using docker. For development iteration on Jetson Devices, docker is much faster for several reasons.
1. QEMU make it possible to dev locally fast, parallel build
2. Docker image could build at cloud to make image build faster due to the fast connection to internet(`wget`, `apt install`)
3. Able to inspect each layer individually.
4. Deploy faster than flash SD card, I use [Balena](https://www.balena.io/). to deploy on Jetson NX Xavier. You are able to plug monitor, keyboard in as normal
5. 100% Reproducible

### Here is the list of what not work
1. Method 1: start with [official SD card method](https://developer.nvidia.com/embedded/downloads), and try to upgrade OS version to the next LTS from Ubuntu 18.04 bionic to Ubuntu 20.04 focal. You will likely come out of Ubuntu 20.04 with corrupted `apt` system. 
2. Method 2: start with base images which are not installed L4T It is hard to get right the installation of L4T along with `cuda` is complex. You should let professional handle that
3. Method 3: start off Ubuntu 20.04, you are basically run into the sea of storm. This place is too easy to install the ROS2 foxy, but you wouldn't be able to make Jetson/CUDA/L4T driver works.

### The working method 

 
Pieces of Jigsaw for this success that worth mention.
1. [dusty-nv/jetson-containers](https://github.com/dusty-nv/jetson-containers) - The starting base and very inspiring base image
2. [ZED Docker ROS1 file](https://github.com/stereolabs/zed-docker/blob/master/3.X/jetpack_4.X/ros-devel/Dockerfile) - sample of working `cmake-args`
3. [Azure/IntelligentEdgeHOL](https://github.com/Azure/IntelligentEdgeHOL/blob/master/docker/jetson-nano-l4t/Dockerfile) - this help me to know that `/usr/lib/aarch64-linux-gnu/tegra` is related to `L4T 32.5` that is missing in l4t base docker.

Method 4: Stay at Ubuntu 18.04 and Build ROS2 Foxy to work on Ubuntu 18.04. I always turn away from the building ROS2, but This is the only way to make everything coexist in harmony.

finally just run 
```
ros2 launch zed_wrapper zed2i.launch.py 
```
![screenshot of working](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d92xd4n4ibwsozld1jnb.png)

TADA~ 😮🎉