一、赛题简介
(一)2025六大选题
//源自官方文件
(二)本题要求
单 / 双 / 三频相位周跳探测、伪距多路径误差估算、相位平滑伪距。
二、题目预测与分析
(一)赛题预测
- 给定试题册,会包含原始数据、具体的实现流程、结果要求。
- 参赛选手要编程实现的:
- 读取原始数据
- 数据预处理与质量检测三大模块:
- 周跳探测与修复
- 伪距多路径改正
- 相位平滑伪距
- 多模块协同处理以及质量综合评估
- 结果输出
(二)深度剖析
//这部分内容很多,包括各个模块涉及到的原理,友友们如果不想深究的话,可以直接跳到2.2.8,我在这部分给出了对这道赛题的整体理解的总述。
2.2.1 原始数据分析
- 给定某测站的双频(L1/L2)RINEX 2.11 格式观测文件(
obs.dat
)及对应星历文件(nav.dat
),大概会是这样👇
2.2.2 周跳探测与修复模块
- 原理:GNSS(全球导航卫星系统)信号在传输过程中,由于卫星信号遮挡、电离层闪烁等因素,会使载波相位观测值发生整周数的突变,即周跳 。在单频情况下,通过分析载波相位观测值的变化率等方法来探测周跳;双频或三频时,利用不同频率信号受电离层延迟等误差影响不同的特性,构造线性组合(如宽巷组合、窄巷组合等),提高周跳探测的精度和可靠性。
- 作用:准确探测周跳是保证 GNSS 载波相位观测数据质量的关键,只有正确修复周跳,才能利用载波相位观测值进行高精度定位、定轨等后续处理。
- 处理方法:
//源:AI深度思考
2.2.3 伪距多路径改正模块
- 原理:多路径误差是 GNSS 测量中重要的误差源之一,它是由于卫星信号经过反射物(如高大建筑物、水面等)反射后进入接收机,与直接信号产生干涉,导致测量的伪距产生偏差 。通过分析不同卫星信号的相关特性,比如利用不同高度角卫星信号受多路径影响程度不同,结合接收机天线特性、周围环境信息等,建立模型来估算伪距多路径误差。
- 作用:准确估算多路径误差,有助于在 GNSS 数据处理中对其进行改正,提高定位精度,尤其是在城市峡谷、水域附近等多路径效应严重的环境下,对提升定位可靠性意义重大。
- 处理方法:
2.2.4 相位平滑伪距模块
- 原理:载波相位观测值精度高但存在整周模糊度问题,伪距观测值精度相对低但无整周模糊度。相位平滑伪距是利用载波相位观测值的高精度特性,对伪距观测值进行平滑处理。一般是基于卡尔曼滤波等滤波算法,将载波相位观测值与伪距观测值进行融合,以改善伪距观测值的精度。
- 作用:经过相位平滑后的伪距,精度得到提高,可用于提高 GNSS 定位的精度和稳定性,特别是在动态定位场景下,能更好地满足实时定位需求。
- 处理方法:
2.2.5 三大预处理模块的逻辑
2.2.6 多模块协同处理以及质量综合评估模块
2.2.7 结果输出预测
-
预处理后数据文件
-
周跳修复后相位文件(
phase_corrected.obs
) -
多路径改正后伪距文件(
pseudo_range_corrected.obs
) -
平滑伪距文件(
smoothed_pseudo_range.dat
)
-
-
质量评估报告
-
文本报告(
quality_report.txt
) -
可视化报告(按照规律,文本报告就够了)
-
2.2.8 整体处理链路
- 其实简而言之,依旧是常规套路:
- 读取GNSS多星多频数据
- 执行三部分预处理
- 输出结果
三、C#实现⭐⭐⭐⭐⭐
(一)文件组织架构--MVVM
//这一赛题真的挺复杂,在组织文件的时候用了MVVM这个方法。简单来讲,在我们这个程序里的体现,就是实现分层处理。GNSSDataProcessing.Core
类库中接受原始数据并存放具体的计算,是最底层的实现。forms文件夹下的各个窗体中只需要关注要实现什么功能,控件怎样排布。在窗体中通过代码建立类库与窗体控件的关联,实现当用户点击控件时,能够正确执行对应代码,输出理想结果。
//以下是对MVVM的详细介绍。
-
3.1.1 Model(模型层)
- 聚焦业务逻辑与数据管理 ,涵盖数据的存储、获取、处理以及业务规则的实现。
- 在我们的 GNSS 数据处理程序中,就对应我们的
GNSSDataProcessing.Core
类库。 - 负责 GNSS 原始数据的读取(对接文件、网络等数据源 )、解析(按 RINEX 等格式规范处理 )、以及数据校验(检查数据完整性、合法性 )等操作 ,完全不关心数据如何在界面展示。
-
3.1.2 View(视图层)
- 即用户直接交互的界面 ,负责展示数据、接收用户输入(点击、输入文本等操作 )。
- 在 Windows 窗体应用中,就是
GNSSDataProcessing.WinForms
项目里Forms
目录下的各个窗体(如MainForm
、ObservationForm
),通过 WinForms 提供的控件(按钮、表格、标签等 )搭建界面,用于呈现 GNSS 处理后的数据(观测数据表格展示、周跳信息列表展示 ),以及响应用户的文件打开、处理操作等交互。 - 本身 “很单纯” ,几乎不包含复杂业务逻辑 ,主要做数据展示和事件触发 ,像按钮点击事件只是触发一个指令,具体逻辑交给 ViewModel 处理,它不知道 Model 层具体怎么运作,只和 ViewModel 交互。
-
3.1.3 ViewModel(视图模型层)
- 作为 View 和 Model 之间的 “桥梁” ,一方面从 Model 获取数据并进行转换、封装 ,使其适配 View 展示需求;另一方面接收 View 传递的用户操作(如按钮点击 ),调用 Model 对应的业务逻辑处理 ,并在数据变化时通知 View 更新。
- 数据转换与封装:比如在 GNSS 程序里,Model 层获取到的原始观测数据可能是较为底层、复杂的结构,ViewModel 会将其转换为 View 中表格控件能直接绑定显示的格式(整理成列表、设置好列对应的数据字段 )。
- 命令与事件处理:当用户点击 “处理数据” 按钮(View 层事件 ),ViewModel 接收该指令,调用 Model 层的数据处理方法(如周跳探测、多路径估算流程 ),处理完成后,通过数据绑定机制让 View 自动更新展示处理后的结果(如更新表格数据、提示处理完成状态 )。
- 数据绑定支持:借助框架提供的数据绑定功能(如 WPF 的 XAML 数据绑定、WinForms 可通过代码或第三方库实现简易数据绑定 ),建立 View 控件与 ViewModel 数据属性的关联,实现数据双向或单向同步 。
-
3.1.4 数据流向与交互
- 初始化与数据加载:程序启动后,ViewModel 初始化时会调用 Model 层方法获取初始数据(比如 GNSS 程序启动后,若需要加载默认配置或初始示例数据 ,ViewModel 让 Model 去读取、解析 ),Model 从数据源(文件、数据库、网络等 )拿到数据后返回给 ViewModel ,ViewModel 进行适配处理,然后通过数据绑定,View 自动渲染展示这些数据(如观测数据表格加载出初始数据 )。
- 用户交互处理:用户在 View 上进行操作(如点击 “打开文件” 按钮选择 GNSS 数据文件 ),View 将操作事件传递给 ViewModel ,ViewModel 调用 Model 层对应的业务方法(如
RinexFileReader
的文件读取解析逻辑 ),Model 执行完读取、处理(如解析 RINEX 格式数据 )后返回结果给 ViewModel ,ViewModel 再通过数据绑定更新 View 展示(如观测数据表格刷新为新读取的数据 ) - 数据更新反馈:当 Model 层数据因自身业务逻辑(如定时从网络获取最新 GNSS 星历数据 )发生变化时,会通知 ViewModel ,ViewModel 处理后,再通过数据绑定让 View 同步更新(如地图上卫星位置标记更新 )。
-
3.1.5数据绑定机制
- 双向绑定:是 MVVM 很重要的特性 ,View 中控件数据变化(如用户在输入框修改 GNSS 数据筛选条件 ),会自动同步到 ViewModel 对应的属性;反之,ViewModel 属性数据变化(如处理后得到新的平滑伪距结果 ),也会自动更新 View 控件显示 。例如在一些前端框架(Vue )里,通过
v - model
指令轻松实现输入框和 ViewModel 数据的双向绑定;在 WinForms 中,可借助类似BindingSource
等工具结合代码实现类似效果,让界面和数据保持实时同步。 - 单向绑定:相对简单,一般是从 ViewModel 到 View 的数据同步 ,用于一些只需展示、不需要用户反向修改的场景(如 GNSS 处理结果的展示标签 ,处理完成后结果数据从 ViewModel 单向更新到 View 显示 )。
- 双向绑定:是 MVVM 很重要的特性 ,View 中控件数据变化(如用户在输入框修改 GNSS 数据筛选条件 ),会自动同步到 ViewModel 对应的属性;反之,ViewModel 属性数据变化(如处理后得到新的平滑伪距结果 ),也会自动更新 View 控件显示 。例如在一些前端框架(Vue )里,通过
(二) GNSSDataProcessing.Core
3.2.1Model
//见名知意,在这一类库下,存放三大数据的结构定义类
- CycleSlip
- ProcessingResult
- SatelliteObservation
3.2.2 Interfaces
//存放整个程序处理过程中各大方法的接口类
- IFileReader(文件读取)
- ICycleSlipDetector(周跳检测)
- IMultipathEstimator(多路径效应检测)
- IPseudorangeSmoother(伪距平滑)
- IResultExporter(结果输出)
3.2.3 Algorithms
//对各大接口基于的算法的具体实现。这部分的算法是不唯一的,检测周跳、多效应路径、伪距平滑的算法都有很多种,这里小编把用到的算法也都列了出来,友友们如果觉得小编的麻烦,有更好的实现方法也欢迎在评论区指出,一起进步!
- MelbourneWubbenaCycleSlipDetector(使用Melbourne-Wubbena组合法检测周跳)
- MultipathEstimator(多路径效应的检测和修正)
- KalmanFilter(卡尔曼滤波器,用卡尔曼滤波算法来实现伪距平滑)
- KalmanFilterPseudorangeSmoother(利用卡尔曼滤波器实现伪距平滑)
3.2.4 Services
//服务层,数据读入,结果导出
- RinexFileReader(读取数据)
- CsvResultExporter(导出结果)
3.2.5 Processors⭐
//数据处理核心类,协调各处理步骤
- DataProcessor
3.2.6 小总结
以上就是这部分的全部内容啦,我们完成了对原始数据的读取、对误差(周跳,多路径效应)的修正、对伪距的精细化(相位平滑伪距)、对结果的导出。到此其实已经将这道题的核心完成了,之后就是在窗体中进行调用的事了。
明显的感觉到,这一道题和第一道题(RANSAC)相比,难度上升不止一点哈哈。
小编还有侥幸心理,想着这么难怎么会被选中成为今年的国赛题(因为到时候是六选一),但是小编知道,你以为也只是你以为哈哈,只是对这部分涉及到的知识不熟悉罢了。
比赛的意义,重要的真的不是那个结果。而是在备赛过程中,你跨越的难关,你积累的经验,你更高的视野。现在踏实走好的每一步,都有意义,都算数。
(三)GNSSDataProcessing.Form
//小编花了6/6下午的两三个小时,找到了一条更简易更适合在比赛那么短的时间中实现的方法!!!
//欢迎各位友友移步到这一篇专门实现简易程序的文章👇