【二】FMCW雷达距离检测的实现
注:这里的距离检测适用于FMCW雷达,而不是Pulse LFM雷达。
基本思路
FMCW雷达发射的扫频信号频率随时间线性上升。接收到的回波信号是发射信号在一段时间 之后的延迟信号。将发射信号与接收信号混频后,会产生一个频率恒定的中频信号,称为拍频 ()。而目标越远,回波延迟 越大,发射和接收信号之间的频率差 就越高 。因此通过检测 的大小即可得到距离。
去除直流偏置
假设已经得到了某个天线16×128的接收信号,令为变量mat。详情见英飞凌毫米波雷达接收数据的格式
avgs = np.average(mat,1).reshape(config.num_chirps,1)mat = mat - avgsFFT运算
加窗
由于FFT是有限长的,这会导致频谱泄露的情况,加窗可以压制旁瓣,虽然会稍微牺牲一点分辨率,但能更容易发现大目标旁边的微弱小目标。
在这里我们加的是Blackman-Harris 窗。
mat = np.multiply(mat,signal.windows.blackmanharris(config.chirp.num_samples).reshape(1,config.chirp.num_samples))TODO:不同窗函数的特性和应用场景?
补零
zp1 = np.pad(mat,((0,0),(0,config.chirp.num_samples)),'constant') # 补零在 samples维度末尾填充一倍长度的零。补零并不会提高雷达物理上的“分辨率”,但它增加了频率轴上的采样点密度,使 FFT 后的频谱图更加平滑,有助于更精确地定位反射峰值的中心。
执行FFT
range_fft = np.fft.fft(zp1)/config.chirp.num_samplesrange_fft = 2*range_fft[:,range(int(config.chirp.num_samples))]沿着快时间(Samples)轴进行 FFT,并只取前一半。为什么只取前面一半呢?
这是因为对于任何长度为 的实数序列 ,其离散傅里叶变换(DFT)结果 满足 由于BGT60TR13C 给出的是实数信号,因此根据上面的性质,经过FFT得到的频谱是中心对称的。后一半数据(负频率部分)是前一半的镜像,不包含额外信息,因此直接舍弃。乘以 2 是为了保持原始信号的振幅量级,补偿由于舍弃负频率带来的幅度损失。如下图所示。


计算谱图
range_fft_abs = abs(range_fft)distance_data = range_fft_abs.sum(axis=0)对FFT运算得到的距离谱图取模,在chirp维度将幅度求和,聚合能量,找峰值就可以得到谱(如上图图2所示)。
当然还有一步,就是将index转换为真实距离。公式如下:
其中为在这里为256(因为补了128个零,总共256点FFT)。根据本文的参数配置计算得到,也就是一格代表3.75cm。将坐标进行映射即可。在本实验中我们补零的数量等于,因此有,即
index_to_distance_cm = 3e8 * config.chirp.num_samples / (2 * bandwidth_hz * config.chirp.num_samples * 2) * 100 # in cmprint(f"index_to_distance_cm={index_to_distance_cm:.2f} cm")range_bins = np.arange(config.chirp.num_samples) * index_to_distance_cm寻找波峰
完成谱图构建后,最后就是找峰值作为波峰。在上面的图中我们发现有两个峰值,但实际上靠近0的波峰是一个伪峰,它属于直流泄露,大致是由于天线间耦合导致的。在这里我们暂时不深入探究它出现的原因和解决方案,我们直接屏蔽前8个index,在第9个index开始寻峰。
range_bins = np.arange(config.chirp.num_samples) * index_to_distance_cm # 映射坐标
skip = 8distance_peak = np.argmax(distance_data[skip:])distance_peak_cm = index_to_distance_cm * (distance_peak + skip)print(f"Distance Peak: {distance_peak_cm:.2f} cm") # Distance Peak: 37.50 cm至此,测距功能就完成了。
参考文献
Infineon RFS SDK Documentation Python Wrapper部分。
← Back to blog