毫米波调频连续波 (FMCW) 雷达通过发射和检测射频 (RF) 电磁波来工作。由于其独特的特性,该技术为交互式系统和应用提供了多种优势。它不受光照条件、环境噪声或天气的影响,提供快速准确的传感能力。
此外,它可以穿透各种材料,非常适合集成到各种设备和环境中。该传感器可以构建为毫米波射频频率的小型固态半导体单元 - 本质上是雷达芯片。该芯片结构紧凑,功耗低,没有移动部件,并且可以以低成本大批量生产。
mmWave FMCW 雷达可用于许多设备,例如:
此外,毫米波 FMCW 雷达可以与深度学习模型一起使用来解决各种任务:
请注意,所有这些应用都可以在没有摄像头的情况下、使用非常低功耗的设备和相对较小的 NN 来解决。
未来几年,许多消费电子产品可能会开始积极使用这种带有深度学习算法的传感器来解决上述问题。此外,2021 年,IEEE 802.11ау Wi-Fi 标准获得批准。该标准使用相同的无线电频率和工作原理,使 Wi-Fi 路由器能够访问与 mmWave FMCW 雷达相同的功能。
本文和接下来的两篇文章将涵盖:
本文介绍了如何处理毫米波 FMCW 雷达信号。用于生成大多数图形的代码可在Google Colab中或文章末尾找到。
毫米波 FMCW 雷达的信号能够测量其视野范围内所有物体的距离、速度和角度位置(方位角和仰角)。雷达信号可以处理成非常小分辨率图像的形式(通常约为 32x32 - 256x64 像素),距离/速度/角度沿着图像轴,如下图所示 - 距离-多普勒(距离-速度)距离-角度图像。
传感器由多根(1根或多根)全向发射天线和多根(1根或多根)接收天线组成。发射和接收天线同时工作。雷达视场通常约为120°,最大距离可为几厘米至几十米。
我们通常需要在时间t1发射信号并在时间t2接收其反射来测量距离。然后可以计算距离为d=(t2-t1)*c ,其中c是光速,因为无线电波以光速传播。
FMCW 毫米波雷达天线是全向的,需要一种方法来测量雷达视野内所有物体的时间t1和t2 。为此使用 FMCW(调频连续波)信号。雷达的主要成分是啁啾。啁啾是一种正弦无线电信号,其频率随时间线性增加,如下图所示。
线性调频脉冲的特征在于起始频率 (f_start) 和终止频率 (f_end)、带宽 ( B=f_end-f_start ) 和线性调频脉冲时间 (Tc)。线性调频脉冲时间范围从几微秒到几毫秒。起始频率通常为 ~30、60 或 77GHz,具体取决于雷达应用。线性调频脉冲带宽范围从 ~0.5GHz 到几 GHz。
接收(Rx)和发射(Tx)天线同时工作。合成器连续产生一个啁啾,发送到发射天线Tx和混频器。同时,Rx天线接收到的信号也被馈送到混频器。混频器输出发送到Tx的信号与Rx接收到的信号之间的差值。
线性调频信号的频率随时间按照已知的线性规律(斜率)变化,这意味着,如果雷达前方有一个物体,该物体将产生一个信号x_out ,其
我们只需分析混频器发出的信号,无需测量时间,即可测量雷达视野范围内所有物体的距离: d=(F_obj*c)/(2*S)。在文献中, x_out信号被称为“IF 信号”(中频信号)。
传感器设计的另一个好处是:信号的载波频率通常在 30GHz 或 60Ghz 左右。如果我们需要数字化这种频率的信号,我们对 ADC 的要求会非常高。所有信号分析都是在 IF 信号上进行的,其频率通常在几 MHz 左右,这大大放宽了对 ADC 的要求。
如上所示,要找到雷达 FoV 中所有物体的距离,我们需要将信号x_out分解为其频率分量。傅里叶变换是一种将时域信号转换为频域的算法。
中频信号的傅里叶变换将显示多个音调,并且每个音调的频率与每个物体与雷达的距离成正比 - 在文献中,这种傅里叶变换也称为快速时间傅里叶变换或距离傅里叶变换。
问题:如果多个物体距离相同,我们就麻烦了,因为距离 FFT 无法让我们区分两个物体。但如果物体以不同的速度移动,则可以通过速度将它们分开。
线性调频信号通常会立即重复,或者略有延迟。在文献中,两个线性调频信号开始之间的时间称为线性调频信号重复时间。多个线性调频信号(通常为 16 到 256 个)堆叠在一起形成一个雷达帧。一帧时间 = 线性调频信号重复时间 * 线性调频信号数量。通常,1 帧的时间从几十微秒到几十毫秒。
为什么要将多个线性调频信号堆叠在一起?中频信号的相位对雷达视野范围内物体的微小和巨大振动非常敏感 - 它甚至可以用于测量发动机的振动频率或人或动物的心跳。
通过分析随时间变化的相位变化(从一个啁啾到另一个啁啾的相位变化),可以测量特定范围内物体的速度:
使用 mmWave FMCW 雷达测量速度的算法非常简单:
对帧中的每个 chirp 应用傅里叶变换。每个频率对应到物体的特定距离。有时,这些频率被称为范围箱,因为每个频率对应一个特定的范围
如果原始 IF 信号用非复数值表示,则根据奈奎斯特-香农定理,必须丢弃频率的后半部分(范围区间)
在每个距离箱上应用另一个傅里叶变换 - 将随时间变化的相位分解为频率,其中频率将对应于特定的多普勒(速度)值
问题:如果有两个物体以相同的速度在相同的距离内移动,它们将在距离多普勒图像中产生一个峰值。但如果我们有多个接收 Rx 天线,则可能可以通过它们的角度位置来区分物体
如前所述,距离的微小变化将导致相位变化。时间上分离的啁啾的相位变化可用于计算物体的速度。空间上分离的啁啾(由不同的 Rx 天线接收到的啁啾)的相位变化可用于角度估计。
多接收天线Rx的角度估计算法非常简单:
使用 Tx 天线发送一帧啁啾信号。
计算所有 Rx 天线接收到的帧的 2D 傅里叶变换(距离多普勒图像)。每个 Rx 天线的距离多普勒图像将在相同位置和多普勒处出现峰值,但相位不同(相位差对应于 Rx 天线之间的距离)。
使用相位差(ω)来估计物体的到达角 - 对所有 Rx 天线应用第三次傅里叶变换。
import os import numpy as np import scipy import scipy.io as spio import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec import math
从RAMP-CNN 项目下载毫米波 FMCW 雷达数据示例。
!pip uninstall gdown -y && pip install gdown !gdown -V !gdown --folder https://drive.google.com/drive/folders/1Eg-8R45RPvifNf2VYI_MG-LRjdkLOHTf -O /content/sample_slice_data
从文件加载数据。
file_name = '/content/sample_slice_data/2019_04_30/2019_04_30_pbms002/2019_04_30_pbms002_000000.mat' mat = spio.loadmat(file_name, squeeze_me=True) adc_data = np.asarray(mat["adc_data"]) print(adc_data.shape) # ADC samples, vRx, chirps - (128, 8, 255) print(adc_data.dtype) # complex128
可视化功能。
def show_one_chirp(one_chirp_data, y_label='amplitude', x_label='One chirp'): plt.figure(figsize=[5, 4]) plt.plot(one_chirp_data) plt.xlabel(x_label) plt.ylabel(y_label) plt.show() def show_image(image_data, image_name, x_label='', y_label=''): plt.imshow(image_data) plt.title(image_name) plt.xlabel(x_label) plt.ylabel(y_label) plt.show() def show_3_images(img_data1, img_data2, img_data3): plt.figure(figsize=(10, 8)) plt.subplot(2, 2, 1) plt.imshow(img_data1[0], aspect=1.44) plt.title(img_data1[1]) plt.xlabel(img_data1[2]) plt.ylabel(img_data1[3]) plt.subplot(2, 2, 2) plt.imshow(img_data2[0], aspect=1.0) plt.title(img_data2[1]) plt.xlabel(img_data2[2]) plt.ylabel(img_data2[3]) plt.subplot(2, 2, 3) plt.imshow(img_data3[0], aspect=1.0) plt.title(img_data3[1]) plt.xlabel(img_data3[2]) plt.ylabel(img_data3[3]) plt.show()
显示一个线性调频脉冲的 ADC 数据。
show_one_chirp(np.absolute(adc_data[:,0,0]), x_label='IF signal of a chirp')
在范围 fft 之后显示一个啁啾声。
chirp_fft = np.fft.fft(adc_data[:,0,0]) show_one_chirp(np.absolute(chirp_fft), x_label='IF signal amplitude (range)', y_label='Amplitude')
在时间和频率域中显示雷达框架。
# show all chirps show_one_chirp(np.absolute(adc_data[:,0,:]), x_label='IF signal of frame chirps') show_image(np.absolute(np.fft.fft(adc_data[:,:,:], axis=0).mean(1)), 'range FFT', x_label='Chirps', y_label='Range')
从雷达数据中获取距离、多普勒和角度。
def get_range_doppler_angle(adc_data_in): # adc_data_in - ADC samples, vRx, chirps samples_in = adc_data_in.shape[0] range_window = np.hamming(samples_in).reshape(-1,1,1) range_data = np.fft.fft(adc_data_in*range_window, samples_in, axis=0) # chirps_in = range_data.shape[2] doppler_window = np.hamming(chirps_in).reshape(1,1,-1) range_doppler_data = np.fft.fftshift(np.fft.fft(range_data*doppler_window, chirps_in, axis=2), axes=2) # # samples, vRx, chirps angle_window = np.hamming(range_doppler_data.shape[1]).reshape(1,-1,1) angle_bins=180 rda_data = np.fft.fftshift(np.fft.fft(range_doppler_data*angle_window, angle_bins, axis=1), axes=1) return range_data, range_doppler_data, rda_data
range_image, range_doppler_image, rda_cube = get_range_doppler_angle(adc_data)
show_3_images([np.absolute(range_image.mean(axis=1)), 'range doppler', 'Doppler', 'Range'], [np.absolute(rda_cube.mean(axis=2)), 'range angle', 'Angle', 'Range'], [np.absolute(rda_cube.mean(axis=0)), 'angle doppler', 'Doppler', 'Angle'] )
接下来的两篇文章将介绍: