Согласование датчиков зрения с ROS

Согласование датчиков зрения с ROSВ предыдущей статье «Согласование приводов и датчиков с контроллером робота» мы рассматривали некоторые роботизированные датчики, используемые в нашем роботе, и их взаимодействие с микроконтроллером LaunchPad. Основная тема этой статьи – датчики машинного зрения и их интерфейс.

Серия статей на тему: «Создание с нуля автономного мобильного обслуживающего робота с использованием Python»

  1. Начало работы с операционной системой для робота (ROS)
  2. Основные понятия роботов с дифференциальным приводом
  3. Моделирование робота с дифференциальным приводом
  4. Моделирование дифференциального привода робота, управляемого операционной системой ROS
  5. Проектирование оборудования и схем ChefBot
  6. Согласование приводов и датчиков с контроллером робота
  7. Согласование датчиков зрения с ROS
  8. Создание аппаратного обеспечения ChefBot и интеграция ПО программного обеспечения
  9. Разработка графического интерфейса для робота с использованием Qt и Python

Робот, который мы проектируем, оборудован трехмерным датчиком технического зрения, который взаимодействует с помощью таких библиотек технического зрения, как Open Source Computer Vision (OpenCV), Open Natural Interaction (OpenNI) и Point Cloud Library (PCL). Основные задачи, возлагаемые на датчик технического трехмерного зрения, следующие: автономная навигация, избегание препятствий, обнаружение предмета, отслеживание (определение) людей и т. д.

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

В последней части этой статьи мы рассмотрим алгоритм отображения и локализации, который будет использован в нашем роботе. Этот алгоритм называется SLAM (одновременная локализация и отображение), реализуем его с использованием датчика 3D vision, ROS и библиотек обработки изображений.

В этой статье мы рассмотрим следующие темы:

  • список роботизированных датчиков технического зрения и библиотек
    изображений;
  • введение в формат OpenCV с поддержкой OpenNI. и PCL;
  • интерфейс ROS-OpenCV;
  • обработка облака точек с помощью интерфейса PCL-ROS;
  • преобразование данных облака точек в данные лазерного сканирования;
  • введение в SLAM.

Технические требования

Для выполнения примера, приведенного в этой статье, вам понадобятся операционная система Ubuntu 16.04 с установленной Ros Kinetic, веб-камера и стереокамера. В первой части статьи мы познакомимся с двухмерными и трехмерными датчиками технического зрения. Эти датчики можно приобрести через интернет и применять в разных роботах.

Список робототехнических датчиков зрения и библиотек для работы с изображением

Двухмерный датчик изображения, который может заменить обычная камера, обеспечивает двухмерное изображение окружающей среды, тогда как трехмерный датчик изображения обеспечивает, кроме двухмерного изображения, дополнительный параметр, называемый глубиной каждой точки изображения. Мы можем получить расстояние от датчика трехмерного изображения к каждой точке по осям x, y и z. На рынке предлагается много датчиков технического зрения. Мы рассмотрим те датчики, которые будут использованы в нашем роботе.

Pixy2/CMUcam5

На следующем рисунке показан двухмерный датчик под названием Pixy/CMU Cam 5 (http://www.cmucam.org/). Датчик способен обнаружить с высокой точностью цветные объекты, и ему даже не помешает высокая скорость движения. Датчик может подключаться к плате Arduino. Этот датчик может быть использован для быстрого обнаружения объекта, а пользователь может указать, какой объект он должен отслеживать. В модуле Pixy установлены датчики CMOS и NXP (http://www.nxp.com/) и процессор для обработки изображений:

Вид модулей
1) Вид модуля Pixy/CMUсam 5.     2) Вид модуля Pixy2/CMUсam 5 (http://a.co/fZtPqck)

Веб-камера Logitech C920

На следующем рисунке вы увидите популярную веб-камеру Logitech, которая может захватывать изображения с разрешением до 5 мегапикселей и HDвидео:

Веб-камера Logitech HD C920
Веб-камера Logitech HD C920 (http://a.co/02DUUYd)

Kinect 360

Теперь мы рассмотрим датчики трехмерного технического зрения, доступные на рынке. Наиболее популярными датчиками являются Kinect, Intel RealSense серии D400 и Orbbec Astra.

Датчик Kinect 360
Датчик Kinect 360

Kinect – это 3D-датчик видеообзора, который используется вместе с игровой консолью Xbox 360 от Microsoft. Он содержит камеру RGB, инфракрасный прожектор, датчик глубины, блок с микрофоном и встроенный в основание камеры двигатель, позволяющий наклонять камеры под нужным углом. RGBкамера и камера глубины захватывает изображение с разрешением 640×480 с частотой 30 Гц. Камера RGB захватывает цветное двухмерное изображение, тогда как камера глубины захватывает монохромное изображение глубины. Kinect измеряет глубину в пределах от 0,8 до 4 м.

Некоторые применения Kinect – захват движения в трех плоскостях, структурное отслеживание, распознавание лиц и речи.

Kinect может подключаться к ПК с через интерфейс USB 2.0 и программируется с помощью Kinect SDK, OpenNI и OpenCV. Библиотека Kinect SDK работает только с платформами Windows, разрабатывается и поставляется корпорацией «Майкрософт». Остальные две библиотеки (OpenNI и OpenCV) с открытым исходным кодом и доступны для всех платформ. Мы используем одну из последних версий Kinect, поддерживается она только на платформе Windows.

Производство датчиков серии Kinect прекращено, но вы все еще можете найти датчик на Amazon и eBay.

Intel RealSense серии D400

Датчики глубины Intel RealSense D400 имеют стереокамеры, которые идут с ИК-проектором для улучшения данных глубины, как показано на рисунке

Intel RealSense D400 series
Intel RealSense D400 series (https://realsense.intel.com/)

Наиболее популярные модели датчиков серии D400 – это D415 и D435. На рисунке сверху показан датчик D415. Ниже – датчик D435. Каждый из датчиков состоит из стереопары, RGB-камеры и ИК-прожектора. Стереопара камер вычисляет глубину окружающей среды с помощью ИК-прожектора.

Главная особенность этой камеры глубины в том, что она может работать как в помещении, так и на открытом воздухе. Камера предоставляет поток глубины изображений с разрешением 1280×720 на 90 кадров/с, а разрешение RGBкамеры составляет до 1920×1080. Intel RealSense взаимодействует с ПК через USB-С, который обеспечивает высокоскоростную передачу данных между датчиком и компьютером. Датчик имеет небольшие размеры и малый вес, что позволяет использовать его в мобильных роботах как датчик технического зрения.

Устройства Kinect и Intel RealSense функционально одинаковы, за исключением функции распознавания речи. Эти датчики работают с платформами Windows, Linux и Mac. Для работы устройства потребуются ROS, OpenNI и OpenCV. На следующем рисунке показана блок-схема камеры серии D400.

Блок-схема камеры серии D400
Блок-схема камеры серии D400

Справочную информацию по Intel RealSense вы найдете на странице по адресу: https://software.intel.com/sites/default/files/Intel_RealSense_Depth_Cam_D400_Series_Datasheet.pdf.

Чтобы прочитать исследовательскую работу о датчике глубины Intel Realsense, перейдите по следующей ссылке: https://arxiv.org/abs/1705.05548.

Пакет Intel RealSense SDK находится по ссылке: https://github.com/IntelRealSense/librealsense.

Датчик глубины изображения Orbbec Astra

Альтернативой датчику Kinect является новый датчик Orbbec. Этот датчик имеет такие же характеристики, как Kinect, и использует аналогичную технологию для получения глубины изображения. Так же, как и Kinect, он оснащен ИК-прожектором, RGB-камерой и ИК-датчиком. Устройство снабжено и микрофоном для распознавания голосовых команд.

На следующем рисунке показаны все элементы датчика глубины Orbbec Astra.

Элементы датчика глубины Orbbec Astra
Элементы датчика глубины Orbbec Astra

В продаже можно найти датчики Astra двух моделей: Astra и Astra S. Основная разница между эти двумя моделями – глубина обзора. Astra имеет глубину обзора от 0,6 до 8 м, а глубина обзора Astra S – от 0,4 до 2 м. Astra S лучше всего подходит для 3D-сканирования, тогда как Astra может быть применена в робототехнике. Размер и вес Astra гораздо меньше, чем у Kinect. Эти две модели поставляют данные глубины изображения по RGB-каналам с разрешением 640×480 на 30 кадров/с. Можно использовать и более высокое разрешение, например 1280×960. Но в этом случае понижается частота кадров. Эти датчики, так же как и датчики Kinect, могут отслеживать структуру пространства.

Датчик совместим с фреймворком OpenNI, поэтому приложение, работающее с OpenNI, может работать и с этим датчиком. Мы данный датчик применим в нашем роботе.

SDK совместим с Windows, Linux и Mac OS X. Для получения дополнительной
информации зайдите на сайт разработчика: https://orbbec3d.com/develop/.

Один из датчиков, который также можно использовать в нашем роботе, – это камера ZED (https://www.stereolabs.com/zed/). Эта стереокамера обеспечивает видеосигнал с высоким разрешением и хорошую частоту. Она дороже, чем перечисленные выше датчики технического зрения. Ее цена – около 450 долл. США. Эту камеру можно использовать для высококлассных роботов, где от датчиков требуется высокая точность.

Сопряжение данного датчика с ROS мы рассмотрим в следующей части этой статьи.

Введение в OpenCV, OpenNI и PCL

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

Что такое OpenCV?

OpenCV – это открытый исходный код с BSD-лицензированной библиотекой компьютерного зрения, который включает в себя сотни алгоритмов компьютерного зрения. Библиотека в основном ориентирована на компьютерное зрение в реальном времени. Разработана в исследовательской корпорации Intel в России и сейчас активно поддерживается Itseez.

Логотип OpenCV
Логотип OpenCV

OpenCV в основном написан на C и C++, а его основной интерфейс разработан в C++. OpenCV имеет хорошие интерфейсы в Python, Java, Matlab/Octave и также имеет оболочки и для других языков. Например: C# и Ruby.

В новой версии OpenCV есть поддержка CUDA и OpenCL, ускоряющая работу GPU (https://developer.nvidia.com/cuda-zone).

OpenCV хорошо работает с большинством платформ ОС, таких как Windows, Linux, Mac OS X, Android, ОС FreeBSD, OpenBSD и FreeBSD, iOS и BlackBerry.

В Ubuntu OpenCV и Python были установлены при установке пакетов roskinetic-desktop-full. Если этот пакет по каким-то причинам не был установлен, примените приведенные ниже команды для установки пакета OpenCV-ROS:

$ sudo apt-get install ros-kinetic-vision-opencv

Чтобы проверить, установлен ли модуль OpenCV-Python в вашей системе, запустите терминал Linux и введите команду python. Будет показан интерпретатор Python. Далее для проверки установки OpenCV выполните в терминале следующие команды:

>> import cv2
>>> cv2.__version__

Если эта команда будет выполнена успешно, значит, данная OpenCV установлена в вашей системе. Версия может быть 3.3.x или 3.2.х.

Чтобы попробовать OpenCV в Windows, для установки перейдите по следующей ссылке:
https://docs.opencv.org/2.4/doc/tutorials/introduction/windows_install/windows_install.html.

Для установки OpenCV на MAC OS X обратитесь к ссылкам:
https://www.pyimagesearch.com/2016/12/05/macos-install-opencv-3-and-python-3-5/;
https://www.learnopencv.com/install-opencv3-on-macos/.

Основные области применения OpenCV:

  • обнаружение объектов;
  • распознавание жестов;
  • взаимодействие человека и компьютера;
  • мобильная робототехника;
  • отслеживание движения;
  • распознавание лиц.

Теперь мы можем рассмотреть процедуру установки OpenCV в Ubuntu 14.04.2 из исходного кода.

Установка OpenCV в Ubuntu из исходного кода

Есть разные варианты установки OpenCV. Один из вариантов – установка из исходных кодов. Как выполнить такую установку, узнайте, перейдя по ссылке: https://docs.opencv.org/trunk/d7/d9f/tutorial_linux_install.html.

Для работы с примерами, приведенными в этой статье, лучше всего использовать OpenCV, установленную вместе с ROS.

Чтение и отображение изображения с помощью интерфейса Python-OpenCV

Первый пример загрузит изображение в оттенках серого и отобразит его на экране. В следующем разделе кода мы импортируем модуль numpy для обработки массива изображений. Модуль cv2 – это оболочка OpenCV для Python, которую мы можем использовать для доступа к API OpenCV Python. NumPy – это расширение языка программирования Python, добавляющее поддержку больших многомерных массивов и матриц, а также большую библиотеку высокоуровневых математических функций для работы с этими массивами (более подробная информация – на сайте https://pypi.python.org/pypi/numpy):

#!/usr/bin/env python
import numpy as np
import cv2

Следующая функция считывает изображение robot.jpg и загружает его в полутоновом формате. Первый аргумент функции cv2.imread() – это имя изображения. Следующий аргумент является флагом, который определяет тип цвета загруженного изображения. Если флаг > 0, то изображение возвращает три цветовых канала цветного изображения (RGB). Если флаг = 0, загружаемое изображение будет черно-белым. Если флаг < 0, то загруженное изображение будет возвращено:

img = cv2.imread(‘robot.jpg’, 0)

В следующем разделе кода будет показано, как с помощью функции imshow() прочитать изображение. Функция cv2.waitKey(0) является функцией привязки клавиатуры. Ее аргументом является время в миллисекундах. Если аргумент равен 0, функция будет ждать нажатия клавиши.

cv2.imshow(‘image’,img)
cv2.waitKey(0)

Функция cv2.destroyAllWindows() закрывает все ранее открытые окна:

cv2.destroyAllWindows()

Сохраните предыдущий код с именем image_read.py и скопируйте файл robot.jpg в папку, в которой расположен код. Выполните код с помощью следующей команды:

$python image_read.py

Выходные данные загрузят изображение в оттенках серого, потому что в качестве значения функции imread() мы использовали 0:

Вывод прочитанного кода изображения
Вывод прочитанного кода изображения

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

Захват видео с веб-камеры

Следующий код захватит изображение с помощью веб-камеры с именем устройства: /dev/video0 или /dev/video1.

Для захвата изображения с камеры нам нужно импортировать модули NumPy и cv2:

#!/usr/bin/env python
import numpy as np
import cv2

Следующая функция создает объект VideoCapture. Класс VideoCapture используется для захвата видео с видеофайлов или камер. Аргумент инициализации класса VideoCapture – индекс камеры или название видеофайла. Устройство index – это просто число для указания камеры. Первый индекс камеры равен 0 и имеет имя устройства /dev/video0. Поэтому в следующем коде мы поставим 0:

cap = cv2.VideoCapture(0)

Следующий раздел кода зациклен для чтения кадров изображения из объекта VideoCapture и показывает каждый кадр. При нажатии любой клавиши цикл прервется:

while(True):
# Захват кадра
ret, frame = cap.read()
# Отображение результирующего кадра
cv2.imshow(‘frame’,frame)
if cv2.waitKey(10):
break

Ниже показан скриншот вывода программы:

Выход видеозахвата
Выход видеозахвата

Вы можете узнать больше о работе OpenCV-Python, перейдя по следующей ссылке: http://opencv-python-tutroals.readthedocs.org/en/latest/py_tutorials/py_tutorials.html.

Далее мы рассмотрим библиотеку OpenNI и ее применение.

Что такое OpenNI?

OpenNI – это мультиязычный, кроссплатформенный фреймворк, содержащий API для создания приложений и использующий естественное взаимодействие (NI) (чтобы узнать больше, перейдите по ссылке https://structure.io/openni). Естественное взаимодействие – это способ, благодаря которому люди общаются между собой естественным образом: с помощью жестов, выражений и движений, – и открывают для себя мир, оглядываясь вокруг и манипулируя физическими объектами и материалами.

API OpenNI состоит из набора интерфейсов, которые используются для создания приложений NI.

На следующем рисунке показано трехслойное представление библиотеки OpenNI.

Архитектура программной поддержки OpenNI
Архитектура программной поддержки OpenNI

Верхний слой представляет прикладной уровень, реализующий естественное взаимодействие на основе взаимодействия. Средний слой – это слой поддержки OpenNI. Он предоставляет интерфейсы связи, взаимодействующие с датчиками и промежуточными компонентами, анализирующими данные, получаемые от датчиков. Middleware можно использовать для полного анализа тела, положения руки, обнаружения жестов и т. д. Одним из примеров среднего слоя является NITE, который может обнаружить жест и структуру.

На нижнем уровне находятся аппаратные средства, захватывающие визуальные и звуковые элементы сцены. Нижний уровень включает в себя 3D-датчики, RGB-камеры, ИК-камеру и микрофон.

Последняя версия OpenNI2 поддерживает такие датчики, как ASUS Xtion Pro. Первая версия OpenNI в основном поддерживала датчик Kinect 360.

OpenNI кроссплатформенный, успешно скомпилирован и развернут для ОС Linux, Mac ОС X и Windows.

В следующей части статьи мы рассмотрим, как установить OpenNI на Ubuntu 14.04.2.

Установка OpenNI в Ubuntu

Мы можем установить библиотеку OpenNI вместе с пакетами ROS. ROS уже взаимодействует с OpenNI, но при полной установке Ros desktop пакеты OpenNI могут и не установиться. В этом случае нам OpenNI следует установить с помощью менеджера пакетов.

Следующая команда установит библиотеку ROS-OpenNI (которая в основном поддерживается сенсором Kinect Xbox 360) в Kinetic и Melodic:

$ sudo apt-get install ros-<version>-openni-launch

Команда, показанная ниже, установит библиотеку ROS-OpenNI 2 (которая в основном поддерживается компаниями ASUS Xtion Pro и Carmine):

$ sudo apt-get install ros-<version>-openni2-launch

Исходный код и последняя сборка с поддержкой OpenNI для Windows, Linux и MacOS X доступны на http://structure.io/openni.

В следующей части мы рассмотрим, как установить PCI.

Что такое PCL?

Облако точек – это набор точек данных в пространстве, представляющих 3D-объект или среду. Обычно облако точек создается с помощью датчиков глубины, таких как Kinect и LIDAR. PCL (Point Cloud Library) – это крупномасштабный открытый проект для обработки 2D/3D-изображений и облаков точек. Фреймворк PCL содержит множество алгоритмов, которые выполняют фильтрацию, оценку характеристик, реконструкцию поверхности, регистрацию, подгонку модели и сегментацию. Используя эти методы, мы можем обрабатывать облако точек, извлекать ключ идентификаций для распознавания объектов в мире на основе их геометрических форм, создавать поверхности из облаков точек и визуализировать их.

PCL выпущен под лицензией BSD, т. е. с открытым исходным кодом и бесплатным для коммерческого использования или исследования. PCL является кроссплатформенным приложением и успешно скомпилирован и развернут для Linux, Mac OS X, Windows и Android/iOS.

Скачать PCL можно по следующей ссылке: http://pointclouds.org/downloads/.

Логотип PCL
Логотип PCL

PCL уже интегрирован в ROS. Библиотека PCL и его ROS устанавливаются вместе с полной установкой ROS. В предыдущей статье «Согласование приводов и датчиков с контроллером робота» мы обсудили, как установить полный комплект ROS. PCL – это основное приложение ROS для обработки трехмерных изображений.

Чтобы подробнее узнать о пакете PCL, перейдите по следующей ссылке: http://wiki.ros.org/pcl.

Программирование Kinect с использованием Python ROS, OpenCV и OpenNI

Давайте посмотрим, как мы можем взаимодействовать с датчиком Kinect в ROS. ROS комплектуется драйвером OpenNI, который с помощью Kinect делает выборку RGB и глубины изображения.

Этот пакет может быть использован для Microsoft Kinect, PrimeSense Carmine, Asus Xtion Pro и Pro Live.

В основном этот драйвер публикует исходную глубину изображения, RGB и потоки ИК-изображений. Пакет openni_launch установит такие пакеты, как openni_camera и openni_launch.

Пакет openni_camera является драйвером Kinect, который публикует необработанные данные c информационных датчиков, в то время как пакет openni_launch содержит файлы запуска ROS. Эти файлы запускают несколько узлов одновременно и публикуют такие данные, как необработанная глубина, изображения RGB и IR, а также облако точек.

Как запустить драйвер OpenNI

Датчик Kinect подключается к компьютеру через USB. Чтобы убедиться, что компьютер устройство обнаружил, введите в терминал команду dmesg. После подключения Kinect для получения данных с устройства следует запустить драйвер OpenN ROS. Следующая команда откроет устройство OpenNI и загрузит все узлы для преобразования необработанных потоков глубина/RGB/IR в глубину изображений, разницу изображений и облака точек. Пакет узлов ROS предназначен для запуска нескольких алгоритмов в одном процессе с нулевым переносом копий между алгоритмами:

$ roslaunch openni_launch openni.launch

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

$ rostopic list

Изображение RGB можно просмотреть с помощью инструмента ROS с названием image_view:

$ rosrun image_view image_view image:=/camera/rgb/image_color

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

Интерфейс ROS в формате OpenCV

OpenCV также интегрирован в ROS, в основном для обработки изображений. Стек vision_opencv ROS включает в себя полную библиотеку OpenCV и ее интерфейс в ROS. Метапакет vision_opencv состоит из нескольких пакетов:

  • cv_bridge: содержит класс СvBridge; этот класс преобразует сообщения из ROS в тип данных изображения OpenCV и наоборот;
  • image_geometry: содержит коллекцию методов обработки изображений и геометрию пикселей.

На следующей схеме показано, как OpenCV взаимодействует с ROS.

Интерфейс OpenCV – ROS
Интерфейс OpenCV – ROS

Типами данных изображений формата OpenCV являются IplImage и Mat. Если нам потребуется в ROS работать с OpenCV, нам необходимо передаваемые изображения преобразовать в IplImage или Mat ROS.

Пакет ROS vision_opencv содержит класс CvBridge; этот класс преобразует IplImage в образ ROS, и наоборот. Как только мы получим темы изображений ROS от любого датчика технического зрения, задействуем ROS CvBridge для преобразования изображения из темы ROS в формат Mat или IplImage.

В следующей части показано, как создать ROS-пакет. Этот пакет содержит узел для подписки на RGB-изображения и глубину изображения, обработку RGB-изображений с целью обнаружения краев и отображение всех изображений после их преобразования в тип изображения, эквивалентный OpenCV.

Создание пакета ROS с поддержкой OpenCV

Мы можем создать пакет sample_opencv_pkg со следующими зависимостями: sensor_msgs, cv_bridge, rospy и std_msgs. Зависимость sensor_msgs определяет сообщения для часто используемых датчиков, включая камеры и сканирующий лазерный дальномер; cv_bridge является интерфейсом OpenCV ROS.

Следующая команда создаст пакет ROS с предыдущими зависимостями:

$ catkin-create-pkg sample_opencv_pkg sensor_msgs cv_bridge rospy std_msgs

После создания пакета создайте папку scripts внутри пакета и сохраните код, указанный в следующем разделе.

Вывод изображений с Kinect с помощью Python, ROS и cv_bridge

Первый раздел кода Python приведен ниже. Главным образом этот код включает в себя импортированные модули rospy, sys, cv2, sensor_msgs, cv_bridge и numpy.

Sensor_msgs импортирует тип данных ROS Image и CameraInfo. Модуль cv_bridge импортирует класс CvBridge для преобразования типа данных ROS image в тип данных OpenCV, и наоборот:

import rospy
import sys
import cv2
import cv2.cv as cv
from sensor_msgs.msg import Image, CameraInfo
from cv_bridge import CvBridge, CvBridgeError
import numpy as np

Следующий раздел кода является определением класса CvBridge в Python с функцией демонстрации. Класс называется cvBridgeDemo:

class cvBridgeDemo():
def __init__(self):
self.node_name = «cv_bridge_demo»
# инициализировать узел ros
rospy.init_node(self.node_name)
# что мы делаем во время выключения
rospy.on_shutdown(self.cleanup)
# Создание объекта cv_bridge
self.bridge = CvBridge()
# Подпишитесь на темы изображения и глубины камеры и установите
# соответствующие обратные вызовы
self.image_sub =
rospy.Subscriber(«/camera/rgb/image_raw», Image,
self.image_callback) self.depth_sub =
rospy.Subscriber(«/camera/depth/image_raw», Image,
self.depth_callback)
# обратный вызов выполняется во время паузы таймера
rospy.Timer(rospy.Duration(0.03), self.show_img_cb)
rospy.loginfo(«Waiting for image topics…»)

Зависимость cv_bridge является интерфейсом OpenCV ROS. Ниже приведен код обратного вызова для отображения фактического изображения RGB, обработанного изображения RGB и изображения глубины:

def show_img_cb(self,event):
try:
cv2.namedWindow(«RGB_Image», cv2.WINDOW_NORMAL)
cv2.moveWindow(«RGB_Image», 25, 75)
cv2.namedWindow(«Processed_Image», cv2.WINDOW_NORMAL)
cv2.moveWindow(«Processed_Image», 500, 75)
# И одно для изображения глубины
cv2.moveWindow(«Depth_Image», 950, 75)
cv2.namedWindow(«Depth_Image», cv2.WINDOW_NORMAL)
cv2.imshow(«RGB_Image»,self.frame)
cv2.imshow(«Processed_Image»,self.display_image)
cv2.imshow(«Depth_Image»,self.depth_display_image)
cv2.waitKey(3)
except:
pass

Следующий код создает функцию обратного вызова цветного изображения из Kinect. При поступлении в тему цветного изображения /camera/rgb/image_color будет вызываться эта функция, которая обработает границы цвета для обнаружения края и покажет их в сочетании с оригинальным изображением:

def image_callback(self, ros_image):
# Использование cv_brige для преобразования образа ROS в формат Opencv
try:
self.frame = self.bridge.imgmsg_to_cv2(ros_image, «bgr8»)
except CvBridgeError, e:
print e
pass
# Преобразуйте изображение в массив Numpy, так как большинство функций cv2
# требуют массивы Numpy.
frame = np.array(self.frame, dtype=np.uint8)
# Обработайте кадр с помощью функции process_image()
self.display_image = self.process_image(frame)

Следующий код с помощью Kinect вызывает функцию обратного вызова глубины изображения. Функция обратного вызова будет вызвана, когда данные по глубине изображения поступят на тему /camera/depth/raw_image. С помощью этой функции будет отображено необработанное изображение глубины:

def depth_callback(self, ros_image):
# Использование cv_brige() для преобразования образа ROS в формат Opencv
try:
# Глубина изображения – одноканальные изображения float32
depth_image = self.bridge.imgmsg_to_cv2(ros_image, «32FC1»)
except CvBridgeError, e:
print e
pass
# Преобразуйте изображение в массив Numpy, так как большинство функций cv2
# требуют массивы Numpy.
depth_array = np.array(depth_image, dtype=np.float32)
# Нормализация глубины изображения между 0 (черный) и 1 (белый)
cv2.normalize(depth_array, depth_array, 0, 1, cv2.NORM_MINMAX)
# Обработка глубины изображения.
self.depth_display_image = self.process_depth_image(depth_array)

Следующая функция называется process_image(), преобразует цветное изображение в серое, затем размывает изображение и находит границы с помощью фильтра Кэнни:

def process_image(self, frame):
# Преобразование в оттенки серого
grey = cv2.cvtColor(frame, cv.CV_BGR2GRAY)
# Размытие изображения
grey = cv2.blur(grey, (7, 7))
# Вычислить границы через фильтр Кэнни
edges = cv2.Canny(grey, 15.0, 30.0)
return edges

Приведенная ниже функция называется process_depth_image(). Она просто возвращает глубину границы:

def process_depth_image(self, frame):
# Просто верните изображение raw для этой демонстрации
return frame

Функция, код которой показан ниже, закроет окно изображения, когда узел завершит работу:

def cleanup(self):
print «Shutting down vision node.»
cv2.destroyAllWindows()

Следующий код для функции main(). Он инициализирует класс cvBridgeDemo() и вызывает функцию rospy.spin():

def main(args):
try:
cvBridgeDemo()
rospy.spin()
except KeyboardInterrupt:
print «Shutting down vision node.»
cv.DestroyAllWindows()
if __name__ == ‘__main__’:
main(sys.argv)

Сохраните предыдущий код в cv_bridge_demo.py и измените разрешение узла с помощью следующей команды. Узел виден только команде rosrun, если мы дадим ему права доступа.

$ chmod +X cv_bridge_demo.py

Ниже приведены команды для запуска драйвера и узлов. Запустите драйвер Kinect с помощью следующей команды:

$ roslaunch openni_launch openni.launch

Запустите узел с помощью следующей команды:

$ rosrun sample_opencv_pkg cv_bridge_demo.py

Ниже приведен скриншот вывода.

RGB, глубина и изображения края
RGB, глубина и изображения края

Согласование Orbbec Astra с ROS

Одной из альтернатив Kinect является Orbbec Astra. Для Astra доступны драйверы ROS. Рассмотрим настройку этого драйвера и получим изображение, глубину и облако точек от этого датчика.

Установка драйвера Astra-ROS

Полные инструкции по настройке драйвера Astra-ROS в Ubuntu приведены на https://github.com/orbbec/ros_astra_camera и http://wiki.ros.org/Sensors/OrbbecAstra. После установки драйвер запускается следующей командой:

$ roslaunch astra_launch astra.launch

Драйвер Astra также можно установить из репозитория пакетов ROS. Ниже представлена команда для установки этих пакетов:

$ sudo apt-get install ros-kinetic-astra-camera
$ sudo apt-get install ros-kinetic-astra-launch

После установки этих пакетов необходимо обнаружить и идентифицировать камеру, чтобы с устройством можно было работать. Как это сделать, описано в http://wiki.ros.org/astra_camera. Темы ROS, созданные с помощью этого драйвера, можно проверить с помощью команды rostopic в терминале. Кроме того, для обработки изображений мы можем использовать тот же код Python, что был рассмотрен в предыдущей части статьи.

Работа с облаками точек с помощью Kinect, ROS, OpenNI и PCL

Трехмерное облако точек – это способ представления 3D-среды и 3D-объектов в виде геометрических координат по осям x, y и z. Мы можем получить облако точек из различных источников: облако точек можно создать программным способом либо синтезировать из данных датчика глубины или лазерных сканеров.

PCL изначально поддерживает интерфейсы OpenNI 3D. Таким образом, он может получать и обрабатывать данные с таких устройств, как 3D-камеры Prime Sensor, Microsoft Kinect или Asus Xtion Pro.

PCL включен в полную настольную установку ROS. Давайте посмотрим, как создать и сделать видимым облако точек в RViz, инструменте визуализации данных в ROS.

Открытие устройства и создание облака точек

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

$ roslaunch openni_launch openni.launch

Эта команда активирует драйвер Kinect и обрабатывает необработанные данные в удобные выходные данные, такие как облако точек.

При использовании Orbbec Astra применяйте следующую команду:

$ roslaunch astra_launch astra.launch

Для просмотра облаков точек мы воспользуемся инструментом 3D-отображения RViz. Для запуска RViz воспользуйтесь командой

$ rosrun rviz rviz

В левой части окна RViz отображается панель для настройки глобальных параметров. Настройте в RViz параметры Fixed Frame – camera_link. Параметр camera_link находится в верхней части панели Global Options.

На левой боковой панели Global Options нажмите кнопку Add (Добавить) и выберите опцию отображения PointCloud2. Установите тему в каталог /camera/depth/points (это тема для Kinect; она будет отличаться для других датчиков).

Измените настройки Color Transformer of PointCloud2 на AxisColor.

Все настройки показаны на следующем рисунке, в левой части окна RViz и обведены красными прямоугольниками. Кроме настроек, на следующем рисунке показан снимок экрана данных облака точек RViz. Вы можете видеть, что близлежащие объекты отмечены красным цветом, а самые дальние объекты – фиолетовым и синим. Объекты, установленные перед Kinect, оказались кубом и цилиндром.

Отображение данных облака точек в Rviz
Отображение данных облака точек в Rviz

Преобразование данных облака точек в данные лазерного сканирования

Мы в этом роботе используем Astra, чтобы дублировать функцию дорогостоящего лазерного сканера. Данные облака точек с помощью пакета ROS обрабатываются и преобразуются в эквивалент данных лазерного сканера depthimage_to_laserscan (http://wiki.ros.org/depthimage_to_laserscan).

Вы можете установить этот пакет из исходного кода или использовать менеджер пакетов Ubuntu. Вот команда для установки этого пакета из менеджера пакетов Ubuntu:

$ sudo apt-get install ros-<version>-depthimage-to-laserscan

Функция этого пакета состоит в том, чтобы нарезать разделы данных облака точек и преобразовать их в эквивалентный тип данных для лазерного сканирования. Тип сообщения Ros sensor_msgs/LaserScan используется для публикации данных лазерного сканирования. Пакет depthimage_to_laserscan выполнит это преобразование и сымитирует данные лазерного сканера. Формируемые данные лазерного сканирования можно увидеть в RViz. Чтобы запустить преобразование, мы должны запустить конвертор nodelets, который выполнит эту операцию. Это мы должны указать в нашем файле запуска.

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

<!— Fake laser —>
<node pkg=»nodelet» type=»nodelet»
name=»laserscan_nodelet_manager» args=»manager»/> <node pkg=»nodelet» type=»nodelet»
name=»depthimage_to_laserscan»
args=»load depthimage_to_laserscan/DepthImageToLaserScanNodelet
laserscan_nodelet_manager»>
<param name=»scan_height» value=»10″/>
<param name=»output_frame_id» value=»/camera_depth_frame»/>
<param name=»range_min» value=»0.45″/>
<remap from=»image» to=»/camera/depth/image_raw»/>
<remap from=»scan» to=»/scan»/>
</node>

Тему изображения глубины можно изменить в каждом датчике. Для этого необходимо изменить название темы в соответствии с темой изображения глубины.

Наряду с запуском конвертера nodelet нам для более качественного преобразования нужно настроить некоторые параметры nodelet. Чтобы получить более подробное описание каждого настраиваемого параметра, (http://wiki.ros.org/depthimage_to_laserscan).

Ниже показано отображение данных предыдущего лазерного сканирования. Для просмотра результата лазерного сканирования добавьте опцию LaserScan. Эта операция похожа на то, как мы добавляли опцию PointCloud2 и изменяли значение темы LaserScan на /sca.

Отображение данных лазерного сканирования в RViz
Отображение данных лазерного сканирования в RViz

Работа в SLAM с помощью ROS и Kinect

Основная цель установки и настройки в нашем роботе датчиков технического зрения — самостоятельная навигация, обнаружение и обход препятствий. SLAM – это используемый в мобильных роботах алгоритм для создания карты неизвестной среды или обновления ранее созданной карты с помощью отслеживания текущего местоположения робота.

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

Картографирование позволяет сформировать профиль препятствий вокруг робота. Благодаря картографированию робот поймет, как выглядит мир. Локализация – это процесс оценки положения робота на создаваемой нами карте.

SLAM извлекает данные из различных датчиков и использует их для построения карт. Датчик зрения 2D/3D-формата можно использовать как входной сигнал для SLAM. 2D-датчики зрения, как и лазерные дальномеры и 3D-датчики, такие как Kinect, в основном используются в качестве входных данных SLAMалгоритма.

Название библиотеки SLAM – OpenSlam (http://openslam.org/gmapping.html). Эта библиотека интегрирована в ROS как пакет под названием gmapping. Пакет gmapping предоставляет узел для выполнения лазерной обработки SLAM и называется slam_gmapping. Этот пакет поможет создать двухмерную карту данных лазерного сканирования и расположить собранные мобильным роботом данные.

Пакет gmapping доступен на http://wiki.ros.org/gmapping.

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

Узел slam_gmapping получает сообщения от sensor_msgs/LaserScan и nav_msgs/Odometry и создает карту (nav_msgs/OccupancyGrid). Сгенерированную карту можно получить с помощью темы или сервиса ROS.

Чтобы применить SLAM в нашем Chefbot, мы использовали следующий файл запуска. Этот файл запускает узел slam_gmapping и содержит необходимые параметры для начала отображения среды робота:

$ rosrun gmapping slam_gmapping scan:=base_scan

Итоги

В этой статье мы рассмотрели датчики зрения, которые будут использоваться в нашем роботе. Мы обсуждали использование Kinect, OpenCV, OpenNI и PCL в роботе и их применение. Мы также рассмотрели роль датчиков зрения в навигации робота, популярный метод SLAM и применение его в ROS. В следующей статье «Согласование датчиков зрения с ROS» мы рассмотрим полное взаимодействие робота и научимся выполнять автономную навигацию нашего Chefbot.

За основу данной статьи взята книга Д. Лентина «Изучение робототехники с использованием Python» 

С Уважением, МониторБанк

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *