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

    Это продолжение повествования об автономном дроне. В первой части говорилось про 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 и медиасервера для управления несколькими дронами одновременно.
    • Резервные каналы связи и системы спасения дронов
    • Машинное зрение и лидары для избежания столкновения с препятствиями

    Продолжение следует…
    • +23
    • 6,1k
    • 8
    Поделиться публикацией
    Похожие публикации
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 8
    • 0
      А теперь то же самое только с перламутровыми пуговицами только с защищенным каналом(ми) связи, распознаванием местности и кое-какой автономностью, бо желающих создать помеху много развелось.
      • 0
        Об этом тоже будет. От простого к сложному для лучшего понимания.
      • 0
        Большое спасибо, ждем про автоматическую смену батареек.
        А передвижной пункт зарядки не задумывался?
        • 0
          В принципе, посадочный бокс можно поставить как на крышу здания, так и на автоприцеп. Запитывать можно от авто или отдельного аккумулятора. А вот такой пункт зарядки пока не задумывался:
        • 0
          Можно проще — сажаем по GPS где попало, и подбираем машинкой
          • 0
            О! Клево, коллега! Будет интересно посмотреть, каким путем пойдете дальше!
            Из рекомендаций — замените VLC на земле гстримером. Задержка меньше будет, он гибче. У нас на 7500 километров (Москва-Китай) около 0,4 секунды было, а Москва-Питер 0,2 примерно. В постах у habr.com/users/Gol можете глянуть историю наших экспериментов.
            • +1
              Спасибо. За описание ваших экспериментов тоже спасибо, я с ними знаком. Так как камер несколько (на борту и на земле), то в итоговом варианте я остановился на готовом медиасервере, который может принимать и отдавать видео в любом виде и встраиваться в web-based GCS. Я об этом еще напишу.
            • 0
              Ожидаем продолжения! Обычно, весь энтузиазм кончается на «скворечнике» :)

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

              Самое читаемое