
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坑一起把这些经验沉淀下来。