Tutorial 1 — Minha primeira órbita: onde estão os satélites GPS
Kind: orbit · Cenário: scenarios/orbit-sgp4-gps.toml (cópia didática: scenarios/orbit.toml) · Dificuldade: iniciante · ~15 min
Ao final você terá propagado a constelação GPS operacional real, lido sua disponibilidade e geometria e exportado uma tabela de onde cada satélite realmente está no espaço — e saberá que essa tabela é validada contra uma referência externa, não contra si mesma.
O que este cenário é#
Os satélites GPS (Global Positioning System) dizem ao usuário onde ele está e que horas são. Antes de tudo isso, é preciso saber onde estão os satélites e quantos deles um usuário consegue ver. Isso é geometria, e a geometria define o piso da exatidão com que você pode ser posicionado (a diluição da precisão, ou DOP). Este tutorial:
- toma um instantâneo genuíno
gps-opsdo Celestrak da constelação GPS (2021-07-28, 30 satélites, elementos de duas linhas reais, TLEs), - propaga cada satélite com o modelo SGP4/SDP4 validado (Simplified General Perturbations 4 / Simplified Deep-space Perturbations 4),
- a cada passo de tempo determina quais satélites um usuário em órbita terrestre baixa consegue ver (linha de visada, ocultação pela Terra e uma máscara de elevação de 5°),
- transforma essa geometria em um PDOP (diluição da precisão de posição) e uma exatidão de posição, e
- exporta as posições reais dos satélites, centradas e fixas na Terra (ECEF), para um arquivo SP3 (Standard Product 3, o formato de órbita precisa do Serviço Internacional de GNSS, IGS; GNSS é Global Navigation Satellite System).
A espinha dorsal é: TLE → propagação SGP4 → ECEF por época → visibilidade → contagem de satélites visíveis → PDOP → sigma de posição = PDOP · σ_UERE, onde σ_UERE é o erro equivalente de alcance do usuário (o erro de medição de distância de 1-σ por satélite).
Execute#
cargo run -- scenarios/orbit-sgp4-gps.toml
Python:
import json, kshana
result = json.loads(kshana.run(open("scenarios/orbit-sgp4-gps.toml").read()))
print(result["geometry"]["best_pdop"], result["geometry"]["best_position_sigma_m"])
Ou abra o Studio no navegador e escolha o cenário de órbita.
Leia o resumo de uma linha#
A execução determinística (seed = 17) imprime:
scenario 4c51512369a6 | 345/361 samples GNSS-nominal | best PDOP 1.07 pos 1.07m | quantum holdover 0s p95 2.59e-5ns integrity 1.000 security n/a (no attack) | classical holdover 0s p95 6.7ns integrity 1.000 security n/a (no attack)
Campo a campo:
scenario 4c51512369a6— o hash de 12 caracteres do cenário. Ele identifica as entradas exatas (seed, limiares, parâmetros do modelo, o bloco TLE). Altere qualquer entrada e ele muda; mantenha-as iguais e você reproduz a execução bit a bit. O mesmo hash é carimbado no rodapé do gráfico e no arquivo JSON (JavaScript Object Notation) de resultado.345/361 samples GNSS-nominal— dos 361 passos de tempo, o usuário tem uma solução utilizável em 345 deles (95,6 %). A execução é uma passagem de 12 h (43.200 s) com passo de 120 s.best PDOP 1.07— a melhor (menor) diluição da precisão de posição ao longo da passagem. Um PDOP perto de 1 é geometria excelente; quanto menor, melhor.pos 1.07m— a melhor exatidão de posição: sigma de posição = PDOP · σ_UERE. Neste cenáriosigma_uere_m = 1.0, de modo que os dois números são numericamente iguais aqui — mas a regra é PDOP × UERE, não “posição = PDOP”. Com um UERE de 3 m, o sigma de posição seria ~3,2 m. (Veja a armadilha no final.)- As figuras de relógio (
holdover,p95,integrity,security) vêm junto porque o pacote de órbita também carrega um relógio durante a passagem; são o foco do Tutorial 2, não deste. (securitymostran/a (no attack)porque nenhum ataque está configurado.)
O bloco de geometria no JSON tem os números subjacentes:
"geometry": {
"samples_total": 361,
"samples_with_fix": 345,
"sigma_uere_m": 1.0,
"best_pdop": 1.0713624151805556,
"median_pdop": 2.318376881311817,
"best_position_sigma_m": 1.0713624151805556,
"median_position_sigma_m": 2.318376881311817
}
Onde estão os satélites? (a recompensa)#
A geometria é boa porque os satélites estão realmente na camada GPS. Prove: exporte suas posições fixas à Terra:
cargo run -- scenarios/orbit-sgp4-gps.toml --export-sp3 gps.sp3
Os três primeiros satélites no primeiro passo de amostragem, ECEF em km (o arquivo SP3 traz uma quarta coluna, de relógio, escrita com o marcador de “sem valor” 999999,999999):
PG01 9771.575585 24612.128830 0.003744 999999.999999
PG02 20449.643959 -11875.958365 -12379.457079 999999.999999
PG03 26467.367408 45.510223 4010.411755 999999.999999
Tome o raio geocêntrico do PG01:
|r(PG01)| = sqrt(9771.575585^2 + 24612.128830^2 + 0.003744^2) = 26480.9 km
A referência independente não circular: esta é mesmo uma órbita GPS?#
Um tutorial que confere o mecanismo contra ele mesmo não prova nada. Aqui está a âncora externa e não circular para cada afirmação acima.
1. Os satélites estão na camada real de órbita terrestre média (MEO) do GPS. O semieixo maior nominal do GPS é a = 26.560 km, altitude ≈ 20.180 km acima do raio médio da Terra de 6.378 km (IS-GPS-200, a especificação de interface do GPS; o GPS Standard Positioning Service (SPS) Performance Standard, Departamento de Defesa dos EUA (DoD); Misra & Enge, Global Positioning System, 2ª ed.). O raio instantâneo do PG01, de 26.480,9 km, fica a poucas centenas de km de a — exatamente o que a excentricidade real do GPS (~0,005–0,02) produz. O teste tests/tutorials.rs::tutorial1_satellites_are_in_the_gps_meo_shell afirma 26000 km < |r(PG01)| < 27200 km contra este a publicado, que é externo ao Kshana.
2. A duração da passagem é uma revolução do GPS. A terceira lei de Kepler dá o período T = 2π√(a³/μ) com a = 26,560 km e μ = 398,600.4418 km³/s² (World Geodetic System 1984, WGS-84; relatório técnico NIMA TR8350.2 da National Imagery and Mapping Agency): T = 43,078 s = 11.967 h, meio dia sideral. A duração do cenário de 43.200 s (“~uma revolução do GPS”) coincide com isso em menos de 0,3 %, e a trilha no solo do GPS se repete a cada dia sideral (duas revoluções), segundo a IS-GPS-200.
3. As posições propagadas são validadas, não apenas autoconsistentes. O propagador SGP4/SDP4 que produziu esta tabela ECEF concorda com todos os 666 vetores de verificação AIAA (American Institute of Aeronautics and Astronautics) 2006-6753 no pior caso de 4,12 mm (tests/sgp4_verification.rs, docs/SGP4-VALIDATION.md) e coincide com o crate independente sgp4 em nível submicrométrico. Assim, a tabela que você exportou é conferida contra uma implementação de referência externa, não contra a aritmética do próprio Kshana.
Uma observação sobre as datas do SP3. O cabeçalho de época do SP3 mostra uma data de calendário provisória (2000-01-01); a propagação, na verdade, parte da própria época de cada TLE (2021). Leia a tabela como “posições ECEF no primeiro passo de amostragem”, não “em 1 de jan de 2000.”
O que o teste fixa#
tests/tutorials.rs transforma cada número acima em um contrato de CI:
tutorial1_orbit_headline_holds—best_pdop ≈ 1.071,best_position_sigma_m == best_pdop(porquesigma_uere_m = 1.0),samples_total == 361, e o resumo contém345/361.tutorial1_satellites_are_in_the_gps_meo_shell— o raio do PG01 está na faixa da camada GPS, conferido contra oa = 26,560 kmpublicado.
Se o mecanismo algum dia deixar de produzir uma camada GPS real, o build fica vermelho.
Armadilhas e unidades#
- O sigma de posição é PDOP × UERE, não PDOP. Os dois são iguais apenas porque
sigma_uere_m = 1.0aqui. Mude o UERE e eles se separam. - As figuras de temporização estão em nanossegundos, a figura de posição em metros. Não os misture.
holdover_sé quantizado pela grade (um limite inferior no passo da grade de tempo). Nesta passagem o usuário está essencialmente sempre com solução, de modo que o holdover é 0 s (nenhuma interrupção a atravessar) — esse é o caso bom.
Próximos passos#
- Aperte ou alargue a máscara de elevação (
mask_deg) e veja a disponibilidade mudar — isso é um exercício do Nível 2. - Troque por um instantâneo TLE novo com
scripts/fetch_tles.sh(Nível 2, “usar dados novos”). - Passe ao Tutorial 2 — Holdover de relógio, em que o sinal GNSS é retirado e o relógio de bordo precisa seguir sozinho.