DIY автономный дрон с управлением через интернет. Часть 2 про ПО

в 15:28, , рубрики: ArduPilot, diy или сделай сам, navio, Raspberry Pi, БПЛА, дрон, коптер, мультикоптеры, Разработка робототехники, робототехника

Это продолжение повествования об автономном дроне. В первой части говорилось про hardware, в этой речь пойдет про software. Для начала небольшой ликбез про взаимодействие оператора с коптером. Вот типичная схема у большинства самосборных дронов:

image

А вот схема у продвинутых дронов:

image

Так работают игрушечные дроны, которые управляются со смартфона:

image

Управлять дроном через интернет можно так (при наличии сим-карты со статическим IP-адресом):

image

Или так, если IP-адрес динамический:

image

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

image

Далее я буду описывать процесс настройки полетного контроллера Emlid Navio 2 и микрокомпьютера Raspberry Pi 3.

image
Но, с небольшими модификациями, эти настройки подойдут для любого полетного контроллера, с которым можно общаться по протоколу MAVLink в связке с любым компьютером на ОС семейства Linux.

image

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

ПО для управления дроном на ПК и планшетах

Для управления БПЛА используются специальные программы GCS (Ground Control Station). Далее по тексту я буду использовать эту аббревиатуру. Мне по душе пришлась QGroundControl, мультиплатформенная (Windows, Linux, MacOS, iOS, Android) GCS с открытым исходным кодом, которая стала частью проекта DroneCode. Но есть и альтернативы, бесплатные и коммерческие: APM Planner, MissionPlanner, UgCS, LibrePilot, OpenPilot, Tower (DroidPlanner) для Android, MAVPilot (iOS), SidePilot (iOS). А также консольная MAVProxy.

Установка образа ОС на SD-карту

Для нормальной работы автопилота крайне рекомендуется использовать “быстрые” SD-карты (класс 10). Медленные карты памяти не успевают сохранять логи автопилота даже на небольшой частоте, в результате чего они получаются кривыми или вообще не пишутся. Свидетельством этого может быть ошибка “No IO heartbeat”, которую можно наблюдать в консоли MAVLink (как смотреть консоль MAVLink описано ниже). При покупке смотрите на возможность писать 4К видео: скорее всего это будет быстрая SD. К сожалению, я об этом узнал после падения дрона, когда нужно было проанализировать логи и узнать причину. Логи оказались нечитаемы для нескольких GCS. Причина отключения моторов в полете оказалась банальна: я забыл подправить в настройках значение минимального напряжения на аккумуляторе для срабатывания failsafe.

Итак, скачиваем готовый образ Raspbian Stretch с предустановленными Ardupilot и ROS от Emlid со страницы оригинальной инструкции. И пишем его на карту памяти с помощью Etcher или любой подобной программы.

Чтобы сразу после включения Raspberry соединялся с вашей WiFi сетью, необходимо отредактировать файл wpa_supplicant.conf в корне SD-карты. В нем должны быть такие строки:

network={
    ssid="название_wifi_сети"
    psk="пароль_wifi_сети"
}

Можно настроить и без WiFi, подключив одноплатник к роутеру Ethernet-кабелем. Теперь вынимаем SD-карту из ПК, вставляем ее в Raspberry и включаем питание. Через полминуты он должен появиться в админке роутера на странице подключенных устройств (хостнейм navio).

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

Открываем SSH-клиент и соединяемся с Raspberry (локальный IP-адрес navio вместо RASPBERRY_IP_ADDRESS):

ssh pi@RASPBERRY_IP_ADDRESS

Стандартный пароль: raspberry. В первую очередь необходимо расширить файловую систему ОС на весь объем SD-карты:

sudo raspi-config --expand-rootfs

и перегрузиться:

sudo reboot

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

sudo apt-get update && sudo apt-get dist-upgrade -y

Устанавливаем дополнительные пакеты:

sudo apt-get install autoconf automake libtool pkg-config libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libraspberrypi-dev gstreamer1.0-tools gstreamer1.0-plugins-good gstreamer1.0-plugins-bad

и компилируем обертку gst-rpicamsrc для gstreamer и родной камеры Raspicam:

git clone https://github.com/thaytan/gst-rpicamsrc.git rpicamsrc
cd rpicamsrc
chmod +x autogen.sh
./autogen.sh --prefix=/usr --libdir=/usr/lib/arm-linux-gnueabihf/
make
sudo make install

Проверим работает ли камера (создается видеофайл test.h264):

gst-launch-1.0 rpicamsrc bitrate=1000000 ! filesink location=test.h264

Если gstreamer запустился, подождите пару секунд, чтобы записалось видео. Прервать процесс можно клавишами Ctrl+C. Если видео есть, значит камера работает.

Настройка и запуск Ardupilot

Релизы новых версий Ardupilot немного запаздывают в сборке от Emlid. Если необходимый функционал доступен в самой последней версии, то установить ее из исходников можно по этой инструкции.

Разработчики Navio добавили в свою сборку простую и удобную утилиту Emlid tool для проверки датчиков и настройки Ardupilot. Сначала проверим, видит ли Raspberry контроллер Navio:

emlidtool info

Если в ответ на эту команду выдает что-то вроде:

Vendor: Emlid Limited
Product: Navio 2
Issue: Emlid 2018-06-05 831f3b08594f2da17dccae980a2e3659115ef71f
Kernel: 4.14.34-emlid-v7+
RCIO firmware: 0xcaec2284

значит видит. Проверим состояние датчиков (покажет список и состояние):

emlidtool test

и драйвера ШИМ-контроллера в ядре Linux:

cat /sys/kernel/rcio/status/alive

0 = не работает, 1 = работает.

Прошивка ШИМ-контроллера обновляется так:

sudo emlidtool rcio update

Теперь настроим Ardupilot:

sudo emlidtool ardupilot

В терминале откроется текстовый GUI с пошаговыми менюшками. Выбираем copter последней версии, тип arducopter, автозапуск при включении (On boot: enable), старт после настройки (Ardupilot: start).

image

Выходим через пункт меню Quit.

Проверим запустился ли Ardupilot:

sudo systemctl status arducopter

Обратите внимание, файл запуска в systemd называется arducopter, так как настроен был вариант copter.

Теперь нужно настроить Ardupilot так, чтобы он отправлял нам телеметрию. Для этого отредактируем файл конфигурации:

sudo nano /etc/default/arducopter 

В нем должны быть такие строки:

TELEM1="-A udp:127.0.0.1:14550"
ARDUPILOT_OPTS="$TELEM1"

Сохраняем файл (Ctrl+X, затем Y) и перезапускаем Ardupilot:

sudo systemctl daemon-reload
sudo systemctl restart arducopter

Проверить состояние процесса Ardupilot можно такой командой:

sudo systemctl status arducopter

С такими настройками Ardupilot будет транслировать телеметрию (пакеты MAVLink) в локальный UDP-порт 14550. Далее, скрипт MAVProxy (описание ниже) будет забирать оттуда телеметрию и передавать в GCS или скрипт, а также отправлять в обратном направлении пакеты с командами.

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

image

Однако, такой подход оправдан, если данные телеметрии больше нигде не используются и у устройства с GCS статический IP адрес. Иначе каждый раз в настройках Ardupilot придется прописывать новый. Чтобы общаться с автопилотом по TCP могли одновременно несколько GCS с динамическими адресами и еще какие-нибудь скрипты на самом бортовом компьютере, удобнее использовать MAVProxy.

image

Этот скрипт (написан на Python) может получать пакеты MAVLink на локальный UDP-адрес и ретранслировать их на несколько локальных или удаленных IP-адресов как по UDP, так и по TCP. Пакеты передаются в обоих направлениях Ardupilot ⇔ GCS. Кроме того, MAVProxy представляет из себя полноценную GCS, но с текстовым интерфейсом.

MAVProxy

MAVProxy уже установлен в образе Navio. Его также можно установить и на ПК (Windows, Linux, MacOS) для дальнейшего общения с автопилотом в консольном режиме.

Убедившись, что Ardupilot работает, запустим на Raspberry скрипт MAVProxy такой командой:

mavproxy.py --master=udp:127.0.0.1:14550

Параметр --master=udp:127.0.0.1:14550 задает для скрипта источник данных. Это локальный UDP-порт, который был прописан в файле конфигурации Ardupilot. После запуска команды, MAVProxy соединиться с этим портом и выведет на экран сообщения автопилота, примерно как у меня:

pi@navio:~ $ mavproxy.py --master=udp:127.0.0.1:14550
Connect udp:127.0.0.1:14550 source_system=255
Failed to load module: No module named adsb. Use 'set moddebug 3' in the MAVProxy console to enable traceback
Log Directory: 
Telemetry log: mav.tlog
Waiting for heartbeat from 127.0.0.1:14550
 MAV> online system 1
STABILIZE> Mode STABILIZE
fence breach
GPS lock at 0 meters
APM: APM:Copter V3.5.5 (88a1ecdd)
APM: Frame: UNKNOWN
APM: PreArm: RC Roll not configured
APM: PreArm: Compass not calibrated
APM: PreArm: 3D Accel calibration needed
APM: PreArm: check firmware or FRAME_CLASS
APM: PreArm: Throttle below Failsafe

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

arm throttle
takeoff 20

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

Установка связи с дроном в локальной сети

Остановим скрипт (Ctrl+C) и снова запустим его в таком виде:

mavproxy.py --master=udp:127.0.0.1:14550 --out=tcpin:0.0.0.0:5762

С дополнительным параметром --out=tcpin:0.0.0.0:5762 MAVProxy будет слушать порт 5762 на входящие TCP соединения от GCS. Как только GCS соединиться, пакеты с данными начнут перемещаться между дроном и GCS. Попробуем подключиться с ПК:

image

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

image

image

Калибровка датчиков и настройка параметров автопилота

Калибровку автопилота можно сделать почти в любой GCS. В документации Ardupilot она описана во всех подробностях. Прежде всего устанавливаем тип рамы. У меня стандартная 4-х моторная компоновка, поэтому это Quad X.

image

Первый полет лучше все же сделать в ручном режиме. Подключаем и калибруем радиоуправление (приемник и передатчик).

image

Осталось откалибровать акселерометр и компас.

image

Для того, чтобы Ardupilot видел и учитывал данные с внешних датчиков, установим необходимые параметры:

Для PX4Flow (калибровка самого датчика и обновление прошивки)

FLOW_ENABLE = 1 (Enabled)
FLOW_ADDR = 0 (0 = вариант для стандартного адреса 0х42)

Для лазерного высотомера VL53L0X (инструкция)

RNGFND_TYPE = 16 (VL53L0X)
RNGFND_ORIENT = 25 (ориентация дальномера вниз)
RNGFND_ADDR = 41 (I2C-адрес в десятичном виде). Адрес датчика по-умолчанию 0x29, что в десятичном виде = 41.
RNGFND_SCALING = 1
RNGFND_MIN_CM = 5
RNGFND_MAX_CM = 120
RNGFND_GNDCLEAR = 15 (расстояние от датчика до поверхности, когда дрон стоит на земле)

Для IRLock (подробная инструкция, wiki IR-Lock)

PLND_ENABLED = 1
PLND_TYPE = 2
PLND_BUS = 1

Для сонара переднего обзора (инструкция)

RNGFND2_TYPE = 2 (MaxbotixI2C sonar)
RNGFND2_ORIENT = 0 (ориентация дальномера вперед)
RNGFND2_MAX_CM = 700 (макс дальность в сантиметрах)

Полный список параметров Ardupilot.

Теперь перезапускаем Ardupilot из меню GCS, снова соединяемся с бортом и открываем окошко MAVLink Inspector, чтобы увидеть данные с датчиков.

image

К сожалению, показания IR-Lock тут не видны, для анализа его работы придется взглянуть на бортовые логи. Как это сделать описано здесь.

Осталось настроить параметры безопасности и можно запускать дрон:

image

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

Видеотрансляция

Проверим как работает видеотрансляция в сети WiFi. Такой командой можно запустить видео в TCP-порт на Raspberry с использованием родной утилиты raspivid для камеры Raspicam:

raspivid -t 0 -hf -fps 25 -w 640 -h 480 -o - | gst-launch-1.0 fdsrc ! h264parse ! rtph264pay config-interval=1 pt=96 ! gdppay ! tcpserversink host=0.0.0.0 port=5001

А вот такой командой делается тоже самое, только с использованием ранее скомпилированной обертки rpi-camsrc для gstreamer:

gst-launch-1.0 rpicamsrc sensor-mode=4 ! h264parse ! rtph264pay config-interval=1 pt=96 ! gdppay ! tcpserversink host=0.0.0.0 port=5001

В обоих случаях, трансляция в формате h264 доступна по IP-адресу Raspberry на порту 5001.

Посмотреть ее можно запустив на своем ПК такую команду (должен быть установлен gstreamer), вместо RPI_ADDRESS указываем адрес Raspberry в сети:

gst-launch-1.0 -v tcpclientsrc host=RPI_ADDRESS port=5001  ! gdpdepay !  rtph264depay ! avdec_h264 ! videoconvert ! autovideosink sync=false

В результате должно открыться окошко с видео.

Практически в любую GCS встроен видеоплеер, который может показывать RTSP-видеопоток. Чтобы сделать из Raspberry RTSP-сервер можно использовать консольный плеер VLC. Установка:

sudo apt-get install vlc

Видеотрансляция запускается так:

raspivid -o - -t 0 -n -w 320 -h 240 -fps 25 | cvlc -vvv stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8554/live}' :demux=h264

Видео доступно по адресу (вместо RPI_ADDRESS, адрес Raspberry):

rtsp://RPI_ADDRESS:8554/live

Настройка GCS:

image

image

Адрес потока можно использовать для подключения нескольких плееров на разных устройствах, но, так как видеозахват и трансляция для Raspberry весьма трудоемкий процесс, то для нескольких потребителей видео лучше использовать внешний сервер (описание ниже).

Телеметрия через интернет

Чтобы GCS могла подключиться через интернет к дрону с динамическим IP-адресом, необходим промежуточный сервер со статическим IP, на котором будет запущен скрипт MAVProxy. Для этих целей я воспользовался арендой облачного сервера у одного из известных провайдеров. Для MAVProxy подойдет самая минимальная конфигурация, но так как у меня этот же сервер будет заниматься ретрансляцией видео, то я выбрал вариант с чуть большей памятью (одно ядро и 1Гб памяти, Ubuntu 18.04). Для минимальной задержки в прохождении данных между бортом и GCS, сервер должен располагаться в максимальной географической близости к дрону и GCS.

image

Устанавливаем MAVProxy на сервер. Сначала зависимости:

sudo apt-get install python-dev python-opencv python-wxgtk3.0 python-pip python-matplotlib python-pygame python-lxml python-yaml

а потом и сам скрипт через PIP:

sudo pip install MAVProxy

пропишем путь:

echo "export PATH=$PATH:$HOME/.local/bin" >> ~/.bashrc

и запустим скрипт с такими параметрами:

mavproxy.py --master=udp:0.0.0.0:15001 --out=tcpin:0.0.0.0:15002 

MAVProxy слушает порт 15001 на входящие пакеты телеметрии от дрона по протоколу UDP, а порт 15002 на входящее TCP-соединение от GCS.

Запустим MAVProxy на Raspberry еще с одним параметром, чтобы телеметрия транслировалась еще и на сервер (вместо SERVER_IP адрес своего сервера):

mavproxy.py --master=udp:127.0.0.1:14550 --out=tcpin:0.0.0.0:5762 --out=udpout:SERVER_IP:15001

После старта скрипта на бортовом компьютере, в консоли сервера появятся сообщения от автопилота. Как уже говорилось выше, MAVProxy представляет из себя полноценную GCS с текстовым интерфейсом и в таком состоянии уже можно редактировать параметры и управлять дроном посредством команд в консоли сервера.

Подключим GCS на ПК или планшете к серверу. Настройки соединения такие же как и для локальной сети, только вместо IP-адреса Raspberry указываем адрес сервера и порт 15002.

image

Теперь можно подключить 4G USB-модем к Raspberry и оценить с какой задержкой реагирует авиагоризонт на экране.

Видео через интернет

image

Для ретрансляции видео установим на сервер VLC плеер:

sudo apt-get install vlc

После установки, запустим его как ретранслятор c UDP порта 5001 в RTSP канал SERVER_IP:8554/live:

cvlc -vvv udp://@:5001 --sout '#rtp{sdp=rtsp://:8554/live}' :demux=h264

На борту запустим видеотрансляцию с камеры на сервер по UDP (вместо SERVER_IP адрес сервера):

gst-launch-1.0 rpicamsrc bitrate=1000000 ! video/x-h264,width=640,height=480,framerate=25/1 ! h264parse  ! udpsink host=SERVER_IP port=5001

Адрес потока теперь можно использовать как источник видео в настройках GCS или открыть в любом плеере, поддерживающим этот протокол.

Теперь можно спланировать маршрут полета и запустить дрон через интернет, предварительно его включив, например, с помощью помощника по телефону.

Очевидно, что из-за относительно большого времени путешествия видео и телеметрии по сети, такой способ вряд ли подойдет для FPV-полетов в ручном режиме между препятствиями.

Темы для последующих публикаций:

  • Варианты автоматической зарядки дрона в своем скворечнике и на каком из них остановился я.
  • Реализация web-based GCS с помощью MAVProxy, NodeJS, socket.io и медиасервера для управления несколькими дронами одновременно.
  • Резервные каналы связи и системы спасения дронов
  • Машинное зрение и лидары для избежания столкновения с препятствиями

Продолжение следует…

Автор: nee77

Источник


* - обязательные к заполнению поля