Друзья, привет! 👋
Продолжаем наш цикл статей о ROS.
В прошлой статье мы поговорили об основных концепциях ROS2, а сегодня обзор файловой системы.
Наш Телеграмм канал, где мы описываем прогресс нашего проекта — https://t.me/it_s_working.
Полезные ссылки:
Репозиторий ROS2
Официальная документация
Введение
Файловая система ROS — где робот хранит свои «кирпичики»?
Мы же не ищем гвозди в ящике с болтами? (обычно это так 😀) Так вот, файловая система ROS — это идеально организованная мастерская, где каждый винтик, чертеж и инструкция лежат на своих местах. Сегодня мы разберёмся, как не заблудится в этом порядке и даже постараемся полюбить его.
ROS Filesystem Level
Представьте, что робот — это шкаф, который нужно собрать. Файловая система ROS — это:
📦 коробки с деталями (packages/пакеты);
📜 инструкции (launch-файлы);
🧩 список недостающих винтиков (dependencies/зависимости).
Если нарушить эту систему, робот превратится в груду непонятных запчастей. Давайте разбираться, как этого избежать!
📦 Пакеты (Packages) — «Контейнеры с LEGO»
Что это: минимальная единица ROS. Каждый пакет — это отдельный модуль: драйвер камеры, алгоритм навигации или даже набор тестов.
Полезная аналогия: представьте, что пакеты — это коробки с отдельными наборами деталей LEGO. Каждый набор из коробки — отдельное «изделие», но при этом и детали из разных наборов можно соединять друг с другом. Например, в коробке «Датчики» лежат детали для сборки лидара, а в «Моторы» — шестерни и провода, и всё соединяемо.
Цель пакетов: предоставить полезную функциональность в удобной для использования форме, чтобы программное обеспечение можно было легко использовать повторно. В целом, пакеты ROS следуют принципу «Золотой середины»: достаточно функциональности, чтобы быть полезным, но не слишком много, чтобы пакет не стал тяжелым и его было трудно использовать из другого программного обеспечения.
Пакет ROS — это просто папка, находящаяся внутри пути ROS_PACKAGE_PATH (https://wiki.ros.org/ROS/EnvironmentVariables#ROS_PACKAGE_PATH ), в котором есть файл package.xml. Пакеты — это самая атомарная/наименьшая единица, которую можно построить в ROS, и это способ, которым строится программное обеспечение.
my_robot_pkg/
├── CMakeLists.txt ← Главный сценарий сборки
├── package.xml ← Паспорт пакета: имя, версия, зависимости
├── include/
│ └── my_robot_pkg/ ← Чтобы не путать с другими пакетами
│ └── utils.h ← C++ заголовки (как чертежи для инженеров)
├── src/ ← Исходный код — святая святых
│ └── my_robot_pkg/ ← Для Python-модулей
│ └── algorithms.py ← Наш гениальный код, который можно экспортировать
├── scripts/ ← Исполняемые файлы (bash, Python)
│ └── startup.sh ← Например, скрипт для калибровки
├── msg/ ← Кастомные сообщения (если нужно)
│ └── RobotStatus.msg ← Типа: «Батарея: 73%, Статус: В порядке»
├── srv/ ← Кастомные сервисы
│ └── GetDiagnostics.srv ← Запрос → Ответ
└── launch/ ← Launch-файлы (не в стандарте, но все так делают)
└── core.launch ← Запускаем всё разом!
Дополнительные пояснения:
- Имя пакета — как номер детали в LEGO. Никаких пробелов или спецсимволов! Только буквы, цифры и подчеркивания.
- include/ — только для C++. Если писать на Python, можно пропустить.
- msg/ и srv/ — нужны, если стандартные сообщения ROS не устраивают. Нужно, чтобы ноды обменивались стихами?
-- Создайте Poem.msg! - scripts/ vs src/ — путаница возникает из-за Python:
исполняемые скрипты (например, node.py) → кладите в scripts/,модули для импорта (например, math_utils.py) → кладите в src/my_robot_pkg/. - CMakeLists.txt — это «дирижер»:
собирает C++ код; устанавливает связи между Python-модулями;генерирует код из .msg и .srv файлов. - package.xml — история, которую читает только ROS. Он сообщает ROS информацию о зависимостях, лицензии пакета и так далее (https://wiki.ros.org/catkin/package.xml). Он будто говорит: «Мне нужен пакет roscpp! И еще OpenCV, версии 4.2!»:<buildtool_depend>catkin</buildtool_depend> <depend>roscpp</depend> <depend>std_msgs</depend>
- launch/ — негласный стандарт. Да, этой папки нет в официальной документации, но вся экосистема ROS использует её для launch-файлов. Это как класть ключи в вазу у двери — вроде не по фэншую, но так делают все, чтобы не искать их по всему дому.
Почему так? Сообщество ROS давно договорилось: launch/ — стандартное место для скриптов запуска. Это упрощает жизнь: открыл любой пакет и сразу понял, где искать «кнопку старта».
Важно:
- ROS не требует строго следовать этой структуре, но так любой из сообщества сможет понять пакет даже в 3 часа ночи.
- Если лень создавать папки руками — можно использовать catkin_create_pkg, он сделает основу сам.
Совет:
Если пакет — простой скрипт на Python, структуру можно упростить:
my_mini_pkg/
├── CMakeLists.txt
├── package.xml
└── scripts/
└── my_awesome_node.py
Главное — не забыть в CMakeLists.txt указать:
catkin_install_python(PROGRAMS scripts/my_awesome_node.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})
Теперь попробуем создать тестовый пакет. Мы используем ROS2 запущенный в Docker контейнере, поэтому будем использовать аналог команды Catkin_create_pkg
ros2 pkg create
Данная команда принимает следующие аргументы:
[--package-format {2,3}]
[--description DESCRIPTION]
[--license LICENSE]
[--destination-directory DESTINATION_DIRECTORY]
[--build-type {cmake,ament_cmake,ament_python}]
[--dependencies DEPENDENCIES [DEPENDENCIES ...]]
[--maintainer-email MAINTAINER_EMAIL]
[--maintainer-name MAINTAINER_NAME]
[--node-name NODE_NAME]
[--library-name LIBRARY_NAME]
package_name
Будет создана следующая структура
📜 Launch-файлы — «Дирижёр оркестра»
Что это: скрипты, которые запускают ноды, параметры и другие пакеты одной командой.
Полезная аналогия: представьте, что launch-файл — это кнопка «Старт» на микроволновке. Нажал — и робот начинает греться (работать).
Пример:
<launch>
<!-- Запускаем ноду камеры -->
<node pkg="camera_driver" type="camera_node" name="my_camera" output="screen" />
<!-- Устанавливаем параметр частоты кадров -->
<param name="frame_rate" type="int" value="30" />
<!-- Подключаем алгоритм распознавания лиц -->
<include file="$(find face_detection)/launch/detect.launch" />
</launch>
Зачем это нужно:
можно запустить 10 нод одной командой: roslaunch my_robot startup.launch;
изменить параметры без пересборки кода (например, скорость робота);
переиспользовать куски кода, как конструктор.
🧩 Зависимости — «Список покупок для робота»
Что это: другие пакеты и библиотеки, без которых код не заработает.
Полезная аналогия: зависимости в ROS — как педали, цепь и колеса у велосипеда. Можно сколько угодно держаться за руль, но без этих деталей поехать не удастся. Зависимости — именно такие детали. ROS не будет искать и устанавливать зависимости сам — как велосипед сам не отрастит колёса или цепь.
Для установки зависимостей используется rosdep install.
Где указывать: в файле package.xml.
Например:
<depend>roscpp</depend> ← Основная библиотека ROS для C++
<depend>sensor_msgs</depend> ← Для работы с данными сенсоров
<exec_depend>opencv</exec_depend> ← OpenCV (уже должен быть установлен)
Заключение: зачем нам эти пакеты?
Всего через неделю мы уже могли бы забыть, например, как называется нода, которая читает данные с камеры. Но благодаря файловой системе ROS мы:
- быстро найдём нужный код по структуре пакета;
- переиспользуем (если нужно) launch-файлы для новых проектов;
- не будем тратить часы на поиск «пропавших» зависимостей.
В следующей статье начнём знакомство с вычислительным графом ROS — как ноды общаются сплетнями (и при чём тут топики).
__________________________________________________________________________________________
P.S. Попробуйте создать свой пакет — у вас точно получится. Если застряли, есть вопросы или темы, которые хотите обсудить — обязательно напишите в комментарии, — разберёмся вместе и сделаем наши статьи ещё полезнее!
Подписывайтесь на наш Телеграмм канал, где мы публикуем как сами применяем полученные знания на реальном примере — популярно делимся нашими результатами, вместе будет интереснее https://t.me/it_s_working!