Библиотеки клиента: rclpy и rclcpp

Чтобы писать узлы, нужна клиентская библиотека: для Python это rclpy. Разберём её устройство.

rclpy — официальная клиентская библиотека ROS 2 для Python; она даёт классы и функции для создания узлов, издателей, подписчиков и таймеров.

Три уровня: rcl, rclpy, rclcpp

В основе ROS 2 лежит библиотека на C под названием rcl (ROS Client Library) — она реализует базовую логику узлов поверх middleware. Поверх неё построены языковые обёртки: rclcpp для C++ и rclpy для Python. Благодаря общему ядру узлы на Python и C++ ведут себя одинаково и без проблем общаются друг с другом — связь идёт через DDS, а не через язык.

БиблиотекаЯзыкКогда выбирают
rclpyPythonПрототипы, логика высокого уровня, обучение
rclcppC++Производительность, реальное время, драйверы
rclCЯдро, на нём построены остальные

Скелет узла на rclpy

Любой узел на Python устроен по одному шаблону: импортируем rclpy, наследуемся от класса Node, инициализируем библиотеку, создаём узел, запускаем spin и в конце аккуратно завершаемся. Код ниже помечен как language-text, потому что его нельзя выполнить в браузере — нужен установленный ROS-рантайм.

import rclpy
from rclpy.node import Node

class MyNode(Node):
    def __init__(self):
        super().__init__('my_node')   # имя узла в графе
        self.get_logger().info('Узел запущен')

def main():
    rclpy.init()           # инициализация ROS
    node = MyNode()        # создание узла
    rclpy.spin(node)       # цикл обработки событий
    node.destroy_node()    # корректное завершение
    rclpy.shutdown()

if __name__ == '__main__':
    main()

Что делает каждая строка

  • rclpy.init() — поднимает контекст ROS, подключается к middleware. Без него ничего не заработает.
  • super().__init__('my_node') — регистрирует узел в графе под именем my_node.
  • rclpy.spin(node) — блокирует выполнение и крутит executor: ждёт сообщения, таймеры, запросы и вызывает колбэки.
  • destroy_node() и shutdown() — освобождают ресурсы при выходе.

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

spin() — это, по сути, бесконечный цикл, который опрашивает middleware: «есть новые события?». Когда приходит сообщение по подписке, срабатывает таймер или поступает запрос сервиса, executor ставит соответствующий колбэк в очередь и вызывает его. По умолчанию executor однопоточный — колбэки выполняются по очереди, и если один из них надолго «зависнет» (например, тяжёлый расчёт), остальные ждут. Для параллельной обработки берут MultiThreadedExecutor.

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

  • Забыть rclpy.init(). Любая попытка создать узел до инициализации падает с ошибкой.
  • Тяжёлый расчёт прямо в колбэке. При однопоточном executor он блокирует все остальные колбэки узла.
  • Пытаться запустить код узла в браузере или без ROS. rclpy требует установленного рантайма ROS 2 — это не обычный Python-скрипт.

Итоги

  • rclpy (Python) и rclcpp (C++) — клиентские библиотеки поверх общего ядра rcl.
  • Узлы на разных языках свободно общаются через DDS.
  • Шаблон узла: init → создать узел → spin → shutdown.
  • spin крутит executor и вызывает ваши колбэки.
Проверьте себя
1. Какая клиентская библиотека ROS 2 предназначена для Python?
Arclcpp
Brclpy
Croscpp
Drospy
2. Что делает rclpy.spin(node)?
AУдаляет узел
BЗапускает цикл обработки событий и вызывает колбэки
CУстанавливает ROS
DСоздаёт новый топик
3. Почему узлы на Python и C++ могут общаться между собой?
AПотому что Python компилируется в C++
BПотому что связь идёт через DDS, а не через язык
CПотому что они всегда в одном процессе
DОни не могут общаться