diff --git a/.github/workflows/ground-amd64-build.yml b/.github/workflows/ground-amd64-build.yml index 8fb7edf..3421438 100644 --- a/.github/workflows/ground-amd64-build.yml +++ b/.github/workflows/ground-amd64-build.yml @@ -85,4 +85,6 @@ jobs: fi - name: Build the ground image - run: docker buildx build --push -t ghcr.io/jacopopan/ground-image:${{ env.DOCKER_TAG }} -f ./tools_and_docs/docker/ground.dockerfile . + run: | + docker buildx build --target ros2-image --output type=oci,dest=/tmp/transitionary-ros2-image,tar=false -f ./tools_and_docs/docker/aircraft.dockerfile . + docker buildx build --push --build-context transitionary-ros2-image=oci-layout:///tmp/transitionary-ros2-image -t ghcr.io/jacopopan/ground-image:${{ env.DOCKER_TAG }} -f ./tools_and_docs/docker/ground.dockerfile . diff --git a/.github/workflows/simulation-amd64-build.yml b/.github/workflows/simulation-amd64-build.yml index 5e6133d..1bf9ba2 100644 --- a/.github/workflows/simulation-amd64-build.yml +++ b/.github/workflows/simulation-amd64-build.yml @@ -85,4 +85,8 @@ jobs: fi - name: Build the simulation image - run: docker buildx build --push -t ghcr.io/jacopopan/simulation-image:${{ env.DOCKER_TAG }} -f ./tools_and_docs/docker/simulation.dockerfile . + run: | + + docker buildx build --target ros2-image --output type=oci,dest=/tmp/transitionary-ros2-image,tar=false -f ./tools_and_docs/docker/aircraft.dockerfile . + docker buildx build --target ros2-qgc-image --build-context transitionary-ros2-image=oci-layout:///tmp/transitionary-ros2-image --output type=oci,dest=/tmp/transitionary-ros2-qgc-image,tar=false -f ./tools_and_docs/docker/ground.dockerfile . + docker buildx build --push --build-context transitionary-ros2-qgc-image=oci-layout:///tmp/transitionary-ros2-qgc-image -t ghcr.io/jacopopan/simulation-image:${{ env.DOCKER_TAG }} -f ./tools_and_docs/docker/simulation.dockerfile . diff --git a/tools_and_docs/docker/aircraft.dockerfile b/tools_and_docs/docker/aircraft.dockerfile index 3dc5d12..f138995 100644 --- a/tools_and_docs/docker/aircraft.dockerfile +++ b/tools_and_docs/docker/aircraft.dockerfile @@ -1,14 +1,18 @@ +################################################################################ +# Pick amd64 (for simulation) or arm64 (on Jetson) image from the NGC Catalog ## +################################################################################ FROM nvcr.io/nvidia/cuda:12.9.1-cudnn-runtime-ubuntu22.04 AS base_amd64 FROM nvcr.io/nvidia/l4t-jetpack:r36.4.0 AS base_arm64 + ################################################################################ -# Stage 1 ###################################################################### +# Add tools and ROS2 ########################################################### ################################################################################ FROM base_${TARGETARCH} AS ros2-image # Tell apt (and other Debian tools) not to prompt for user input during package installs ENV DEBIAN_FRONTEND=noninteractive -# Update the package list and install basic dependencies +# Install general use tools RUN apt update \ && apt install -y --no-install-recommends \ wget gosu htop vim ruby tmux xclip net-tools iproute2 iputils-ping netcat-openbsd \ @@ -20,34 +24,36 @@ RUN apt update \ # Install ROS2 Humble # Based on https://docs.ros.org/en/humble/Installation/Ubuntu-Install-Debs.html +ENV LANG=en_US.UTF-8 RUN apt update \ && apt install -y --no-install-recommends \ locales \ - && apt clean \ - && rm -rf /var/lib/apt/lists/* -RUN locale-gen en_US en_US.UTF-8 -RUN update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 -ENV LANG=en_US.UTF-8 -RUN apt update \ + && locale-gen en_US en_US.UTF-8 \ + && update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 \ && apt install -y --no-install-recommends \ software-properties-common curl \ - && apt clean \ - && rm -rf /var/lib/apt/lists/* -RUN curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg -RUN echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu \ - $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | tee /etc/apt/sources.list.d/ros2.list > /dev/null -RUN apt update \ + && curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu \ + $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | tee /etc/apt/sources.list.d/ros2.list > /dev/null \ + && apt update \ && apt install -y --no-install-recommends \ ros-humble-desktop ros-dev-tools \ ros-humble-bondcpp ros-humble-ament-cmake-clang-format \ ros-humble-vision-msgs \ && apt clean \ + && rm -rf /var/lib/apt/lists/* \ + && echo "source /opt/ros/humble/setup.bash" >> /root/.bashrc \ + && rosdep init + +# Install Zenoh ROS2 bridge +RUN echo "deb [trusted=yes] https://download.eclipse.org/zenoh/debian-repo/ /" | sudo tee -a /etc/apt/sources.list > /dev/null \ + && apt-get update && \ + apt-get install -y zenoh-bridge-ros2dds \ + && apt clean \ && rm -rf /var/lib/apt/lists/* -RUN echo "source /opt/ros/humble/setup.bash" >> /root/.bashrc -RUN rosdep init ################################################################################ -# Stage 2 ###################################################################### +# Add PX4 messages ############################################################# ################################################################################ FROM ros2-image AS ros2-px4msgs-image @@ -55,12 +61,12 @@ FROM ros2-image AS ros2-px4msgs-image COPY /_github_clones/px4_msgs /aas/github_ws/src/px4_msgs WORKDIR /aas/github_ws RUN rosdep update -RUN rosdep install --from-paths src --ignore-src --rosdistro humble -y +RUN rosdep install --from-paths src --ignore-src --rosdistro humble -y && apt clean && rm -rf /var/lib/apt/lists/* # Explicitly use bash, not sh, to source and build the workspace RUN bash -c "source /opt/ros/humble/setup.bash && colcon build --symlink-install" ################################################################################ -# Stage 3 ###################################################################### +# Add uXRCE-DDS agent ########################################################## ################################################################################ FROM ros2-px4msgs-image AS ros2-px4msgs-dds-image @@ -76,7 +82,7 @@ RUN mkdir build && cd build && \ # Run with $ MicroXRCEAgent udp4 -p 8888 ################################################################################ -# Stage 4 ###################################################################### +# Add MAVROS ################################################################### ################################################################################ FROM ros2-px4msgs-dds-image AS ros2-px4msgs-dds-mavros-image @@ -84,12 +90,12 @@ FROM ros2-px4msgs-dds-image AS ros2-px4msgs-dds-mavros-image RUN apt-get update && \ apt-get install -y ros-humble-mavros ros-humble-mavros-extras ros-humble-mavros-msgs \ && apt clean \ - && rm -rf /var/lib/apt/lists/* -RUN /opt/ros/humble/lib/mavros/install_geographiclib_datasets.sh + && rm -rf /var/lib/apt/lists/* \ + && /opt/ros/humble/lib/mavros/install_geographiclib_datasets.sh # Run with $ ros2 launch mavros apm.launch fcu_url:=[URI] ################################################################################ -# Stage 5 ###################################################################### +# Add GStreamer, OpenCV, and Ultralytics YOLO ################################## ################################################################################ FROM ros2-px4msgs-dds-mavros-image AS ros2-px4msgs-dds-mavros-yolo-image @@ -111,8 +117,8 @@ RUN apt update \ # Install YOLO and ONNX in virtual environment /yolo-env/ # See https://github.com/ultralytics/ultralytics/blob/main/README.md and https://onnxruntime.ai/getting-started -RUN python3 -m venv /yolo-env -RUN /yolo-env/bin/pip3 install --no-cache-dir --upgrade pip && \ +RUN python3 -m venv /yolo-env \ + && /yolo-env/bin/pip3 install --no-cache-dir --upgrade pip && \ /yolo-env/bin/pip3 install --no-cache-dir --resume-retries 5 ultralytics onnx # Check YOLO with $ /yolo-env/bin/python3 -c "import ultralytics; print(ultralytics.__version__)" # NOTE: the venv avoids shadowing the system Python's OpenCV (with GStreamer support) with a newer one without GStreamer support @@ -120,7 +126,8 @@ RUN /yolo-env/bin/pip3 install --no-cache-dir --upgrade pip && \ # Versus $ /yolo-env/bin/python3 -c "import cv2; print(cv2.getBuildInformation())" ################################################################################ -# Alternate stage for ONNX Runtime GPU: use CUDA in sim, TensorRT on Orin ###### +# amd64 stage for ONNX Runtime GPU: from wheel for CUDA support in simulation ## +# Mutually exclusive with the next stage ####################################### ################################################################################ FROM ros2-px4msgs-dds-mavros-yolo-image AS image-with-hardware-specific-ort-deepstream-and-drivers_amd64 # Add ONNX Runtime with GPU (CUDA) support for system Python @@ -128,6 +135,10 @@ RUN pip3 install --no-cache-dir --upgrade pip && \ pip3 install --no-cache-dir --resume-retries 5 onnxruntime-gpu # Check with $ python3 -c "import onnxruntime as ort; print(ort.__version__); print(ort.get_available_providers())" +################################################################################ +# arm64 stage for ONNX Runtime GPU: from source for TensorRT support on Jetson # +# Mutually exclusive with the previous stage ################################### +################################################################################ FROM ros2-px4msgs-dds-mavros-yolo-image AS image-with-hardware-specific-ort-deepstream-and-drivers_arm64 # Build ONNX Runtime from source with Jetson (TensorRT) support for system Python # Based on https://onnxruntime.ai/docs/build/eps.html#nvidia-jetson-tx1tx2nanoxavierorin @@ -159,7 +170,7 @@ RUN apt update && \ ENV PYTHONPATH=/aas/github_apps/onnxruntime/build/Linux/Release # Check with $ python3 -c "import onnxruntime as ort; print(ort.__version__); print(ort.get_available_providers())" -# Install DeepStream 7.1 on Orin to use NVIDIA accelerated GStreamer preprocessing (e.g. nvdewarper) +# Also install DeepStream 7.1 on Orin to use NVIDIA accelerated GStreamer preprocessing (e.g. nvdewarper) # Based on https://docs.nvidia.com/metropolis/deepstream/7.1/text/DS_Installation.html WORKDIR / RUN apt update \ @@ -169,17 +180,21 @@ RUN apt update \ gstreamer1.0-tools gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav \ libgstrtspserver-1.0-0 libjansson4 libyaml-cpp-dev \ && apt clean \ - && rm -rf /var/lib/apt/lists/* -RUN pip3 install --no-cache-dir --upgrade pip && \ - pip3 install --no-cache-dir --resume-retries 5 meson ninja -RUN wget https://download.gnome.org/sources/glib/2.76/glib-2.76.6.tar.xz \ + && rm -rf /var/lib/apt/lists/* \ + && pip3 install --no-cache-dir --upgrade pip && \ + pip3 install --no-cache-dir --resume-retries 5 meson ninja \ + && wget https://download.gnome.org/sources/glib/2.76/glib-2.76.6.tar.xz \ && tar -xf glib-2.76.6.tar.xz \ && cd glib-2.76.6 \ && meson build --prefix=/usr \ && ninja -C build \ - && ninja -C build install -RUN curl -LO 'https://api.ngc.nvidia.com/v2/resources/nvidia/deepstream/versions/7.1/files/deepstream-7.1_7.1.0-1_arm64.deb' -RUN apt update && apt-get install -y ./deepstream-7.1_7.1.0-1_arm64.deb + && ninja -C build install \ + && cd .. \ + && curl -LO 'https://api.ngc.nvidia.com/v2/resources/nvidia/deepstream/versions/7.1/files/deepstream-7.1_7.1.0-1_arm64.deb' \ + && apt-get install -y ./deepstream-7.1_7.1.0-1_arm64.deb \ + && rm -rf deepstream-7.1_7.1.0-1_arm64.deb glib-2.76.6.tar.xz glib-2.76.6 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* # Also install the Livox ROS2 driver only on Orin for deployment COPY /_github_clones/Livox-SDK2 /aas/github_apps/Livox-SDK2 @@ -199,7 +214,7 @@ RUN cp -f src/livox_ros_driver2/package_ROS2.xml src/livox_ros_driver2/package.x RUN bash -c "source /opt/ros/humble/setup.bash && colcon build --symlink-install --packages-select livox_ros_driver2 --cmake-args -DROS_EDITION=ROS2 -DDISTRO_ROS=humble -DCMAKE_BUILD_TYPE=Release" ################################################################################ -# Stage 6 ###################################################################### +# Add KISS-ICP ################################################################# ################################################################################ FROM image-with-hardware-specific-ort-deepstream-and-drivers_${TARGETARCH} AS ros2-px4msgs-dds-mavros-yolo-kissicp-zenoh-image @@ -210,15 +225,8 @@ WORKDIR /aas/github_ws # Explicitly use bash, not sh, to source and build the workspace RUN bash -c "source /opt/ros/humble/setup.bash && colcon build --symlink-install --packages-skip livox_ros_driver2 --cmake-args -DCMAKE_BUILD_TYPE=Release" -# Install Zenoh -RUN echo "deb [trusted=yes] https://download.eclipse.org/zenoh/debian-repo/ /" | sudo tee -a /etc/apt/sources.list > /dev/null -RUN apt-get update && \ - apt-get install -y zenoh-bridge-ros2dds \ - && apt clean \ - && rm -rf /var/lib/apt/lists/* - ################################################################################ -# Stage 7 ###################################################################### +# Add analysis tools and YOLO models ########################################### ################################################################################ FROM ros2-px4msgs-dds-mavros-yolo-kissicp-zenoh-image AS ros2-px4msgs-dds-mavros-yolo-kissicp-zenoh-analysis-models-image @@ -244,7 +252,7 @@ RUN /yolo-env/bin/python3 -c "from ultralytics import YOLO; YOLO('yolo26n.pt').e rm yolo26n.pt ################################################################################ -# Stage 8 ###################################################################### +# Copy AAS resources and build AAS ROS2 workspace ############################## ################################################################################ FROM ros2-px4msgs-dds-mavros-yolo-kissicp-zenoh-analysis-models-image AS aircraft-dev-image @@ -253,7 +261,7 @@ COPY ground/ground_ws/src/ground_system_msgs /aas/aircraft_ws/src/ground_system_ COPY aircraft/aircraft_ws/src /aas/aircraft_ws/src WORKDIR /aas/aircraft_ws RUN rosdep update -RUN rosdep install --from-paths src/ --ignore-src --rosdistro humble -y --skip-keys "px4_msgs" +RUN rosdep install --from-paths src/ --ignore-src --rosdistro humble -y --skip-keys "px4_msgs" && apt clean && rm -rf /var/lib/apt/lists/* # Explicitly use bash, not sh, to source and build the workspace RUN bash -c "source /opt/ros/humble/setup.bash && source /aas/github_ws/install/setup.bash && colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release" @@ -261,15 +269,15 @@ RUN bash -c "source /opt/ros/humble/setup.bash && source /aas/github_ws/install/ COPY aircraft/aircraft_resources/ /aas/aircraft_resources COPY aircraft/aircraft_resources/patches/kiss_icp.rviz /aas/github_ws/src/kiss-icp/ros/rviz/kiss_icp.rviz COPY aircraft/aircraft_resources/patches/apm_pluginlists.yaml /opt/ros/humble/share/mavros/launch/apm_pluginlists.yaml -RUN ln -s /aas/aircraft_resources/patches/cancellable_action.py /usr/local/bin/cancellable_action -RUN chmod +x /aas/aircraft_resources/patches/cancellable_action.py +RUN ln -s /aas/aircraft_resources/patches/cancellable_action.py /usr/local/bin/cancellable_action \ + && chmod +x /aas/aircraft_resources/patches/cancellable_action.py # Copy sensor configuration COPY simulation/simulation_resources/aircraft_models/sensor_config.yaml /aas/aircraft_resources/sensor_config.yaml # Source the workspaces -RUN echo "source /aas/github_ws/install/setup.bash" >> /root/.bashrc -RUN echo "source /aas/aircraft_ws/install/setup.bash" >> /root/.bashrc +RUN echo "source /aas/github_ws/install/setup.bash" >> /root/.bashrc \ + && echo "source /aas/aircraft_ws/install/setup.bash" >> /root/.bashrc # If needed (but already in .bashrc) $ source /opt/ros/humble/setup.bash && source /aas/github_ws/install/setup.bash && source /aas/aircraft_ws/install/setup.bash # Final config diff --git a/tools_and_docs/docker/ground.dockerfile b/tools_and_docs/docker/ground.dockerfile index 5839347..26d8b2a 100644 --- a/tools_and_docs/docker/ground.dockerfile +++ b/tools_and_docs/docker/ground.dockerfile @@ -1,59 +1,18 @@ ################################################################################ -# Stage 1 ###################################################################### +# Import ROS2 layer from aircraft.dockerfile ################################### ################################################################################ -FROM nvcr.io/nvidia/cuda:12.9.1-cudnn-runtime-ubuntu22.04 AS ros2-image - -# Tell apt (and other Debian tools) not to prompt for user input during package installs -ENV DEBIAN_FRONTEND=noninteractive - -# Update the package list and install basic dependencies -RUN apt update \ - && apt install -y --no-install-recommends \ - wget gosu htop vim ruby tmux xclip net-tools iproute2 iputils-ping netcat-openbsd \ - python3-pip python3-venv \ - mesa-utils \ - && gem install tmuxinator \ - && apt clean \ - && rm -rf /var/lib/apt/lists/* - -# Install ROS2 Humble -# Based on https://docs.ros.org/en/humble/Installation/Ubuntu-Install-Debs.html -RUN apt update \ - && apt install -y --no-install-recommends \ - locales \ - && apt clean \ - && rm -rf /var/lib/apt/lists/* -RUN locale-gen en_US en_US.UTF-8 -RUN update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 -ENV LANG=en_US.UTF-8 -RUN apt update \ - && apt install -y --no-install-recommends \ - software-properties-common curl \ - && apt clean \ - && rm -rf /var/lib/apt/lists/* -RUN curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg -RUN echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu \ - $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | tee /etc/apt/sources.list.d/ros2.list > /dev/null -RUN apt update \ - && apt install -y --no-install-recommends \ - ros-humble-desktop ros-dev-tools \ - ros-humble-bondcpp ros-humble-ament-cmake-clang-format \ - ros-humble-vision-msgs \ - && apt clean \ - && rm -rf /var/lib/apt/lists/* -RUN echo "source /opt/ros/humble/setup.bash" >> /root/.bashrc -RUN rosdep init +FROM transitionary-ros2-image AS ros2-image ################################################################################ -# Stage 2 ###################################################################### +# Add QGroundControl ########################################################### ################################################################################ -FROM ros2-image AS ros2-qgc-zenoh-image +FROM ros2-image AS ros2-qgc-image # QGroundControl (as qgcuser) # Based on https://docs.qgroundcontrol.com/master/en/qgc-user-guide/getting_started/download_and_install.html WORKDIR / -RUN useradd -m -s /bin/bash qgcuser -RUN usermod -aG dialout qgcuser +RUN useradd -m -s /bin/bash qgcuser \ + && usermod -aG dialout qgcuser # RUN apt-get remove modemmanager -y RUN apt update \ && apt install -y --no-install-recommends \ @@ -61,8 +20,8 @@ RUN apt update \ libfuse2 \ libxcb-xinerama0 libxkbcommon-x11-0 libxcb-cursor-dev \ && apt clean \ - && rm -rf /var/lib/apt/lists/* -RUN wget https://d176tv9ibo4jno.cloudfront.net/latest/QGroundControl-x86_64.AppImage && \ + && rm -rf /var/lib/apt/lists/* \ + && wget https://d176tv9ibo4jno.cloudfront.net/latest/QGroundControl-x86_64.AppImage && \ chmod +x /QGroundControl-x86_64.AppImage && \ /QGroundControl-x86_64.AppImage --appimage-extract && \ rm /QGroundControl-x86_64.AppImage @@ -75,17 +34,10 @@ RUN apt update \ && apt clean \ && rm -rf /var/lib/apt/lists/* -# Install Zenoh -RUN echo "deb [trusted=yes] https://download.eclipse.org/zenoh/debian-repo/ /" | sudo tee -a /etc/apt/sources.list > /dev/null -RUN apt-get update && \ - apt-get install -y zenoh-bridge-ros2dds \ - && apt clean \ - && rm -rf /var/lib/apt/lists/* - ################################################################################ -# Stage 3 ###################################################################### +# Add GStreamer and MAVLink #################################################### ################################################################################ -FROM ros2-qgc-zenoh-image AS ros2-qgc-zenoh-gst-mavlink-image +FROM ros2-qgc-image AS ros2-qgc-gst-mavlink-image # Add GStreamer packages to stream the cameras to the aircraft containers RUN apt update \ @@ -117,15 +69,15 @@ RUN meson setup build . --buildtype=release \ COPY /_github_clones/c_library_v2 /usr/local/include/mavlink/ ################################################################################ -# Stage 4 ###################################################################### +# Copy AAS resources and build AAS ROS2 workspace ############################## ################################################################################ -FROM ros2-qgc-zenoh-gst-mavlink-image AS ground-dev-image +FROM ros2-qgc-gst-mavlink-image AS ground-dev-image # Build the ROS 2 workspace COPY ground/ground_ws/src /aas/ground_ws/src WORKDIR /aas/ground_ws RUN rosdep update -RUN rosdep install --from-paths src/ --ignore-src --rosdistro humble -y +RUN rosdep install --from-paths src/ --ignore-src --rosdistro humble -y && apt clean && rm -rf /var/lib/apt/lists/* # Explicitly use bash, not sh, to source and build the workspace RUN bash -c "source /opt/ros/humble/setup.bash && (source /aas/github_ws/install/setup.bash || true) && colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release" diff --git a/tools_and_docs/docker/simulation.dockerfile b/tools_and_docs/docker/simulation.dockerfile index 0fcf62a..2988eca 100644 --- a/tools_and_docs/docker/simulation.dockerfile +++ b/tools_and_docs/docker/simulation.dockerfile @@ -1,102 +1,21 @@ ################################################################################ -# Stage 1 ###################################################################### +# Import ROS2 layer from aircraft.dockerfile, QGC layer from ground.dockerfile # ################################################################################ -FROM nvcr.io/nvidia/cuda:12.9.1-cudnn-runtime-ubuntu22.04 AS ros2-image - -# Tell apt (and other Debian tools) not to prompt for user input during package installs -ENV DEBIAN_FRONTEND=noninteractive - -# Update the package list and install basic dependencies -RUN apt update \ - && apt install -y --no-install-recommends \ - wget gosu htop vim ruby tmux xclip net-tools iproute2 iputils-ping netcat-openbsd \ - python3-pip python3-venv \ - mesa-utils \ - && gem install tmuxinator \ - && apt clean \ - && rm -rf /var/lib/apt/lists/* - -# Install ROS2 Humble -# Based on https://docs.ros.org/en/humble/Installation/Ubuntu-Install-Debs.html -RUN apt update \ - && apt install -y --no-install-recommends \ - locales \ - && apt clean \ - && rm -rf /var/lib/apt/lists/* -RUN locale-gen en_US en_US.UTF-8 -RUN update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 -ENV LANG=en_US.UTF-8 -RUN apt update \ - && apt install -y --no-install-recommends \ - software-properties-common curl \ - && apt clean \ - && rm -rf /var/lib/apt/lists/* -RUN curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg -RUN echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu \ - $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | tee /etc/apt/sources.list.d/ros2.list > /dev/null -RUN apt update \ - && apt install -y --no-install-recommends \ - ros-humble-desktop ros-dev-tools \ - ros-humble-bondcpp ros-humble-ament-cmake-clang-format \ - ros-humble-vision-msgs \ - && apt clean \ - && rm -rf /var/lib/apt/lists/* -RUN echo "source /opt/ros/humble/setup.bash" >> /root/.bashrc -RUN rosdep init +FROM transitionary-ros2-qgc-image AS ros2-qgc-image ################################################################################ -# Stage 2 ###################################################################### +# Add Gazebo Sim ############################################################### ################################################################################ -FROM ros2-image AS ros2-qgc-zenoh-image - -# QGroundControl (as qgcuser) -# Based on https://docs.qgroundcontrol.com/master/en/qgc-user-guide/getting_started/download_and_install.html -WORKDIR / -RUN useradd -m -s /bin/bash qgcuser -RUN usermod -aG dialout qgcuser -# RUN apt-get remove modemmanager -y -RUN apt update \ - && apt install -y --no-install-recommends \ - gstreamer1.0-plugins-bad gstreamer1.0-libav gstreamer1.0-gl \ - libfuse2 \ - libxcb-xinerama0 libxkbcommon-x11-0 libxcb-cursor-dev \ - && apt clean \ - && rm -rf /var/lib/apt/lists/* -RUN wget https://d176tv9ibo4jno.cloudfront.net/latest/QGroundControl-x86_64.AppImage && \ - chmod +x /QGroundControl-x86_64.AppImage && \ - /QGroundControl-x86_64.AppImage --appimage-extract && \ - rm /QGroundControl-x86_64.AppImage -# Run with $ gosu qgcuser /squashfs-root/AppRun - -# Install wmctrl and xrandr to resize Gazebo/QGC window -RUN apt update \ - && apt install -y --no-install-recommends \ - wmctrl x11-xserver-utils \ - && apt clean \ - && rm -rf /var/lib/apt/lists/* - -# Install Zenoh -RUN echo "deb [trusted=yes] https://download.eclipse.org/zenoh/debian-repo/ /" | sudo tee -a /etc/apt/sources.list > /dev/null -RUN apt-get update && \ - apt-get install -y zenoh-bridge-ros2dds \ - && apt clean \ - && rm -rf /var/lib/apt/lists/* - -################################################################################ -# Stage 3 ###################################################################### -################################################################################ -FROM ros2-qgc-zenoh-image AS ros2-qgc-zenoh-gz-image +FROM ros2-qgc-image AS ros2-qgc-gz-image # Gazebo Harmonic # Based on https://gazebosim.org/docs/harmonic/install_ubuntu/ RUN apt update \ && apt install -y --no-install-recommends \ lsb-release gnupg \ - && apt clean \ - && rm -rf /var/lib/apt/lists/* -RUN curl https://packages.osrfoundation.org/gazebo.gpg --output /usr/share/keyrings/pkgs-osrf-archive-keyring.gpg -RUN echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] http://packages.osrfoundation.org/gazebo/ubuntu-stable $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/gazebo-stable.list > /dev/null -RUN apt update \ + && curl https://packages.osrfoundation.org/gazebo.gpg --output /usr/share/keyrings/pkgs-osrf-archive-keyring.gpg \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] http://packages.osrfoundation.org/gazebo/ubuntu-stable $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/gazebo-stable.list > /dev/null \ + && apt update \ && apt install -y --no-install-recommends \ gz-harmonic ros-humble-ros-gzharmonic \ libgz-transport13-* libgz-msgs10-dev \ @@ -106,32 +25,36 @@ RUN apt update \ # Run with $ gz sim ################################################################################ -# Stage 4 ###################################################################### +# Add PX4 ###################################################################### ################################################################################ -FROM ros2-qgc-zenoh-gz-image AS ros2-qgc-zenoh-gz-px4-image +FROM ros2-qgc-gz-image AS ros2-qgc-gz-px4-image # PX4 SITL (NOTE: install PX4 tools first to avoid conflicts with ArduPilot, build later to customize) # Based on https://docs.px4.io/main/en/dev_setup/dev_env_linux_ubuntu.html COPY /_github_clones/PX4-Autopilot /aas/github_apps/PX4-Autopilot WORKDIR /aas/github_apps/PX4-Autopilot -RUN bash ./Tools/setup/ubuntu.sh --no-sim-tools +RUN bash ./Tools/setup/ubuntu.sh --no-sim-tools \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* ################################################################################ -# Stage 5 ###################################################################### +# Add ArduPilot ################################################################ ################################################################################ -FROM ros2-qgc-zenoh-gz-px4-image AS ros2-qgc-zenoh-gz-px4-ardupilot-image +FROM ros2-qgc-gz-px4-image AS ros2-qgc-gz-px4-ardupilot-image # ArduPilot SITL (temporarily as arduuser, then re chown to root) # Based on https://ardupilot.org/dev/docs/building-setup-linux.html#building-setup-linux COPY /_github_clones/ardupilot /aas/github_apps/ardupilot WORKDIR /aas/github_apps/ardupilot -RUN useradd -m -s /bin/bash arduuser && \ - echo "arduuser ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/arduuser && chmod 0440 /etc/sudoers.d/arduuser && \ - gosu arduuser git config --global --add safe.directory /aas/github_apps/ardupilot && \ - chown -R arduuser:arduuser /aas/github_apps/ardupilot -RUN USER=arduuser gosu arduuser bash ./Tools/environment_install/install-prereqs-ubuntu.sh -y -RUN gosu arduuser bash -c "cd /aas/github_apps/ardupilot && ./waf configure --board sitl && ./waf build" -RUN chown -R root:root /aas/github_apps/ardupilot +RUN useradd -m -s /bin/bash arduuser \ + && echo "arduuser ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/arduuser && chmod 0440 /etc/sudoers.d/arduuser \ + && gosu arduuser git config --global --add safe.directory /aas/github_apps/ardupilot \ + && chown -R arduuser:arduuser /aas/github_apps/ardupilot \ + && USER=arduuser gosu arduuser bash ./Tools/environment_install/install-prereqs-ubuntu.sh -y \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* +RUN gosu arduuser bash -c "cd /aas/github_apps/ardupilot && ./waf configure --board sitl && ./waf build" \ + && chown -R root:root /aas/github_apps/ardupilot # Run with $ /aas/github_apps/ardupilot/build/sitl/bin/arducopter # ArduPilot Gazebo Plugin @@ -152,11 +75,11 @@ RUN mkdir build && cd build && \ make -j$(nproc) # Pre-build in the Docker image to speed up the first use of sim_vehicle.py -RUN /aas/github_apps/ardupilot/Tools/autotest/sim_vehicle.py -v ArduCopter -RUN /aas/github_apps/ardupilot/Tools/autotest/sim_vehicle.py -v ArduPlane +RUN /aas/github_apps/ardupilot/Tools/autotest/sim_vehicle.py -v ArduCopter \ + && /aas/github_apps/ardupilot/Tools/autotest/sim_vehicle.py -v ArduPlane ################################################################################ -# Temporary stage to filter airframes ########################################## +# Ephemeral stage to grab AAS PX4 custom airframes ############################# ################################################################################ FROM ubuntu:22.04 AS airframe_filter_stage COPY simulation/simulation_resources/aircraft_models/ /temp_folder @@ -164,9 +87,9 @@ RUN mkdir /airframes RUN find /temp_folder -type f -regex '.*/[0-9]+_.*' -exec cp {} /airframes/ \; ################################################################################ -# Stage 6 ###################################################################### +# Build PX4 SITL with AAS airframes using the airframe_filter_stage stage ###### ################################################################################ -FROM ros2-qgc-zenoh-gz-px4-ardupilot-image AS ros2-qgc-zenoh-gz-px4custom-ardupilot-image +FROM ros2-qgc-gz-px4-ardupilot-image AS ros2-qgc-gz-px4custom-ardupilot-image # Apply PX4 patch (DDS Agent on custom IP, ...) created with $ git diff > ../px4-v1.16.2.patch COPY simulation/simulation_resources/patches/px4-v1.16.2.patch /aas/github_apps/px4-v1.16.2.patch @@ -190,9 +113,9 @@ RUN make px4_sitl # Run with $ /aas/github_apps/PX4-Autopilot/build/px4_sitl_default/bin/px4 ################################################################################ -# Stage 7 ###################################################################### +# Add GStreamer, MAVLink, flight_review, wave simulation, ZeroMQ ############### ################################################################################ -FROM ros2-qgc-zenoh-gz-px4custom-ardupilot-image AS ros2-qgc-zenoh-gz-px4custom-ardupilot-gst-logs-waves-zmq-image +FROM ros2-qgc-gz-px4custom-ardupilot-image AS ros2-qgc-gz-px4custom-ardupilot-gst-logs-waves-zmq-image # Add GStreamer packages to stream the cameras to the aircraft containers RUN apt update \ @@ -215,8 +138,8 @@ RUN apt-get update && \ && rm -rf /var/lib/apt/lists/* COPY /_github_clones/flight_review /aas/github_apps/flight_review WORKDIR /aas/github_apps/flight_review/app -RUN python3 -m venv /px4fr-env -RUN /px4fr-env/bin/pip3 install --no-cache-dir --upgrade pip && \ +RUN python3 -m venv /px4fr-env \ + && /px4fr-env/bin/pip3 install --no-cache-dir --upgrade pip && \ /px4fr-env/bin/pip3 install --no-cache-dir --resume-retries 5 -r requirements.txt # Build the Gazebo wave plugin in github_ws/ @@ -245,22 +168,22 @@ RUN pip3 install --no-cache-dir --upgrade pip \ && pip3 install --no-cache-dir --resume-retries 5 pyzmq ################################################################################ -# Stage 8 ###################################################################### +# Copy AAS resources and build AAS ROS2 workspace ############################## ################################################################################ -FROM ros2-qgc-zenoh-gz-px4custom-ardupilot-gst-logs-waves-zmq-image AS simulation-dev-image +FROM ros2-qgc-gz-px4custom-ardupilot-gst-logs-waves-zmq-image AS simulation-dev-image # Build the ROS 2 workspace COPY simulation/simulation_ws/src /aas/simulation_ws/src WORKDIR /aas/simulation_ws RUN rosdep update -RUN rosdep install --from-paths src/ --ignore-src --rosdistro humble -y +RUN rosdep install --from-paths src/ --ignore-src --rosdistro humble -y && apt clean && rm -rf /var/lib/apt/lists/* # Explicitly use bash, not sh, to source and build the workspace RUN bash -c "source /opt/ros/humble/setup.bash && (source /aas/github_ws/install/setup.bash || true) && colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release" # Copy resources and configuration files from this repository COPY simulation/simulation_resources/ /aas/simulation_resources -RUN chmod +x /aas/simulation_resources/aircraft_models/_create_ardupilot_models.sh -RUN chmod +x /aas/simulation_resources/simulation_worlds/_create_ardupilot_world.sh +RUN chmod +x /aas/simulation_resources/aircraft_models/_create_ardupilot_models.sh \ + && chmod +x /aas/simulation_resources/simulation_worlds/_create_ardupilot_world.sh # Copy QGC configuration (only for GND_CONTAINER=false) COPY ground/ground_resources/patches/QGroundControl.ini /home/qgcuser/.config/QGroundControl/QGroundControl.ini @@ -276,8 +199,8 @@ WORKDIR /aas/simulation_resources/aircraft_models/ RUN ruby _create_sdfs_using_sensor_config.rb # Source the workspaces -RUN echo "source /aas/github_ws/install/setup.bash" >> /root/.bashrc -RUN echo "source /aas/simulation_ws/install/setup.bash" >> /root/.bashrc +RUN echo "source /aas/github_ws/install/setup.bash" >> /root/.bashrc \ + && echo "source /aas/simulation_ws/install/setup.bash" >> /root/.bashrc # If needed (but already in .bashrc) $ source /opt/ros/humble/setup.bash && source /aas/github_ws/install/setup.bash && source /aas/simulation_ws/install/setup.bash # Final config diff --git a/tools_and_docs/sim_build.sh b/tools_and_docs/sim_build.sh index 5bb93b6..995a2d4 100755 --- a/tools_and_docs/sim_build.sh +++ b/tools_and_docs/sim_build.sh @@ -95,10 +95,13 @@ fi unzip -q -o "$ZIP_FILE" -d "$SCRIPT_DIR/.." if [ "$BUILD_DOCKER" = "true" ]; then - # The first build takes ~45' and ~70GB of disk usage (~23GB of content size) - docker build $BUILD_ARGS -t simulation-image -f "${SCRIPT_DIR}/docker/simulation.dockerfile" "${SCRIPT_DIR}/.." - docker build $BUILD_ARGS -t ground-image -f "${SCRIPT_DIR}/docker/ground.dockerfile" "${SCRIPT_DIR}/.." + # Build common layers reused between images + docker build $BUILD_ARGS --target ros2-image -t transitionary-ros2-image -f "${SCRIPT_DIR}/docker/aircraft.dockerfile" "${SCRIPT_DIR}/.." + docker build $BUILD_ARGS --target ros2-qgc-image -t transitionary-ros2-qgc-image -f "${SCRIPT_DIR}/docker/ground.dockerfile" "${SCRIPT_DIR}/.." + # Build the 3 main images, the first build takes ~45' docker build $BUILD_ARGS -t aircraft-image -f "${SCRIPT_DIR}/docker/aircraft.dockerfile" "${SCRIPT_DIR}/.." + docker build $BUILD_ARGS -t ground-image -f "${SCRIPT_DIR}/docker/ground.dockerfile" "${SCRIPT_DIR}/.." + docker build $BUILD_ARGS -t simulation-image -f "${SCRIPT_DIR}/docker/simulation.dockerfile" "${SCRIPT_DIR}/.." else echo -e "Skipping Docker builds" fi