СПО пульта управления БПЛА - DRONE520/DRONE520-main GitHub Wiki
QGroundControl - PuppetMaster
В проекте DRONE520 в качестве пульта управления БПЛА используется приложение QGroundControl. Оно позволяет не только подавать команды дрону и получать данные телеметрии, но и загружать прошивку автопилота, задавать последовательность действий (миссии) и управлять в ручном режиме.
Цель
Модификация приложения QGroundControl под нужды проекта DRONE520: использование телеметрии для контроля лебёдки провода питания.
Для дрона предлагается вместо аккумуляторов использовать проводное питание. Чтобы предотвратить запутывание провода и предотвратимое зацепление за препятствия, а также контролировать натяжение, наземная станция должна иметь возможность управлять лебёдкой в соответствии с расстоянием до дрона. Эти данные телеметрии доступны в приложении QGroundControl для просмотра, но возможности их вывода и использования в других приложениях не предусмотрено. Следовательно, необходимо модифицировать программу; предпочтительно - интегрировать управление лебёдкой в функционал приложения.
Архитектура ПО
QGroundControl использует компонентно-ориентированную архитектуру с дополнительной абстракцией.
Поскольку приложение должно работать с прошивкой дрона, для которой определена только спецификация протокола связи MAVLink, привязываться к конкретной реализации прошивки недопустимо. Чтобы изолировать общий для всех прошивок код от специфического, используется модель плагинов. Это означает, что ядро программы общается с подключаемыми модулями через интерфейсы, которых для QGroundControl определено три вида:
- FirmwarePlugin инкапсулирует функционал прошивки;
- AutoPilotPlugin инкапсулирует функционал автопилота;
- QGCCorePlugin инкапсулирует функционал всех остальных модулей программы, не связанных с управляемым аппаратом.
Сборка ПО
Для разработки приложения используется IDE Qt Creator версии 4.
Чтобы собрать приложение, нужно загрузить его (Clone), открыть проект qgroundcontrol.pro в Qt Creator и произвести сборку проекта (Build). Собранное приложение будет помещено в подпапку staging папки сборки: ../build-qgroundcontrol-[Название комплекта сборки]-[Debug/Release]
.
После изменения структуры или файлов разметки интерфейса (QML) и перед началом сборки следует запустить скрипт custom/updateqrc.py
, чтобы зафиксировать эти изменения в файле ресурсов (custom/qgroundcontrol.qrc
).
Системные требования
Комплект сборки в Qt Creator - набор инструментов сборки, используемых в конкретном проекте. Комплект включает в себя указание на устройство сборки (в случае удалённой сборки), компилятор, отладчик, используемый профиль Qt, программу сборки CMake и утилиту QMake.
Комплект сборки для QGroundControl должен иметь следующие параметры:
- Профиль Qt: 5.15.2
-
- Дополнительная библиотека Qt Charts (поставляется с установщиком Qt)
- Платформа: amd64
- Компилятор:
-
- Для Windows: MSVC 2019 (устанавливается как часть Visual Studio 2019)
-
- Для Linux: GCC 5 или новее
Дополнительно - для использования скрипта обновления ресурсов: Python 3
Заметки о версировании
Поскольку этот проект является ответвлением оригинального, Github предоставляет возможность заполучить последние обновления (Fetch Upstream).
Для сборки необходимо наличие всех подмодулей! Использование: git clone --recursive
для полной загрузки или git submodule update --init --recursive
для уже загруженного проекта.
Больше информации о сборке проекта: https://dev.qgroundcontrol.com/master/en/getting_started/
Способы расширения функциональности
Плагины
Архитектура QGroundControl подразумевает использование плагинов для индивидуальной настройки приложения. Для отображения функций самого приложения QGroundControl, которые не связаны с транспортным средством, через стандартный интерфейс, используется интерфейс QGCCorePlugin. Затем плагин используется пользовательскими сборками для настройки набора функций QGroundControl в соответствии с их потребностями. Каждый плагин в проекте представлен отдельным файлом включения .pri
.
Для стандартизации и упрощения расширения функционала QGC использует систему фактов (Fact), каждый из которых представляет собой одно значение в системе. К факту привязан объект FactMetaData, хранящий детали о его смысле, предназначении и совместимости. Интерфейс Fact Control использует Fact и его FactMetaData, чтобы вывести информацию на экран пользователя. Самый простой способ получить информацию - воспользоваться функцией интерфейса прошивки getFact("factName").
Модификация интерфейса
Проект QGroundControl организован так, чтобы пользовательские сборки (custom) по умолчанию имели приоритет в процессе сборки приложения. Таким образом, для переопределения элементов интерфейса достаточно скопировать соответствующий исходный файл разметки (QML) и изменить его по своему усмотрению.
Например, такой код в custom/res/CustomFlyViewOverlay.qml
создаёт кнопку снизу слева на главном экране, нажатие на которую выводит в диалоговое окно (MessageDialog) координаты базы, текущее положение БПЛА и расстояние между этими двумя точками:
//-------------------------------------------------------------------------
//-- My button
Rectangle {
id: buttonHell
width: ScreenTools.defaultFontPixelHeight * 1.5
height: ScreenTools.defaultFontPixelHeight * 1.5
radius: 2
anchors.bottom: parent.bottom
anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * 1.5
anchors.left: parent.left
anchors.leftMargin: ScreenTools.defaultFontPixelHeight * 1.5
Button {
text: "Where"
anchors.centerIn: parent
onClicked: messageHell.open()
MessageDialog {
id: messageHell
x: 256
y: -512
title: qsTr("Vehicle position")
property var rtkSettings: QGroundControl.settingsManager.rtkSettings
property bool useFixedPosition: rtkSettings.useFixedBasePosition.rawValue
function vehiclePosition() {
var lat = _activeVehicle.gps.getFact("lat").rawValue;
var lon = _activeVehicle.gps.getFact("lon").rawValue;
return "Vehicle position: " + (lat < 0 ? -lat : lat) + "\u00b0 " + (lat < 0 ? 'S' : 'N') + ' ' + (lon < 0 ? -lon : lon) + "\u00b0 " + (lon < 0 ? 'W' : 'E')
+ "; alt. " + _activeVehicle.altitudeRelative.rawValue + ' ' + _activeVehicle.altitudeRelative.units;
}
function ditoBase(bLat, bLon, bAlt) {
const degToMeters = 6.371e6 * Math.PI / 180;
var y = (bLat - _activeVehicle.gps.getFact("lat").rawValue) * degToMeters;
var x = (bLon - _activeVehicle.gps.getFact("lon").rawValue) * Math.cos(bLat) * degToMeters;
var z = bAlt - _activeVehicle.altitudeRelative.rawValue;
return "Distance to base: " + Math.sqrt(x * x + y * y + z * z) + " m";
}
function hellString() {
var basePosition = "";
var distanceToBase = "Distance unavaliable";
if (useFixedPosition) {
var bLatF = rtkSettings.fixedBasePositionLatitude.rawValue;
var bLonF = rtkSettings.fixedBasePositionLongitude.rawValue;
var bAltF = rtkSettings.fixedBasePositionAltitude.rawValue;
basePosition = "Using fixed base position\nBase position: "
+ (bLatF < 0 ? -bLatF : bLatF) + "\u00b0 " + (bLatF < 0 ? 'S' : 'N') + ' '
+ (bLonF < 0 ? -bLonF : bLonF) + "\u00b0 " + (bLonF < 0 ? 'W' : 'E')
+ "; alt. " + bAltF + ' ' + _activeVehicle.altitudeRelative.units;
distanceToBase = ditoBase(bLatF, bLonF, bAltF);
}
else if (!QGroundControl.gpsRtk.active.rawValue) basePosition = "RTK GPS is inactive!";
else if (!QGroundControl.gpsRtk.connected.rawValue) basePosition = "RTK GPS is disconnected!";
else if (!QGroundControl.gpsRtk.valid.rawValue) basePosition = "RTK GPS data is invalid!";
else {
var bLatD = QGroundControl.gpsRtk.currentLatitude.rawValue;
var bLonD = QGroundControl.gpsRtk.currentLongitude.rawValue;
var bAltD = QGroundControl.gpsRtk.currentAltitude.rawValue;
basePosition = "Using GPS RTK survey\nBase position: "
+ (bLatD < 0 ? -bLatD : bLatD) + "\u00b0 " + (bLatD < 0 ? 'S' : 'N') + ' '
+ (bLonD < 0 ? -bLonD : bLonD) + "\u00b0 " + (bLonD < 0 ? 'W' : 'E')
+ "; alt. " + bAltD + ' ' + _activeVehicle.altitudeRelative.units;
distanceToBase = ditoBase(bLatD, bLonD, bAltD);
}
return basePosition + "\n" + (_activeVehicle ? vehiclePosition() + "\n" + distanceToBase : "\nNo vehicle was found!");
}
text: qsTr(hellString())
standardButtons: StandardButton.Ok
onAccepted: messageHell.close()
}
}
}
Как можно заметить, данные о БПЛА система получает методом getFact
объекта _activeVehicle
, который был получен заранее как QGroundControl.multiVehicleManager.activeVehicle
. Так же и координаты базовой станции: данные о её положении содержатся в настройках приложения в разделе RTK GPS (QGroundControl.settingsManager.rtkSettings
). Значение факта получается как rawValue
.
Рабочее устройство
В качестве лебёдки предлагается использовать мотор-редуктор IG-42M (https://electroprivod.ru/ig-42gm.htm). При передаточном числе 504 и выше его крутящий момент достигает 30 кг•см с разумной скоростью вращения 13,5 об/мин.
Для управления мотором предлагается использовать контроллер BMSD (https://electroprivod.ru/bdc-driver_bmsd.htm). Регулировка скорости осуществляется с помощью встроенного в мотор энкодера на основе датчика Холла. Управление с компьютера осуществляется через интерфейс RS-485, который подключается через преобразователь NPort 5232 (https://moxa.pro/catalog/nport5232) в режиме Real COM к линии Ethernet. Таким образом, компьютер обменивается сообщениями с контроллером через виртуальный COM-порт.
Протокол обмена контроллера BMSD предполагает использование сообщений длиной 5 байтов.
Байты управляющего сообщения (от компьютера к контроллеру):
- Заголовок - байт всегда равен 0xE6;
- Адрес блока - устанавливается перед началом работы;
- Код команды - см. ниже;
- Данные - см. ниже;
- CRC - помехозащитный байт.
Не более чем через 50 мс после получения сообщения "опрос состояния" (0x50) контроллер отправляет ответное сообщение. Биты ответного сообщения (от контроллера к компьютеру):
- [0-7]. Адрес блока;
- [8]. Режим работы с датчиком Холла:
-
- 0 в асинхронном режиме (отсутствие импульсов от датчика Холла);
-
- 1 в синхронном режиме - автоматическая стабилизация скорости;
- [9]. Бит переполнения счётчика оборотов;
- [10]. Режим установки параметров:
-
- 0 - по умолчанию (ручная установка);
-
- 1 - с компьютера;
- [11]. Бит направления движения;
- [12-23]. Счётчик оборотов;
- [24-31]. Скорость вращения;
- [32-39]. CRC - помехозащитный байт.
В ответ на другие команды контроллер посылает сообщение длиной 5 байт:
- Адрес блока;
- Сообщение;
- Данные 1;
- Данные 2;
- CRC - помехозащитный байт.
Список команд, посылаемых от ПК, и ответов блока:
Команда | Ответ | ||||
---|---|---|---|---|---|
Команда | Код | Данные | Сообщение | Данные 1 | Данные 2 |
Установка адреса (только по адресу 0xFF) | 0xA0 | Новый адрес (0x00..0xFE) | 0xA0 | Новый адрес | 0x00 |
Отбой установки адреса (только по адресу 0xFF) | 0xA1 | Любые | --- | Ответ не посылается | --- |
Число импульсов Холла на один оборот | 0xA2 | Число (0x00..0xFF) | 0xA2 | 0x00 | Число |
Скорость, об./сек | 0xA3 | Скорость (0..250) | 0xA3 | 0x00 | Скорость |
Максимальная скорость | 0xA4 | Макс. скорость (0..250) | 0xA4 | 0x00 | Макс. скорость |
Ускорение | 0xA5 | Ускорение (1..24) | 0xA5 | 0x00 | Ускорение |
Торможение | 0xA6 | Торможение (1..24) | 0xA6 | 0x00 | Торможение |
Направление | 0xA7 | 0 или 1 | 0xA7 | 0x00 | Направление |
Вход в режим регулировки от ПК (запуск) | 0x51 | Любые | 0x51 | 0x00 | Любые |
Вход в дежурный режим (остановка) | 0x52 | Любые | 0x52 | 0x00 | Любые |
Заключение
Индивидуальная настройка приложений - важная часть их адаптации в собственный проект, поскольку это позволяет получить от готового продукта новый, ранее недоступный функционал, который нужен именно в этом проекте. Благодаря открытой (Open Source) природе и модульной структуре QGroundControl является отличным приложением для реализации расширенного функционала наземной станции, оставаясь при этом совместимым со стандартом прошивок автопилота MavLink.