2. 坐标系与空间参考:地理坐标系、机体坐标系、经纬度与UTM、高度系统(AGL/MSL)

做航线规划,第一个绕不开的问题就是:飞机到底在哪儿?

你可能会说,GPS报个经纬度不就行了?嗯,没那么简单。我刚开始飞无人机的时候,也以为经纬度就是一切。直到有一次,我在山区做测绘,飞机返航点设在了经纬度坐标上,结果落地偏差了十几米——后来才发现,是坐标系没搞对。

这一章,我们就来把坐标系这件事彻底讲清楚。你理解了它,后面的航点设计、航线偏移、避障逻辑,都会顺很多。

2.1 地理坐标系:地球不是平的

地理坐标系,说白了就是用经纬度来描述地球上的位置。地球是个椭球体,不是正圆,所以不同国家、不同地区用的椭球模型也不一样。

坐标系名称 椭球模型 主要使用区域
WGS-84 WGS 84 全球(GPS默认)
CGCS2000 CGCS2000 中国
GCJ-02 WGS-84加密偏移 中国(高德、腾讯地图)
BD-09 GCJ-02二次加密 中国(百度地图)
⚠️ 避坑指南: 我曾经在对接百度地图API时,直接把BD-09坐标写进了航点任务,结果飞机飞到了偏离目标点几百米的地方。记住:无人机飞控只认WGS-84,其他坐标系必须转换。

我个人习惯,在航线规划软件里统一使用WGS-84。如果遇到客户提供的地图数据是GCJ-02或BD-09,我会先做一次坐标转换,再写入航点文件。

2.2 机体坐标系:飞机自己的“身体坐标”

地理坐标系描述的是飞机在地球上的位置,而机体坐标系描述的是飞机自身的姿态和方向。

机体坐标系的原点通常在飞机的重心,三轴定义如下:

  • X轴(前向):指向机头方向
  • Y轴(右向):指向飞机右侧
  • Z轴(下向):指向飞机下方(符合右手定则)

你想想看,飞机转弯、俯仰、横滚,这些动作都是在机体坐标系里描述的。飞控通过IMU(惯性测量单元)感知这些变化,再结合地理坐标系,才能算出飞机到底往哪飞。

💡 小技巧: 在做航线规划时,如果你需要让飞机在某个航点执行“偏航角”动作(比如让机头对准某个目标),这个偏航角就是相对于机体坐标系的。我一般会在任务脚本里明确标注:yaw_angle_relative_to_north 还是 yaw_angle_relative_to_heading,避免混淆。

2.3 经纬度与UTM:从球面到平面

经纬度是球面坐标,适合描述全球位置。但航线规划里,我们经常需要计算距离、面积、航点间距——这些在球面上算起来很麻烦。

所以就有了UTM(通用横轴墨卡托)投影。它把地球切成60个带区,每个带区6度经度宽,然后把球面投影到平面上。

特性 经纬度(WGS-84) UTM
坐标单位 度、分、秒 米
适用场景 全球定位、航点存储 局部区域距离/面积计算
精度 随纬度变化 带区内高精度(<1米)
缺点 距离计算复杂 跨带区需转换

我在做测绘航线规划时,习惯先用经纬度定义航点,然后转成UTM坐标来计算航点间距和总航程。这样算出来的距离,误差可以控制在厘米级。

📌 核心要点: 经纬度是“存位置”,UTM是“算距离”。两者配合使用,才能既保证定位准确,又保证计算高效。

2.4 高度系统:AGL与MSL

高度问题,是新手最容易踩坑的地方。我见过不止一次,飞机在山区飞行时,明明设了100米高度,结果撞上了山腰——因为高度参考搞错了。

  • MSL(Mean Sea Level,平均海平面):以海平面为基准的绝对高度。GPS给出的高度就是MSL。
  • AGL(Above Ground Level,离地高度):以正下方地面为基准的相对高度。避障、仿地飞行用的就是AGL。

为什么会出问题?因为MSL高度不随地形变化。你设了MSL 200米,飞过一座海拔150米的山顶时,飞机离山顶只有50米——如果山更高,就直接撞上了。

⚠️ 避坑指南: 我曾经在山区执行测绘任务,用了MSL高度,结果飞机在翻越山脊时差点撞树。后来我改用了AGL+地形跟随模式,飞机自动根据下方地形调整高度,才安全完成。记住:山区飞行,优先用AGL。

现在很多飞控支持“相对起飞点高度”,这其实是一种折中方案。它把起飞点的MSL高度作为基准,然后往上加。但如果你从山顶起飞,飞到山谷,这个高度就不准了。

2.5 知识体系总览

下面这张图,把本章的核心概念串在了一起。你可以把它当作坐标系与空间参考的“速查地图”。

坐标系与空间参考知识体系 坐标系与空间参考知识体系 地理坐标系 机体坐标系 WGS-84 GCJ-02 / BD-09 CGCS2000 X/Y/Z 三轴 UTM 投影(平面坐标) 高度系统 MSL(绝对高度) AGL(相对高度) 核心原则:经纬度存位置 → UTM算距离 → AGL保安全

2.6 实战:坐标转换代码示例

下面是一段Python代码,演示了如何将WGS-84经纬度转成UTM坐标,并计算两点之间的距离。我在实际项目中经常用这个片段。

import utm
from math import radians, sin, cos, sqrt, atan2

# 定义两个WGS-84航点
lat1, lon1 = 40.7128, -74.0060  # 纽约
lat2, lon2 = 34.0522, -118.2437 # 洛杉矶

# 转成UTM坐标(自动选择带区)
x1, y1, zone1, letter1 = utm.from_latlon(lat1, lon1)
x2, y2, zone2, letter2 = utm.from_latlon(lat2, lon2)

print(f"纽约 UTM: {x1:.2f}, {y1:.2f} (Zone {zone1}{letter1})")
print(f"洛杉矶 UTM: {x2:.2f}, {y2:.2f} (Zone {zone2}{letter2})")

# 计算平面距离(米)
distance_m = sqrt((x2 - x1)**2 + (y2 - y1)**2)
print(f"直线距离: {distance_m/1000:.2f} km")
💡 提示: 如果两个航点跨UTM带区,直接计算距离会有误差。我一般会先判断带区是否相同,如果不同,就改用Haversine公式在球面上算距离。

2.7 本章小结

坐标系和空间参考,是航线规划的“地基”。地基不稳,上层建筑再漂亮也没用。

  • 地理坐标系:用经纬度描述位置,全球通用,但注意WGS-84、GCJ-02、BD-09的区别。
  • 机体坐标系:描述飞机自身姿态,偏航角、俯仰角、横滚角都在这个坐标系里定义。
  • UTM投影:把球面坐标转成平面米制坐标,方便计算距离和面积。
  • 高度系统:MSL是绝对高度,AGL是相对高度。山区飞行,优先用AGL。