Белый Анатолий

Введение в программирование в Операционной Системе для Роботов (ROS)

Введение в программирование в Операционной Системе для Роботов (ROS)

• Мы рассмотрим несколько примеров узлов C ++, обменивающихся данными в рамках ROS

• Повторим понятия узлов, тем и сообщений ROS.

• Более детально рассмотрим структуру хранилища rosbuild, а также создание и построение простого программного пакета, используя rosmak.

 

Общие сведения – краткое описание ROS

• ROS это пакет промежуточного программного обеспечения для программирования роботов, который содержит равноправные узлы.
• Мы используем ROS, потому что он позволяет облегчить абстракцию аппаратных средств и повторное использование кода.
• В ROS, все основные функции разбиваются на ряд блоков, которые обмениваются данными с помощью сообщений.
• Каждый блок называется узлом и, как правило, работает как отдельный процесс.
• Установление связи между узлами осуществляется ROS Мастером.

 

работа ROS

ROS Узлы
Анод представляет собой процесс, который выполняет некоторые вычисления. Обычно мы стараемся разделить всю функциональность программного обеспечения на различные модули – каждый работает при помощи одного или нескольких узлов. Узлы объединены в график и передают друг другу информацию с помощью разделов потоковой передачи данных, услуги «Удаленный вызов процедур» (Remote Procedure Call,RPC), а также сервера параметров. Эти узлы предназначены для работы в мелкоструктурном масштабе; система управления роботом обычно включает множество узлов.

 

ROS разделы
Разделами называют шины, через которые узлы обмениваются сообщениями. Разделы имеют анонимную семантику публикаций/подписок. Это значит, что для узла безразлично, какой узел опубликовал данные, которые он получает, или какой узел подписан на данные, публикуемые им. По одному разделу может быть несколько издателей и подписчиков. Нетрудно иметь несколько подписчиков. Каждый раздел очень типизирован ROS сообщениями, которые он передает. Передача выполняется с помощью TCP или UDP.

 

ROS сообщения
Узлы общаются друг с другом с помощью публикации сообщения к определенному разделу.
Сообщение – простая структура данных, содержащая введенные поля. Вы можете взглянуть на некоторые основные типы здесь:
std_msgs/Bool
std_msgs/lnt32
std_msgs/String
std_msgs/Empty
В данной статье мы будем рассматривать создание своих собственных сообщений. Сообщения могут также содержать специальное поле заголовка с именем, которое задает временную отметку и систему отсчета.

 

Получение кода образца
Эти учебные пособия основаны на пособиях для начинающих пользователей ROS. • Все сегодняшние учебные пособия доступны здесь: http://farnsworth.csres.utexas.edu/tutorials/
Используйте следующие команды для установки архива в вашей рабочей среде:
• roscd
• wget http://farnsworth.csres.utexas.edu/tutorials/intro_to_ros.tar.gz
• tar xvzf intro_to_ros.tar.gz
• rosws set intro_to_ros
• Crestart terminal>
• rosmake intro to ros

talker.cpp (intro_to_ros)
#include "ros/ros.h"
#include Mstd_msgs/String.h"
#include
int main(int argc, char **argv) {
ros::init(argc, argv, "talker"); ros::NodeHandle n;
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
ros::Rate loop_rate(1) ;
int count = 0;
while (ros::ok()) {
std_msgs::String msg;
std::stringstream ss;
ss << "hello world " << count;
msg.data = ss.str();
ROS_INFO("%s", msg.data.c_str());
chatter_pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
++count;
}
return 0;
}
listener.cpp (intro_to_ros)
#include "ros/ros.h"
#include Mstd_msgs/String.h"

void chatterCallback(const std_msgs::String::ConstPtr msg) {
ROS_INFO("I heard: [%s]", msg->data.c_str());
}

int main(int argc, char **argv) {
ros::init(argc, argv, "listener");
ros::NodeHandle n;
ros::Subscriber sub =
n.subscribe<std_msgs::String>("chatter", 1000, chatterCallback)
ros::spin() ;
return 0;

talker.cpp
#include "ros/ros.h"
#include "std_msgs/String.h"
#include

ros/ros.h это заголовок для удобства, включающий в себя большинство составляющих, необходимых для запуска системы ROS
std_msgs/string.h это тип сообщения, на которое нам нужно будет отреагировать в этом примере: вы должны будете включить другой заголовок, если вы хотите использовать другой тип сообщения
sstream несет ответственность за некоторые работы со строками в C++

talker.cpp
ros::init(argc, argv, "talker");
ros::NodeHandle n;

ros::init отвечает за сбор ROS конкретной информации от аргументов, переданных в командной строке, он также присваивает имя нашего узла, Помните, что имена узлов должны быть уникальными в работающей системе. Мы видим пример такого аргумента в следующем примере.
Создание объекта ros::NodeHandle выполняет много заданий, это инициализирует узел, что делает возможной связь с другими узлами ROS и мастером в ROS инфраструктуре, позволяет взаимодействовать с узлом, который связан с этим процессом

talker.cpp
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
ros::Rate loop_rate(1);

NodeHandle::advertise несет ответственность за вызов XML/RPC к Мастеру ROS, который объявляет std_msgs:: строку, в разделе под названием "щебетание"
loop_rate используется для поддержания частоты публикации с частотой 1 Гц (т.е. 1 сообщение в секунду).

talker.cpp
int count = 0;
while (ros::ok()) {


count используется для отслеживания количества передаваемых сообщений. Его значение прикрепляется к строке сообщения, которое он публикует
ros::ok() гарантирует, что все по-прежнему в порядке в рамках ROS. Если что-то не так, то будет показано значение false, программа завершится. Примеры ситуаций, когда будет показано значение false:
Вы выполняете в программе операцию Ctrl+c (это расценивается как сбор секретной информации с помощью сигналов).
Вы открываете другой узел с тем же именем
Вы прописываете команду ros::shutdown () где-то в коде

talker.cpp
std_msgs::String msg;
std::stringstream ss;
ss << "hello world " << count;
msg.data = ss.str();

Эти 4 строки выполняют некоторые манипуляции со строками, чтобы установить счетчик внутри сообщения строки. Причина, по которой мы делаем это таким образом, – это то, что С ++ не имеет хорошего эквивалента функции toString()
msg.data является std::string
Примечание: я обычно использую boost::lexical_cast() вместо функции toString(). Iexical_cast() в значительной степени лучше выполняет для вас функцию, описанную выше (Изучите эту функцию, если вы заинтересовались)

talker.cpp
ROS_INFO("%s", msg.data.c_str());
chatter_pub. publish (msg) ;

 

ROS_INFO является макросом, который публикует информационное сообщение в экосистеме ROS. По умолчанию сообщения ROS_INFO также публикуются на экране.
Есть средства отладки в ROS, которые могут читать эти сообщения. Вы можете изменить данные о том, какой уровень сообщений должен быть опубликован
ros::Publisher::publish() отправляет сообщение всем подписчикам

talker.cpp
ros::spinOnce() ;
loop_rate.sleep() ;
++count;

ros::spinOnce() аналогична главной функции в инфраструктуре ROS.
Когда вы подписаны на один или несколько разделов, функции обратного вызова для получения сообщений по этим разделам не запрашиваются сразу. Вместо этого они помещаются в очередь, которая обрабатывается, когда вы делаете запрос ros::spinOnce()
Что произойдет, если мы удалим вызов spinOnce()?
ros::Rate.sleep() помогает поддерживать определенную частоту публикации, подсчет увеличивается, чтобы отслеживать сообщения

listener.cpp - в обратном порядке!

int main(int argc, char **argv) {
ros::init(argc, argv, "listener");
ros::NodeHandle n;
ros::Subscriber sub =
n.subscribe<std_msgs::String>("chatter", 1000, chatterCallback) ;
ros::spin();
return 0;
}


ros::NodeHandle::subscribe делает XML / RPC вызов мастеру ROS, это выполняет подписку на тему щебетание.
1000 – это размер очереди. В случае, если мы не в состоянии обрабатывать сообщения достаточно быстро. Это полезно только в случае нерегулярных периодов обработки сообщений. Почему?
Третий аргумент – это функция обратного вызова для определения того, что мы получаем сообщение
ros::spin() представляет собой удобную функцию, которая делает цикл вокруг ros:: spinOnce() во время проверки ros::ok()

listener.cpp

#include "ros/ros.h"
#include "std_msgs/String.h"

void chatterCallback(const std_msgs::String::ConstPtr msg) {
ROS_INFO("I heard: [%s]M, msg->data.c_str());
}

 те же заголовки, что и раньше
chatterCallback() является функцией, благодаря которой мы определяем, когда мы получаем сообщение на тему, которая есть в подписках, это имеет хорошо напечатанный аргумент.

 

Выполнение кода
Вы должны будете выполнить следующие шаги, чтобы заставить этот пример работать. После того, как вы загрузили наш код, постройте пример пакета rosmake intro_to_ros.
В отдельных терминальных окнах, выполните следующие программы:
• roscore
• rosrun intro_to_ros talker
• rosrun intro_to_ros listener

 

Пример 2 - Добавление узла передачи информации


Неоднократно в системе ROS вы будете иметь большое количество узлов, которые последовательно обрабатывают данные. Например, узел обнаружения сгустка определяет расположение сгустка для каждого изображения с камеры, которое он получает. Чтобы продемонстрировать это, мы изменим наш предыдущий пример следующим образом: представление узла передачи информации, который прослушивает сообщения на тему щебетание и направляет их на тему щебетание2. (Я не мог придумать более забавного название для этой темы). 
В командной строке происходит перераспределение, в результате которого слушатель подписывается на щебетание2 вместо щебетания.

messenger.cpp (intro_to_ros)
#include "ros/ros.h"
#include Mstd_msgs/String.h"

 

ros::Publisher chatter_pub;
std_msgs::String my_msg;

 

void chatterCallback( const std_msgs::String::ConstPtr msg) {
ROS_INFO("I heard: [%s]", msg->data.c_str());
my_msg.data = msg->data + ". Dont kill the messenger!";
chatter_pub.publish(my_msg);
}

 

int main(int argc, char **argv) {
ros::init(argc, argv, "messenger");
ros::NodeHandle n;
ros::Subscriber sub =
n.subscribe<std_msgs::String>("chatter", 1000, chatterCallback)
chatter_pub = n.advertise<std_msgs::String>("chatter2", 1000);
ros::spin();
return 0;
}
Выполнение кода
Вы должны будете выполнить следующие шаги, чтобы заставить этот пример работать.
В отдельных терминальных окнах, выполните следующие программы:
roscore
rosrun intro_to_ros talker
rosrun intro_to_ros listener chatter:=chatter2
rosrun intro_to_ros messenger

 

иерархия кодов

Repository (Хранилище): Содержит весь код из определенной группы разработки (У нас есть 3 хранилища из utexas)
Stack (Стек): Группирует весь код по конкретной теме/устройству
Packages (Пакеты): Отдельные модули, которые обеспечивают различные услуги
Nodes (Узлы): Исполняемые файлы, которые существуют в каждой модели (Вы это уже видели)

  3 ветки

2

пример

 

Инструменты командной строки – rospack

rospack – это программа командной строки, которая используется для поиска пакетов среди "совокупности деревьев" кода в типичном распределении ROS, рассчитывает зависимости, корректирует сборочные файлы, и вообще содействует миру и гармонии в распределении ROS. Некоторые примеры:
• rospack find intro_to_ros
• rospack list grep ros
• rospack depends intro_to_ros

 

Инструменты командной строки – rosstack

rosstack – это инструмент командной строки для получения информации о ROS стеках, доступных в файловой системе. Он реализует широкий спектр команд, начиная от местоположения ROS стеков в файловой системе до перечисления доступных стеков и расчета дерева зависимостей стеков. Некоторые примеры:

• rosstack contains intro_to_ros
• rosstack list-names grep examples
• rosstack depends art_examples.

 

Инструменты командной строки – roscd

roscd является частью rosbash комплекта. Это позволяет изменять каталог (т.е., cd) непосредственно в пакет или стек по имени вместо того, чтобы узнавать путь файловой системы. Некоторые примеры:
• rosed art_examples
• rosed intro_to_ros
• rosed intro_to_ros/src

 

rosbuild 

rosbuild содержит сценарии для управления основанной на CMake системой сборки для ROS. 3 файла используются для построения вашего пакета ROS

CMakeLists.txt - стандартный CMake файл построения, но допускает ROS макросы.
manifest.xml – указывает ваши зависимости, а также предоставляет компиляторные и связующие флажки.
Makefile -1 простая строка, которая вызывает CMake. Вы никогда не должны изменять ее.

 

CMakeLists.txt
CMakeLists.txt является эквивалентом Makefile. Он используется cmake для построения кода.
Давайте взглянем на файл CMakeLists.txt для нашего intro_to_ros пакета. Есть ряд хороших примеров CMakeLists.txt: http://www.ros.ora/wiki/rosbuild/CMakeLists/ExamDles
Мы быстро увидим некоторые из параметров и функции, которые могут быть использованы в CMakeLists.txt

 

rosbuild флажки

ROS_BUILD_TYPE: Устанавливает тип сборки. Опции (по умолчанию: RelWithDeblnfo):
• Debug : w/ debug символы, w/o оптимизация
• Release : w/o debug символы, w/ оптимизация
• RelWithDeblnfo : w/ debug символы, w/ оптимизация
• Rel With Asserts : w/o debug символы, w / оптимизация, w/ утверждения (т.е. w/o -DNDEBUG). Новый в ros 1.1.
• MinSizeRel: w/o debug символы, w/оптимизация, очищенные двоичные файлы

• ROS_BUILD_STATIC_EXES: Только статические исполняемые файлы для построения (например, для копирования на другой машине)? true or false; по умолчанию: false

• ROS_BUILD_SHARED_LIBS: Build shared libs? true or false; по умолчанию: true

• ROS_BUILD_STATIC_LIBS: Build static libs? true or false; по умолчанию: false

• ROS_COMPILE_FLAGS: Компиляторные флажки по умолчанию для всех исходных файлов; по умолчанию: W -Wall -Wno-unused-parameter -fno-strict-aliasing"

• ROS_LINK_FLAGS: Связывающие флажки по умолчанию для всех исполняемых файлов и библиотек; по умолчанию:""

CMakeLists.txt (contd)
Основные ROS макросы, которые вы будете завершать с помощью:
• rosbuild_add_library
• создает библиотеку из данного файла C ++
• размещаетбиблиотеку по умолчанию в папке lib
• rosbuild_add_executable
• создает исполняемый файл из данного файла C ++ – должен иметь основной
• исполняемые файлы помещаются в папку bin
• target_link_libraries
• соединяет исполняемый файл в вашем пакете с библиотекой внутри одного и того же пакета
• не требуется для библиотек в других пакетах
• требуется для внешних библиотек.

 

manifest.xml

manifest.xml предоставляет информацию о зависимостях от системы rosbuild – intro_to_ros manifest.xml.   Обеспечивает некоторую базовую документацию для пакета. Это хорошо для опубликованных пакетов. Например manifest.xml в ROS пакете “velodyne common” используется для автоматизации генерации раздела 1 на вики-странице.

• Обеспечивает системные зависимости пакета

• Обеспечивает другие зависимости пакета ROS

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

 

manifest.xml (contd)

 • флаги компилятора

-Kpath to include directory>
• флаги компоновщика
-L
-Kiibrary name> (многократно для нескольких библиотек)
—wi, —rpath, $ {prefix} /lib (путь к динамически подключенным библиотекам)
Таким образом, заданный velodyne_common имеет эти строки. Он имеет библиотеку (velodyne) и систему зависимости (pcap):


-Wl,-rpath,${prefix}/lib -lvelodyne -lpcap"/>

Что такое rosmake?

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

• rosmake – будет строить пакеты ROS вместе с ROS зависимостями
• rosmake – будет строить все пакеты в этом стеке
• rosmake --pre-clean – запускает функцию make clean && make на всех пакетах в дереве зависимостей
• rosmake --rosdep-install – устанавливает все необходимые зависимости системы
• Запуск: rosmake –help – увидеть все варианты

 

rosmake по сравнению с make

Чтобы сконструировать пакет, вы также можете перейти в этот каталог пакетов и напечатать make
• rosed intro_to_ros
• make
• make только построит пакет (т.е. не зависимости)
• make быстрее, чем rosmake
• полное дерево зависимостей не проверено
Я обычно использую rosmake при построении пакета впервые, или если мне что-то непонятно на счет зависимостях. После этого я использую make

 

Инструменты командной строки – roscreate-pkg

roscreate-pkg создает новый пакет в вашем текущем каталоге. Для этого, конечно, вы будете создавать только новые пакеты в каталоге spr12 внутри учебно-экспериментальной среды. Это автоматически генерирует стандартные файлы внутри пакета: CMakeLists.txt, Makefile, manifest.xml и mainpage.dox (не волнуйтесь о последнем). Пример:
• rosed spr12
• roscreate-pkg piyush_khandelwal_p2

Как написать пакет intro_to_ros
Создайте пакет
• rosed art_examples
• roscreate-pkg intro_to_ros
Внутри пакета создайте папку для содержания исходных файлов
• rosed intro_to_ros OR cd intro_to_ros
• mkdir src
Внутри каталога src напишите три файла:
• rosed intro_to_ros/src OR cd src
• gedit talker.cpp
• gedit messenger.cpp
• gedit listener.cpp

Как написать пакет intro_to_ros
Преобразуйте эти 3 файла в исполняемые файлы; Обновите CMakeLists.txt
• rosed intro_to_ros OR cd../
• gedit CMakeLists. txt
Используйте макрос rosbuild_add_executable, чтобы создать исполняемые файлы для этих трех файлов.
Запустите make; вы получите сообщение ошибки о том, что ros.h не был найден.
Обновите manifest.xml для добавления roscpp зависимости.
• gedit manifest.xml
Запустите make и продолжайте редактирование кода, чтобы решить вопросы компиляции и выполнения программы.

Обзор (продолжение)
С этим материалом, вы должны:
• Уметь создавать новые пакеты ROS
• Написать базовый код ROS, и уметь обновлять CMakeLists.txt и manifest.xml на основе вашего кода
• (Дополнительная возможность) Уметь писать библиотеки через систему построения ROS, которая будет использоваться вашим кодом и другими пакетами
• Использовать некоторые основные инструменты командной строки для перемещения по экосистеме ROS и отображать основную информацию о стеках и пакетах.

Подумайте о том, какие шаги удобны для вас. Обсудите с нами в рабочее время.

 

 

 

 

 


Похожие посты:

Молодым и амбициозным !

Start Up or Go Home

0
Комментировать
Введите код: