Оновлення MAVLink для Ada.#
Анотація
MAVLink — це дуже легкий протокол обміну повідомленнями з дронами. У цій статті представлено значне оновлення бібліотеки MAVLink для Ada, що забезпечує підтримку рекомендованої версії MAVLink 2.0. Основні цілі оновлення включають підвищення надійності, безпеки та зменшення розміру об'єктного коду, що робить бібліотеку придатною для архітектур з обмеженими ресурсами. Детально описано впровадження нового підходу до використання можливостей Ada 2022 для створення розширюваних перелічуваних типів, що покращує гнучкість протоколу та безпеку використання. Практичним результатом оновлення є створення пакетів Alire для діалектів common та ardupilotmega в обох версіях MAVLink, що сприяє зручності застосування та подальшому розширенню бібліотеки, роблячи її сучасною та ефективною для розробників дронів та вбудованих систем.
MAVLink — це дуже легкий протокол обміну повідомленнями з дронами та між їхніми бортовими компонентами. Опис протоколу подано у вигляді XML-файлів, які спеціальний генератор перетворює на бібліотеки для різних мов програмування. Підтримку мови Ada додав Андрій Філь у листопаді 2022 року. Зараз ми готуємо значне оновлення цієї бібліотеки, тож у цій статті ми хочемо підсумувати зміни та нововведення. Метою нашого оновлення є
підтримка версії MAVLink 2.0, яка зараз є рекомендованую до використання
забезпечити більш надійне та безпечне використання бібліотеки
зменшити розмір об'єктного коду бібліотеки
Формат повідомлень у MAVLink 2 зазнав змін, зокрема код повідомлення зараз має довжину 24 бита замість 8, з'явився не обов'язковий підпис повідомлень та поля розширення. Тож деякі прийоми генерації кода довелося змінити. Зокрема немає можливості використовувати код типу повідомлення як індекс масиву бо значень дуже багато.
У цьому оновленні ми вирішили відмовитись від використання тегових типів для кодування повідомлень. Для цього є декілька причин
службовий код для підтримки тегових типів доволі об’ємний та складає значну частину коду бібліотеки, що унеможливлює її використання на архітектурах з обмеженими ресурсами.
загальна частина усіх повідомлень містить лише службові поля транспортного рівня (довжину повідомлення, послідовний номер, код відправника та інше). При створенні повідомлення користувачу немає сенсу їх задавати. Тож ми вирішили відділити їх від інформаційних полів.
Протокол MAVLink надає можливість розробнику розширювати його в деяких місцях. Щоб забезпечити безвідмовну роботу при будь яких вхідних даних ми змінили засіб методу кодування типів компонент повідомлень:
при кодуванні бітових структур (bitmask) ми додаємо додаткові поля для представлення усіх бітів у слові, полуслові або байті. Це дає змогу кодувати/декодувати додаткові біти навіть коли вони не використовуються у стандартних повідомленнях.
схожа проблема є для перелічуваних типів (enumerations), коли розробники додають нові значення до стандартного переліку. Як приклад це трапляється коли вводяться нові команди, або стани системи. Якщо використовувати для представлення цих типів перелічувані типи Ada, то додаткові значення призведуть до виникнення винятку Constraint_Error. Для роботи з цим ми використали нові можливості Ada 2022, щоб зробити “перелічувані типи здатними до розширення” які розглянемо докладніше далі.
У деяких випадках MAVLink використовує значення NaN (not a number) у полях з рухомою комою. Ada не підтримує такі значення, тож їх використання також призведе до появи винятку. Щоб попередити розробника про можливість використання NaN та інших не стандартних значень ми замінили Short_Float тип на приватний тип Raw_Float, який має операції перевірки на дійсність значення та перетворення до Interfaces.IEEE_Float_32 і назад.
Як і в попередній версії ми надаємо тип Connection який відповідає за декодування при прийомі повідомлень, та кодування при відправці. Але як засвідчила практика ці операції не є насправді симетричними. Наприклад при відправці Connection зобов'язаний проставити послідовний номер повідомлення у розрізі System_Id/Component Id. Тож система має створювати окремі об'єкти Connection для кожной пари значень System_Id/Component Id. Тоді як прийом може використовувати один такий об'єкт для усіх наявних систем та компонент. Тож ми впровадили додаткові окремі типи In_Connection/Out_Connection для роботи лише в одному напрямку.
Перелічувані типи здатний до розширення#
Перелічувані типи Ada мають корисні властивості, такі як статичні значення літералів, здатність літералів до перевантаження, заздалегідь відомий перелік значень, зручні операції перетворення на рядок (строку), тощо. Це дозволяє зручно та безпечно їх використовувати, наприклад сумісно з case-інструкціями та case-виразами, як індекси масивів, використовувати літерали як зазначення дискримінантів у агрегатах та в інших місцях де потрібно статичне значення. Проте інколи потрібно мати можливість додавати нові значення до типу, а це неможливо для перелічуваних типів. Як приклад таких випадків - росширення протоколу, як от MAVLink чи Protobuf. На щастя з новими можливостями Ada 2022 ми можемо цього досягнути, хоче це потребує явного кодування. Як приклад розглянемо тип Safety_Switch_State який має значення Safe та Dangerous з кодами 0 та 1 відповідно. Тож спочатку ми оголошуємо цілочисельний тип шириной в один байт який відповідає визначенню цього типу в MAVLink:
type Safety_Switch_State is new Interfaces.Unsigned_8;
Замість літералів ми використовуємо статичні функції:
function Safe return Safety_Switch_State is (0)
with Static;
function Dangerous return Safety_Switch_State is (1)
with Static;
Хоча оголошені константи теж працюють як статичні значення, їх використання не таке зручне як функції, бо вони не дозволяють перегрузку імен, а це важливо у випадку з генерованим кодом, де можливі кофлікти імен. Завдяки перегрузці імен ми можемо позбутися спільних префіксів (наприклад Safety_Switch_State_Safe) які використовують у Сі щоб забезпечити унікальність імен. Тож ми використовуємо коротші та більш зручні імена.
Щоб мати підтип лише з цих значень оголосимо його додавши суфікс Well_Known
subtype Safety_Switch_State_Well_Known is Safety_Switch_State
with Static_Predicate => Safety_Switch_State_Well_Known in
Safe .. Dangerous;
Оскільки ми вказали Static_Predicate компілятор знає вичерпний перелік значень цього підтипу під час компіляції та може виконувати відповідні перевірки на вичерпність. Наприклад ми маємо змогу оголосити функцію перетворення на рядок:
function Well_Known_Image
(Value : Safety_Switch_State_Well_Known) return String is
(case Value is
when Safe => "Safe",
when Dangerous => "Dangerous")
with Static;
Там де нам потрібно мати розширений набір значень, наприклад при прийомі повідомлень ми використовуємо Safety_Switch_State тип. А щоб переконатися, що прийняте значення нам відоме ми використовуємо перевірку “Value in Safety_Switch_State_Well_Known”. Аналогічно ми можемо оголосити функцію Succ для пошуку наступного значення та реалізувати за її допомоги ітерації, але для MAVLink протоколу це не має застосування, тож ми цього не робимо.
Пакети Alire#
Наразі ми створили пакети для двох найбільш цікавих з нашої точки зору діалектів MAVLink - common та ardupilotmega. Кожен з них має дві версіі - MAVLink 1 та MAVLink 2. Тож вийшло 4 пакети:
mavlink_commonmavlink_common_v2mavlink_ardupilotmegamavlink_ardupilotmega_v2
Це дасть змогу застосовувати їх у потрібних комбінаціях. Додаткові діалекти могуть бути додані при потребі.
Висновок#
Це оновлення бібліотеки MAVLink для Ada є значним кроком уперед, забезпечуючи підтримку рекомендованої версії MAVLink 2.0. Основні цілі оновлення — підвищення надійності та безпеки використання бібліотеки, а також зменшення розміру об'єктного коду, що робить її більш придатною для архітектур з обмеженими ресурсами. Впровадження нових підходів до кодування повідомлень, відмова від тегових типів та використання можливостей Ada 2022 для розширюваних перелічуваних типів значно покращують гнучкість та стійкість протоколу. Розділення типів In_Connection та Out_Connection оптимізує роботу з потоками даних. Створення пакетів Alire для діалектів common та ardupilotmega в обох версіях MAVLink (1 та 2) забезпечує зручність застосування та подальшого розширення. Ці зміни роблять бібліотеку MAVLink для Ada сучасною, ефективною та адаптованою до потреб розробників дронів та вбудованих систем.