Używanie rzeczywistych TLE konstelacji
Dołączony scenarios/orbit-sgp4-gps.toml zawiera już rzeczywiste TLE (dwuwierszowe zestawy elementów): zrzut gps-ops z Celestrak operacyjnej konstelacji GPS (Global Positioning System) skatalogowanej 2021-07-28, 30 satelitów, z strict_checksum = true. Każdy satelita jest propagowany za pomocą SGP4/SDP4 (Simplified General Perturbations 4 / Simplified Deep-space Perturbations 4), co zostało sprawdzone względem oficjalnych wektorów AIAA (American Institute of Aeronautics and Astronautics) 2006-6753. Ten sam zrzut jest dołączony jako tests/fixtures/celestrak/gps-ops_2021-07-28.txt, a scripts/fetch_tles.sh pobiera nowy. Przed przywołaniem z niego liczby opisującej geometrię należy przeczytać sekcję 3: ten scenariusz propaguje każdego satelitę od jego własnej epoki.
Jako syntetyczny, samodzielny przykład scenarios/orbit-real-tle.toml podaje sześć satelitów podobnych do GPS jako gołe rekordy z wierszem 2, propagowane jako analityczne elementy keplerowskie, a każdy scenariusz orbit bez bloku tle buduje konstelację Walkera.
Aby badać aktualną konstelację GPS (lub dowolną inną), należy wstawić świeży zrzut.
1. Pobranie aktualnego zrzutu#
Celestrak redystrybuuje zestawy elementów z katalogu NORAD (North American Aerospace Defense Command), odświeżane co najmniej raz dziennie. Dla GPS:
curl -o gps-ops.txt "https://celestrak.org/NORAD/elements/gp.php?GROUP=gps-ops&FORMAT=tle"
Inne przydatne grupy: galileo, glo-ops (GLONASS, rosyjski Global Navigation Satellite System), beidou, stations (ISS, International Space Station, i inne stacje załogowe).
Plik jest ciągiem rekordów trzywierszowych (nazwa, wiersz 1, wiersz 2). Parser Kshana ignoruje wiersze z nazwami, więc plik można wkleić bez zmian.
2. Wstawienie go do scenariusza#
W dowolnym scenariuszu orbitalnym należy ustawić blok konstelacji tle na zawartość zrzutu:
[constellation]
# Paste the Celestrak gps-ops block here (name/line1/line2 triples). Two real records
# from tests/fixtures/celestrak/gps-ops_2026-06-07.txt are shown; a real block has ~30.
strict_checksum = true # real Celestrak TLEs carry valid checksums; enforce them
tle = """
GPS BIIR-5 (PRN 22)
1 26407U 00040A 26158.26673196 .00000043 00000+0 00000+0 0 9990
2 26407 54.8526 215.5566 0121168 302.4173 18.5084 2.00557626189748
GPS BIIR-8 (PRN 16)
1 27663U 03005A 26157.61055816 .00000039 00000+0 00000+0 0 9995
2 27663 54.8837 215.3893 0147927 53.0597 289.9583 2.00561160171094
"""
(PRN to numer kodu pseudolosowego, który nadaje satelita GPS.)
Para wiersz 1 + wiersz 2 jest propagowana za pomocą SGP4/SDP4 (człony oporu i przestrzeni głębokiej); sam wiersz 2 jest traktowany jako analityczne średnie elementy keplerowskie. Oba rodzaje można mieszać.
strict_checksum = true odrzuca każdy wiersz, w którym suma kontrolna modulo 10 z kolumny 69 jest błędna — to dobra kontrola integralności świeżo pobranego pliku. Domyślnie ma wartość false, ponieważ syntetyczne scenariusze dydaktyczne używają zastępczych sum kontrolnych.
3. Uwagi o epokach — przeczytaj to przed przywołaniem liczby opisującej geometrię#
SGP4 propaguje każdego satelitę od jego własnej epoki TLE, a parse_propagators (w src/tle.rs) zwraca wyłącznie propagatory, więc czas scenariusza t jest stosowany jako tsince = t dla każdego satelity niezależnie. Jest to właściwa konwencja tylko wtedy, gdy wszystkie zestawy elementów w pliku mają wspólną epokę.
Plik grupy z Celestrak tego nie zapewnia. Plik jest pobierany w jednej chwili, ale zestaw elementów każdego satelity jest odświeżany we własnym rytmie, więc epoki w nim są rozłożone na kilka dni. Zmierzone na zestawach dołączonych do tego repozytorium (wiersz 1, kolumny 19–32):
| plik testowy | zestawy | rozrzut epok |
|---|---|---|
tests/fixtures/celestrak/gps-ops_2026-06-07.txt |
32 | 70,6 h |
tests/fixtures/celestrak/gps-ops_2021-07-28.txt |
30 | 76,4 h |
tests/fixtures/celestrak/galileo_2026-06-07.txt |
33 | 335,7 h |
70,6 h to 5,9 obiegu GPS. Po propagacji bez zmian fazowanie w płaszczyźnie jest pomieszane: satelity znajdują się na właściwych wysokościach i nachyleniach, ale nie tam, gdzie były w którymkolwiek jednym dniu, więc widoczny zbiór, DOP (dilution of precision) i każda obliczona z nich dostępność opisują konstelację, która nigdy nie istniała. Nic w parserze nie mierzy tego rozrzutu za użytkownika, a rodzaje orbit i integrity nie wyrównują epok: blok TLE w scenariuszu jest zawsze propagowany od epoki każdego satelity z osobna.
Zamiast tego należy zrobić tak. Epokę należy trzymać przy propagatorze, wybrać jeden chwilowy punkt odniesienia i przesunąć tsince każdego satelity względem niego. Tle::epoch_days_1950 jest publiczne, więc pętla parsowania jest krótka; tests/igs_real_data.rs (real_gps_tle_snapshot) jest przykładem roboczym w tym drzewie:
use kshana::orbit::Propagator;
use kshana::sgp4::wgs72;
use kshana::tle::parse_tle;
/// TEME position (m) of one satellite at `t` seconds after the common reference
/// instant `t_ref_jd` (a Julian date), not after its own TLE epoch.
fn aligned_teme_m(line1: &str, line2: &str, t_ref_jd: f64, t: f64) -> Result<[f64; 3], String> {
let tle = parse_tle(line1, line2)?;
let jd_epoch = 2_433_281.5 + tle.epoch_days_1950;
let prop = Propagator::Sgp4(Box::new(tle.to_sgp4(wgs72(), false)));
let tsince_s = (t_ref_jd - jd_epoch) * 86_400.0 + t;
Ok(prop.position_eci(tsince_s))
}
TEME to układ prawdziwego równika i średniego równonocy, w którym działa SGP4; tests/igs_real_data.rs obraca go do współrzędnych związanych z Ziemią za pomocą teme_to_ecef.
Jeśli epoki nie zostały wyrównane, trzeba o tym powiedzieć przy podawaniu liczby: jest to stwierdzenie o powłokach orbitalnych, a nie o rzeczywistym niebie.
O tym, jak duże ma to znaczenie, mówi pomiar w tests/araim_dual_real_data.rs, który stosuje te same przesunięcia (chwila odniesienia: najpóźniejsza epoka w połączonych plikach GPS + Galileo, 2026-06-07T07:21:04 UTC (Coordinated Universal Time)) w 24-godzinnym przebiegu dostępności ARAIM (advanced receiver autonomous integrity monitoring) dla dwóch konstelacji. Przy VAL (vertical alert limit) 12 m wyrównane niebo daje dla samego GPS 0,993, dla połączonych GPS+Galileo 1,000 i dla dwóch konstelacji odpornych na uszkodzenia konstelacji 0,990; niewyrównana konwencja epoki każdego satelity z osobna daje dla tych samych danych 0,208, 0,671 i 0,031 — to inny wniosek, a nie mały błąd.
Zobacz też#
README.md— scenariusze orbitalne.SCENARIOS.md— pola rodzajuorbit; rodzajeintegrity,gnss-sim,jammingiconstellation-designprzyjmują tę samą tabelęconstellation, aephemerisprzyjmuje pojedynczytle.INTEGRITY.md— silnik ARAIM, którym steruje test rzeczywistego nieba.src/tle.rs— parser (parse_propagators,ParseOpts { strict_checksum }).