ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

便携式FMCW雷达信号处理平台PLFM_RADAR:从硬件到算法全链路解析

便携式FMCW雷达信号处理平台PLFM_RADAR:从硬件到算法全链路解析

PLFM_RADAR 这个项目,是我过去大半年断断续续搭起来的一套便携式雷达信号采集与处理平台。PLFM 是我自己给项目起的内部代号,全称是 Portable Lab Field Module,直译过来就是"便携实验室外场模块";RADAR 就不用多解释了,整套东西的核心确实是雷达——严格来说,是一台以调频连续波(FMCW)体制为主的软件定义雷达。

这个平台能做的事,简单说就是:把雷达的发射、接收、中频采集、距离/速度解算、目标检测全部从零开始打通,并封装成一套可带到外场快速部署的实验系统。它不是某个厂商的现成评估板,而是从天线、射频前端、ADC采集中频,再到 PC 上的距离-多普勒处理链路,每一环都自己选型、自己接线、自己写算法的那一类"慢工出细活"项目。适合正在做雷达相关课题的研究生、打算从嵌入式或信号处理方向切入雷达领域的工程师,以及想给学生做真实信号处理演示的高校老师参考。即使你之前没碰过雷达,只要懂基本的傅里叶变换概念,这套文章的链路拆解也能帮你建立起"雷达数据到底是怎么变成目标点迹"的完整认知。

1. 项目定位:PLFM_RADAR 到底是一台什么样的雷达

1.1 从命名说起:为什么叫 PLFM,为什么非要加上 RADAR

PLFM 这个名字并不是一开始就想好的。项目早期我只是在工位上用一台二手频谱仪和一个信号源拼凑"能出多普勒频移"的验证装置,后来发现实验一出实验室就崩,笔记本供电不稳、天线支架一碰就晃、线缆接口接触不良……于是我才意识到,我需要的是一个能"背着走"的模块化平台。PLFM 就这么来的:Portable 表示整套系统可以在一个 40cm×30cm×20cm 的箱子里面装下;Lab 表示它的核心场景是实验验证而不是量产;Field 是最重要的一条,所有模块的电源、接口、固定方式都得为外场折腾设计;Module 则强调射频前端、中频采集、信号处理可以拆开替换。

加上 RADAR 后缀,是为了让项目定位足够明确。市面上叫 Platform、叫 Module 的项目太多了,但真正围绕"雷达信号全链路"展开的并不多。PLFM_RADAR 强调的不只是硬件平台,而是从天线口面的射频信号一路处理到目标距离、速度数据的完整系统。雷达和通信虽然共用很多射频技术,但处理思路差异非常大:通信关注的是解调误码率,雷达关注的是"回波里的目标在哪个距离单元、哪个多普勒单元"。所以这个项目从第一天起就锚定 RADAR,不往软件无线电通信方向跑偏。

1.2 这个平台能做什么:三个典型应用场景

我实际拿 PLFM_RADAR 做过三类实验,也都跑通了。第一类是室内人员感知。把雷达架在房间角落,发射功率开得很低,可以检测到人在房间内的存在与大致位置,距离精度在 0.2 米上下。这其实已经是智能家居、养老监护领域非常常见的需求,只是我用自研链路复现了一遍,不是为了产品化,而是为了搞清楚每一级处理到底在干什么。

第二类是走廊/园区场景的移动目标监测。人可以,自行车也可以,距离在 5~30 米范围。FMCW 体制天然支持同时测距测速,所以在距离-多普勒图上,走动的行人会呈现出一个明显的"亮点",跑动的目标亮点会沿多普勒轴偏移。这个场景很适合验证速度解算、恒虚警检测(CFAR)和轨迹连续性。

第三类是教学演示。我把 AD 采集后的原始数据用脚本存成 npz 文件,课堂上可以直接加载、逐级做 FFT、画距离像,学生能看到"从时域波形到距离峰、再到距离-多普勒图"的全过程。很多学生第一次直观理解"雷达并不是直接看到目标,而是通过频率变化反推目标信息",靠的就是这种可视化的数据链路演示。

1.3 适合谁参考,需要什么基础

这个项目的完整复现门槛不低,但参考价值覆盖面很广。如果你是信号处理方向的工程师,可以重点看第 3 章的算法链路,直接在自己的数据上验证;如果你是射频工程师,可以重点看第 2 章的链路预算和硬件选型,理解中频规划为什么和 ADC 采样率强相关;如果你只是学生、刚接触雷达,我建议你从第 3.1 节的测距测速原理开始读,把公式吃透后再倒回去看硬件,就不会被一堆名词吓住。

基础知识方面,需要懂复数的概念、傅里叶变换的基本性质,以及一点 Python 编程。射频知识反而不是必需的,因为 FMCW 雷达的射频部分可以当"黑盒"来用,只要搞清楚输入输出接口和增益关系就能起步。

2. 系统总体设计与硬件选型逻辑

2.1 雷达体制选择:为什么是 FMCW,而不是脉冲或连续波多普勒

做雷达系统,第一个要拍板的事情就是体制。脉冲雷达虽然测距精度高、作用距离远,但收发隔离困难,需要大功率发射机和精密时序控制,对便携实验平台来说成本和复杂度都太高。连续波(CW)雷达结构最简单,只能测速度、不能测距离,应用面太窄。FMCW 则刚好落在中间:发射信号频率随时间线性变化,通过比较发射和接收信号的频率差来同时获得距离和速度,并且发射功率可以做得很低,适合短距离、高精度的场景。

这里给一个直观类比:FMCW 的原理可以想象成一个人不停变化音调地唱歌,你听到的回声和他当前唱的声调之间的高低差异,就对应着他的距离。音调变化得越快,回声的"音差"就越明显,测距分辨率就越高。实际系统中这个"音调变化速度"就是调频斜率 B/Tc,B 是扫频带宽,Tc 是一个 chirp 的持续时间。

这个选择还带来了一个额外好处:FMCW 收发可以同时进行,不需要像脉冲雷达那样在发射和接收之间快速切换,因此射频前端可以做得更简单,隔离度要求也低很多。对于 PLFM_RADAR 这种面向短距离、低速目标的平台来说,FMCW 几乎是唯一不需要"硬刚"大功率器件的选择。

2.2 射频前端与天线:24GHz 是便携雷达的性能甜点

确定体制之后,下一步是选频段。我最终选了 24GHz,原因有三。第一,24GHz 属于 ISM 频段,设备可以在低功率下合法使用,实验环境无需申请专门频率。第二,24GHz 的射频芯片和天线模块选择多、价格相对低,供应链成熟。第三,24GHz 波长约为 12.5mm,天线尺寸可以做得很小,适合便携平台的集成。

射频前端的核心指标是发射功率和接收增益。我在设计里采用了"一发一收"的天线架构:发射端由一个压控振荡器(VCO)产生 24GHz 扫频信号,经功率放大器后馈入发射天线;接收端由接收天线拾取回波,经低噪声放大器(LNA)放大后与本地发射信号混频,输出差频中频信号。

链路预算可以这么算:假设发射功率 10dBm,收发天线增益各 10dBi,目标反射截面积(RCS)取 1 平方米(近似人体),距离 30 米,则接收功率约为:

P_r = P_t + G_t + G_r + σ - 20log10(4πR²/λ²)

代入数值:10 + 10 + 10 - 20log10(4π×900/0.000156) ≈ -75dBm。接收链路噪声系数按 6dB、中频带宽按 1MHz,热噪声功率约为 -174 + 60 + 6 = -108dBm,因此信噪比可以达到 30dB 以上,完全足够目标检测。这个预算说明:24GHz + 低功率就能覆盖 30 米范围的目标探测,完全不需要大功率放大器,这正是便携系统最理想的工作点。

2.3 中频采集与数据通路:ADC 参数如何定下来

射频前端的混频器输出的是低频差频信号,频率范围从几百 kHz 到 1~2MHz,这个信号需要经过 ADC 采样变成数字数据。中频频率上限直接决定了 ADC 采样率:采样定理要求采样率至少大于最高信号频率的两倍,实际工程中我会至少留 20% 余量。

我用的是一个 2MSPS、14bit 的 ADC 模块,配合 Xilinx Zynq FPGA 完成数据缓冲和实时预处理。2MSPS 采样率对应的奈奎斯特频率是 1MHz,这决定了系统的最大可测中频为 1MHz,再结合 FMCW 测距公式可以算出最大不模糊距离。具体的计算我在 3.4 节详细展开。

这里必须提一个常见误区:很多人以为 ADC 位数越高越好,但在雷达系统里,动态范围才是更关键的限制因素。近距离强反射目标会让接收机饱和,压住远距离弱目标。14bit 的 ADC 理论动态范围约 84dB,实际可用大约 70dB,已经能应付从 1 米到 30 米的目标动态范围。再往上堆位数,成本上升但系统噪声和前端线性度反而会成为新的瓶颈。

3. 信号处理链路的核心算法与实现细节

3.1 FMCW 测距测速原理:从差频频率到距离、速度的完整推导

这一节是整个项目的大脑。FMCW 雷达发射频率随时间线性上升,设调频斜率为 k = B/Tc,则发射信号频率为 f_t = f_c + k t,经过时间延迟 τ = 2R/c 后,接收信号频率为 f_r = f_c + k(t - τ)。混频器输出的差频频率为:

f_b = k τ = (B/Tc) · (2R/c) = 2BR / (c·Tc)

反解距离就是:

R = f_b · c · Tc / (2B)

这就是测距原理,一句话总结就是:差频越高,目标越远。距离分辨率取决于带宽:ΔR = c/(2B)。带宽 200MHz 时,ΔR = 0.75m,意味着两个距离相差小于 0.75 米的目标会在距离维 FFT 后落在同一个 bin 里,无法分辨。

测速则需要观察多个连续 chirp 之间的相位变化。设 chirp 周期为 Tc,目标径向速度为 v,则相邻两个 chirp 间因目标移动引入的相位差为 Δφ = 4πvTc/λ。对同一距离单元跨 chirp 做 FFT,峰值对应的多普勒频率 f_d 满足:

v = f_d · λ / 2

这里多普勒频率是通过对 N 个 chirp 做 FFT 得到的,最大不模糊速度由采样定理决定为 v_max = λ/(4Tc)。速度分辨率由总观测时间决定为 Δv = λ/(2N·Tc)。参数的相互制约关系(Tc 越小测速范围越大但距离变近)会在 3.4 节做算例分析。

3.2 从原始 ADC 数据到距离-多普勒图:逐级处理流程

数据处理的完整流程我可以拆成五步。第一步,对每个 chirp 的 ADC 采样序列去除直流分量,这是为了去掉混频器输出的直流偏置,否则距离维 FFT 会在零频附近出现一个很大的虚假峰。第二步,加窗函数。直接做 FFT 会因为频谱泄漏导致距离峰出现高旁瓣,我默认选择汉明窗,主瓣稍宽但旁瓣抑制效果好,实测旁瓣可以压到 -40dB 以下。第三步,对每个 chirp 做 N_fft 点 FFT,得到距离维频谱。第四步,对每个距离单元,跨 chirp 方向再做一次 FFT,得到多普勒维频谱。第五步,将二维频谱取幅度、做对数压缩,将窄带噪声在视觉上压平,方便后续检测。

这个流程的 Python 参考实现如下:

import numpy as np def range_doppler_map(adc_data, n_chirps, n_samples, fft_len=256): """ adc_data shape: (n_chirps, n_samples) 返回 distance_axis, doppler_axis, rd_map """ window = np.hanning(n_samples) range_fft = np.fft.fft(adc_data * window, n_fft, axis=1) range_fft = range_fft[:, 0:n_fft//2] # 单边谱 doppler_window = np.hanning(n_chirps) rd_fft = np.fft.fft(range_fft * doppler_window[:, None], n_chirps, axis=0) rd_map = np.abs(np.fft.fftshift(rd_fft, axes=0)) # 对数压缩 rd_db = 20 * np.log10(rd_map + 1e-12) return rd_db

这里最关键的一个工程细节是:距离维 FFT 的点数不一定等于 ADC 采样点数。如果你把 256 个采样点直接做 256 点 FFT,得到的频率分辨率是 fs/N = 2MHz/256 ≈ 7.8kHz,对应的距离分辨率是 0.75m,和理论值一致。但如果采样点数不足,可以通过补零到 512 点做插值,让峰值更平滑,测距精度可以通过抛物线插值进一步细化为 0.1m 量级。

3.3 CFAR 检测与目标聚类:从热图到点迹的最后一公里

距离-多普勒图是一张能量图,要从中提取目标,最可靠的方法是恒虚警检测(CFAR)。CFAR 的核心思想是:对每个待检单元,用周围参考单元估计噪声功率,当待检单元能量超过噪声均值乘以门限系数 α 时判定为目标。这样门限会随局部噪声自适应变化,避免用固定门限导致近处强杂波淹没远处弱目标。

我用的是 CA-CFAR(单元平均恒虚警)。具体参数:参考单元数 16,保护单元数 4,虚警概率设为 1e-4。门限系数 α 可以由虚警概率公式反算,但工程上我更习惯直接根据实测噪声底标定,免得公式推导中的分布假设与实际不符。实测下来,当目标信噪比大于 15dB 时,CFAR 检测非常稳定;信噪比降至 10dB 以下时,会出现零星虚警,需要用后续聚类或帧间关联来过滤。

CFAR 之后得到的是若干"检测单元"的集合,它们往往来自同一个目标的多个相邻 bin,因此还要做聚类合并。我没有用复杂算法,直接采用连通域合并:把距离维相邻不超过 2 个 bin、多普勒维相邻不超过 2 个 bin 的检测点归为同一个目标,取能量最高点作为目标中心。这个简单规则在单人场景下非常鲁棒,多人场景则需要换成 DBSCAN 或基于卡尔曼滤波的航迹关联,不过那是后续扩展的方向了。

3.4 参数设计算例:把这些数字一个个算给你看

决定系统能测多远、能测多快、分辨率多少,是由一套互相制约的参数决定的。我最终采用的参数如下:载频 24.125GHz,扫频带宽 B=200MHz,chirp 周期 Tc=200us,单 chirp 采样点数 400 点,ADC 采样率 2MSPS,每帧 chirp 数 N=128。

先算距离分辨率:ΔR = c/(2B) = 3e8/(2×2e8) = 0.75m。这代表两个目标必须相距 0.75m 以上才能在距离维分开,作为人员检测场景足够了。

再算最大不模糊距离。ADC 采样率 2MSPS,可测最大中频为 1MHz,代入距离公式:R_max = f_b_max · c · Tc / (2B) = 1e6 × 3e8 × 200e-6 / (2×200e6) = 150m。实际受限于发射功率和链路预算,可靠探测距离约 30 米,但这说明中频带宽不是瓶颈。

接着算最大不模糊速度:v_max = λ/(4Tc) ≈ 0.01245/(4×200e-6) ≈ 15.6m/s,约 56km/h。这覆盖了人员走动和自行车速度,但覆盖不了高速汽车。

最后算速度分辨率:Δv = λ/(2N·Tc) = 0.01245/(2×128×200e-6) ≈ 0.243m/s。0.24m/s 的精度足够区分"站立"(多普勒接近 0)和"走动"(约 1~2m/s),但如果需要分辨 0.1m/s 的微动,就得增大 N 或减小 Tc。

帧率方面,每帧 128 个 chirp,总时间约 25.6ms,对应约 39fps 的刷新率,实时性非常好。这些数字算下来,我自己最满意的是这个参数集刚好卡在低速人员检测的需求上,没有浪费算力也没有明显短板。

4. 外场实测过程与结果解读

4.1 外场测试怎么布置:场景、流程与校准

参数设计得再漂亮,也得拿到外面跑一跑才算数。我选择的测试场地是一条长约 40 米、宽 3 米的室内走廊,这样既有相对干净的背景,又能保证目标做直线运动。雷达架在走廊一端,离地高度约 1.2 米,朝向走廊纵深方向。在雷达正前方 5 米、10 米、20 米处用卷尺做了地面标记,用于后续测距精度比对。

测试流程分三类。第一类是静止目标测距:人站在标记点不动,各采集 100 帧数据,统计距离估计的均值和方差。第二类是运动目标测速:人从雷达前 5 米处匀速走向 25 米处,同时用秒表记录通过两个标记点的时间,计算平均速度作为参考。第三类是多目标场景:两个人在不同距离上错开站立,观察 CFAR 是否能稳定分离两个目标。

供电和干扰排查是我在外场吃过亏的地方。笔记本用电池供电时 ADC 测得的数据明显更干净,插上电源适配器后,距离-多普勒图上会出现规律的 50Hz 干扰线。原因是适配器开关电源的纹波通过地回路耦合进了模拟前端。最终解决方案是用隔离供电给射频前端和中频采集板单独供电,同时将笔记本充电器换成低纹波的线性电源。

4.2 典型的距离-多普勒结果图是怎么读的

用上面参数采集一组数据后,得到的距离-多普勒图有几个典型特征。静止目标出现在 0 多普勒附近,距离轴对应真实位置,但由于静止目标的多普勒频率为 0,它和背景杂波会混在一起,CFAR 检测时需要额外压低零多普勒附近的检测门限,否则会把墙体、桌椅全部检测成目标。

移动目标则不同,它的能量峰既出现在正确的距离单元上,又出现在对应的多普勒单元上。人迎着雷达走来时,多普勒频率为正;远离时,多普勒频率为负。我从 20 米处迎向雷达步行,实测多普勒峰对应速度约为 1.2m/s,与秒表计算的 1.15m/s 误差在 5% 以内。这个结果说明整条链路从射频到算法都没有明显偏差。

距离估计准确性方面,目标在 5 米时估计值 4.85 米,10 米时估计 9.91 米,20 米时估计 19.75 米,误差都在 0.2 米以内。0.75 米距离分辨率并没有限制测距精度,是因为我对距离维 FFT 谱峰做了抛物线插值,估计精度可以远高于一个 bin 的宽度。

4.3 误差来源分析:为什么测距测速不是完美的

实测误差来源可以归为三类。第一类是系统误差,主要是 VCO 的非线性调频。理想情况下频率随时间是线性的,但实际 VCO 在扫频边沿会有几百 kHz 的频率偏差,导致差频频率不再是准确的距离映射,表现为邻近目标峰的展宽。解决思路是在基带增加去斜处理,或者用 PLL 锁定扫频线性度,但会显著增加系统复杂度。

第二类是热噪声与相位噪声。近距离强目标会让接收机进入非线性区,产生交叉调制,导致远处的弱目标被掩盖。这个现象在实测中表现为:人走到离雷达 2 米以内时,20 米外的静止目标 CFAR 检测概率明显下降。这是 FMCW 雷达的固有短板,只能通过降低接收增益或增加 STC(灵敏度时间控制)来缓解。

第三类是栅栏效应和量化噪声。FFT 谱峰的真实位置落在两个 bin 之间时,幅度峰值会降低,测距精度也受影响。抛物线插值可以一定程度上恢复真实位置,但如果目标信噪比很低,插值结果会抖动。量化噪声则主要是 ADC 的量化误差,14bit 精度下影响很小,几乎可以忽略。

5. 常见问题与调参避坑指南

5.1 高频问题速查表

我在反复调试过程中遇到过不少问题,挑了几个最容易复现的整理成表。

现象可能原因解决方案
距离-多普勒图上出现水平条纹中频信号耦合了电源纹波隔离供电,加 LC 低通滤波
近距离一片高能量杂波发射信号直接泄漏进接收机提高收发天线隔离度,加屏蔽罩
静止目标检测不到零多普勒被滤波器滤除或门限过高单独降低零多普勒门限,或改用微动检测
测速结果整体偏大晶振频率偏差导致 Tc 不准用温补晶振替换普通晶振,实测校准
CFAR 虚警在远距离突然增多噪声不是均匀高斯分布改用有序统计 CFAR(OS-CFAR)
两个相近目标检测成一个距离分辨率不足或旁瓣掩蔽增大带宽、压低窗函数旁瓣

5.2 三个必须重视的细节:直流偏置、非线性调频和窗函数

第一个必须重视的细节是直流偏置。FMCW 混频器输出的差频信号通常叠加了一个较大的直流分量,直接做距离维 FFT 会在零频处产生巨大的谱峰,甚至淹没问题。我一开始在代码里简单用均值相减,但发现均值估计会受强目标影响,导致消不干净。后来改成在每个 chirp 内先做高通滤波,截止频率设在 10kHz 以下,彻底解决了直流泄漏问题。

第二个细节是非线性调频。VCO 的频率-电压曲线不是严格线性的,扫频带宽越大,非线性越显著。我的实测数据里,200MHz 带宽下距离峰展宽约 20%,直接导致距离分辨率退化为约 0.9 米。如果不作处理,再好的算法也挽回不了这个损失。简单方法是在软件里做"频率标定":用已知距离的强反射体测量实际差频曲线,建立频率到距离的查找表,代替理论公式。这个方法成本低、效果好,强烈推荐。

第三个细节是窗函数的选择。很多人对距离维 FFT 直接不做加窗,结果是目标的旁瓣能高出主瓣 13dB 量级,相邻目标很容易被"淹没"在旁瓣里。我对比过矩形窗、汉宁窗和布莱克曼窗:汉宁窗主瓣约 1.44 倍 bin 宽度,旁瓣衰减 31dB;布莱克曼窗旁瓣衰减 58dB 但主瓣展宽到 2.35 倍。对于大多数场景,汉宁窗是性价比最高的选择。多普勒维我也用了汉宁窗,实测旁瓣被压到 -40dB 以下,两个速度相差 1m/s 的目标也能很容易分开。

5.3 高效调试方法论:先点亮一个目标,再逐步加难度

调试雷达系统最忌讳一上来就搞多目标复杂场景。我的建议是"三步走"。

第一步,裸板点亮。找一个金属板或者大 RCS 角反射器,放在雷达正前方 3~5 米处,静态采集数据,先确认距离维 FFT 能出峰。这个阶段不看测速,不看 CFAR,只看主峰。

第二步,单目标动态测试。让目标做匀速直线运动,确认多普勒维 FFT 能出峰,测速方向正确。如果这一步发现速度不对,优先检查 chirp 周期 Tc 和载频 λ 的取值是否一致,这个低级错误我犯过不止一次。

第三步,多目标与复杂背景。确认单目标链路全通后,再加入第二个目标、墙面的多径反射等干扰,逐步调 CFAR 门限和聚类参数。这样做的最主要原因是,多目标场景的问题来源千奇百怪,你必须在单目标阶段已经把链路相关的问题全部排掉,后面才不会白费力气。

另外强烈建议从一开始就把"录制原始 ADC 数据"的能力做进系统。外场测试信号稍纵即逝,如果只做在线处理,出问题时没有数据回放就只能干瞪眼。PLFM_RADAR 的 FPGA 逻辑里做了一个循环缓冲,最近 5 秒的原始数据可以通过按键一键保存到 SD 卡,所有算法都在 PC 端离线重放验证。我的经验是,凡是在外场"灵光一现"的现象,几乎都要靠回放数据才能定位原因。

5.4 关于调仓与扩展的个人体会

整套系统跑通之后,我还做过几个小的扩展实验。一是把 chirp 周期从 200us 改为 100us,最大不模糊速度翻倍到 31m/s,代价是最大探测距离降到了 75 米,说明参数设计的灵活性就是这么来的。二是加入了微多普勒分析,让目标在距雷达 5 米处挥手,距离-多普勒图上能看到以 0 多普勒为中心的周期性旁瓣,这是非常有辨识度的人体生命体征特征。

如果要再往下走,我觉得有几个方向很值得尝试。用两个接收天线做干涉测角,就可以把平台从"一维测距测速"升级成"二维定位";把处理链路迁移到 FPGA 内部做实时推理,可以摆脱笔记本,实现全嵌入式部署;引入卡尔曼滤波做多帧航迹关联,则可以让平台真正接近一个可用的感知系统。但这些扩张的前提,仍然是把本文这套基础链路做扎实,先能稳定地测准距离和速度再说。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进