2、定位基础理论:卫星定位基本原理、伪距测量与载波相位、定位误差来源分析、坐标系与时间系统
各位同学,欢迎来到定位基础理论这一章。说实话,这部分内容看起来有点枯燥,但它是整个双模定位系统的根基。我当年刚入行时,觉得只要会用模块就行,理论不重要。结果有一次项目调试,定位数据死活不对,折腾了两天,最后发现是坐标系搞错了。嗯,从那以后,我再也不敢轻视这些基础了。
2.1 卫星定位基本原理
卫星定位的原理,说白了就是一个「三边测量」问题。你想想看,如果我们知道三颗卫星的位置,又知道卫星到接收机的距离,那就能算出接收机的位置。这就像你在教室里,知道三个墙角的位置,又知道离每个墙角的距离,你就能确定自己坐在哪。
但实际中,卫星和接收机的时间不同步,所以需要第四颗卫星来解算时间误差。这就是为什么GPS至少需要4颗卫星才能定位。
核心公式:
接收机位置 (x, y, z) 和钟差 t 满足以下方程组:
√[(x₁ - x)² + (y₁ - y)² + (z₁ - z)²] + c·t = ρ₁
√[(x₂ - x)² + (y₂ - y)² + (z₂ - z)²] + c·t = ρ₂
√[(x₃ - x)² + (y₃ - y)² + (z₃ - z)²] + c·t = ρ₃
√[(x₄ - x)² + (y₄ - y)² + (z₄ - z)²] + c·t = ρ₄
其中 ρ 是伪距测量值,c 是光速。
我在项目中遇到过一个问题:在城市峡谷中,卫星信号被遮挡,可见卫星只有3颗。这时候怎么办?我个人的习惯是结合惯性导航(IMU)或者使用高程辅助,把海拔高度当作已知量,这样3颗卫星也能定位。
2.2 伪距测量与载波相位
伪距测量和载波相位,是两种不同的测距方式。我刚开始做定位时,觉得伪距简单粗暴,载波相位太复杂。后来发现,两者各有千秋。
2.2.1 伪距测量
伪距测量,就是测量信号从卫星到接收机的传播时间,再乘以光速。为什么叫「伪」距?因为测量值里包含了各种误差——卫星钟差、接收机钟差、大气延迟等等。说白了,它不是真实的几何距离。
伪距的精度一般在米级,对于普通导航够用了。但如果你要做厘米级的定位,比如自动驾驶、精准农业,伪距就不够看了。
2.2.2 载波相位
载波相位测量,是测量卫星发射的载波信号和接收机本地产生的载波信号之间的相位差。载波的波长很短(L1波段19cm),所以理论上精度可以达到毫米级。
但载波相位有个大坑——整周模糊度。你只能测到相位的小数部分,整数部分不知道。这就像你只知道秒针的位置,但不知道现在是第几分钟。
避坑指南:
我曾经在RTK项目中,因为整周模糊度解算失败,导致定位结果跳变了几十厘米。后来我总结出经验:
- 初始化时一定要保证卫星几何构型好
- 使用LAMBDA算法时,注意Ratio值的阈值设置
- 如果长时间失锁,建议重新初始化
2.3 定位误差来源分析
定位误差,说白了就是「理想很丰满,现实很骨感」。我整理了一下主要的误差来源,大家看看在实际项目中哪些最头疼。
| 误差来源 | 典型量级 | 应对方法 |
|---|---|---|
| 卫星星历误差 | 1-5米 | 使用精密星历、差分定位 |
| 卫星钟差 | 1-3米 | 广播星历修正、差分定位 |
| 电离层延迟 | 2-10米 | 双频接收机、电离层模型 |
| 对流层延迟 | 0.5-2米 | 模型修正(如Hopfield模型) |
| 多路径效应 | 0.5-10米 | 抗多路径天线、选址避开反射面 |
| 接收机噪声 | 0.1-0.5米 | 高质量接收机、滤波算法 |
我个人觉得,多路径效应是最难搞的。在城市环境中,高楼大厦反射信号,你测到的伪距可能偏大好几米。我有个项目在金融街测试,定位结果飘得跟喝醉了似的。后来换了扼流圈天线,情况才好转。
注意:
电离层延迟在太阳活动高峰期会显著增大,最高可达50米以上。如果你在做双模定位(GPS+北斗),可以利用两个系统的不同频率来消除电离层误差。这是双模系统的一大优势。
2.4 坐标系与时间系统
坐标系和时间系统,是定位中最容易出错的地方。我见过太多人因为坐标系搞混,导致定位结果偏差几百米。
2.4.1 常用坐标系
GPS用的是WGS-84坐标系,北斗用的是CGCS2000坐标系。两者非常接近,差异在厘米级,一般导航可以忽略。但如果你做高精度应用,比如测绘,就必须考虑这个差异。
另外,我们常用的经纬度是地理坐标系,而实际计算中用的是地心地固坐标系(ECEF)。两者之间的转换,我建议直接用现成的库,比如PROJ.4,自己写容易出错。
坐标转换示例:
// 经纬度转ECEF(简化版)
double lat = 39.9042; // 北京纬度
double lon = 116.4074; // 北京经度
double h = 50.0; // 海拔高度
double a = 6378137.0; // 地球长半轴
double f = 1/298.257223563; // 扁率
double e2 = 2*f - f*f; // 第一偏心率平方
double N = a / sqrt(1 - e2 * sin(lat*PI/180) * sin(lat*PI/180));
double x = (N + h) * cos(lat*PI/180) * cos(lon*PI/180);
double y = (N + h) * cos(lat*PI/180) * sin(lon*PI/180);
double z = (N*(1-e2) + h) * sin(lat*PI/180);
2.4.2 时间系统
GPS时间系统是GPST,北斗是BDT。两者都是原子时,但起点不同。GPST从1980年1月6日开始,BDT从2006年1月1日开始。两者相差1356周(约14秒)。
另外,GPST和UTC之间还有闰秒的问题。我记得2017年有一次闰秒调整,很多老旧的接收机直接死机了。所以,我建议在代码中处理时间时,尽量使用原子时,避免闰秒带来的麻烦。
我的经验:
在嵌入式系统中,时间处理建议使用周内秒(TOW)格式,这样计算简单,占用资源少。需要显示时再转换成UTC。另外,北斗和GPS的时间转换,我一般用一个偏移量搞定,不需要每次都查表。
好了,这一章的内容就到这里。下一章我们会讲双模定位的硬件设计,包括天线选型、射频前端、基带处理等等。到时候我会分享一些实际项目中的电路设计经验,敬请期待。