feat(pps): add adaptive disciplined timing loop

This commit is contained in:
2026-07-25 17:56:41 +03:00
parent 0f6b3482c5
commit ecbb8d0b68
39 changed files with 4505 additions and 96 deletions
+78 -12
View File
@@ -7,7 +7,7 @@ event-driven Python modelidir.
Bu bir genel amaçlı GNSS simülatörü değildir. Özellikle aşağıdaki proje
davranışlarını taklit eder:
- RF `ABS_SAMPLE` sayacı: `16.368 MHz`, 32 bit ve wrap eden sayaç.
- RF `ABS_SAMPLE` sayacı: `16.367981 MHz`, 32 bit ve wrap eden sayaç.
- Tracking/PPS sayacı: `125 MHz` free-running sayaç.
- Navigation solve periyodu: `NAV_SOLVE_TIMER=10`, yani `200 ms`.
- Ortak navigation bit transmit epoch'u ve uyduların farklı propagation
@@ -18,11 +18,21 @@ davranışlarını taklit eder:
corrected_abs = ABS_SAMPLE - REM_CODE_PHASE / 1.023e6
```
- Integer RF sample kenarinda yakalanan 125 MHz counter da ayni code
boundary'ye geri cekilir:
```text
capture_correction_ticks =
round((REM_CODE_PHASE / 1.023e6) * (125e6 / 16.367981e6))
corrected_capture = raw_capture - capture_correction_ticks
```
Model ve C ayni 8 ns integer mailbox yuvarlamasini kullanir.
- `gps_unwrap_corrected_abs_sample()` ile aynı signed modulo-32 unwrap.
- `gps_ip.c` ile aynı pseudorange datum'u:
```text
precise_ms_i = abs_i / 16368 - minimum + 68.802
precise_ms_i = abs_i / 16367.981 - reference + 68.802
P_i = precise_ms_i * c / 1000 + satellite_clock_i * c
```
@@ -45,6 +55,8 @@ Software dizininden:
```bash
python3 pps_python/simulate_pps.py
python3 -m unittest pps_python/test_pps_model.py
python3 pps_python/simulate_adaptive_pps.py
python3 -m unittest pps_python/test_pps_adaptive.py
```
Kısa veya farklı PI koşusu:
@@ -92,11 +104,12 @@ olarak yazılır; simülasyon sonuç sayfaları `output/` altındaki PNG'leri ku
## Modeldeki doğru zaman bağı
Mevcut observation denkleminde WLS bias doğrudan PPS fazı değildir. Minimum
kanal için yaklaşık ilişki:
Mevcut observation denkleminde WLS bias doğrudan PPS fazı değildir. İlk
çözümde seçilen ve mevcut kaldığı sürece korunan referans kanal için yaklaşık
ilişki:
```text
b/c = STARTOFFSET - signal_flight_time_min
b/c = STARTOFFSET - signal_flight_time_ref
```
Bu nedenle doğru GPS referansı:
@@ -105,7 +118,7 @@ Bu nedenle doğru GPS referansı:
GPS_TIME_AT_CAPTURE = transmit_epoch_TOW + STARTOFFSET - b/c
```
ile kurulur ve minimum kanala ait `tracking_tick_125` ile eşlenir. Referans
ile kurulur ve referans kanala ait `tracking_tick_125` ile eşlenir. Referans
uydu değiştiğinde raw `b/c` milisaniyeler seviyesinde basamak yapabilir; TOW ve
eşlenmiş timestamp ile oluşturulan GPS zamanı ise sürekli kalır. Üretilen ilk
grafik bu farkı açıkça gösterir.
@@ -148,14 +161,16 @@ bu üç etkiyi ayrı gösterir.
1. Raw 125 MHz counter resetten itibaren free-running çalışır.
2. İlk geçerli HOW week/6-second mutlak zaman etiketini sağlar; ilk hardware
delivery epoch'u için 160 ms sabit readout düzeltmesi ayrıca eklenir.
3. İlk coherent WLS çözümünde minimum corrected-ABS kanalının uçuş süresi
3. İlk coherent WLS çözümünde minimum corrected-ABS kanalı datum olarak
seçilir; aynı SVID mevcut kaldığı sürece onun uçuş süresi
`STARTOFFSET - b/c` ile elde edilir.
4. Bu receive GPS zamanı aynı kanalın yakalanmış 125 MHz timestamp'ıyla
eşlenerek PPS accumulator coarse-align edilir.
5. Sonraki çözümler aynı eşleşmeden residual phase error üretip PI'yi besler.
Minimum kanal yalnız zaman datum'unu seçer; `b` bütün WLS uydularıyla beraber
çözülür. İstenirse çözüm sonrası her uydu için
Referans kanal yalnız zaman datum'unu seçer; `b` bütün WLS uydularıyla beraber
çözülür. Referans kaybolursa yeni en erken kanal seçilir ve filtre bilinçli
coarse re-anchor edilir. İstenirse çözüm sonrası her uydu için
`(rho + iono + tropo) / c - satellite_clock` hesaplanıp kendi timestamp'ına
bağlanabilir. Doğru hizalamada bunların hepsi aynı receiver time mapping'ini
vermelidir; bu ayrıca güçlü bir coherency testi olur.
@@ -198,6 +213,56 @@ Bunlar Q2.46 donanım katsayılarının ilk çalışma değerleridir. Karttan cl
serisi ve oscillator drift ölçüldükten sonra Allan deviation/phase-noise
davranışına göre yeniden ayarlanmalıdır.
Donanım loop filter'ı bu PI yapısının kendisidir. Ayrı bir phase-IIR veya
derivative/D kolu yoktur. Küçük yazılım filtresi yalnız WLS clock-bias
ölçümünün residual gürültüsünü Doppler clock-drift prediction sonrasında
sınırlar; PI dinamiğinin yerine geçmez. Acquisition sırasında `0.12 Hz`,
precision modunda `0.035 Hz`, zayıf geometride robust `0.012 Hz` doğal frekans
kullanılır. `Kp`, `Ki`, `20 ppm` slew limiti ve lock politikası çalışma anında
profil ile değişir; integrator normal profil geçişlerinde korunur. Valid lock
için beş ardışık residual'ın 125 MHz saatinde sekiz tick (`64 ns`) içinde
olması gerekir. Üretim profilleri tek seyrek WLS sıçramasında fiziksel pulse
kaçırmamak için lock'u ancak `128 tick = 1.024 us` üstünde bırakır; watchdog,
quality holdover ve slew clamp daha büyük arızaları ayrıca sınırlar.
## Adaptif PPS senaryo matrisi
Tam fixed-point/holdover matrisi:
```bash
python3 -m pps_python.analyze_pps_scenarios
```
Model, 125 MHz çıkış grid'ini de PPS kenarına quantize eder. 2026-07-25
regresyonunda ayrı donanım IIR olmadan:
| Senaryo | Lock | İlk lock p95 | Edge jitter p95 |
|---|---:|---:|---:|
| temiz precision | 30/30 | 10.80 s | 5.50 ns |
| 320 ns kart noise + outlier | 50/50 | 12.31 s | 13.62 ns |
| 650 ns zayıf geometri | 30/30 | 13.77 s | 12.31 ns |
| başlangıç 1.1 us noise, sonra temiz | 30/30 | 16.93 s | 8.45 ns |
| aralıklı noise burst, sonra recovery | 30/30 | 12.00 s | 10.82 ns |
| iki uydu-kaybi aralığı ve recovery | 30/30 | 11.60 s | 12.57 ns |
| Doppler kaybı ve recovery | 30/30 | 11.60 s | 12.41 ns |
| +18 ppm, slew sınırına yakın | 30/30 | 18.20 s | 12.01 ns |
| +25 ppm, 20 ppm sınırının dışında | 0/10 | lock yok | geçerli edge yok |
Ek olarak kısa/uzun WLS kesintisi, quality profile geçişi, multipath basamağı
ve hiç Doppler olmayan fallback yolu test edilir. Linux
`test_gps_pps_adaptive_loop.c` aynı geçişli ortamları C implementasyonu ve
Q32/Q46 aritmetiğiyle çoklu seed altında tekrarlar. `test_gps_pps_quality.c`
NaN, dört uydunun altına düşme, eşik sınırları ve histerezisi;
`test_gps_pps_time_filter.c` drift prediction, gap/re-anchor ve hard-outlier
reddini sınar.
İki zaman eşiği bilinçli olarak ayrıdır: iki saniyelik watchdog gözlem yokken
PPS validliğini holdover'a indirir; aynı referans SVID için Doppler-predicted
clock-bias ve PI state'i 30 saniyeye kadar korunur. Modelde 15 saniyelik WLS
ve uydu kaybı boşlukları ek coarse commit/unlock üretmeden geri döner.
30 saniyeyi aşan boşluk veya referans SVID değişimi güvenli coarse re-anchor
yapar.
## C kodu analizi sırasında görülen önemli noktalar
1. `leastSquaresSTD()` artık aynı başarılı çözümün `x/y/z/b` vektörünü çağırana
@@ -210,9 +275,10 @@ davranışına göre yeniden ayarlanmalıdır.
3. Pseudorange her epoch'ta `minimum` ile yeniden normalize edildiği için RF
counter'ın mutlak fazı WLS observation'da iptal olur. RF frequency error ise
uyduların arrival-time farklarını ölçeklediği için tamamen iptal olmaz.
4. PPS tarafı array'in ilk elemanını referans kabul etmiyor; minimum corrected
ABS kanalının TOW'u ve aynı nav-solve olayındaki C125 capture'ı birlikte
taşınıyor.
4. PPS tarafı array'in ilk elemanını referans kabul etmiyor; ilk geçerli
çözümde minimum corrected ABS kanalı seçiliyor ve aynı SVID coherent
snapshot'ta kaldığı sürece datum sabit tutuluyor. O kanalın TOW'u ve aynı
nav-solve olayındaki C125 capture'ı birlikte taşınıyor.
5. `POSTPONE_TOW=0.160`, hardware'ın mevcut subframe'i doğrulamak için takip
eden subframe'den 8 bit daha beklemesinden oluşan sabit readout gecikmesidir.
Uydu konum/saat epoch'u buna göre 160 ms ileri alınır. Bu değer signal