ROS
Основная документация: https://wiki.ros.org.
ROS – это широко используемый фреймворк для создания сложных, распределенных робототехнических систем.
Установка
ROS уже установлен на образе для RPi.
Концепции
Ноды
Основная статья: https://wiki.ros.org/Nodes.
ROS-нода1 – это специальная программа (обычно написанная на Python или C++), которая взаимодействует с другими нодами посредством ROS-топиков и ROS-сервисов. Разделение сложных робототехнических систем на изолированные ноды дает определенные преимущества: понижается связанность кода, повышается переиспользуемость и надежность.
Очень многие робототехнические библиотеки и драйвера выполнены именно в виде ROS-нод.
Для того, чтобы превратить обычную программу в ROS-ноду, необходимо подключить к ней библиотеку rospy
(Python) или roscpp
(C++) и добавить инициализирующий код.
Пример ROS-ноды на языке Python:
import rospy
rospy.init_node('my_ros_node') # имя ROS-ноды
rospy.spin() # входим в бесконечный цикл...
Любая программа для автономного полета является ROS-нодой.
Топики
Основная статья: https://wiki.ros.org/Topics.
Топик – это именованная шина данных, по которой ноды обмениваются сообщениями. Любая нода может опубликовать сообщение в произвольный топик, а также подписаться на произвольный топик.
Для каждого созданного топика должен быть задан тип сообщений, которые по нему передаются. ROS включает в себя большое количество стандартных типов сообщений, покрывающих различные аспекты робототехники, но при необходимости возможно создание собственных типов сообщений. Примеры стандартных типов сообщений:
Тип сообщения | Описание |
---|---|
std_msgs/Int64 |
Целое число. |
std_msgs/Float64 |
Число с плавающей точкой (дробное) двойной точности. |
std_msgs/String |
Строка. |
geometry_msgs/PoseStamped |
Позиция и ориентация объекта с заданной системой координат и временной меткой (широко используется для передачи текущей позиции робота и его частей). |
geometry_msgs/TwistStamped |
Линейная и угловая скорость объекта с заданной системой координат и временной меткой. |
sensor_msgs/Image |
Изображение (см. статью о работе с камерой) |
Смотрите остальные стандартные типы сообщений в пакетах
common_msgs
,std_msgs
,geometry_msgs
,sensor_msgs
и других.
Пример публикации сообщения типа std_msgs/String
(строка) в топик /foo
на языке Python:
import rospy
from std_msgs.msg import String
rospy.init_node('my_ros_node')
foo_pub = rospy.Publisher('/foo', String, queue_size=1) # создаем Publisher
foo_pub.publish(data='Hello, world!') # публикуем сообщение
Пример подписки на топик /foo
:
import rospy
from std_msgs.msg import String
rospy.init_node('my_ros_node')
def foo_callback(msg):
print(msg.data)
# Подписываемся. При получении сообщения в топик /foo будет вызвана функция foo_callback.
rospy.Subscriber('/foo', String, foo_callback)
rospy.spin() # входим в бесконечный цикл, чтобы программа не завершила работу
Вы можете прочитать данные из топика однократно, используя функцию wait_for_message
:
msg = rospy.wait_for_message('/foo', String, timeout=3) # ждать сообщения в топике /foo в таймаутом 3 с
Также существует возможность работы с топиками с помощью утилиты rostopic
. Например, с помощью следующей команды можно просматривать сообщения, публикуемые в топик /mavros/state
:
rostopic echo /mavros/state
Команда rostopic info
позволяет узнать тип сообщений в топике, команда rostopic hz
— частоту публикуемых в топике сообщений.
Сервисы
Основная статья: https://wiki.ros.org/Services.
Сервис – это некоторый аналог функции, которая может быть вызвана из одной ноды, а обработана в другой. У сервиса есть имя, аналогичное имени топика, и 2 типа сообщений: тип запроса и тип ответа.
Таким образом, сервисы реализуют паттерн удаленного вызова процедур.
Пример вызова ROS-сервиса из языка Python:
import rospy
from drone.srv import GetTelemetry
rospy.init_node('my_ros_node')
# Создаем обертку над сервисом get_telemetry пакета drone с типом GetTelemetry:
get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry)
# Вызываем сервис и получаем телеметрию дрона:
telemetry = get_telemetry()
С сервисами можно также работать при помощи утилиты rosservice
. Так можно вызвать сервис /get_telemetry
из командной строки:
rosservice call /get_telemetry "{frame_id: ''}"
Больше примеров использования сервисов для автономных полетов можно посмотреть в документации ноды simple_offboard.
Имена
Основная статья: https://wiki.ros.org/Names.
Любой топик, сервис или параметр идентифицируется с помощью уникального имени. ROS-имя представляет собой иерархическую структуру с символом /
в качестве разделителя (сходно с именами в файловой системе).
Примеры ROS-имен:
/
(глобальное пространство имен)/foo
/stanford/robot/name
/wg/node1
Эти имена является глобальными (аналогично полному пути в файлу в файловой системе). На практике рекомендуется использование приватных или относительных имен.
Приватное имя
Каждая нода может использовать собственное приватное пространство имен (соответствующее имени ноды) для своих ресурсов. Например, нода aruco_detect
может публиковать такие топики:
/aruco_detect/markers
/aruco_detect/visualization
/aruco_detect/debug
Когда нода ссылается на свой приватный ресурс, вместо пространства имен (/aruco_detect/
) используется символ ~
, например:
~markers
~visualization
~debug
Таким образом, создание топика foo
в приватном пространство имен из Python будет выглядеть так:
private_foo_pub = rospy.Publisher('~foo', String, queue_size=1)
Относительное имя
Несколько нод также могут объединяться в общее пространство имен (например, при одновременной работе нескольких роботов). Для того, чтобы ссылаться на топики с учетом общего пространства имен, в названии ресурса опускается начальный символ /
.
Пример создание топика foo
с учетом общего пространства имен:
relative_foo_pub = rospy.Publisher('foo', String, queue_size=1)
В общем случае всегда рекомендуется использовать приватные или относительные имена ресурсов и никогда не использовать глобальные.
Работа на нескольких машинах
Основная статья: https://wiki.ros.org/ROS/Tutorials/MultipleMachines.
Преимуществом использования ROS является возможность распределения нод на несколько машин в сети. Например, ноду, осуществляющую распознавание образом на изображении можно запустить на более мощном компьютере; ноду, управляющую коптером можно запустить непосредственно на Raspberry Pi, подключенном к полетному контроллеру и т. д.
Дополнительные материалы
- Учебник по ROS от Voltbro - http://docs.voltbro.ru/starting-ros/.
- Другие книги по ROS - https://wiki.ros.org/Books.
1. Также встречается перевод "узел". ↩