Издатель (Publisher)
Last updated
Last updated
Издатель - это инструмент, который передает сигналы внутри системы управления.
В зависимости от того что это за сигналы, в терминах теории управления мы можем говорить о входящих или исходящих сигналах, но в ROS инструментом, который передает эти сигналы всегда является Издатель.
Cигналы в ROS - это сообщения, несущие структуру данных, а сами сигналы возникают в какой-то определенной точке системы - топике.
Так, например, контроллер робота подсчитывает обороты двигателей, чтобы сказать какое расстояние прошел робот и при помощи Издателя передает данные об этом в ROS. Или наша программа управления - регулятор - решает повернуть робота на определенный угол и при помощи Издателя передает это управляющее воздействие в ROS.
Сейчас мы не будем разбирать Издателя, делающий что-то связанное с реальным роботом. Для простоты мы смоделируем элементарный пример с которого начинаются все языки программирования. А именно напишем программу выводящую на экран “Hello ROS”.
Писать мы будем на языке Python с использованием IDE Visual Studio Code, но вы можете использовать любую другую среду разработки под Python (PyCharm, Notepad+ и прочее).
Сформулируем задачу более определенно: Мы будем писать Издатель, который публикует строку “Hello ROS” в топик с именем: “welcome_topic”.
Назовем нашу программу: publisher.py и сохраним ее в папку ros-cource в корневой папке.
Все эти ROS-сущности: топик, Издатель, тип данных - строка, уже описаны в библиотеке по работе с ROS для Python. Она называется rospy и по умолчанию ставится вместе с установкой ROS. Для того, чтобы просто использовать эти сущности в нашей программе, нам надо подключить эту библиотеку:
Теперь давайте определим тип и структуру данных, которые мы будем передавать при помощи Издателя. Раз мы хотим напечатать строку “Hello ROS”, то тип данных с очевидностью будет строка. Для того чтобы бы мы могли использовать структуру данных ROS в Python, ее надо сначала импортировать. Давайте сделаем это:
Как вы видите есть отличие в написании. Строка в Python называется str, строка в ROS называется String с большой буквы. Если сейчас вам это кажется непривычным, не волнуйтесь - к этому дуализму структур данных вы довольно быстро привыкните.
Теперь давайте создадим и зарегистрируем в ROS нашу ноду. Как вы помните ноды это и есть отображение в ROS наших программ. Для создания ноды в rospy есть стандартный метод init_node(). Как это принято в Python, доступ к методам и объектам внутри библиотеки, происходит по их полному имени, через точку после названия библиотеки. Назовем нашу ноду welcome_node вот так:
Теперь давайте создадим объект Издатель. Для простоты назовем экземпляр этого объекта pub
Теперь, нам необходимо указать название топика в который издатель будет публиковать данные и название структуры этих данных. Это welcome_topic и String:
Это основные параметры при инициализации Издателя и уже в таком виде он будет запускаться и работать, правда с предупреждением, которое мы рассмотрим позже.
Теперь нам надо создать объект нашей структуры данных String и заполнить ее значением “Hello robot”:
Тут мы создаем новый объект класса String и присваиваем значение “Hello robot” переменной data этого объекта.
Теперь давайте напишем основной цикл нашей программы.
Для программ под ROS рекомендуется такая структура основного цикла:
Такой вид цикла позволит нам корректно выйти из нашей программы по нажатию Ctrl+C
В самом цикле, мы будем публиковать значение нашей структуры данных s
при помощи созданного нами Издателя pub
:
publish
- это метод класса Издатель и он просто публикует структуру данных которую вы передаете ему в качестве аргумента, в соответствии с теми параметрами которые мы указали при инициализации, т.е. структура будет String, а публиковать ее надо в топик "welcome_topic"
Вот и все! Мы написали первую программу для ROS! Давайте сохраним ее, запустим и посмотрим как она работает.
Запустим roscore и оставим его запущенным в окне терминала. Откроем новый терминал и напишем python3 и полный путь до файла с нашей программой:
Запустилось, но выдает предупреждение о котором мы предупреждали.
Мы поправим его позже, а пока давайте посмотрим что изменилось в системе.
Для тестирования нашей программы мы будем использовать уже известные нам сервисные утилиты - rostopic и rosnode.
Давайте посмотрим какие ноды и топики есть сейчас в системе. Для этого в новом окне терминала вызовем:
Мы видим две новые записи, это записи /welcome_node и /welcome_topic
/welcome_node - это та самая нода, которую мы создали в нашей программе;
/welcome_topic - это топик, в который мы публикуем наше значение.
Т.е. мы запустили нашу программу и она инициализировала в системе свою ноду и зарегистрировала топик. А как проверить, что программа работает так как мы хотим, т.е. публикует Hello ROS в топик /welcome_topic ?
Для этого снова воспользуемся утилитой rostopic и напишем:
Отлично ! Мы видим череду сообщений "Hello ROS", а это значит, что все работает так как надо!
Теперь давайте быстро поправим нашу программу, чтобы при ее запуске не было предупреждений, а так же изменим частоту публикации нашего сообщения в топик.
Допишем в инициализацию Издателя параметр размера очереди сообщений queue_size и поставим его равным 10.
Подробнее про этот и другие дополнительные параметры инициализации Издателя и Подписчика вы можете почитать здесь:
http://wiki.ros.org/rospy/Overview/Publishers%20and%20Subscribers
И вишенка на торте нашей программы - поставим частоту публикации сообщения “Hello ROS”
В ROS есть несколько способов обеспечить требуемую частоту публикации, и сейчас мы воспользуемся самым простым, но не самым точным из всех - методом sleep() библиотеки rospy.
Этот метод приостанавливает работу программы на то количество секунд, которое мы передаем ему в качестве аргумента. Давайте напишем rospy.sleep(1) т.е. мы хотим, чтобы сразу после публикации сообщения наша программа "засыпала" на 1 секунду.
Теперь давайте все сохраним и снова запустим нашу программу.
Как вы видите все обязательные параметры указаны верно и никаких предупреждений программа не выдает.
Для того, чтобы убедиться, что публикация в топик /welcome_topic действительно идёт один раз в секунду воспользуемся новым параметром утилиты rostopic: