雷达仿真这件事,我是从“跑通别人代码”开始踩坑的。私下练手时找了一段FMCW单发单收的MATLAB仿真,距离、速度都能测出来,但一加角度维度就发现整个体系乱掉了——TDMA-MIMO虚拟阵列该怎么合成、补偿什么时候该加、加了又会影响哪一维,这些根本不是看代码能看明白的。这篇文章就把我个人整理的一套FMCW TDMA-MIMO毫米波雷达信号处理仿真完整拆开讲,包含信号建模、距离-多普勒二维FFT、虚拟孔径合成时的相位补偿、角度估计、CFAR检测,以及最后怎么把TDMA架构改成DDMA架构。内容面向正在入门雷达仿真、想自己搭一套可控代码的读者,也适合已经从仿真转到实测、遇到通道相位问题的人回头对照。
1. FMCW TDMA-MIMO仿真到底在解决什么问题
1.1 为什么我建议先用TDMA-MIMO搭框架
很多雷达初学者是从单发单收FMCW开始的,发射一个chirp、接收一个通道,距离和多普勒都能通过两次FFT拿到。这时大家会误以为“FMCW雷达已经会了”,结果一接触MIMO就懵了:为什么要多个发射天线轮换发射?为什么通道数不是简单的发射数加接收数?角度估计为什么非要在一堆复数数据上再做一次FFT?
我的建议是,无论你最后要用DDMA还是更复杂的波形,都先花两周时间把TDMA-MIMO仿真跑通。理由很现实:TDMA(时分复用)是原理上最容易理解的MIMO实现方式,多个发射天线之间只是轮流工作,不存在同时同频干扰问题,接收端按时间片就能区分信号来自哪个发射天线。这个特性让虚拟阵列合成的链路非常干净,方便把注意力集中在相位关系、多普勒补偿和阵列信号处理这些核心问题上。
而且仿真框架搭好之后,后面换DDMA、换BPM-MIMO,都只是在同一个数据流上改波形配置和分离逻辑,不会推倒重来。我见过太多人一上来就追求复杂的DDMA方案,最后连“FDMA频偏在距离维错开”都没理解透,把问题越搞越乱。先TDMA后DDMA,是投入产出比最高的路线。
另外,TDMA-MIMO还有一层价值:它迫使你把“时分导致的慢时间采样率变化”想明白。这个坑在单发单收里完全不存在,但在实际雷达工程里特别常见。如果你连仿真里的多普勒模糊和相位补偿都搞不定,上了硬件只会更难受。
1.2 一套完整的毫米波雷达仿真包括哪几件事
我通常把一套完整的FMCW MIMO雷达仿真分成下面几个模块,每个模块在代码里都有清晰的输入输出边界:
- 参数设计与信号建模:确定载频、带宽、chirp时长、采样率、PRI等参数,生成带目标信息的差拍中频信号。
- 距离维FFT:对每个chirp做快时间维FFT,把中频频率换算成距离。
- 多普勒维FFT:对同一距离单元里的慢时间序列做FFT,提取目标速度。
- MIMO虚拟阵列合成:把多发射多接收通道映射成虚拟阵元,完成相位补偿。
- 角度维FFT或数字波束形成:利用虚拟阵列的孔径估计目标角度。
- CFAR检测与点迹解算:在距离-多普勒谱或距离-角度谱上检测目标,并换算成物理坐标。
这套流程里的顺序不是可以随意调整的。TDMA-MIMO的相位补偿必须放在多普勒处理之后、角度估计之前;CFAR如果放在角度估计之后,计算量会成倍增长;而点迹解算是整个流水线的收口。项目标题里提到的“4D毫米波雷达”,本质上就是把角度维拆成方位和俯仰两个维度,数据流仍然和上面高度一致,只是在虚拟阵列排布上从一维线阵改成二维面阵。
1.3 这份仿真适合谁,不适合谁
如果你的目标是把这套框架当作自己项目的基础,那么这份内容适合三类人:一是刚入门需要一份能跑起来、且每一步都知道在做什么的雷达仿真;二是已经做嵌入式或射频硬件,想补清信号处理原理的开发;三是准备把算法移植到嵌入式平台,需要先用MATLAB验证算法的工程师。
不适合的情况也明确说:如果你只是想用现成雷达开发套件快速出点云,不需要理解底层,那这份仿真对你来说是过度的。另外如果你做的是超远距雷达(几百公里量级),这套近距离参数和流程只能作为参考,系统设计逻辑不变但细节差很多。我写的参数接近车载中近距离雷达场景,具体使用时请按自己的需求重算。
2. 信号模型和雷达参数:先自己算清楚再写代码
2.1 FMCW差拍信号模型,一句话说透
FMCW雷达发射的是频率线性变化的连续波,目标回波和本振信号混频后得到一个差拍中频信号。设发射信号调频斜率为S,目标距离为R,那么回波延时τ=2R/c,混频后中频信号的频率近似为:
- f_b = S·τ = 2SR/c
也就是说,中频频率和目标距离成正比,测出f_b就等于测出了距离。同时,中频信号的相位中还携带着目标的微细距离信息:φ = 2π·f_c·τ = 4πR/λ。目标运动时,R在慢时间维度上逐chirp变化,这个相位就会以多普勒频率fd=2v/λ旋转。所以FMCW的信号模型本质上就是一个“快时间做测距、慢时间做测速”的二维相位编码系统。
理解这一句话就够用了。剩下的所有算法,包括距离FFT、多普勒FFT、角度FFT,都是在不同的维度上对这个相位做傅里叶变换,把隐藏在复数相位里的目标参数提取出来。
2.2 我常用的这组参数,以及每个数字怎么来的
写仿真最忌讳的是参数拍脑袋。下面是我个人常用的一组近距离雷达参数,以及每个参数的计算依据。
| 参数 | 数值 | 计算依据与说明 |
|---|---|---|
| 载频 fc | 77 GHz | 车载毫米波雷达常用频段,波长 λ≈3.9mm |
| 带宽 B | 500 MHz | 距离分辨率 ΔR = c/(2B) = 0.3m |
| chirp时长 Tc | 50 us | 决定PRI和最大中频带宽 |
| 调频斜率 S | 10 GHz/us | S = B/Tc = 500MHz/50us = 1e13 Hz/s |
| 采样率 fs | 20 MHz | 差拍中频最高不超过fs/2,留足余量 |
| PRI | 100 us | Tc + 空闲时间,用于切换和波形隔离 |
| 每帧chirp数 | 128 | 其中2个TX各占64个chirp,多普勒FFT点数64 |
| 快时间采样点数 | 1000 | Ns = fs·Tc = 20MHz × 50us |
| 距离FFT点数 | 1024 | 补零到1024,提高频谱插值密度 |
用这组参数算一下关键指标:
- 最大不模糊距离:R_max = c·fs/(2S) = 3e8 × 20e6 / (2×1e13) = 150m。实际近距场景30m以内足够,所以采样率余量很大。
- 速度分辨率:Δv = λ/(2·T_frame) = 3.9mm / (2×12.8ms) ≈ 0.15m/s。这个分辨率在行人检测场景够用。
- 最大不模糊速度(单TX模式):v_max = λ/(4·PRI) = 3.9mm/(4×100us) ≈ 9.7m/s。
看到最后一个数字,懂行的人已经意识到问题了:TDMA-MIMO下,单个发射天线的实际慢时间采样间隔是2·PRI,也就是200us,所以最大不模糊速度会掉到约4.9m/s。这在车载场景下明显不够。这就是我后面要专门讲的“TDMA多普勒代价”。你在仿真里千万别只看单TX理论速度上限,那会给你一个虚假的安全感。
2.3 开始写代码前必须知道的几个换算陷阱
第一个陷阱是“距离FFT的bin间隔到底是多少”。如果不补零,频率分辨率是fs/Ns = 20MHz/1000 = 20kHz,对应距离间隔是ΔR_freq = Δf·c/(2S) = 20kHz×3e8/(2×1e13) = 0.3m,正好等于距离分辨率c/(2B)。如果你补零到1024点,距离bin间隔会变成0.292m左右,谱更平滑但独立信息没变多。这个区别在CFAR选参考单元时会影响性能,因为参考单元应该按独立分辨率元来选,而不是按补零后的bin来选。
第二个陷阱是速度和多普勒频率的符号。目标靠近时回波延时减小,多普勒频率为正还是为负,不同教材定义可能不同。我自己吃过亏:在某次仿真里速度符号写反了,结果角度谱完全不对,排查了一下午最后发现是符号问题。建议在代码里固定约定:靠近为正多普勒频率,并在生成回波时和提取时保持一致。
第三个陷阱是快时间内的距离走动。低速目标在一个chirp内位移极小,可以忽略;但高速目标或长chirp时长下,τ会随快时间变化,导致差拍信号产生一个额外的二次相位项。在仿真里如果不加处理,高速目标的距离峰会展宽。这个在MATLAB信号仿真里属于“你不知道它存在就不会出错、知道了就一定要处理”的问题。先记着这个概念,后面在真实目标中才不会被奇怪的谱峰形状困惑。
3. 从单chirp到距离-多普勒二维谱:数据流和MATLAB实现
3.1 数据立方体怎么摆,决定后面所有处理好不好写
我在写代码时,把接收数据统一组织成一个三维数组:
- 维度1:快时间采样点,长度Ns(每个chirp内采样点序号)
- 维度2:chirp序号,长度N_Chirp(一帧内的chirp个数)
- 维度3:接收通道序号,长度N_RX
TDMA模式下还需要额外记住每个chirp对应哪个发射通道。在仿真里可以直接根据chirp序号算:mod(chirp_idx-1, N_TX)+1。这样后续做虚拟阵列时,可以把“第m个chirp、第rx个接收通道”映射成虚拟阵元索引。
这里我建议不要把TDMA的TX维度和RX维度混在一个数组里管理,否则后面多普勒补偿和角度估计的代码会很乱。我的做法是先生成原始三维数据,处理到距离-多普勒域后,再按“虚拟阵元索引”把数据重排。这样每一层的物理含义非常清楚,调试时打出来的变量一眼能看懂。
3.2 Range FFT和Doppler FFT的完整实现
生成回波信号的简化MATLAB代码大概长这样:
fc = 77e9; B = 500e6; Tc = 50e-6; S = B/Tc; fs = 20e6; Ns = round(fs * Tc); PRI = 100e-6; N_Chirp = 128; N_RX = 4; N_TX = 2; c = 3e8; % 目标参数:距离10m,速度3m/s,角度15度 R0 = 10; v0 = 3; theta0 = 15*pi/180; t_fast = (0:Ns-1).' / fs; s_if = zeros(Ns, N_Chirp, N_RX); for m = 1:N_Chirp tx_idx = mod(m-1, N_TX) + 1; % TDMA切换 R_m = R0 + v0 * ((m-1) * PRI); % 慢时间距离近似 tau_m = 2 * R_m / c; for rx = 1:N_RX phase = 2 * pi * (S * tau_m * t_fast + fc * tau_m); % 角度相位:虚拟阵元位置带来的波程差 phase_ang = 2 * pi * (rx-1) * 0.5 * sin(theta0); % 简化示意 s_if(:, m, rx) = exp(1j * (phase + phase_ang)); end end得到中频信号后,距离维FFT和多普勒维FFT的处理如下:
N_FFT_r = 1024; N_FFT_d = 128; win_r = hamming(Ns); win_d = hamming(N_Chirp); S_range = fft(s_if .* win_r, N_FFT_r, 1); % 距离维 S_rd = fft(S_range .* win_d, N_FFT_d, 2); % 多普勒维 S_rd = fftshift(S_rd, 2); % 把零多普勒移到中心这几行代码跑完之后,S_rd就是距离-多普勒二维谱。我要提醒一下:加窗是有代价的,Hamming窗会把距离主瓣展宽约1.4倍,但能压低旁瓣。如果你仿真里有两个距离很近、幅度差异很大的目标,没有窗函数时弱目标会被强目标的旁瓣淹没。窗函数的选择永远是在主瓣宽度和旁瓣抑制之间做权衡,别默认“加了窗就一定好”。
3.3 从RD谱坐标反推目标物理量
假设你在S_rd里找到峰值在(rb, db)位置,换算成物理量时用以下公式:
距离:R = rb × c/(2B) × (Ns/N_FFT_r),未补零时就是 rb × 0.3m。
速度:先算多普勒索引对应的频率偏移,再除以2/λ:
v = (db - N_FFT_d/2) × PRI_freq / (2/λ)
其中多普勒频率分辨率fd_res = 1/(N_FFT_d·PRI),速度分辨率就是vd_res = λ·fd_res/2 = λ/(2·N_FFT_d·PRI)。用我们的参数算出来约0.15m/s,和前面手算一致。
我在初学阶段经常犯一个错:把多普勒FFT点数直接等于chirp数,忘了自己做过fftshift。fftshift之后索引从0到N_FFT_d-1的映射关系变了,速度可能直接差一个符号。建议写成显式函数来换算,不要在CFAR代码里裸奔。
这里顺便说一句,RD谱上不仅有目标峰,还有两个常见干扰源:零多普勒通道的静止杂波,以及距离维DC分量。仿真里常常能看到目标距离轴附近出现一条亮线,这是本振泄漏和静态目标耦合到零频的结果。一般做法是在多普勒FFT之前做慢时间均值相减(也就是MTI高通滤波),或者直接用DC陷波。这些在实际工程里是必做的,仿真里建议至少加一个开关,方便观察加与不加的区别。
4. TDMA-MIMO虚拟孔径合成:相位补偿是最大翻车点
4.1 2发4收怎么变成8个虚拟阵元
MIMO虚拟阵列的核心逻辑是:发射天线和接收天线之间的双程波程差,可以等价成一个“虚拟接收阵列”里的单程波程差。比如2发4收,发射天线间距d_tx = 4×(λ/2)(按常规设计),接收天线间距d_rx = λ/2,那么收发组合会产生8个等效相位中心。这些相位中心如果排成均匀线阵,等效于8个虚拟阵元,间距λ/2。
分离度取决于天线布局设计。如果发射天线与接收天线构成线性卷积关系,虚拟阵元就是均匀的;如果布局不好,虚拟阵元会重叠或出现空洞,角度估计性能下降甚至出现鬼影。仿真里大多数人都直接假设理想的均匀虚拟线阵,这在验证算法阶段没问题,但到了真实雷达设计阶段,天线布局的非理想性必须进仿真。
在代码层面,我通常直接建立一个虚拟阵元坐标数组:
- TX1对应的虚拟通道索引:1~4
- TX2对应的虚拟通道索引:5~8
并在角度估计前把RD谱按这个顺序重组。
4.2 TDMA引入的多普勒相位污染到底有多严重
TDMA模式下,不同发射天线在时间上是错开的。假设TX1在t=0时刻发第一个chirp,TX2在t=PRI时刻才发它的第一个chirp。对同一个运动目标来说,多普勒相位会随时间变化。于是同样一个目标,在TX2的chirp里会比TX1多出一段相位:
- Δφ = 2π·fd·PRI
其中fd=2v/λ是多普勒频率。
这意味着什么?如果你直接把8个虚拟通道的快照拼起来做角度FFT,通道之间的相位不仅包含目标角度带来的波程差,还叠加了目标运动带来的多普勒相位差。目标速度越快,角度谱峰值偏移越大,甚至会出现假峰。
我用仿真做过一个直观对比:目标设置在15度方向、速度3m/s,不做补偿时角度FFT峰值大概会偏到10度左右,旁瓣也被抬高。如果速度继续增大,角谱会完全乱掉。这个现象在单发单收里根本不存在,所以很多人第一次遇到会完全摸不着头脑——等你把相位补偿加上去,谱峰又干净了。
4.3 相位补偿的两种路线,以及我推荐哪一种
路线A:在多普勒FFT之前,先在慢时间维上对TX2的数据做延时对齐。具体做法是把TX2的慢时间序列插值到与TX1对齐的时间网格,或乘以exp(-j·2π·fd·PRI)的估计值。这个方案对fd的估计精度要求高,而且插值会引入额外误差,我不太推荐作为最初的实现。
路线B:先把所有数据都做完距离维FFT和多普勒FFT,得到一个完整的距离-多普勒域数据立方体,然后在距离-多普勒域对TX2对应的虚拟通道进行复数乘法补偿。因为这时每个bin的多普勒频率是已知的(由bin索引决定),补偿相位量可以直接算出来:
fd_axis = (-N_FFT_d/2 : N_FFT_d/2 - 1) / N_FFT_d / PRI; comp = exp(-1j * 2 * pi * fd_axis * PRI); % 假设S_rd_mimo是 [N_FFT_r, N_FFT_d, 8],前4通道是TX1,后4个是TX2 for vch = 5:8 S_rd_mimo(:, :, vch) = S_rd_mimo(:, :, vch) .* comp; % 自动广播到所有距离bin end注意上面代码里fd_axis的顺序要与fftshift后的多普勒轴一致,这是最容易出错的地方。我建议先打印一下comp的虚部/实部对照,确认在正值多普勒处是负相位旋转。
路线B的好处是逻辑清晰、计算开销小、不容易引入插值误差。缺点是它要求多普勒FFT里不出现速度模糊,或者至少目标在无模糊速度范围内。如果目标速度超出最大不模糊速度,多普勒频率会折叠,comp就补偿错了。实际工程里会在系统层面用波形设计保证目标不模糊,或者配合解模糊算法。
4.4 怎么验证补偿做对了
验证方法不是看CFAR结果,而是直接看虚拟阵列快照的相位连续性。具体做法:用点目标仿真,设置目标在0度方向且固定不动,那么理论上所有8个虚拟通道的复数值应该完全相等(相位差为0)。一旦加入速度和角度,补偿后各通道之间的相位差应该严格满足:
- Δφ = 2π·d·sin(θ)/λ
其中d是相邻虚拟阵元间距。你可以把补偿后的8个复数相位画成极坐标图或直接打印出来,和理论值对照。差在0.1弧度以内说明补偿链路是对的。
这个验证步骤虽然简单,但真的能省掉后面无数奇奇怪怪的问题。我在做DDMA改造时也沿用了这个方法,效果很好。以后你们做别的MIMO波形,也建议保留这个“标准点目标校验”脚本。
5. 角度维FFT与CFAR检测:把目标从谱峰变成可用的点迹
5.1 角度FFT:在虚拟阵列上做什么、怎么做
角度估计的原理在仿真里可以这样理解:8个虚拟阵元接收到同一目标的回波,因为阵元位置不同,波程差导致每个阵元的复信号相位不同。这个相位差和角度直接相关。对8个通道做FFT,本质上就是做一次空间匹配滤波,峰值对应的bin就是目标角度。
用我们的参数,虚拟阵元数N=8、阵元间距d=λ/2,理论上能分辨的角度约为:
- θ_res ≈ 0.886λ/(N·d·cosθ) ≈ 12.7°(θ=0时)
注意这是在单个快照、无窗、高信噪比下的理论值。实际里加窗、有限快照、通道幅相误差都会让角度分辨率变差。仿真里如果要做更精细的角度分辨,不能只靠增加FFT点数(那只是插值,不增加真实分辨率),而要增加虚拟阵元数量,也就是增加发射或接收通道数。
在MATLAB里对某个检测单元做角度FFT的代码:
snapshot = squeeze(S_rd_mimo(R_bin, D_bin, :)); % 8x1 theta_fft = fftshift(fft(snapshot, 256)); % 补零到256点看谱形 angle_axis = asin((-128:127)/256 * 2) * 180/pi; % 对应角度轴更进阶的算法是Capon或MUSIC,它们在多目标且阵元数充足时可以突破瑞利限。但MIMO雷达里通道数往往不够多,且RD谱上多目标可能落在同一个距离-多普勒单元,这时超分辨算法才有用武之地。仿真阶段建议先把FFT的角度结果吃透,再往上加复杂算法。
5.2 先把CFAR放在哪个域里做,后面会省很多事
CFAR检测有两种常见做法:
第一种是在距离-多普勒谱上做二维CFAR,检测到目标后再针对每个目标做角度估计。优点是计算量小,因为角度FFT只需要对检测点做;缺点是如果在同一个距离-多普勒单元里有两个不同角度的目标,它们会叠在一起,CFAR也只能检测到一个目标,角度估计会被两个目标的矢量合成带偏。
第二种是先在距离维做CFAR,然后在每个检测距离上做“距离-角度谱”或“角度-多普勒谱”的CFAR。这种方法更接近4D雷达的实际处理,因为4D点云需要在距离、速度、方位、俯仰四个维度上定位目标。缺点是计算量大,内存占用高。
我自己的建议是:仿真教学阶段用第一种,简单清晰,风险可控;做项目阶段至少过渡到“距离维CFAR + 角度维CFAR”的级联方式,才能处理多目标场景。CFAR的实现核心是滑窗统计,下面给个二维CFAR的框架:
function det_map = cfar2d(rd_map, guard_r, ref_r, guard_d, ref_d, alpha) % guard_r/ref_r: 距离维保护单元和参考单元 % guard_d/ref_d: 多普勒维保护单元和参考单元 % alpha: 门限因子 [Nr, Nd] = size(rd_map); det_map = zeros(Nr, Nd); for rr = 1+guard_r+ref_r : Nr-guard_r-ref_r for dd = 1+guard_d+ref_d : Nd-guard_d-ref_d % 取参考窗 win = rd_map(rr-ref_r-guard_r:rr+ref_r+guard_r, ... dd-ref_d-guard_d:dd+ref_d+guard_d); % 剔除保护区域 win(guard_r+1:end-guard_r, guard_d+1:end-guard_d) = 0; noise = mean(abs(win(:))); det_map(rr, dd) = abs(rd_map(rr,dd)) > alpha * noise; end end这个双重循环跑起来很慢,实际MATLAB里可以矩阵化或分块处理。但更重要的是理解保护单元的作用:目标主瓣可能会展宽到相邻几个bin,如果不设保护单元,目标自身的能量会被算进噪声均值,把门限抬得过高,导致目标检测不出来。这也是CFAR调参最容易踩的坑。
5.3 换成物理坐标:距离、速度、角度的解算
当CFAR检测到目标后,把索引换算成物理量是整个仿真里最“枯燥但绝不能错”的部分。常踩的坑有这么几个:
- 距离索引没乘窗函数带来的幅度损失补偿。补零FFT不影响峰值位置,但距离FFT点数变化会改变频率轴刻度,建议用统一函数换算。
- 速度索引因为fftshift的原因,0速在中心,正负半轴分别表示靠近和远离。码代码时注意偏置量。
- 角度索引通过asin函数转换时,如果谱峰出现在边缘,说明目标可能超过了阵列不模糊角度范围。8阵元、λ/2间距的不模糊范围为±90度,理论够用,但实际仿真里如果天线间距超过λ/2,就会出栅瓣,需要格外小心。
我倾向于把这三个换算写成一个函数:
function [R, v, theta] = bin2phys(rb, db, ang_bin, ... B, Ns, N_FFT_r, lambda, N_D, PRI, N_FFT_a) R = rb * c / (2 * B) * (Ns / N_FFT_r); v = (db - N_D/2) * lambda / (2 * N_D * PRI); theta = asin((ang_bin - N_FFT_a/2) / (N_FFT_a/2)) * 180 / pi;这样做整个数据流非常清晰。我在做多目标场景时,就直接对每个检测单元调用这个函数,很快就能得到点云。
6. 把TDMA改成DDMA:几处关键改动背后是同一套闭环逻辑
6.1 DDMA本质就是给每个发射天线贴一张“频率标签”
DDMA(多普勒频分多址)的思路和TDMA完全不同:所有发射天线同时工作,但每个发射天线发射的chirp在起始频率上有不同的偏移。接收端混频后,不同发射天线对应的差拍信号会落在不同的中频位置上,相当于在距离维上“错开”,因此可以按频率区间把各发射天线的回波分离开。
用FDMA这个思路实现MIMO,最大的收益是发射效率高。TDMA模式下任意时刻只有一个发射机工作,发射功率利用率天然受限;DDMA则可以同时开多个通道,等效辐射功率更高。另外DDMA模式对“时分造成慢时间采样率减半”的问题有一定缓解,代价是引入了新的频率-距离耦合和多普勒模糊问题。
做一个直观的类比:TDMA像是一家餐厅只有一个厨师,几个灶台轮流炒菜;DDMA像好几个厨师同时开火,但每位厨师用了不同颜色的围裙,上菜后按围裙颜色区分菜是哪个厨师做的。听起来很美好,但问题是“围裙颜色”会让盘子里的菜自带多余的调味料,后面得专门去除。
6.2 频偏间隔怎么选,这里有一个必须算的折中
DDMA频偏的选择直接决定系统性能。设距离FFT点数为N_FFT_r,采样率为fs,则一个距离bin对应的频率宽度为:
- Δf_bin = fs / N_FFT_r
为了让不同发射天线的回波在距离维上可分,频偏至少取几个bin的宽度。我常用的默认值是:
- Δf_DD = 4 × Δf_bin
用前面的参数算:Δf_bin = 20MHz/1024 ≈ 19.5kHz,4个bin就是约78kHz。这个频偏带来的距离偏移为:
- ΔR_off = c·Δf_DD/(2S) = 3e8×78e3/(2×1e13) ≈ 1.17m
也就是说,TX2的所有目标在距离维上会比TX1多出约1.17m的偏移,相当于4个距离bin。分离时按频段切分,再把这个偏移搬回去,就能把两个TX的数据对齐到同一距离网格。
频偏不是越大越好。选大了,不同TX的回波在距离上错开更多,更容易分离,但会占用更多中频带宽,压缩最大可测距离;选小了,分离度不够,强目标旁瓣会跨到其他TX的频率区间,形成串扰。实际设计里通常要求:
- 系统最高中频 + Δf_DD 仍小于 fs/2
比如目标在30m处,差拍频率约2MHz,加78kHz后也就2.1MHz,余量还很足。如果目标在100m处,差拍频率约6.7MHz,加78kHz后仍低于10MHz,也还能接受。所以这个参数组合的余量是够的,但当你加大带宽或采样率时,一定要重算这个不等式。
6.3 让人头疼的多普勒模糊,以及一种实用解法
DDMA的麻烦在于:频偏不仅让目标在距离维上错开,它还会在慢时间维上产生一个附加相位,影响到多普勒估计。如果你每个chirp都保持同一个频偏,那么不同发射天线的回波在多普勒维里会自带一个固定的频移,这个频移和目标的真实多普勒混在一起,很难分辨。
工程上常用的一种解法是“双chirp频偏交替”:第奇数个chirp,TX2使用+Δf_DD;第偶数个chirp,TX2使用-Δf_DD。这样,TX2的相邻两个慢时间样本之间的相位差里,包含了两倍频偏产生的已知相位,也包含目标多普勒产生的未知相位。利用相邻chirp的差分相位,可以把目标的真实多普勒解出来。
具体实现上,要在信号生成时对TX2加上变化的频偏:
for m = 1:N_Chirp if mod(m, 2) == 1 f_off = +df_dd; else f_off = -df_dd; end % 在差拍信号的相位中额外加入 -2*pi*f_off*t 的项 end接收端先按距离区间分离TX1和TX2,再做多普勒FFT,然后对TX2的相邻chirp做相位差分估计速度。这个过程比TDMA的补偿多绕一步,但换来的是所有发射天线全时工作,慢时间采样率不再减半,最大不模糊速度通常可以恢复到与单发模式相当的水平。
需要说明的是,双chirp方案只是DDMA的一种常见实现,业界还有更复杂的四chirp组合、随机变频等方案。仿真阶段先把双chirp方案吃透,后面理解其他方案会快很多。
6.4 TDMA和DDMA怎么选,我给的一张对比表
| 维度 | TDMA-MIMO | DDMA-MIMO |
|---|---|---|
| 发射方式 | 分时轮换 | 同时发射、频率错开 |
| 实现难易 | 简单直观 | 中等,频偏设计有讲究 |
| 发射功率利用率 | 低(单时刻单通道) | 高(多通道同时) |
| 慢时间采样率 | 每TX减半 | 不减半,但有多普勒模糊耦合 |
| 信号分离方式 | 按时序区分 | 按距离FFT频段区分 |
| 最常踩的坑 | 多普勒相位补偿 | 频偏选择和多普勒解模糊 |
| 仿真阶段推荐度 | 强烈推荐先做 | 在TDMA跑通后再改造 |
我个人在项目中的体会是,TDMA适合作为算法验证和教学的基础方案;DDMA适合要真正上板子、追求发射效率和最大不模糊速度的场景。但是DDMA的工程坑比TDMA深得多,如果你还没把补偿流程练熟,不要贸然上DDMA。
7. 仿真和实测之间的几个非理想因素,提前给自己打预防针
7.1 通道幅相不一致:角度估计的头号隐形杀手
仿真里每个通道的幅度和相位都是理想均匀的,但真实接收通道之间存在幅相偏差。天线增益不同、射频链路的滤波和放大不完全一致、PCB布线长度差异、ADC通道校准误差,都会导致各虚拟通道的复增益不一样。后果是:即使目标在0度方向,角度FFT也会因为通道相位偏差而出现谱峰偏移,幅度偏差则会抬高旁瓣。
在仿真里提前演练这个问题很简单,只要在生成回波时给每个通道乘一个复常数。比如:
gain_err = 1 + 0.1 * randn(N_vch, 1); phase_err = exp(1j * 0.05 * randn(N_vch, 1)); snapshot = snapshot .* gain_err .* phase_err;做完之后你很快就会看到角度谱变差。真实雷达系统里,需要用内定标源或向日葵法做通道校正。仿真阶段明白这个影响有多大,比实测时硬着头皮调参有效得多。
7.2 本振泄漏、量化饱和和CFAR门限之间的博弈
毫米波雷达前端的本振泄漏会在混频输出中形成直流分量,表现为RD谱上零距离、零多普勒附近的高能量。这个泄漏在近距离高灵敏度场景会严重影响CFAR门限,因为CFAR参考窗一旦包含这些强分量,门限就会被抬高,导致附近真实目标被漏检。
仿真里至少要做两件事:一是模拟一个静止目标和DC泄漏,看CFAR在低速、近距离场景的表现;二是练习零多普勒陷波或均值对消的工程手段。ADC量化同样不能忽略。如果直接用浮点仿真,等于自动回避了ADC位宽问题。我建议在仿真中加上一个简单的定点化或量化函数,比如把信号量化到位宽12bit,观察谱噪底的变化。位宽不够时,远距离弱小目标会直接被量化噪声淹没。
7.3 用仿真提前演练多径和镜像目标
多径是近距离雷达绕不开的话题。车辆、墙壁、护栏反射会让雷达看到一个“镜像目标”,其角度往往和真实目标对称或出现在不期望的位置。多径产生的虚假点在CFAR检测里很可能形成稳定点迹,单帧仿真看不出问题,多帧关联后才会发现目标轨迹跳变。
在仿真里加多径的方式是:在回波信号里再叠加一个幅度较低、距离略大、角度经过墙面反射的目标。然后观察CFAR输出能否把真实目标和镜像目标区分开。实际工程里最终要靠多帧关联、速度一致性检验和RCS差异来滤除虚假点,但在仿真阶段积累“哪些特征是虚假点”的经验,对后面做点云后处理非常有帮助。
这里分享一个我自己实际操作的体会:仿真做得好的人,不是因为他把信道模型做得多么逼真,而是他时刻清楚每一个非理想因素加进去之后,会给哪一步处理带来什么后果。所以每加一个非理想因素,就盯着RD谱和角度谱看一遍,对照它出现的位置和形态,这比跑一百次端到端仿真的收获都大。
最后多说一句小经验。无论是TDMA还是DDMA,我在每次跑完仿真后都不会直接看CFAR结果,而是先把距离-多普勒谱和角度谱画出来目测一遍。图像不容易骗人,看到异常谱峰往往比看指标更早发现问题。这个习惯我从做仿真一直保持到现在,帮我在项目里省下了大量排查时间。