Softivation

Python'da Pixhawk irtifası yanlış (Mission Planner doğru)

Python'da Pixhawk irtifası yanlış mı geliyor? GLOBAL_POSITION_INT içindeki alt deniz seviyesini verir; Mission Planner'daki irtifa için relative_alt oku.

Furkan IŞIKAY 6 dk okuma

Mission Planner drone'u 10 metrede gösteriyor. Raspberry Pi'deki Python kodun aynı anda 510 diyor; bölmeyi unuttuysan 510080. Drone daha yerdeyken bile kodun "10 metreye çıktım" deyip sıradaki adıma geçiyor.

Aynı pakette iki ayrı irtifa var ve kodun, Mission Planner'ın göstermediğini okuyor.

Kod drone yerdeyken kamerayı açıyor

Savaşan İHA görevinde sık kurulan bir koşul düşün: drone kalkışta 10 metreyi geçince kamera kaydı başlasın. Kod konum paketini okur, irtifayı 1000'e bölüp metreye çevirir, sonuç 10'dan büyükse kamerayı açar.

Sahanın rakımı 500 metreyse bu koşul drone yerdeyken de doğrudur, çünkü 500 zaten 10'dan büyük. Pervaneler dönmeden kayıt başlar ve kod kalkışı beklemeden görevin sonraki adımına geçer.

Aynı pakette iki irtifa var

ArduPilot konumu GLOBAL_POSITION_INT paketinde yollar. Paketin iki irtifa alanı var ve ikisi de milimetre:

  • alt deniz seviyesinden ölçer. Rakımı 500 metre olan sahada drone yerdeyken 500080 civarı okursun.
  • relative_alt kalkış noktasından (home) ölçer. Mission Planner'ın ekranda gösterdiği irtifa budur.

Şekilde üç okun da aynı drone'da bittiğine, ama farklı çizgiden başladığına bak. Kırmızı ok sahanın rakımını da içinde taşır; mavi ok yalnızca kalkıştan bu yana tırmanılan yüksekliği.

Aynı drone, üç sıfır noktası

Aynı drone için üç irtifa alanı farklı sıfır noktasından ölçülür
Okların başladığı çizgiye bak: kırmızı ok denizden, mavi ok home noktasından, kesikli ok EKF orijininden ölçer. Dikey eksen ölçekli değil.

Kesikli ok üçüncü bir kaynaktır: LOCAL_POSITION_NED paketindeki z. Bu eksen aşağıyı pozitif sayar, bu yüzden drone 10 metre yukarıdayken −9.98 gibi eksi bir değer okursun. VFR_HUD paketindeki irtifa da varsayılan ayarda deniz seviyesinden ölçer.

Sık yapılan hata

alt alanını 1000'e bölmek sorunu çözmez. Birim metreye döner ama sıfır noktası hâlâ deniz seviyesidir; kod 10 yerine sahanın rakımı artı 10'u görür ve 510 okur.

Çözüm: kalkış noktasına göre oku

Koşulu home noktasına göre kur. Aşağıdaki kod iki alanı yan yana basar, böylece hangisinin Mission Planner'la eşleştiğini kendi ekranında görürsün:

Python
from pymavlink import mavutil

# Pixhawk'a hangi adresten bağlanıyorsan onu yaz (seri port, UDP ya da TCP)
baglanti = mavutil.mavlink_connection('tcp:127.0.0.1:5760')
baglanti.wait_heartbeat()
baglanti.mav.request_data_stream_send(baglanti.target_system, baglanti.target_component,
                                      mavutil.mavlink.MAV_DATA_STREAM_POSITION, 5, 1)

for _ in range(3):
    m = baglanti.recv_match(type='GLOBAL_POSITION_INT', blocking=True)
    deniz = m.alt / 1000            # mm -> m, deniz seviyesine göre
    kalkis = m.relative_alt / 1000  # mm -> m, kalkış noktasına (home) göre
    print(f"deniz seviyesi: {deniz:.2f} m | kalkış noktasına göre: {kalkis:.2f} m")

Gir: kamera koşulunda m.relative_alt / 1000 kullan. Gör: drone yerdeyken sıfıra yakın bir değer, havadayken Mission Planner'daki irtifayla aynı sayı. Değilse: home noktasının nerede yazıldığına bak (aşağıda).

Ne göreceksin

Drone yerdeyken kodu çalıştırırsan şunu görürsün:

Kod
deniz seviyesi: 500.08 m | kalkış noktasına göre: 0.01 m
deniz seviyesi: 500.08 m | kalkış noktasına göre: 0.01 m
deniz seviyesi: 500.08 m | kalkış noktasına göre: 0.01 m

Drone 10 metreye çıktıktan sonra aynı kodu çalıştırırsan şunu görürsün:

Kod
deniz seviyesi: 510.08 m | kalkış noktasına göre: 10.00 m
deniz seviyesi: 510.08 m | kalkış noktasına göre: 10.00 m
deniz seviyesi: 510.08 m | kalkış noktasına göre: 10.00 m

Çıktıdaki 500 metre sahanın rakımıdır. Kendi sahanda ilk sütun oranın rakımıyla başlar, ikinci sütun ise her sahada sıfırdan başlar.

Home noktası ARM anında yazılır

relative_alt'ın sıfırı home noktasıdır. ArduCopter home noktası kilitli değilse onu her ARM'da drone'un o anki konumuna yeniden yazar (AP_Arming_Copter.cpp). Bu yüzden ARM'dan önce okuduğun değer sıfırdan kayabilir; kalkış koşulunu ARM'dan sonra okuduğun değere göre kur.

Hata Mesajları ve Anlamları

AttributeError: 'NoneType' object has no attribute 'relative_alt'

recv_match zaman aşımına düştü ve paket yerine None döndü. Konum akışını istemeden okuyorsan paket hiç gelmez; koddaki request_data_stream_send satırının yerinde olduğuna ve dönen değerin None olup olmadığına bak.

Field Elevation Set: 500m

Otopilot sahanın rakımını bu sayıya kurdu. BARO_FIELD_ELV = 0 (varsayılan) iken sayı EKF orijininin yüksekliğidir ve alt alanı bu rakımın üstüne biner. Senin sahanda sayı o sahanın rakımı olur.

PreArm: Baro: GPS alt error

GPS'in verdiği deniz seviyesi irtifası ile barometrenin hesapladığı irtifa arasında BARO_ALTERR_MAX'tan (varsayılan 2000 m) büyük fark var. Mesajın devamında farkın metre cinsinden değeri yazar; ARM izni gelmez.

Python'dan uçuşu adım adım kur

Bağlanma, öznitelik dinleyicileri, GUIDED komutları ve görev yükleme sırasıyla Python ile Sıfırdan İHA Kontrolü eğitiminde. Kurs derslerinde irtifa kaynaklarının hangisinin ne zaman sıfırlandığını ve log'da nasıl ayırt edildiğini de bulursun.

Bu yazı işinize yaradı mı?

Ücretsiz kaynakArduPilot SITL kurulum rehberiKodunuzu sahaya çıkmadan SITL'de deneyin: kurulum ve bağlantı baştan sona.