ŞEK. 01
KAYIT KÜNYESİ
Kategori
Gömülü Sistemler
TARİH
YOLO modeliniz Jetson üzerinde çalışıyor ve hedefi kamera karesinde 15-20 FPS ile buluyor. Hemen ardından bir sonraki soru geliyor: bu tespiti uçuş kontrolcüsüne nasıl ulaştıracağız? Uçağa o koordinatlara gitmesini, orada beklemesini ve yükü bırakmasını kim söyleyecek?
İlk refleksimiz "her şeyi uçuş kontrolcüsüne koyalım" olmuştu. Pixhawk sınıfı bir karttaki mikrodenetleyici, saniyede yüzlerce kez IMU okuyup motor çıkışlarını hesaplamakla zaten meşgul. Orada bir sinir ağı çalıştırmak mümkün değil; başarsanız bile kontrol döngüsünü mahvedersiniz.
Çözüm işi ikiye bölmek: gerçek zamanlı kontrol uçuş kontrolcüsünde (FC) kalır, ağır hesaplama ise onun yanına monte edilen ikinci bir bilgisayara taşınır. Bu ikinci bilgisayarın adı companion computer (yardımcı bilgisayar); ArduPilot bunu, FC'ye MAVLink protokolü üzerinden bağlanan ve uçuş sırasında karar veren bir birim olarak tanımlıyor. Bu yazıda o iki kutu arasındaki kabloyu, üzerinden akan protokolü ve gerçekten çalışan kodu ele alıyoruz.
İş neden böyle bölünüyor?
Uçuş kontrolcüsünün işi katı gerçek zamanlıdır: stabilizasyon döngüsü asla kaçırılmaz ve ortada bir işletim sistemi bile yoktur (ArduPilot, ChibiOS üzerinde koşar). Companion computer'ın işi ise "yumuşak" gerçek zamanlıdır: bir kareyi geç işlemek görevi geciktirir ama uçağı düşürmez. Bu ayrım aynı zamanda bir güvenlik sınırıdır: companion çökerse FC uçmaya devam eder, failsafe (güvenli-mod) devreye girer ve uçak RTL (kalkış noktasına dönüş) uygular. Tersi geçerli değildir.
Tipik companion işleri: nesne tespiti, gimbal kontrolü, haritalama, yer istasyonuna video akışı ve üst seviye görev mantığı. SUAS 2026 uçağımızda bu rolü Jetson Orin NX 16GB üstleniyor: SIYI A8 mini kameradan RTSP akışını çekiyor, YOLO11m ile tespit yapıyor ve sonucu MAVLink üzerinden FC'ye bir konum komutuna çeviriyor.
Fiziksel bağlantı: UART, USB, Ethernet
Üç seçenek var ve çoğu takım için doğru cevap birincisi.
Yöntem | Ayar | Ne zaman kullanılır |
|---|---|---|
UART (TELEM1/TELEM2) |
| Varsayılan tercih. Yalnızca 3 kablo (TX, RX, GND) ve FC yeniden başladığında port adı değişmiyor |
USB (SERIAL0) | Kabloyu tak, | Tezgâh testi ve parametre yazma. Uçuşta kullanmayın: konnektör titreşimde yerinden çıkar ve port adı numaralandırma sırasına göre kayar |
Ethernet |
| ArduPilot 4.5 ve sonrası, Ethernet MAC'i olan kartlarda (Pixhawk6X, CubeRed). ROS 2/DDS ve yüksek veri hacimleri için |
ArduPilot'ta seri portlar şöyle eşlenir: SERIAL0 = USB, SERIAL1 = TELEM1, SERIAL2 = TELEM2, SERIAL3 = GPS. Bir SERIALx_PROTOCOL değeri 1 ise MAVLink1, 2 ise MAVLink2 konuşulur. Companion için 2 kullanın. SERIALx_BAUD parametresi ise baud hızının bine bölünmüş hâlidir: 57=57600, 115=115200, 921=921600.
Kablolama çaprazdır: FC TX → companion RX, FC RX → companion TX, GND → GND. Pixhawk UART'ları 3.3 V lojik seviyede çalışır; 5 V TTL bir kartı doğrudan bunlara bağlamayın ve FC'yi companion'ın USB'sinden beslemeyin.
Linux tarafında portun seri konsol olarak kullanılmadığından emin olun. Raspberry Pi'de "login shell over serial" seçeneğini raspi-config içinden kapatın, donanım UART'ını açık bırakın; port o zaman /dev/serial0 olarak görünür. Jetson'da genelde /dev/ttyTHS1 olur ve nvgetty servisinin devre dışı bırakılması gerekir.
Üç kavramda MAVLink
Mesajlar. MAVLink paket tabanlıdır. Her paket bir System ID, bir Component ID, bir Message ID ve veri alanlarını taşır; azami boyut MAVLink1'de 263 bayt, MAVLink2'de 280 bayttır. Araç varsayılan olarak system ID 1 kullanır (MAV_SYSID), yer istasyonları için ise geleneksel olarak 255 kullanılır.
Heartbeat. Bağlantı kurulduktan sonra her iki taraf da 1 Hz'de bir HEARTBEAT (mesaj ID 0) gönderir. Bu hem "hayattayım" sinyalidir hem de aracın uçuş modunu (custom_mode) ve arm durumunu taşır. Kodda yapacağınız ilk şey bir heartbeat beklemektir, çünkü hedef sistem numarasını oradan öğrenirsiniz.
Akış hızları. FC her mesajı kendiliğinden göndermez; hangilerini hangi hızda istediğinizi söylemeniz gerekir. Eski yaklaşım, mesaj gruplarını REQUEST_DATA_STREAM ile istemektir. ArduPilot 4.0 ve sonrasında tercih edilen yaklaşım ise mesajları tek tek MAV_CMD_SET_MESSAGE_INTERVAL (komut ID 511) ile istemektir: aralık mikrosaniye cinsindendir, yani 10 Hz için 100000 yazarsınız.
Sık kullanılan mesajlar ve birimleri:
Mesaj | ID | İçerik | Birim tuzağı |
|---|---|---|---|
| 0 | Mod, arm durumu |
|
| 33 | Konum, irtifa, hız | lat/lon degE7, irtifa mm, hız cm/s |
| 30 | roll/pitch/yaw | radyan, derece değil |
| 1 | Batarya, sensör sağlığı | gerilim mV, akım cA |
pymavlink ile bağlanmak ve telemetri okumak
Kurulumu pip install pymavlink ile yapılır. Aşağıdaki blok tek başına çalışır; UDP satırının yorumunu kaldırırsanız bunun yerine bir SITL simülasyonuna bağlanır.
recv_match bloklayıcıdır; ana görev döngünüzü tıkamasını istemiyorsanız telemetriyi ayrı bir thread'de okuyup paylaşılan bir sözlüğe yazın. Jetson'da tam olarak bunu yapıyoruz: tespit döngüsü ile MAVLink döngüsü ayrı thread'lerde çalışıyor.
Komut göndermek: mod değiştirmek ve GUIDED ile bir konuma uçmak
GUIDED, aracın dışarıdan verilen konum ve hız hedeflerini takip ettiği moddur. ArduPilot belgeleri bu modun bir companion computer veya Lua betikleriyle kullanılabileceğini açıkça belirtiyor. Ön koşullar: GPS kilidi ve dikey eksende hedef veriyorsanız aracın hâlihazırda havada olması.
type_mask hangi alanların dikkate alınacağını belirler: 0 olan bir bit alanın kullanıldığı, 1 olan bit ise yok sayıldığı anlamına gelir. 0b110111111000 "yalnızca konum" demektir. Bu maskeyi yanlış kurmak en sık görülen sessiz hatadır: araç irtifa değiştirir ama yatayda hiç kıpırdamaz.
Bir konum hedefi, araç oraya varana kadar geçerli kalır. Hız veya ivme hedefi gönderiyorsanız GUID_TIMEOUT (varsayılan 3 saniye) içinde yenisini göndermeniz gerekir; aksi hâlde araç yavaşlar ve durur. Yatay hız WP_SPD ile sınırlıdır (varsayılan 10 m/s).
MAVROS ve ROS 2 alternatifi
Tek başına pymavlink yetmediğinde devreye bir ROS katmanı giriyor.
Yaklaşım | Ne zaman tercih edilir |
|---|---|
pymavlink | Tek bir Python süreci, birkaç mesaj tipi, hızlı prototipleme. Bağımlılık açısından en hafif seçenek |
MAVROS | Zaten ROS ekosistemindesiniz ve hazır düğümler, TF ağacı ile mesaj dönüşümleri emeğinin karşılığını veriyor. Bir MAVLink köprüsü üzerinden çalışır |
AP_DDS (yerleşik DDS) | ArduPilot 4.5 ve sonrası; arada köprü olmadan XRCE-DDS üzerinden doğrudan ROS 2 ile konuşur. En iyi Ethernet bağlantısıyla eşleşir |
ROS 1 2025'te destek ömrünü tamamladı; dolayısıyla yeni projelerde (2026 itibarıyla) ROS 2 tarafına bakmak mantıklı. Simülasyonda Gazebo + SITL + ROS 2 kullanıyoruz, ama uçuş yazılımının kritik yolu hâlâ doğrudan pymavlink konuşuyor: daha az katman, daha az sürpriz.
Sık düşülen hatalar
Seri konsolu açık bırakmak. Linux
/dev/serial0üzerinde bir login shell çalıştırıyorsa açılış mesajları MAVLink verisine karışır ve tek bir paket bile ayrıştırılamaz.Aynı portu iki uygulamadan açmak. Bir seri portu aynı anda yalnızca tek bir süreç tutabilir. Hem kendi kodunuzun hem de MAVProxy ya da bir yer kontrol istasyonunun bağlanması gerekiyorsa
mavlink-routerkurun ve portu birden fazla UDP uç noktasına dağıtın.Komut göndermeden önce şunu çağırmayı unutmak:
wait_heartbeat(). O ana kadarmaster.target_system0'dır; komutlarınız hiçbir yere gitmez ve hata bile almazsınız.Birimleri karıştırmak. Enlem/boylam degE7 (10⁷ ile ölçeklenmiş tam sayı), irtifa mm, hız cm/s, açılar radyan,
SET_MESSAGE_INTERVALise mikrosaniye cinsindendir. Bunlardan birini karıştırırsanız ortaya çıkan hata sessizdir.Akış hızlarını sonuna kadar açmak. 57600 bps'lik bir telemetri bağlantısında her mesajı 50 Hz'de istemek bant genişliğini doldurur ve paket kaybına yol açar. Yalnızca ihtiyacınız olan mesajları, gerçekten ihtiyaç duyduğunuz hızda isteyin.
Companion'a yer istasyonuyla aynı system ID'yi vermek. Companion'ın heartbeat'i, FC'nin bağlantıyı hâlâ ayakta sanmasına yol açarak GCS failsafe'ini susturabilir; yer istasyonu bağlantısı gerçekten kopsa bile failsafe hiç devreye girmez.
Güvenlik notları
FC bir arm komutunu reddedebilir; bu bir hata değil, bir koruma katmanıdır. ARMING_CHECK kontrolleri GPS kalitesi, EKF tutarlılığı, pusula sağlığı ve batarya durumu gibi alanları kapsar. Kodunuz COMMAND_ACK sonucunu incelemeli ve komut reddedildiğinde göreve başlamayı reddetmelidir.
Devrede bir companion varken GCS failsafe'ini ayrıca düşünün: FS_GCS_ENABLE açıkken FC, birincil yer istasyonundan (MAV_GCS_SYSID ile tanımlanan sistem) gelen heartbeat'i izler ve FS_GCS_TIMEOUT (varsayılan 5 saniye) boyunca sessizlik olursa failsafe'i tetikler. Bu korumanın çalışmaya devam etmesi için companion'ınıza farklı bir system ID verin.
Son olarak, pilotun mod anahtarı her zaman companion'ın komutlarını geçersiz kılabilmelidir. ~20 m'den iki hedefi tespit edip otonom bırakma testimizin arkasında haftalarca süren SITL tekrarları var; hiçbir kod parçası sahada ilk kez çalışmadı.
Pratik özet
TELEM2 kullanın:
SERIAL2_PROTOCOL=2,SERIAL2_BAUD=921, kablolama çapraz TX↔RX, ortak GND. Uçuşta USB'ye güvenmeyin.Her bağlantıda
wait_heartbeat()çağırın, ardından yalnızca ihtiyacınız olan mesajları şununla isteyin:MAV_CMD_SET_MESSAGE_INTERVAL.Komutlarınızı doğrulayın: mod değişikliklerini
HEARTBEAT.custom_modeile, arm ve diğer komutlarıCOMMAND_ACK.resultile doğrulayın. "Gönderdim" ile "kabul edildi" aynı şey değildir.Şunları iki kez kontrol edin:
type_maskve birimler — degE7, mm, cm/s, radyan, mikrosaniye.Companion'a rağmen failsafe'i çalışır tutun: ayrı bir system ID kullanın, pilot müdahalesini asla engellemeyin ve sahaya çıkmadan önce senaryoyu SITL'de prova edin.
Kaynaklar: ArduPilot dev/copter belgeleri (Companion Computers, Telemetry Port Setup, MAVLink Basics, Requesting Data, Guided Mode, Network Setup) ve mavlink.io ortak mesaj tanımları.
