教程1——我的第一条轨道:GPS卫星在哪里
Kind: orbit · 场景:scenarios/orbit-sgp4-gps.toml(教学副本:scenarios/orbit.toml) · 难度:入门 · 约15分钟
学完本教程,你将对真实的在役GPS星座完成轨道外推,读出其可用性与几何构型,并导出一张列出每颗卫星在空间中实际位置的表——同时你会知道,这张表是经独立外部参考核对过的,而不是与自身比对。
这个场景是什么#
GPS(全球定位系统)卫星告诉用户自己在哪里以及现在是几点。在此之前,你需要知道卫星在哪里,以及用户能看到其中多少颗。这就是几何问题,而几何构型决定了定位精度的下限(即精度因子,DOP)。本教程将:
- 取一份真实的Celestrak
gps-opsGPS星座快照(2021-07-28,30颗卫星,真实的两行根数,TLE), - 用经独立外部参考核对过的SGP4/SDP4模型(Simplified General Perturbations 4 / Simplified Deep-space Perturbations 4)外推每一颗卫星,
- 在每个时间步计算低地球轨道用户能看到哪些卫星(视线、地球遮挡,以及5° 的高度截止角),
- 把这种几何构型转换为PDOP(位置精度因子)和位置精度,并
- 把卫星实际的地心地固(ECEF)位置导出为SP3文件(Standard Product 3,国际GNSS服务组织IGS的精密轨道格式;GNSS即全球导航卫星系统)。
主线是:TLE → SGP4外推 → 每历元的ECEF → 可见性 → 可见卫星数 → PDOP → 位置sigma = PDOP · σ_UERE,其中 σ_UERE是用户等效测距误差(每颗卫星的1-σ 测距误差)。
运行#
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"])
也可以打开浏览器版Studio,选择轨道场景。
读取单行概括#
确定性运行(随机种子 = 17)输出:
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)
逐字段说明:
scenario 4c51512369a6——12位字符的场景哈希。它为全部输入(随机种子、阈值、模型参数、TLE数据块)生成指纹。改动任何输入,它都会变化;保持输入不变,则可逐位复现该次运行。同一哈希还印在图表页脚和结果JSON(JavaScript Object Notation)文件中。345/361 samples GNSS-nominal——在361个时间步中,用户有345个时间步具备可用定位解(95.6 %)。本次运行是一个12 h的过境(43,200 s),步长120 s。best PDOP 1.07——整个过境期间最佳(最低)的位置精度因子。PDOP接近1即为极佳的几何构型;越低越好。pos 1.07m——最佳位置精度:位置sigma = PDOP · σ_UERE。在本场景中sigma_uere_m = 1.0,因此这两个数值在此处数值相等——但规则是PDOP × UERE,而不是“位置 = PDOP”。若UERE为3 m,位置sigma约为3.2 m。(见末尾的易错点。)- 时钟相关数据(
holdover、p95、integrity、security)会一并给出,因为该轨道包在整个过境期间还带有一个时钟;它们是教程2的重点,而非本教程的重点。(security显示n/a (no attack),因为没有配置任何攻击。)
JSON中的几何块给出了底层数值:
"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
}
卫星在哪里?(真正的收获)#
几何构型之所以好,正是因为卫星确实位于GPS轨道壳层中。来证明这一点——导出它们的地固位置:
cargo run -- scenarios/orbit-sgp4-gps.toml --export-sp3 gps.sp3
第一个采样步上的前三颗卫星,ECEF坐标,单位km(SP3文件还带有第四列,即时钟列,以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
取PG01的地心半径:
|r(PG01)| = sqrt(9771.575585^2 + 24612.128830^2 + 0.003744^2) = 26480.9 km
非循环的参考基准(oracle):这真的是GPS轨道吗?#
只拿引擎与自身核对的教程什么也证明不了。下面是上述每一项结论的外部非循环锚点。
1. 卫星位于真实的GPS中地球轨道(MEO)壳层上。GPS标称半长轴为a = 26,560 km,高度约20,180 km(相对于6,378 km的平均地球半径)(IS-GPS-200,即GPS接口规范;美国国防部(DoD)的GPS标准定位服务(SPS)性能标准;Misra & Enge,Global Positioning System,第2版)。PG01的瞬时半径26,480.9 km与a相差仅数百km——这正是真实GPS的偏心率(约0.005–0.02)所造成的。测试tests/tutorials.rs::tutorial1_satellites_are_in_the_gps_meo_shell针对这一公开发布的a断言26000 km < |r(PG01)| < 27200 km,而该值独立于Kshana之外。
2. 过境时长是GPS绕地一圈。开普勒第三定律给出周期T = 2π√(a³/μ),其中a = 26,560 km、μ = 398,600.4418 km³/s²(世界大地坐标系1984,WGS-84;美国国家影像与测绘局技术报告NIMA TR8350.2):T = 43,078 s = 11.967 h,即半个恒星日。场景时长43,200 s(“约一个GPS圈”)与此吻合,偏差小于0.3 %;并且依据IS-GPS-200,GPS星下点轨迹每个恒星日重复一次(两圈)。
3. 外推得到的位置经独立外部参考核对,而非仅自洽。生成这张ECEF表的SGP4/SDP4外推器与全部666个AIAA(美国航空航天学会)2006-6753验证向量一致,最坏情况为4.12 mm(tests/sgp4_verification.rs,docs/SGP4-VALIDATION.md),并与独立的sgp4 crate在亚微米量级上吻合。因此,你导出的这张表是对照外部参考实现核对的,而不是对照Kshana自己的运算。
关于SP3日期的说明。SP3历元头部显示的是一个占位日历日期(2000-01-01);外推实际上从各TLE自身的历元(2021)开始。请把这张表理解为“第一个采样步的ECEF位置”,而不是“2000年一月1日的位置”。
测试固定了什么#
tests/tutorials.rs把上面每个数字都变成一项CI约定:
tutorial1_orbit_headline_holds——best_pdop ≈ 1.071、best_position_sigma_m == best_pdop(因为sigma_uere_m = 1.0)、samples_total == 361,且摘要包含345/361。tutorial1_satellites_are_in_the_gps_meo_shell——PG01的半径位于GPS壳层范围内,并对照公开发布的a = 26,560 km核对。
一旦引擎不再产生真实的GPS壳层,构建就会变红。
易错点与单位#
- 位置sigma是PDOP × UERE,而不是PDOP。两者相等,只是因为此处
sigma_uere_m = 1.0。改变UERE,它们就会分开。 - 授时数值以纳秒为单位,位置数值以米为单位。不要混用。
holdover_s是按网格量化的(即时间网格步长上的下界)。在本次过境中,用户基本始终处于可定位状态,因此守时(holdover)为0 s(没有需要滑行度过的中断)——这是好的情形。
接下来去哪里#
- 收紧或放宽高度截止角(
mask_deg),观察可用性如何变化——这是第2级的练习。 - 用
scripts/fetch_tles.sh换入新的TLE快照(第2级“使用最新数据”)。 - 继续学习教程2——时钟守时:在那里GNSS信号被撤走,星载时钟必须独自滑行。