@@ -86,11 +86,12 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
8686# Keep pip-managed tooling isolated while still exposing Debian/ROS Python modules
8787# that ROS entrypoints expect at runtime.
8888RUN python3 -m venv --system-site-packages ${VIRTUAL_ENV} \
89- && ${VIRTUAL_ENV}/bin/pip install -U --retries 10 --timeout 120 pip setuptools wheel
89+ && ${VIRTUAL_ENV}/bin/pip install -U --retries 10 --timeout 120 pip ' setuptools<80' wheel
9090
9191# ── PyTorch (CUDA 12.8 wheel) ────────────────────────────────────────────────
9292RUN ${VIRTUAL_ENV}/bin/pip install -U --retries 10 --timeout 120 --extra-index-url https://download.pytorch.org/whl/cu128 \
93- torch torchvision torchaudio
93+ torch torchvision torchaudio \
94+ && ${VIRTUAL_ENV}/bin/pip install -U --retries 10 --timeout 120 'setuptools<80'
9495
9596# ── General Python packages ──────────────────────────────────────────────────
9697RUN ${VIRTUAL_ENV}/bin/pip install -U --retries 10 --timeout 120 \
@@ -103,6 +104,11 @@ RUN ${VIRTUAL_ENV}/bin/pip install -U --retries 10 --timeout 120 \
103104
104105# ── elevation_mapping_cupy Python deps ──────────────────────────────────────
105106RUN if [ "$INSTALL_EMCUPY_ROSDEPS" = "true" ]; then \
107+ if [ "$ROS_DISTRO" = "humble" ]; then \
108+ SCIPY_SPEC='scipy>=1.10,<1.16'; \
109+ else \
110+ SCIPY_SPEC='scipy>=1.17.1'; \
111+ fi; \
106112 ${VIRTUAL_ENV}/bin/pip install --prefer-binary -U --retries 10 --timeout 120 \
107113 'scikit-learn' \
108114 'opencv-python' \
@@ -112,13 +118,14 @@ RUN if [ "$INSTALL_EMCUPY_ROSDEPS" = "true" ]; then \
112118 "numpy>=1.24,<2" \
113119 shapely \
114120 transforms3d \
115- 'scipy>=1.17.1' ; \
121+ "${SCIPY_SPEC}" ; \
116122 fi
117123
118124# ── elevation_mapping_cupy apt deps ─────────────────────────────────────────
119125RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
120126 if [ "$INSTALL_EMCUPY_ROSDEPS" = "true" ]; then \
121- apt-get update && apt-get install -y --no-install-recommends \
127+ apt-get update \
128+ && apt-get install -y --no-install-recommends \
122129 libboost-all-dev \
123130 ros-${ROS_DISTRO}-grid-map-msgs \
124131 ros-${ROS_DISTRO}-grid-map-ros \
@@ -130,9 +137,6 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
130137 ros-${ROS_DISTRO}-cv-bridge \
131138 ros-${ROS_DISTRO}-tf-transformations \
132139 ros-${ROS_DISTRO}-rviz2 \
133- ros-${ROS_DISTRO}-ros-gz \
134- ros-${ROS_DISTRO}-ros-gz-bridge \
135- ros-${ROS_DISTRO}-ros-gz-sim \
136140 ros-${ROS_DISTRO}-point-cloud-transport \
137141 ros-${ROS_DISTRO}-camera-calibration-parsers \
138142 ros-${ROS_DISTRO}-camera-info-manager \
@@ -142,6 +146,36 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
142146 python3-colcon-common-extensions \
143147 python3-colcon-parallel-executor \
144148 python3-colcon-output \
149+ && pick_first_pkg() { \
150+ for pkg in "$@"; do \
151+ if apt-get install -s --no-install-recommends "$pkg" > /dev/null 2>&1; then \
152+ apt-get install -y --no-install-recommends "$pkg"; \
153+ return 0; \
154+ fi; \
155+ done; \
156+ echo "None of these packages exist for ${ROS_DISTRO}: $*" >&2; \
157+ exit 1; \
158+ } \
159+ && install_if_exists() { \
160+ pkg="$1"; \
161+ if apt-get install -s --no-install-recommends "$pkg" > /dev/null 2>&1; then \
162+ apt-get install -y --no-install-recommends "$pkg"; \
163+ else \
164+ echo "Skipping unavailable package: $pkg"; \
165+ fi; \
166+ } \
167+ && pick_first_pkg \
168+ ros-${ROS_DISTRO}-ros-gz \
169+ ros-${ROS_DISTRO}-ros-ign \
170+ && pick_first_pkg \
171+ ros-${ROS_DISTRO}-ros-gz-bridge \
172+ ros-${ROS_DISTRO}-ros-ign-bridge \
173+ && pick_first_pkg \
174+ ros-${ROS_DISTRO}-ros-gz-sim \
175+ ros-${ROS_DISTRO}-ros-ign-gazebo \
176+ && install_if_exists ros-${ROS_DISTRO}-gazebo-ros-pkgs \
177+ && install_if_exists ros-${ROS_DISTRO}-turtlebot3-gazebo \
178+ && install_if_exists ros-${ROS_DISTRO}-turtlebot3-description \
145179 && apt-get clean && rm -rf /var/lib/apt/lists/*; \
146180 fi
147181
0 commit comments