ArduPilot jest rodziną autopilotów dla wielu klas pojazdów, a nie pojedynczym programem „do quadcoptera”. ArduCopter, ArduPlane, Rover, Sub i pozostałe aplikacje pojazdów korzystają ze wspólnej infrastruktury sprzętowej, estymacji, komunikacji, parametrów i logowania, lecz implementują odmienne tryby oraz prawa sterowania. Dla programisty najważniejsze jest rozdzielenie trzech rzeczy: kodu wspólnego w libraries/, kodu konkretnego pojazdu oraz opisu sprzętu, na którym firmware ma działać.

Mapa repozytorium i procesu startu#

W katalogach aplikacji pojazdów znajdują się punkty wejścia, harmonogramy zadań, tryby lotu i kod specyficzny dla danej dynamiki. Biblioteki AP_* realizują m.in. abstrakcję sensorów, AHRS/EKF, nawigację, miksowanie, łączność MAVLink, logowanie i obsługę pamięci parametrów. AP_HAL wyznacza granicę między logiką autopilota a systemem operacyjnym i peryferiami. Dzięki temu duża część tego samego kodu może działać na ChibiOS, w procesie SITL i na wybranych platformach linuksowych.

Schemat przepływu nie jest jednak prostym potokiem wywoływanym raz na próbkę:

sterowniki sensorów -> warstwa sensorów AP_* -> AHRS/EKF -> stan pojazdu
                                                        |
RC / misja / GCS -> tryb lotu -> generatory wartości zadanych -> regulatory
                                                        |
                         ograniczenia i alokacja -> wyjścia aktuatorów
                                                        |
                       AP_Logger, MAVLink, failsafe i monitoring

Sterownik może pracować asynchronicznie względem pętli sterowania, estimator może konsumować dane z kilku kolejek, a logger zapisuje podzbiór sygnałów z własnym budżetem czasu. Czytając kod, trzeba śledzić zarówno własność obiektu, jak i częstotliwość oraz kontekst wykonania. Sama nazwa metody update() nie mówi, czy wywołuje się ją przy każdej próbce IMU, w wolniejszym harmonogramie, czy tylko po zmianie stanu.

AP_HAL i opis płytki#

AP_HAL udostępnia wspólny interfejs dla UART, SPI, I²C, GPIO, magazynu, czasu, schedulerów i mechanizmów krytycznych. Nie usuwa jednak różnic sprzętowych. Opóźnienie transakcji SPI, dostępne kanały DMA, mapowanie przerwań, domeny zasilania i sposób resetu są cechami konkretnej płytki.

W portach ChibiOS istotne są pliki hwdef.dat oraz warianty bootloadera. Określają piny, magistrale, sensory pokładowe, wyjścia, zasoby pamięci i cechy targetu. Błąd w opisie sprzętu może wyglądać jak błąd algorytmu: zamienione osie IMU, konflikt timera, błędny chip-select albo brak sterowania linią zasilania sensora powodują objawy daleko od miejsca faktycznej usterki.

Przed dodaniem nowej płytki należy zbudować tabelę zasobów:

Zasób Pytanie projektowe Sposób weryfikacji
IMU która magistrala, orientacja, DRDY i redundancja? odczyt identyfikatora, log osi, test termiczny
wyjścia które timery i kanały obsługują protokół? test bez śmigieł, analiza przebiegu
UART poziomy, inwersja, DMA, przepływność licznik błędów i test obciążenia
pamięć flash, RAM, karta SD, FRAM raport rozmiaru, zapis i wymuszony reset
zasilanie które szyny są przełączane i monitorowane? brownout, restart peryferium, pomiar napięcia
watchdog kto go karmi i jaki reset pozostawia ślad? kontrolowane zawieszenie w stanowisku

Scheduler i budżet czasu#

ArduPilot używa harmonogramu z zadaniami o różnych częstotliwościach i deklarowanym budżecie wykonania. Zadanie sterowania nie może czekać na zapis pliku, wolny sensor ani odpowiedź urządzenia zewnętrznego. Operacje blokujące przesuwają kolejne deadline’y, zwiększają jitter i mogą sprawić, że estimator dostanie próbki o złej osi czasu.

Wydajności nie ocenia się średnim użyciem CPU. Krytyczne są najgorszy czas wykonania, rozkład opóźnień, przekroczenia budżetu i zachowanie podczas jednoczesnego logowania, telemetrii oraz błędów peryferiów. Zmiana, która działa w spokojnym zawisie SITL, może ujawnić problem dopiero po włączeniu szybkiego logowania, dwóch odbiorników GNSS i dodatkowego urządzenia CAN.

Praktyczna inspekcja nowego modułu powinna odpowiedzieć na pytania:

  1. Kto inicjuje obiekt i kiedy jest on gotowy?
  2. W jakim kontekście wykonywany jest kod okresowy?
  3. Czy operacja może blokować lub alokować pamięć?
  4. Jaki jest timestamp danych: czas pomiaru, odebrania czy przetworzenia?
  5. Jak starzenie danych wpływa na wyjście modułu?
  6. Co dzieje się po błędzie i jak stan wraca do normy?

Parametry są publicznym API konfiguracji#

Parametr ArduPilot ma nazwę, typ, wartość domyślną, zakres, metadane i trwałą reprezentację. Dodanie parametru zwiększa powierzchnię utrzymania: trzeba zachować znaczenie przy aktualizacji, przewidzieć migrację, opisać jednostkę i ustalić zachowanie dla wartości spoza zakresu. Parametr nie powinien maskować nieokreślonego algorytmu ani służyć jako przypadkowy przełącznik diagnostyczny pozostawiany na zawsze.

Pełnego pliku parametrów nie należy kopiować między różnymi płatowcami. Zawiera kalibracje, orientacje, mapowanie wyjść, identyfikatory sensorów, limity i konfigurację failsafe. Bezpieczniejsza jest migracja warstwowa:

  1. zachować eksport starej konfiguracji i dokładną wersję firmware;
  2. uruchomić nową wersję na ustawieniach właściwych dla targetu;
  3. przenieść świadomie parametry konstrukcji i misji;
  4. powtórzyć kalibracje zależne od egzemplarza;
  5. przejrzeć różnice oraz komunikaty migracji;
  6. wykonać testy wejść, wyjść i failsafe bez napędu.

Konfigurację produkcyjną warto przechowywać w repozytorium jako jawny zestaw różnic od wartości domyślnych, wraz z numerem płatowca, wersją kodu i wynikiem testu. Eksport bez kontekstu nie jest reprodukowalną konfiguracją.

SITL jako pierwsze środowisko wykonawcze#

SITL kompiluje kod autopilota jako proces hosta i łączy go z modelem dynamiki oraz wirtualnymi urządzeniami. Jest właściwym początkiem, ponieważ zapewnia debugger, sanitizery, szybkie restarty i kontrolę scenariusza. Nie dowodzi jednak poprawności sterowników, zasilania, czasu rzeczywistego ani modelu fizycznego.

Minimalny start z repozytorium ArduPilot może wyglądać tak:

cd ArduCopter
../Tools/autotest/sim_vehicle.py -w --console --map

Opcja -w czyści wirtualny EEPROM, dlatego stosuje się ją świadomie. Kolejne przebiegi powinny otrzymać nazwę przez --aircraft, oddzielny katalog logów i plik parametrów. Dla ArduPlane wybiera się aplikację oraz właściwy model, zamiast zakładać, że test Coptera pokrywa logikę stałopłata.

Dobry scenariusz SITL jest automatycznym eksperymentem:

  • uruchamia określoną rewizję kodu i zestaw parametrów;
  • czeka na gotowość estymatora, nie tylko na HEARTBEAT;
  • wprowadza kontrolowane wejścia lub misję;
  • rejestruje wartości zadane, stan i wyjścia;
  • wymusza utratę RC, GNSS albo GCS;
  • sprawdza oczekiwany tryb, limit i czas reakcji;
  • kończy się jednoznacznym wynikiem oraz zachowuje artefakty.

Parametry SIM_* umożliwiają modelowanie wiatru, błędów sensorów i utraty RC. Test failsafe nie może ograniczać się do odłączenia interfejsu w losowym momencie: potrzebuje zdefiniowanego stanu początkowego, czasu usterki, oczekiwanej maszyny stanów i kryterium zaliczenia.

MAVLink łączy autopilota z Mission Planner, MAVProxy, QGroundControl, companion computer i payloadami. sysid identyfikuje system, compid komponent, a HEARTBEAT sygnalizuje obecność oraz ogólny stan. Heartbeat nie potwierdza świeżości estymacji, sprawności aktuatorów ani uprawnień nadawcy.

Każde łącze ma własny budżet. Żądanie wielu szybkich strumieni przez wolny modem zwiększa kolejki i wiek danych. Przy diagnostyce należy odróżnić:

  • brak wygenerowania wiadomości w autopilocie;
  • odrzucenie przez politykę routingu;
  • przepełnienie bufora portu;
  • stratę w radiu lub sieci IP;
  • opóźnienie lub filtr po stronie GCS.

Komendy zmieniające stan muszą przechodzić przez istniejące kontrole trybu, uzbrojenia i uprawnień. Nowy komponent nie powinien omijać maszyny stanów przez bezpośredni zapis wewnętrznej zmiennej tylko dlatego, że działa to w demonstracji.

Estymacja, tryb lotu i regulatory#

Tryb lotu nie jest jedynie etykietą interfejsu. Określa źródło wartości zadanej, wymagane estymaty, ograniczenia oraz reakcję na utratę danych. Tryb pozycyjny może wymagać poprawnego rozwiązania poziomego, podczas gdy tryb stabilizacji korzysta przede wszystkim z orientacji. Dodając funkcję, należy jawnie zadeklarować zależności i zachowanie po degradacji.

Przepływ sterowania warto analizować od dołu:

  1. sterownik publikuje próbki z wiarygodnym timestampem;
  2. warstwa sensora wybiera i monitoruje instancje;
  3. EKF wyznacza stan oraz innowacje;
  4. tryb tworzy trajektorię lub setpoint;
  5. pętle pozycji, prędkości, orientacji i rate tworzą żądane siły/momenty;
  6. alokacja uwzględnia geometrię i ograniczenia napędów;
  7. backend wyjściowy generuje sygnał dla ESC lub serwa.

Jeżeli pojazd oscyluje, nie zaczyna się od losowej zmiany gainów. Najpierw sprawdza się znaki osi, timing, wibracje, saturację, ograniczenia i to, czy regulator otrzymuje właściwą wartość zadaną. PID jest tylko jednym elementem tego łańcucha.

DataFlash i diagnostyka#

Log pokładowy jest ważniejszy od ekranu GCS, bo zachowuje szybsze sygnały i nie zależy od utraty łącza. Każdy test powinien mieć log, wersję firmware, parametry, opis sprzętu i notatkę o przebiegu. Analizę prowadzi się warstwami:

Warstwa Przykładowe pytanie
zdarzenia kiedy zmienił się tryb, uzbrojenie i stan failsafe?
estymator czy innowacje i wariancje rosły przed błędem?
sterowanie czy setpoint był osiągalny i czy pojawiła się saturacja?
napęd czy wyjścia rozjechały się z napięciem, RPM lub prądem?
scheduler czy wystąpiły opóźnienia i przekroczenia czasu?
łączność czy problem był lokalny, czy tylko zniknęła telemetria?

Nowe wiadomości logu powinny mieć stabilną semantykę, jednostki, ograniczoną częstotliwość i koszt znany przed włączeniem. Rejestrowanie wszystkiego w najszybszej pętli może samo stworzyć usterkę, którą próbuje się mierzyć.

Cykl zmiany od hipotezy do lotu#

Bezpieczna zmiana ma mały zakres i mierzalny skutek:

  1. odtworzyć problem na niezmienionej rewizji;
  2. zapisać konfigurację, log i scenariusz;
  3. dodać test jednostkowy lub automatyczny przypadek SITL;
  4. zmienić jedną warstwę i uruchomić testy statyczne oraz kompilację targetów;
  5. porównać logi bazowe i zmienione, także dla błędów;
  6. uruchomić właściwy firmware na stole bez śmigieł;
  7. sprawdzić kierunki sensorów, wyjść, RC i wszystkie failsafe;
  8. wykonać ograniczony lot w kontrolowanym środowisku;
  9. zachować artefakty i kryteria akceptacji.

Test stołowy nie powinien zasilać napędu, jeżeli nie jest to potrzebne. Gdy wymagany jest test silników, platforma musi być mechanicznie zabezpieczona, nieuzbrojona i pozbawiona śmigieł. Pierwszy lot nie jest miejscem do sprawdzania, czy mapowanie wyjść i kierunek korekcji są poprawne.

Typowe błędy początkującego programisty#

Zmiana wielu parametrów naraz#

Bez pojedynczej hipotezy nie można wskazać przyczyny poprawy ani regresji. Należy stosować kontrolowane różnice i porównywalny scenariusz.

Test wyłącznie ręczny#

Ręczny lot jest trudny do powtórzenia i nie pokrywa timeoutów. Krytyczne zachowanie trzeba kodować jako test automatyczny lub przynajmniej deterministyczną procedurę.

Uznanie SITL za model rzeczywistości#

SITL dobrze sprawdza logikę, lecz nie potwierdza odporności EMC, mechaniki, termiki, sterowników i realnych opóźnień. Po nim potrzebne są HIL, stanowisko i stopniowane próby fizyczne.

Bezpośrednie sterowanie z callbacku komunikacyjnego#

Parser wiadomości nie powinien omijać walidacji stanu i ograniczeń. Komenda ma tworzyć żądanie obsługiwane przez właściwą maszynę stanów.

Log bez synchronizacji czasu#

Porównywanie próbek według chwili odebrania zamiast pomiaru prowadzi do fałszywych wniosków o fazie regulatora i opóźnieniu sensora.

Kopiowanie konfiguracji innego płatowca#

Podobna rama nie oznacza tej samej orientacji, masy, napędu i charakterystyki wibracji. Konfiguracja musi przejść commissioning konkretnego egzemplarza.

Biblioteki AP_ i granice modułów#

Kod ArduPilot jest podzielony na biblioteki odpowiedzialne m.in. za sensory, estymację, nawigację, sterowanie, parametry, logowanie i komunikację. Nazwa rozpoczynająca się od AP_ zwykle wskazuje współdzielony komponent, ale kontrakt należy odczytać z kodu i dokumentacji aktualnej gałęzi.

Nowa funkcja nie powinna czytać globalnych sterowników z przypadkowego miejsca. Warstwa pojazdu przekazuje kontekst, biblioteka publikuje wyraźne API, a zależności sprzętowe przechodzą przez AP_HAL. Dzięki temu kod działa w SITL i na różnych płytkach.

Inicjalizacja ma kolejność. Konstruktor obiektu nie jest dobrym miejscem na operacje zależne od gotowego sprzętu. Metody init rejestrują parametry, wykrywają backendy i zgłaszają stan. Błąd inicjalizacji powinien być widoczny w pre-arm check lub statusie, nie prowadzić do cichego wskaźnika null w locie.

Parametry i kompatybilność#

Parametr jest trwałym API dla operatora, GCS, skryptów i istniejących konfiguracji. Nazwa ma limit oraz konwencję, typ i zakres są częścią umowy. Zmiana jednostki pod tą samą nazwą jest błędem kompatybilności.

Wartość domyślna musi być bezpieczna dla wszystkich platform, których dotyczy. Nowa funkcja eksperymentalna powinna pozostać wyłączona, dopóki użytkownik jawnie jej nie skonfiguruje. Dokumentacja podaje zależności i potrzebę restartu.

Migracja parametrów zachowuje stare instalacje. Test obejmuje start z czystą EEPROM, start ze starym zestawem, zmianę i restart oraz zachowanie po downgrade, jeśli jest wspierany. W SITL można automatycznie tworzyć te scenariusze.

Backend i frontend sensora#

Wiele bibliotek rozdziela frontend udostępniający jednolite dane od backendów konkretnych urządzeń. Frontend zarządza instancjami, zdrowiem i wspólną konfiguracją; backend komunikuje się przez SPI, I²C, CAN lub serial.

Driver nie powinien blokować pętli na długie oczekiwanie. Transfer jest planowany, dane mają timestamp pomiaru, a timeout zmienia health. CRC poprawnej ramki nie dowodzi sensownej wartości, więc sprawdza się zakres i ciągłość.

Dodanie backendu wymaga identyfikacji urządzenia, obsługi wielu instancji, resetu magistrali i testu braku sensora. Kod powinien działać także wtedy, gdy urządzenie odpowie ID, a potem przestanie dostarczać próbki.

Scheduler i wydajność#

Plan zadań określa częstotliwość i budżet. Funkcja o nominale 50 Hz nie może okresowo zajmować czasu pętli 400 Hz. Wydajność mierzy się na najsłabszym wspieranym kontrolerze, z logowaniem i komunikacją aktywną.

Alokacja pamięci, formatowanie tekstu i zapis storage nie należą do krytycznej ścieżki. Ciężkie obliczenie dzieli się na kroki lub uruchamia rzadziej. Wynik dla regulatora musi mieć timestamp i ważność; „ostatnia wartość” po spóźnieniu jest potencjalnie niebezpieczna.

SITL na szybkim PC nie ujawnia braku budżetu MCU. Test sprzętowy loguje load, free memory, loop time i błędy scheduler. Zmiana jest gotowa dopiero z zapasem, nie przy średnim użyciu bliskim 100%.

DataFlash jako kontrakt diagnostyczny#

Nowa funkcja powinna dać się zdiagnozować po locie. Log zawiera wejście, wynik, stan jakości, tryb, ograniczenie i przyczynę odrzucenia. Nazwy pól, jednostki i skala są dokumentowane. Zbyt szybkie logowanie może jednak obciążyć medium, dlatego wybiera się częstotliwość odpowiednią do zjawiska.

Event i error zapisują przejścia dyskretne, message daje tekst dla operatora, a struktura binarna pozwala wykresy. Tekst nie zastępuje pól maszynowych. Dla automatu stanów loguje się stary stan, nowy stan i reason code.

Replay może odtworzyć część przetwarzania z zapisanych sensorów. Jest wartościowy dla estymatora i regresji, ale zakres zależy od kompletności logu oraz wersji. Nie jest pełnym odtworzeniem aerodynamiki ani aktuatorów.

Testy i review zmiany#

Najtańszy test obejmuje czystą funkcję, parser albo automat bez uruchamiania pojazdu. SITL następnie sprawdza integrację, misję i failsafe. AutoTest pozwala włączyć scenariusz do regresji projektu. HIL i lot badają różnice sprzętowe.

Zmiana powinna przejść formatowanie, statyczne kontrole, build dla odpowiednich celów i testy. Review ocenia nie tylko happy path, lecz także brak urządzenia, timeout, NaN, restart i kompatybilność parametrów. Duży patch łatwiej podzielić na neutralny refactor, test i zmianę zachowania.

Minimalny artefakt reprodukcji zawiera commit, komendę build, typ pojazdu, plik parametrów, polecenia MAVProxy/GCS, log i oczekiwany wynik. Film z lotu nie pozwala odtworzyć błędu scheduler lub EKF.

Ścieżka pierwszej własnej zmiany#

  1. Zbudować niezmieniony kod i uruchomić SITL.
  2. Zapisać commit, parametry i test bazowy.
  3. Znaleźć właściciela danych oraz istniejące API, zamiast tworzyć równoległy tor.
  4. Dodać najmniejszą zmianę z parametrem wyłączającym, jeśli wpływa na lot.
  5. Dodać log oraz test błędu przed testem pozytywnym.
  6. Uruchomić różne pojazdy korzystające ze wspólnej biblioteki.
  7. Sprawdzić CPU, pamięć, komunikację i trwałość parametrów na sprzęcie.
  8. Rozszerzać obwiednię dopiero po analizie logu.

Najważniejszą kompetencją nie jest znalezienie miejsca, w którym da się dopisać if, lecz rozpoznanie kontraktu między biblioteką, schedulerem, parametrami i stanami bezpieczeństwa.

Powiązane tematy#

Przypisy#

  1. ArduPilot Dev Documentation — Learning ArduPilot — AP_HAL, biblioteki i organizacja kodu.
  2. ArduPilot Dev Documentation — Using SITL — uruchamianie, urządzenia, logi i wiele wyjść MAVLink.
  3. ArduPilot Dev Documentation — SITL simulation parameters — kontrola modelu, usterek, wiatru i utraty RC.
  4. ArduPilot Dev Documentation — Testing with Replay — odtwarzanie logów przez kod estymatora.
  5. ArduPilot GitHub — bieżący kod, targety, testy i historia zmian.
  6. MAVLink Guide — identyfikacja systemów, routing, mikroserwisy i diagnostyka protokołu.

Źródła z centralnego rejestru

  1. Terry Kilby, Belinda Kilby, „Make: Drony dla początkujących” [książka]
  2. Sumit Sharma, „Drone Development from Concept to Flight” [książka]
  3. ArduPilot: Using Simulation Parameters to Control the Simulation [dokumentacja]
  4. ArduPilot: Downloading and Analyzing Data Logs [dokumentacja]
  5. MAVLink Protocol Overview [specyfikacja]