Руководство · Начальный · 1 час

Установка ROS 2 на Raspberry Pi и рабочее пространство

Запустите ROS 2 на Raspberry Pi: выберите операционную систему, установите из apt, соберите рабочее пространство colcon и настройте обмен по Wi-Fi.

Введение

В ROS 2 ничто не кажется сложным, пока вы не попытаетесь установить его на робота. В этот момент одновременно ломаются три несвязанные вещи: операционная система оказывается не той, рабочее пространство не собирается в памяти Pi, а ноутбук не видит узлы робота. Строго говоря, это не проблемы ROS, поэтому официальные руководства и не предупреждают о них.

С помощью этого руководства вы перейдёте от пустой SD-карты к тому, что команда ros2 topic list на ноутбуке работает с узлами, запущенными на роботе.

Выберите операционную систему, а не только плату

Бинарные пакеты ROS 2 собраны для Ubuntu, а не для Raspberry Pi OS. Raspberry Pi OS основан на Debian, поэтому пакетов apt там просто нет, а каждое обходное решение — сборка из исходников, Docker, conda — стоит часов ещё до написания кода робота.

Поэтому установите Ubuntu Server 24.04 LTS (64-разрядная версия) и согласуйте её с выпуском ROS 2, собранным под неё. На момент написания такая пара — Jazzy Jalisco, поддерживаемая до 2029 года; проверьте страницу установки, чтобы узнать актуальную версию, и замените название во всех местах.

При записи образа на SD-карту нужно правильно выбрать три вещи:

  • 64-разрядная версия. Пакеты ROS 2 arm64 существуют; пакетов armhf нет.
  • Server (сервер), а не Desktop (рабочий стол). У робота нет монитора, а графическая среда расходует RAM, который нужен для зрения.
  • Pi 4 с 4 GB или Pi 5. Плата с 2 GB нормально запускает ROS 2, но не позволяет комфортно собирать пакеты ROS.

Установка ROS 2 из apt

Добавьте источник apt для ROS 2, затем выполните установку. Настройка репозитория меняется от выпуска к выпуску, поэтому ниже приведена общая форма, а не фрагмент для запоминания:

sudo apt update && sudo apt install -y software-properties-common curl
sudo add-apt-repository universe

# Fetch and install the package that registers the ROS 2 apt repository and key.
export ROS_APT_SOURCE_VERSION=$(curl -s \
  https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest \
  | grep -F "tag_name" | awk -F\" '{print $4}')
curl -L -o /tmp/ros2-apt-source.deb \
  "https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo $VERSION_CODENAME)_all.deb"
sudo apt install -y /tmp/ros2-apt-source.deb

sudo apt update
sudo apt install -y ros-jazzy-ros-base ros-dev-tools

Обратите внимание: нужен ros-base, а не desktop. Метапакет desktop подтягивает RViz и демонстрационные графические интерфейсы (GUIs), которые робот без монитора никогда не запустит, а на SD-карте их установка занимает очень много времени. Визуализация должна выполняться на ноутбуке, где вы устанавливаете полный ros-jazzy-desktop.

ros-dev-tools предоставляет colcon и rosdep. Один раз инициализируйте rosdep:

sudo rosdep init      # skip if it says the file already exists
rosdep update

Подключите базовый слой (underlay), затем наложенный слой (overlay)

ROS 2 ничего не делает, пока не подключено его окружение, и именно здесь возникает большая часть ранней путаницы.

source /opt/ros/jazzy/setup.bash

Это базовый слой (underlay) — установленный дистрибутив. Ваше собственное рабочее пространство после сборки становится наложенным слоем (overlay) поверх него. Подключение наложенного слоя неявно подключает и базовый слой, на котором он был собран.

echo "source /opt/ros/jazzy/setup.bash" >> ~/.bashrc

Размещение базового слоя в .bashrc — стандартная и безопасная практика. Размещение там же наложенного слоя — ловушка, от которой стоит избавиться сразу: в день, когда у вас появятся два рабочих пространства или когда вы пересоберёте рабочее пространство для другого дистрибутива, каждый новый терминал будет молча начинать с устаревшего окружения, и вы полдня будете отлаживать фантомную проблему. Подключайте наложенный слой явно, отдельно для каждого терминала, там, где он нужен.

Создайте рабочее пространство и пакет

Рабочее пространство colcon — это каталог с src/ внутри. Вот и всё описание.

mkdir -p ~/ros2_ws/src && cd ~/ros2_ws
ros2 pkg create --build-type ament_python --license Apache-2.0 my_robot

Затем соберите его и подключите наложенный слой:

cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -y
colcon build --symlink-install
source install/setup.bash

Используйте --symlink-install. Он связывает файлы Python с местом установки, а не копирует их, поэтому изменение узла вступает в силу при следующем запуске, а не после пересборки. На Pi, где пересборка идёт медленно, это разница между итерациями и ожиданием.

После сборки в ~/ros2_ws находятся build/, install/ и log/ рядом с src/. Под контролем версий следует хранить только src/.

Сборка без исчерпания памяти Pi

colcon build компилирует пакеты параллельно, по одному процессу на ядро, и каждая компиляция C++ может занимать почти гигабайт. На четырёхъядерном Pi это четыре тяжёлых компилятора одновременно, и сборка завершается сообщением об остановленном процессе — либо вся плата полностью зависает.

MAKEFLAGS="-j1" colcon build --parallel-workers 1 --symlink-install

Так медленнее, но сборка завершается. У чистых пакетов Python этой проблемы нет; она возникает, как только вы собираете что-то с C++. Добавление нескольких гигабайт подкачки тоже помогает, хотя на SD-карте это исключительно медленно.

Свяжитесь с роботом с ноутбука

В ROS 2 нет главного узла (master). Узлы находят друг друга с помощью обнаружения DDS (DDS discovery) по сети, поэтому ноутбук и Pi в одной локальной сети (LAN) могут образовать единый граф вообще без настройки — если всё работает.

Задайте одинаковый домен на обеих машинах:

export ROS_DOMAIN_ID=42        # any value 0–101; the same on every machine

Домен разделяет сеть. Два робота в одной комнате с доменом по умолчанию будут слышать темы друг друга и бороться за них — это запоминающийся способ понять, что делает эта настройка.

Схема установки ROS 2 на двух машинах: Raspberry Pi на роботе запускает узлы камеры, детектора и привода, а ноутбук запускает RViz и инструменты командной строки; их соединяет облако Wi-Fi с подписью «DDS discovery over multicast» — обнаружением DDS через многоадресную передачу. На обеих машинах указано одинаковое значение ROS_DOMAIN_ID, а примечание отмечает точку доступа как компонент, блокирующий многоадресную передачу (multicast).
Один граф ROS 2 на двух машинах: узлы на роботе, визуализация на ноутбуке и шаг обнаружения между ними, зависящий от пересылки многоадресного трафика точкой доступа. Скачать SVG

Проверьте с ноутбука, пока на Pi работает узел talker:

ros2 topic list
ros2 node list
ros2 topic echo /chatter

Обеспечьте обнаружение через Wi-Fi

Случай, когда ros2 topic list показывает пустоту, хотя Pi явно публикует данные, — самая частая сетевая ошибка ROS 2, и почти никогда она не является виной ROS.

Обнаружение использует многоадресную передачу (multicast), а многие точки доступа её не пересылают. Бытовые маршрутизаторы часто ограничивают скорость многоадресного трафика или отбрасывают его, а режим «client isolation» (изоляция клиентов) или гостевая сеть полностью блокируют трафик между клиентами. Узлы работают; пакеты, которые должны были представить их друг другу, просто не приходят.

Проверяйте в таком порядке:

  1. Одна подсеть? Ноутбук в сети 5 GHz и Pi в гостевой SSID находятся в разных сетях, как бы ни были похожи их адреса.
  2. Одинаковый ROS_DOMAIN_ID в том терминале, где действительно работает узел? export в одном терминале не попадает в другой и не попадает в службу systemd.
  3. Попробуйте проводную связь. Если Ethernet работает, а Wi-Fi нет, вы доказали, что дело в многоадресной передаче, а не в ROS.
  4. Проверьте брандмауэр. Выполните sudo ufw allow in proto udp from <subnet> на обоих концах или отключите его на время проверки.
  5. Вернитесь к серверу обнаружения. Fast DDS может использовать известную конечную точку вместо многоадресной передачи — задайте ROS_DISCOVERY_SERVER на адрес робота на обеих машинах. Это надёжное решение в сети, которой вы не управляете.

Ещё один, менее заметный момент: поддерживайте синхронизацию часов. TF2 сравнивает метки времени между машинами, а Pi без RTC загружается с неверным временем. Установите chrony на обоих концах, иначе каждый поиск преобразования завершится ошибкой экстраполяции, похожей на ошибку ROS.

Запускайте узлы робота при загрузке

Робот, в который нужно подключаться по SSH, чтобы запустить узлы, фактически выключен. Исправьте это модулем systemd:

# /etc/systemd/system/my-robot.service
[Unit]
Description=Robot bringup
After=network-online.target

[Service]
User=ubuntu
Environment=ROS_DOMAIN_ID=42
ExecStart=/bin/bash -lc 'source /opt/ros/jazzy/setup.bash && \
  source /home/ubuntu/ros2_ws/install/setup.bash && \
  ros2 launch my_robot bringup.launch.py'
Restart=on-failure

[Install]
WantedBy=multi-user.target
sudo systemctl enable --now my-robot
journalctl -u my-robot -f

Строка Environment= важнее, чем кажется. systemd не читает ваш .bashrc, поэтому служба не наследует ни одной переменной ROS из интерактивного терминала — именно поэтому робот, работающий по SSH, замолкает при самостоятельном запуске.

Когда что-то идёт не так

Симптом Обычно
ros2: command not found Базовый слой не был подключён в этом терминале
ros2 topic list пуст на ноутбуке Многоадресная передача заблокирована или ROS_DOMAIN_ID не совпадает
Сборка прервалась без ошибки Не хватает памяти — ограничьте число параллельных рабочих процессов
Изменение кода не дало эффекта Сборка без --symlink-install или наложенный слой не подключён заново
Пакет не найден после сборки Наложенный слой не подключён или подключён до завершения сборки
Ошибки TF об экстраполяции в будущее Часы на машинах не синхронизированы
По SSH работает, при загрузке не работает Служба systemd не получает окружение ROS

Когда окружение работает, следующий вопрос — что в него поместить. Это уже вопрос проектирования, а не установки. Узлы, темы, сервисы и действия описывают выбор между шаблонами взаимодействия, а системы координат TF2 — часть, на которой люди спотыкаются после этого.

Исследуйте граф

Входит в эти сборки

Проекты и учебные пути, в которые входит это руководство.

Дополнительные материалы

Источники