Drone ilk hedefi atlıyor (Python ile ArduPilot GUIDED)
Drone ilk hedefi atlıyor ve doğrudan ikinci noktaya gidiyorsa Python kodun varışı beklemiyordur. ArduPilot GUIDED'de varışı ölçen kodu kopyala, çalıştır.
Python'dan drone'a iki nokta gönderiyorsun: önce kuzeydeki köşe, sonra doğudaki hedef. Drone havalanıyor, birinci noktaya hiç uğramadan çapraz bir çizgiyle ikinciye gidiyor. Kodda hata mesajı yok, iki komut da gitmiş görünüyor.
Bazı takımlar bunu fark edince iki komutun arasına otopilotun "vardım" mesajını bekleyen bir satır koyuyor ve bu kez kod birinci noktada sonsuza kadar duruyor. İki belirtinin kökü aynı: kod, drone'un hedefe ne zaman vardığını bilmiyor.
Drone neden birinci noktaya uğramıyor
GUIDED modda gönderdiğin her konum hedefi bir öncekinin üstüne yazılır. Otopilotta bir hedef kuyruğu yoktur; Python satırı bitirip bir sonrakine geçtiğinde drone hâlâ kalkış noktasının yakınındadır ve yeni hedef eskisini anında siler.
Aşağıdaki şemada iki uçuşun üstten izi var. Kırmızı izde iki hedef art arda gönderilmiş; drone 1. hedefe en fazla 27 metre yaklaşıyor ve doğrudan 2. hedefe dönüyor. Mavi izde kod birinci noktaya varışı beklemiş, drone köşeyi dönüp ikinciye geçmiş.
İkinci hedef birinciyi siliyor: iki uçuşun izi
Yük bırakma görevinde drone'u önce hedefin üstüne gönderip sonra servoyu açan bir kod yazdığını düşün. Varışı beklemezsen Python servo satırına hemen geçer, drone ise o sırada hâlâ yoldadır ve yük hedefin çok gerisinde düşer.
Otopilot vardığını söylemiyor mu
Varsayılan ayarlarda söylemez. ArduCopter 4.7'de GUID_OPTIONS parametresi 0 iken konum hedefi doğrudan konum kontrolcüsüne gider ve varışta MISSION_ITEM_REACHED mesajı gönderilmez. Bu mesajı bekleyen kod bu yüzden takılır.
Mission Planner'ın gösterdiği hedef mesafesi de NAV_CONTROLLER_OUTPUT mesajındaki wp_dist alanından gelir ve tam sayı metredir. Drone hedefe 0,7 metre uzaktayken bu alan 0 yazar; 1 metreden küçük bir eşiği bu sayıyla kontrol edemezsin.
En sağlam yol, kodun drone'un konumunu kendisinin okuyup hedefe olan mesafeyi hesaplaması. Konum zaten her saniye birkaç kez GLOBAL_POSITION_INT ile geliyor; eksik olan tek şey bu sayıyı bir eşikle karşılaştıran döngü.
En sık yapılan hata: hedef komutlarını art arda yazıp drone'un sırayla gideceğini sanmak. DroneKit'teki simple_goto da aynı şekilde hemen döner; arkasından gelen her komut önceki hedefi iptal eder.
Varışı kod kendisi ölçsün
Aşağıdaki program drone'u kaldırır, 40 metre kuzeye ve sonra 40 metre doğuya gönderir. Her hedefin ardından varis_bekle fonksiyonu yatay mesafe 1 metrenin, irtifa farkı 0,5 metrenin altına inene kadar sonraki satıra geçmez.
import math
import time
from pymavlink import mavutil
BAGLANTI = "tcp:127.0.0.1:5760" # Pi UART: "/dev/serial0"
BAUD = 57600 # Pixhawk tarafindaki SERIALx_BAUD ile ayni
ESIK_M = 1.0 # yatay varis esigi (metre)
IRTIFA_ESIK_M = 0.5
m = mavutil.mavlink_connection(BAGLANTI, baud=BAUD, source_system=255)
m.wait_heartbeat()
m.mav.request_data_stream_send(m.target_system, m.target_component,
mavutil.mavlink.MAV_DATA_STREAM_ALL, 10, 1)
def mesafe_m(lat1, lon1, lat2, lon2):
r = 6371000.0
p1, p2 = math.radians(lat1), math.radians(lat2)
a = (math.sin((p2 - p1) / 2) ** 2 +
math.cos(p1) * math.cos(p2) * math.sin(math.radians(lon2 - lon1) / 2) ** 2)
return 2 * r * math.asin(math.sqrt(a))
def hedef_gonder(lat, lon, irtifa):
m.mav.set_position_target_global_int_send(
0, m.target_system, m.target_component,
mavutil.mavlink.MAV_FRAME_GLOBAL_RELATIVE_ALT_INT,
0b110111111000, # yalnizca konum
int(lat * 1e7), int(lon * 1e7), irtifa,
0, 0, 0, 0, 0, 0, 0, 0)
def varis_bekle(lat, lon, irtifa, zaman_asimi=60):
baslangic = time.time()
while time.time() - baslangic < zaman_asimi:
if m.flightmode != "GUIDED":
print("Mod degisti:", m.flightmode, "- bekleme iptal")
return False
p = m.recv_match(type="GLOBAL_POSITION_INT", blocking=True, timeout=2)
if p is None:
continue
yatay = mesafe_m(p.lat / 1e7, p.lon / 1e7, lat, lon)
dikey = abs(p.relative_alt / 1000 - irtifa)
if yatay < ESIK_M and dikey < IRTIFA_ESIK_M:
print(f"Varildi: yatay {yatay:.2f} m, dikey {dikey:.2f} m, t={p.time_boot_ms/1000:.1f} s")
return True
print("Zaman asimi: hedefe varilamadi")
return False
def kuzey_dogu(lat0, lon0, kuzey_m, dogu_m):
dlat = kuzey_m / 6378137.0
dlon = dogu_m / (6378137.0 * math.cos(math.radians(lat0)))
return lat0 + math.degrees(dlat), lon0 + math.degrees(dlon)
# GPS, GUIDED, ARM, kalkis
while True:
g = m.recv_match(type="GPS_RAW_INT", blocking=True)
if g.fix_type >= 3 and g.satellites_visible >= 6:
break
m.set_mode("GUIDED")
for deneme in range(5): # ARM ilk denemede reddedilebilir
m.arducopter_arm()
m.recv_match(type="HEARTBEAT", blocking=True, timeout=3)
if m.motors_armed():
break
time.sleep(8)
m.mav.command_long_send(m.target_system, m.target_component,
mavutil.mavlink.MAV_CMD_NAV_TAKEOFF, 0, 0, 0, 0, 0, 0, 0, 10)
ev = m.recv_match(type="GLOBAL_POSITION_INT", blocking=True)
lat0, lon0 = ev.lat / 1e7, ev.lon / 1e7
while m.recv_match(type="GLOBAL_POSITION_INT", blocking=True).relative_alt < 9500:
pass
print("Kalkis tamam")
# iki nokta: once 40 m kuzey, sonra 40 m dogu
for kuzey, dogu in ((40, 0), (40, 40)):
lat, lon = kuzey_dogu(lat0, lon0, kuzey, dogu)
hedef_gonder(lat, lon, 10)
if not varis_bekle(lat, lon, 10):
break
m.set_mode("LAND")
print("LAND")- Gir: BAGLANTI satırına kendi hattını yaz. Raspberry Pi'nin UART'ında "/dev/serial0" ve Pixhawk'taki SERIALx_BAUD ile aynı baud.
- Gör: Her noktada bir "Varildi" satırı. Satırdaki yatay değer eşiğin altında olmalı.
- Değilse: 60 saniyede "Zaman asimi" yazıyorsa eşik drone'un havada tutabildiği konumdan dar. Önce ESIK_M'yi 1,5 ya da 2 yap, sonra GPS'in yatay doğruluğuna bak.
Fonksiyon her turda modu da kontrol eder. Pilot kumandadan LOITER'a ya da RTL'e alırsa bekleme biter ve kod bir sonraki hedefi göndermez; böylece pilotun aldığı kontrolü Python geri almaz.
Ne göreceksin
Programı çalıştırıp drone iki noktayı da tamamlarsa terminalde şunu görürsün:
Kalkis tamam
Varildi: yatay 0.94 m, dikey 0.02 m, t=4716.3 s
Varildi: yatay 0.71 m, dikey 0.01 m, t=4724.0 s
LANDt değeri otopilotun açılıştan beri saydığı süredir. İki satır arasındaki fark, 40 metrelik ikinci bacağın kaç saniye sürdüğünü verir; bu örnekte yaklaşık 8 saniye.
Hata mesajları ve anlamları
Mode change to Guided failed: requires position
Otopilot konum kestirimi hazır değilken GUIDED'e geçmeyi reddetti. Kod o zaman başka bir modda kalır ve varis_bekle ilk turda "Mod degisti" yazıp çıkar. Programdaki GPS döngüsü bu yüzden 3D fix ve en az 6 uydu görmeden GUIDED komutuna geçmez.
Zaman asimi: hedefe varilamadi
Drone 60 saniye içinde eşiğin içine girmedi. Ya eşik dar, ya hedef çok uzak, ya da drone rüzgârda konumunu eşik kadar sıkı tutamıyor. Hedefe olan son mesafeyi yazdırıp eşikle karşılaştır.
Mod degisti: LAND - bekleme iptal
Beklerken mod GUIDED'den çıktı: pilot müdahale etti ya da bir failsafe devreye girdi. Kod bilerek durur; sebebini Mission Planner'ın Messages sekmesinde ara.
Python ile otonom kontrolü baştan sona öğren
Varışın otopilot tarafında nasıl karar verildiğini, MISSION_ITEM_REACHED'in hangi ayarla geldiğini ve logda hangi alan doldu diye bakacağını Python ile Sıfırdan İHA Kontrolü eğitimindeki derste adım adım anlatıyoruz.
Bu yazı işinize yaradı mı?
Bu konuyu baştan sona öğrenin
Sezon: altı eğitimin hepsi 9 ay, ayda ₺790. Lise ve üniversite öğrencisine ayda ₺390, üye kodunuzla ilk ay ₺351. İstediğiniz ay bırakırsınız. Sezon'a başlayın · Öğrenciyim