Softivation

İHA AUTO modda ilk waypoint'e gitmiyor

Mission Planner'dan görev yüklendi görünüyor ama İHA AUTO modda ilk waypoint'e gitmiyor. Yüklemenin neden sessizce boşta kaldığını ve çözümünü anlatıyoruz.

Furkan IŞIKAY 9 dk okuma

Görevi Python koduyla yükledin. Otopilot onay verdi, kod hatasız bitti.

Sonra AUTO'ya alıyorsun ve araç hiçbir yere gitmiyor. Ya da daha kötüsü: bir önceki uçuşun görevini uçuruyor.

Çoğu zaman sebep, kodun yanlış onaya güvenmesidir. Görev yükleme el sıkışmasını adım adım kuralım ve bu tuzağı nasıl yakalayacağını görelim.

Gelen onay hangi komuta ait

Çoğu örnek kodda akış şöyledir: eski görevi sil, otopilota kaç öğe geleceğini söyle, sonra gelen ilk onayı yakala.

Eski görevi silme komutunun da kendi onayı vardır. Onu okumazsan döngün, otopilot daha tek bir waypoint istemeden o onayı görür, "kabul edildi" okur ve "yüklendi" diye çıkar.

Şekildeki sarı şeride bak: ilk onay silme komutuna aittir. Yüklemenin onayı ancak otopilot her öğeyi tek tek istedikten sonra gelir. Yüklemenin kanıtı da bu isteklerdir; hiç istek gelmeden düşen onay bir önceki komuta aittir.

Görev yüklemede iki ayrı onay gelir

MISSION_CLEAR_ALL kendi MISSION_ACK'ini döndürür; ardından MISSION_COUNT 4 gönderilir, otopilot seq 0'dan 3'e kadar her öğeyi MISSION_REQUEST_INT ile ister, kod her birine MISSION_ITEM_INT ile cevap verir ve en sonda yüklemenin MISSION_ACK'i gelir
Nereye bak: sarı şerit. İlk type=0 onayı silme komutuna aittir; yüklemenin onayı ancak otopilot dört öğeyi tek tek istedikten sonra, yeşil şeritte gelir.

Kodu önce SITL'de dene

Kodu karta bağlamadan önce bilgisayarında SITL ile deneyebilirsin. Aşağıdaki komutlar ArduCopter SITL'i indirip Şanlıurfa koordinatlarında başlatır.

Ayrı bir terminalde açık bırak; Python kodu buna TCP 5760'tan bağlanacak.

Bash
mkdir -p ~/sitl && cd ~/sitl
curl -sL -o arducopter https://firmware.ardupilot.org/Copter/stable/SITL_x86_64_linux_gnu/arducopter
chmod +x arducopter
curl -sL -o copter.parm https://raw.githubusercontent.com/ArduPilot/ardupilot/master/Tools/autotest/default_params/copter.parm
pip install pymavlink
./arducopter -S -I0 --model + --speedup 5 --defaults copter.parm --sysid 1 --home 37.1591,38.7969,500,0

Doğru kod

Aşağıdaki kod üç şeyi doğru yapar: CLEAR_ALL'in ACK'ini tüketir, MISSION_REQUEST ve MISSION_REQUEST_INT'in ikisini de dinler, sonunda istenen seq sayısını kontrol eder.

Python
import time
from pymavlink import mavutil

WPS = [(37.1600, 38.7969, 20.0), (37.1600, 38.7980, 20.0), (37.1591, 38.7980, 20.0)]

m = mavutil.mavlink_connection('tcp:127.0.0.1:5760')
m.wait_heartbeat()
m.mav.request_data_stream_send(m.target_system, m.target_component,
                               mavutil.mavlink.MAV_DATA_STREAM_ALL, 4, 1)

# Eski gorevi sil VE CLEAR_ALL'in kendi ACK'ini tuket.
m.mav.mission_clear_all_send(m.target_system, m.target_component)
m.recv_match(type='MISSION_ACK', blocking=True, timeout=5)

def item(seq):
    lat, lon, alt = (WPS[0][0], WPS[0][1], 0.0) if seq == 0 else WPS[seq - 1]
    return m.mav.mission_item_int_encode(
        m.target_system, m.target_component, seq,
        mavutil.mavlink.MAV_FRAME_GLOBAL_RELATIVE_ALT,
        mavutil.mavlink.MAV_CMD_NAV_WAYPOINT,
        0, 1, 0, 3, 0, 0,
        int(lat * 1e7), int(lon * 1e7), alt, 0)

# seq 0 HOME'dur: len(WPS) + 1 gonderilir.
m.mav.mission_count_send(m.target_system, m.target_component, len(WPS) + 1, 0)

ack, served = None, []
t0 = time.time()
while time.time() - t0 < 40:
    msg = m.recv_match(type=['MISSION_REQUEST', 'MISSION_REQUEST_INT', 'MISSION_ACK'],
                       blocking=True, timeout=5)
    if msg is None:
        continue
    if msg.get_type() == 'MISSION_ACK':
        ack = msg
        break
    served.append(msg.seq)
    m.mav.send(item(msg.seq))

print("Istenen seq listesi :", served)
print("MISSION_ACK type    :", ack.type if ack else None)
assert ack is not None and ack.type == 0, "ACK gelmedi ya da reddedildi"
assert len(served) == len(WPS) + 1, "Otopilot her item'i istemedi -> gorev eksik!"
print("SONUC: gorev yuklendi ve el sikismasi teyit edildi.")

Doğru çalışınca ne görürsün

Kodu çalıştırdığında şunu görürsün:

Kod
Istenen seq listesi : [0, 1, 2, 3]
MISSION_ACK type    : 0
SONUC: gorev yuklendi ve el sikismasi teyit edildi.

3 waypoint göndermene rağmen istenen seq listesi 4 eleman, çünkü seq 0 HOME'dur ve sayıma dahildir. Bunu atlarsan son waypoint'in sessizce kaybolur.

Silme onayını okumazsan ne görürsün

CLEAR_ALL'in onayını tüketmeyen, ilk MISSION_ACK'i yakalayıp çıkan bir kod şuna benzer bir çıktı verir:

Kod
HEARTBEAT sys=1 comp=0
GPS OK fix=6 sat=10
ACK: MISSION_ACK {target_system : 255, target_component : 0, type : 0, mission_type : 0}
UPLOAD OK, servis edilen seq: []
Traceback (most recent call last):
  File "mission_test.py", line 78, in <module>
    print("READBACK count =", cnt.count)
AttributeError: 'NoneType' object has no attribute 'count'

Servis edilen seq listesi BOŞ. Otopilot hiçbir item istemedi, ama ekranda type=0 bir ACK var. Kod "başarılı" dedi, araçta görev yok.

Yani MISSION_ACK tek başına yüklemenin kanıtı değildir. Kanıt, otopilotun her seq için MISSION_REQUEST göndermiş olmasıdır.

Örnek: Yük bırakma görevinde bırakma noktasını son dakikada değiştirip yeni rotayı sahada yüklüyorsun. Kod ilk onayı görüp "yüklendi" derse, AUTO'ya aldığında drone yerinden kıpırdamaz, çünkü araçta görev yoktur. Kodun ekrana bastığı istenen seq listesine bakmak bunu daha AUTO'ya geçmeden yakalar: liste boşsa yeni görev araçta değildir.

Yarışma koşullarında bu kod yetmez

Savaşan İHA sahasında bu minimal kodun açıkta bıraktığı noktalar var:

  • Geri okuma yok: Otopilot ACK verdi diye koordinatlar doğru yazıldı demek değil. MISSION_REQUEST_LIST ile geri okuyup metre cinsinden karşılaştırmak gerekir.
  • AUTO'da varış teyidi yok: Görev yüklenmesi ile görevin uçulması ayrı şeyler. MISSION_ITEM_REACHED dinlenmeden "waypoint'e gitti" denemez.
  • Telemetri kaybı senaryosu yok: Gerçek linkte MISSION_REQUEST paketi düşerse otopilot tekrar ister; kodun bunu yeniden gönderecek şekilde kurgulanmış olmalı.
  • Kart bazlı seri port farkları: Pixhawk TELEM2, Cube ve Matek kartlarında SERIALx_PROTOCOL ve baud ayarları farklıdır; yanlış ayarda hiç MISSION_REQUEST gelmez.

Hata Mesajları

İlk iki satır doğru koddaki kontrollerden, üçüncüsü tuzağa düşen kodun çıktısından gelir. Hangisini gördüğün, yüklemenin nerede kaldığını söyler.

AssertionError: Otopilot her item'i istemedi -> gorev eksik!

Doğru koddaki ikinci kontrol tuttu: onay geldi ama istenen seq sayısı waypoint sayısı + 1 değil. Görev araçta eksik ya da hiç yok; istenen seq listesine bak.

AssertionError: ACK gelmedi ya da reddedildi

Doğru koddaki ilk kontrol tuttu: 40 saniye içinde onay gelmedi ya da onayın type değeri 0 değil. Bağlantıyı ve gönderilen öğeleri kontrol et.

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

Tuzağa düşen kodun çıktısında boş seq listesinin hemen ardından gelir. Geri okuma isteğine yanıt gelmedi ve kod boş yanıtın count alanını okumaya çalıştı; araçta görev yok.

Bu yazıyı okuyanlara

Görev yükleme, geri okuma, AUTO'da varış teyidi ve kart bazlı seri port ayarlarının tamamı Python ile Sıfırdan İHA Kontrolü Eğitimi içinde adım adım işleniyor.

Yapay Zeka ve İHA Simülasyon Sanal Makinesi: ArduPilot SITL, ROS Noetic ve Gazebo 11 kurulu gelir; simülasyonu kurulumla uğraşmadan başlat.

Bu yazı işinize yaradı mı?

Ücretsiz kaynakPixhawk ve ArduPilot hata mesajları sözlüğüBu yazıdaki 2 mesaj ve benzerleri sözlükte: ne demek, neden çıkar, ilk neye bakılır.