☰
GPS基础原理详解:从卫星测距到定位计算与误差分析
2026/10/5 1:01:40 网站建设 项目流程

GPS从入门到放弃(一)--- GPS基础原理

说实话,GPS这个玩意儿大家天天都在用,手机导航、打车、跑步记录、无人机返航,哪个都离不开它。但是你要是真问一句"GPS到底是怎么知道我位置的",能说清楚的人还真不多。我自己早年做定位模块开发的时候,也是被一堆术语锤得晕头转向:伪距、星历、电离层延迟、晶振误差、NMEA协议、WGS84坐标系……这些东西单独看都能看懂,连起来就不是那么回事了。这篇算是把我这些年踩过的坑和摸清的门道捋一遍,从最基础的原理讲起,适合刚接触GPS开发、或者想搞明白定位导航到底怎么工作的人。后续我还会写坐标转换、硬件天线设计、常见定位漂移排查这些话题。

1. 先搞明白GPS到底是个什么东西

1.1 三大部分:天上的、地上的、手里的

GPS全称是全球定位系统(Global Positioning System),最早是美国军方搞的,后来开放给民用。整个系统分三段:

  • 空间段:天上的卫星星座,目前大概有三十多颗卫星在轨运行,分布在6个轨道面上。这个设计保证了地球上任何一个地方、任何一个时刻,你头顶上空至少能看到4颗以上的卫星。
  • 地面段:分布在全球的地面监测站和主控站,负责监视卫星的轨道和时钟,定期把修正参数上传给卫星。
  • 用户段:就是我们手里的GPS接收机,手机、车载导航、定位模块都算。

这里有个很关键的思维转变:卫星不是"发信号告诉你在哪",而是"发信号告诉你它自己在哪、现在是什么时间"。接收机拿到这些信息之后,自己算出来自己在哪。说白了,卫星是一把"会报时的尺子",而定位计算这件事,完全是接收机自己完成的。

1.2 一颗卫星就是一把"会报时的尺子"

想理解GPS定位原理,最朴素的办法是先忘掉卫星,想一个生活中的场景:你站在操场上,听到远处有人敲鼓。你知道声音在空气中传播速度大约是340米/秒,你测出从鼓手敲下到声音传到你耳朵的时间差是3秒,那你就能估算出鼓手距离你大约1020米。

GPS的原理一模一样,只不过把声速换成了光速(约30万公里/秒),把鼓声换成了卫星发射的微波信号。卫星在发射信号时,会在信号里包含自己当前的位置坐标和发射时间。接收机收到信号后,对比自己的本地时钟和信号里记录的发射时间,时间是已知的,速度是已知的,距离就能算出来:

距离 = (接收时间 - 发射时间) × 光速

这个计算出来的距离叫伪距。注意"伪"这个字很重要,因为实际算出来的距离跟真实距离之间是存在误差的,后文会细聊。

1.3 为什么至少要4颗卫星才能定位

一个距离只能确定一个球面。如果只收到一颗卫星,你只知道自己在这个球面上某个位置,具体不知道在哪。收到两颗卫星,两个球面相交成一个圆,你在这个圆的某一点上。收到三颗卫星,三个球面交到两个点,其中一个点通常在地球表面附近,另一个点在太空深处,可以直接排除,理论上三颗卫星就能定出经纬度了。

但现实是,你的接收机里面用的时钟是一个普通的石英晶振,远没有卫星上搭载的原子钟那么准。哪怕只偏了微秒级别,乘以光速之后的位置误差就是几百米。所以接收机需要引入一个额外的未知数:接收机的时钟钟差。

这就变成了四元方程:经度(x)、纬度(y)、高度(z)、时钟差(Δt)。要解四个未知数,至少需要四个方程。这就是为什么搜到4颗卫星是一个分水岭,少于4颗根本解不出位置,多于4颗反而可以做一些冗余校准,让结果更稳定。

2. 卫星信号里到底装了什么东西

2.1 导航电文里的核心信息

卫星发射的信号里,最核心的数据叫导航电文。里面包含了卫星星历、卫星时钟修正参数、电离层修正参数、卫星健康状况等信息。

其中最重要的可以说是星历。通俗讲,星历就是卫星的"轨道参数表",用它可以在任意时刻推算出卫星在空间中的精确位置。GPS卫星大约每两小时更新一次星历,地面监测站会持续跟踪每颗卫星的实际位置,把偏差算出来,再通过主控站上传给卫星,让卫星播发修正后的星历。

这个机制决定了你的接收机开机多久能定位。如果接收机里有有效的星历(比如刚才关机的手机),它知道卫星大概在什么方位,搜星会快很多,这就是所谓的热启动。如果完全没存星历,比如从仓库拿出来的新模块,它不知道该往哪个方向找卫星,只能全频段慢慢扫描,这就是冷启动,可能需要几十秒甚至好几分钟。

从这个角度也能看出来,星历其实是带"时效性"的。卫星一直在飞,轨道也在细微地变,如果接收机拿着两年前缓存的星历去算卫星位置,偏差会大到离谱,根本无法定位。

2.2 信号调制与抗干扰的底层逻辑

GPS卫星信号本身是极微弱的。卫星距离地面大约两万公里,发射功率大约只有50瓦左右,等信号传到地面时,功率已经衰减到约 -130dBm 量级。这个功率有多小呢?比环境底噪还低差不多20到30dB。也就是说,GPS信号实际上是淹没在噪声里的。

那它怎么能被接收到?关键在于调制方式。GPS信号采用了扩频通信技术。简单说,原始数据流通过一个已知的伪随机码序列进行调制,接收机用同样的伪随机码去相关解扩,就能把淹没在噪声里的信号"提"出来。这就像在嘈杂的派对上,所有人都同时在说话,你听不清单独的任何一个声音,但如果一个人用你们约定好的暗语说话,你就能在嘈杂中听懂他在说什么。

了解了这一点,就不难理解为什么天线设计和接收机灵敏度那么重要。信号本来就弱,如果天线增益不够、接收通道噪声太大,解扩出来的信噪比就会很差,定位精度和稳定性都会受到明显影响。

3. 定位计算的核心逻辑

3.1 伪距方程组的思想实验

前面说了,接收机到卫星的距离约等于光速乘以时间差,但这个时间差测量得并不完美,于是就有了伪距的概念。伪距和真实距离之间的关系可以写成:

伪距 = 真实距离 + 接收机时钟钟差 × 光速 + 各种延迟误差

其中,真实距离是卫星位置坐标和接收机位置坐标的函数,卫星位置可以通过星历算出,所以真正未知的就是接收机三维坐标加上钟差。这就是一个含有四个未知数的方程组,解出来就是你的位置和时间。

当年我第一看到"接收机帮你对表"这个观点时还挺不习惯的。仔细想想,GPS接收机不但给你定位,还顺便给你一个极其精准的时间源。很多基站同步、金融系统时间戳、电网相位测量都在用GPS授时功能,因为卫星上的原子钟实在太准了。

3.2 定位求解时的工程处理

在手算或者写代码模拟的时候,往往会用最小二乘法来处理这个非线性方程组。先猜一个初始位置,然后线性化、迭代求解,每次迭代都在调整接收机位置,直到残差收敛到足够小。实际接收机芯片里,用的是卡尔曼滤波器,它不仅有当前时刻的观测值,还把之前的运动状态也利用了起来,所以动态环境下输出更平滑、更稳定。

这儿要提一个常见的误解:有人觉得"GPS定位精度差是因为收到的卫星少"。卫星数量少确实是因素之一,但更本质的问题是信号传播路径上的误差。哪怕你收到12颗卫星,如果大量信号都是经过建筑物反射以后才到达的,算出来的位置照样可能偏出一大截,这就是常说的多径效应。

4. 误差从哪里来,怎么削掉它

4.1 误差来源分类

GPS定位误差按来源可以分成几个大类,每个类别的量级和应对手段差别很大:

误差来源产生原因典型量级削弱方法
卫星时钟误差卫星钟与GPS标准时间有偏差1~2米播发钟差参数,双频观测
星历误差卫星播发的轨道参数不精确1~2米精密星历,差分定位
电离层延迟带电粒子影响信号传播速度5~10米双频修正,模型修正
对流层延迟大气水汽影响信号传播1~3米模型修正
多径效应信号反射叠加1~5米甚至更大抗多径天线,信号处理
接收机噪声硬件热噪声、量化误差0.1~0.5米高性能射频前端

可以看到,大气层延迟误差占比相当大,尤其是电离层。电磁波穿过电离层时,传播速度会发生改变,而且这个改变量跟信号频率有关。这就是为什么后来出现了双频GPS接收机,用两个不同频率的信号做对比,就能比较准确地估算并消除大部分电离层误差。

4.2 多径效应是城市定位的头号杀手

我实际做项目中对多径效应感受最深。在开阔的郊区,GPS模块定位精度可以做到2米左右。但在高楼林立的商业区,同样的模块经常飘出去十几米,甚至出现跳变。原因就是信号经过玻璃幕墙、建筑物表面反射后才被接收机收到,此时接收机测得的"距离"实际上是从卫星到反射物再到接收机的总路径长度,比真实直线距离要长。

反射信号通常比直达信号晚到,而接收机的捕获环路一旦锁定在反射信号上,伪距就会被拉长。比较新的接收机芯片会用窄相关、边缘检测等技术压制多径,但在恶劣环境下还是不能完全避免。

如果项目里需要城市环境下的高精度定位,一般做法是接入地基增强系统的差分改正数,或者干脆融合惯导模块做惯导+GPS的组合导航,用加速度计和陀螺仪的数据顶住GPS信号被遮挡、反射时的位置漂移。

4.3 差分GPS和RTK到底是什么

地面上架一个已知准确坐标的基准站,它实时接收GPS信号,算出每颗卫星的伪距误差(因为基准站真实坐标是精确测量过的,所以误差可以直接求出来),然后把误差修正量通过无线链路播发给附近的移动站。移动站用这个修正量去纠正自己的伪距测量值,精度就能大幅提升。这就是差分GPS,也就是DGPS。

如果把载波相位观测值也用上,精度还能进一步提升到厘米级,这就是**实时动态差分(RTK)**技术。测绘领域用的就是RTK,测量精度能做到2厘米左右。不过RTK依赖基准站的改正数链路,信号盲区或者链路断开的时候,系统会自动降级,回到普通单点定位的精度。

5. 坐标系与地图显示之间的"坑"

5.1 WGS84坐标系是GPS的"母语"

GPS直接计算出来的坐标是WGS84坐标系下的经纬度。WGS84是一个地心地固坐标系,它用一个椭球体来近似地球的形状,所有GPS卫星的轨道参数也都是在这个坐标系下定义的。

日常开发里,绝大多数时候我们都是直接拿这个经纬度去地图上标注。但如果你做的是国内地图应用,马上会遇到一个绕不开的问题:火星坐标系。

国内主流地图服务商(包括高德、腾讯等)使用的坐标是在WGS84基础上做了非线性偏移加密处理之后的坐标系,通常是GCJ-02。WGS84和GCJ-02之间的偏移量不是固定常数,不同城市、不同位置偏移量都不一样,有的地方偏几十米,有的地方偏几百米。直接把GPS的WGS84坐标画在高德地图上,位置会偏出好大一截,看起来就像定位漂移。

处理办法是做一次坐标转换。下面给出一个常用的WGS84转GCJ-02的Python实现,这是有公开算法支撑的,可以直接用在数据预处理环节。

import math def wgs84_to_gcj02(lng, lat): """ 将WGS84坐标系经纬度转换为GCJ02坐标系经纬度 适用于中国大陆地区的地图坐标纠偏 """ a = 6378245.0 ee = 0.00669342162296594323 def _transform_lat(x, y): ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * math.sqrt(abs(x)) ret += (20.0 * math.sin(6.0 * x * math.pi) + 20.0 * math.sin(2.0 * x * math.pi)) * 2.0 / 3.0 ret += (20.0 * math.sin(y * math.pi) + 40.0 * math.sin(y / 3.0 * math.pi)) * 2.0 / 3.0 ret += (160.0 * math.sin(y / 12.0 * math.pi) + 320 * math.sin(y * math.pi / 30.0)) * 2.0 / 3.0 return ret def _transform_lng(x, y): ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * math.sqrt(abs(x)) ret += (20.0 * math.sin(6.0 * x * math.pi) + 20.0 * math.sin(2.0 * x * math.pi)) * 2.0 / 3.0 ret += (20.0 * math.sin(x * math.pi) + 40.0 * math.sin(x / 3.0 * math.pi)) * 2.0 / 3.0 ret += (150.0 * math.sin(x / 12.0 * math.pi) + 300.0 * math.sin(x / 30.0 * math.pi)) * 2.0 / 3.0 return ret dlat = _transform_lat(lng - 105.0, lat - 35.0) dlng = _transform_lng(lng - 105.0, lat - 35.0) radlat = lat / 180.0 * math.pi magic = math.sin(radlat) magic = 1 - ee * magic * magic sqrtmagic = math.sqrt(magic) dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * math.pi) dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * math.pi) mglat = lat + dlat mglng = lng + dlng return mglng, mglat

用法很简单:把GPS模块输出的WGS84经纬度传进去,返回的是GCJ-02经纬度,直接喂给高德地图API就行。值得注意的是,GPS在境内直接采集的原始坐标受法律法规管控,地图服务商播放的坐标又经过了偏移。这里只讨论已知公开的通用转换算法,做个人技术验证没问题。

5.2 把GPS数据导出到地图里看轨迹

做外业测试或者跑车实验时,光看串口输出的坐标很难直观判断定位质量。我常用的做法是把NMEA语句里的GGA或RMC字段解析出来,存成CSV文件,再转换成KML格式,直接用Google Earth打开看轨迹。

核心解析逻辑不复杂。NMEA的RMC语句长这样:

$GPRMC,064036.000,A,3103.4241,N,12122.7783,E,0.00,99.35,080722,,,D*67

其中3103.4241,N表示北纬31度03.4241分。注意这个格式是"度分"格式,要转成十进制度才能用:31 + 03.4241/60 = 31.0570683。很多新手直接拿这个数当十进制度用,结果点位偏得离谱,我曾经也干过这事儿,后来看到轨迹跑到海里才反应过来。

解析完坐标之后,可以自己拼KML文件。KML里头最关键的就是<coordinates>标签,里面按顺序写经度、纬度、高度,用逗号分隔。多写几个坐标点,Google Earth就会画出轨迹线,还能叠加到卫星影像上看,排查定位漂移和信号遮挡问题非常好用。

6. 天线选型:无源陶瓷天线和有源天线的门道

6.1 为什么GPS接收机大多用陶瓷天线

GPS信号频率在1575.42MHz,波长大约19厘米。按理论,一个高效的天线尺寸差不多是波长的一半,也就是10厘米左右。但消费级设备里根本塞不下这么大个天线,所以行业里普遍用的是陶瓷贴片天线。陶瓷材料的介电常数比较高,可以让天线的物理尺寸缩小到几毫米到十几毫米,同时保持可接受的增益。

陶瓷天线是无源器件,它本身不放大信号,只是把电磁波转换成电信号。接入接收机之后,信号经过接收机内部低噪声放大器(LNA)和射频前端处理后,才能进入基带解调。由于GPS信号极其微弱,无源天线到接收芯片之间的走线如果太长、损耗太大,信号质量会急剧下降。所以很多GPS模块会把无源陶瓷天线直接贴在模块上,紧挨着射频前端,尽量减少损耗。

6.2 什么时候必须用有源天线

如果设备结构决定了天线和主板距离比较远,比如车载追踪器把GPS天线装在车顶、主板藏在仪表台下面,连接线可能超过20厘米甚至更长。这时候无源天线加长馈线的损耗会吃掉大量信号,接收机很可能连星都搜不到。

解决办法是改用有源天线。有源天线内置了一个低噪声放大器,通常增益在15dB到30dB之间,能把微弱的GPS信号在进入长馈线之前先放大一遍。但放大器需要供电,所以有源天线一般有三根线:信号线、电源线、地线,或者通过同轴电缆馈电的方式,用一根射频线同时传信号和直流偏置。

给有源天线供电的电压常见的有3V、3.3V、5V,具体以天线规格为准。如果供电电压不对,或者偏置电路没做好,天线可能完全没输出。我见过不少板子因为少加了一个馈电电感,导致有源天线直流短路,接收机死活搜不到星。正确做法是在射频通路串一个电感给天线馈电,同时并联一个电容到地做射频旁路,防止射频信号串到电源轨上去。

6.3 实际项目中的天线布局心得

做便携设备时,陶瓷天线的净空区域特别重要。天线正上方不能有大面积金属遮挡,周围也尽量不要铺铜,否则天线辐射方向图会变形,增益下降。一般陶瓷天线会放在PCB板边角,且下方那一层掏空,不做完整地平面。还有一点容易被忽略:陶瓷天线对附近的塑料外壳厚度和材质很敏感,金属外壳几乎等于屏蔽罩,GPS信号直接废掉。样机阶段一定要实测整机灵敏度,别等开模完了才发现天线被壳子挡住。

如果板子上同时有Wi-Fi、蓝牙这些2.4G的天线和4G天线,GPS天线要尽量远离它们。GPS信号最弱,抗干扰能力也最差,其他天线的高次谐波或者辐射泄漏有可能直接落在GPS频段附近,拉低整机灵敏度。业内通常的做法是把GPS天线放在板子一角,其他射频天线放在相对的另一角,中间用地过孔墙隔离。

7. 为什么有时候定位"失效"了

7.1 GPS信号覆盖和遮挡的现实问题

GPS信号本质上是一种来自两万公里外卫星的微弱微波信号,几乎没有任何穿透能力。树叶稍微密一点、玻璃贴个隔热膜、隧道里拐个弯,信号就可能完全丢失。我测试过一辆贴了金属隔热膜的车,前排座位上的手机导航勉强能用,后排直接搜不到星。这不是设备坏了,是物理层面的信号衰减实在太严重。

所以那个热搜词"GPS生成式欺骗失效保护"背后的含义也容易理解了。GPS信号弱,意味着它很容易被干扰甚至被仿冒。实际工程里,当GPS信号被堵塞或者被欺骗时,单纯依赖卫星定位的系统就会失效。工业界成熟的应对思路是多源融合:

  • GNSS + 惯导:GPS信号短时丢失时,用IMU推算航位,输出连续轨迹。
  • GNSS + 基站定位:手机里常用,没有卫星信号时切到蜂窝基站做粗略定位。
  • GNSS + 视觉/雷达:自动驾驶的主流方案,用环境感知数据辅助车辆在地图中的位置匹配。

这种"不是只信一个源"的设计哲学,是工程系统可靠性的基本盘。做产品时如果链路里只有GPS一个定位源,一定要提前想好信号丢失时的降级策略。

7.2 冷启动、温启动、热启动的区别

  • 冷启动:接收机内没有任何有效的星历和位置信息,要重新搜索全部卫星信号,下载星历。这个过程可能需要30秒到几分钟。
  • 温启动:接收机存有旧星历(超过有效期但还没完全失效),或者大概知道当前时间和位置,只需下载部分新星历,几秒到几十秒。
  • 热启动:刚关机不久,星历和位置都还新鲜,重新开机后几秒内就能定位。

这个分类在做产品功耗设计时很关键。因为冷启动搜星阶段电流比较大,对电池供电的设备来说是一个不可忽略的功耗峰值。有些物联网追踪器会定期给模块发休眠命令,让模块保持热启动状态,就是为了避免频繁冷启动造成的高功耗和长定位时延。

8. 实测经验:一个定位漂移Bug的排查全过程

前几年做过一个车辆定位终端,客户反馈说车明明停在公司楼下,后台地图上显示的位置却在一个街区之外,而且每隔几十秒还会跳一下,让人很头疼。

我拿到设备后先做了三件事。

第一件事,检查天线。打开外壳发现GPS天线通过一根大约15厘米的延长线接到了主板,用的是无源陶瓷天线。我心里顿时一紧,因为无源天线接这么长的线,放大器在接收机内部,线缆损耗会吃掉一部分信号,极限情况下接收灵敏度会明显下降。不过手里没有频谱仪,只能先换上一条有源天线试一下,接上之后发现跳变少了一些,但漂移还在。

第二件事,把NMEA数据在开阔楼顶连续记录了一小时,解析出坐标轨迹。发现设备静止时,轨迹呈一个直径10米左右的云团状漂移,时不时还有一个明显的大跳变。在开阔环境下10米漂移看起来偏大,正常应该压到3米以内。

第三件事,检查了设备安装位置。客户把终端贴在了仪表台靠近前挡风玻璃的位置,挡风玻璃如果是金属隔热膜就麻烦了。让客户把设备临时挪到副驾挡风玻璃下沿,信号改善不少。但真正解决问题是换了带大参考地平面的有源天线,并且挪到车顶鲨鱼鳍内部,完全露天。之后漂移量降到了可接受水平,定位数据稳定很多。

这次排查给我最大的教训是:GPS定位飘移很多时候不是接收机芯片的问题,而是天线端、安装端、环境端的问题。芯片指标只是下限,实际体验上限被天线和结构设计决定。

现象可能原因排查方法
完全搜不到星天线没接好/天线损坏/供电异常用频谱仪测射频通路,短接有源天线电源串电流表
开机很久才定位星历过期/冷启动对比热启动与冷启动时间,检查天线馈线损耗
静止时位置漂移大多径效应/天线增益不足/供电纹波大换开阔场地测试,检查电源纹波
位置跳变到远方信号被遮挡后解算异常记录完整NMEA数据,用轨迹回放定位跳变时刻
车辆运动时定位乱跳车载电子干扰/天线位置不当逐步关闭车内电器排查干扰源
温度变化后失锁陶瓷天线频率偏了/射频匹配不良温箱实测灵敏度,对比不同天线

9. 一点个人总结和下一步方向

回到"GPS从入门到放弃"这个标题,我个人觉得真正想放弃的时刻,往往不是看不懂原理,而是把原理读了十遍,设备在现场还是定不了位。其实GPS原理的本质就那么几件事:卫星播发时间和位置,接收机测距、解方程、输出坐标。这项技术非常成熟,成熟到有时候我们会忘记它背后其实是原子钟、相对论修正、扩频通信这些硬核技术的集合。

如果你正打算入门GPS开发,我的建议是先买一个带UART输出和PPS授时脚的模块,接个USB转串口,在电脑上看NMEA输出的原始数据。然后拿手机做对比,看同一时间同一个位置的坐标差多少。这个过程会让你迅速建立对GPS的"直觉"。接下来可以试试自己解析NMEA语句,画一条轨迹,体验一下从数据到可视化的完整链路。只有亲手把数据流跑通,那些枯燥的原理才会真正串联起来。

下一篇我会重点写NMEA协议解析、常见模块对比,以及把GPS轨迹数据转换到国内地图坐标的实操细节,包括一些可以直接跑的Python脚本。有实际项目经验的朋友也欢迎在评论区分享自己踩过的GPS坑,一起把这些经验沉淀下来。

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

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

立即咨询