简介:一套基于空时阵列最佳旋转角度的卫星导航抗干扰信号处理MATLAB仿真代码,面向卫星导航抗干扰算法研究者与高年级工科学生,聚焦MVDR算法在复杂电磁环境下的性能优化。方案在MVDR(最小方差无失真响应)算法基础上引入旋转角度优化,改善经典MVDR对干扰源估计过于理想化、对噪声功率敏感等局限,比常规空时处理更适应多径和人为干扰并存的场景。压缩包共7个文件,包含6个.m脚本和1个txt说明文档,脚本涵盖方向向量生成、相关系数计算、参数扫描及多测试用例仿真等模块,整体仅8KB,结构简明、易读易改。核心仿真覆盖数据采集、干扰估计、旋转角计算、MVDR滤波与性能评估全流程,可辅助复现不同频点、不同角度间隔下的抗干扰效果,并支持替换信号模型与干扰场景后自行验证。该代码已在开放社区获得347人学习浏览,适合需要快速实现并对比改进算法性能的工程实践者。
1. 卫星导航抗干扰里,MVDR最容易栽在“角度失配”上
做卫星导航抗干扰仿真时,MVDR 是大多数人第一个想到的算法,但真正把它搬到空时阵列上跑一遍,翻车往往不在干扰多强,而在卫星信号的来向估计差了那么零点几度。GNSS 信号本来就比噪声低 20 dB 左右,MVDR 的约束条件一旦没对准真实来向,波束形成器会把弱信号当成干扰一起抑制掉,输出信干噪比直接掉到不可用。标题里说的“基于空时阵列最佳旋转角度的卫星导航抗干扰信号处理仿真代码”,本质就是在 MVDR 权重计算之前,增加一个导向矢量旋转角度搜索环节:在标称来向附近扫一圈,找到一个让输出信干噪比最大的角度,再用这个修正后的导向矢量重新算权重。这个思路对做抗干扰算法验证、毕业设计仿真和接收机前端预研都很有用,尤其适合在 MATLAB 里快速搭一套可复现的空时抗干扰链路。
2. 把空时阵列和 MVDR 约束模型先立住:从数据模型到权重推导
要理解“最佳旋转角度”改进在干什么,先得把空时阵列的数据模型和 MVDR 的约束优化模型对齐。很多人直接抄公式算权重,最后方向图却对不上,问题基本都出在空时导向矢量的排列顺序上。
2.1 空时增广快拍:M 个阵元 × P 个延迟抽头
空时阵列和纯空域阵列的区别在于,每个阵元后面多接了一串时间延迟抽头。假设均匀线阵有 M 个阵元,每个阵元后面接 P 个抽头,那么某个采样时刻 t 的空时快拍向量是一个 MP×1 的列向量,按“阵元优先”的顺序排列:
x(t) = [x1(t), x2(t), ..., xM(t), x1(t-Ts), x2(t-Ts), ..., xM(t-Ts), ..., x1(t-(P-1)Ts), ..., xM(t-(P-1)Ts)]^T
其中 Ts 是抽头延迟间隔,通常取采样周期。这样一个快拍同时保留了空间维度和时间维度的信息。窄带干扰在空间上表现为一个固定相位差,宽带干扰则会在时间维上分散成多阶延迟分量,所以只靠 M 个阵元不够,必须加上时间自由度才能抑制宽带压制干扰。
对应的空时导向矢量写成 Kronecker 积形式:
s(theta, fd) = b(fd) ⊗ a(theta)
其中 a(theta) 是空间导向矢量,b(fd) 是时间导向矢量。对均匀线阵,a(theta) 的第 m 个元素是 exp(jπ(m-1)cos(theta)),b(fd) 的第 p 个元素是 exp(j2πfd(p-1)/fs)。注意这里 ⊗ 的左右顺序必须和快拍向量里“阵元优先”的排列顺序一致,否则后面算出来的权向量方向图是错的。
2.2 MVDR 权重推导:响应约束为 1、输出功率最小化
MVDR 的目标是在期望信号方向响应恒为 1 的约束下,最小化输出总功率。写成优化问题就是:
min_w w^H R w s.t. w^H s(theta_s, fd_s) = 1
其中 R 是接收数据的协方差矩阵,s(theta_s, fd_s) 是期望信号的空时导向矢量。这个问题的闭式解是:
w = R^{-1} s / (s^H R^{-1} s)
在 MATLAB 里,工程上一般不直接写成 inv(R)s,而是用左除算子求解线性方程组,数值上更稳一点。实际实现时,协方差矩阵 R 是用 N 个快拍估计出来的样本协方差矩阵 R_hat = XX'/N,这种做法的经典名字是 SMI,即采样矩阵求逆。
这里有一个必须提前说的点:MVDR 的自适应自由度很高,当快拍数不够或者干扰来向和期望信号比较接近时,样本协方差矩阵的病态问题会非常突出。常见做法是对 R_hat 做对角加载,也就是在 R_hat 上加一个小的单位阵缩放项,保证矩阵满秩,代价是零陷深度会略微变浅。
2.3 最佳旋转角度的引入:把点约束变成区间搜索
传统 MVDR 假设期望信号来向完全已知,约束条件是一个“点约束”。但真实卫星导航场景里,接收机天线相位中心误差、载体姿态变化、多径效应都会让标称来向和真实来向之间出现偏差。一旦偏差存在,w^H s(theta_s) = 1 这个约束实际上并没有让真实信号无失真通过,MVDR 会把信号当成残余干扰压掉。
改进的思路是:不再死盯标称角度,而是在标称角度附近一个小区间内搜索,把“点约束”放宽成“区间内选优”。具体说,就是遍历若干个候选旋转角度 theta_c,对每个角度都计算一次 MVDR 权向量,然后用仿真中已知的信号协方差和干扰加噪声协方差评估输出 SINR,选择 SINR 最大的那个角度作为最佳旋转角。这个角度往往接近真实来向而非标称来向,能显著缓解导向矢量失配造成的信号自消。
3. 用 MATLAB 把改进算法跑起来:仿真场景、常规 MVDR 与旋转角搜索
这一章直接给可复现的 MATLAB 仿真流程。我按“先生成仿真数据,再算常规 MVDR,最后加旋转角搜索”的顺序拆成三步,每一步都给出代码和参数说明。
3.1 场景生成:GNSS 信号、干扰与噪声的仿真数据
仿真场景设置成一个 8 阵元均匀线阵,阵元间距取 L1 载波半波长,采样率 10 MHz。卫星信号的真实来向故意设成 10.8 度,但接收机标称来向写的是 10 度,用来模拟角度失配。干扰用两个窄带压制干扰,来向分别是 -30 度和 40 度。
% st_gnss_sim.m —— 空时阵列抗干扰仿真:常规MVDR与旋转角度改进版 M = 8; % 阵元数 P = 5; % 时域抽头数 N = 1000; % 快拍数 fs = 10e6; % 抽头采样率 10 MHz lambda = 0.19; % GPS L1 波长约 0.19 m d = lambda / 2; % 阵元间距 theta_nominal = 10; % 接收机标称来向,单位度 theta_true = 10.8; % 真实来向,存在 0.8 度失配 theta_j = [-30, 40]; % 干扰来向 SNR_dB = -20; % 卫星信号信噪比,典型弱信号 INR_dB = [40, 35]; % 两个干扰的干噪比 % 空时导向矢量函数:b(fd) kron a(theta) a_theta = @(theta) exp(1j*pi*(0:M-1).' * cosd(theta)); b_fd = @(fd) exp(1j*2*pi*fd*(0:P-1).'/fs); s_st = @(theta, fd) kron(b_fd(fd), a_theta(theta)); % 生成原始阵列采样,时长 N+P-1 个采样点 fd_s = 1000; % 卫星多普勒 1 kHz sig = 10^(SNR_dB/20) * (randn(1,N)+1j*randn(1,N))/sqrt(2); samples = zeros(M, N+P-1); for nn = 1:N+P-1 r = (randn(M,1) + 1j*randn(M,1))/sqrt(2); % 基底热噪声 if nn <= N r = r + a_theta(theta_true) * sig(nn); % 真实卫星信号 end for k = 1:length(theta_j) jamp = 10^(INR_dB(k)/20) * (randn+1j*randn)/sqrt(2); r = r + a_theta(theta_j(k)) * jamp; % 窄带干扰 end samples(:, nn) = r; end % 把原始采样构造成 MP x N 的空时快拍矩阵 X X = zeros(M*P, N); for t = 1:N for p = 0:P-1 X((p*M+1):((p+1)*M), t) = samples(:, t+P-1-p); end end这段代码里最关键的是最后那个双重循环。X 的每一列对应一个空时快拍,前 M 行是当前时刻各阵元采样,接下来 M 行是延迟一个采样周期后的采样,依次类推。行排列顺序必须和后面 s_st 函数里 kron(b_fd, a_theta) 的分块顺序保持一致,否则仿真结果全乱。
参数说明:M=8、P=5 意味着空时自由度为 40,协方差矩阵是 40×40,需要至少 80~100 个快拍才能稳定估计。N=1000 对这个维度来说足够充裕。SNR_dB=-20 是故意设置的,模拟 GNSS 信号淹没在噪声里的真实场景;INR_dB 设为 40 和 35,保证干扰远超噪声,否则抗干扰效果看不出来。
3.2 常规 MVDR 实现:样本协方差矩阵与 SMI 求权
拿到空时快拍矩阵 X 之后,第一步是估计协方差矩阵,然后加对角加载,最后用左除算子求权向量。这一段对应原版 MVDR 基线,后面所有对比都拿它做参照。
% 协方差矩阵估计与对角加载 R_hat = (X * X') / N; % MP x MP 样本协方差 reg_coef = 1e-3; % 对角加载系数 R_use = R_hat + reg_coef * trace(R_hat) / (M*P) * eye(M*P); % 常规 MVDR 权向量:用标称来向构造约束 s_nominal = s_st(theta_nominal, fd_s); w_mvdr = (R_use \ s_nominal) / (s_nominal' * (R_use \ s_nominal)); % 仿真评估用:已知信号协方差 Rs,干扰加噪声协方差用 R_hat 近似减信号分量 s_true = s_st(theta_true, fd_s); Rs = 10^(SNR_dB/10) * (s_true * s_true'); Rin = R_hat - Rs; SINR_mvdr = 10*log10(real(w_mvdr'*Rs*w_mvdr / (w_mvdr'*Rin*w_mvdr))); fprintf('常规 MVDR 输出 SINR = %.2f dB\n', SINR_mvdr);这里有两个细节值得说明。第一,R_use 不是直接用 R_hat,而是加了一个对角加载项,加载量是 trace(R_hat)/(M*P) 的千分之一。这个量级既能抑制矩阵病态,又不会把自适应零陷抹平太多。第二,求权向量用了两次左除,没有再算 inv(R_use),避免显式求逆引入的数值误差。
SINR 评估这里用了仿真里的“上帝视角”:信号协方差直接用真实来向和真实功率构造,干扰加噪声协方差用 R_hat 减去信号分量近似。这个方法只能在仿真里用,实测阶段没有这么干净的信号分量,但作为算法对比基线是够用的。要注意的是 Rin 可能出现非正定,所以评估时用 real 取实部,并且不要对负数开 log。
3.3 改进 MVDR 实现:旋转角搜索与导向矢量修正
改进算法的核心就一段角度扫描。围绕标称来向 ±5 度,每隔 0.1 度取一个候选角度,每个候选角都重新构造导向矢量、重新求 MVDR 权向量,最后统计哪个角度下输出 SINR 最高。
% 旋转角度搜索:在标称来向附近 ±5 度扫描 theta_range = theta_nominal - 5 : 0.1 : theta_nominal + 5; SINR_scan = zeros(size(theta_range)); for k = 1:length(theta_range) s_cand = s_st(theta_range(k), fd_s); w_cand = (R_use \ s_cand) / (s_cand' * (R_use \ s_cand)); SINR_scan(k) = 10*log10(real(w_cand'*Rs*w_cand / ... (w_cand'*Rin*w_cand))); end % 取 SINR 最大的角度作为最佳旋转角,重新计算最终权向量 [best_SINR, idx] = max(SINR_scan); theta_best = theta_range(idx); s_opt = s_st(theta_best, fd_s); w_opt = (R_use \ s_opt) / (s_opt' * (R_use \ s_opt)); fprintf('最佳旋转角 = %.1f 度\n', theta_best); fprintf('改进 MVDR 输出 SINR = %.2f dB\n', best_SINR);这段代码逻辑不复杂,但计算量比常规 MVDR 大了几百倍,因为每个候选角度都要解一次 40 维线性方程组。实际仿真里我一般先以 0.5 度步长粗扫,锁定峰值区间后再用 0.1 度细扫,能把计算时间压缩一大截。搜索范围 ±5 度是经验值,角度失配超过 5 度的情况在固定接收机场景里很少见,如果做高动态载体仿真,可以把范围放宽到 ±10 度,同时加大扫描步长。
最终输出的 theta_best 如果是 10.8 度附近,说明改进算法确实把角度失配找回来了。如果扫出来还是标称角 10 度,那说明当前干扰场景下角度失配没有造成明显的信号自消,MVDR 基线本来就够用。
4. 仿真结果怎么看:零陷深度、SINR 曲线与参数选择
算法代码跑通之后,不能只看一个 SINR 数字就完事。我一般会从三个角度验证改进是否真的有意义:方向图零陷形态、SINR 随旋转角的变化曲线、以及不同参数组合下的性能趋势。
4.1 方向图对比:改进算法在干扰方向上的零陷差异
空时阵列的方向图定义为 w^H 与扫描导向矢量的内积模值。由于仿真里窄带干扰的时间导向矢量基本只和频率有关,而这里统一看零频参考,所以可以直接对角度扫描来画方向图。
% 对比常规 MVDR 与改进算法在角度维的方向图 angles = -90:0.1:90; F_mvdr = zeros(size(angles)); F_opt = zeros(size(angles)); for k = 1:length(angles) s_scan = s_st(angles(k), 0); % 以零多普勒扫描 F_mvdr(k) = 20*log10(abs(w_mvdr' * s_scan) + eps); F_opt(k) = 20*log10(abs(w_opt' * s_scan) + eps); end figure; plot(angles, F_mvdr, '--', angles, F_opt, '-', 'LineWidth', 1.5); xlabel('来向角 / deg'); ylabel('阵列增益 / dB'); legend('常规 MVDR', '改进 MVDR'); grid on; xlim([-90 90]);从方向图上最容易看到两个现象。第一,两种算法在 -30 度和 40 度干扰方向都会形成零陷,但改进算法的零陷位置更准、深度更深,因为它的导向矢量约束用了更接近真实来向的角度。第二,期望信号方向也就是 10.8 度附近,常规 MVDR 可能出现一个轻微的凹陷,而改进算法在这个方向保持接近 0 dB 的增益。
空时方向图还有一个容易被忽略的点:时间抽头引入了频率选择性,方向图会随频率变化。对宽带干扰来说,只画一个角度维方向图不够,还需要画角度-频率二维响应,但那是进阶验证的事,这里先用角度维方向图判断零陷是否正常。
4.2 输出 SINR 随旋转角变化:最佳角是搜出来的
旋转角搜索得到的 SINR_scan 曲线本身就很有价值。把 theta_range 作为横轴、SINR_scan 作为纵轴,能看到一个明显的峰值,峰值位置就是最佳旋转角。如果曲线在标称角附近是一条平线,说明角度失配在这个场景里没有造成性能损失,改进算法是“白改进”的。
SINR 曲线的峰值宽度也能反映系统的鲁棒性。峰值越尖锐,说明系统对角度误差越敏感,这时候改进算法的价值越大;峰值很平坦,说明 MVDR 本身对这个场景不太挑角度,搜索更多是锦上添花。实际仿真中我遇到过峰值出现在偏离真实角 0.2 度位置的情况,原因是样本协方差矩阵有估计误差,搜索曲线本身也有起伏,所以不要指望每一次都精确命中真实角,接近真实角即可。
4.3 阵元数、抽头数、快拍数怎么配:一组经验参数表
做参数整定时,我常用的经验值如下表。这个表是基于窄带干扰为主、宽带干扰不超过 20 MHz 的场景,参数之间是联动的,不能只看单个值。
| 参数 | 推荐范围 | 说明 |
|---|---|---|
| M(阵元数) | 4~16 | 决定空间自由度,零陷数量上限约为 M-1 |
| P(抽头数) | 1~5 | 窄带干扰 P=1 就够,宽带干扰建议 P=3~5,再大收益降低 |
| N(快拍数) | ≥ 2MP | 快拍数低于 2MP 时协方差矩阵容易病态 |
| 对角加载系数 | 1e-4 ~ 1e-2 | 太小数值不稳,太大会让零陷深度掉 5 dB 以上 |
| 旋转角搜索范围 | ±5 度 | 固定场景够用,高动态场景放宽到 ±10 度 |
| 旋转角搜索步长 | 0.1~0.5 度 | 先粗扫后细扫,直接 0.01 度只会增加耗时 |
M 和 P 的乘积决定了空时自由度的总量。比如 M=8、P=5 就是 40 个自由度,能同时抑制的干扰数量远多于纯空域的 8 自由度,但代价是协方差矩阵维度从 8×8 涨到 40×40,快拍数和计算量都跟着涨。如果你的干扰全是窄带,P 设 1 就够,不需要盲目堆时间抽头。
5. 空时抗干扰仿真里绕不开的四个坑:现象、原因、对策
这一章写我在调这套仿真时实际遇到的四个典型问题。每个都是“现象→原因→解决”的结构,比算法本身更值得存下来。
5.1 协方差矩阵求逆发散:快拍数不够时矩阵是奇异的
现象:运行常规 MVDR 时,w_mvdr 里出现 NaN 或 Inf,方向图变成一堆毛刺。
原因:空时快拍向量维度是 M*P,如果快拍数 N 小于这个维度,R_hat 的秩最多只有 N,矩阵不满秩,求逆没有稳定解。例如 M=8、P=5 时维度是 40,N 只给 30 个快拍,R_hat 的秩只有 30,必然出问题。
解决:把快拍数提到 2 倍自由度以上;同时给 R_hat 做对角加载。加载量可以从 trace(R_hat)/(M*P) 的 1e-3 开始调,如果矩阵还是病态,提高到 1e-2。另外求权时用左除而不是 inv,能减少一部分数值问题。
5.2 期望信号被当成干扰抑制:角度失配的典型翻车现象
现象:方向图在干扰方向确实有零陷,但期望信号方向也凹下去一块,输出 SINR 反而比不做抗干扰还低。
原因:标称导向矢量和真实来向偏差过大,MVDR 为了保证输出功率最小,把真实信号理解成了残留干扰的一部分。信号越弱越容易被牺牲,因为它的功率在总输出里占比太小,MVDR 优化器不会在乎损失这点功率。
解决:用旋转角搜索把约束方向修正到真实来向附近。如果搜索范围设得不够,比如失配了 2 度但扫描范围只有 ±1 度,效果会打折扣。更稳妥的做法是把搜索范围和实际载体运动状态挂钩,动态场景下宁可扫描范围大一点,用粗步长换覆盖。
5.3 旋转角搜索步长太密:性能没提升,计算量翻倍
现象:把搜索步长从 0.1 度改成 0.01 度后,最佳角度只变了 0.02 度,SINR 提升了不到 0.1 dB,但仿真时间多了 10 倍。
原因:样本协方差矩阵的估计误差本身就有限制,角度搜索分辨率做到比协方差矩阵能分辨的角度还要细,属于过度拟合。0.01 度的角度分辨率远高于 40 维协方差矩阵在有限快拍下能达到的角度分辨能力。
解决:先 0.5 度粗扫找峰值区间,再 0.1 度细扫精确定位。如果细扫之后 SINR 起伏仍然很大,说明快拍数不够,应该增加 N 而不是加密角度步长。另外可以对 R_use 做一次 Cholesky 分解或者特征分解,候选角度复用同一个分解结果来加速求权。
5.4 宽带干扰零陷变浅:抽头数没跟上干扰带宽
现象:方向图在宽带干扰方向上只有 10 dB 左右的抑制,而窄带干扰方向能压到 -40 dB,干扰残余仍然压不住。
原因:窄带干扰在空间维就能被一个零陷覆盖,但宽带干扰的能量在频率上展宽,单一频率方向图无法代表整个干扰带宽。P 太小的时候,时间自由度不足以模拟干扰信号的延迟相关结构。
解决:把 P 从 1 增大到 3~5,重新估计协方差矩阵。仿真时干扰源如果用白噪声通过滤波器生成,带宽越宽需要的抽头数越多。判断 P 是否够用,可以看干扰带宽和采样率的关系,通常要求 P 乘以采样周期覆盖干扰信号的主要相关时间。P 加大后记得同步增加 N,否则协方差矩阵又会病态。
6. 最后一步:跑角度扫描、做蒙特卡洛,验证改进算法的稳健性
单次仿真里最佳旋转角找得准,不代表算法在实际运行中一定可靠。我最后习惯做一件事:把角度失配设成随机量,跑 200 次蒙特卡洛,统计常规 MVDR 和改进算法的输出 SINR 均值与方差。
具体做法是在每次蒙特卡洛里随机生成一个失配角,范围比如 ±1 度,信号真实来向跟着失配角变化,但接收机标称来向始终固定。每次迭代重新生成数据、重新做旋转角搜索、记录两个算法的输出 SINR。最后对比两个 SINR 数组的均值和标准差。改进算法应该表现出两个特征:一是平均 SINR 明显高于常规 MVDR,二是 SINR 的波动更小,说明对角度失配不敏感。
如果做蒙特卡洛时发现常规 MVDR 偶尔也会“蒙对”,导致均值差距不明显,可以把失配范围加大到 ±3 度再看。随机失配场景下,改进算法的优势通常比单次固定失配更清楚,因为固定失配可能正好落在 MVDR 不太敏感的角度区域。
还有一个实用的验证技巧:把输出 SINR 的直方图画出来。常规 MVDR 的 SINR 分布往往有一个长尾,说明存在某些失配角度组合下性能崩掉;改进算法的分布会更集中,长尾明显变短。这个直方图在论文和报告里比单个 SINR 数字更有说服力。我自己做这套仿真时,最大的教训就是不要被单次方向图骗了,看起来漂亮的零陷很可能是特定参数下的巧合,统计验证才是最后一道防线。希望帮到你。
本文还有配套的精品资源,点击获取