ROS на практике

ros_practice

Давайте на практике разберем архитектуру ROS, изучим файловую систему ROS, рассмотрим некоторые концепции, инструменты и примеры взаимодействия с узлами, темами и сервисами ROS, а также посмотрим как все это работает в связке.

Я уже упоминал, что в архитектуре ROS можно выделить два основных концептуальных уровня: уровень файловой системы и уровень вычислительного графа.

Навигация по файловой системе ROS

В ROS есть несколько инструментов командной строки для навигации по файловой системе.

Для получения информации и перехода к пакетам и стекам используются инструменты rospac, rosstack, roscd и rosls.

rospack и rosstack используются для получения информации о пакетах и стеках, путях, зависимостях и т.д.

Например, если вы хотите найти путь к пакету turtlesim, необходимо написать в командной строке:

Вы получите в ответ следующее:

То же самое происходит со стеками, установленными в системе. Пример:

Для получения списка файлов, внутри пакета или стека, используйте

После этого вы увидите следующее:

Если вы хотите перейти внутрь папки, то вам необходимо использовать roscd следующим образом:

В ответ вы получите следующий новый путь:

 

Создание собственного рабочего пространства

Перед тем как что-либо делать, необходимо создать собственное рабочее пространство. В этом рабочем пространстве у вас будет весь код, который вы создадите.

Чтобы посмотреть, какое рабочее пространство использует ROS, необходимо выполнить следующую команду:

Вы увидите что-то типа:

Папка, которую мы собираемся создать находится в /dev/roboschool/. Для добавления этой папки, используем следующие строки:

Как только папка будет создана, нам необходимо добавить этот новый путь в ROS_PACKAGE_PATH. Чтобы это сделать, нам нужно только добавить новую строку в конец файла /baschrc:

Проверяем новое значение переменной окружения:

Теперь у нас есть новая папка, созданная и сконфигурированная для работы с ROS.

Создание пакета ROS

Как я уже говорил ранее, вы можете создать пакет вручную. Но для того, чтобы избежать скучной работы, мы используем инструмент командной строки roscreate-pkg.

Мы создадим новый пакет в подготовленной ранее папке, используя следующие строки:

Формат этой команды включает имя пакета и зависимости, которые используются этим пакетом. В нашем случае, это std_msgs, rospy и roscpp. Это показано в следующей командной строке:

Зависимости включают:

  • std_msgs — содержит общие типы сообщений, представленные примитивными типами данных и другими базовыми конструкциями сообщений, такими как многомерные массивы.
  • rospy — это клиентская библиотека Python для ROS
  • rospy — это C++ реализация ROS. Она обеспечивает клиентскую библиотеку, подключаемую программистами на C++ для быстроко интерфейса с темами, сервисами и параметрами ROS.

Если все сделано правильно, вы увидите на экране что-то типа этого:

создание пакета ROS

Как мы говорили ранее, вы можете использовать команды rospack, roscd и rosls для получения информации о новом пакете:

  • rospack find architect_tutorials — эта команда помогает нам найти путь
  • rospack depends architect_tutorials — эта команда позволяет посмотреть зависимости
  • rosls architect_tutorials — команда позволяет посмотреть содержимое
  • roscd architect_tutorials — меняет текущий путь

 

Компиляция пакета ROS

Как только ваш пакет создан, необходимо выполнить компиляцию пакета.

После выполнения операции, вы увидите что-то вроде:

Компиляция пакета ROS

Если не произойдет каких-то ошибок, пакет будет откомпилирован.

 

Работаем с узлами ROS

Узлы являются исполняемыми программами, и эти исполняемые файлы находятся в директории имя_пакета/bin. Чтобы попрактиковаться и изучить работу с узлами, мы используем пакет под названием turtlesim.

Перед тем, как начать работать, необходимо выполнить:

Результат выглядит примерно так:

Запуск ROS

Установим простенький симулятор если он не был установлен заранее (если при установке ROS вы выбрали вариант в котором устанавливаются все модули и пакеты, то этот шаг можно пропустить):

Для получения информации об узлах существует инструмент rosnode. Чтобы посмотреть, какие у этой команды есть параметры, открываем новое окно Терминала и выполняем в нем команду:

Вы увидите список возможных параметров, как показано ниже:

Параметры rosnode

Если вам требуется более подробное описание, как использовать эти параметры, используйте следующий формат:

Теперь, когда roscore запущен, мы собираемся получить информацию о запущенных узлах:

Вы увидите, что выполняется только узел /rosout. Это нормально, потому что этот узел выполняется вместе с roscore.

Мы можем получить информацию об узле, используя различные параметры. Попробуйте использовать следующие команды для получения дополнительной информации:

Запустим новый узел, используя rosrun:

Должно открыться новое окно с маленькой черепашкой в центре.

Запуск turtlesim

Если теперь посмотреть на список узлов, то мы увидим в нем узел с именем /turtlesim.

Информацию об узле можно посмотреть, используя rosnode info имя_узла. Вы можете увидеть большое количество информации, которую можно использовать для отладки ваших программ:

Здесь мы можем увидеть публикации (тем), описания (тем) и сервисы (srv), которые есть у узла, а также уникальные имена каждого.

Теперь давайте посмотрим, как взаимодействовать с узлами, используя темы и сервисы.

 

Взаимодействие с темами

Для взаимодействия и получения информации о темах используется инструмент rostopic, имеющий следующие параметры:

  • rostopic bw — Отображает ширину полосы данных, используемую темой
  • rostopic echo — Выводит сообщения на экран
  • rostopic find — Ищет темы по их типу
  • rostopic hz — Отображает скорость публикации тем
  • rostopic info — Выводит информацию об активных темах
  • rostopic list — Список активных тем
  • rostopic pub — Публикует данные в тему
  • rostopic type — Выводит тип темы

Если вы хотите посмотреть больше информаии об этих параметрах, используйте -h:

Используя параметр pub, мы можем публиковать темы, на которые может подписаться любой узел. Нам нужно лишь опубликовать тему с корректным именем.

Используем узел, который необходим для управления. Запустим в новом окне Терминала:

Мы можем двигать черепашку, используя клавиши со стрелками.

Управлените черепашкой в ROS

Как черепашка движется во время выполнения turtle_teleop_key?

Если вы хотите увидеть информацию об узлах /teleop_turtle и /turtlesim, мы можем посмотреть на следующий код, который находится в теме, под названием * /turtle1/ cmd_vel [geometry_msgs/Twist] в разделе Publications первого узла. В разделе Subscriptions второго узла есть * /turtle1/cmd_vel [geometry_msgs/Twist]:

Это означает, что первый узел публикует тему, на которую может подписаться второй узел.

turtlesim_node и узел turtle_teleop обмениваются информацией посредством тем ROS. turtle_teleop_key публикует клавиши перемещения в теме, в то время как turtlesim подписан на ту же самую тему для получения клавиш перемещения. Можно использовать rqt_graph, который показывает выполняющиеся в настоящий момент узлы и темы.

rqt_graph создает динамический граф того, что происходит в системе. rqt_graph является частью пакета rqt. Если rqt_graph еще не установлен в системе, выполните:

В новом окне Теринала выполним следующую команду:

У вас должно появиться похожее окно:

Окно rqt_graph

Если переместить указатель мыши на /turtle1/cmd_vel, то это выделит узлы ROS (здесь — синим и зеленым цветом) и темы (здесь — красным цветом). Как вы можете видеть, /teleop_turtle обменивается информацией с /turtlesim, используя тему /turtle1/cmd_vel.

Узлы rqt_graph

Используя параметр echo, мы можем посмотреть информацию, отправленную узлом. Выполните следующую команду и используйте клавиши со стрелками, чтобы посмотреть что за данные были отправлены:

Вы увидите что-то похожее на следующее:

Вновь вернемся с rqt_graph. В левом верхнем углу нажмите кнопку Обновить для отображения нового узла.

Новый узел rqt_graph

Как видно, показанный здесь красным rostopic echo, также теперь подписан на тему turtle1/cmd_vel.

Вы можете посмотреть список тем, на которые подписаны и которые опубликованы, используя следующую строку кода:

Посмотреть тип сообщения, отправленного темой, можно используя следующую команду:

Если вам необходимо посмотреть поля сообщения, выполните:

Это полезные инструменты, потому что, используя эту информацию, мы можем публиковать темы, используя команду rostopic pub [topic] [msg_type] [args]

Вы увидите черепашку, создающую кривую.

Результат публикации темы

Эта команда отправляет единственное сообщение в turtlesim, в котором содержится информация о том, что необходимо двигаться с линейной скоростью равной 3.0 и угловой скоростью равной 2.0.

Разберем эту команду по частям:

  • rostopic pub — публикуем сообщение в данной теме
  • -1 — публиковать только одно сообщение, затем выйти
  • /turtle1/cmd_vel — имя темы, в которую публиковать
  • geometry_msgs/Twist — тип сообщения, который использовался при публи- кации темы
  • — — — двойное тире сообщает анализатору синтаксиса, что ни один из следующих аргументов не является параметром. Это необходимо в тех случаях, когда в аргумент входит дефис, например в отрицательных числах.
  • '[3.0, 0.0, 0.0]' '[0.0, 0.0, 2]' — сообщение geometry_msgs/Twist имеет два вектора: linear и angular, каждый из которых состоит из трех числовых элементов c плавающей точкой. В нашем случае, '[3.0, 0.0, 0.0]' становится линейным значением с x=3, y=0, z=0 и '[0.0, 0.0, 2]' является угловым значением с x=0, y=0, z=2. Эти аргументы имеют YAML- синтаксис.

 

Использование сервисов

Сервисы являются еще одним способом, посредством которого узлы могут обмениваться информацией друг с другом. Сервисы позволяют узлам отправлять запрос и получать ответ.

Для взаимодействия с сервисами используется инструмент rosservice. Параметры для этой команды:

  • rosservice args /service — Отображает аргументы сервиса
  • rosservice call /service — Вызывает сервис с представленными аргументами
  • rosservice find msg-type — Ищет сервисы по их типу
  • rosservice info /service — Выводит информацию о сервисе
  • rosservice list — Список активных сервисов
  • rosservice type /service — Отображает тип сервиса
  • rosservice uri /service — Выводит ROSPRC URI сервиса

Для получения списка доступных сервисов для узла turtlesim, используется следующий код. Если он не заработает, выполните roscore и запустите узел turtlesim.

Вы увидите следующее:

Рабочий стол при этом выглядит примерно таким образом:

Внешний вид рабочего стола при работе ROS

Для того, чтобы посмотреть тип любого сервиса, например, сервиса /clear

Вы увидите:

Для вызова сервиса используйте rosservice call [service] [args]. Если вы хотите запустить сервис /clear:

В окне turtlesim вы увидите, что линии, созданные движением черепашки будут удалены.

Теперь попробуйем другой сервис, например, сервис /spawn. Этот сервис создаст другую черепашку в другом месте, с другой пространственной ориентацией.

Увидим следующее:

Используя эти поля, мы знаем как запустить сервис. Нам необходимы координаты x и y, ориентация theta и имя новой черепашки:

Увидим следующий результат:

Создание новой черепашки в ROS

Использование сервера параметров

Сервер параметров используется для хранения данных, доступных любым узлам. В ROS имеется инструмент для управления сервером параметров под названием rosparam. Параметры:

  • rosparam set parameter value — устанавливает параметр
  • rosparam get parameter — получает параметр
  • rosparam load file — загружает параметры из файла
  • rosparam dump file — выгружает параметры в файл
  • rosparam delete parameter — удаляет параметр
  • rosparam list — список имен параметров

Например, мы можем посмотреть параметры на сервере, которые используются всеми узлами:

На выходе получим:

Параметры background принадлежат узлу turtlesim. Эти параметры изменяют цвет окон, который изначально голубой. Если вы хотите считать значение, используйте параметр get:

Для установки нового значения, используйте параметр set:

Для того, чтобы изменный параметр начал действовать, необходимо вызвать сервис clear:

Если нам нужно посмотреть содержимое всего сервера параметров, то для этого используется команда rosparam get /:

Другим важным свойством rosparam является параметр dump. Используя этот параметр, мы можем загружать или сохранять содержимое сервера параметров.

Для сохранения сервера параметров используйте rosparam dump [file_name] [пространство_имен]:

Для загрузки файла с новыми данными на сервер параметров используйте rosparam load [file_ name] [пространство_имен]:

Пример: загрузим сохраненный сервер параметров в новое пространство имен, например copy:

 

Создание узлов

Теперь мы создадим два узла: один для публикации некоторых данных, другой для их получения. Это основной способ взаимодействия между двумя узлами.

Создадим файл example1_a.cpp, который будет посылать данные по имени узла и файл example1_b.cpp, который будет показывать данные в оболочке.

Скопируйте следующий код в файл example1_a.cpp:

Несколько пояснений к коду. В заголовке подключаются библиотеки ros/ros.h, std_msgs/String.h и sstream. Здесь ros/ros.h включает все необходимые файлы для использования узла с ROS и std_msgs/String.h включает заголовок, который обозначает тип сообщения, которое мы собираемся использовать:

Инициализируем узел и присваиваем ему имя, которое должно быть уникальным:

Следом идет обработчик нашего процесса:

Устанавливаем издателя и сообщаем мастеру имя и тип темы. Имя message и второй параметр является размером буфера. Если тема быстро публикует данные, буфер будет содержать 1000 сообщений:

Установим частоту отправки данных, в этом случае, равную 10 Гц:

Библиотека ros::ok () останавливает узел, если он принимает нажатие клавиш Ctrl + C или если ROS останавливает все узлы:

Далее создается переменная для сообщения с корректным типом отправляемых данных:

Публикация сообщения:

Далее, у нас есть подписчик, где ROS обновляет и читает все темы:

Необходимое время для паузы, чтобы получить частоту 10 Гц:

Скопируйте следующий код в файл example_b.cpp:

Некоторые пояснения по поводу представленного кода. Подключаем заголовки и тип сообщения для использования в теме:

Эта функция вызывается каждый раз, когда узел получает сообщение. Это то место, где мы делаем что-то с данными. В этом случае, мы показываем их в оболочке:

Создаем подписчика и «слушаем» тему с именем message. Буфер будет 1000 и функция-обработчик сообщения будет messageCallback:

Библиотека ros::spin () является циклом, где узел начинает читать тему и затем приходит сообщение, называемое messageCallback. Когда пользователь нажимает Ctrl + C, узел выходит из цикла и цикл завершается:

 

Компиляция узла

Так как мы используем пакет architect_tutorials, нам нужно отредактировать файл CMakeLists.txt. Для этого вы можете использовать текстовый редактор или использовать инструмент rosed. Он открывает файл в редакторе Vim:

В конец файла копируем следующие строки кода:

Эти строки создадут два исполняемых файла в папке /bin.

Теперь для построения пакета и компиляции всех узлов используем инструмент rosmake:

Если ROS не запущена на вашем компьютере, используйте:

Вы можете проверить запущена ли ROS, используя команду rosnode list:

Теперь запустим оба узла в различных оболочках:

Если вы проверите оболочку, где запущен узел example1_b, вы увидите что-то типа:

Все что происходит, проиллюстрировано ниже на рисунке. Узел example_1 публикует тему message и узел example_2 подписан на тему.

Компиляция узла ROS

Вы можете использовать rosnode и rostopic для отладки и контроля за тем, что делает узел.

Попробуйте следующие команды:

 

Создание файлов msg и srv

msg и srv являются файлами, содержащие определения типов передаваемых данных и сами данные. ROS использует эти файлы для создания необходимого кода для нас.

В примере из предыдущего раздела «Компиляция узла» мы создали два узла стандартного типа mesaage. Теперь мы создадим пользовательские сообщения при помощи инструментов, имеющихся в ROS.

Во-первых, создадим новую папку msg в нашем пакете architect_tutorials и создадим новый файл architect_msg1.msg, добавив в него следующие строки:

Теперь отредактируем CMakeLists.txt, удалим # из строки # rosbuild_genmsg (), и откомпилируем пакет, используя rosmake:

Для проверки все ли нормально, можно использовать команду rosmsg:

Если вы увидите то же содержимое что и в файле architect_msg1.msg, то все нормально.

Создадим файл srv. Для этого создадим новую папку с именем srv в папке architect_tutorials и создадим новый файл architect_srv1.srv, добавив следующие строки:

Отредактируем CMakeList.txt и удалим # из строки # rosbuild_gensrv () и откомпилируем пакет, используя rosmake architect_tutorials.

Для проверки все ли нормально, используем инструмент rossrv:

Если вы увидите то же содержимое, что и в файле architect_srv1.srv, то все нормально.

 

Использование новых файлов srv и msg

Теперь разберем как создать сервис и как использовать его в ROS. Наш сервис будет вычислять сумму трех чисел. Нам нужно два узла: клиент и сервер.

В пакете architect_tutorials создадим два новых узла с именами example2_a.cpp и example2_b.cpp. Файлы необходимо поместить в папку src.

В файл example2_a.cpp добавляем следующий код:

Подключаем необходимые заголовки и созданный нами файл srv:

Следующая функция добавляет три переменные и отправляет результат в другой узел:

Далее создается сервис и оповещается ROS:

В файл example2_b.cpp добавляем код:

Создаем клиента для сервиса с именем add_3_ints:

Здесь мы создаем экземпляр нашего файла srv и заполняем все значения для отправки. Сообщением имеет три поля:

Этими строками кода вызывается сервис и отправляются данные. Если вызов прошел успешно, call () вернет true, если же нет — call () вернет false:

Для компиляции нового в файл CMakeList.txt добавим следующие строки:

Выполняем команду:

Для запуска узлов выполняем в двух оболочках следующие строки команд:

После этого, вы должны увидеть следущее:

Теперь создадим узлы, используя наш пользовательский файл msg. В качестве примера опять же берем example1_a.cpp, но уже с новым сообщением architect_msg1.msg.

Следующий фрагмент кода представляет содержимое файла example3_a.cpp:

Ниже приведено содержимое файла example3_b.cpp:

Если мы запустим оба узла сейчас, то увидим что-то похожее:

 

Как вы оцениваете эту публикацию? 1 звезда2 звезды3 звезды4 звезды5 звезд (6 голосов, средняя оценка: 5.00 из 5)
Loading ... Loading ...

Вы можете пропустить чтение записи и оставить комментарий. Размещение ссылок запрещено.

5 комментариев к записи “ROS на практике”

  1. tom пишет:

    Вы пишите

    >Несколько пояснений к коду. В заголовке подключаются библиотеки ros/ros.h, std_msgs/String.h и sstream.

    Но у вас в коде нет sstream, только пустой include на 3й строчке

    поэтому ошибка при компилировании получается, надо поправить на

    • tom пишет:

      Подобные ошибки еще в example2_a.cpp

      chapter2_srv1.h стоит вместо architect_srv1.h соответственно этот кусок кода из примера

      неверный и надо заменить на

      Кстати, компилятор ругается на разрыв из 2х строк в bool add, который надо не забыть убрать после копирования.

      и в example2_b.cpp

      3я строчка пустая, ее вообще надо убрать

    • Спасибо большое, ошибки исправил.

  2. tom пишет:

    Лично у меня все получилось, но были следующие проблемы

    1. Я использовал

    вместо вашего

    который у меня лично не работал

    2. Каждый раз, открывая новый терминал приходилось добавлять

    Хотелось бы настроить так, чтобы не вводить их постоянно.

    3. черепаха двигалась только когда окно терминала с выполненной командой

    было поверх остальных окон. Наверное, это тоже как-то можно исправить.

    еще у вас 2 раза стоит rospy вместо rospy и roscpp

    rospy — это клиентская библиотека Python для ROS

    rospy — это C++ реализация ROS. Она обеспечивает клиентскую библиотеку, подключаемую программистами на C++ для быстроко интерфейса с темами, сервисами и параметрами ROS.

    • В окне с командой rosrun tuttlesim turtle_teleop_key работает приложение, которое считывает нажатые клавиши, поэтому оно и должно быть активным — это правильно (в фоновом режиме клавиши не считываются).

Оставить комментарий