背景
最近在做一个基于当前 GPS 坐标,通过输入目标经纬度来计算相对位置与距离的硬件装置。
在查阅相关算法时,我发现网上的推导过程大多较为碎片化或直接给出结论。为了彻底理解其底层的数学逻辑,我决定从零开始重新推导一遍,并将其系统地记录下来。
本文将完整呈现这一推导过程:从建立三维空间直角坐标系开始,利用向量点积导出球面余弦定律(Law of Cosines)。此外,我们还会深入探讨该公式在短距离场景下产生“精度丢失”的物理本质,以及如何利用半角恒等式引入 Haversine 公式 来修正误差。最后,我将分享如何通过数学化简,精简公式降低运算量,从而实现更高的运算效能。
简化模型(平面模型)
我们在高中数学中学习过欧几里得距离公式, 用于计算平面上两点之间的距离. 同样的,当地球表面两点距离相对较近时, 我们可以将这一局部地区视为一个平面, 此时直接使用欧几里得距离公式即可
但是当地球表面两点距离相对较远时, 我们就需要考虑地球的曲率了.下面将介绍如何计算球面两点之间的距离。
球面模型
真实的地球是椭球体, 考虑地球的曲率会增加计算的复杂度。 在大多数情况下, 我们可以将地球简化为球体, 得到如下图所示的几何模型。
其中,
计算任意两点间的距离
要在球面上精确锁定
从几何模型来看,这段距离本质上是球心角
具体的求解思路如下:
三维坐标转换:先通过经纬度将
可得AB两点之间的直线距离为
代入原公式
代入后得到
提取
括号内的部分可以被替换为经度差的余弦:
最终公式
这个公式就是著名的球面余弦定律 (Law of Cosines)。化简后的形式逻辑清晰,运算量从推导过程中的 9 次三角函数精简到了 6 次,非常适合嵌入式 MCU 运行。
踩坑笔记:数值稳定性的陷阱 (Numerical Stability)
虽然这个公式在数学上严丝合缝,但在计算机的浮点运算世界里,它存在一个致命的“短板”:两点距离极近(如小于几十米)时,精度会产生剧烈波动甚至完全失效。
究其原因,这主要源于计算机处理数字的物理局限:
- 有效精度被“挤”出去了:当 A、B 两点靠得非常近时,球心角
趋于 ,此时 的值会无限趋近于 。由于双精度浮点数 ( double) 的精度上限仅有 15-17 位,用“1”去承载一个极其微小的偏移量时,代表精确偏移量的最后几位有效数字会被直接截断。- 反余弦函数的“死亡陡坡”:观察
的图像可以发现(arccos 函数图像),它在 附近的导数趋向无穷大。这意味着在 附近,自变量哪怕只有极其微小的抖动(比如仅仅是最后一位的舍入误差),都会被 函数无限放大,导致计算出的距离在 和一个巨大的错误值之间“反复横跳”。 简而言之,对于需要处理近距离(如几米到几十米)的定位应用,球面余弦定律可能会直接罢工。为了搞定这个坑,我们需要引入基于半角恒等式推导出的 Haversine 公式。
Haversine公式
在介绍Haversine公式之前, 我们先介绍一下正矢函数
如上图所示,versine函数中文叫正矢函数, 定义为
红色线段为
基于高中学过的半角公式
将其两边平方得到
基于高中学过的三角恒等式变形
通过变形,我们可以得到积化和差的形式:
现在回到球面余弦定律的公式
提取其中的公因式
根据弧长公式
则有
此时两边同时被1减去,得到
稍作整理
注意到
根据半正矢函数定义
再次代入弧长公式
经过一系列三角函数变换, 最终得到的这一公式被称为Haversine公式 它解决了球面余弦定律在近距离计算时的数值稳定性问题
下一篇, 我们将介绍如何计算任意两点之间的方位角 (Bearing)