Подписчик (Subscriber)
Last updated
Was this helpful?
Last updated
Was this helpful?
Подписчик - это инструмент, который принимает сигналы, передающиеся внутри системы управления.
Вне зависимости от того, какие это сигналы: данные лидара, одометрия, видео с камеры, положения сервоприводов или любые другие, их всегда передает, т.е. публикует Издатель, а принимает, т.е. подписывается на них Подписчик.
Например, лидар детектирует препятствия вокруг робота и при помощи Издателя передает данные об этом в ROS в топик /scan. Очевидно, что нам надо как-то получить эти данные для использования в наших программах. Так вот, инструмент, которым мы считываем эти данные из сообщений, это и есть Подписчик.
Чтобы продолжить то, что мы делали ранее (урок про Издателя), сигнал, который мы будем считывать сейчас это будет сообщение “Hello ROS” от, уже написанного нами Издателя.
Назовем нашу программу: subscriber.py и сохраним ее в папку ros-cource в корневой папке.
Итак начнем: Как мы помним у нас есть Издатель, который публикует строку “Hello ROS” в топик с именем “welcome_topic”.
Для того, чтобы использовать сущность Подписчика ROS в Python, нам надо подключить библиотеку rospy.
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import rospy
Теперь давайте определим тип и структуру данных, которые мы будем принимать при помощи нашего Подписчика. Тут все просто: имя топика и тип данных определяется Издателем, который публикует сообщения для нас.
Вспоминая нашего уже написанного Издателя, мы определим тип данных как строка, так как передаётся сообщение “Hello ROS” с типом данных String. Топик будет “welcome_topic”, потому что так мы написали в нашей прошлой программе.
from std_msgs.msg import String
Теперь создадим и зарегистрируем в ROS нашу ноду стандартным методом init_node():
rospy.init_node("subscriber_node")
Теперь давайте создадим объект Подписчик. В отличие от урока про Издателя при создании объекта Издатель, мы пользовались его методом publish
для публикации наших сообщений. У Подписчика мы не будем пользоваться его методами и поэтому, мы можем не передавать ссылку на экземпляр Подписчика ни в какую переменную:
rospy.Subscriber
Теперь, нам необходимо указать название топика из которого Подписчик будет получать данные и название структуры этих данных:
rospy.Subscriber("/welcome_topic", String, callback)
Третьим аргументом при инициализации Подписчика является имя функции обратного вызова. Разберём поподробнее, что такое функция обратного вызова для Подписчика.
В общем случае это функция, которая вызывается каждый раз, когда в топике на который подписан Подписчик появляются сообщения, то есть, каждый раз когда Издатель публикует сообщение, ROS оповещает об этом Подписчика и передает ему сообщение от Издателя с заполненной структурой данных. Объект Подписчик же в свою очередь принимает это сообщение, вызывает функцию обратного вызова внутри нашей программы, и передает в нее полученную структуру данных в качестве аргумента.
Давайте напишем функцию обратного вызова, которая будет выводить на экран всю переданную в нее в качестве аргумента структуру данных:
def callback(msg):
print(msg)
Функция принимает объект структуры данных в качестве аргумента и просто печатает его при помощи функции print()
.
Теперь давайте напишем основной цикл нашей программы.
Используем стандартный ROS цикл:
while not rospy.is_shutdown():
А в самом цикле используем метод библиотеки rospy - spin
. Сам метод ничего не делает, кроме того, что не даёт нашему Подписчику закрыться пока мы не выйдем из цикла:
while not rospy.is_shutdown():
rospy.spin()
Вот и все! Мы с вами написали программу Подписчика! Давайте сохраним её, запустим и посмотрим как она работает.
Запустим roscore
и оставим его запущенным в терминале.
Откроем новый терминал напишем python3 и полный путь до файла с нашей программой:
python3 ros_course/subscriber.py
Запустилось. Но ничего не происходит… Правильно, ведь публикация-то сообщений не идет. И наша программа начнет выводить данные на экран, только тогда когда мы запустим программу Издателя (publisher.py).
Давайте откроем еще один терминал и запустим нашего Издателя:
python3 ros_course/publisher.py
Наш Подписчик начал принимать сообщения от нашего Издателя! Всё работает так как надо!
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import rospy
from std_msgs.msg import String
rospy.init_node("subscriber_node")
def callback(msg):
print(msg)
rospy.Subscriber("/welcome_topic", String, callback)
while not rospy.is_shutdown():
rospy.spin()
В этом примере мы ничего не делаем с теми данными, которые нам поступают от Издателя, если не считать, того, что мы выводим их на экран. На следующем уроке разберем программу, которая принимает данные с робота