雷达信号处理:快慢时间维、匹配滤波与MTD仿真实战
2026/9/14 12:51:43 网站建设 项目流程

简介:这是一份面向雷达信号处理初学者与相关工程技术人员的MATLAB源码包,围绕脉冲串回波信号处理流程,覆盖快时间匹配滤波与慢时间多普勒处理(MTD)两大核心环节,可用于理解雷达测距、测速的基本原理与实现路径。包内共7个文件,全部为.m脚本,按信号生成、回波模拟、匹配滤波、加窗、MTD处理与主控调用等模块划分,整体压缩包仅9KB,代码精炼、便于逐行研读和二次修改。目前已有848人学习下载,适合正在学习雷达原理、数字信号处理或准备课程设计的人员参考。代码完整展示了从发射脉冲、目标回波到距离-多普勒谱输出的处理链路,能够帮助读者将课本中的快慢时间概念与具体算法对应起来,快速搭建自己的雷达信号处理实验框架。通过观察各模块脚本的参数取值和中间结果,还能进一步体会窗函数对旁瓣抑制的作用以及MTD对运动目标检测的增益,从而加深对雷达信号处理全流程的理解。

1. 快时间慢时间:雷达回波为什么要排成二维矩阵

用 1 ms 脉冲重复周期、脉冲宽度 100 us 的雷达,目标以 10 m/s 运动,一个脉冲内目标只移动 0.1 mm,反射信号的时延变化约 0.67 ps,直接测快时间根本测不到;但相邻脉冲间的相位差在 10 GHz 载频下约 0.42 度,积累 64 个脉冲就很明显。这就是快时间和慢时间必须分开看待的原因。快时间是脉冲内距离维采样的时间轴,慢时间是跨脉冲序列的索引轴。项目中的回波矩阵,行方向对应快时间采样点,列方向对应脉冲号,之后的匹配滤波作用在行上,MTD 作用在列上。理解了这个二维矩阵,main.m 里各函数的关系就清晰了。

2. 脉冲串回波建模:signal_trans、rect 与 Signal_echo 的职责

2.1 rect 函数:数字信号处理里的矩形窗

很多没有接触过雷达仿真的朋友看到 rect.m 以为它只是画方波,实际上它作用在发射信号包络上。rader4 项目里的 rect(x) 实现的是一个宽度归一化的矩形窗:

function y = rect(x) % 矩形窗:|x| <= 0.5 时输出 1,否则输出 0 y = double(abs(x) <= 0.5); end

这里的 x 不是时间轴本身,而是相对脉冲宽度 T 的归一化坐标。比如rect((t - T/2) / T)会把 t 等于 0 到 T 之间的值映射到 [-0.5, 0.5],从而只在中间那段区间输出 1。这个函数会被 signal_trans.m 调用,用来限定线性调频信号只在脉冲持续时间内存在。直接在exp函数外加矩形窗,得到的包络虽然不是平滑滚降,但作为发射信号本身没有太大问题,因为雷达发射机本来就需要在时域上截断脉冲。

注意:rect 的默认定义是|x| <= 0.5时取 1,而不是严格只在|x| < 0.5。MATLAB 里用<=可以避免边界时出现整道距离门归零的问题。

2.2 signal_trans 生成基带线性调频脉冲

signal_trans.m 在该项目里的作用是把发射波形从零中频产生出来。下面是一段可以放进 main.m 调用的实现:

% signal_trans.m function s_tx = signal_trans(fs, T, B) t = 0 : 1/fs : T - 1/fs; % 基带LFM:瞬时频率从 -B/2 线性变化到 +B/2 s_tx = rect((t - T/2) / T) .* exp(1j * pi * (B / T) * (t - T/2).^2); end

参数 fs 是快时间采样率,T 是单个脉冲宽度,B 是扫频带宽。(B / T)是调频斜率 K,它决定了瞬时频率随时间的变化速度。乘以1j * pi * K * t^2得到复基带线性调频信号,频域上能量集中在带宽 B 内,但时域是等幅包络。这里用复信号而不是实信号,是为了保留相位信息。后续回波建模时,目标运动带来的多普勒相位会叠加到这个复信号上,如果用实信号,正负频率混叠会把相位信息弄丢。

表:项目仿真中可参考的发射参数

参数变量示例取值说明
脉冲宽度T100e-6 s决定距离向发射能量
带宽B5e6 Hz决定距离分辨率
采样率fs10e6 Hz需满足 fs >= 2B
脉冲重复周期PRI1e-3 s对应 1 ms
载频fc10e9 Hz决定多普勒频率

2.3 Signal_echo 把多个目标回波写成矩阵

Signal_echo.m 做的事情比 signal_trans 复杂一些。对第 n 个慢时间脉冲,第 k 个目标的距离会随速度线性变化,即R_k(n) = R0_k + v_k * (n-1) * PRI。回波时延对应为tau_k(n) = 2 * R_k(n) / c,接收到的信号就是发射波形延迟 tau 后,叠加一个与多普勒位移对应的相位。下面的代码是去掉大量工程注释后的核心循环:

% Signal_echo.m 核心结构 function echo = Signal_echo(s_tx, fs, PRI, N_pulse, targets, fc) c = 3e8; lambda = c / fc; R_max = max([targets.R0] + [targets.v] * (N_pulse - 1) * PRI); N_sample = length(s_tx) + round(fs * 2 * R_max / c); echo = zeros(N_sample, N_pulse); for n = 1:N_pulse for k = 1:length(targets) R_n = targets(k).R0 + targets(k).v * (n - 1) * PRI; delay_n = round(2 * R_n / c * fs); phase_n = exp(-1j * 4 * pi * R_n / lambda); idx = delay_n + 1 : delay_n + length(s_tx); if idx(end) <= N_sample echo(idx, n) = echo(idx, n) + s_tx(:) * phase_n; end end end echo = echo + 0.01 * (randn(size(echo)) + 1j * randn(size(echo))) / sqrt(2); end

这里 targets 是一个 struct 数组,每个元素包含R0v两个字段。R_max按目标在一帧内的最大径向位移计算,防止目标远离雷达后超出回波矩阵。delay_n通过四舍五入把连续时延量化到采样点上,这是仿真的精度损失来源,采样率越高,距离量化误差越小。phase_n是完整的回波相位:它包含初始距离相位和慢时间多普勒相位,并不改变脉冲内部波形,只改变每个脉冲的起始相位。最后加的是复高斯白噪声,用来验证匹配滤波在低信噪比下的检测能力。

经过 Signal_echo 生成的 echo 是一个N_sample × N_pulse的矩阵。行号乘以c / (2fs)就是距离,列号乘以 PRI 就是慢时间。在后续的 Signal_match 里,矩阵的行方向由快时间采样决定,这一维做匹配滤波可以得到距离维脉冲压缩结果;在 Signal_MTD 里,矩阵的列方向代表同一距离门在不同脉冲间的幅度和相位变化,这一维做 FFT 就得到多普勒谱。

3. 快时间维匹配滤波:Signal_match 的距离压缩实现

3.1 为什么是匹配滤波而不是简单取出脉冲

雷达信号处理中对回波的第一级处理通常是脉冲压缩,原因很直接:窄脉冲有距离分辨率但能量低,宽脉冲能量高但距离分辨率差。线性调频信号把能量摊到宽脉冲里,接收后再通过匹配滤波把它压回窄脉冲,从而同时拿到能量和分辨率。匹配滤波的本质是让信号频谱通过一个相位共轭的滤波器,使所有频率分量在输出时刻同相叠加,噪声相位则是随机的,难以同相累积,所以输出信噪比最大。

在 MATLAB 中,匹配滤波可以写成y = conv(x, conj(fliplr(s_tx))),但是卷积长度会随着输入变化。另一个更稳定的做法是利用 DFT 的卷积性质,在频域把回波 FFT 乘上发射信号 FFT 的共轭,再 IFFT 回来。这正好对应 Signal_match.m 的实现方式。

3.2 Signal_match 的频域实现

% Signal_match.m function compressed = Signal_match(echo, s_tx) [N_range, N_pulse] = size(echo); Nfft = 2^nextpow2(N_range + length(s_tx) - 1); S_f = fft(s_tx, Nfft); compressed = zeros(N_range, N_pulse); for n = 1:N_pulse Y_f = fft(echo(:, n), Nfft) .* conj(S_f); y_t = ifft(Y_f); compressed(:, n) = y_t(1:N_range); end end

这段代码对每个慢时间脉冲独立做距离维匹配滤波。Nfft取到下一个 2 的幂,目的是让 FFT 长度不小于N_range + length(s_tx) - 1,否则循环卷积会把脉冲压缩后的信号尾部折叠到前面,形成虚假目标。conj(S_f)是发射信号频谱的共轭,乘上回波频谱后,每个频率分量的相位被补偿,输出的 IFFT 在目标时延处产生峰值。由于回波中可能有多个目标,每个目标对应一个延时峰值,峰值位置与目标距离成正比。

需要注意,这里的匹配滤波没有除以发射信号能量来归一化。y_t的幅度会比回波幅度高sqrt(length(s_tx))倍左右,这是匹配滤波的相干积累增益。在实际工程中,如果要比较不同波形的输出幅度,需要在Signal_match.m里除以sqrt(sum(abs(s_tx).^2)),但 rader4 仿真里目标之间的相对幅度已经足够,不是必须的。

提示:不要用conv处理大矩阵。conv 是直接线性卷积,复杂度 O(NM),当回波行数超过几万时会非常慢;FFT 方法的复杂度是 O(N log N),并且各脉冲之间没有数据依赖,可以用 parfor 并行。

3.3 距离分辨率和距离窗的取舍

匹配滤波后的距离分辨率只由带宽决定:delta_R = c / (2B)。带宽 5 MHz 对应 30 米分辨率,带宽 50 MHz 对应 3 米。这个关系与脉冲宽度无关,是 LFM 信号脉压的核心优势。表格给几个常用带宽在 c=3e8 下的距离分辨率:

带宽 B距离分辨率 c/(2B)
1 MHz150 m
5 MHz30 m
10 MHz15 m
50 MHz3 m

采样率的选择不是匹配滤波决定的,而是要在快时间维满足奈奎斯特条件。如果采样率低于两倍带宽,匹配滤波输出会出现栅瓣,峰值位置不再准确。上述 Signal_echo 里的采样率建议取fs >= 2B,再留 20% 余量。采样率太高会增加数据处理量,但不会提高距离分辨率,只会减小距离量化间隔。

另外一个实际问题是距离窗长度。Signal_echoN_sample = length(s_tx) + round(fs * 2 * R_max / c),这相当于把最大目标距离对应的延时放进回波窗,但发射信号的尾沿也会被完整接收。如果目标距离超过窗口,会发生折叠;如果窗口太大,则大部分矩阵元素是纯噪声,做 MTD 时会增加无谓的 FFT 数量。比较合适的做法是先估算感兴趣的最远探测距离,再把矩阵行数取成round(fs * 2 * R_max / c)后向上取到 2 的幂,Signal_match 里再补零。

4. MTD 动目标检测:Signal_window 与 Signal_MTD 的多普勒滤波

4.1 目标运动如何体现在慢时间相位

经过 Signal_match 后,每个慢时间脉冲对应一列压缩后的距离像。静止目标在同一个距离门上的幅度基本不变,运动目标因为径向速度 v,载频 fc 会产生多普勒频率fd = 2 v / lambda。如果观察某个距离门在第 n 个慢时间脉冲处的复数值,它近似是A * exp(1j * 4 * pi * v * (n-1) * PRI / lambda)。这正好是一个以 n 为自变量的离散复正弦信号,频率就是 fd。因此,在慢时间维做 FFT 就可以把不同速度的目标分到不同的多普勒单元里,这就是 MTD 动目标检测的核心。

MTD 与单次脉冲的多普勒处理不同:单次脉冲只能测距,多次脉冲跨慢时间才能测速。rader4 中 Signal_MTD.m 正是对这个按距离门组织的慢时间序列做 FFT。为了避免目标在多普勒维产生高旁瓣,Signal_window.m 会先乘窗函数。

4.2 Signal_window:多普勒维加窗抑制旁瓣

% Signal_window.m function win = Signal_window(N_pulse, window_type) switch lower(window_type) case 'hamming' win = hamming(N_pulse).'; case 'hanning' win = hann(N_pulse).'; case 'blackman' win = blackman(N_pulse).'; otherwise win = ones(1, N_pulse); end end

这里的返回值是一个行向量,方便对数据矩阵按行广播。对回波矩阵M(N_range, N_pulse),加窗写作M_win = M .* win,广播到每个距离门。Hamming 窗的第一旁瓣约 -43 dB,比矩形窗的 -13 dB 好很多,适合检测强目标周围是否存在弱目标;它的代价是主瓣变宽,多普勒分辨率略微下降。需要根据目标场景选择窗型:如果只看单目标,矩形窗没有主瓣展宽问题;如果要分辨相邻目标,Hamming 更稳。

4.3 Signal_MTD:逐距离门 FFT 与速度轴映射

% Signal_MTD.m function [mtd_spectrum, v_axis] = Signal_MTD(range_x_pulse, PRF, fc, nfft) if nargin < 4 nfft = 2 * size(range_x_pulse, 2); end win = Signal_window(size(range_x_pulse, 2), 'hamming'); data_win = range_x_pulse .* win; mtd_spectrum = fftshift(fft(data_win, nfft, 2), 2); f_doppler = (-nfft/2 : nfft/2-1) * PRF / nfft; lambda = 3e8 / fc; v_axis = f_doppler * lambda / 2; end

fft(..., nfft, 2)沿第 2 维做 FFT,即对每个距离门做慢时间变换。fftshift把零频搬移到谱中心,这样负多普勒和正多普勒分布在中心两侧。v_axis就是把多普勒频率转换成径向速度,单位为 m/s,正负号表示目标远离或靠近雷达。

表:MTD 输出参数示例

参数数值说明
PRF1000 Hz最大不模糊多普勒 ±500 Hz
脉冲数 N_pulse64决定速度分辨率和积累增益
nfft128补零 FFT,细化谱点
fc10 GHz波长 0.03 m
不模糊速度范围±3.75 m/s多普勒折叠界限

这里要注意输出速度分辨率是PRF * lambda / (2 * N_pulse),而不是PRF * lambda / (2 * nfft)。补零只插值,不提高真实分辨率;真实分辨率由相参积累时间N_pulse * PRI决定。因此提高速度分辨率的正确方法是增多脉冲数,而不是把 nfft 调大。

盲速问题也集中在这里。当目标速度 v 使多普勒频率超过 PRF/2,频谱会折叠到另一个速度单元。在 fc=10GHz、PRF=1000Hz 时,最大不模糊速度只有 3.75 m/s,这显然不能满足大部分运动目标。工程上会采用多 PRF 切换或相位编码等解速度模糊方案,rader4 中只有一个 PRF,所以仿真时要避免目标速度超过这个范围,否则会看到峰值出现在镜像位置。

注意:Signal_echo 里的目标速度一定要经过不模糊速度判断。例如在项目 main.m 中设置v = [2, -1.5]是安全的,设置v = [10, -10]会出现多普勒混叠,看似出现了目标,实际上速度值需要解模糊。

5. 峰值提取与调参验证

5.1 从距离-多普勒谱读目标参数

MTD 完成后,可以用imagesc(v_axis, range_axis, 20*log10(abs(mtd_spectrum)))画出距离-多普勒图。这时峰值位置的两个坐标就是目标的距离和速度。自动提取时,可以先在全图上找峰值:

PdB = 20*log10(abs(mtd_spectrum)); [~, idx] = max(PdB(:)); [range_idx, doppler_idx] = ind2sub(size(PdB), idx); target_range = range_axis(range_idx); target_v = v_axis(doppler_idx);

这段代码直接读出最强峰对应的距离和速度。若要提取多个目标,把max换成findpeaks或先做二维 CA-CFAR 检测。最简单的做法是设置一个相对门限,比如 13 dB:先滤除旁瓣,再按区域极大值排序。不要用绝对门限,因为回波幅度会受噪声电平和积累点数影响,相对门限更稳定。

5.2 调整加窗与门限如何影响速度谱

实测中发现,直接对矩形窗做 MTD,强目标的多普勒旁瓣可能掩盖旁边弱目标,这时 Signal_window 换成 Hamming 后速度谱旁瓣下降,但主瓣略宽。另一个容易被绊住的地方是20*log10(abs(mtd_spectrum))在图形界面中会丢负无穷值,最好先执行mtd_spectrum(abs(mtd_spectrum) < eps) = eps再取对数。

想要验证整条链路是否正常,可以设置两个目标速度差 1 m/s,脉冲数 64,理论上速度分辨约 0.47 m/s,应该在谱上看到两个可分离峰;如果只看到一个平坦峰,说明加窗主瓣展宽导致分辨不足。把速度差拉大到 2 m/s,或者把 N_pulse 改成 128,重新跑一遍 main.m,你会看到两个分离峰;如果两个峰始终黏在一起,再去查 Signal_window 是不是把整个慢时间维乘成了矩形窗而不是 Hamming 窗。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询