353 lines
15 KiB
Markdown
353 lines
15 KiB
Markdown
# GPS PPS zaman modeli
|
||
|
||
Bu dizin, mevcut C navigation yolunu değiştirmeden önce WLS clock-bias ile
|
||
125 MHz PPS kontrol döngüsünün zaman davranışını incelemek için hazırlanmış
|
||
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.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
|
||
delay'lerle art arda tracking olayı üretmesi.
|
||
- Firmware'deki corrected sample denklemi:
|
||
|
||
```text
|
||
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 / 16367.981 - reference + 68.802
|
||
P_i = precise_ms_i * c / 1000 + satellite_clock_i * c
|
||
```
|
||
|
||
- `NavEquations.c` ile aynı dört state:
|
||
|
||
```text
|
||
[ECEF_X, ECEF_Y, ECEF_Z, common_bias_m]
|
||
```
|
||
|
||
- Uydu saat düzeltmesi, Earth-rotation düzeltmesi, Klobuchar, aktif C
|
||
troposfer modeli ve URA/elevation ağırlıkları.
|
||
- İlk 20 saniye 4 uydu, sonra 5 ve 7 uydu; ayrıca drop/re-acquisition
|
||
senaryosu.
|
||
- WLS compute gecikmesi, APB gecikmesi, yapay CPU stall ve 125 MHz PI loop.
|
||
|
||
## Çalıştırma
|
||
|
||
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
|
||
```
|
||
|
||
## Bit-level Linux PPS uçtan uca testi
|
||
|
||
Bit üretiminden trusted PPS karşılaştırmasına kadar deterministik mutlak zaman
|
||
regresyonu ayrı `pps_end_to_end_validation` paketine taşınmıştır. Ayrıntılı
|
||
kapsam, 20 ms teşhisi ve donanım doğrulama adımları için
|
||
[`pps_end_to_end_validation/README.md`](../pps_end_to_end_validation/README.md)
|
||
dosyasına bakın.
|
||
|
||
Software dizininden çalıştırma:
|
||
|
||
```bash
|
||
python3 -m pps_end_to_end_validation.pps_end_to_end
|
||
python3 -m unittest pps_end_to_end_validation/test_pps_end_to_end.py
|
||
```
|
||
|
||
```text
|
||
scenario bits correction reference error DUT - trusted PPS
|
||
current-rtl/180ms 9 180 ms -0.000032 ms +0.000032 ms
|
||
current-rtl/160ms 9 160 ms -20.000032 ms +20.000032 ms
|
||
current-bit/160ms 8 160 ms -0.000032 ms +0.000032 ms
|
||
```
|
||
|
||
Kısa veya farklı PI koşusu:
|
||
|
||
```bash
|
||
python3 pps_python/simulate_pps.py \
|
||
--duration 300 \
|
||
--loop-bandwidth-hz 0.02 \
|
||
--max-slew-ppm 10
|
||
```
|
||
|
||
Varsayılan çıktılar `pps_python/output/` altına yazılır:
|
||
|
||
- `01_wls_time_model.png`: raw WLS bias, doğru zaman rekonstrüksiyonu,
|
||
konum hatası ve referans uydu değişimi.
|
||
- `02_latency_timeline.png`: satellite arrival span, WLS ve APB gecikmeleri.
|
||
- `03_pi_loop_response.png`: timestamp'lı PI, free-run ve yanlış APB-now
|
||
davranışı.
|
||
- `04_pps_edge_error.png`: 8 ns çıkış quantization dahil PPS kenar hatası.
|
||
- `05_startup_tow_alignment.png`: ilk HOW, propagation delay ve WLS ile
|
||
coarse PPS hizalama karşılaştırması.
|
||
- `epoch_results.csv`: bütün epoch sonuçları.
|
||
- `summary.txt`: RMS ve percentile özeti.
|
||
|
||
Matplotlib GUI kullanmaz; grafikler doğrudan PNG üretilir.
|
||
|
||
## Teknik PDF raporu
|
||
|
||
Teori, mevcut C/RTL mapping'i, LNAV/HOW/subframe zaman şemaları, WLS bias
|
||
türetimi, 125 MHz cross-timestamp, APB commit ve PI mimarisi tek raporda:
|
||
|
||
```text
|
||
GPS_PPS_Teori_Proje_Mapping.pdf
|
||
```
|
||
|
||
Grafikler güncellendikten sonra raporu yeniden üretmek için:
|
||
|
||
```bash
|
||
python3 pps_python/simulate_pps.py
|
||
python3 pps_python/generate_report.py
|
||
```
|
||
|
||
Rapor A4, 27 sayfadır. `generate_report.py` içindeki şemalar PDF'e vektörel
|
||
olarak yazılır; simülasyon sonuç sayfaları `output/` altındaki PNG'leri kullanır.
|
||
|
||
## Modeldeki doğru zaman bağı
|
||
|
||
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_ref
|
||
```
|
||
|
||
Bu nedenle doğru GPS referansı:
|
||
|
||
```text
|
||
GPS_TIME_AT_CAPTURE = transmit_epoch_TOW + STARTOFFSET - b/c
|
||
```
|
||
|
||
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.
|
||
|
||
Raw `b/c` değerini PI phase error olarak doğrudan kullanmak doğru değildir.
|
||
|
||
Klasik GNSS denklemindeki `c*delta_t_r` clock bias ile buradaki `b` aynı datum
|
||
değildir: capture'ların ortak receiver zamanı önceden çıkarılmıştır. Doppler
|
||
velocity WLS'nin dördüncü state'i uydulara ortak receiver clock/frequency
|
||
drift'idir; fakat bu göreli `b` değerinin doğrudan türevi olarak kullanılmaz.
|
||
PPS modeli datumun değişimini seçilen referans uydunun geometrik range-rate'i,
|
||
broadcast satellite clock drift'i ve Doppler-WLS receiver velocity'sinden
|
||
hesaplar:
|
||
|
||
```text
|
||
bias_drift =
|
||
-reference_geometric_range_rate
|
||
+ c * reference_satellite_clock_drift
|
||
```
|
||
|
||
## İlk HOW ve PPS başlangıcı
|
||
|
||
`parse_subframe()` HOW Z-count alanını `6 s` ile çarpıp `tow.sec` yapar. Bu,
|
||
uydunun transmit subframe sınırı etiketidir. Full-subframe interrupt'ının
|
||
receiver'a ulaştığı an değildir.
|
||
|
||
Mevcut hardware, subframe doğrulama/parity akışında eski shift register'i
|
||
okuduğu için takip eden subframe'in dokuzuncu bitinde teslim yapar. Navigation
|
||
data 50 bit/s olduğu için sabit readout gecikmesi `9 × 20 ms = 180 ms` olur ve
|
||
production yazılımda `POSTPONE_TOW=0.180` ile temsil edilir. Bu yüzden ilk
|
||
teslim edilen subframe için:
|
||
|
||
```text
|
||
transmit_epoch_TOW = HOW_TOW + POSTPONE_TOW
|
||
GPS_TIME_AT_CAPTURE = transmit_epoch_TOW + STARTOFFSET - b/c
|
||
```
|
||
|
||
`POSTPONE_TOW` signal flight time veya receiver clock bias değildir; hardware
|
||
readout/pipeline epoch düzeltmesidir. Bundan sonra ayrıca uydu clock düzeltmesi
|
||
ve yaklaşık 65--85 ms signal flight time gelir.
|
||
|
||
Mevcut baremetal kodda `eph->tow.sec` raw HOW değerini tutmaya devam eder;
|
||
`satpos()` kullanım anında `eph->tow.sec + POSTPONE_TOW` hesaplar. PPS yolu da
|
||
epoch-aligned transmit time'ı baremetal navigation katmanında tam bir kez
|
||
oluşturmalıdır. PPS APB periferiki kendisine verilen GPS reference time'a
|
||
`POSTPONE_TOW` değerini tekrar eklememelidir.
|
||
|
||
Tracking RTL ileride current-bit candidate window ile sekizinci bitte validate
|
||
edecek şekilde düzeltilirse aynı release'de firmware değeri 160 ms'ye geri
|
||
alınmalıdır; RTL ve firmware düzeltmeleri birbirinden bağımsız uygulanamaz.
|
||
|
||
İlk HOW'un hangi kanaldan geleceği sadece uydunun yakınlığına bağlı değildir.
|
||
Acquisition tamamlanma anı, bit lock ve bir sonraki tam subframe sınırı çoğu
|
||
zaman propagation delay farkından daha baskındır. Monte Carlo startup modeli
|
||
bu üç etkiyi ayrı gösterir.
|
||
|
||
Önerilen ownership:
|
||
|
||
1. Raw 125 MHz counter resetten itibaren free-running çalışır.
|
||
2. İlk geçerli HOW week/6-second mutlak zaman etiketini sağlar; mevcut RTL'nin
|
||
ilk hardware delivery epoch'u için 180 ms sabit readout düzeltmesi ayrıca
|
||
eklenir.
|
||
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.
|
||
|
||
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.
|
||
|
||
## Compute ve APB gecikmesi
|
||
|
||
Doğru model şu çifti taşır:
|
||
|
||
```text
|
||
(GPS_TIME_AT_CAPTURE, TRACKING_COUNTER_AT_CAPTURE, epoch_sequence)
|
||
```
|
||
|
||
Commit anında peripheral geçen süreyi 125 MHz raw counter farkından ekler.
|
||
WLS/APB gecikmesi böylece faz ölçümünün içine girmez; yalnızca kontrol
|
||
komutunun gecikmesi olarak loop transfer fonksiyonunda kalır.
|
||
|
||
Karşılaştırma amacıyla `untagged APB-now` modeli eski GPS referansını APB
|
||
yazıldığı anda geçerli kabul eder. Bunun sonucu compute/APB gecikmesine yakın
|
||
milisaniyelik PPS faz hatasıdır. PI bunu oscillator hatasından ayıramaz.
|
||
|
||
## PI modeli
|
||
|
||
PI, raw 125 MHz sayacı değiştirmez. Ayrı GPS time accumulator'ın rate word'ünü
|
||
ayarlar:
|
||
|
||
```text
|
||
integrator += Ki * phase_error * update_period
|
||
rate_command = integrator + Kp * phase_error
|
||
```
|
||
|
||
Varsayılan katsayılar ikinci dereceden düşük bant genişlikli bir loop için:
|
||
|
||
```text
|
||
natural frequency = 0.035 Hz
|
||
damping = 0.9
|
||
maximum slew = 20 ppm
|
||
```
|
||
|
||
Bunlar Q2.46 donanım katsayılarının ilk çalışma değerleridir. Karttan clock-bias
|
||
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.
|
||
|
||
2026-07-26 Genesys2 logu ile kalibre edilen aynı-datum A/B testinde position
|
||
WLS clock-bias gürültüsü `15.87 m`, referans-datum drift'i yaklaşık
|
||
`291.75 m/s`, Doppler drift gürültüsü `3.47 m/s` ve oscillator hatası
|
||
`1.592 ppm` olarak modele verildi. Linux C fixed-point testinde Doppler
|
||
predictor clock-bias RMS'i `2.75 m`, yalnız son bias'i tutan fallback ise
|
||
`21.22 m` verdi. Python modeli sekiz seed'de hem phase RMS hem 125 MHz grid'e
|
||
quantize edilmiş edge-jitter p95 için predictor'un fallback'ten iyi kalmasını
|
||
regresyon koşulu yapar. Kart status register phase'i fiziksel pin jitter'i
|
||
değildir; `15-20 ns` çıkış hedefi son olarak scope/TIC ile ölçülmelidir.
|
||
|
||
İ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
|
||
çıkarıyor; PPS yalnız bu çağrıdaki `b` değerini kullanıyor.
|
||
2. `normVect(xVec)` C'de yalnız ilk üç elemanı okuyor. Dolayısıyla convergence
|
||
kararı XYZ update'e göre veriliyor; son clock update ayrıca kontrol
|
||
edilmiyor. Python model bu davranışı aynen taklit eder ve CSV'ye
|
||
`final_clock_update_m` yazar. PPS uygulamasından önce gerçek loglarda bunun
|
||
dağılımı incelenmelidir.
|
||
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; 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.180`, hardware'ın mevcut subframe'i eski shift register
|
||
üzerinden doğrulayıp dokuzuncu takip eden bitte teslim etmesinden oluşan
|
||
sabit readout gecikmesidir. Uydu konum/saat epoch'u buna göre 180 ms ileri
|
||
alınır. Bu değer signal
|
||
flight time veya WLS receiver clock bias ile birleştirilmemelidir. Mevcut
|
||
`satpos()` zaten kullanım anında bir kez ekler; PPS peripheral tekrar eklemez.
|
||
6. 125 MHz timestamp `ABS_SAMPLE` ve `REM_CODE_PHASE` ile aynı hardware
|
||
nav-solve eventinde per-channel bank'a latch ediliyor. ISR yalnız önceden
|
||
yakalanmış değeri okuyor; interrupt/WLS gecikmesi epoch'a karışmıyor.
|
||
|
||
## Sınırlar
|
||
|
||
- Satellite ephemeris orbitleri gerçek almanac dosyasından alınmıyor; gerçekçi
|
||
ECEF/azimuth/elevation geometrisi sentetik kuruluyor.
|
||
- Multipath ve atmosfer residual'ları elevation-dependent Gaussian modeldir.
|
||
- 16.368 ve 125 MHz clock'larda ortak ve bağımsız drift bileşenleri vardır;
|
||
gerçek kart spektrumu ölçülünce bunlar değiştirilmelidir.
|
||
- PPS edge sonucu 125 MHz için 8 ns grid'e quantize edilir. Bu, ölçüm
|
||
doğruluğunun otomatik olarak 8 ns olduğu anlamına gelmez.
|