1- ARG ROS_DISTRO=rolling
2- FROM ros:$ROS_DISTRO-ros-base as ci
1+ ARG ROS_DISTRO=jazzy
2+ FROM ros:$ROS_DISTRO-ros-base AS ci
33
44ENV DEBIAN_FRONTEND=noninteractive
55
@@ -18,6 +18,7 @@ RUN apt-get -q update \
1818 clang-tools \
1919 python3-pip \
2020 python3-dev \
21+ python3-venv \
2122 lsb-release \
2223 wget \
2324 gnupg \
@@ -26,7 +27,8 @@ RUN apt-get -q update \
2627 && apt-get clean -y \
2728 && rm -rf /var/lib/apt/lists/*
2829
29- # Install all ROS dependencies
30+ # Install all ROS dependencies for _just_ blue
31+ # (we have not imported other repos from .repos files)
3032RUN apt-get -q update \
3133 && apt-get -q -y upgrade \
3234 && rosdep update \
@@ -36,16 +38,24 @@ RUN apt-get -q update \
3638 && apt-get clean -y \
3739 && rm -rf /var/lib/apt/lists/*
3840
39- FROM ci as robot
40-
41- # Configure a new non-root user
42- ARG USERNAME=blue
41+ # This stage includes
42+ # - Switching to the non-root user
43+ # - Copying 'blue' source from this repo into the non-root user's workspace
44+ # - Installing blue deps using pip, apt and rosdep
45+ # - Installs the remaining blue dependencies from blue_robot.repos
46+ # - Installs deps from rosdep for all src dependencies
47+ # - colcon build
48+ #
49+ FROM ci AS robot
50+
51+ #
52+ # Ubuntu 24.04 "Noble", which is used as the base image for
53+ # jazzy and rolling images, now includes a user "ubuntu" at UID 1000
54+ ARG USERNAME=ubuntu
4355ARG USER_UID=1000
4456ARG USER_GID=$USER_UID
4557
46- RUN groupadd --gid $USER_GID $USERNAME \
47- && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \
48- && echo $USERNAME ALL=\( root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
58+ RUN echo $USERNAME ALL=\( root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
4959 && chmod 0440 /etc/sudoers.d/$USERNAME \
5060 && usermod -a -G dialout $USERNAME \
5161 && echo "source /usr/share/bash-completion/completions/git" >> /home/$USERNAME/.bashrc
@@ -56,6 +66,16 @@ ENV DEBIAN_FRONTEND=noninteractive
5666USER $USERNAME
5767ENV USER=$USERNAME
5868
69+ # Python in Ubuntu is now marked as a "Externally managed environment",
70+ # Per best practice, create a venv for local python packages
71+ #
72+ # These two ENVs effectively "activate" the venv for subsequent calls to
73+ # python/pip in the Dockerfile
74+ WORKDIR /home/$USERNAME
75+ ENV VIRTUAL_ENV=/home/$USERNAME/.venv/blue
76+ RUN python3 -m venv --system-site-packages --symlinks $VIRTUAL_ENV
77+ ENV PATH="$VIRTUAL_ENV/bin:$PATH"
78+
5979# Install MAVROS dependencies
6080WORKDIR /home/$USERNAME
6181RUN wget https://raw.githubusercontent.com/mavlink/mavros/ros2/mavros/scripts/install_geographiclib_datasets.sh \
@@ -81,58 +101,100 @@ RUN sudo apt-get -q update \
81101 gstreamer1.0-plugins-ugly \
82102 gstreamer1.0-plugins-bad \
83103 gstreamer1.0-libav \
104+ libgstreamer1.0-dev \
105+ gstreamer1.0-gl \
106+ libgstreamer-plugins-base1.0-dev \
84107 && sudo apt-get autoremove -y \
85108 && sudo apt-get clean -y \
86109 && sudo rm -rf /var/lib/apt/lists/*
87110
111+ # Manually install MAVROS from source in the ws_blue/ workspace
112+ WORKDIR $USER_WORKSPACE/src/
113+ ARG MAVROS_RELEASE=ros2
114+ # mavlink-gdp-release has not been released for Jazzy, so we use the Rolling release
115+ ARG MAVLINK_RELEASE=release/rolling/mavlink
116+ RUN git clone --depth 1 -b ${MAVROS_RELEASE} https://github.com/mavlink/mavros.git
117+ RUN git clone --depth 1 --recursive -b ${MAVLINK_RELEASE} https://github.com/mavlink/mavlink-gbp-release.git mavlink
118+ # - mavgen uses future.standard_library for backwards compatibility with Python2;
119+ # However, this caused issues with Python 3.12 installed in "noble".
120+ # Comment those lines out in mavlink.
121+ #
122+ # - Fix linkage for yaml-cpp in mavros_extra_plugins
123+ RUN sed -i -e 's/^from future import standard_library/#from future import standard_library/' \
124+ -e 's/standard_library.install_aliases()/#standard_library.install_aliases()/' \
125+ mavlink/pymavlink/generator/mavgen.py && \
126+ sed -i -e 's/^# find_package(yaml_cpp REQUIRED)/find_package(yaml-cpp REQUIRED)/' \
127+ -e '/^ament_target_dependencies(mavros_extras_plugins$/i target_link_libraries(mavros_extras_plugins yaml-cpp::yaml-cpp)' \
128+ -e '/^ament_target_dependencies(mavros_extras$/i target_link_libraries(mavros_extras yaml-cpp::yaml-cpp)' \
129+ mavros/mavros_extras/CMakeLists.txt
130+
131+ WORKDIR $USER_WORKSPACE
88132RUN sudo apt-get -q update \
89133 && sudo apt-get -q -y upgrade \
134+ && vcs import src < src/blue/blue.repos \
90135 && rosdep update \
91136 && rosdep install -y --from-paths src --ignore-src --rosdistro ${ROS_DISTRO} \
92137 && sudo apt-get autoremove -y \
93138 && sudo apt-get clean -y \
94139 && sudo rm -rf /var/lib/apt/lists/*
95140
141+ # Actually build workspace
142+ RUN . "/opt/ros/${ROS_DISTRO}/setup.sh" \
143+ && colcon build
144+
96145RUN echo "source ${USER_WORKSPACE}/install/setup.bash" >> /home/$USERNAME/.bashrc \
97- && echo "source /opt/ros/${ROS_DISTRO}/setup.bash" >> /home/$USERNAME/.bashrc
146+ && echo "source /opt/ros/${ROS_DISTRO}/setup.bash" >> /home/$USERNAME/.bashrc \
147+ && echo "source $VIRTUAL_ENV/bin/activate" >> /home/$USERNAME/.bashrc \
148+ && echo "\n # Ensure colcon is run in the venv\n alias colcon='python3 -m colcon'" >> /home/$USERNAME/.bashrc
98149
99- FROM robot as desktop
150+ FROM robot AS desktop
100151
101152ENV DEBIAN_FRONTEND=noninteractive
102- ENV GZ_VERSION=garden
103-
104- # Install Gazebo Garden: https://gazebosim.org/docs/garden/install_ubuntu
105- RUN sudo wget https://packages.osrfoundation.org/gazebo.gpg -O /usr/share/keyrings/pkgs-osrf-archive-keyring.gpg \
106- && 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 \
107- && sudo apt-get -q update \
108- && sudo apt-get -y --quiet --no-install-recommends install \
109- gz-garden \
110- && sudo apt-get autoremove -y \
111- && sudo apt-get clean -y \
112- && sudo rm -rf /var/lib/apt/lists/*
113-
114- # Install ArduPilot and ardupilot_gazebo dependencies
115- RUN sudo apt-get -q update \
116- && sudo apt-get -q -y upgrade \
117- && sudo apt-get -q install --no-install-recommends -y \
153+ ENV GZ_VERSION=harmonic
154+
155+ # Install Gazebo Harmonic: https://gazebosim.org/docs/harmonic/install_ubuntu
156+ # Per DL3004, use "USER root" rather than "sudo"
157+ # https://github.com/hadolint/hadolint/wiki/DL3004
158+ USER root
159+ # Install custom rosdep list
160+ ADD --chown=root:root --chmod=0644 https://raw.githubusercontent.com/osrf/osrf-rosdep/master/gz/00-gazebo.list /etc/ros/rosdep/sources.list.d/00-gazebo.list
161+ RUN wget https://packages.osrfoundation.org/gazebo.gpg -O /usr/share/keyrings/pkgs-osrf-archive-keyring.gpg \
162+ && 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" | tee /etc/apt/sources.list.d/gazebo-stable.list > /dev/null \
163+ && apt-get -q update \
164+ && apt-get -y --quiet --no-install-recommends install \
165+ cppzmq-dev \
166+ gz-${GZ_VERSION} \
167+ python3-pexpect \
118168 python3-wxgtk4.0 \
169+ python3-future \
119170 rapidjson-dev \
120171 xterm \
121- && sudo apt-get autoremove -y \
122- && sudo apt-get clean -y \
123- && sudo rm -rf /var/lib/apt/lists/*
172+ rapidjson-dev \
173+ libopencv-dev \
174+ && apt-get autoremove -y \
175+ && apt-get clean -y \
176+ && rm -rf /var/lib/apt/lists/*
177+ USER $USERNAME
124178
125179# Clone ArduSub
126180# ArduSub is installed for simulation purposes ONLY
127181# When deployed onto hardware, the native installation of ArduSub
128182# (on the FCU) will be used.
129183WORKDIR /home/$USERNAME
130- RUN git clone https://github.com/ArduPilot/ardupilot.git --recurse-submodules
184+ # Really should do version pinning but Sub-4.5 is waaaay behind master
185+ # (e.g. it doesn't know about "noble" yet)
186+ ARG ARDUPILOT_RELEASE=master
187+ RUN git clone -b ${ARDUPILOT_RELEASE} https://github.com/ArduPilot/ardupilot.git --recurse-submodules
131188
132189# Install ArduSub dependencies
133190WORKDIR /home/$USERNAME/ardupilot
134191ENV SKIP_AP_EXT_ENV=1 SKIP_AP_GRAPHIC_ENV=1 SKIP_AP_COV_ENV=1 SKIP_AP_GIT_CHECK=1
135- RUN Tools/environment_install/install-prereqs-ubuntu.sh -y
192+ # Do not install the STM development tools
193+ ENV DO_AP_STM_ENV=0
194+ # Do not activate the Ardupilot venv by default
195+ ENV DO_PYTHON_VENV_ENV=0
196+ RUN echo "\n # Below from ardupilot script \" install-prereqs-ubuntu.sh\"\n " >> /home/$USERNAME/.bashrc && \
197+ Tools/environment_install/install-prereqs-ubuntu.sh -y
136198
137199# Build ArduSub
138200WORKDIR /home/$USERNAME/ardupilot
@@ -155,7 +217,7 @@ RUN [ "/bin/bash" , "-c" , " \
155217WORKDIR $USER_WORKSPACE
156218RUN sudo apt-get -q update \
157219 && sudo apt-get -q -y upgrade \
158- && vcs import src < src/blue/blue .repos \
220+ && vcs import src < src/blue/sim .repos \
159221 && rosdep update \
160222 && rosdep install -y --from-paths src --ignore-src --rosdistro ${ROS_DISTRO} \
161223 && sudo apt-get autoremove -y \
@@ -171,7 +233,7 @@ RUN . "/opt/ros/${ROS_DISTRO}/setup.sh" \
171233# Setup the simulation environment variables
172234RUN echo "source ${USER_WORKSPACE}/src/blue/.docker/entrypoints/sim.sh" >> /home/$USERNAME/.bashrc
173235
174- FROM desktop as desktop-nvidia
236+ FROM desktop AS desktop-nvidia
175237
176238# Install NVIDIA software
177239RUN sudo apt-get update \
0 commit comments