Подписчик (Subscriber)
Last updated
Last updated
Подписчик - это инструмент, который принимает сигналы, передающиеся внутри системы управления.
Вне зависимости от того, какие это сигналы: данные лидара, одометрия, видео с камеры, положения сервоприводов или любые другие, их всегда передает, т.е. публикует Издатель, а принимает, т.е. подписывается на них Подписчик.
Например, лидар детектирует препятствия вокруг робота и при помощи Издателя передает данные об этом в ROS в топик /scan. Очевидно, что нам надо как-то получить эти данные для использования в наших программах. Так вот, инструмент, которым мы считываем эти данные из сообщений, это и есть Подписчик.
Чтобы продолжить то, что мы делали ранее (урок про Издателя), сигнал, который мы будем считывать сейчас это будет сообщение “Hello ROS” от, уже написанного нами Издателя.
Назовем нашу программу: subscriber.py и сохраним ее в папку ros-cource в корневой папке.
Итак начнем: Как мы помним у нас есть Издатель, который публикует строку “Hello ROS” в топик с именем “welcome_topic”.
Для того, чтобы использовать сущность Подписчика ROS в Python, нам надо подключить библиотеку rospy.
Теперь давайте определим тип и структуру данных, которые мы будем принимать при помощи нашего Подписчика. Тут все просто: имя топика и тип данных определяется Издателем, который публикует сообщения для нас.
Вспоминая нашего уже написанного Издателя, мы определим тип данных как строка, так как передаётся сообщение “Hello ROS” с типом данных String. Топик будет “welcome_topic”, потому что так мы написали в нашей прошлой программе.
Теперь создадим и зарегистрируем в ROS нашу ноду стандартным методом init_node():
Теперь давайте создадим объект Подписчик. В отличие от урока про Издателя при создании объекта Издатель, мы пользовались его методом publish
для публикации наших сообщений. У Подписчика мы не будем пользоваться его методами и поэтому, мы можем не передавать ссылку на экземпляр Подписчика ни в какую переменную:
Теперь, нам необходимо указать название топика из которого Подписчик будет получать данные и название структуры этих данных:
Третьим аргументом при инициализации Подписчика является имя функции обратного вызова. Разберём поподробнее, что такое функция обратного вызова для Подписчика.
В общем случае это функция, которая вызывается каждый раз, когда в топике на который подписан Подписчик появляются сообщения, то есть, каждый раз когда Издатель публикует сообщение, ROS оповещает об этом Подписчика и передает ему сообщение от Издателя с заполненной структурой данных. Объект Подписчик же в свою очередь принимает это сообщение, вызывает функцию обратного вызова внутри нашей программы, и передает в нее полученную структуру данных в качестве аргумента.
Давайте напишем функцию обратного вызова, которая будет выводить на экран всю переданную в нее в качестве аргумента структуру данных:
Функция принимает объект структуры данных в качестве аргумента и просто печатает его при помощи функции print()
.
Небольшая ремарка. В связи с тем что программа в Python выполняется последовательно, мы должны определить нашу функцию обратного вызова до того, как укажем ее в Подписчике, поэтому необходимо расположить её перед вызовом Подписчика.
Теперь давайте напишем основной цикл нашей программы.
Используем стандартный ROS цикл:
А в самом цикле используем метод библиотеки rospy - spin
. Сам метод ничего не делает, кроме того, что не даёт нашему Подписчику закрыться пока мы не выйдем из цикла:
Вот и все! Мы с вами написали программу Подписчика! Давайте сохраним её, запустим и посмотрим как она работает.
Запустим roscore
и оставим его запущенным в терминале.
Откроем новый терминал напишем python3 и полный путь до файла с нашей программой:
Запустилось. Но ничего не происходит… Правильно, ведь публикация-то сообщений не идет. И наша программа начнет выводить данные на экран, только тогда когда мы запустим программу Издателя (publisher.py).
Давайте откроем еще один терминал и запустим нашего Издателя:
Наш Подписчик начал принимать сообщения от нашего Издателя! Всё работает так как надо!
В этом примере мы ничего не делаем с теми данными, которые нам поступают от Издателя, если не считать, того, что мы выводим их на экран. На следующем уроке разберем программу, которая принимает данные с робота