MATLAB实现雷达测速测距仿真:从FMCW差频到二维FFT
2026/9/16 14:38:27 网站建设 项目流程

简介:面向电子工程、物理研究人员、大学生及工程技术人员的MATLAB雷达仿真学习包,系统讲解雷达测速与测距中的多普勒效应核心原理。内容覆盖发射信号建模、回波接收、多普勒频移提取、目标距离与速度解算及数据处理等完整流程,并通过仿真实验直观呈现测量结果。压缩包共593个文件,总大小约7.75MB,以480个m源码文件为主体,辅以mat数据文件、fig图像与png结果图、c/cpp扩展及dll动态库等,便于在MATLAB中直接运行、修改与验证算法。已有178人学习下载。可运行的MATLAB实现帮助读者快速重现多普勒测速测距实验,理清频移计算与距离速度联合解算思路;同时融入交通管理、军事侦察、气象监测等应用前景讨论,并引用多份参考资料,为后续深入研究提供延伸方向。

1. 雷达测速测距的仿真从哪里下手:多普勒频移与差频信号不能分开看

做雷达测速测距的算法验证,最难的不是套公式,而是不知道数据里哪一部分该做 FFT、做完 FFT 又该看哪个轴。只用连续波测速时,多普勒频移只给出速度,距离信息完全缺失;只用 FMCW 测距时,差频频率可以映射距离,但目标一旦运动,差频里又会混进多普勒频移,直接算距离会偏。要同时解开两个量,惯用的做法是把一帧里的多个 chirp 排成矩阵,沿快时间维做距离 FFT、沿慢时间维做速度 FFT,最后从距离-多普勒图里同时读取距离和速度。MATLAB 在整套流程里顺手得多:波形生成、窗函数、二维 FFT 和图像显示都是现成函数,几十行代码就能把原理落成可见结果。这篇文章会从信号模型、最小可运行代码、结果分析一直讲到参数边界和验证方式,适合课程设计、雷达算法预研以及刚接触毫米波雷达数据的读者。

2. 多普勒测速与 FMCW 测距的原理,在 MATLAB 里先要建立哪两个模型

2.1 距离信息在快时间维,速度信息在慢时间维,两者由同一个差频信号携带

FMCW 雷达发射信号的频率随时间线性上升。设调频带宽为 B,chirp 持续时间为 Tc,则调频斜率 S=B/Tc。发射信号用复数形式写为:

s_tx(t)=exp(j2π(f_c t + 1/2 S t^2))

目标回波相对于发射信号有一个时间延迟 τ=2R/c。接收机把回波信号与发射信号的共轭相乘,得到差频(拍频)信号。忽略幅度和多径后,差频信号的相位近似为:

s_if(t)=exp(j2π(f_c τ + Sτ t))

其中第一项是固定相位,第二项是一个随时间线性变化的相位项,其瞬时频率是 Sτ。对快时间 t 做 FFT,会在频率 Sτ 处形成一个谱峰;因为 τ=2R/c,所以谱峰位置正比于距离。这就是 FMCW 测距的基本关系。

当目标以径向速度 v 运动时,每个 chirp 对应的 τ 都在变化。设慢时间为 t_slow,则距离 R(t_slow)=R0+v·t_slow,τ(t_slow)=2R(t_slow)/c。把它代回 s_if(t) 的固定相位项 f_c τ 中,会看到该相位随 chirp 序号线性变化。相邻 chirp 之间的相位差是 4πvTc/λ,也就是慢时间维上的多普勒频移 f_d=2v/λ。快时间维和慢时间维在同一个差频信号矩阵里,但分属不同维度,这正是二维 FFT 可以同时得到雷达测距和雷达测速结果的原因。

2.2 先定好 6 个雷达参数,再看距离分辨率和速度分辨率的边界

在 MATLAB 里做仿真要先定一组参数。我一般用下面这组,它接近常见的毫米波雷达前级参数:

参数符号取值作用由它决定的边界
fc77 GHz载波频率λ=c/fc≈3.9 mm,速度换算系数
B200 MHz调频带宽距离分辨率 ΔR=c/(2B)=0.75 m
Tc50 µs单个 chirp 时长最大不模糊速度 v_max=λ/(4Tc)≈19.5 m/s
fs4 MHz快时间采样率最大不模糊距离 R_max=c·fs/(4S)≈75 m
Nchirp128一帧内 chirp 数量速度分辨率 Δv=λ/(2Nchirp·Tc)≈0.305 m/s
S4×10^12 Hz/s调频斜率由 B/Tc 计算,不要手工写死

把这组参数代进去,距离分辨率 0.75 m,速度分辨率 0.305 m/s。一个 50 m 处、以 10 m/s 靠近的目标,差频约 1.33 MHz,在 N_range=256 时谱峰大约落在第 86 个 bin;多普勒维大约落在第 33 个 bin。第一次跑仿真时,目标参数一定要放在这两个边界以内;如果直接设速度 25 m/s,慢时间采样率 1/Tc=20 kHz,而 f_d=2×25/0.0039≈12.8 kHz,超过了 10 kHz 的奈奎斯特频率,速度谱会混叠成一个错误的负速度峰。同理,目标放在 80 m 时,差频 f_IF=S·2R/c≈2.13 MHz,也会超过 fs/2=2 MHz,被折叠到一个虚假的近距峰。看到这种“测出来的值突然变小”的结果,先检查有没有越过边界,而不是急着调 FFT 参数。

2.3 为什么差频信号在 MATLAB 里用 exp(1j*...) 而不写成 cos

仿真代码里几乎不会出现 cos(2πft) 这种写法。原因有两个。第一,差频信号是单边频谱,用复数指数建模后,快时间 FFT 的峰值只在正频率一侧出现,负频率部分不会生成镜像,目标检测的峰值干净得多。第二,慢时间维度需要保留速度方向,也就是正负多普勒频移。cos 信号在频谱上对称地分成 ±f 两个峰,幅度和相位信息被拆散,处理起来很别扭。相位式 exp(1jf_cdelay + 1jSdelay*t_fast) 既包含当前 chirp 对应的距离延迟,又能通过跨 chirp 的固定相位变化还原出速度方向。因此后续所有代码都按复数基带形式组织。

3. 用 MATLAB 串起差频信号、二维 FFT 与峰值读取的最小链路

3.1 生成差频信号矩阵的完整 MATLAB 代码

先给最小可运行代码。下面这段脚本会生成一个 Ns×Nchirp 的复数差频矩阵 IF_sig,行对应快时间采样,列对应一帧里的不同 chirp。

% 雷达与波形参数 fc = 77e9; % 载频 77 GHz c = 3e8; % 光速 B = 200e6; % 调频带宽 200 MHz Tc = 50e-6; % 单个 chirp 时长 50 us fs = 4e6; % 差频信号采样率 4 MHz S = B / Tc; % 调频斜率 4e12 Hz/s % 目标与帧参数 R0 = 50; % 目标初始距离 50 m v = 10; % 目标径向速度 10 m/s,正值表示靠近雷达 Nchirp = 128; % 一帧内 chirp 数量 % 时间轴 Ns = round(Tc * fs); % 每个 chirp 的采样点数 t_fast = (0:Ns-1) / fs; % 快时间轴 t_slow = (0:Nchirp-1) * Tc; % 慢时间轴 lambda = c / fc; % 波长 % 差频信号矩阵 IF_sig = zeros(Ns, Nchirp); for k = 1:Nchirp % 当前 chirp 发送时刻目标的真实距离 R_k = R0 + v * t_slow(k); delay = 2 * R_k / c; % 回波延迟 % 差频信号:快时间项 S*delay*t_fast 对应距离; % 恒定相位项 fc*delay 跨 chirp 变化,对应多普勒 IF_sig(:, k) = exp(1j * 2 * pi * (fc * delay + S * delay * t_fast)); end

这段代码直接写出了差频后的相位,等价于先构造 s_tx、s_rx 再做s_tx.*conj(s_rx),没有缺步骤。最核心的地方在于 delay 的计算。如果用 delay=2*R0/c 并固定不变,测速信息就完全丢失,后面多普勒 FFT 不会出现峰值,v_est 会变成 0。这里的 R_k 随 t_slow 变化,正是多普勒频移的来源。

Tc*fs=200是整数,所以Ns直接取 round 也不会有问题;如果换参数后不是整数,必须用 round 并检查Ns*fs是否准确对应一个 chirp 时长,否则多普勒轴会整体偏移。t_slow从 0 开始,相邻 chirp 的间隔就是 Tc,它决定了慢时间的采样周期。

3.2 沿快时间做距离 FFT,沿慢时间做多普勒 FFT

下一步是二维 FFT。先用 nextpow2 把两个维度的 FFT 长度都取成 2 的幂,再用 hamming 窗压低旁瓣。

% FFT 长度,取 2 的幂方便频点计算 N_range = 2^nextpow2(Ns); N_doppler = 2^nextpow2(Nchirp); % 窗函数:减少距离维和多普勒维的频谱泄漏 range_win = hamming(Ns); doppler_win = hamming(Nchirp); % 第一步:快时间 FFT,得到距离维频谱 RD_map = fft(IF_sig .* range_win, N_range, 1); % 第二步:慢时间 FFT,得到多普勒维频谱 % doppler_win 是列向量,用转置变为行向量后与矩阵按维相乘 RD_map = fft(RD_map .* doppler_win', N_doppler, 2); % 将多普勒零频移动到中间,方便按照正负频率查看 RD_map = fftshift(RD_map, 2);

逻辑说明:第一次 fft 沿着第 1 维做,等价于对每个 chirp 做一次距离维变换,输出是“距离门 × chirp 序号”的二维复数矩阵。第二次 fft 沿着第 2 维做,输入是同一个距离门在一帧内各 chirp 的相位序列,输出就是多普勒频谱。两个维度合在一起,才得到距离-多普勒矩阵 RD_map,也就是常说的距离-多普勒图。这里fftshift只作用于第 2 维,距离维轴仍然从零频开始,不需要 shift。

IF_sig .* range_win中 range_win 是 Ns×1 列向量,与 Ns×Nchirp 矩阵相乘时由 MATLAB 的隐式扩展完成;doppler_win需要转置成 1×Nchirp 才能沿着列方向扩展。如果版本较老,显式写repmat会更保险。下面是这一步的维度关系:

FFT 步骤作用维度输入矩阵输出矩阵语义
fft(IF_sig .* range_win, N_range, 1)快时间维Ns×NchirpN_range×Nchirp,每一列是单个 chirp 的距离谱
fft(..., N_doppler, 2)慢时间维N_range×NchirpN_range×N_doppler,距离与多普勒的二维联合谱
fftshift(..., 2)多普勒维同上多普勒零频移到中间,按正负速度查看

3.3 从峰值位置把距离和速度换算出来

峰值检索和换算也可以直接写成代码:

% 找距离-多普勒图上幅度最大的点 [~, idx] = max(abs(RD_map(:))); [r_idx, d_idx] = ind2sub(size(RD_map), idx); % 距离维:由 FFT bin 换算到差频频率,再换算到距离 f_if_est = (r_idx - 1) / N_range * fs; R_est = f_if_est * c / (2 * S); % 多普勒维:由 fftshift 后的 bin 换算到多普勒频率,再换算到速度 f_d_axis = (-N_doppler/2 : N_doppler/2 - 1) / N_doppler / Tc; f_d_est = f_d_axis(d_idx); v_est = f_d_est * lambda / 2; fprintf('估计距离: %.2f m\n', R_est); fprintf('估计速度: %.2f m/s\n', v_est);

这段代码把频率轴定义和 bin 索引换算讲清楚了。MATLAB 的fft结果从下标 1 开始,所以真实频率要写成(r_idx-1)/N_range*fs,和索引从 0 开始的 C 语言 FFT 不同。多普勒维因为做了fftshift,频率轴是负半轴在前、正半轴在后,直接和f_d_axis(d_idx)对应。运行后 R_est 应该在 50 m 附近,v_est 在 10 m/s 附近,但不会精确等于设定值,因为 FFT 频率分辨率的限制让峰值落在 bin 中心之外,这是正常的栅栏效应,下一节会讲怎么进一步压缩这个误差。

4. 距离-多普勒图的结果研究:峰值换算、参数对照与三个常见误设

4.1 把谱峰读数换成距离和速度的两级换算

上一章的换算里隐藏了一个细节:R_est是先把 FFT 的 bin 索引换算成差频频率,再把差频频率换算成距离。距离维频率分辨率是fs/N_range。以 N_range=256 为例,距离维 bin 间隔约为 1.17 m,但物理距离分辨率由带宽 B 决定,是 c/(2B)=0.75 m。补零到 2048 只是把 bin 间隔变小,让谱峰看起来更平滑,不会把两个相距 0.5 m 的目标分开。

多普勒维的情况类似。多普勒频率分辨率是1/(Nchirp*Tc),速度分辨单元是λ/(2*Nchirp*Tc)。想提高速度分辨率,直接增加 Nchirp 最有效。不过 Hamming 窗会把主瓣展宽约 1.44 倍,加窗后的实际分辨能力比理论值略差,这一点在多目标邻近时尤其明显。

4.2 雷达测速测距参数调整对照表

调参是结果研究里最重要的部分。很多初学的人觉得距离分辨率不够就调大带宽,结果差频超过采样率,反而测不出正确距离。下面这张表是调参时最常用的依据:

优化目标推荐改法副作用与代价
提高距离分辨率增大带宽 B差频频率随 B 上升,fs 不够时最大测距下降
提高最远测距提高 fs 或增大 Tc增大 Tc 会降低多普勒不模糊速度,可能出现测速混叠
提高速度分辨率增大一帧内 chirp 数 Nchirp帧时间变长,实时性下降,更新率降低
提高最大不模糊速度减小 Tc单个 chirp 变短,快时间采样点变少,距离分辨率受限
压低旁瓣换凯塞窗等主瓣展宽,峰值定位误差变大

例如要把距离分辨率从 0.75 m 提高到 0.375 m,B 从 200 MHz 涨到 400 MHz,在 Tc 不变时 S 翻倍,同样的 50 m 目标差频从 1.33 MHz 变成 2.67 MHz,已经超过 fs/2,距离谱会混叠。此时要么把 fs 同步提到 8 MHz,要么接受最大测距减半。反过来,把 Tc 从 50 µs 加大到 100 µs,最大不模糊速度从 19.5 m/s 降到 9.75 m/s,10 m/s 的目标会立刻变成“折叠”后的假速度。调参时距离边界和速度边界必须一起看。

注意:当目标距离超过 R_max=c·fs/(4S) 时,差频峰值会发生频谱折叠。如果你发现 R_est 突然变得很小且和设置值对不上,先算这个边界,而不是改 FFT 长度。

4.3 三种最常导致“跑不出峰”的 MATLAB 误设

第一,取实部丢了速度方向。把IF_sigreal(IF_sig)处理后再做 FFT,会得到对称的双峰,峰值定位严重受影响。差频信号应该保持复数形式。第二,两个 FFT 的维度写反。快时间和慢时间都做 FFT 后应当得到一个二维复数矩阵;如果fft(...,2)被误写成fft(...,1),速度维根本没有展开,RD_map 上不会出现孤立峰,而会出现一整条沿距离维的亮线。第三,忘记 fftshift 或 shift 了错误维度。多普勒轴如果不 shift,零速度峰被放在频谱两端,负速度目标会显示在右边缘,初看容易误判。检查方法很简单:先画出mesh(abs(RD_map)),距离维看峰的位置能否对应 R0,多普勒维看峰是否落在零频附近且只有一侧有清晰旁瓣;不符合预期就回去检查 FFT 的维度。

5. 用峰值插值和二维 CFAR 把雷达测速测距结果推得更稳

5.1 三点抛物线插值压低栅栏误差

FFT 峰值落在整数 bin 之间时,max得到的 bin 索引会带来最多半个分辨单元的误差。对单目标场景,一个三点抛物线插值就能明显改善:取峰值前后的 bin 幅度,拟合抛物线,顶点就是更精确的峰位置。

if r_idx > 1 && r_idx < N_range y = abs(RD_map(r_idx-1:r_idx+1, d_idx)); delta_r = 0.5 * (y(3) - y(1)) / (y(1) - 2*y(2) + y(3) + eps); f_if_est = ((r_idx - 1 + delta_r) / N_range) * fs; R_est = f_if_est * c / (2 * S); end

这个公式就是二次函数在三个等距采样点上的顶点坐标。eps是为了避免分母为零。多普勒维用同样的方式插值,速度估计会更接近真实值。

5.2 多目标场景把单峰 max 换成二维 CFAR 检测

max搜索在多目标场景下会被强目标盖住弱目标。更接近工程化的做法是使用 Phased Array System Toolbox 提供的二维恒虚警检测器phased.CFARDetector2D:对每个距离-多普勒单元,用周围训练单元估计噪声底,超过门限才认为是目标。

cfar = phased.CFARDetector2D( ... 'TrainingBandSize', [4 4], ... 'GuardBandSize', [2 2], ... 'FalseAlarmRate', 1e-4); det = cfar(abs(RD_map), (1:numel(RD_map))'); mask = reshape(det, size(RD_map));

FalseAlarmRate是虚警概率门限,取 1e-4 是比较稳的起点;TrainingBandSizeGuardBandSize控制参考窗和保护窗的尺寸。训练单元太小,门限会被邻近目标抬高;保护单元太小,目标能量会泄漏进参考窗。这里的 [4 4] 和 [2 2] 要按距离-多普勒图中目标的实际尺寸调整,不是固定值。

5.3 仿真结果的验证方法

跑完上面任意一种检测,把 R_est、v_est 与仿真里设置的 R0、v 直接相减,误差落在半个分辨单元的量级内就说明差频、FFT、换算这条链路是自洽的。还想进一步确认速度方向时,把 v 改成 -10 重跑一次,观察 RD_map 上的峰是否移动到多普勒轴的负半轴,这是最直观的方向验证。

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

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

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

立即咨询