资讯动态

基于SVD的北斗接收机自主完好性监测(RAIM)实现

发布时间:2026/10/6 17:36:10 来源:尧图企业网站定制
最早做北斗接收机完好性算法时劝退我的不是卡尔曼滤波而是RAIM里那一大堆“看似简单却对不上号”的公式。后来我把定位解算流程整体梳理清楚又用奇异值分解把奇偶空间那一步重写了一遍整个逻辑才顺过来。这篇文章就相当于那段时间的复盘基于SVD的接收机自主完好性监测RAIM为什么值得学MATLAB源码怎么组织以及仿真和跑数据时最容易踩的坑。适合正在做北斗单点定位、伪距故障检测或者准备把完好性监测写进课设、论文的读者参考。1. 完好性监测到底在监测什么RAIM的检测逻辑与位置1.1 接收机自主完好性监测解决的问题RAIM全称Receiver Autonomous Integrity Monitoring接收机自主完好性监测它在导航系统里干的活很纯粹当某颗卫星的伪距测量出了毛病或者卫星星历悄悄偏了定位结果已经不可信的时候及时告诉用户“现在这个定位不能用于安全关键场景”。北斗接收机在城市峡谷、民航进近、无人机导航里使用如果解算出的位置偏差几十米甚至上百米而机器毫无察觉后果相当严重。RAIM不需要地面增强系统也不需要额外硬件它就靠接收机当前可见卫星的多余观测做自检。这句话怎么理解单点定位最少需要解4个未知数三维位置加接收机钟差实际上还要考虑对流层残差、电离层残差但线性化后核心是4个状态。如果天空中有7颗可用卫星那就多出来3个观测冗余RAIM利用这3个冗余去检测是否存在一颗卫星“说谎”。很多人第一次看RAIM会把它和定位精度混在一起。定位精度解决的是“定位结果准不准”RAIM解决的是“定位结果能不能在给定风险概率下被信任”。一个是性能指标一个是完好性指标完全不冲突。北斗系统本身有星基完好性增强的策略但接收机端做自主完好性监测反应更快、不依赖地面链路所以RAIM一直是接收机算法里的标配模块。1.2 卫星故障时的观测方程怎么变形观测方程是所有完好性算法的起点。伪距观测线性化之后写成y G·x ε这里y是“伪距残差向量”维度等于可见卫星数nx是4维状态增量包含东、北、天方向的定位误差和接收机钟差等效距离误差ε是测量噪声。G是几何矩阵也叫设计矩阵每行对应一颗卫星的观测方向形式是G [ -sin(az)·cos(el), -cos(az)·cos(el), sin(el), 1 ]其中az是卫星方位角el是仰角。这个矩阵很关键RAIM的所有统计量几乎都从它和观测残差y的组合里出来。如果某颗卫星j存在故障偏差b_j那么观测方程会变成y G·x b_j·e_j εe_j是第j个元素为1的单位向量。故障带来的影响有两层一是会直接污染位置解导致定位出现系统性偏差二是会在残差里留下痕迹。RAIM要做的就是从“被污染的解”和“含噪声的残差”里把异常揪出来。但这里有个麻烦位置解本身被G投影过故障信号和噪声混在一起直接看定位结果很难区分。所以RAIM选择换个角度看问题——不直接看位置域而是把观测向量投影到与几何矩阵正交的“奇偶空间”里。1.3 为什么选SVD而不是普通最小二乘残差传统教材里最常见的RAIM实现是最小二乘残差法Least Squares ResidualLSR检测统计量直接取后验残差平方和SSE。LSR的好处是直观代码也就十几行。但我在实际复现时很快发现LSR有几个让我头疼的问题。第一LSR要用 (GᵀG)⁻¹。当卫星几何分布差比如所有卫星都集中在一个方向时G的列接近线性相关(GᵀG)的条件数会变得非常大求逆的数值误差会直接污染后续的残差计算。我见过模拟数据里同一组观测用单精度和双精度跑LSR检测门限判断竟然出现完全相反的结论。第二LSR把“奇偶空间”这个概念藏在矩阵求逆背后初学者很难直观理解检测到底发生在哪个子空间。而SVD直接把G分解成GUΣVᵀU矩阵的前几列对应可观测子空间剩余列组成奇偶空间的单位正交基检测的几何意义一目了然。第三SVD还能顺带给出矩阵的奇异值。奇异值的大小直接揭示了观测几何的健康程度。最小奇异值趋近于0说明某个方向几乎不可观测这时候无论怎么提高精度位置解都靠不住。这个信息LSR给不了SVD免费送。所以我的结论是LSR适合写教材公式推导SVD更适合落到MATLAB源码里跑仿真、接真实数据、做数值稳定的工程实现。这也是这篇文章一直要强调SVD的原因。2. SVD如何把“有没有问题”变成一道线性代数判断题2.1 设计矩阵的SVD分解与子空间切割我们先看SVD做了什么。任意一个n×4的几何矩阵G都可以分解为G U·Σ·VᵀU是n×n正交矩阵V是4×4正交矩阵Σ是n×4的对角矩阵对角线上是奇异值σ₁≥σ₂≥σ₃≥σ₄。正交矩阵的性质是UᵀUI这意味着U的列向量构成n维空间的单位正交基。G的列空间也就是“观测能影响到的方向”是U前4列张成的子空间而U从第5列到最后那些列张成了与G的列空间正交的补空间这就是奇偶空间Parity Space。用数学术语写就是Q U(:, 5:n)Q是n×(n-4)矩阵满足性质Gᵀ·Q 0这个性质是RAIM的命根子。把观测向量y投影到Q上得到奇偶矢量pp Qᵀ·y Qᵀ·(G·x ε) Qᵀ·ε因为GᵀQ0故障和噪声里属于可观测子空间的分量全被过滤掉了只剩下和几何矩阵正交的“纯冗余分量”。位置状态x根本不影响p所以奇偶矢量天然排除了定位解的影响只反映测量异常和噪声。你可能会问这个Q和传统LSR里的残差投影矩阵R I - G(GᵀG)⁻¹Gᵀ有什么关系其实Q·Qᵀ R两者等价。SVD方式的优势是Q的列是单位正交的数值上更干净而且直观地告诉你奇偶空间的维度是n-4。2.2 检验统计量为什么是卡方分布得到奇偶矢量p之后RAIM检测统计量就定义为SSE pᵀ·p这个SSE就是残差平方和。假设测量噪声ε服从零均值正态分布标准差为σ那么在无故障情况下p的每个分量都是独立正态变量除以σ再平方求和SSE/σ²服从自由度为n-4的卡方分布。这里要特别强调自由度。很多人写成n-4就完事其实严谨地说自由度等于“可见卫星数减去待估状态数”。北斗定位里状态数是4所以自由度是n-4。如果因为几何秩亏导致可观测状态少于4自由度还要相应调整后面第五部分我会单独讲这个坑。有了分布就能定门限。给定误警概率Pfa检测门限T为T chi2inv(1 - Pfa, n-4)误警概率含义是无故障时误报“发现故障”的概率。航空领域对误警概率要求根据阶段不同从10⁻⁵到10⁻⁶不等民用算法一般取1e-5量级。如果实际计算出的SSE/σ²大于T就认为存在故障卫星。这个判断可以等价写成一个p值判断p chi2cdf(SSE/σ², n-4, upper)当p小于Pfa时报警。2.3 保护级把“检测能力”翻译成“可用性”检测到故障只是RAIM的一半另一半是回答这个问题即使没有检测到故障定位结果的误差上界是多少这个上界就是保护级。水平保护级HPLHorizontal Protection Level和垂直保护级VPL是完好性系统的核心输出。保护级要和告警限Alert Limit对比如果HPL小于水平告警限HAL说明当卫星故障发生时接收机有足够能力把它检测出来定位结果可被信任如果HPL大于HAL接收机必须发出“完好性不可用”的警告用户不能依赖这个定位做安全关键操作。保护级的推导从故障斜率开始。对第j颗卫星如果它产生一个偏差b这个偏差会给水平定位结果带来分量也会在奇偶空间里留下SSE增量。单位SSE增量对应的水平定位误差就是水平斜率slopeH_j sqrt(A(1,j)² A(2,j)²) / sqrt(S_jj)其中A pinv(G)是位置解算矩阵S I - G·pinv(G)是冗余矩阵S_jj是S第j个对角元素。直观理解这个比值表示“这颗卫星的故障能被观测到多少”。斜率越大说明该卫星的故障很难被残差反映出来却能很大地污染定位这类卫星是完好性最担心的。最坏情况下取所有可见卫星里最大的斜率再乘上漏检约束对应的最小可检测偏差b_min就得到HPL max(slopeH_j) × b_minb_min σ × sqrt(λ_min)这里λ_min是满足漏检概率PMD约束的非中心参数。给定门限T和自由度n-4求λ_min使得非中心卡方分布ncx2cdf(T, n-4, λ_min) PMD。PMD表示故障存在却没有被检测出来的概率航空上常取0.001左右。这个公式的物理意义是在规定的误警和漏检风险下最糟糕的那颗卫星如果发生故障最坏的水平定位误差不会超过HPL。HPL是人为构造的界不是真实误差但它能保证用户风险被限制在可接受范围内。VPL同理只看A矩阵第三行垂直方向的斜率计算VPL max(slopeV_j) × b_min。2.4 基于SVD的代码级计算路径把上述公式落到MATLAB时注意用SVD实现A矩阵A V × diag(1./σ) × U₁ᵀ这里U₁是U的前4列。这段形式其实就是伪逆pinv(G)但显式写出来能避免MATLAB内部对(GᵀG)⁻¹的隐式处理。S矩阵直接S eye(n) - G×A特征斜率用A和S对角元素算一行代码搞定。检测统计量更简单直接复用SVD的U矩阵后n-4列p Qᵀ × y这是源码里效率最高、最不容易出错的部分。3. MATLAB逐行拆解SVD-RAIM可复现实现3.1 函数骨架与输入参数设计我建议把SVD-RAIM封装成一个独立函数输入输出都明确方便嵌到自己的定位解算流程里。函数入参包括卫星方位角、仰角、线性化观测残差、误警概率、漏检概率、伪距噪声标准差和水平告警限。下面是完整可运行的函数代码function [flag, exclSat, HPL, VPL, stat] bds_svd_raim(az, el, y, Pfa, PMD, sigma, HAL) % bds_svd_raim - 基于奇异值分解的北斗RAIM演示实现 % 输入: % az : 可见卫星方位角, n×1 (deg) % el : 可见卫星仰角, n×1 (deg) % y : 线性化伪距残差, n×1 (m)等价于观测减去先验几何距离 % Pfa : 误警概率, 例如 1e-5 % PMD : 漏检概率, 例如 1e-3 % sigma : 等精度伪距观测标准差, m % HAL : 水平告警限, m % 输出: % flag : 是否检出故障, logical % exclSat: 建议排除的卫星编号, 0表示无需排除 % HPL : 水平保护级, m % VPL : 垂直保护级, m % stat : 结构体含统计量、门限等中间量 n numel(az); if n 4 error(可见卫星数必须大于4否则不存在冗余观测无法进行RAIM); end % 1. 构造ENU本地坐标系的几何矩阵 cosel cosd(el); G [-sind(az).*cosel, -cosd(az).*cosel, sind(el), ones(n,1)]; % 2. SVD分解提取奇偶空间基 [U, S, V] svd(G); r sum(diag(S) 1e-10); % 秩判断 Q U(:, r1:end); % 奇偶空间基 % 3. 检验统计量 p Q * y; % 奇偶矢量 SSE p * p; % 残差平方和 df n - r; % 自由度 stat.SSE SSE; stat.df df; % 4. 门限与检测 T chi2inv(1 - Pfa, df); flag (SSE / sigma^2) T; stat.T T; % 5. 故障排除逐个移除卫星找最小SSE的候选 SSE_k inf(n, 1); for k 1:n mask true(n,1); mask(k) false; Gk G(mask, :); [Uk, Sk, ~] svd(Gk); rk sum(diag(Sk) 1e-10); Qk Uk(:, rk1:end); SSE_k(k) sum((Qk * y(mask)).^2); end [~, best] min(SSE_k); exclSat 0; if flag (n - 1) 4 % 如果排除后统计量明显下降则认为best是故障卫星 if SSE_k(best) / sigma^2 T exclSat best; end end stat.SSE_k SSE_k; % 6. 用SVD显式构造伪逆计算保护级 A V * diag(1 ./ max(diag(S), 1e-12)) * U(:, 1:r); Smat eye(n) - G * A; slopeH sqrt(A(1,:).^2 A(2,:).^2) ./ sqrt(diag(Smat)); slopeV abs(A(3,:)) ./ sqrt(diag(Smat)); % 求解满足漏检率的非中心参数 fun (lam) ncx2cdf(T, df, lam) - PMD; lam_max 10; while fun(lam_max) 0 lam_max lam_max * 10; end lambda_min fzero(fun, [0 lam_max]); HPL max(slopeH) * sigma * sqrt(lambda_min); VPL max(slopeV) * sigma * sqrt(lambda_min); stat.slopeH slopeH; stat.slopeV slopeV; end这段代码有两点要注意。第一svd(G)默认返回完整SVDU是n×n矩阵所以QU(:,r1:end)取的就是奇偶空间基。如果你用svd(G,econ)当n4时U只有前4列奇偶空间就取不到了。我最初就栽在这个地方看着统计量始终是0排查半天才发现是经济型分解把后n-4列丢了。第二A矩阵里diag(1 ./ max(diag(S), 1e-12))是为了避免极小奇异值导致除零属于数值保护不是偷懒。3.2 单点定位主流程怎么调用RAIM上面函数接收的y必须是“线性化伪距残差”也就是做完卫星位置、接收机位置、钟差初值扣除之后的观测残差。在实际接收机解算流程里y不会凭空出现你得先做一遍迭代最小二乘单点定位。下面是一个主流程示例rng(42); az [35; 130; 210; 265; 310; 345; 20]; el [25; 42; 60; 75; 30; 55; 18]; n length(az); % 构造真实状态: 东、北、天方向误差 钟差等效距离 xTrue [5; -2; 3; 7]; % 生成几何矩阵 cosel cosd(el); G [-sind(az).*cosel, -cosd(az).*cosel, sind(el), ones(n,1)]; sigma 2.5; y G * xTrue sigma * randn(n, 1); % 手动向第4颗卫星注入10米故障 y(4) y(4) 10; % 调用SVD-RAIM [flag, exclSat, HPL, VPL, stat] bds_svd_raim(az, el, y, 1e-5, 1e-3, sigma, 40); fprintf(检验统计量 SSE/σ^2 %.2f\n, stat.SSE / sigma^2); fprintf(检测门限 T %.2f\n, stat.T); fprintf(是否检出故障: %d\n, flag); fprintf(建议排除卫星编号: %d\n, exclSat); fprintf(HPL %.2f m, HAL 40 m\n, HPL); fprintf(VPL %.2f m\n, VPL);跑一次这个脚本你的北斗RAIM就通了。注意我给第4颗卫星加了10米的故障这个偏差是真实噪声标准差的4倍理论上足够触发检测。排除逻辑会把每颗卫星剔除后的SSE都算一遍故障星对统计量的贡献最大剔除它之后SSE会明显回落到门限以下于是该星被标记出来。3.3 FDE循环多颗故障时的策略上面给了单故障排除的版本。如果环境比较复杂比如多径严重城区里同时出现两颗问题卫星单次排除可能不够。更完整的FDE故障检测与排除做法是计算全星座SSE如果超出门限进入排除逐一剔除候选星计算剩余星座SSE选SSE最低的候选星剔除对剩余星座重新计算SSE和门限如果仍超门限继续剔除重复直到SSE低于门限或剩余卫星数不大于4为止。多故障场景不能简单用“最小SSE”一票决定因为故障混杂会让最小SSE那组也不可信。标准做法是做“假设检测”组合若干卫星子集看哪个子集的SSE正常。这部分代码量会大好几倍但核心仍然是SVD求奇偶空间思路完全一致。对做课设和初步研究的场景单故障排除已经能说明问题。4. 仿真与结果判读从检测统计量到HPL可用性4.1 无故障时SSE的分布是否符合卡方我用上面脚本把故障注入那行去掉只保留7颗卫星随机噪声跑了好几组蒙特卡洛测试。结果SSE/σ²的值大多落在2到8之间而自由度n-43的标准卡方分布期望值正好是3这说明检验统计量的构造是合理的。不同随机种子下大约会有1%左右的情形统计量超过门限如果把Pfa设成1e-5门限大约在23这个量级实际误报率远小于1%。我建议读者拿到代码后先做这一步验证在无故障数据上确认误警率符合预期再往下做故障注入不然算法对结果的影响完全没法归因。4.2 单星故障检测和排除的典型表现注入10米故障后全星座SSE会剧烈上升。原因很好理解故障偏差被投影到奇偶空间其效果是给SSE叠加一个很大的非中心增量。排除逻辑中把真正的故障星剔除后剩余6颗星的SSE会回到正常水平而如果你误剔除一颗健康星剩余星座里还留着故障星的污染SSE仍然居高不下。所以SSE_k最低的候选星基本就是真正的故障星。值得注意的细节是故障偏差方向会影响检测灵敏度。如果故障偏差恰好与某列U的方向接近在奇偶空间的投影能量可能偏小。这也是为什么RAIM依赖几何多样性——卫星分布在多个方向任何一颗故障星的偏差都不可能同时与所有奇偶基正交。4.3 HPL与告警限的对比究竟意味着什么算例里如果HPL33米HAL40米结论是“水平完好性可用”。这个结论不是说定位误差一定小于33米而是说在给定的误警、漏检风险约束下最坏情况下位置误差的上界不会超过33米。真实定位误差可能只有几米但完好性必须按最坏情况来保障。我在读结果时有一条经验HPL的数值主要由两个因素驱动一是最大特征斜率的卫星二是卫星数决定的自由度。当可见卫星数从7颗降到6颗自由度变小检测门限和非中心参数都会变化HPL常常明显跳变。这种跳变在北斗星座动态变化时很常见尤其是高轨IGSO卫星进出地平线时。4.4 误警和漏警怎么从数据里区分误警是无故障却报警来源一般是噪声过大、模型误差、电离层残余、对流层残余。漏警是故障真实存在却漏报来源一般是故障星贡献在奇偶空间投影太小或者故障偏差还小于最小可检测偏差。仿真时可以通过扫描故障偏差幅度来看漏警率变化把故障偏差从1σ逐步加到的10σ统计每个幅度下的检测概率会得到一条类似“检测概率随偏差增大而上升”的S形曲线。曲线在偏差约等于sigma*sqrt(lambda_min)处开始快速上升这就是保护级公式里b_min的仿真验证。我很推荐把这个扫描图放进论文或报告里它比单点结果有说服力得多。5. 从仿真到真实数据数值与工程层面的避坑5.1 可见卫星数等于4的检测盲区这是初学者最容易忽略的边界条件。当可见卫星数只有4颗时n-40奇偶空间维度为0SSE恒等于0RAIM完全不工作。换句话说恰好满足定位所需卫星数时接收机没有任何冗余来检验测量质量。实际工程上北斗RAIM至少需要5颗卫星才能做单故障检测想隔离故障则一般建议6颗以上。源码里入口判断直接报错就是这个原因。5.2 自由度到底是n-4还是n-rank(G)我们在2.2节简单提过这里展开说。正常几何下G是列满秩rank4自由度n-4没问题。但北斗星座里GEO卫星仰角固定、位置相对地面几乎静止如果多颗GEO加上接近的导航卫星G可能出现病态甚至秩亏。当rank小于4时能独立估计的状态数减少自由度实际是n-rank(G)不是n-4。代码里用diag(S)1e-10判断秩再存到df变量就是为了自动适应这种情况。测试这个边界条件的方法构造两颗方位角完全相同的卫星把G的其中两行设成几乎一样运行代码看自由度变化。你会看到奇异值从正常的几十降到接近0自由度减少1HPL也相应改变。能复现这个现象就说明你对SVD的理解到位了。5.3 加权观测才是真实场景高仰角不能和低仰角同权我前面的教学代码用了等精度sigma方便讲核心逻辑。真实北斗伪距观测低仰角卫星穿过大气路径长电离层、对流层延迟残差大噪声明显更高。工程实现里建议按仰角建模sigma_i 0.3 3.0 * exp(-el / 10);这只是一个经验型选择具体参数和接收机跟踪环路带宽相关。加权时构造权重矩阵W diag(1 ./ sigma_i.^2); Gw sqrt(W) * G; yw sqrt(W) * y;然后把Gw、yw传给RAIM函数。注意所有统计量和门限都要在加权域里计算HPL公式里的sigma也要换成统一的参考sigma0。加权后的好处是低仰角卫星不会被异常噪声轻易误判成故障坏处是低仰角卫星的权重降低后它对斜率的贡献也变小保护级可能变差。这两者需要权衡。5.4 SVD数值稳定性与奇异值数量级跨越SVD的数值稳定性很好但要注意的是MATLAB里svd函数对输入的缩放很敏感。假设你的y单位是米G的元素大约在10⁻³到1之间奇异值最小的可能只有10⁻⁶。代码里max(diag(S),1e-12)这个下限其实只是兜底更理性做法是先看奇异值分布的降幅。如果最小奇异值和最大奇异值差超过1e4这个星座几何已经非常危险位置解的方差会巨大此时HPL大概率超过告警限算法会自动输出“不可用”这本身就是RAIM的正确行为。5.5 动态星座下的故障隔离与卫星重新进场实际接收机在行驶或飞行时卫星会不断进出视野。隔离一颗故障星后过几分钟它可能又回到低仰角视野此时必须重新做RAIM判断。FDE状态机要维护一张“故障星黑名单”在后续历元里检查黑名单卫星是否还在奇偶空间里有显著贡献而不是无脑把它一直排除。如果星座变化导致剩余卫星少于5颗RAIM会自动退化这时候安全策略是停止输出完好性告警。这些状态管理代码不复杂但特别容易漏我自己的经验是先写好单历元RAIM再套一层历元状态机别把状态逻辑和检测逻辑混在一个函数里。6. 从模拟星座切换到真实北斗数据流程与扩展方向6.1 真实观测数据的接入顺序模拟数据验证过核心函数后换真实北斗数据时整个链路的顺序应该是读RINEX观测文件得到每颗可见卫星的伪距、载波相位、多普勒读广播星历计算卫星位置用接收机概略位置和卫星位置计算每颗星的方位角、仰角、几何距离做迭代最小二乘定位得到接收机位置和钟差最后一次迭代时保留线性化残差y和几何矩阵G把az, el, y直接喂给bds_svd_raim函数根据HPL与告警限判断当前历元的完好性状态。这里最容易错的一步是第5步。很多人拿起RAIM就开始跑却没留意y得是“最后迭代”的伪距残差而不是初始伪距。如果用初始伪距直接检测里面的定位误差和钟差误差全会变成“伪故障”误警率会高得离谱。我在代码注释里反复强调y的语义就是这个原因。6.2 北斗多星座融合时的G矩阵扩展北斗用B1I、B3I信号GPS用L1/L5GLONASS用G1/G2。如果接收机做多系统融合定位状态量会变成4系统钟差数乘1每增加一个系统就多一个钟差未知数。几何矩阵G的列不再只有4列而是包含每个系统的一个钟差列。这个变化直接影响了SVD维度奇偶空间维度变为n - (3 N_sys)其中N_sys是系统钟差数量。做GPS北斗双系统时状态数是5至少需要6颗星才能启动RAIM。很多论文里的“基于SVD的多星座RAIM”就是在这个方向扩展核心代码基本不用改只要动态把G的列数传到函数里就行。6.3 向ARAIM延伸的空间这篇文章覆盖的RAIM属于经典接收机自主完好性监测。民航下一代完好性方案是ARAIM先进接收机自主完好性监测它利用双频观测消除电离层误差同时利用地面完好性支持信息IS M对卫星故障概率建模把RAIM从“检测北斗卫星突发故障”扩展为“同时监控卫星轨道、钟差、信号畸变等完整误差包络”。SVD在ARAIM里的角色依然重要只是奇偶空间换成增强版观测模型保护级公式增加了先验故障概率加权。想继续深入的话我建议按“单星故障→多星故障→加权RAIM→ARAIM”这条路径走。每前进一步都在前面代码基础上加模块不要推倒重来。最后分享一个我自己的习惯调试RAIM时永远先把“检测统计量是否超过门限”和“位置解是否偏差过大”分开画图。前者是完好性后者是精度两者经常不同步。只有把这两个概念在数据上彻底分清楚你才算真正理解RAIM。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑