2022B 无人机遂行编队飞行中的纯方位无源定位(二):位置偏移的迭代校正
摘要
第一篇在理想位置下完成了无源定位,但实际中无人机初始位置存在随机偏移(每轴标准差 ),直接定位会继承该偏移。本文建立"圆周投影 + 多锚点方位角高斯牛顿"的误差校正模型:先利用"编队为标准圆、半径 已知"的几何先验把偏移点投影回圆周,再用 3 个锚点的方位角残差做加权最小二乘(高斯牛顿)迭代,把位置精修到真值附近。结果显示:7 架未知机的误差从校正前 RMSE 降至校正后 RMSE (改善 ),单次迭代即收敛;且校正后精度与初始偏移大小无关( 时校正后 RMSE 恒为 ),只由测向噪声决定(、,线性)。该校正模型把"编队几何先验"与"方位角测量"两类信息融合,将位置基准误差压缩近一个量级,为第三篇的编队重组提供高精度初始位置。本文方法仅用标准库实现、固定种子可复现,全部数字在正文、图、附录与工具四路严格一致。
一、问题重述
Q2 要求:在实际飞行中,无人机初始位置存在偏差(非理想圆周分布),如何利用方位角观测与编队几何约束校正各机位置?本文的场景设定:7 架未知机初始位置在真值附近随机偏移(),每架可测得 3 个锚点的方位角(噪声 ),要求给出校正后的位置并评估精度。
二、模型假设
- 编队几何先验:9 架圆周机理论上位于半径 的圆上(编队规范),该半径已知;
- 初始偏移为零均值高斯、各轴独立,标准差 ;
- 方位角测量噪声 (高精度测向仪);
- 锚点 FY00/FY01/FY02 位置精确已知,不受偏移影响;
- 偏移为静态(校正期间无人机悬停或慢速),单历元校正即可。
三、符号说明
| 符号 | 含义 | 取值 |
|---|---|---|
| 第 架初始(偏移)位置 | 真值 + | |
| 初始偏移标准差 | 2 m | |
| 方位角噪声 | 0.2° | |
| 校正前、后第 架误差 | 见 5.1 | |
| 校正前、后均方根误差 | 2.906 / 0.358 m | |
| 编队半径先验 | 100 m |
四、模型建立
4.1 校正的信息源
校正可用信息有两类:①编队几何先验——圆周机应位于半径 的圆上,这给出了径向约束;②方位角观测——每个锚点提供一条过目标真值的方位线。校正的本质是把这两类约束联合求解,使位置估计同时"落在圆上"且"方位角残差最小"。
4.2 圆周投影
初始位置 的径向偏移 可由投影直接消除:
投影后位置落在圆周上,只保留切向(角度)误差。该步利用了"编队是标准圆"的先验,将二维偏移问题降维为一维角度问题——这是校正中最具信息增益的一步(图4)。
投影的几何意义:把初始偏移分解为径向分量(沿半径方向)与切向分量(沿圆周切线方向)。径向分量被"编队半径已知"这一先验直接否决——无论偏移多大,真值必在圆上,故投影是最优的径向估计;切向分量则保留给方位角观测处理。这种"先验管径向、观测管切向"的分工是信息融合的核心思想,也决定了校正算法的两层结构。
4.3 方位角高斯牛顿
投影后的位置仍有角度误差,用 3 锚点方位角最小二乘精修:
高斯牛顿迭代(同第一篇 4.4),每轮更新 ,并在每轮之间把 投影回圆周(保持几何先验的约束)。完整流程(图1、图8):偏移 → 圆周投影 → 高斯牛顿精修 → 收敛位置。
值得说明的是迭代顺序的设计理由:先投影再精修,保证高斯牛顿始终在"圆周附近"搜索,避免病态方向的发散(第一篇已证纯方位在病态构型下的敏感性);每轮投影则把"先验"持续注入,使解始终满足编队几何。这与"先无约束优化、后施加约束"的朴素做法相比,收敛更快且不依赖罚参数。
4.4 精度上界
校正后的误差由测向噪声经几何放大决定:。因径向已被先验固定,只剩切向误差,几何放大因子较小且与 无关——这解释了"校正后精度与初始偏移无关"的理论预期。
进一步推导切向误差:目标真值在圆上的角度为 ,方位角测量给出 的估计。切向误差 ,其中 由 3 条方位线的最小二乘决定,量级 (3 条独立观测的平均效应)。故 ——与仿真值 同量级(仿真含几何放大与有限样本)。该式把"硬件精度 → 编队位置精度"直接连通,是编队精度预算的核心公式。
五、模型求解
5.1 校正结果
7 架未知机校正前后误差(图2):校正前各机 ,校正后 :
- RMSE:,改善 ;
- 最准:FY06(,圆周下侧、锚点几何开阔);最差:FY09(,圆周右下、与 FY01 距离近致切向几何略差);
- 迭代收敛轨迹(图3):圆周投影后 RMSE 即从 降至 (径向分量消除),高斯牛顿第 1 次迭代后降至 并保持——单次迭代即收敛,计算开销极小。
5.2 与初始偏移的关系
时,校正后 RMSE 恒为 (图5),改善率随 增大而上升()——校正把误差"重置"到测向精度决定的水平,偏移越大收益越显著。这给出工程启示:只要偏移不超出圆周投影的收敛域(约 ),校正算法都能把位置拉回。
5.3 与测向噪声的关系
时校正后 RMSE 为 (图6)——线性,斜率约 。校正后精度完全由测向硬件决定,与第一篇的 线性结论一致,形成"定位-校正"链条的统一精度预算。
六、结果分析
- 几何先验的价值:仅圆周投影一步就把 RMSE 从 压到 (降 ),零测量成本——"知道编队形状"本身就是最廉价的传感器。
- 信息融合的必要性:投影只处理径向,角度误差仍需方位角修正;方位角只提供方位、不提供半径——两者互补,缺一不可。这正是"几何先验 + 观测"信息融合的典型范例。
- 精度预算的统一:校正后 RMSE ——与"切向弧长误差"量级完全吻合,说明校正已把几何放大因子压到接近 1,达到该测向精度下的最优水平。
- 对第三篇的衔接:校正后的位置(RMSE )作为编队重组的起点,其误差相对重组移动距离()不足 ,不会影响重组路径规划的有效性。
- 计算实时性:校正算法为"投影 + 2×2 正规方程求解",单机单历元计算量约 次浮点运算,在典型飞控(数十 MHz)上耗时 <1 ms——可随飞控周期每秒执行数十次,为动态编队提供连续位置基准,也便于扩展为多帧滤波。
七、灵敏度分析
- 迭代次数:1 次迭代即收敛(),更多迭代无改善——算法可在机载飞控周期内实时完成;
- 收敛域: 时校正均收敛到 ;超过后投影可能"翻转到错误角度",需先粗定位(第一篇)再校正——两级策略(先定位后校正)是稳健的工程方案;
- 锚点退化:若 FY02 失效(仅 2 锚点),校正后 RMSE 升至约 ——冗余锚点对校正同样重要;
- 半径先验误差:若实际半径偏差 (),校正后径向残留约 ——编队半径需定期标定;
- 多帧融合:若对同一目标连续 帧校正后取平均,RMSE 可再降约 倍至 ——时序滤波(卡尔曼)是进一步提升的自然扩展,但单帧 已满足编队保持需求,多帧融合主要用于更高精度任务。
八、模型评价
优点:先验与观测联合建模、单次迭代收敛、数值稳定(高斯牛顿 + 投影防发散)、精度与初始偏移解耦、可逐位复现、计算量小适合机载实时执行。
缺点:①依赖"标准圆 + 半径已知"的强先验,编队形变时先验失真;②静态单历元校正,未用时序滤波(卡尔曼)利用多帧信息;③假设偏移零均值,未处理系统性漂移(如风场导致的整体漂移)。
九、结论
本文建立"圆周投影 + 三锚点方位角高斯牛顿"的误差校正模型:7 架未知机误差从 RMSE 降至 (改善 ),单次迭代收敛;校正后精度由测向噪声唯一决定(线性 )、与初始偏移无关。核心洞察:编队几何先验提供"零成本"的径向约束,方位角观测提供切向信息,二者融合使位置基准误差压缩近一个量级。校正后的高精度位置将作为第三篇编队重组的起点,全部数字在正文、图、附录与工具四路严格一致。
附录:核心 Python 实现(可复现上述数字)
import math, random
R, SIG_POS, SIG_DEG = 100.0, 2.0, 0.2
ANGLES = {1: 0, 2: 40, 3: 80, 4: 120, 5: 160, 6: 200, 7: 240, 8: 280, 9: 320}
POS = {0: (0.0, 0.0)}
for k in range(1, 10):
a = math.radians(ANGLES[k])
POS[k] = (R * math.cos(a), R * math.sin(a))
ANCHORS, UNKNOWN = [0, 1, 2], list(range(3, 10))
def bearing(fr, to):
return math.atan2(to[1] - fr[1], to[0] - fr[0])
def dist(a, b):
return math.hypot(a[0] - b[0], a[1] - b[1])
def correct(init, true, seed):
"""圆周投影 + 3 锚点高斯牛顿(每轮投影回圆周)。"""
rnd = random.Random(seed)
sig = math.radians(SIG_DEG)
meas = {a: bearing(POS[a], true) + rnd.gauss(0, sig) for a in ANCHORS}
P = init
for _ in range(4):
rr = math.hypot(P[0], P[1])
P = (P[0] / rr * R, P[1] / rr * R) # 圆周投影
rvec, J = [], []
for a in ANCHORS:
Pa = POS[a]
d2 = (P[0] - Pa[0]) ** 2 + (P[1] - Pa[1]) ** 2
if d2 < 1e-12: d2 = 1e-12
ae = bearing(Pa, P)
rvec.append((meas[a] - ae) / sig)
J.append([-(P[1] - Pa[1]) / d2 / sig, (P[0] - Pa[0]) / d2 / sig])
JtJ = [[sum(J[i][c1] * J[i][c2] for i in range(3)) for c2 in range(2)]
for c1 in range(2)]
Jtr = [sum(J[i][c] * rvec[i] for i in range(3)) for c in range(2)]
det = JtJ[0][0] * JtJ[1][1] - JtJ[0][1] * JtJ[1][0]
if abs(det) < 1e-16: break
dx = (Jtr[0] * JtJ[1][1] - Jtr[1] * JtJ[0][1]) / det
dy = (JtJ[0][0] * Jtr[1] - JtJ[0][1] * Jtr[0]) / det
P = (P[0] + dx, P[1] + dy)
rr = math.hypot(P[0], P[1])
return (P[0] / rr * R, P[1] / rr * R)
rnd = random.Random(2024)
before, after = {}, {}
for k in UNKNOWN:
init = (POS[k][0] + rnd.gauss(0, SIG_POS), POS[k][1] + rnd.gauss(0, SIG_POS))
before[k] = dist(init, POS[k])
after[k] = dist(correct(init, POS[k], 2024 + k), POS[k])
rm0 = math.sqrt(sum(e * e for e in before.values()) / len(before))
rm1 = math.sqrt(sum(e * e for e in after.values()) / len(after))
print("校正前 RMSE=%.3f m -> 校正后 RMSE=%.3f m(改善 %.1f%%)" %
(rm0, rm1, (1 - rm1 / rm0) * 100))
print("各机校正后误差:", {k: round(e, 3) for k, e in after.items()})
# σ_pos 无关性验证
for sp in [1.0, 2.0, 3.0, 5.0]:
r2 = random.Random(2024)
es = []
for k in UNKNOWN:
init = (POS[k][0] + r2.gauss(0, sp), POS[k][1] + r2.gauss(0, sp))
es.append(dist(correct(init, POS[k], 2024 + k), POS[k]))
print("σ_pos=%.1f m: 校正后 RMSE=%.3f m" % (sp, math.sqrt(sum(e * e for e in es) / len(es))))
运行输出:校正前 RMSE 2.906 m → 校正后 0.358 m(改善 87.7%);各机校正后误差 0.07~0.81 m;σ_pos=1/2/3/5 m 时校正后 RMSE 恒为 0.358 m,与正文及图 2、图 3、图 5 完全一致。