Топик, Издатель (Publisher)
В ROS программы, отправляющие сообщения, принято называть Издатель (Publisher), а программы которые получают данные принято называть Подписчик (Subscriber). При этом в архитектуре ROS - Подписчик и Издатель могут быть как разные программы запущенные на одном компьютере, так и разные программы, запущенные на разных устройствах.
Немного теории. Мы будем писать наши программы на языке Python и для того, чтобы наши программы могли коммуницировать с ROS, нам необходимо подключить специальную библиотеку rospy, которая реализует основные функции связи с ROS для Python. В частности, для создания Издателя(Publisher) мы будем использовать метод библиотеки rospy, который так и называется Publisher. Как вы могли узнать из курса Python, для вызова методов библиотеки надо пользоваться следующей конструкцией: <имя библиотеки>.<имя метода>(аргументы метода). В нашем случае это будет выглядеть так: rospy.Publisher('/cpu_temp', Float32, queue_size=1). Где аргументы это: '/cpu_temp' - имя топика, в который мы хотим публиковать, Float32 - тип данных который мы хотим публиковать, queue_size=1 - количество одновременных сообщений которое можно публиковать в этот топик.
Если вы хотите более подробно узнать о возможностях и методах библиотеки rospy или любого из ее классов, смотрите официальную документацию:
Она клевая и понятная, но на английском.
Ранее мы обсудили некоторую условность, что все данные передаются через сообщения. Давайте создадим программу Издатель, которая будет передавать данные о температуре процессора нашего робота.
Перед началом работы создайте на роботе папку base-ros,в которой будете сохранять поурочно программы, которые будете изучать.

Вот пример кода, который мы будем использовать далее:
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import rospy
from std_msgs.msg import Float32
rospy.init_node('temp_publisher')
pub = rospy.Publisher('/cpu_temp', Float32, queue_size=1)
rate = rospy.Rate(1)
temp = Float32()
def getCPUTemp():
data = open('/sys/class/thermal/thermal_zone0/temp', 'r').read()
return round(float(int(data)/1000.0),1)
while not rospy.is_shutdown():
temp.data = getCPUTemp()
pub.publish(temp)
rate.sleep()
Пока не особо вдаваясь в подробности как именно работает код, скопируем его в Visual Studio Code и сохраним его на вашем роботе (именно на нем мы хотим считать температуру) в файл/home/pi/base-ros/lesson2/temp_topic_publisher.py
Значение температуры Raspberry Pi "публикует" в "специальный" файл:/sys/class/thermal/thermal_zone0/temp Для того, чтобы получить это значение мы должны прочитать его из этого файла стандартными средствами Python.
data = open('/sys/class/thermal/thermal_zone0/temp', 'r').read()
Значение температуры в данном файле записано в миллиградусах, поэтому, чтобы получить более привычные нам градусы Цельсия, разделим это значение на 1000.
Запустим .py файл через ssh
ssh pi@turtlebro37.local
cd base-ros/lesson2
python3 temp_topic_publisher.py
Запустили, и на первый взгляд ничего не произошло (в том числе вывода ошибки, что уже хорошо). Откроем новое окно (Ctrl-Alt-T) терминала, снова подключимся к роботу и попробуем разобраться что изменилось в системе.
Мы собирались передавать данные о температуре, в ROS есть специальный механизм для такого вида взаимодействия. Он называется "топик". В данной модели взаимодействия есть Издатель - скрипт, который публикует данные в топик. И есть Подписчики - скрипты, которые могут получать данные из этого топика.
Чтобы данные можно было различать, у топиков есть уникальные имена. Давайте выполним команду rostopic list которая выводит список всех существующих топиков (покажет имена):
rostopic list
/bat
/cmd_vel
/diagnostics
/imu
/joint_states
/cpu_temp
/odom
/rosout
/rosout_agg
/scan
/tf
/tf_static
Мы увидели список топиков. В этом списке есть топик /cpu_temp, посмотрим что это такое:
rostopic info /cpu_temp
Type: std_msgs/Float32
Publishers:
* /temp_publisher (http://192.168.1.73:45151/)
Subscribers: None
Из описания нам видно, что в этом топике есть данные типа std_msgs/Float32 а информацию об этом публикует Издатель (Publisher) с именем /temp_publisher, это и есть "результат" работы нашего скрипта.
И самое интересное -- давайте посмотрим какая температура CPU нашего робота.
Выполним команду rostopic echo <имя топика>
rostopic echo /cpu_temp
data: 52.5999984741
---
data: 52.5999984741
---
data: 52.0999984741
---
data: 52.0999984741
---
data: 52.0999984741
---
data: 52.5999984741
Раз в секунду мы получаем новую строчку с данными о температуре, это приблизительно то чего мы ожидали.
Подведем краткий итог. Мы написали скрипт на python, который запускается на роботе и публикует данные в топик с выбранным именем. При помощи утилиты rostopic , мы смогли его найти в списке и при помощи утилитыechoсмогли "посмотреть" полученную информацию.
Давайте немного вернемся назад, и более внимательно разберем наш python скрипт. Сейчас, зная что он делает, это будет не сложно.
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# Импорт python библиотеки ROS
import rospy
# Импорт типа сообщения ROS Float32 из пакета std_msgs
from std_msgs.msg import Float32
# Инициализация ноды с именем temp_publisher
rospy.init_node('temp_publisher')
# Создадим обьект Publisher, из библиотеки rospy, который будет
# публиковать в топик /cpu_temp данные формата Float32
pub = rospy.Publisher('/cpu_temp', Float32, queue_size=1)
# Установить частоту публикации данных
rate = rospy.Rate(1)
# Инициализировать пустой обьект Float32
temp = Float32()
# Функция получения данных с датчика температуры
# платы RaspberryPi. Функция возвращает температуру в градусах
def getCPUTemp():
data = open('/sys/class/thermal/thermal_zone0/temp', 'r').read()
return round(float(int(data)/1000.0),1)
# Рабочий цикл всей программы. Выполнять цикл пока программу
# пока не остановили
while not rospy.is_shutdown():
# Получить данные температуры, и присвоить ее переменной temp.data
temp.data = getCPUTemp()
# Опубликовать сообщение temp
pub.publish(temp)
# Ожидать, пока не пройдет время необходимое для работы с
# выбранной частотой.
rate.sleep()
Итак мы создали и запустили нашу первую программу Издатель для ROS
Про базовые утилиты ROS вы можете узнать здесь: https://youtu.be/v0RIdmc--UE
Пример создания простой программы Издателя: https://youtu.be/t17WIlZJDuo