Horisontmasker og himmelgeometri
Til og med 0,36 var hver synlighetstest mot jorden i motoren én enkelt elevasjonsgrense, mask_deg: en satellitt telte når den var ved eller over ett tall, uansett retning. En gate, en kai, en fjord eller en kran blokkerer en del av himmelen og lar resten være åpen. En skyline er en elevasjonsgrense som avhenger av asimut; himmelgeometrifunksjonene gjør et sted, et tidspunkt, konstellasjoner og en skyline om til den synlige mengden, presisjonsfortynningen (DOP), geometrikovariansen, den horisontale feilellipsen, en Monte Carlo-sky og et skyplot. Utformingen er docs/design/2026-10-12-geometry-and-skyline-design.md (punkt 1 og 2).
Evidens: beslutningen om maskert synlighet (geodetiske synsvinkler, tabellmasken, den synlige mengden og dens DOP) er VALIDATED mot Orekit 12,2 og gnss_lib_py 1.0.4 i en forhåndsregistrert sammenligning, og det samme gjelder feilellipsen og kofaktoren per system (numpy, forhåndsregistrert); reduksjonene for kanjon, sektor og terreng, forhåndsinnstillingene og resten av himmelgeometrifunksjonene er MODELLED (Evidens). En skyline fjerner satellitter med fri sikt og ingenting mer. Forhåndsinnstillingene er REPRESENTATIVE geometrier, ikke oppmålinger.
Skylinen#
En skyline er det punktvise maksimum av fire beskrivelser. Asimut er grader med klokken fra sann nord i stedets lokale øst-nord-opp-system; elevasjoner er i [0, 90).
| Beskrivelse | TOML | Hva det er |
|---|---|---|
| Tabell | table = [[az, el], ...] |
Elevasjoner lineært interpolert i asimut, brutt rundt ved 360°. Asimuter strengt økende i [0, 360); høyst 3600 rader. |
| Bygate | street_az_deg, width_m, height_left_m, height_right_m, antenna_m, length_m |
To rette parallelle vegger (nedenfor). |
| Sektorer | sectors = [{ az_from, az_to, el_deg }] |
Skarpkantede intervaller, med klokken fra az_from (inkludert) til az_to (ekskludert), som kan gå rundt nord; høyst 360. |
| Terreng | terrain = [{ az, distance_m, height_m }] |
Punkter redusert til en tabell: elevasjon atan((height_m − d²/(2 R_eff)) / d), med krumningsfallet for R_eff = 4/3 × 6371 km (en valgt, oppgitt konstant). height_m er over antennen. |
preset = "<name>" starter fra en navngitt geometri; kanjonfeltene overstyrer deretter preset-ens kanjon felt for felt, og table, sectors og terrain legges til den.
Mottakerens mask_deg beholder sin betydning: den er en flat skyline. Den effektive grensen ved asimut az er max(mask_deg, skyline(az)), og en satellitt er synlig når elevasjonen er ved eller over den: den samme >= som den flate masken alltid brukte. En satellitt over mask_deg men under skylinen er maskert av skylinen.
Bygaten#
En gate går langs asimut s, w meter mellom veggene, med antennen a meter oppe på midtlinjen. Langs asimut az, med θ = az − s, når strålen en vegg etter d(az) = (w/2) / |sin θ|, så en vegg med høyde h skjærer ved
cut(az) = atan( (h − a) / d(az) ) (the right wall for sin θ > 0, the side at s + 90°)
Den åpne stripen ligger langs gaten. Med length_m = L (antennen i midten) forlater en stråle gjennom en åpen ende, og veggen skjærer ingenting, når d(az) · |cos θ| > L/2. En vegg som ikke er høyere enn antennen skjærer ingenting. antenna_m er som standard 1,5 m (et biltak eller en håndholdt mottaker, et oppgitt valg); en ny kanjon trenger width_m.
Forhåndsinnstillinger#
Valgte og oppgitte dimensjoner (fra utformingsnotatet), ikke oppmålinger av noe reelt sted. kshana skyline --preset <name> skriver ut én med proveniensen og grensen for hver grad.
| Forhåndsinnstilling | Geometri | Opphav |
|---|---|---|
city-street |
Kanjon: gate 0°, bredde 20 m, vegger 30 m og 30 m, antenne 1,5 m. 70,7° på tvers av gaten, åpen langs den. | Forhold mellom høyde og bredde 1,5, innenfor båndet 0,5–2 for sideforhold i bygater hos Oke (1988), Street design and urban canopy layer climate, Energy and Buildings 11, 103–113. |
harbour-approach |
Sektorer: åpen mot sjøsiden over 090–270 (180°); kaibygninger 8° over 315–045 (90°); molo og fyr 3° over 045–090 og 270–315. | Oppgitte valg (for eksempel 40 m lagerbygg omtrent 285 m unna). |
fjord |
Terreng: vegger 600 m over antennen på 1500 m til hver side av et nord-sør-gående sund, ett punkt per grad (ved 1500/|sin az| m), med krumningsfall. 21,8° på tvers, under 1° langs aksen. |
Av samme størrelsesorden som bredden og relieffet i de dype fjordene på Vestlandet (Holtedahl (1967), Notes on the formation of fjords and fjord-valleys, Geografiska Annaler 49A, 193–203). |
container-terminal |
Sektorer: containerstabler 12° over den landvendte halvdelen 000–180; kranbommer 35° over 245–255 og 25° over 285–295; åpent mot vannet ellers. | Fem ISO 668 high-cube-containere (14,5 m) omtrent 60 m unna en antenne 2 m oppe; en bom omtrent 50 m over kaien ved 70 m og 100 m, av størrelsesorden for en post-Panamax-kran. En kransektor er ugjennomsiktig. |
I et scenario#
En valgfri seksjon [skyline], som gjelder foran kind-ens egen grense:
| Type | Hva skylinen endrer | Per sample |
|---|---|---|
orbit (med user_site) |
Synlighetstidslinjen (GNSS-tilgjengelighet) og DOP-sammendraget. | — |
integrity (med user_site) |
Satellittene RAIM og ARAIM (araim_dual) bruker. |
epochs[].masked_by_skyline |
gnss-sim |
Satellittene hvis pseudoavstander simuleres og brukes av RAIM. | gnss_measurements[].masked_by_skyline |
jamming |
Satellittene mottakeren kan spore, før jammeren. | epochs[].masked_by_skyline |
leo-pvt |
Hver modus sin mengde i sikte over hvert systems egen maske, polarsveipet inkludert (samme skyline på hvert sted). Omhyllingen for Doppler-modus og den utformede enkeltpasseringen er grenser for hva en mottaker må håndtere og beholder hvert systems maske. | joint.epochs[].masked_by_skyline |
leo-pass |
Hvilke epoker som regnes som over masken, tiden over den, satellittene i GNSS-sammenligningen. | satellites[].pass.epochs_masked_by_skyline |
nmea-scenario (trenings-NMEA) |
Satellittene i GSV og i posisjonsbestemmelsen. Asimuter er sanne peilinger festet til bakken, ikke fartøyets kurs. | — |
Bakkestedet for orbit og integrity. Begge kind-ene modellerer en bruker i bane med geosentrisk elevasjon og uten jordfast asimut, så de tar en skyline bare med utformingsnotatets bakkestedsmodus: user_site = { lat_deg, lon_deg, height_m } i stedet for user (nøyaktig én av de to). Hvert sample er ett absolutt tidspunkt, epoch + t: hver satellitt propageres til det (et elementsett, en kringkastet efemeride eller en SP3-fil føres frem fra sin egen epoke, en Walker-satellitt teller t fra epoch) og roteres til jordfast ved det, slik at stedet ser én konsistent himmel. epoch er orbit-scenarioets egen; uten en (og alltid for integrity, som ikke har noen) er det den nyeste epoken blant satellittene som har en, eller J2000 bare for Walker-mønstre. Elevasjon og asimut er geodetiske (WGS-84). Fordelingen mellom horisontal og vertikal for ARAIM-beskyttelsesnivåene og Stanford-vertikalfeilen i integritetskind-en bruker den samme geodetiske opp-retningen (WGS-84-ellipsoidens normal, omtrent 0,19° fra den geosentriske radialen ved 45° bredde); øyeblikksbilde-RAIM brukte den allerede. Et user_site uten skyline er en vanlig bakkebruker; banestien user i bane er uendret.
kind = "integrity"
mask_deg = 5.0
# ...
[user_site]
lat_deg = 59.45
lon_deg = 24.75
height_m = 15.0
[skyline]
preset = "harbour-approach"
Bakoverkompatibilitet. Uten en seksjon [skyline] er et scenario byte-identisk med det samme motoren ga før skylinekoden fantes: tests/skyline_scenarios.rs kontrollerer JSON, diagram og sammendrag for hvert medfølgende scenario som kjører en av disse kind-ene, og NMEA-teksten for hvert treningsscenario, mot SHA-256-sammendrag av grunnlinjen «0,36 portable» (sammendragene fra utgivelsescommiten for 0.35.0, rebasert da motoren gikk over til portabel matematikk og beholdt i testen som protokoll: docs/revisions/STUDIO15-portable-math-rebaseline.md). En tom seksjon [skyline] skjærer ingenting; resultatet er da lik kjøringen uten den, bortsett fra den tillagte blokken skyline og de nullstilte tellingene for masked_by_skyline.
Hva som avvises, med begrunnelsen i meldingen: en skyline på en user i bane; user og user_site sammen; en ukjent preset; en kanjon uten width_m; en tabell som ikke er strengt økende i [0, 360); en elevasjon utenfor [0, 90); en tom sektor; en ikke-positiv terrengavstand; inndata over grensene; enhver ukjent nøkkel.
Resultatet får skyline: { source, open_fraction, provenance } når seksjonen er til stede: source er preset:<name>, preset:<name>+overrides eller custom; open_fraction er andelen av den øvre halvkulens romvinkel over max(mask_deg, skyline) (gjennomsnittet av 1 − sin(cut) over asimut: 1 for en nullmaske, 0,5 for en flat grense på 30°); provenance er preset-ens linje eller scenarioets egen. Enheter og proveniensklasser står i blokken units.
Medfølgende eksempler (kshana example <name>):
| Eksempel | Hva det viser (fjern seksjonen [skyline] for å sammenligne) |
|---|---|
orbit-urban-canyon-skyline |
GPS + Galileo nederst i city-street: 17 av 289 samples beholder en posisjonsbestemmelse, median PDOP 70,5 (1,14 under åpen himmel). |
integrity-harbour-approach |
ARAIM med to konstellasjoner ved innseiling til en havn: 70 satellitt-epoker skjult, tilgjengelighet uendret (145 av 145). |
gnss-sim-container-terminal-skyline |
Pseudoavstander og RAIM på en kai: 44 satellitt-epoker skjult; RAIM-tilgjengelighet 0,59 (0,85 under åpen himmel). |
jamming-harbour-approach-skyline |
En jammer på 2 W i en havn: 83 satellitt-epoker skjult, sporing uendret (jammeren hadde allerede tatt dem). |
leo-pvt-fjord-skyline |
GPS + Galileo + et LEO-lag i en fjord: median fusjonert PDOP 1,14 (0,93 under åpen himmel). |
leo-vertical-autonomous-vehicle-skyline |
Kanjonen leo-vertical-autonomous-vehicle som en flat grense på 35° og som city-street dreid langs bilens kurs: 8 mot 4 til 5 GPS- og Galileo-satellitter; fusjonert middelfeil 2,1 m i begge; alarmen på 1,5 m ved 51 % og 59 % av epokene. |
Himmelgeometri#
Fem motorfunksjoner (src/geometry.rs), de samme på alle flater:
| Funksjon | Inndata → utdata |
|---|---|
sky_geometry(request) |
per satellitt id, system, az_deg, el_deg, cut_deg, visible, masked; n_visible, n_masked, open_fraction; dop (GDOP, PDOP, HDOP, VDOP, TDOP, tdop_by_clock); states, cofactor_enu (enhetsvarians), covariance_enu_m2; ellipse_1sigma og ellipse ved det forespurte konfidensnivået; label, statement, advisory |
sky_monte_carlo(request, seed, n) |
n (høyst 5000, en grense for inndata) minste kvadraters feil under uavhengige gaussiske avstandsfeil på σ_UERE fra en ChaCha8-strøm med seed seed: samples_enu_m, den empiriske kovariansen, horisontal og 3D RMS ved siden av σ_UERE × HDOP og σ_UERE × PDOP, andelen innenfor 95 %-ellipsen |
skyline_presets() |
preset-ene med merkelapp, beskrivelse, proveniens, grensen for hver grad og open_fraction |
skyline_profile(skyline) |
en skyline-seksjon redusert til tabellen med 360 oppføringer motoren bruker, med source, provenance, open_fraction |
skyplot_svg(request) |
skyplottet som statisk SVG (uten skript, uten ekstern referanse, hver inndatastreng escapet) |
En forespørsel:
{
"site": {"lat_deg": 59.91, "lon_deg": 10.75, "height_m": 5},
"time_s": 3600,
"systems": ["gps-baseline", "galileo", "beidou-meo", "xona-pulsar"],
"mask_deg": 5,
"skyline": {"preset": "fjord"},
"clock": "per-system",
"sigma_uere_m": 1.5,
"confidence": 0.95
}
systems er motorens konstellasjonspreset-er (constellation-designs gps-baseline, galileo, beidou-meo, glonass, ...; LEO-preset-ene xona-pulsar, iridium-stl, ...) eller en full leo-pvt-tabell [[system]], propagert til time_s (Kepler med sekulær J2, banene i fellesmodusen leo-pvt). Deres relative faser kommer fra ulike referanseepoker, så himmelen er en representativ geometri, ikke himmelen på den datoen på det stedet. Satellitter kan i stedet (eller i tillegg) gis direkte: "satellites": [{"id": "G05", "system": "GPS", "az_deg": 120, "el_deg": 35}, ...], eller med "ecef_m": [x, y, z] og et site eller user_ecef_m. Standardverdier: hvert systems egen maske (5° for GNSS, 10° for LEO; 5° for satellitter gitt direkte), én mottakerklokke per system ("common" for én felles klokke), σ_UERE 1 m (en representativ budsjettlinje for to frekvenser), konfidensnivå 0,95. Grenser for inndata: høyst 2000 satellitter over horisonten (en systemtabell som ber om flere avvises før den bygges) og 16 mottakerklokker.
En datert himmel fra elementsett. "tle" tar tekst med to-linjers elementsett (en navnelinje før hvert sett er valgfri; høyst 4 MiB, en grense for inndata), propagert av motorens SGP4 (WGS-72, propagatoren orbit-real-tle bruker) til "epoch" pluss time_s, rotert til jordfast med UT1 satt lik UTC og uten polbevegelse, og sett fra site. "epoch" er UTC i ISO 8601 (2026-06-07T12:00:00Z) og daterer bare elementsettene (preset-ene har ingen dato, så en epoch uten tle avvises); "tle_system" merker dem for klokken per system (standard TLE). Hvert resultat sier hvilken himmel det er i sky_source og sky_statement:
sky_source |
Himmelen |
|---|---|
presets |
motorens konstellasjonspreset-er: en representativ geometri |
tle-at-epoch |
elementsettene propagert til den oppgitte epoken: himmelen disse elementsettene gir ved den epoken, ikke en måling av den (nøyaktigheten er SGP4s og settenes alder) |
tle-at-element-epoch |
ingen epoch: elementsettene propagert til det nyeste settets egen epoke pluss time_s, en representativ himmel |
satellites |
satellitter gitt direkte, som oppgitt |
En blanding forener dem med +. epoch_utc er tidspunktet elementsettene ble propagert til, og tle_skipped navngir hva av teksten som ikke ble brukt, med begrunnelse: misdannede eller foreldreløse elementsettlinjer (med linjenumre), sett parseren avviste, og sett SGP4 ikke kunne propagere til det tidspunktet (forfalt, eller utenfor sine grenser); høyst 100 oppføringer til sammen, deretter én siste oppføring som teller resten. En tom systems-liste legger ikke til noen preset-er. Skyplottet oppgir grunnlaget i bunnteksten.
Én kjerne. Kofaktormatrisen er orbit::cofactor_from_los, oppbyggingen av designmatrisen og Gauss-Jordan-inversen bak orbit::dop. orbit::dop_cov eksponerer kovariansen og orbit::dop er reduksjonen av den, så de VALIDATED skalarene er uendret og fortsatt festet av tests/dop_reference.rs. Det finnes ingen andre DOP-implementasjon.
Ellipsen. Halvakser k σ √λ for egenverdiene λ til øst-nord-blokken, med k = √(−2 ln(1 − p)) (√5.991 = 2.448 ved 95 %, 1 ved 39,35 %), og hovedaksens asimut ½ atan2(2 Q_EN, Q_NN − Q_EE) i [0, 180) fra nord.
| Flate | Inngangspunkter |
|---|---|
| CLI | kshana sky <request.json|toml> eller kshana sky --site <lat,lon[,h]> (--systems <a,b> | --tle <file>) [--epoch] [--tle-system] [--time] [--mask] [--skyline-preset] [--uere] [--clock], med --monte-carlo <n> --seed <s> eller --svg; kshana skyline --preset <name> | --presets | --profile <file> |
| Rust | kshana::geometry::{sky_geometry, sky_monte_carlo, skyline_presets, skyline_profile, skyplot_svg}, kshana::surface::* med de samme navnene |
| Python | kshana.sky_geometry, sky_monte_carlo, skyline_presets, skyline_profile, skyplot_svg |
| WASM | sky_geometry(request_json), sky_monte_carlo(request_json, seed, n), skyline_presets(), skyline_profile(skyline_json), skyplot_svg(request_json) |
| MCP | sky_geometry (request, eller skyline_preset); ingen Monte Carlo over MCP (bulkdata en agent bør oppsummere, ikke bære med seg) |
Hvert resultat bærer label (MODELLED), statement (geometri under en oppgitt feilmodell: uavhengige, like gaussiske avstandsfeil med null forventning; ikke en prediksjon av en mottakers reelle feil, som også har biaser, flerveisutbredelse og feil uten fri sikt; ikke en integritetsgrense) og den veiledende merknaden: Veiledende programvare, ikke typegodkjent navigasjonsutstyr (IEC 61108, IEC 61162): operatøren er fortsatt ansvarlig for fartøyets navigasjon.
Evidens#
Fem registerrader (docs/VERIFICATION-MATRIX.md), slik utformingsnotatet avgrenser dem:
| Rad | Status | Uavhengig referanse |
|---|---|---|
| Asimutavhengig horisontmaske: synlig mengde, asimut og elevasjon, og DOP under masken | VALIDATED | Orekit 12,2 (synsvinkler fra TopocentricFrame, ElevationMask) med gnss_lib_py 1.0.4 (get_dop og DOP-matrisen), forhåndsregistrert i xval/orekit-skyline/PREREGISTRATION.md (commit e4b9d912) før noen av dem ble kjørt: 1173 synsvinkler på seks steder og fire epoker, seks tabeller, 142 synlige mengder; verste elevasjon 1.3e-13°, asimut 2.3e-13°, maske 1.1e-12° mot 1e-9°; identiske synlige mengder, ingen i grensebåndet; DOP 3.3e-13 relativt og kofaktor 6.6e-13 av matrisens skala mot 1e-9. Omfang: tabellmasker, geodetiske synsvinkler, den maskerte mengden og dens DOP og kofaktor med felles klokke. |
| Gatekløft-, sektor- og terrengreduksjoner til en tabell | MODELLED | håndberegnede verdier; sammenligningen ovenfor leser tabellene deres som inndata og kontrollerer dem ikke |
| Skyline-preset-er | MODELLED | ingen: valgte, oppgitte dimensjoner (kontrollert bare mot seg selv) |
| Horisontal feilellipse og kofaktor per system fra geometrikovariansen | VALIDATED | numpy 2.5.4 linalg.inv og linalg.eigh (standard P2) på de 142 innsjekkede synlige mengdene, felles klokke og én klokke per system, forhåndsregistrert i xval/numpy-ellipse/PREREGISTRATION.md (commit 0bbeeaee): 270 tilfeller, akser 5.1e-13 relativt, orientering 5.3e-12°, kofaktor 1.0e-12 av matrisens skala, mot 1e-9 og 1e-6° |
| Himmelgeometrifunksjoner | MODELLED | sammensetningen: propagering av preset-ene til en representativ himmel, Monte Carlo-skyen (kontrollert mot geometrien den trekker fra), flatene |
At en seksjon [skyline] mangler, kontrolleres byte for byte mot utdataene fra 0.35.0, noe som viser bakoverkompatibilitet og validerer ingenting. gnss_lib_py bruker bare én enkelt elevasjonsmaske, så den er DOP-referansen her, ikke maskereferansen.
Hva en skyline ikke modellerer: diffraksjon over en veggkant, refleksjoner og signaler uten fri sikt som en reell mottaker fortsatt kan spore (de forkastes, ikke degraderes), delvis gjennomsiktighet (en gitterkran er ugjennomsiktig over hele sektoren sin), terreng utenfor de oppgitte punktene, og jordens krumning inne i kanjon- og sektorformene.