Библиотеки клиента: 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, а не через язык.
| Библиотека | Язык | Когда выбирают |
| rclpy | Python | Прототипы, логика высокого уровня, обучение |
| rclcpp | C++ | Производительность, реальное время, драйверы |
| rcl | C | Ядро, на нём построены остальные |
Скелет узла на 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 и вызывает ваши колбэки.