From 11492b74dcf87b48c8fc3720a76cdf7a94a8afe0 Mon Sep 17 00:00:00 2001 From: Sebastian Loh Lindholm Date: Fri, 26 Jun 2026 23:50:41 +0200 Subject: [PATCH 1/2] Update install and runtime support across Ubuntu versions --- Dockerfile | 13 +++-- docker-compose-bridge.yml | 4 +- docker-compose-test.yml | 2 +- docker-compose.yml | 4 +- scripts/installation/dependencies.txt | 1 + scripts/installation/install_atos.sh | 33 +++++++++++- scripts/installation/install_deps.sh | 66 +++++++++++++++++++---- scripts/installation/install_functions.sh | 66 ++++++++++++++++++++--- setup_atos.sh | 38 ++++++++----- 9 files changed, 185 insertions(+), 42 deletions(-) diff --git a/Dockerfile b/Dockerfile index b90a777db..c4ecc4431 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,9 +19,12 @@ COPY ./atos_gui/requirements.txt ./atos_gui/requirements.txt COPY ./atos_gui/package.xml ./atos_gui/package.xml COPY ./atos_interfaces/package.xml ./atos_interfaces/package.xml COPY ./atos/package.xml ./atos/package.xml - -RUN --mount=type=cache,target=/var/cache/apt \ - ./scripts/installation/install_deps.sh ${REPO_DIR} COPY . . -RUN ./scripts/installation/install_atos.sh ${REPO_DIR} -WORKDIR /root/atos_ws \ No newline at end of file +RUN --mount=type=cache,target=/var/cache/apt \ + ./setup_atos.sh +WORKDIR /root/atos_ws +RUN chmod +x /root/atos_git/scripts/run_atosfleetmanagement.sh + +EXPOSE 8420 8765 9090 8114 + +CMD ["/bin/bash", "-lc", "/root/atos_git/scripts/run_atosfleetmanagement.sh"] diff --git a/docker-compose-bridge.yml b/docker-compose-bridge.yml index 79fc37b52..36b4c68e9 100644 --- a/docker-compose-bridge.yml +++ b/docker-compose-bridge.yml @@ -28,7 +28,7 @@ services: - "9090:9090" - "8765:8765" - "8000:8000" - command: bash -c "source /root/atos_ws/install/setup.sh ; ros2 launch atos launch_basic.py insecure:=True" + command: bash -c "source /root/.local/share/atos/venv/bin/activate ; source /root/atos_ws/install/setup.sh ; ros2 launch atos launch_basic.py insecure:=True" foxglove-studio: image: ghcr.io/foxglove/studio:1.76 networks: @@ -36,4 +36,4 @@ services: ports: - 8080:8080 volumes: - - ./plugins/foxglove/Map, 3D and control layout.json:/foxglove/default-layout.json \ No newline at end of file + - ./plugins/foxglove/Map, 3D and control layout.json:/foxglove/default-layout.json diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 254ece545..640a45fcb 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -15,7 +15,7 @@ services: - ./conf/conf/:/root/.astazero/ATOS/conf - ./conf/odr/:/root/.astazero/ATOS/odr - ./conf/osc/:/root/.astazero/ATOS/osc - command: bash -c "source /root/atos_ws/install/setup.sh ; python3 -m pytest /root/atos_ws/src/atos/scripts/integration_testing/run_scenario_test.py" + command: bash -c "source /root/.local/share/atos/venv/bin/activate ; source /root/atos_ws/install/setup.sh ; python3 -m pytest /root/atos_ws/src/atos/scripts/integration_testing/run_scenario_test.py" isoObject: image: astazero/iso_object_demo:latest networks: diff --git a/docker-compose.yml b/docker-compose.yml index 50b53ca8c..14c7370f0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,9 +14,9 @@ services: volumes: - ~/.astazero/ATOS/:/root/.astazero/ATOS/ network_mode: "host" - command: bash -c "source /root/atos_ws/install/setup.sh ; ros2 launch atos launch_basic.py insecure:=True" + command: bash -c "source /root/.local/share/atos/venv/bin/activate ; source /root/atos_ws/install/setup.sh ; ros2 launch atos launch_basic.py insecure:=True" foxglove-studio: image: ghcr.io/foxglove/studio:1.76 network_mode: "host" volumes: - - ./plugins/foxglove/Map, 3D and control layout.json:/foxglove/default-layout.json \ No newline at end of file + - ./plugins/foxglove/Map, 3D and control layout.json:/foxglove/default-layout.json diff --git a/scripts/installation/dependencies.txt b/scripts/installation/dependencies.txt index 15765b353..976e58269 100644 --- a/scripts/installation/dependencies.txt +++ b/scripts/installation/dependencies.txt @@ -11,6 +11,7 @@ gnupg2 lsb-release python3-pip + python3-openssl proj-bin clang libstdc++-12-dev diff --git a/scripts/installation/install_atos.sh b/scripts/installation/install_atos.sh index a37f96441..2bf37acef 100755 --- a/scripts/installation/install_atos.sh +++ b/scripts/installation/install_atos.sh @@ -13,6 +13,21 @@ ATOS_REPO_PATH="$1" source "${ATOS_REPO_PATH}/scripts/installation/install_functions.sh" check_command_failed $? "Failed to source ${ATOS_REPO_PATH}/scripts/installation/install_functions.sh" +ROS_DISTRO="${ROS_DISTRO:-$(get_supported_ros_distro)}" +check_command_failed $? "Failed to determine ROS 2 distribution for this Ubuntu release." +ATOS_VENV_PATH="$(get_atos_venv_path)" + +if [ -z "${ROS_DISTRO}" ]; then + echo "Failed to determine a supported ROS 2 distribution for this Ubuntu release." + exit 1 +fi + +if [ ! -f "${ATOS_VENV_PATH}/bin/activate" ]; then + echo "ATOS Python virtual environment was not found at ${ATOS_VENV_PATH}." + echo "Run setup_atos.sh again to recreate Python dependencies." + exit 1 +fi + ################################################ ############## Install ATOS #################### ################################################ @@ -32,12 +47,18 @@ echo "Dependecy installation done and ATOS workspace created." # First make sure the submodules are up to date echo "Updating submodules to make sure they are up to date..." cd $HOME/atos_ws/src/atos -git submodule update --init --recursive +if command -v git >/dev/null 2>&1 && git rev-parse --is-inside-work-tree >/dev/null 2>&1; then + git submodule update --init --recursive +else + echo "Skipping submodule update: source tree is not a git repository in this environment." +fi cd - # temporarily cd into the workspace and build with colcon echo "Building ATOS..." cd $HOME/atos_ws +# shellcheck disable=SC1090 +source "${ATOS_VENV_PATH}/bin/activate" source /opt/ros/$ROS_DISTRO/setup.bash MAKEFLAGS=-j4 colcon build --symlink-install --cmake-args -DCMAKE_EXPORT_COMPILE_COMMANDS=ON check_command_failed $? "Failed to build ATOS." @@ -47,15 +68,23 @@ cd - ###### Configure setup scripts ###### ##################################### +atos_venv_setup_script="source $ATOS_VENV_PATH/bin/activate" +atos_python_site_packages="$(python -c 'import site; print(site.getsitepackages()[0])')" +check_command_failed $? "Failed to determine ATOS Python site-packages path." +atos_pythonpath_script="export PYTHONPATH=$atos_python_site_packages:\$PYTHONPATH" atos_setup_script="source $HOME/atos_ws/install/setup." ros2_setup_script="source /opt/ros/$ROS_DISTRO/setup." case "$SHELL" in */bash) + add_source_line_if_needed $HOME/.bashrc "bash" "${atos_venv_setup_script}" + add_source_line_if_needed $HOME/.bashrc "bash" "${atos_pythonpath_script}" add_source_line_if_needed $HOME/.bashrc "bash" "${ros2_setup_script}" add_source_line_if_needed $HOME/.bashrc "bash" "${atos_setup_script}" ;; */zsh) + add_source_line_if_needed $HOME/.zshrc "zsh" "${atos_venv_setup_script}" + add_source_line_if_needed $HOME/.zshrc "zsh" "${atos_pythonpath_script}" add_source_line_if_needed $HOME/.zshrc "zsh" "${ros2_setup_script}" add_source_line_if_needed $HOME/.zshrc "zsh" "${atos_setup_script}" ;; @@ -63,4 +92,4 @@ case "$SHELL" in echo "Unsupported shell detected! Please use either bash or zsh shells to run ATOS" exit 1 ;; -esac \ No newline at end of file +esac diff --git a/scripts/installation/install_deps.sh b/scripts/installation/install_deps.sh index 5d643fc80..dd54c26da 100755 --- a/scripts/installation/install_deps.sh +++ b/scripts/installation/install_deps.sh @@ -24,16 +24,62 @@ if [ -z "${ROS_DISTRO:-}" ]; then exit 1 fi -PIP_INSTALL_CMD=(python3 -m pip install) -if python3 -m pip help install 2>/dev/null | grep -q -- "--break-system-packages"; then - PIP_INSTALL_CMD+=(--break-system-packages) -fi +ATOS_VENV_PATH="$(get_atos_venv_path)" +apt_update_retry() { + local attempts=5 + local delay=5 + local i=1 + while [ "$i" -le "$attempts" ]; do + if sudo apt-get update; then + return 0 + fi + echo "apt update failed (attempt ${i}/${attempts}); cleaning apt cache and retrying..." + sudo apt-get clean + sudo rm -rf /var/lib/apt/lists/* + sleep "$delay" + i=$((i + 1)) + done + return 1 +} + +apt_install_retry() { + local attempts=3 + local delay=5 + local i=1 + while [ "$i" -le "$attempts" ]; do + if sudo apt-get install -y "$@"; then + return 0 + fi + echo "apt install failed (attempt ${i}/${attempts}); retrying..." + sleep "$delay" + i=$((i + 1)) + done + return 1 +} # Update and install required dependencies specified in dependencies.txt and requirements.txt file apt_deps=$(cat ${ATOS_REPO_PATH}/scripts/installation/dependencies.txt | tr '\n' ' ') echo "Installing dependencies... $apt_deps" -sudo apt update && sudo apt install -y ${apt_deps} -"${PIP_INSTALL_CMD[@]}" -r ${ATOS_REPO_PATH}/scripts/installation/requirements.txt +apt_update_retry +apt_install_retry ${apt_deps} +apt_install_retry python3-pip +apt_install_retry python3-venv + +if [ -d "${ATOS_VENV_PATH}" ] && [ "$REINSTALL" = true ]; then + echo "Removing existing ATOS Python virtual environment at ${ATOS_VENV_PATH}..." + rm -rf "${ATOS_VENV_PATH}" +fi + +if [ ! -f "${ATOS_VENV_PATH}/bin/activate" ]; then + echo "Creating ATOS Python virtual environment at ${ATOS_VENV_PATH}..." + mkdir -p "$(dirname "${ATOS_VENV_PATH}")" + # ROS Python tooling depends on distro packages such as `empy` being importable + # while the ATOS venv is active during colcon builds. + python3 -m venv --system-site-packages "${ATOS_VENV_PATH}" +fi + +"${ATOS_VENV_PATH}/bin/python" -m pip install --upgrade pip +"${ATOS_VENV_PATH}/bin/python" -m pip install -r ${ATOS_REPO_PATH}/scripts/installation/requirements.txt # Check if apt failed to install dependencies check_command_failed $? "Failed to install dependencies." @@ -46,7 +92,8 @@ if ! (apt list | grep -q "ros-$ROS_DISTRO-desktop"); then echo "Adding the ROS2 $ROS_DISTRO apt repository..." # Install ROS2 prerequisites - sudo apt update && sudo apt install -y lsb-release ros-dev-tools + apt_update_retry + apt_install_retry lsb-release ros-dev-tools # Authorize the ROS2 gpg key with apt sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key \ @@ -60,7 +107,8 @@ fi # Install ROS2 packages echo "Installing ROS2 packages..." -sudo apt install -y \ +apt_update_retry +apt_install_retry \ ros-${ROS_DISTRO}-desktop \ python3-rosdep \ ros-${ROS_DISTRO}-launch-pytest @@ -75,7 +123,7 @@ check_command_failed $? "Failed to install ROS2 dependencies." ######## Install ATOS GUI dependencies ######## ############################################### -"${PIP_INSTALL_CMD[@]}" -r ${ATOS_REPO_PATH}/atos_gui/requirements.txt +"${ATOS_VENV_PATH}/bin/python" -m pip install -r ${ATOS_REPO_PATH}/atos_gui/requirements.txt ########################################### ###### Install some deps from source ###### diff --git a/scripts/installation/install_functions.sh b/scripts/installation/install_functions.sh index 9f8601a07..da9b9dae5 100755 --- a/scripts/installation/install_functions.sh +++ b/scripts/installation/install_functions.sh @@ -3,7 +3,59 @@ # Function to get Ubuntu distribution codename get_ubuntu_codename() { source /etc/os-release - echo $UBUNTU_CODENAME + + if [ -n "${UBUNTU_CODENAME:-}" ]; then + echo "$UBUNTU_CODENAME" + return 0 + fi + + if [ -n "${VERSION_CODENAME:-}" ]; then + echo "$VERSION_CODENAME" + return 0 + fi + + case "${VERSION_ID:-}" in + "20.04"|"20") + echo "focal" + ;; + "22.04"|"22") + echo "jammy" + ;; + "24.04"|"24") + echo "noble" + ;; + esac +} + +is_standard_ubuntu() { + source /etc/os-release + [ "${ID:-}" = "ubuntu" ] +} + +is_ubuntu_core() { + source /etc/os-release + [ "${ID:-}" = "ubuntu-core" ] +} + +get_supported_ros_distro() { + case "$(get_ubuntu_codename)" in + "focal") + echo "foxy" + ;; + "jammy") + echo "humble" + ;; + "noble") + echo "jazzy" + ;; + *) + return 1 + ;; + esac +} + +get_atos_venv_path() { + echo "$HOME/.local/share/atos/venv" } # Function that checks if command failed @@ -39,12 +91,12 @@ update_symlink() { add_source_line_if_needed() { local file="$1" local shell_type="$2" - local source_line="$3$shell_type" + local source_line="$3" - if [ ! grep -qF "$source_line" "$file" ]; then - # Ask the user if they want to add the source line. - # First check for noninteractive shell with DEBAIN_FRONTEND=noninteractive - if [ -z "$DEBIAN_FRONTEND" && ! -z $GITHUB_ACTION ]; then + if ! grep -qF "$source_line" "$file"; then + # Ask the user only for interactive local shells. + # In non-interactive environments (e.g. CI), append automatically. + if [ -t 0 ] && [ -z "$DEBIAN_FRONTEND" ] && [ -z "$GITHUB_ACTION" ]; then echo "Do you want to add the following line to your $shell_type config file $file:" echo "$source_line" echo "y/n" @@ -58,4 +110,4 @@ add_source_line_if_needed() { echo "$source_line" >> "$file" fi fi -} \ No newline at end of file +} diff --git a/setup_atos.sh b/setup_atos.sh index 91ef83090..6ada7c3eb 100755 --- a/setup_atos.sh +++ b/setup_atos.sh @@ -9,28 +9,38 @@ source "scripts/installation/install_functions.sh" # Get this file location REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd)" -# Check if running on Ubuntu -if ! grep -q "Ubuntu" /etc/os-release; then - echo "This script is designed for Ubuntu systems only." +# Check if running on a supported Ubuntu variant +if is_ubuntu_core; then + echo "Ubuntu Core is not supported for native ATOS installation." + echo "Use Docker instead, or run this script on Ubuntu 20.04, 22.04, or 24.04 with apt available." exit 1 fi -# Set ROS_DISTRO based on Ubuntu distribution -case "$(get_ubuntu_codename)" in - "focal") - ;; - "jammy") - ;; - *) - echo "Unsupported Ubuntu distribution. Only 20.04 (focal) and 22.04 (jammy) are supported." +if ! is_standard_ubuntu; then + echo "This script is designed for standard Ubuntu systems only." exit 1 - ;; -esac +fi + +UBUNTU_CODENAME="$(get_ubuntu_codename)" +ROS_DISTRO="$(get_supported_ros_distro)" + +if [ -z "${UBUNTU_CODENAME}" ] || [ -z "${ROS_DISTRO}" ]; then + echo "Unsupported Ubuntu distribution. Supported releases are 20.04 (focal), 22.04 (jammy), and 24.04 (noble)." + exit 1 +fi + +if ! command -v apt-get >/dev/null 2>&1; then + echo "apt-get is required for native ATOS installation but was not found on this system." + exit 1 +fi + +export ROS_DISTRO # Add -h/--help option if [ "$1" == "-h" ] || [ "$1" == "--help" ]; then echo "Usage: ./setup_atos.sh [single option]" - echo "This script will install all necessary dependencies, setup the ROS workspace at ~/atos_ws and install ATOS. Please open and inspect this script for further details." + echo "This script will install all necessary dependencies, setup the ROS workspace at ~/atos_ws and install ATOS." + echo "Supported native targets: Ubuntu 20.04 with ROS 2 Foxy, Ubuntu 22.04 with ROS 2 Humble, and Ubuntu 24.04 with ROS 2 Jazzy." echo "Options:" echo " -h, --help Show this help message and exit" echo " -r Reinstall dependencies" From c862dc34962f995d343afa87648e3c1184f5b5f3 Mon Sep 17 00:00:00 2001 From: Sebastian Loh Lindholm Date: Sat, 27 Jun 2026 00:08:03 +0200 Subject: [PATCH 2/2] Remove fleet management script dependency from Dockerfile --- Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index c4ecc4431..17521cd4d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,8 +22,7 @@ COPY ./atos/package.xml ./atos/package.xml COPY . . RUN --mount=type=cache,target=/var/cache/apt \ ./setup_atos.sh -WORKDIR /root/atos_ws -RUN chmod +x /root/atos_git/scripts/run_atosfleetmanagement.sh + WORKDIR /root/atos_ws EXPOSE 8420 8765 9090 8114