Integrate asynchronous GPS IMU fusion

This commit is contained in:
2026-07-16 23:49:43 +03:00
parent 38a96dd88f
commit 7cc3eb2a54
80 changed files with 3901 additions and 553 deletions
+135 -13
View File
@@ -12,6 +12,55 @@ Bu bölüm yeni bir geliştirme oturumunun nereden devam edeceğini tek yerde
özetler. Aşağıdaki Python model ve bare-metal C uygulaması aynı problemi çözer,
fakat aynı program değildir:
### Asenkron IMU/GPS düzeltmesi ve sentetik oran matrisi
Önceki prototipte 52 Hz ST akışından yalnız yaklaşık 250 ms'de bir ham örnek
seçiliyordu. Bu inertial downsampling değildir: kısa gyro hareketi iki seçilen
örneğin arasında kalınca değişen gravity vektörü görülüyor, dönüş görülmüyor ve
yanlış yatay ivme entegre ediliyordu. Linux C hızlı-eğim testinde bu yol 8.169 m
tepe yatay hata ve 1.554 m/s kalıcı hız üretti.
Bu seçim katmanı kaldırıldı. Artık her raw sample kendi timestamp'iyle işlenir;
ardışık accel/gyro örnekleri midpoint mechanization ile entegre edilir. GPS,
IMU'dan bağımsız bir position observation'dır. WLS yalnız geçerli olduğunda
ölçüm epoch'unda uygulanır; epoch iki IMU sample'ı arasındaysa input lineer
interpolate edilir, update sonrası kalan IMU geçmişi current-time horizon'a
replay edilir. Ana döngü IMU kuyruğunu WLS'den önce ve sonra tamamen boşaltır.
`async_rate_matrix_test.c` aynı üretim C kaynaklarına 52 Hz timestamp'li IMU,
100/200/1000 ms GPS, 73/310 ms delivery delay, farklı eksenlerde ivmelenme ve
fren, yaw dönüşü ve 10--18 s GPS outage verir. Sonuçlar sırasıyla 0.172/0.180/
0.389 m yatay RMSE ve outage sırasında 0.634/0.671/0.822 m tepe hatadır; üçünde
de GPS recovery kabul edilmiş, false ZUPT ve NIS reject sıfırdır. Tam GPS'siz
koşu da kendine konum feed etmeden yerel dead-reckoning yapar: global origin
false kalır, kovaryans büyür ve 25 s sonunda 3.674 m drift oluşur. Bu drift
gizlenmez; mutlak konumun IMU-only durumda gözlenememesinin beklenen sonucudur.
`gps_reacquisition_test.c`, canlı UART'ta görülen kötü ilk GPS fix'i senaryosunu
ENU'da 80/40/-170 m başlangıç ofsetiyle tekrarlar. Hard NIS kapısı tek başına
sonraki doğru fix'leri sürekli reddettiği için fusion engine zaman tabanlı bir
position reacquisition uygular: son başarılı position fusion üzerinden yedi
saniye timeout geçtikten ve en az üç rejected fix kendi içinde devamlı olduktan
sonra yalnız position state resetlenir. Hız, attitude ve IMU bias'ları korunur.
Test 100/200/1000 ms GPS periyotlarında sıfır son hata üretir; ayrı
150/-120/+80 m tek-fix testi aykırı ölçümün reddedildiğini ve state reset
oluşturmadığını doğrular.
Testin `--trace` seçeneği UART'a benzer `IMU ts=...`, `GPS ts=... arrival=...`
satırları üretir. Standart regression komutu:
```sh
make -C soc/software/fusion/tests test
```
`platform_scenario_matrix_test.c` ayrıca stationary/tilt/vibration, yaya,
trafik ışığında duran otomobil ve ani dönüşlü/yüksek ivmeli uçak profillerini;
200/500/1000 ms GNSS ile 19/20/200/300 ms IMU'nun 48 kombinasyonunda çalıştırır.
GNSS dört uydu kullanır, ilk bölümde 5--10 m, sonra 3--5 m sınıfı yatay gürültü,
3 saniye outage ve 2 saniye tutarlı büyük hata içerir. Kısa hata yedi saniyelik
recovery timeout'unu açamaz. 200/300 ms IMU yüksek dinamikteki doğruluk kaybıyla
birlikte açıkça raporlanır; test bunu daha sık IMU varmış gibi gizlemez.
```text
Offline model:
UART GPS + IMU logları -> Python parser -> fixed/adaptive ESKF -> CSV/grafik/harita
@@ -213,16 +262,16 @@ yoktur.
Temel parçalar:
- `gps_system/src/eskf.c`: ENU konum/hız, body-to-ENU quaternion, accel bias,
- `gps_system/src/fusion/eskf.c`: ENU konum/hız, body-to-ENU quaternion, accel bias,
gyro bias ve 15x15 covariance içeren 15-hata-durumlu ESKF;
- `gps_system/src/fusion_motion.c`: bootstrap/stationary/moving/candidate
- `gps_system/src/fusion/fusion_motion.c`: bootstrap/stationary/moving/candidate
durum makinesi, filtrelenmiş jerk ve ZUPT izni;
- `gps_system/src/fusion_engine.c`: başlangıç kalibrasyonu, asenkron IMU/GPS,
- `gps_system/src/fusion/fusion_engine.c`: başlangıç kalibrasyonu, asenkron IMU/GPS,
NIS kapısı ve gecikmiş GPS için fixed-lag IMU replay;
- `gps_system/src/fusion_gps_adapter.c`: WGS-84 LLH/ECEF/ENU dönüşümü ve
- `gps_system/src/fusion/fusion_gps_adapter.c`: WGS-84 LLH/ECEF/ENU dönüşümü ve
covariance tabanı;
- `gps_system/src/tdk_icm42688.c`: ICM-42688-P SPI/INT1 sürücüsü;
- `gps_system/src/navigation_fusion.c`: GPS ve IMU kuyruklarını algoritmaya
- `gps_system/src/drivers/imu/tdk_icm42688.c`: ICM-42688-P SPI/INT1 sürücüsü;
- `gps_system/src/fusion/navigation_fusion.c`: GPS ve IMU kuyruklarını algoritmaya
bağlayan üst koordinatör.
### ESKF state ve matematik sınırı
@@ -270,6 +319,64 @@ Default ESKF process/başlangıç değerleri:
| Maksimum propagation alt adımı | 20 ms |
| Konum NIS kapısı | 16.266236, 3 DOF %99.9 |
### Innovation rejection, recovery ve katman siniri (2026-07-16)
Standart ESKF position update'i tek basina buyuk ve kalici bir baslangic
ofsetini duzeltemez. GPS--INS residual'i NIS kapisini astiginda olcum state'e
hic uygulanmaz; state GPS'e yaklasmadigi icin sonraki dogru GPS fix'leri de
ayni nedenle sonsuza kadar reddedilebilir. NIS yalniz iki bilgi kaynaginin
tutarsiz oldugunu soyler. GPS'in mi hatali, yoksa ataletsel cozumun mu yanlis
ankrajlandigini matematiksel update tek basina belirleyemez.
Bu nedenle sorumluluk iki katmana ayrilir:
- `eskf.c` innovation, innovation covariance, NIS gate, kabul edilmis Kalman
correction ve covariance bakimindan dogru position-reset primitive'ini
icerir. Rejected olcumu gizlice correction'a sokmaz ve NIS'i bypass etmez.
- `fusion_engine.c` sensor gecmisi ve zaman bilgisine sahip supervisor'dur.
Ardisik rejected GNSS fix'lerinin kendi aralarinda zamansal olarak tutarli
olup olmadigini izler ve gerekli recovery/reset kararini burada verir.
Mevcut yalın recovery, son başarılı position fusion'dan sonra yedi saniyelik
timeout dolmuşsa ve en az üç rejected position fix'i kendi arasında zamansal
tutarlıysa yalnız position state ve position covariance'ini GNSS'e yeniden
ankrajlar. Position cross-covariance'lari gecersiz korelasyon tasimamasi icin
sifirlanir; velocity, attitude ve IMU bias state'leri korunur. Hard NIS gate
aktif kalir ve tek aykiri olcum reset uretemez. Bu bir innovation-bypass
workaround'u degil, kontrollu state recovery mekanizmasidir.
PX4 EKF2 de ayni temel ayrimi yapar. Generic `fuseHorizontalPosition()` yalniz
innovation testinden gecen olcumu fuse eder. GNSS'e baslama, quality check,
`time_last_fuse` timeout'u, state reset, fusion stop ve sensor-fault kararlari
ayri GNSS control akisindadir. Otomatik modda baska yatay konum kaynagi yoksa
uzun fusion timeout'undan sonra GNSS'e reset yapilabilir; alternatif aiding
varsa veya dead-reckoning politikasinda GNSS durdurulabilir/fault kabul
edilebilir. Kaynaklar:
- <https://github.com/PX4/PX4-Autopilot/blob/main/src/modules/ekf2/EKF/aid_sources/gnss/gps_control.cpp>
- <https://github.com/PX4/PX4-Autopilot/blob/main/src/modules/ekf2/EKF/position_fusion.cpp>
- <https://docs.px4.io/main/en/advanced_config/tuning_the_ecl_ekf>
Mevcut recovery PX4'teki aiding yoneticisinin sade bare-metal karsiligidir;
nihai mimari hedefi asagidaki acik GNSS aiding durum makinesidir:
```text
DISABLED -> STARTING -> FUSING -> FAULTED/RECOVERING
```
Karar yalniz rejected-candidate suresine degil son basarili position fusion
zamanina baglanmalidir. Uydu sayisi, finite covariance, DOP, WLS integrity ve
alternatif aiding kaynaklari birlikte degerlendirilmelidir. Tam dort uyduda
WLS residual redundancy/chi-square DOF bulunmadigi icin temporal consistency
daha onemlidir. Ileride Doppler velocity ayri innovation, fusion timeout ve
velocity-reset politikasi ile fuse edilmelidir. Yatay position ve height da
barometre gibi ek kaynaklar geldiginde birbirinden bagimsiz yonetilmelidir.
Baslangic GNSS'i icin mutlak bir dogruluk referansi yoksa tutarli fakat yanlis
bir GNSS kumesini otomatik olarak gercek konumdan ayirmak temel olarak mumkun
degildir. Kisa bir stable-fix/startup-quality penceresi riski azaltir, fakat
spoofing veya tutarli multipath'e karsi tek basina kanit degildir.
### Asenkron veri akışı ve timestamp
IMU ve GPS aynı local monotonic CPU/CLINT tick alanında timestamp edilir.
@@ -313,6 +420,13 @@ verir. Yaw gravity ile gözlenemediği için başlangıçta sıfır referanslı
Benzer şekilde stationary IMU ile yatay accel bias ve küçük tilt tamamen
ayrılamaz; sonraki GPS/kinematik update'ler bu error-state'leri düzeltir.
IMU motion-state eşikleri tanılama için tutulur, fakat ZUPT yetkisini tek başına
vermez. PX4 ayrımına uygun olarak `fusion_rest_detector` titreşim metriklerini
izler ve dışarıdan gelen `platform_landed` kapısıyla birleşir. Prototipin unarmed
bench modu landed=true başlar; gerçek araç kontrolü bu değeri kendi state'inden
güncellemelidir. Sessiz IMU, landed=false iken sabit hızlı hareketi stationary
ilan edemez.
Motion-state default eşikleri:
| Karar parametresi | Değer |
@@ -328,12 +442,20 @@ Motion-state default eşikleri:
| Stationary'e dönüş quiet dwell | 1.0 s |
| Zayıf hareket doğrulaması | 3 ardışık IMU örneği |
Güçlü accel/gyro/jerk veya yüksek ESKF hızı stationary state'ten tek örnekte
çıkabilir. Geri dönüş daha konservatiftir: quiet IMU, düşük ESKF hızı, aktif
GNSS-moving veto olmaması ve 1 s dwell birlikte gerekir. ZUPT ile zero-gyro
update yalnız gerçek `STATIONARY` state'inde, her IMU örneğinde değil 20 Hz'de
uygulanır. ZUPT velocity sigma 0.03 m/s, zero-gyro sigma eksen başına
0.01 deg/s'dir.
Güçlü accel/gyro/jerk veya yüksek ESKF hızı motion tanılamasını tek örnekte
moving'e çıkarabilir. ZUPT ve zero-gyro ise yalnız ardışık iki timestamp'li
örnekte dış supervisor `vehicle_at_rest=true` verdiğinde 200 ms periyotla
uygulanır. ZUPT velocity sigma 0.20 m/s'dir. Zero-gyro aynı 200 ms penceredeki
delta-angle toplamından ortalama açısal hız üretir; tek bir örneği bias diye
kabul etmez. Bu politika PX4 EKF2 `ZeroVelocityUpdate`/`ZeroGyroUpdate` ve land
detector katman ayrımının bare-metal karşılığıdır.
Kaynaklar:
- <https://github.com/PX4/PX4-Autopilot/blob/main/src/modules/ekf2/EKF/aid_sources/ZeroVelocityUpdate.cpp>
- <https://github.com/PX4/PX4-Autopilot/blob/main/src/modules/ekf2/EKF/aid_sources/ZeroGyroUpdate.cpp>
- <https://github.com/PX4/PX4-Autopilot/blob/main/src/modules/land_detector/LandDetector.cpp>
- <https://github.com/PX4/PX4-Autopilot/blob/main/src/modules/sensors/vehicle_imu/VehicleIMU.cpp>
GPS motion evidence, ardışık kabul edilmiş ENU konumları arasındaki yatay
displacement için 2 DOF `9.21034` (%99) NIS ve en az 0.50 m/s hız ister. Moving
@@ -836,7 +958,7 @@ azınlık TOW'unu çoğunluğa kopyalayan geçici recovery yolu da kaldırıldı
veya problemli kanal reject edilir. TOW değeri sessizce başka kanalın
değeriyle değiştirilmez.
Üretim kodu `header/gps_time_anchor.h` ve `src/gps_time_anchor.c` içindedir.
Üretim kodu `header/gps/gps_time_anchor.h` ve `src/gps/gps_time_anchor.c` içindedir.
`parse_subframe()` artık TOW state'ini değiştirmez; yalnız HOW TOW değerini
dışarı verir. `gps_time_from_sample_anchor()` her nav-solve için GPS zamanını
son HOW ve iki receiver-sample latch'i arasındaki farktan baştan üretir.