【电子战】 第22篇:误差椭圆与置信区间【含matlab代码】

第22篇:误差椭圆与置信区间

一、作用:把"协方差矩阵"翻译成"用户看得懂的图"

上一篇我们讲了 EKF,它每时每刻都输出两个东西:

  • 状态估计 x^\hat{\mathbf{x}}x^:目标在哪里;
  • 协方差矩阵 P\mathbf{P}P:这个估计有多不确定。

但用户(指挥官、飞行员、分析师)不想看 4×4 的矩阵。他们想要的是:

"目标在这个椭圆里的概率是 95%。"

这就是误差椭圆(Error Ellipse) 的价值------把抽象的数字翻译成直观的图形。

误差椭圆有三种最常见的用途:

  1. 定位系统的精度报告:说"CEP₅₀ = 500 m"比说"协方差矩阵是 [..." 直观一万倍;
  2. 作战决策支持:椭圆形指示哪里最可能有目标,指挥官据此分配侦察/打击资源;
  3. 系统设计验证:椭圆大小直接反映 CRLB,可用来评估传感器布站是否合理。

本篇核心作用 :从协方差矩阵 P\mathbf{P}P 出发,推导置信椭圆 的参数(长轴、短轴、旋转角);解释 1σ vs 95% 的区别;引入 CEP₅₀(圆概率误差)------一个比椭圆更"用户友好"的指标;用 MATLAB 复现原书第9章的图9.1~9.4,画出漂亮的误差椭圆。

代码出处 :ch9_drawFigures(图9.1~9.4)、utils.drawErrorEllipse、utils.drawCEP50。


二、原理:数学上发生了什么?

2.1 从协方差矩阵到误差椭圆

假设位置估计 x^∈R2\hat{\mathbf{x}} \in \mathbb{R}^2x^∈R2 服从二维高斯分布:

x^∼N(xtrue,P)\hat{\mathbf{x}} \sim \mathcal{N}(\mathbf{x}_{true}, \mathbf{P})x^∼N(xtrue,P)

其中 P∈R2×2\mathbf{P} \in \mathbb{R}^{2 \times 2}P∈R2×2 是位置协方差矩阵:

P=σx2ρσxσyρσxσyσy2\mathbf{P} = \begin{bmatrix} \sigma_x^2 & \rho \sigma_x \sigma_y \\ \rho \sigma_x \sigma_y & \sigma_y^2 \end{bmatrix}P=σx2ρσxσyρσxσyσy2

误差椭圆 定义为等概率密度的等高线------即满足下式的点集:

(x−x^)TP−1(x−x^)=s2(\mathbf{x} - \hat{\mathbf{x}})^T \mathbf{P}^{-1} (\mathbf{x} - \hat{\mathbf{x}}) = s^2(x−x^)TP−1(x−x^)=s2

其中 sss 是缩放因子 ------控制椭圆的大小。这个二次型服从自由度为 2 的卡方分布:

(x−x^)TP−1(x−x^)∼χ22(\mathbf{x} - \hat{\mathbf{x}})^T \mathbf{P}^{-1} (\mathbf{x} - \hat{\mathbf{x}}) \sim \chi^2_2(x−x^)TP−1(x−x^)∼χ22

2.2 椭圆的三个参数

通过特征分解:

P=VΛVT,Λ=diag(λ1,λ2),λ1≥λ2\mathbf{P} = \mathbf{V} \mathbf{\Lambda} \mathbf{V}^T, \quad \mathbf{\Lambda} = \text{diag}(\lambda_1, \lambda_2), \quad \lambda_1 \geq \lambda_2P=VΛVT,Λ=diag(λ1,λ2),λ1≥λ2

椭圆的参数为:

参数 公式 含义
长半轴 a=sλ1a = s\sqrt{\lambda_1}a=sλ1 最大误差方向
短半轴 b=sλ2b = s\sqrt{\lambda_2}b=sλ2 最小误差方向
旋转角 θ=atan2(v1y,v1x)\theta = \text{atan2}(v_{1y}, v_{1x})θ=atan2(v1y,v1x) 长轴相对 x 轴的夹角

其中 v1=v1x,v1yT\mathbf{v}_1 = v_{1x}, v_{1y}^Tv1=v1x,v1yT 是 λ1\lambda_1λ1 对应的特征向量。

2.3 缩放因子 sss 与置信水平

核心问题 :sss 取多少才能让椭圆包含真实目标的概率是 95%?

答案来自卡方分布的分位数:

s2=χ2,p2s^2 = \chi^2_{2, p}s2=χ2,p2

其中 ppp 是置信水平。常用的几个值:

置信水平 s2s^2s2 sss 含义
39.4% 1.0 1.0 1σ 椭圆
86.5% 4.0 2.0 2σ 椭圆
95% 5.991 2.448 95% 椭圆
99% 9.210 3.035 99% 椭圆

关键 :1σ 椭圆不是 68% 置信椭圆(那是 1D 高斯的情况)。在二维中,1σ 只覆盖 39.4%------因为误差可以在两个方向同时出现。

2.4 CEP₅₀:圆概率误差

误差椭圆虽然信息完整,但用户常常想要一个数------比如"精度 500 m"。

CEP(Circular Error Probable,圆概率误差) 定义为:

以真实位置为圆心,50% 概率包含目标的最小圆的半径。

对于各向同性 (σx=σy\sigma_x = \sigma_yσx=σy,ρ=0\rho = 0ρ=0)的二维高斯分布,CEP 与 σ\sigmaσ 的关系为:

CEP=σ2ln⁡2≈1.1774σ\text{CEP} = \sigma \sqrt{2 \ln 2} \approx 1.1774 \sigmaCEP=σ2ln2 ≈1.1774σ

对于一般协方差矩阵,CEP 没有闭式解,需用数值积分或近似公式:

CEP50≈0.75λ1+λ2\text{CEP}_{50} \approx 0.75 \sqrt{\lambda_1 + \lambda_2}CEP50≈0.75λ1+λ2 (粗略近似)

CEP50≈1.1774λ1λ2\text{CEP}_{50} \approx 1.1774 \sqrt{\lambda_1 \lambda_2}CEP50≈1.1774λ1λ2 (各向同性时的精确值)

注意 :当椭圆很扁时(λ1≫λ2\lambda_1 \gg \lambda_2λ1≫λ2),上述近似会低估 CEP。精确值需要对椭圆做二维积分。

2.5 误差椭圆 vs CEP

特性 误差椭圆 CEP₅₀
信息量 完整(方向 + 大小 + 相关性) 单一数字
用户友好度 需要专业背景 直观
计算 特征分解,快 数值积分,慢
适用场景 技术报告、仿真图 作战简报、系统指标

实践建议 :技术文档给椭圆,作战简报给 CEP。


三、完整代码(可直接运行)

matlab 复制代码
%% ========================================================================
% 第22篇:误差椭圆与置信区间
% 参考出处:O'Donoughue, "Emitter Detection and Geolocation for EW",
%           ch9_drawFigures.m, Figures 9.1-9.4
%           https://github.com/nodonoughue/emitter-detection-book
% ========================================================================

clear; close all; clc;
rng(2024);

%% ==================== 图1:误差椭圆基础 ====================

fprintf('======= 误差椭圆基础 =======\n');

% 真实位置
x_true = [0; 1];
x_est  = [0.2; 0.2];

% 协方差矩阵
sigma_x2 = 5;
sigma_y2 = 3;
rho = 0.8;
sigma_xy = rho * sqrt(sigma_x2 * sigma_y2);
P = [sigma_x2, sigma_xy; sigma_xy, sigma_y2];

fprintf('真实位置: (%.2f, %.2f)\n', x_true);
fprintf('估计位置: (%.2f, %.2f)\n', x_est);
fprintf('协方差矩阵:\n'); disp(P);

% 特征分解
[V, D] = eig(P);
lambda = diag(D);
[lambda, idx] = sort(lambda, 'descend');
V = V(:, idx);

fprintf('特征值: lambda1 = %.4f, lambda2 = %.4f\n', lambda(1), lambda(2));
fprintf('特征向量: v1 = (%.4f, %.4f)\n', V(:,1));
fprintf('旋转角: %.2f°\n', rad2deg(atan2(V(2,1), V(1,1))));

% 绘制不同置信水平的椭圆
figure('Name','Fig1 Error Ellipse','Position',[80 80 900 700]);
hold on;

theta = linspace(0, 2*pi, 361);
conf_levels = [0.394, 0.865, 0.95, 0.99];
conf_labels = {'39.4% (1\sigma)', '86.5% (2\sigma)', '95%', '99%'};
colors = lines(numel(conf_levels));

for i = 1:numel(conf_levels)
    p = conf_levels(i);
    s = sqrt(chi2inv(p, 2));

    ellipse_xy = V * diag(sqrt(lambda)) * [cos(theta); sin(theta)];
    ellipse_xy = ellipse_xy + x_est;

    plot(ellipse_xy(1,:), ellipse_xy(2,:), 'Color', colors(i,:), ...
        'LineWidth', 2, 'DisplayName', conf_labels{i});
end

% 真实位置和估计位置
plot(x_true(1), x_true(2), 'kp', 'MarkerSize', 18, 'LineWidth', 2, ...
    'DisplayName', '真实位置');
plot(x_est(1), x_est(2), 'r+', 'MarkerSize', 18, 'LineWidth', 2, ...
    'DisplayName', '估计位置');

xlabel('x'); ylabel('y');
title('误差椭圆:不同置信水平');
legend('Location', 'northeast');
axis equal; grid on;
xlim([-6, 6]); ylim([-5, 5]);

%% ==================== 图2:旋转角可视化 ====================

fprintf('\n======= 旋转角可视化 =======\n');

figure('Name','Fig2 Ellipse Rotation','Position',[100 100 900 700]);
hold on;

% 1σ 椭圆
s1 = sqrt(chi2inv(0.394, 2));
ellipse_xy = V * diag(sqrt(lambda)) * [cos(theta); sin(theta)] * s1;
ellipse_xy = ellipse_xy + x_est;

plot(ellipse_xy(1,:), ellipse_xy(2,:), 'b-', 'LineWidth', 2.5, ...
    'DisplayName', '1\sigma 椭圆');

% 长轴和短轴
axis1 = V(:,1) * sqrt(lambda(1)) * s1;
axis2 = V(:,2) * sqrt(lambda(2)) * s1;

plot([x_est(1), x_est(1)+axis1(1)], [x_est(2), x_est(2)+axis1(2)], ...
    'r-', 'LineWidth', 2.5, 'DisplayName', '长轴');
plot([x_est(1), x_est(1)+axis2(1)], [x_est(2), x_est(2)+axis2(2)], ...
    'g-', 'LineWidth', 2.5, 'DisplayName', '短轴');
plot([x_est(1), x_est(1)-axis1(1)], [x_est(2), x_est(2)-axis1(2)], ...
    'r-', 'LineWidth', 2.5, 'HandleVisibility', 'off');
plot([x_est(1), x_est(1)-axis2(1)], [x_est(2), x_est(2)-axis2(2)], ...
    'g-', 'LineWidth', 2.5, 'HandleVisibility', 'off');

% 旋转角
theta_rot = atan2(V(2,1), V(1,1));
r_theta = 2;
plot([x_est(1), x_est(1)+r_theta], [x_est(2), x_est(2)], 'k--', ...
    'LineWidth', 1, 'DisplayName', 'x 轴参考');
arc_t = linspace(0, theta_rot, 50);
plot(x_est(1)+r_theta*0.5*cos(arc_t), x_est(2)+r_theta*0.5*sin(arc_t), ...
    'k-', 'LineWidth', 1.5, 'HandleVisibility', 'off');
text(x_est(1)+1.2, x_est(2)+0.4, sprintf('\\theta = %.1f°', ...
    rad2deg(theta_rot)), 'FontSize', 12);

plot(x_true(1), x_true(2), 'kp', 'MarkerSize', 18, 'LineWidth', 2, ...
    'DisplayName', '真实位置');
plot(x_est(1), x_est(2), 'r+', 'MarkerSize', 18, 'LineWidth', 2, ...
    'DisplayName', '估计位置');

xlabel('x'); ylabel('y');
title('误差椭圆:长轴、短轴与旋转角');
legend('Location', 'northeast');
axis equal; grid on;
xlim([-6, 6]); ylim([-5, 5]);

%% ==================== 图3:CEP50 与 50% 椭圆 ====================

fprintf('\n======= CEP50 演示 =======\n');

% 使用同一协方差矩阵
x_est_cep = [0.5; -0.2];

% 50% 椭圆
s50 = sqrt(chi2inv(0.5, 2));
ellipse_50 = V * diag(sqrt(lambda)) * [cos(theta); sin(theta)] * s50;
ellipse_50 = ellipse_50 + x_est_cep;

% CEP50 圆(近似)
cep50_approx = 1.1774 * sqrt(lambda(1)*lambda(2))^(0.5) * ...
               (lambda(1)/lambda(2))^0.1;   % 简化近似

% 更精确:数值计算
% 通过采样计算 50% 包含概率的圆半径
N_samples = 100000;
samples = mvnrnd(x_est_cep', P, N_samples)';
r_samples = sqrt(sum((samples - x_est_cep).^2, 1));
cep50 = prctile(r_samples, 50);

fprintf('50%% 椭圆缩放因子 s = %.4f\n', s50);
fprintf('CEP50(数值)= %.4f\n', cep50);

figure('Name','Fig3 CEP50','Position',[120 120 900 700]);
hold on;

% 画 50% 椭圆
plot(ellipse_50(1,:), ellipse_50(2,:), 'b-', 'LineWidth', 2.5, ...
    'DisplayName', '50% 椭圆');

% 画 CEP50 圆
theta_c = linspace(0, 2*pi, 361);
plot(x_est_cep(1)+cep50*cos(theta_c), x_est_cep(2)+cep50*sin(theta_c), ...
    'r--', 'LineWidth', 2.5, 'DisplayName', 'CEP_{50} 圆');

% 真实位置和估计
plot(x_true(1), x_true(2), 'kp', 'MarkerSize', 18, 'LineWidth', 2, ...
    'DisplayName', '真实位置');
plot(x_est_cep(1), x_est_cep(2), 'r+', 'MarkerSize', 18, 'LineWidth', 2, ...
    'DisplayName', '估计位置');

xlabel('x'); ylabel('y');
title('CEP_{50}:50% 圆概率误差 vs 50% 椭圆');
legend('Location', 'northeast');
axis equal; grid on;
xlim([-6, 6]); ylim([-5, 5]);

%% ==================== 图4:不同协方差矩阵的椭圆形状 ====================

fprintf('\n======= 不同协方差矩阵的椭圆形状 =======\n');

% 四种不同的协方差矩阵
P_set = {
    [5, 0; 0, 5], ...             % 各向同性
    [5, 0; 0, 1], ...             % 各向异性(无相关)
    [5, 3; 3, 3], ...             % 相关
    [5, -3; -3, 3]                % 负相关
};
label_set = {'各向同性', '各向异性', '正相关', '负相关'};

figure('Name','Fig4 Covariance Shapes','Position',[140 140 1200 400]);

for idx = 1:4
    subplot(1, 4, idx);
    hold on;

    P_i = P_set{idx};
    [V_i, D_i] = eig(P_i);
    lambda_i = diag(D_i);

    x_est_i = [0; 0];

    % 95% 椭圆
    s95 = sqrt(chi2inv(0.95, 2));
    ellipse_i = V_i * diag(sqrt(lambda_i)) * [cos(theta); sin(theta)] * s95;
    ellipse_i = ellipse_i + x_est_i;

    plot(ellipse_i(1,:), ellipse_i(2,:), 'b-', 'LineWidth', 2.5);

    % 长轴和短轴
    [~, imax] = max(lambda_i);
    [~, imin] = min(lambda_i);
    axis_long = V_i(:,imax) * sqrt(lambda_i(imax)) * s95;
    axis_short = V_i(:,imin) * sqrt(lambda_i(imin)) * s95;

    plot([0, axis_long(1)], [0, axis_long(2)], 'r-', 'LineWidth', 2);
    plot([0, -axis_long(1)], [0, -axis_long(2)], 'r-', 'LineWidth', 2);
    plot([0, axis_short(1)], [0, axis_short(2)], 'g-', 'LineWidth', 2);
    plot([0, -axis_short(1)], [0, -axis_short(2)], 'g-', 'LineWidth', 2);

    plot(0, 0, 'k+', 'MarkerSize', 15, 'LineWidth', 2);

    xlabel('x'); ylabel('y');
    title(label_set{idx});
    axis equal; grid on;
    xlim([-8, 8]); ylim([-8, 8]);
end

sgtitle('不同协方差矩阵的 95% 误差椭圆', ...
    'FontSize', 14, 'FontWeight', 'bold');

fprintf('\n各协方差矩阵的椭圆参数:\n');
for idx = 1:4
    P_i = P_set{idx};
    [~, D_i] = eig(P_i);
    lambda_i = sort(diag(D_i), 'descend');
    s95 = sqrt(chi2inv(0.95, 2));
    a = s95 * sqrt(lambda_i(1));
    b = s95 * sqrt(lambda_i(2));
    fprintf('  %-10s: a = %.2f, b = %.2f, 比值 = %.2f\n', ...
        label_set{idx}, a, b, a/b);
end

%% ==================== 图5:蒙特卡洛验证置信水平 ====================

fprintf('\n======= 蒙特卡洛验证 =======\n');

% 生成大量样本
N_samples = 10000;
x_est_mc = [0; 0];
P_mc = [5, 3; 3, 3];

samples_mc = mvnrnd(x_est_mc', P_mc, N_samples)';

% 计算每个样本的 Mahalanobis 距离平方
d2 = sum((samples_mc - x_est_mc) .* (P_mc \ (samples_mc - x_est_mc)), 1);

% 计算包含在椭圆内的比例
conf_levels = [0.394, 0.5, 0.865, 0.95, 0.99];
actual_levels = zeros(size(conf_levels));

for i = 1:numel(conf_levels)
    s2 = chi2inv(conf_levels(i), 2);
    actual_levels(i) = sum(d2 <= s2) / N_samples;
end

fprintf('\n置信水平验证:\n');
fprintf('%-12s %-15s %-15s\n', '理论', '实际', '误差');
fprintf('--------------------------------------\n');
for i = 1:numel(conf_levels)
    fprintf('%-12.1f%% %-15.2f%% %-15.2f%%\n', ...
        conf_levels(i)*100, actual_levels(i)*100, ...
        (actual_levels(i) - conf_levels(i))*100);
end

figure('Name','Fig5 Monte Carlo','Position',[160 160 900 700]);
hold on;

% 画椭圆
[V_mc, D_mc] = eig(P_mc);
lambda_mc = diag(D_mc);

for i = 1:numel(conf_levels)
    s_i = sqrt(chi2inv(conf_levels(i), 2));
    ellipse_i = V_mc * diag(sqrt(lambda_mc)) * [cos(theta); sin(theta)] * s_i;
    plot(ellipse_i(1,:), ellipse_i(2,:), 'LineWidth', 2, ...
        'DisplayName', sprintf('%.1f%%', conf_levels(i)*100));
end

% 随机画 500 个样本
idx_plot = randperm(N_samples, 500);
scatter(samples_mc(1, idx_plot), samples_mc(2, idx_plot), 15, ...
    'filled', 'MarkerFaceAlpha', 0.3, 'DisplayName', '样本点');

xlabel('x'); ylabel('y');
title('蒙特卡洛验证:椭圆覆盖比例符合理论值');
legend('Location', 'northeast');
axis equal; grid on;
xlim([-8, 8]); ylim([-8, 8]);

%% ==================== 图6:CEP50 随椭圆扁平度变化 ====================

fprintf('\n======= CEP50 vs 椭圆扁平度 =======\n');

% 扫描 lambda 比值
ratio_set = logspace(0, 2, 20);   % 1 到 100
sigma2_base = 1;

cep_vals = zeros(size(ratio_set));
cep_approx_vals = zeros(size(ratio_set));

for idx = 1:numel(ratio_set)
    r = ratio_set(idx);
    lambda1 = sigma2_base * r;
    lambda2 = sigma2_base;
    P_test = diag([lambda1, lambda2]);

    % 数值 CEP
    N_mc = 50000;
    samples_test = mvnrnd([0, 0], P_test, N_mc)';
    r_samples = sqrt(sum(samples_test.^2, 1));
    cep_vals(idx) = prctile(r_samples, 50);

    % 近似值
    cep_approx_vals(idx) = 1.1774 * sqrt(sqrt(lambda1 * lambda2));
end

figure('Name','Fig6 CEP vs Flatness','Position',[180 180 900 600]);
loglog(ratio_set, cep_vals, 'bo-', 'LineWidth', 2, 'MarkerSize', 8, ...
    'DisplayName', '数值 CEP_{50}');
hold on;
loglog(ratio_set, cep_approx_vals, 'r--', 'LineWidth', 2, ...
    'DisplayName', '近似 1.1774\sqrt{\lambda_1\lambda_2}');
xlabel('\lambda_1 / \lambda_2(椭圆扁平度)');
ylabel('CEP_{50}');
title('CEP_{50} 随椭圆扁平度的变化');
grid on; legend('Location', 'northwest');

fprintf('\n椭圆越扁,近似公式越不准\n');
fprintf('扁平度 %.1f 时:精确 %.4f, 近似 %.4f\n', ...
    ratio_set(end), cep_vals(end), cep_approx_vals(end));

fprintf('\n======= 全部完成 =======\n');

四、代码讲解:为什么这么写?

4.1 椭圆生成的"Cholesky 三步走"

matlab 复制代码
ellipse_xy = V * diag(sqrt(lambda)) * [cos(theta); sin(theta)];
ellipse_xy = ellipse_xy + x_est;

为什么这样生成椭圆?

  1. 单位圆 (cos⁡θ,sin⁡θ)(\cos\theta, \sin\theta)(cosθ,sinθ) 是最简单的参数化曲线;
  2. diag(λ)\text{diag}(\sqrt{\lambda})diag(λ ) 缩放:把单位圆按各方向的标准差拉伸;
  3. V\mathbf{V}V 旋转:把拉伸后的椭圆旋转到特征向量的方向;
  4. +xest+\mathbf{x}_{est}+xest 平移:把椭圆移到估计位置中心。

这与 Cholesky 分解等价 :P=LLT\mathbf{P} = \mathbf{L}\mathbf{L}^TP=LLT,L=VΛ\mathbf{L} = \mathbf{V}\sqrt{\mathbf{\Lambda}}L=VΛ 。用 chol(P, 'lower') 更简洁,但用特征分解更直观------你可以显式看到长轴、短轴、旋转角。

4.2 为什么 1σ 椭圆只覆盖 39.4%?

matlab 复制代码
conf_levels = [0.394, 0.865, 0.95, 0.99];

关键陷阱 :很多人以为"1σ 椭圆 = 68% 置信椭圆"------错! 68% 是一维 高斯的 1σ 覆盖概率。在二维中:

P(χ22≤1)=1−e−1/2=39.4%P(\chi^2_2 \leq 1) = 1 - e^{-1/2} = 39.4\%P(χ22≤1)=1−e−1/2=39.4%

为什么? 因为二维误差有两个自由度------x 方向和 y 方向。要让"两个方向同时落在 1σ 内",概率自然更低。

工程含义 :如果你用"1σ 椭圆"给用户报告,用户看到椭圆很小,可能误以为精度很高------但实际上只有 39.4% 的概率包含真实目标。报告精度时,一定要说清置信水平!

4.3 CEP 的精确计算:数值方法

matlab 复制代码
samples = mvnrnd(x_est_cep', P, N_samples)';
r_samples = sqrt(sum((samples - x_est_cep).^2, 1));
cep50 = prctile(r_samples, 50);

为什么不用公式? 对于一般协方差矩阵,CEP 没有闭式解。常用的近似:

CEP50≈1.1774λ1λ21/2\text{CEP}_{50} \approx 1.1774 \sqrt{\lambda_1 \lambda_2}^{1/2}CEP50≈1.1774λ1λ2 1/2

只在各向同性 (λ1=λ2\lambda_1 = \lambda_2λ1=λ2)时精确。当椭圆很扁时,误差很大。

代码用蒙特卡洛 :生成 10 万个样本,计算每个样本到中心的距离,取 50% 分位数------这是 CEP 的定义。

代价 :慢。10 万次采样约 0.1 秒。但图6显示,当椭圆扁平度 < 10 时,近似公式误差 < 5%;扁平度 > 10 时,误差迅速增大。

4.4 蒙特卡洛验证的重要性

matlab 复制代码
d2 = sum((samples_mc - x_est_mc) .* (P_mc \ (samples_mc - x_est_mc)), 1);
actual_levels(i) = sum(d2 <= s2) / N_samples;

这行代码验证了**"Mahalanobis 距离平方服从 χ22\chi^2_2χ22"**这个核心数学事实。

为什么这段验证重要? 因为工程中我们往往假设协方差矩阵正确,直接用公式画椭圆。但如果:

  • 传感器模型错了(如 AOA 噪声不是高斯);
  • 协方差矩阵估计有偏;
  • 观测之间存在相关性被忽略;

那么实际覆盖概率会与理论值严重偏离。

图5的散点图 让你亲眼看到椭圆真的包含了 39.4%、95% 等比例的样本------这是对理论最直观的验证。

4.5 椭圆扁平度对 CEP 的影响

图6展示了一个重要的工程现象:

  • 扁平度 = 1 (圆):1.1774λ1λ21.1774 \sqrt{\lambda_1 \lambda_2}1.1774λ1λ2 精确;
  • 扁平度 = 10(比较扁):近似值偏低约 5%;
  • 扁平度 = 100(极扁):近似值偏低约 50%。

物理直觉 :椭圆越扁,短轴方向精度极高,但长轴方向误差大 。圆的"50% 半径"主要由长轴 主导------但近似公式用几何平均,低估了长轴的贡献。

工程建议:

  • 如果椭圆扁平度 < 5,用近似公式即可;
  • 如果 > 5,必须用数值方法;
  • 或者直接报告椭圆,不报告 CEP。

五、运行结果解读

运行代码后,你将看到 6 张图:

图1:误差椭圆基础

四个同心椭圆(39.4%、86.5%、95%、99%)以估计位置为中心 。真实位置(黑五角星)落在 39.4% 椭圆之外、86.5% 椭圆之内------说明这次估计有中等误差。

图2:旋转角可视化

  • 蓝色:1σ 椭圆;
  • 红色:长轴(主误差方向);
  • 绿色:短轴(次误差方向);
  • 黑色虚线:x 轴参考;
  • 弧线 + 角度标注 :旋转角 θ\thetaθ。

图3:CEP₅₀

  • 蓝色:50% 椭圆;
  • 红色虚线:CEP₅₀ 圆。

可以看到,CEP 圆比 50% 椭圆稍大------因为椭圆是"最紧"的 50% 区域,圆必须放大才能包含同样的概率。

图4:不同协方差矩阵的椭圆形状

四张子图对比:

  • 各向同性:圆形;
  • 各向异性:沿 x 轴拉伸;
  • 正相关:椭圆向右上方倾斜;
  • 负相关:椭圆向右下方倾斜。

关键洞察 :椭圆的方向和扁平度完整地编码了协方差矩阵的所有信息。

图5:蒙特卡洛验证

500 个随机样本点叠加在椭圆上,可以看到:

  • 39.4% 椭圆内:约 200 个点;
  • 95% 椭圆内:约 475 个点;
  • 99% 椭圆内:约 495 个点。

验证了理论的正确性。

图6:CEP vs 椭圆扁平度

  • 扁平度 < 5:近似公式与数值结果几乎重合;
  • 扁平度 > 10:近似值开始明显偏低;
  • 扁平度 = 100:近似值只有精确值的约 1/2。

这提醒工程师 :不要在所有场景都套同一个 CEP 近似公式。


六、工程实战的四条准则

准则 数学依据 工程做法
1. 报告精度必须带置信水平 1σ 只覆盖 39.4% 写"95% 椭圆半径 500 m"而非"误差 500 m"
2. 椭圆优先,CEP 谨慎 椭圆无损信息,CEP 是近似 技术报告用椭圆,简报用 CEP
3. 扁平椭圆慎用近似公式 扁平度 > 5 时误差大 用蒙特卡洛或数值积分
4. 蒙特卡洛验证是必须的 实际系统噪声可能非高斯 至少在标定阶段做一次

七、延伸思考

7.1 三维误差椭球

在 3D 定位中,协方差矩阵是 3×33 \times 33×3,误差区域是椭球而不是椭圆。置信水平对应的卡方分布自由度是 3:

s2=χ3,p2s^2 = \chi^2_{3, p}s2=χ3,p2

  • 1σ 椭球覆盖 19.9%(三维比二维更低!);
  • 95% 椭球缩放因子 s=2.796s = 2.796s=2.796。

7.2 与 CRLB 的关系

如果估计算法达到了 CRLB,那么协方差矩阵 P=CCRLB\mathbf{P} = \mathbf{C}_{CRLB}P=CCRLB。误差椭圆的面积直接正比于 CRLB 的行列式:

Area=πs2det⁡(P)\text{Area} = \pi s^2 \sqrt{\det(\mathbf{P})}Area=πs2det(P)

这意味着:画误差椭圆等价于画 CRLB 的几何可视化。系统设计时,最小化椭圆面积就是最小化 CRLB。

7.3 与后续篇章的关系

本篇讲的是如何表示协方差 。第23篇我们将进入如何评估协方差的"好坏" ------几何精度因子(GDOP) 和 CEP₅₀ 的完整计算方法 。GDOP 是一个无量纲的数,它告诉你:"同样的测量精度,不同几何布站下的定位精度差多少倍"。这是传感器布站优化的核心工具。


下一篇预告(第23篇):几何精度因子(GDOP)与 CEP₅₀

传感器布站是定位系统的"先天条件"------布得好,事半功倍;布得差,再好的算法也救不回来。

几何精度因子(GDOP) 正是衡量"布站好坏"的标准指标。它定义为:

GDOP=trace(CCRLB)σmeas\text{GDOP} = \frac{\sqrt{\text{trace}(\mathbf{C}{CRLB})}}{\sigma{meas}}GDOP=σmeastrace(CCRLB)

GDOP 只依赖几何构型 ,与测量精度无关。GDOP 越小,几何构型越好。

我们将会:

  • 推导 AOA、TDOA、FDOA 三种模态下的 GDOP 公式;
  • 用 MATLAB 画出 GDOP 热力图------一眼看出哪片区域定位精度最差;
  • 实现 CEP₅₀ 的精确计算(二维积分);
  • 对比不同传感器布局的 GDOP 分布------方形 vs 圆形 vs 星形。

敬请期待!

相关推荐
老王爱玩车2 小时前
自定义类型:结构体
c语言·开发语言·学习
潼心1412o2 小时前
C++初阶(长期更新)第5讲:类和对象(中)
开发语言·c++
weixin_307779132 小时前
C++代码实现MATLAB中的normalize函数功能
开发语言·c++·算法·matlab
谢亮_vipxieliang2 小时前
Go WaitGroup与Once——并发同步的基石
开发语言·后端·golang
不会就选b2 小时前
算法日常・每日刷题--<动态规划>11
算法
(Charon)2 小时前
【C++面试】手写String类:同时实现拷贝构造与移动构造
c++·算法
程序员老陆2 小时前
通过std::unique_ptr初始化std::shared_ptr
开发语言·c++
liangshanbo12153 小时前
前端面试题:AI 对话中超长消息导致内存溢出,怎么解决?
java·开发语言·前端
迷途之人不知返3 小时前
算法系列6:模拟
算法