Узлы и граф вычислений

Узел — это базовая единица программы в ROS; из узлов складывается граф вычислений всего робота.

Узел (node) — это отдельная программа в ROS, отвечающая за одну задачу: опрос датчика, управление мотором, планирование маршрута. Множество узлов и связей между ними образуют граф вычислений.

Один узел — одна обязанность

Главный архитектурный принцип ROS: дроби систему на узлы по принципу единственной ответственности. У нашей мобильной платформы это может быть узел lidar_driver (читает лидар), узел camera_driver (читает камеру), узел localization (определяет, где робот), узел planner (строит маршрут) и узел motor_controller (крутит колёса). Каждый можно запустить, остановить, перезапустить и отладить отдельно. Упал планировщик — драйверы продолжают работать.

Узлы могут жить в разных процессах и даже на разных компьютерах. Например, тяжёлую обработку изображения вынесли на мощный ноутбук, а простое управление моторами оставили на Raspberry Pi внутри робота — для ROS это по-прежнему один граф.

Граф вычислений

Если нарисовать все узлы кружками, а связи между ними стрелками, получится граф вычислений — карта всей программной системы робота в данный момент. Это не статичная схема из документации, а живое отражение того, что реально запущено прямо сейчас.

  +---------------+      /scan      +----------------+
  | lidar_driver  | -------------> | localization   |
  +---------------+                +----------------+
                                          |
                                     /pose | 
                                          v
  +---------------+    /cmd_vel     +----------------+
  | motor_control | <------------- |    planner     |
  +---------------+                +----------------+

Инструменты интроспекции

ROS 2 даёт команды, чтобы заглянуть в живой граф. Они начинаются с ros2 node.

# Список всех запущенных узлов
ros2 node list

# Подробности про конкретный узел: что публикует, на что подписан
ros2 node info /localization

Вывод (пример ros2 node list):

/lidar_driver
/localization
/planner
/motor_control

Имена и пространства имён

У каждого узла есть имя, по которому его видно в графе. Имена можно группировать в пространства имён (namespaces) — это особенно важно, когда роботов несколько. Если два одинаковых робота запустить с пространствами имён /robot1 и /robot2, их узлы и топики не столкнутся: будет /robot1/lidar_driver и /robot2/lidar_driver.

Как работает под капотом

Когда узел стартует, библиотека клиента ROS (для Python это rclpy) инициализирует контекст, регистрирует узел в DDS и запускает цикл обработки событий — executor. Executor крутится в spin() и вызывает ваши обработчики (колбэки), когда приходят сообщения, запросы или срабатывают таймеры. Пока узел «спиннится», он живёт; как только spin прерывается — узел корректно отключается от графа.

Частые ошибки

  • Запихивать всё в один узел. Теряется главное преимущество — независимость и отладка по частям.
  • Дублировать имена узлов. Два узла с одинаковым именем в одном домене конфликтуют; используйте namespace.
  • Забыть spin(). Без цикла обработки узел создан, но колбэки не вызываются — кажется, что «ничего не происходит».

Итоги

  • Узел — программа с одной задачей; робот состоит из множества узлов.
  • Граф вычислений — живая карта запущенных узлов и связей.
  • Команды ros2 node list/info показывают, что реально работает.
  • Namespaces разделяют узлы, когда роботов несколько.
Проверьте себя
1. Что такое узел (node) в ROS?
AФизический разъём на роботе
BОтдельная программа, отвечающая за одну задачу
CЦентральный сервер связи
DТип сообщения
2. Что показывает команда ros2 node list?
AСписок файлов проекта
BСписок запущенных в данный момент узлов
CИсторию команд
DСписок установленных дистрибутивов
3. Зачем нужны пространства имён (namespaces)?
AЧтобы ускорить узлы
BЧтобы избежать конфликтов имён, например при нескольких роботах
CЧтобы зашифровать сообщения
DЧтобы заменить топики