☰
开发了一个GNSS软件接收机,大家觉得怎么样?
2026/9/27 5:53:02 网站建设 项目流程

一个 GNSS 软件接收机:Qt6 + C++20,把 GPS / 北斗 / Galileo 十种信号全部打通

一个不依赖任何第三方 GNSS 库的离线软件接收机。21,000 行 C++20 从捕获、跟踪、导航电文译码一路写到多系统联合定位,配上完整的 Qt6 图形界面和命令行批处理工具。十种民用卫星导航信号全部形成实采闭环,包括 Galileo E5 AltBOC 这种 58 Msps 的宽带信号。

如果你是在读卫星导航 / 测绘 / 通信 / 航空航天专业、想把课本上的公式真的跑一遍的学生;如果你是用 RTL-SDR、HackRF 玩过一阵、想试试把天上的卫星抓下来的爱好者;或者你手上恰好有一份采集数据、想知道它到底能不能用——这个项目就是为你写的。

十种民用卫星导航信号全部形成实采闭环,包括 Galileo E5 AltBOC 这种 58 Msps 的宽带信号,具体为B1i,B1c,B2a,B2b,B3i,L1ca、E1、E5a、E5b、E5ab-altboc。每种信号都能独立捕获、跟踪、电文提取、测量、定位。


一、写给三类人:为什么值得自己动手做一遍

先说清楚这个项目是为谁做的。开源的 GNSS 软件接收机不算少,但大多停在「能跑通」;而这个项目从第一天就按「能当学习平台 + 能当验证工具」两条线来设计,因为它最初就是被这两个需求逼出来的。

1.1 卫星导航专业的同学:把教科书里的公式跑起来

如果你在读测绘、导航、通信、航空航天相关专业,大概经历过这种割裂:

课堂上讲扩频、讲相关峰、讲 DLL/PLL 环路带宽、讲最小二乘定位——公式都懂,考试也会做。但真想验证「PLL 带宽从 25 Hz 降到 15 Hz,载噪比门限会怎么变」这类问题时,发现手边没有一个能随手改、改完立刻看到曲线的工具。MATLAB 能算,但要自己把整条链路搭起来已经是另一个课题了。

这个项目就是那个工具。参数面板上几乎每一个数字都对应教科书里的一个公式:

你在课本上学到的在这个项目里对应
相干积分时间捕获页「相干积分」
多普勒搜索范围与步长捕获页「多普勒上限 / 多普勒下限 / 搜索步长」
非相干累加次数捕获页「非相干累加次数」
检测门限与虚警概率捕获页「峰值比门限」
DLL / PLL / FLL 环路带宽跟踪页「DLL 带宽 / PLL 带宽 / FLL 带宽」
早迟码间距跟踪页「E-L 间距」
锁定判据跟踪页「通道状态」与「C/N0 (dB-Hz)」两列

改一个数、点「应用配置」、跑一遍,捕获率和载噪比曲线立刻给出反馈。这比读十页论文更容易建立直觉,而且每一条曲线背后都是真实的采样数据,不是仿真出来的理想波形。

而且系统对参数状态是有门控的:改动任何影响结果的参数,配置就会退回「未应用」状态,三个处理按钮随之禁用。这看似麻烦,实际上是在保护你的实验记录——**不会出现「参数改到一半就跑出一份说不清配置的结果」**这类事故:

更值得说的是那些只在真实系统里才会冒出来的问题——这些恰恰是课本很少讲、但工程里天天遇到的:

  • 采样率不是码率的整数倍时,相关器怎么做分数间隔抽取
  • 多普勒搜索步长怎么和相干积分时长互相约束:步长太细浪费时间,太粗会直接跨过主峰
  • 低载噪比下环路为什么失锁,载波锁定指标怎么提前告诉你「快不行了」
  • 导航电文为什么要交织、为什么要 CRC,误码是怎么被维特比译码纠回来的
  • 多个系统的时间基准不一致,为什么必须额外估一个系统间偏差,不然位置会被偏差吃掉

因为整个工程是完整实现的,你会顺带看到这些问题的真实解法,而不是一句「此处做相应处理」。项目自带单元测试和一整套实采数据验收门,所以它同时也是一个现成的课程设计 / 毕业设计 / 论文实验平台——需要做对比实验时,批处理工具能保证每组结果都可复现、可追溯。

1.2 无线电与 SDR 爱好者:把天上的卫星真的抓下来

如果你玩过 RTL-SDR、HackRF、USRP,用dump1090抓过飞机、用rtl_433收过气象站,那下一步几乎必然是——卫星。

卫星信号的魅力在于它有一个「已知答案」:GPS L1 C/A 的扩频码是公开的,卫星在哪儿是可以算出来的,你解出来的位置对不对,地图上一看就知道。这种有真值可以对照的解码,比抓一堆不明所以的 433 MHz 脉冲要过瘾得多。

但这条路卡住了不少人:抓到一段 IQ 数据之后呢?装 GNSS-SDR 太重、编译半天还不一定过;自己写脚本又只能做到捕获,跟踪一失锁就不知道怎么往下调。

这个项目在这条路上给你一个从采样文件到经纬度的完整闭环,而且每一步都能看见:

  • 相关能量热力图 —— 亲眼看到那条码相位 × 多普勒的亮线
  • 八通道锁定状态表 —— 看每颗卫星什么时候从 PULL-IN 跳进 LOCK
  • 载噪比与多普勒双曲线 —— 直观感受信号强弱和卫星相对运动
  • 天空图 —— 解算出的卫星方位俯仰,和窗外的实际天空对得上

它对采集设备的宽容度也比预期高。项目实测数据里就包含了 8 位、4 位、2 位三种量化位宽,零中频和带中频两种频谱摆放,甚至还包括采集器启动瞬态(开头的 32 ms 是无效数据,靠配置里的「跳过」选项处理)。这些坑都已经踩过并写进了内置预设——同类采集器出来的文件,基本开箱即用。

1.3 做信号验证的人:一份陌生的采集数据,到底能不能用

这是最实用、也最少被开源项目认真对待的场景。

你手上可能有一份新前端采回来的数据、一个新信号制式的样本、或者一段别人给的、来历不明的 IQ 文件。在投入真正的开发之前,你需要先回答几个问题:

  1. 采样率、中频、量化位宽猜对了吗?
  2. 里面真的有信号吗?峰值比够不够?
  3. 能锁定吗?载噪比有多少?
  4. 导航电文能解出来吗?CRC 过不过?
  5. 最后能不能算出位置?

这个项目把这条体检流程做成了几行命令:

# 全星座扫描:这份文件里到底有什么,能不能定位gnss_batch.exe--acquire--signalsgps-l1ca --track-seconds40\--require-lock --self-check--unpaced-oout/probe data/unknown.bin

关键在于结尾那一串--require-*断言:任何一个不满足,进程就以非零码退出。也就是说「这份数据能不能用」这个问题,可以直接由退出码回答,不需要人肉翻几万行日志——挂到流水线里就是一道自动门槛。

我们已经用这套流程做完了 Galileo 四种信号的数据验收,其中E5 AltBOC 是一份 58 Msps、约 23 GB 的宽带采集文件,最终结果是:8 颗卫星全部锁定、171 页电文 CRC 全部通过、组装出 7 组完整星历、14 个定位解。

而且验证结论是可追溯的。每次运行都会写一份manifest.json,记录:

  • 软件版本与配置模式版本(buildVersion/schemaVersion)
  • 本次构建支持哪些信号(capabilities)
  • 对照的接口控制文件版本(icd)
  • 输入文件路径、大小与时间戳
  • 这次实际处理了哪些信号和卫星(processingSignals/processingPrns)
  • 各阶段统计量

把这份 JSON 连同结果 CSV 一起归档,几个月后重新翻出来也能说清「这个结论是怎么来的」。写验收报告、复现同事的实验、排查「上次明明能跑」——靠的都是它。

1.4 共同的起点:MATLAB 原型和工程软件之间那道鸿沟

三类人最终都会撞上同一堵墙。

MATLAB 里调个xcorr就完事的捕获,到了工程里要考虑:采样率不是码率的整数倍、FFT 要不要补零、多普勒步长和积分时长怎么互相约束、跨码周的相关结果怎么累加对齐。跟踪环路更麻烦——教科书上的二阶环路公式很干净,真实数据里的失锁、周跳、多径、采样时钟偏差会让它变得很难缠。

这个项目做的事,就是把这道鸿沟完整走一遍,并把过程留下痕迹:

21,000 行 C++20,不用任何现成的 GNSS 库。码生成、相关器、环路滤波、维特比译码、CRC 校验、最小二乘——全部自己实现。同时配上一套能让人看见中间量的界面,和一套能让人自动回归的命令行工具。

学完能带走的东西很具体:一个能改、能跑、能验证的接收机,以及一份能解释每一个数字从哪来的能力。这大概是自己动手做一遍和直接用现成软件之间,最大的差别。


二、它到底能做什么

先给结论:一个学习平台该有的能力,它基本齐了——十种信号、完整三段式流程、参数全可调、中间量全可导出;一个验证工具该有的能力,它也齐了——命令行入口、断言门槛、结果缓存、可追溯清单。

下面按「信号覆盖 → 处理流程 → 实际操作」三层展开。

2.1 信号覆盖:十种民用信号,全部实采闭环

系统信号中心频率状态
GPSL1 C/A1575.42 MHz✅ 全链路闭环
北斗B1I1561.098 MHz✅ 全链路闭环
北斗B1C1575.42 MHz✅ 全链路闭环
北斗B2a1176.45 MHz✅ 全链路闭环
北斗B2b1207.14 MHz✅ 全链路闭环
北斗B3I1268.52 MHz⚠️ 捕获/跟踪/电文/观测量已验证,定位链已接入
GalileoE11575.42 MHz✅ 全链路闭环
GalileoE5a1176.45 MHz✅ 全链路闭环
GalileoE5b1207.14 MHz✅ 全链路闭环
GalileoE5 AltBOC1191.795 MHz(中心)✅ 全链路闭环(宽带)
GalileoE6-B/C—🔬 实验源码,默认不编译

这里有个容易被忽略的设计点:这三个系统的频点是重叠的。GPS L1 C/A、北斗 B1C、Galileo E1 同在 1575.42 MHz;北斗 B2a 与 Galileo E5a 同在 1176.45 MHz;B2b 与 E5b 同在 1207.14 MHz。所以一份中频数据里往往同时躺着多个系统的信号,能不能把它们都抓出来、并联合解算,是衡量接收机灵活性的硬指标。

「全链路闭环」在这里不是「能捕获到就算」,而是指一段数据完整走完:

捕获 → 跟踪 → 导航电文译码 → 星历组装 → 观测量构造 → 定位解算

2.2 处理流程:经典三段式,但每一段都留了口子

三段式处理本身是教科书标准做法,但真正让这个项目好用起来的,是每段之间都做了可观察和可干预:

  • 捕获段:二维搜索(码相位 × 多普勒),输出峰值比、码相位、多普勒频移,并把相关能量热力图一起留盘。
  • 跟踪段:每颗卫星一条独立通道,DLL/PLL/FLL 三环并联,实时输出 E/P/L 相关值、载噪比、锁相指标、相关峰比。
  • 定位段:观测量构造 + 迭代最小二乘(Householder QR),输出位置、钟差、精度因子、残差。

2.3 五步操作,从打开文件到出定位

界面上的流程被刻意压到五步:打开数据 → 应用配置 → 开始捕获 → 进入跟踪 → 开始定位。

其中「应用配置」这一步是刻意设的:改任何影响结果的参数都会让配置回到「未应用」状态,三个处理按钮随之禁用。这不是麻烦,而是防止你在参数改了一半的状态下跑出一份说不清参数的结果——实验可复现的前提是参数状态明确。


三、核心亮点

亮点 1:P ⊇ T ⊇ S —— 把实验自由度做成了一套自洽的模型

这是整个项目里我个人最满意的设计。

通常的 GNSS 软件只有一层选择:处理哪些卫星。但这个项目把选择拆成了两层,并强制约束包含关系:

S ⊆ T ⊆ P
  • P(处理选择):决定哪些(系统,信号,卫星)进入捕获与跟踪流水线。
  • T(跟踪成功集合):不是选出来的,是跑出来的——真正锁定并取得有效观测的那些。
  • S(定位参与选择):在 T 的基础上,进一步挑哪些观测参与定位解算。

这样做的价值在哪?举个具体场景:

你手里有一份 GPS + 北斗 B1C 的数据。你想同时跟踪两套信号看它们的载噪比对比,但只想用 GPS 单系统算一个位置做基准,再用双系统算一个位置做对比。

传统软件里你得跑两遍。而在这里,P 填全部、S 只填 GPS,跑一遍就能拿到:T 里的全部通道数据(用于对比)+ S 限定的 GPS 单系统位置。换个 S 再点一次定位,不用重新跟踪。

而且系统会主动拒绝非法组合:如果你在 S 里填了一颗没跟踪成功的卫星,它不会静默忽略,而是明确报错告诉你为什么不合法。

界面上的呈现也很直观——P / T / S三个数一直显示在总览页,S 永远不可能大于 T:

亮点 2:多系统联合定位,待估参数随系统数自动增长

单系统定位解 4 个未知量(三维位置 + 接收机钟差)。但当你把多个系统的观测混在一起解算时,问题来了:每个系统的时间基准不一样。

解决方案是在待估参数里加一项系统间偏差(ISB):

参与系统数待估参数个数说明
1 个4位置 3 + 钟差 1
2 个5追加 1 个系统间偏差
3 个6追加 2 个系统间偏差

参考系统优先取 GPS(GPS 在场时),否则取参与解算的第一个系统——参考系统本身不估计偏差项。

实测中这一点得到了直接验证:在 GPS + 北斗 B1C + Galileo E1 的三系统数据上,70 个定位历元里有 2 个真正完成了三系统联合解,GPS ISB 与 Galileo ISB 两列同时非零,且 GDOP 2.634 / 2.637 是全部 70 个历元中最好的两个:

双系统是更常见的工作点,GPS + 北斗 B1C 的组合同样能稳定解出联合解,此时待估参数为 5 个:

亮点 3:E5 AltBOC 宽带处理 —— 一份数据,同时吃出两套电文

Galileo E5 AltBOC 是这个项目里技术含量最高的部分。

AltBOC(15,10) 调制在 1191.795 MHz 中心频率上,副载波 15.345 MHz,把信号能量推到中心频率两侧约 ±15 MHz 处,形成一个宽带信号。它有两个导频分量(E5a-Q、E5b-Q)和两个数据分量(E5a-I、E5b-I),而 E5a-I 承载 F/NAV 电文、E5b-I 承载 I/NAV 电文——是两套不同的导航电文。

这个项目的做法是:用 58 Msps 的完整宽带采样,把中频分别搬移到两侧边带(±15.345 MHz)各搜一次,然后把同一时延、同一多普勒上的两路非相干功率相加。理由是整带复现码的副载波相位未知,直接合成复现码会产生旁瓣歧义。

结果是 8 条跟踪通道,同时产出两套电文:

电文类型页数
I/NAV(来自 E5b-I)147
F/NAV(来自 E5a-I)24
合计171 页,CRC 全部通过

这一点很关键:它不是分别跑 E5a 和 E5b 再拼出来的结果,而是同一条通道在真实的宽带数据上同时解出两套电文,最终组装出 7 颗卫星的完整星历。

另外,E5 AltBOC 的四分量结构在跟踪时要处理两个额外的相位细节:副载波相位修正、以及数据分量 E5b-I 的半相位修正因子;调度块跨码周回绕时(1 ms 码周期)还要做两段累加对齐。

亮点 4:捕获与观测缓存 —— 改选择不用重跑

GNSS 数据处理最耗时的两步是捕获(二维搜索)和跟踪(长时间环路收敛)。这个项目把两者的结果都做成缓存落盘:

<结果目录>/acquisition/acquisition-cache.json # 捕获缓存 + 热力图 <结果目录>/tracking/observation-cache.json # 观测缓存

缓存按输入数据指纹判断有效性。换文件、换采样率、换量化格式——缓存自然失效重跑;但只是改 S 集合、改定位组合、改精度因子阈值——直接读缓存,秒级出结果。

实测中这套机制的价值非常直观:一份 42 秒的 E5 AltBOC 数据(58 Msps),完整跑一遍捕获 + 跟踪 + 定位需要比实时慢约 7 倍;而缓存命中后,改定位组合重算几乎是瞬时的。

亮点 5:界面 + 批处理双入口,断言直接当 CI 门槛

图形界面适合探索和教学,命令行适合自动化和回归。这个项目两条路都做全了。

命令行工具gnss_batch.exe提供49 个选项,覆盖信号选择、卫星范围、跟踪时长、缓存输入输出,以及一整套验收断言:

# 要求 8 颗 GPS 卫星全部捕获并锁定,然后自洽定位gnss_batch.exe--acquire--signalsgps-l1ca--prns3,6,9,15,18,21,22,26\--track-to-end --require-acquired --require-lock --self-check\--unpaced-oout/gps data/GPSdata.bin# 三系统联合定位验收:断言必须解出联合解gnss_batch.exe--acquire--signalsgps-l1ca,bds-b1c,gal-e1\--prns4,8,11,32 --b1c-prns6,8,9,11,12,20,29,30,36,40 --e1-prns16,17,28,30\--track-seconds40--require-joint-pvt-oout/e1-3sys data/B1L1E1_80.bin

断言不满足时进程以非零码退出,所以可以直接挂在流水线里当回归门槛——这一点在持续迭代算法时非常省心。

值得一提的是 Galileo 的验收方式:它没有专门的断言开关,而是用「--require-lock+--require-joint-pvt+ 脚本核对galileo_ephemeris.json的条目数」组合完成。这是有意为之——galileo_navigation.csv里每一页的 CRC 结果、星历有效标志、IODnav 都被如实写出来了,比一个布尔断言能说明的问题多得多。

亮点 6:结果可复现 —— manifest.json 记下全部上下文

每次处理都会在输出目录写一份manifest.json,内容包括:

  • buildVersion/schemaVersion(配置模式版本)
  • capabilities(本次构建支持哪些信号)
  • icd(对照的接口控制文件版本)
  • inputPath/inputBytes/createdUtc
  • processingSignals/processingPrns、positioningSignals/positioningPrns
  • statistics(各阶段统计量)

也就是说,任何一份结果都能回溯到产生它的软件版本、配置和数据文件。做实验记录、写论文、报验收,这一份 JSON 就够了。

配置格式还支持 schema 版本自动迁移——v1 的旧配置能被 v2 的软件直接读入。


四、实测数据

全部数字来自真实采样文件的批处理运行,不是仿真或估算。结果明细(CSV / JSON)随每次运行留盘。

4.1 四个数据集的完整结果

数据集信号与处理选择处理范围捕获/锁定电文页星历定位历元GDOP
E5a-8.binGalileo E5a,SVID 10/21/28/2952 s4 / 420(F/NAV)436.49 ~ 6.53
E5b-8.binGalileo E5b,SVID 4/19/21/23/2842 s5 / 586(I/NAV)4916.73 ~ 16.83
E5ab-4.binE5 AltBOC,8 颗 SVID42 s8 / 8171(I/NAV 147 + F/NAV 24)7143.70 ~ 8.99
B1L1E1_80.binGPS 4 + 北斗 B1C 10 + Galileo E1 440 s18 / 1876(E1 I/NAV)4702.63 ~ 10.59

E5a、E5b、E5 AltBOC 三份数据的定位结果落在同一地点附近,水平坐标一致到百米以内、高程一致到 14 m 以内——这本身就是对 Galileo 三种信号处理链正确性的一个交叉验证。

E5a 用的是 F/NAV 电文,页结构、交织方式和校验长度都与 I/NAV 不同,界面上可以逐页看到 CRC 与星历有效标志:

4.2 三系统联合解的构成

B1L1E1_80.bin 的 70 个有效定位历元,按参与系统拆开看:

参与系统历元数GDOP 范围
GPS 单系统(L1 C/A)3010.29 ~ 10.59
北斗单系统(B1C)184.13 ~ 4.14
Galileo 单系统(E1)47.61 ~ 7.63
GPS + 北斗(L1 C/A + B1C)163.26 ~ 3.26
GPS + 北斗 + Galileo(三系统)22.63 ~ 2.64

这张表很能说明多系统联合的意义:从 GPS 单系统的 GDOP 10.3 一路降到三系统的 2.63。

三系统能成立的前提是三套信号都被干净地抓下来——18 项捕获全部通过峰值比门限:

4.3 一个有意思的观察:系统间偏差是 1 ms 码周期的整数倍

三系统联合解里,两个系统间偏差的估计值分别是:

  • 北斗对 GPS:约2 698 129 m
  • Galileo 对 GPS:约899 372 m

单看绝对值会觉得大得离谱。但注意这些信号的主码周期都是 1 ms,对应光速距离 299 792 m:

2 698 129 ÷ 299 792 ≈ 9.000 899 372 ÷ 299 792 ≈ 3.000

两个偏差几乎正好是 1 ms 主码周期的整数倍——北斗 9 倍,Galileo 3 倍。

这说明它们根本不是物理上的距离偏差,而是系统时间基准之差换算成的距离(那个位置本来就被接收机钟差和整码周期吸收了,剩下的时基差落到了这一列)。所以判断解算是否正常,不能看绝对值大小,而要看它在一段数据内是否稳定:

  • 北斗 ISB 在 18 个历元上的跨度:2.82 m
  • Galileo ISB 在 2 个历元上的跨度:1.54 m

重复性都在米级以内——说明偏差项被稳定估计,而不是被位置分量错误吸收。

如果某一历元这一列突然跳变几百米以上,才说明对应卫星的码相位发生了整周期错位,或电文与观测的配对出了问题。这是排查多系统解算问题时一个非常实用的判据。


五、界面一览

界面采用「中央结果区 + 左右可停靠面板」布局,中间是七个结果页:

页面内容
总览配置摘要、三集合状态、运行状态、七个页签入口
捕获结果每颗卫星的峰值比、码相位、多普勒、相关能量热力图
跟踪动态通道状态表、载噪比曲线、多普勒曲线、载波锁定指标
导航电文按信号分类的电文页表,CRC 与星历有效标志
观测量每颗卫星最新历元的伪距、多普勒、钟差
定位结果位置、精度因子、轨迹、天空图、定位历元表
处理与定位选择P / T / S 三集合的编辑与包含关系展示

各页实拍:

捕获结果页—— 峰值比门限判定一目了然,热力图能看出相关峰的形态:

多系统数据会按星座分块列出,同一份文件里 GPS 与北斗 B1C 各自成组:

跟踪动态页—— 八通道状态表 + 载噪比 / 多普勒双曲线:

导航电文页—— 每页的 CRC 与星历有效标志都如实显示:

观测量页:

定位结果页—— 位置、精度因子、轨迹与天空图:

单系统(GPS L1 C/A)的定位页,天空图上按星座配色的卫星分布一眼可辨:

界面支持亮色 / 暗色主题切换,星座配色是全站统一的:GPS 蓝、北斗红、Galileo 绿、GLONASS 橙。


六、工程实现

6.1 分层架构

层次职责
界面层Qt6 窗口、结果页、图表、主题
应用控制层状态机、界面与处理的编排、线程与心跳
处理层捕获、跟踪、定位三段调度与结果组织
算法信号层码生成、相关、环路滤波、电文译码、最小二乘
数据层采样文件读取、缓存、CSV / JSON 导出

处理层与界面层通过信号槽和后台线程解耦——界面上的曲线长时间不刷新会触发运行指示器变黄,提示超过 500 ms 未收到心跳,而不是让界面卡死。

6.2 规模与技术栈

项内容
语言 / 标准C++20
界面框架Qt 6.11
构建CMake + Ninja,MinGW 13.1 x64
代码规模约 21,400 行 C++(含头文件与测试)
第三方 GNSS 库无

这是我认为最值得强调的一点:没有用任何现成的 GNSS 库。码生成、相关器、锁相环、维特比译码、CRC 校验、最小二乘——全部自己实现。码资源表从官方 ICD 内嵌附件生成后固化成.inc文件,运行时零外部依赖。

6.3 电文译码的几个实现细节

以 Galileo 的 I/NAV 与 F/NAV 为例,两种电文的参数并不相同:

项目I/NAVF/NAV
每页符号数250500
同步头10 符号固定图案12 符号固定图案
编码数据段240 符号488 符号
纠错编码1/2 速率卷积码,约束长度 7,64 状态同 I/NAV
交织30 列 × 8 行分块交织61 列 × 8 行分块交织
维特比输出120 比特244 比特
校验CRC-24Q(多项式 0x864CFB)CRC-24Q,校验前 238 比特

卷积码的生成多项式为 G1=171、G2=133(八进制),且第二支路输出取反。星历需要类型 1 ~ 4 的页面齐备后才组装,并记录 IODnav。

6.4 构建与发布

一键发布脚本会比对源码与上次发布记录、构建、跑单元测试与界面烟雾测试,然后把 Qt、MinGW 和插件依赖部署到发布目录:

.\scripts\publish-windows.ps1

每次替换前的版本自动备份,版本号与源码指纹记录在release.json里——发出去的东西都能对上源码。

测试注册在 CTest 里,从核心单元测试、无界面 GUI 冒烟测试,到实采数据验收门(GPS PVT、B1C 锁定、实采导航子帧、GPS+BDS 联合定位),一条命令跑完。


七、快速上手

# 构建&'C:\Qt\Qt6.11\Tools\CMake_64\bin\cmake.exe'--preset windows-mingw-debug &'C:\Qt\Qt6.11\Tools\CMake_64\bin\cmake.exe'--build--preset windows-mingw-debug# 跑测试&'C:\Qt\Qt6.11\Tools\CMake_64\bin\ctest.exe'--preset windows-mingw-debug# 发布(部署 Qt 依赖到 out/windows-x64).\scripts\publish-windows.ps1

然后直接双击out\windows-x64\gnss_app.exe就能用。命令行工具在同一目录:

.\out\windows-x64\gnss_batch.exe--help

原始数据文件只读使用,不会被复制到构建或输出目录——这一点对动辄几十 GB 的采集文件很重要。


八、已知限制

写文档和写代码一样,把边界说清楚比夸大能力更有价值:

  1. GPS / 北斗 / Galileo 三大系统已完成全链路实采验证,北斗 B3I 的定位链已接入但受单文件可用星数限制,尚未形成单文件解算。
  2. 没有外部真值,因此项目不声明绝对定位精度,只声明内部自洽与多源一致性。
  3. Galileo 星历尚未与精密星历比对——计划纳入后续验证。
  4. Galileo E6-B/C 仅作实验源码,默认不编译,待有实测数据后再验证。
  5. 北斗 GEO 卫星按设计跳过——BDS GEO 相对地球静止、多普勒近零、仰角无连续变化,其捕获跟踪行为与 MEO/IGSO 差异显著,超出本阶段范围。界面会明确标出被忽略的 GEO 卫星及原因。
  6. Galileo 单系统可用星数偏少,几何条件不如 GPS,精度因子偏大。

九、小结

回到最开始的问题:为什么值得自己动手做一遍?

因为这个过程会把 GNSS 从**「一个黑盒函数」变成「一条你能看到每一步的流水线」**。做完之后,你对「为什么低仰角卫星容易失锁」「为什么多系统联合能改善精度因子」「为什么系统间偏差看起来大得离谱但其实正常」这些问题的理解,会和只看论文完全不同。

对三类人来说,它的价值分别落在这里:

你的身份它给你的东西
卫星导航专业学生一个把课本公式跑成曲线、能改能对比的实验平台;从捕获到定位的每一层都看得见、可复现,可直接用于课程设计、毕设与论文实验
无线电 / SDR 爱好者从一段 IQ 采样文件到地图上经纬度的完整闭环;热力图、锁定状态、载噪比、天空图,每一步都有反馈,采集格式的坑已内置预设
做信号验证的工程师一套由退出码回答「这份数据能不能用」的体检流程;断言可挂流水线,manifest.json让结论可追溯

这个项目把这件事做得比较完整:

  • 十种民用信号全部实现,包括 58 Msps、23 GB 量级的宽带 E5 AltBOC
  • 零第三方 GNSS 依赖,21,000 行 C++20 自己写到底
  • P ⊇ T ⊇ S 三集合模型,把实验自由度做成了自洽的约束系统
  • 多系统联合定位,待估参数随系统数自动增长,ISB 稳定可观测
  • 缓存 + 断言 + manifest,让结果可复现、可回归、可追溯
  • 界面与批处理双入口,教学探索和自动化验收两不误

如果你正在学 GNSS、做 SDR 相关的课题、在做信号验证,或者只是单纯对「手机是怎么知道自己在哪」这件事有过好奇——希望这个项目能帮你少走一点弯路。

欢迎在评论区聊聊你想拿它验证什么,或者卡在了哪一步。


本文所有实测数据均来自项目批处理程序的真实运行,结果明细留盘可复现。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询