FMCW雷达测距测速原理与MATLAB仿真:从差频信号到距离-多普勒谱

FMCW雷达测距测速原理与MATLAB仿真:从差频信号到距离-多普勒谱 简介基于MATLAB的FMCW体制雷达测距测速仿真代码面向雷达信号处理初学者与车载毫米波雷达研究人员覆盖单点目标和多点目标两种探测场景。代码内含完整的仿真脚本包括逻辑判断模块、单点变速测量、三目标回波处理等可复现FMCW差拍信号产生、距离与速度解算流程并对照屈飞园等提出的多目标有效检测方法进行验证。压缩包共6个m文件整体仅6KB结构精简无冗余适合逐行研读与二次开发。目前已有200人学习使用可作为课程设计、毕业设计或工程预研的参考实现。1. FMCW雷达测距测速与MATLAB仿真的切入点FMCW 雷达的测距测速本质上是把目标距离和速度这两个物理量搬进差频信号的频率和相位里再用 FFT 把频率和相位差读出来。毫米波 FMCW 雷达之所以在车载、工业测距里成为主流就是因为单个 chirp 内同时携带距离和时间延迟信息而一串 chirp 的相位变化又携带多普勒速度信息。做 MATLAB 仿真的目标不是重复公式而是先把整条链路跑通单点目标验证“基带信号生成-二维FFT-峰值提取-距离速度换算”这条最小路径多点目标再验证目标分离、旁瓣抑制和检测阈值。这个标题适合两类人一类刚接触 radar signal processing想弄清距离维 FFT 和速度维 FFT 到底是什么关系另一类手里有 TI awr2243 或类似毫米波雷达的采集数据需要先在仿真里验证算法再换到实测数据上。接下来我会从差频信号原理讲起然后直接给可运行的 MATLAB 代码最后补上参数设置和常见坑。2. FMCW测距测速原理与关键参数从差频信号到距离-多普勒谱2.1 锯齿波FMCW的差频信号生成过程先固定一个最常用的体制锯齿波 FMCW。发射信号频率在一个 chirp 周期 Tc 内从 fc 线性扫到 fcB调频斜率 S B/Tc。某个目标距离为 R电磁波往返延迟tau 2R/c。接收信号是发射信号经过 tau 延迟后的副本把发射信号与接收信号共轭相乘复基带混频得到差频信号。差频信号的瞬时频率近似为f_b S * tau 2SR/c 2BR/(c * Tc)单看这一个 chirp距离 R 与差频 f_b 是一一映射的。问题在于当目标有径向速度 v 时延迟变成tau 2(R v*t)/c多普勒效应会把一个随慢时间变化的相位叠加进来。严格写差频频率为f_b 2BR/(c*Tc) 2v/lambda其中lambda c/fc是载波波长。距离项和多普勒项混在同一个频率上所以单靠一个 chirp 无法同时解出距离和速度。这就是为什么 FMCW 测距测速必须用多个 chirp 组成一帧再在慢时间维上做一次 FFT。去斜混频后每个采样点对应一个复数值。如果发射信号是tx(t) exp(j*2*pi*(fc*t 0.5*S*t^2))接收信号是把 t 替换为t - tau差频信号就是tx * conj(rx)。实际工程中这一步由雷达前端的混频器和低通滤波器直接完成仿真里则需要用复指数显式构造后面代码会按这个逻辑写。2.2 快时间维FFT测距与慢时间维FFT测速把一帧内 M 个 chirp 的采样数据排成一个 N×M 矩阵N 是单个 chirp 的采样点数。行方向叫快时间维对应一个 chirp 内按 ADC 采样率采到的时间点列方向叫慢时间维对应 chirp 序号 m 乘以 Tc。先沿快时间维做 FFT差频频率就变成峰值位置再根据 f_b 与 R 的比例关系算出距离。这一维通常叫距离维 FFT。做完距离维 FFT 后每一列对应一个距离 bin该 bin 上的复相位在慢时间维上的变化率正是多普勒频率f_d 2v/lambda所以再沿慢时间维做 FFT每个距离 bin 上就能看到速度维的峰值得到距离-多普勒谱Range-Doppler Map。这个过程可以先用fft(sig, N, 1)再fft(..., M, 2)也可以fft2一次完成只要维度顺序别搞反。2.2.1 距离维FFT的bin间距与分辨率快时间维 FFT 的频率分辨率是1/Tc把它代入 f_b 与 R 的线性关系得到距离分辨率dR c/(2*B)注意距离分辨率只由扫频带宽 B 决定与 Tc、采样率无关。B250MHz 时 dR0.6mB1GHz 时 dR0.15m。这是雷达距离方程之外另一个决定雷达测距能力的核心公式。距离维 FFT 的相邻 bin 间隔也是 dR所以单个目标不加插值时的测距量化误差就是 dR 级别。距离维能测到的最大差频受采样率限制。设 ADC 采样率为 fs则 f_b 必须小于 fs/2复基带下可以放宽到 fs对应的最大距离为Rmax c*fs/(4S) c*fs*Tc/(4B)采样率不够时远处目标会折叠到近处这一点在设置 fs 时一定要先算。2.2.2 速度维FFT与最大不模糊速度慢时间维的采样间隔是 Tc对复信号来说可测多普勒频率范围是±1/(2Tc)于是有最大不模糊速度vmax lambda/(4*Tc)77GHz 雷达波长约 3.9mmTc30us 时 vmax 约 32.4m/s够覆盖绝大多数场景。如果 Tc 取得太长比如 100usvmax 只剩约 9.7m/s30m/s 的目标会折叠到负速度区测速结果完全不可用。速度分辨率由一帧总时长T_frame M*Tc决定dv lambda/(2*M*Tc)M128、Tc30us 时 dv 约 0.51m/s。要同时提高 vmax 和 dv只能缩短 Tc 同时增大 M这会增加帧时长和目标距离走动风险。2.3 影响测距测速精度的系统参数把上面几个公式汇总成了一张参数表这是我做仿真前一定会先算一遍的内容参数符号计算式设计影响扫频带宽B需求决定越大距离分辨率越高但对 ADC 采样率和信号处理量要求越高chirp周期Tc需求决定越小 vmax 越大但同样距离的差频 f_b 越高ADC采样率fs 2*S*Rmax/c决定最大可测距离过高会增大数据量chirp数量M需求决定越大速度分辨率越高但帧时间变长载频fc72-81GHz 典型值决定波长直接影响多普勒灵敏度和 vmax这段选参数代码可以直接跑里面包含了我常用的校验逻辑fc 77e9; % 载频 77GHz B 250e6; % 带宽 250MHz Tc 30e-6; % chirp 周期 30us fs 20e6; % ADC 采样率 20MHz M 128; % 一帧 chirp 数 c 3e8; lambda c / fc; S B / Tc; dR c / (2*B); vmax lambda / (4*Tc); dv lambda / (2*M*Tc); Rmax_150 150; f_b_150 S * 2 * Rmax_150 / c; fprintf(dR%.3fm, vmax%.2fm/s, dv%.3fm/s\n, dR, vmax, dv); fprintf(150m 处差频%.2fMHz, fs/2%.1fMHz\n, f_b_150/1e6, fs/2/1e6);这段代码先用大括号括起来的常量定义参数然后按公式算出距离分辨率、最大不模糊速度、速度分辨率和指定距离的差频。f_b_150必须小于fs/2否则远距离目标会混叠。实际调试时如果发现测距结果跑到负距离或目标位置明显不对第一件事就是检查这个约束条件。3. 基于MATLAB的单点目标FMCW测距测速仿真3.1 仿真参数与场景设定单点目标的作用是把整条信号链路跑通。我选择的参数与上一章一致fc77GHzB250MHzTc30usfs20MHzM128。目标距离 R150m径向速度 v30m/s以靠近雷达为正方向。目标属性数值说明距离 R150m对应差频约 8.33MHz速度 v30m/s小于 vmax32.4m/s不会模糊回波幅度 A1.0单点场景先不加噪声与衰减这里速度选 30m/s 是有意的目的是验证参数表里 vmax 的重要性。如果 Tc 取 50us这个目标就会折叠后面读速度维峰值时会得到错误的符号。3.2 发射接收与差频信号生成的MATLAB实现仿真的核心是生成 N×M 的差频信号矩阵。完整代码分两段第一段生成信号第二段做 2D-FFT 和峰值提取。% 基础参数 fc 77e9; c 3e8; B 250e6; Tc 30e-6; fs 20e6; M 128; S B / Tc; lambda c / fc; N round(Tc * fs); % 600 点/chirp % 快时间与慢时间网格 n (0:N-1). / fs; % N×1 快时间列向量 m (0:M-1) * Tc; % 1×M 慢时间行向量 fast repmat(n, 1, M); % N×M slow repmat(m, N, 1); % N×M time fast slow; % 完整时间轴 % 目标150m30m/s R 150.0; v 30.0; A 1.0; tau 2 * (R v * time) / c; tx exp(1j * 2 * pi * (fc * time 0.5 * S * fast.^2)); rx exp(1j * 2 * pi * (fc * (time - tau) 0.5 * S * (fast - tau).^2)); if_sig A * tx .* conj(rx);这段代码里有几个容易写错的地方。repmat把快时间列向量按列方向复制 M 份把慢时间行向量按行方向复制 N 份得到完整时间网格。tau必须用矩阵计算因为速度项要叠加在慢时间维度上。发射信号和接收信号的相位差经过conj(rx)后自然产生了差频不需要再做一次混频。对比一个常见误写直接对发射信号本身做 FFT而不是对tx .* conj(rx)做 FFT。那样的话目标信息会被 fc 附近的高频完全淹没结果只是频率为 fc 附近的尖峰根本读不出距离。3.3 2D-FFT与距离-多普勒谱解读接下来做二维 FFT并换算距离轴和速度轴。% 距离维加窗后做 FFT再对速度维做 FFT win_r hann(N); win_d hann(M).; sig_w if_sig .* (win_r * win_d); rd_map fftshift(fft(fft(sig_w, N, 1), M, 2), 2); % 坐标轴换算 range_axis (0:N-1) * c / (2*B); vel_axis (-M/2:M/2-1) * lambda / (2 * M * Tc); % 单点目标直接取最大值 [~, idx] max(abs(rd_map(:))); [r_idx, v_idx] ind2sub([N, M], idx); est_R range_axis(r_idx); est_v vel_axis(v_idx); fprintf(真实: R%.1fm, v%.1fm/s\n, R, v); fprintf(估计: R%.2fm, v%.2fm/s\n, est_R, est_v);fft(if_sig, N, 1)是沿第 1 维做距离维 FFTfft(..., M, 2)沿第 2 维做速度维 FFT最后fftshift(..., 2)只对速度维移轴使零速在谱中心。距离轴的 0 距离对应第一个 bin因此不做 fftshift。窗函数的作用是压低旁瓣下一章会具体展开。运行结果里估计距离会落在距离轴最接近 150m 的 bin 上估计速度落在 30m/s 附近。注意这里量化误差约为 dR0.6m 和 dv0.51m/s这是 FFT 栅栏效应的固有结果不是代码错误。要进一步提高精度需要做第 5 章的峰值插值。ind2sub用于把一维索引拆成距离维和速度维两个下标。单点目标可以直接取全局最大值到了多点目标就必须换成 CFAR 或局部峰值检测。4. 多点目标FMCW仿真目标分离、窗函数与峰值检测4.1 多点目标回波叠加与仿真场景多点目标仿真的重点不是简单地把代码复制三遍而是理解目标之间的互相干扰。我设置三个目标目标 1 在 100m速度 10m/s目标 2 在 100m速度 30m/s目标 3 在 120m速度 20m/s。目标 1 和目标 2 的距离完全一样只靠速度维区分这是距离维 FFT 无法分离的典型场景。回波生成时把每个目标的差频信号复振幅叠加然后加一点复高斯噪声% 目标列表距离、速度、幅度 targets [ 100.0, 10.0, 1.0; 100.0, 30.0, 0.9; 120.0, 20.0, 0.8 ]; if_sig zeros(N, M); for k 1:size(targets, 1) Rk targets(k, 1); vk targets(k, 2); Ak targets(k, 3); tau_k 2 * (Rk vk * time) / c; tx_k exp(1j * 2 * pi * (fc * time 0.5 * S * fast.^2)); rx_k exp(1j * 2 * pi * (fc * (time - tau_k) 0.5 * S * (fast - tau_k).^2)); if_sig if_sig Ak * tx_k .* conj(rx_k); end % 叠加复高斯噪声 noise_amp 0.02; if_sig if_sig noise_amp * (randn(N, M) 1j * randn(N, M));这里targets矩阵的每一行是一个目标列依次是距离、速度、幅度。幅度对应目标回波强度理想情况下回波功率服从雷达距离方程与距离的四次方成反比。仿真里为了突出距离维和速度维的分离能力我手动指定了幅度。贴近实测时可以把幅度改成(R_ref/R)^2这是幅度与距离平方成反比的关系。如果只对if_sig沿距离维做 FFT100m 处会看到目标 1 和目标 2 叠加成一个峰幅度大约是两者矢量和速度信息完全丢失。只有再沿慢时间维做 FFT才能把两个速度峰值分开。这就是多点目标必须依赖距离-多普勒谱的原因。4.2 频谱泄漏、旁瓣与窗函数选择FFT 默认把信号当成无限周期信号的截断截断造成频谱泄漏。多点场景下大目标的旁瓣可能淹没小目标的主瓣。矩形窗最高旁瓣约 -13.3dB这意味回波幅度相差超过 20dB 的两个目标小目标很容易被掩盖。窗函数主瓣宽度bin最高旁瓣dB适用场景矩形窗1-13.3目标少、幅度接近追求最大分辨率汉宁窗2-31.5多目标幅度差异大最常用布莱克曼窗3-58.1动态范围要求极高分辨率让步大加窗的代码在上一章已经出现过sig_w if_sig .* (win_r * win_d);win_r * win_d是 N×1 列向量和 1×M 行向量的外积形成一个 N×M 的二维窗矩阵。注意加了汉宁窗后主瓣宽度是矩形窗的两倍距离维两个目标间隔小于 1.2m 时反而更难分辨。实际工程里常用汉宁窗做检测再用矩形窗或无窗结果复核两者交叉验证。4.3 距离-多普勒谱上的峰值检测与目标配对单点目标可以直接用max多点目标必须做检测加局部峰值筛选。CFAR恒虚警检测是雷达信号处理里目标检测的标准做法。二维 CA-CFAR 的简化实现如下P abs(rd_map); alpha 8; % 阈值因子控制虚警率 guard 2; % 保护单元数 ref 10; % 参考单元数 % 距离维方向的一维 CA-CFAR对每个速度列独立计算 win ones(2*ref1, 1); win(ref-guard1:refguard1) 0; win win / sum(win); Ppad padarray(P, [refguard, 0], replicate); noise_est filter2(win, Ppad, valid); % 与 P 同尺寸 det_mask P alpha * noise_est;win是长度为2*ref1的列向量中间2*guard1个元素置零作用是去掉被检测单元本身和紧邻单元避免目标能量抬高噪声估计。filter2做滑动窗平均得到局部噪声水平alpha8表示目标幅度超过局部均值 8 倍才判为检测虚警率约在1e-3量级具体数值与噪声分布有关。CFAR 输出是 0/1 掩膜接着要提取局部峰值避免同一目标周围多个相邻单元同时过门限keep false(size(det_mask)); for i 2:N-1 for j 2:M-1 if det_mask(i,j) P(i,j) max(max(P(i-1:i1, j-1:j1))) keep(i,j) true; end end end [r_idx, v_idx] find(keep); for k 1:length(r_idx) fprintf(检测: R%.2fm, v%.2fm/s\n, ... range_axis(r_idx(k)), vel_axis(v_idx(k))); end这个局部峰值筛选用 3×3 邻域内幅度最大作为保留条件实现简单且不需要图像处理工具箱。CFAR 的alpha参数很关键调大到 12 以上会漏掉弱目标调小到 3 以下会产生大量虚警实际我一般先设 8 看检测点数再根据噪声底调整。目标配对在这里已经天然完成距离-多普勒谱上每个峰值点同时给出距离和速度不存在一维频谱里“哪个距离峰对应哪个速度峰”的歧义问题。5. FMCW仿真验证技巧峰值插值、误差核算与常见坑5.1 用抛物线插值消除FFT栅栏效应FFT 峰值只能落在整数 bin 上目标真实位置在两个 bin 之间时直接读峰值坐标会引入最多半个 bin 的量化误差。用峰值点及其左右相邻点的幅度做抛物线插值可以把估计精度提高一个数量级以上% 取峰值位置所在的距离维三格 p P(r_idx, v_idx - 1 : v_idx 1); % 速度维插值 num p(1) - p(3); den 2 * (p(1) - 2*p(2) p(3)); delta num / (den eps); est_v vel_axis(v_idx) delta * lambda / (2 * M * Tc);距离维同样处理只需要把P(r_idx-1:r_idx1, v_idx)带进公式。eps用来避免分母为零的退化情况。对汉宁窗来说峰值附近更接近抛物线形状插值效果比矩形窗稳定但矩形窗的对应公式也能用。5.2 用仿真误差检验参数边界己方估计的误差应当与理论 bin 分辨率对照est_R - R通常能到 0.1m 以内est_v - v能到 0.1m/s 以内。如果误差超过这个量级先检查是否发生速度模糊或距离混叠。判断速度折叠的公式是v_fold mod(v vmax, 2*vmax) - vmax把目标真实速度代进去如果v_fold与估计速度一致说明发生了折叠。解决方法是缩小 Tc 或改用多普勒解模糊序列。5.3 三个容易踩的坑第一测距公式里的 S 用错。常用误写是f_b 2B*R/c少除了 Tc。这个公式只在 Tc1s 时成立一定要带完整表达式2B*R/(c*Tc)。第二距离维 FFT 和速度维 FFT 顺序颠倒。先做慢时间维再快时间维也能算出二维谱但物理意义会混乱。代码里应保持“先距离维后速度维”并在注释里写清楚维度含义。第三忽略了雷达距离方程下的幅度差。距离 10m 和 100m 的目标回波功率会相差 40dB即幅度差 100 倍。仿真里如果给所有目标相同幅度CFAR 结果会过于乐观。贴近实测时按(R_ref/R)^2对幅度加权再用窗函数的旁瓣电平判断哪些目标会被掩盖。把单目标参数替换成目标函数后多点场景本质上就是信号的线性叠加。这段基带仿真代码与 awr2243 等毫米波雷达前端输出的数字中频数据结构完全一致可以直接把仿真里的 2D-FFT 和 CFAR 代码迁移到实测数据上先手动挑一个强目标验证距离和速度再逐步放开检测门限。本文还有配套的精品资源点击获取