Подписка на сообщения
Ранее, для работы с топиками, мы только публиковали данные. В прошлом задании мы увидели, что есть программы, которые получают и обрабатывают эти данные (получают скорости и управляют моторами).
Немного теории. Как и в случае с Издателем (Publisher) - Подписчик(Subscriber) реализован в Python через класс Subscriber библиотеки rospy. Тот подписчик, который мы будем использовать в нашем примере имеет следующую структуру: rospy.Subscriber('cpu_temp', Float32, callback)
Его аргументы это:
- 'cpu_temp' - имя топика, на который он будет подписываться;
- Float32 - тип данных, который он будет ожидать из этого топика;
- callback - имя функции обратного вызова, которую он будет вызывать каждый раз когда в топик, на который он подписан, будут поступать данные в правильном формате.
Обратите внимание, что подписчик начнет вызывать функцию callback, сразу после того, как интерпретатор Python, дойдет до строки с объявлением Подписчика. Поэтому надо понимать, что вся логика обработки функции обратного вызова должна уже быть объявлена в вашей программе к моменту создания подписчика.
Подробнее, как и с Издателем, в официальной документации: http://docs.ros.org/en/lunar/api/rospy/html/rospy.topics.Subscriber-class.html
Мы рассматриваем, только часть аргументов передаваемых методу Subscriber. Остальные аргументы остаются для вашего самостоятельного изучения.
Давайте напишем программу которая умеет получать данные из топика, в терминологии ROS такая программа называется Подписчик (Subscriber). Создайте папку lesson4 и назовите файл temp_topic_subscriber.py
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import rospy
from std_msgs.msg import Float32
def callback(msg):
print (msg.data)
rospy.init_node('temp_subscriber')
sub = rospy.Subscriber('cpu_temp', Float32, callback)
rospy.loginfo("I am a subscriber")
rospy.spin()
Запустим:
python3 temp_topic_subscriber.py
[INFO] [1542121864.164811]: I am a subscriber
Мы увидим информационное сообщение, что скрипт запустился и ничего более, что логично - данные в подписчик не поступают.
Проверим работу подписчика через консольную утилиту rostopic. Откроем еще одно окно терминала и запустим команду публикующую, в наш только что созданный топик, число 55:
$ rostopic pub /cpu_temp std_msgs/Float32 55 -r10
Параметр -r10 означает, что топик публикуется с частотой 10Hz, если этот параметр не указать, публикация произойдет один раз.
В окне терминала где запущен наш Подписчик, мы увидим что начали выводиться значения "55" которые мы публикуем из терминала.
55.0
55.0
55.0
55.0
55.0
55.0
55.0
55.0
Это значит, что наша программа начала получать данные и выводить их в терминал.
На втором уроке, мы писали программу, которая публикует данные о температуре. Запустим Издателя из этого урока.
python3 base-ros/lesson2/temp_topic_publisher.py
В нашей программе Подписчике, мы увидим реальные данные, которые передает Издатель со значениями температуры процессора.
52.5999984741
52.5999984741
52.5999984741
52.5999984741
52.0999984741
Разберем нашу программу более детально.
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# Подключаем библиотеку для работы с ROS
import rospy
# Импортируем объект для работы с нужными нам сообщениями
from std_msgs.msg import Float32
# Простая функция "callback". Данная функция вызывается Подписчиком
# в момент когда в топике появились данные. В нашем примере
# выводит данные на экран
def callback(msg):
print (msg.data)
# Инициализируем ноду ROS
rospy.init_node('temp_subscriber')
# Создаем подписчика, в параметрах указываем
# Название топика, тип сообщения, имя функции которую мы будем вызывать
# при полученни сообщения
sub = rospy.Subscriber('cpu_temp', Float32, callback)
# Выводим информационное сообщение
rospy.loginfo("I am a subscriber")
# Запускаем метод spin, который не даст нашей ноде закрыться,
# пока работает наша программа
rospy.spin()
Обратите внимание, что хотя Подписчик и запускается сразу после его инициализации интерпретатором Python через rospy, однако функция callback вызывается только тогда, когда в топик на который подписан Подписчик поступают правильные данные.
Callback (англ. call — вызов, англ. back — обратный) или функция обратного вызова в программировании — передача исполняемого кода в качестве одного из параметров другого кода. Обратный вызов позволяет в функции исполнять код, который задаётся в аргументах при её вызове. Этот код может быть определён в других контекстах программного кода и быть недоступным для прямого вызова из этой функции. Некоторые алгоритмические задачи в качестве своих входных данных имеют не только числа или объекты, но и действия (алгоритмы), которые естественным образом задаются как обратные вызовы.
Пример создания простой программы Подписчика: https://youtu.be/Vh6C78DlOMY