Сегодня мы рассмотрим, как обнаружить с помощью камеры Raspberry PI красный шарик, и как начать наводить на него наш дрон.
 В предыдущих статьях мы подробно рассматривали запуск автономного виртуального и реального дрона. Настало время нашему дрону обрести реальную цель.
Целью будет, как мы упоминали, красный шарик. Программу для фильтра мы будем писать на Desktop – версии Raspbian. Поскольку для настройки фильтра мы заходим одновременно крутить настройки и видеть результат наших накруток.
На отдельную флешку поставим Desktop-ный Raspbian.
Для работы с десктопным Raspbian нужны отдельные монитор+клавиатура+мышь, подключенные к Raspberry, что не очень удобно. Но можно работать с десктопом headless-Raspberry и по сети, через VNC.
Для этого нужно: Для разработки фильтра на Питоне — поставим OpenCV: Простой способ и быстрый способ выделить цветной объект на картинке – перевести картинку в цветовое пространство HSV, а затем – отфильтровать по нужному диапазону Тона (Hue), Насыщенности (Saturation) и Яркости (value), с помощью cv2.inRange. За основу я брал вот этот пример. Особенность нашей задачи заключается в том, что шарик у нас – красный, а если мы внимательно посмотрим на шкалу Тона (HUE), то увидим, что красный цвет находится по её краям:
 Поэтому если фильтровать только один кусок диапазона – при изменении освещения шарик может «исчезать» из фильтра, что скажется отрицательно на целеустремлённости нашего дрона. Поэтому кроме H, S и V параметров добавим в наш фильтр флаг инверсии invert – чтобы иметь возможность отфильтровать всё кроме шарика, а затем просто инвертировать фильтр. Настройка фильтра на шарик выглядит примерно так: Получив фильтр, мы можем найти шарик на картинке фильтра с помощью функции выделения контура cv2.findContours. В нашей программе мы переберём все найденные контуры, выделим те, которые больше 10х10 точек, и выберем из них самый большой – это и будет искомый шарик. Если в камеру попало несколько объектов – для наведения мы используем ближайший, т.е. самый большой. Полезную информацию фильтра выведем на полученную картинку: нарисуем найденные контуры и обведём самый большой из них, выделим линиями его центр (куда нам лететь), выведем диаметр шарика в точках и посчитаем расстояние до него, угол отклонения по рысканью. Кроме того, в центре экрана я добавил «прицел» + посчитал и вывел частоту кадров – чтобы контролировать скорость работы нашего фильтра. Программа по картинке с камеры считает расстояние до шарика и углы по рысканью и тангажу, на которые шарик отклоняется от центра картинки камеры. Этой информации нам достаточно для наведения дрона на шарик. Дальше мы займёмся программой наведения. Разработанный функционал можно переносить на систему headless-Raspberry с установленным ROS. Мы создадим ROS-пакет baloon, который будет выполнять следующие функции: Перед созданием ROS-пакета – добавим в нашу программу-фильтр следующий функционал для работы в среде ROS: Можно запускать программу на выполнение с помощью обычного python baloon_pose_cv.py – но существует и более удобный способ – упаковать нужный нам функционал в пакет ROS, и настроить его автозапуск при старте системы. В сети довольно много уроков по созданию ROS-пакетов, поэтому я ограничусь перечнем нужных шагов. Создадим каталог рабочего пространства ROS для нашего пакета, и сам пакет ROS: Поместим в каталог ~/baloon_ws/src/baloon/src файлы, необходимые для запуска нашего пакета: Ниже приводим тексты каждого из файлов: После помещения файлов в каталог baloon_ws/src/baloon/src, нужно добавить аттрибут "исполняемый файл" (cmod +x) файлам baloon_pose_cv.py и baloon.service. Затем, в качестве первого теста, запускаем нашу ROS-ноду вручную: После запуска ноды мы можем наблюдать картинку нашего фильтра и шарика через веб-браузер:
 А также получить координаты обнаруженного шарика в топике /baloon_detector/twist: Остаётся добавить автозапуск нашей ноды при старте Raspberry.
Для этого создадим файл описания сервиса systemd baloon.service, следующего содержания: Файл ссылается на описание переменных среды roscore.env: Подключение и запуск сервиса осуществляется с помощью команд:  Теперь нода должна запускаться автоматически при старте Raspberry.
Остановить ноду можно командой sudo systemctl stop baloon, отменить автозапуск – sudo systemctl disable balloon. В результате наших действий мы получили «автоматический обнаруживатель» шариков, запускаемый при старте системы на бортовом компьютере.  В следующей части перейдём к финальному запуску самонаводящегося дрона. Исходный код программ выложен на Гитхабе.