Практическое Использование Ros На Raspberry Pi — Часть 2

Добрый день, уважаемые читатели Хабра! Это вторая статья из серии статей о практическом использовании ROS на Raspberry Pi. В первая статья В цикле я описал установку необходимых компонентов ROS и настройку рабочей среды для работы.

Во второй части серии мы начнем практически использовать возможности ROS на платформе Raspberry Pi. В частности, в этой статье я собираюсь рассказать об использовании платы камеры Raspberry Pi на Raspberry Pi в сочетании с ROS для решения проблем компьютерного зрения.

Кому интересно, смотрите кат.



Плата камеры RPi

Для работы нам понадобится вот такая камера Raspberry Pi Camera Board:

Практическое использование ROS на Raspberry Pi — часть 2

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

Для подключения камеры используется кабель ZIF. Разъем для подключения кабеля на плате расположен между портами Ethernet и HDMI:

Практическое использование ROS на Raspberry Pi — часть 2



Установка библиотек

Итак приступим к установке необходимых библиотек.

Сначала давайте установим OpenCV:

  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
   

$ sudo apt-get install libopencv-dev

Чтобы использовать камеру Raspberry Pi, нам понадобится библиотека raspicam. Скачать архив отсюда .

Далее устанавливаем библиотеку:

$ tar xvzf raspicamxx.tgz $ cd raspicamxx $ mkdir build $ cd build $ cmake .

$ make $ sudo make install $ sudo ldconfig

Вам необходимо включить поддержку камеры в Raspbian через программу raspi-config:

$ sudo raspi-config

Выберите вариант 5 — Включить камеру, сохраните выбор и перезагрузите систему.



Начало работы с РОС

Для простоты использования давайте создадим новое рабочее пространство catkin для наших пакетов:

$ mkdir -p ~/driverobot_ws/src $ cd ~/driverobot_ws/src $ catkin_init_workspace $ cd ~/driverobot_ws $ catkin_make

Создайте новый пакет ROS:

$ cd src/ $ catkin_create_pkg raspi_cam_ros image_transport cv_bridge roscpp std_msgs sensor_msgs compressed_image_transport opencv2

Спецификация команды catkin_create_pkg следующая: catkin_create_pkg [зависит1] [зависит2], где вы можете указать в разделе «Зависимость» столько зависимостей, сколько захотите — библиотеки, которые будет использовать пакет. Эта команда создает скелет проекта ROS: пустой каталог src для сценариев узлов и файлов конфигурации CMakeLists.txt и package.xml. Я нашел простой скрипт, получающий кадры с камеры и публикующий их с помощью «издателя», и адаптировал его для ROS Indigo. Вы можете скачать его отсюда .

Для его использования вам необходимо установить драйвер камеры Raspberry Pi UV4L:

$ curl http://www.linux-projects.org/listing/uv4l_repo/lrkey.asc | sudo apt-key add -

Добавьте следующую строку в файл /etc/apt/sources.list

deb http://www.linux-projects.org/listing/uv4l_repo/raspbian/ wheezy main

, обновите пакеты и установите:

$ sudo apt-get update $ sudo apt-get install uv4l uv4l-raspicam

Чтобы загружать драйвер при каждой загрузке системы, мы также установим дополнительный пакет:

$ sudo apt-get install uv4l-raspicam-extras

Перейдем к редактированию пакета.

Вставьте строки в файл CMakeLists.txt. отсюда .

Самые важные строки в файле CMakeLists.txt:

link_directories(/usr/lib/uv4l/uv4lext/armv6l/) … target_link_libraries(capture ${catkin_LIBRARIES} uv4lext)

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

В конце файла прописываем специальные строки для нашего узла:

add_executable(capture src/capturer.cpp) target_link_libraries(capture ${catkin_LIBRARIES} uv4lext)

Строка add_executable создает двоичный файл для запуска, а target_link_lbraries связывает дополнительные библиотеки для двоичного файла захвата.

Вставить недостающие строки отсюда в файл package.xml, чтобы он выглядел так:

<Эxml version="1.0"?> <package> <name>raspi_cam_ros</name> <version>0.0.0</version> <description>The raspi_cam_ros package</description> <maintainer email="[email protected]">pi</maintainer> <license>TODO</license> <buildtool_depend>catkin</buildtool_depend> <build_depend>cv_bridge</build_depend> <build_depend>image_transport</build_depend> <build_depend>roscpp</build_depend> <build_depend>std_msgs</build_depend> <build_depend>sensor_msgs</build_depend> <build_depend>opencv2</build_depend> <build_depend>compressed_image_transport</build_depend> <run_depend>cv_bridge</run_depend> <run_depend>image_transport</run_depend> <run_depend>roscpp</run_depend> <run_depend>std_msgs</run_depend> <run_depend>sensor_msgs</run_depend> <run_depend>opencv2</run_depend> <run_depend>compressed_image_transport</run_depend> </package>

В первых строках задаются основные параметры узла — имя, версия, описание, информация об авторе.

Строки build_dependent определяют зависимости библиотеки, необходимые для компиляции пакета, а строки run_dependent определяют зависимости, необходимые для запуска кода в пакете.

Создайте файл capturer.cpp внутри папки src и вставьте строки отсюда .

Здесь в методе main() узел инициализируется и запускается в цикле:

ros::init(argc, argv,"raspi_cam_ros"); ros::NodeHandle n; UsbCamNode a(n); a.spin();

Вся логика скрипта заключается в том, что мы получаем изображение с камеры с помощью OpenCV, оборачиваем его в сообщение для ROS в методе fillImage и публикуем в теме.

При этом используется пакет image_transport для создания «издателя» изображения.

Запустим драйвер uv4l, выполнив команду:

$ uv4l --driver raspicam --auto-video_nr --width 640 --height 480 --nopreview

который создаст потоковую передачу MJPEG. Давайте скомпилируем наш узел ROS:

$ roscore $ cd ~/driverobot_ws $ catkin_make

Проверьте значение переменной ROS_PACKAGE_PATH:

echo $ROS_PACKAGE_PATH /opt/ros/indigo/share:/opt/ros/indigo/stacks

Значение переменной ROS_PACKAGE_PATH должно включать путь к нашей рабочей области.

Давайте добавим нашу рабочую область в путь:

$ source devel/setup.bash

Теперь снова запустив echo $ROS_PACKAGE_PATH, мы должны увидеть такой вывод:

/home/youruser/catkin_ws/src:/opt/ros/indigo/share:/opt/ros/indigo/stacks

, где /дом/ /catkin_ws/src — путь к нашему рабочему пространству.

Это означает, что ROS может «видеть» наши узлы, созданные в catkin_ws, и мы можем запускать их через rosrun. Запустим наш узел ROS:

$ rosrun raspi_cam_ros capture

Запустим графическую программу rqt_image_view для отображения видеопотока из темы:

$ rosrun rqt_image_view rqt_image_view

Выберите тему image_raw в окне rqt_image_view.

Практическое использование ROS на Raspberry Pi — часть 2

При запуске узла может возникать ошибка «Gtk-WARNING**: невозможно открыть дисплей: -1» при работе через ssh или «GdkGLExt-WARNING**: Windows system не поддерживает OpenGL».

при запуске в режиме удаленного рабочего стола VNC. Решение — подключиться к Raspberry Pi через SSH с переадресацией X11:

$ ssh -X pi@<host_pi>

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

rostopic hz image_raw

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

Для модели B+ у меня был следующий результат:

average rate: 7.905 min: 0.075s max: 0.249s std dev: 0.02756s

Как видите, частота публикации сообщений составляет 8 Гц.

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

average rate: 30.005 min: 0.024s max: 0.043s std dev: 0.00272s

Сообщения уже публикуются с частотой 30 Гц, что является довольно хорошим приростом скорости по сравнению с моделью B+.



Визуальное управление роботом с помощью OpenCV и ROS

Теперь мы напишем небольшой пакет ROS для использования компьютерного зрения на роботе с Raspberry Pi, который будет выполнять алгоритм распознавания (в нашем случае визуальное ориентирование с использованием метода следования по строке) и публиковать величину необходимого перемещения робота в виде тема.

С другой стороны, узел управления движением робота подпишется на эту тему и отправит команды управления движением на Arduino. Теперь давайте добавим в скрипт capturer.cpp «издатель», который будет публиковать значение сдвига.

Для начала включим определение типа сообщения для значения сдвига — std_msgs/Int16.

#include <std_msgs/Int16.h>

rosserial принимает специальные файлы сообщений msg и генерирует для них исходный код. Используется следующий шаблон:

package_name/msg/Foo.msg → package_name::Foo

Исходный код стандартных сообщений Rosserial хранится в папке package_name внутри каталога ros_lib. Далее инициализируем сообщение для этого типа:

std_msgs::Int16 shift_msg;

Создаем «издателя»:

ros::Publisher shift_pub;

и внутри конструктора UsbCamNode даем ему определение:

shift_pub = nh.advertise<std_msgs/Int16>(“line_shift”, 1);

Здесь мы задаем тип сообщений и название темы для публикации.

Далее мы добавим логику расчета значения сдвига строки с помощью OpenCV и опубликуем ее в теме line_shift в методе take_and_send_image() перед строкой #ifdef OUTPUT_ENABLED:

// Some logic for the calculation of offest shift_msg.data = offset; shift_pub.publish(shift_msg);

Готового алгоритма следования по строкам у меня нет, поэтому читатель волен написать здесь свою логику.

Фактические данные в сообщении хранятся в поле данных.

Структуру сообщения можно просмотреть с помощью команды:

$ rosmsg show std_msgs/Int16

Теперь запустим узел:

$ rosrun raspi_cam_ros capturer

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

$ rostopic echo line_shift

Теперь добавим «абонента» в узел управления роботом.

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

#include <std_msgs/UInt16.h>

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



void messageCb(const std_msgs::UInt16& message) { int shift_val = int(message.data); char* log_msg; if(shift_val < 0) log_msg = "Left"; else if(shift_val > 0 ) log_msg = "Right"; else log_msg = "Forward"; nh.loginfo(log_msg); }

Функция обратного вызова должна иметь тип void и принимать ссылку на константный тип сообщения в качестве аргумента.

Для простоты я записываю сообщение о направлении смещения линии.

Здесь вы можете добавить собственную логику движения робота для вашего сценария.

Создаем подписчика на сообщения из темы line_shift.

ros::Subscriber<std_msgs::UInt16> sub("line_shift", &messageCb);

Здесь мы задаем название темы и ссылку на функцию обратного вызова.

Далее идут стандартные методы эскиза для rosserial_arduino:

void setup() { nh.initNode(); nh.subscribe(sub); Serial.begin(57600); } void loop() { nh.spinOnce(); delay(100); }

Единственное отличие состоит в том, что мы добавляем nh.subscribe(sub) для создания фактической «подписки» узла на тему.

Скетч для управления роботом можно скачать отсюда .

Маленькая хитрость! В ROS есть специальные файлы запуска, которые позволяют автоматически запускать узлы как отдельные процессы с определенными параметрами.

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

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

Вы можете создать файл запуска, чтобы упростить запуск сервера rosserial_python.

$ cd <catkin_ws>/src $ catkin_create_pkg rosserial_controller $ cd src/rosserial_controller $ vim rosserial_controller.launch

Напишем файл запуска следующего содержания:

<launch> <node pkg="rosserial_python" type="serial_node.py" name="arduino_serial"> <param name="port" value="/dev/ttyACM0"/> </node> </launch>

Давайте скомпилируем и запустим его:

$ cd ~/<catkin_ws> $ catkin_make $ source devel/setup.bash $ roslaunch rosserial_controller rosserial_controller.launch

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

$ rqt_plot line_shift

Теперь вы можете в полной мере воспользоваться преимуществами камеры Raspberry Pi и библиотеки OpenCV для визуальной ориентации вашего робота, распознавания объектов, отслеживания и многих других сценариев.

Дайте волю своему воображению! В следующий раз мы поговорим об управлении роботом в режиме телеуправления с помощью нажатия клавиш на клавиатуре.

ПС.

В сети есть полезные шпаргалки — ROS Cheatsheet. Для версии ROS Indigo вы можете скачать это отсюда .

Теги: #Робототехника #arduino #ros

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.