脉冲雷达回波的距离门重排与匹配滤波原理及实现

发布时间:2026/10/30 17:33:22
脉冲雷达回波的距离门重排与匹配滤波原理及实现

简介:这份压缩包提供 single.m MATLAB 脚本,面向雷达信号处理入门学习者与相关课题研究者,集中演示脉冲雷达回波处理中的匹配滤波、距离门设置与距离门重排流程,可直接用于理解和验证基本处理链路。包内仅含 1 个 m 文件,大小约 2KB,代码精简无外部依赖,便于直接运行和二次修改。已有 431 人浏览学习,适合作为雷达成像或目标检测课程设计的参考实现。脚本可在模拟回波上展示匹配滤波器如何通过模板相关增强信噪比,并利用距离门筛选特定距离区间的目标;当存在多径或杂波干扰时,重排操作能重新组织距离门,提升目标检测的准确性。通过学习这份资源,读者可直观对比处理前后的回波特征,并基于代码调整脉冲参数、门限或重排策略,加深对脉冲雷达信号处理关键环节的理解,也可为后续算法改进提供可复现基线。

1. 距离门重排不是排序:脉冲雷达回波为什么先匹配滤波再切门

拿到一个名为 single.zip 的雷达回波工程包,打开后大概率只有三样东西:一段原始采样、一个发射脉冲模板、一份记录采样率和脉宽的参数表。把这个包变成一维距离像,需要经过脉冲匹配滤波把回波在时间轴上压窄,再按 range gate(距离门)把压缩后的数据切成观察窗口,最后做一次距离门重排。很多人以为距离门重排是一种排序,其实它不是:它只是把整段采样重新组织成按距离门排列的矩阵,方便后续做 CFAR 和多普勒处理。这篇文章适合刚接手脉冲雷达回波、正在搭信号处理链路的工程师,也适合做算法验证的人。下面先把两个前提讲透,再给出一套能直接跑通的最小实现。

2. 距离门与匹配滤波:决定脉冲雷达回波能看多远的两个前提

2.1 距离门在雷达回波里到底切什么

脉冲雷达的工作方式并不复杂:发射机发一个窄脉冲,电磁波碰到目标后反射回来,接收机在发射后的某一时刻打开采样窗口,把这个窗口里的数据记录下来。这个窗口就是距离门,它对应雷达回波中一段连续的距离范围。

为什么要设距离门?如果把整个脉冲重复周期都采下来,接收机会把大量无用噪声、地杂波和干扰同时收进来,动态范围很快被顶满,后续匹配滤波的动态优势就没有了。距离门把关注区间限制在 R0 到 R1 之间,既让回波信噪比更集中,也让后续计算量可控。

距离门宽度不是随便定的。它至少要能覆盖一个发射脉冲的持续时间 τ_p,否则回波会被门沿切掉一半,匹配滤波后能量不完整。一般我会留 10%~20% 的保护间隔,也就是 T_gate = (1.1~1.2)τ_p。采样率 fs 决定一个门内有多少个样本点,这一段计算可以写成直接可复现的代码:

c = 3e8 # 光速,单位 m/s R0, R1 = 300.0, 3000.0 # 观察距离范围,单位 m tau_p = 0.5e-6 # 发射脉冲宽度,单位 s fs = 200e6 # 采样率,单位 Hz t0 = 2 * R0 / c # 起始距离对应的回波时刻 t1 = 2 * R1 / c # 终止距离对应的回波时刻 T_gate = 1.2 * tau_p # 单距离门宽度,留 20% 保护间隔 gate_count = int((t1 - t0) / T_gate) print(t0, t1, T_gate, gate_count)

这段代码把 300 米到 3000 米的观测区间按固定门宽切成了多个距离门。t0 是最近距离回波的到达时刻,t1 是最远距离回波的到达时刻,两者之间的时间差就是整个观测窗口的时长。T_gate 取 1.2 倍脉宽而不是 1 倍,目的是给回波跨门留一点余量。gate_count 就是距离门个数,它直接影响后续距离像的长度。

这里有一个容易混淆的点:距离门个数并不等于距离分辨力。距离分辨力由脉冲宽度或匹配滤波后的带宽决定,距离门只是数据组织的格子。真实系统里,距离门宽度往往和匹配滤波后的主瓣宽度匹配,而不是和发射脉宽匹配。比如脉宽 5us、带宽 10MHz 的线性调频信号,匹配滤波后主瓣约 0.1us,距离门应尽量按 0.1~0.2us 设计,否则一个目标会长时间落在一个门里,无法分辨两个靠近的目标。

参数符号作用设置要点
脉冲宽度τ_p决定基础距离分辨力和发射能量匹配滤波前 ΔR = c·τ_p/2
距离门宽度T_gate决定观察窗口的数据组织粒度取 (1.1~1.2)τ_p 起步,压缩后按 1/B 收紧
采样率fs决定距离门内样本点数复基带至少满足 fs ≥ B,通常取 1.2~2 倍带宽
距离门个数N_gate决定一维距离像长度由 R0、R1 和 T_gate 计算,不是随便填

2.2 匹配滤波为什么是脉冲压缩的核心

单纯用窄脉冲发射,距离分辨力好但平均功率低,探测距离上不去;用宽脉冲发射,能量够了但两个目标在时间上叠在一起分不开。匹配滤波解决了这个矛盾:发射宽脉冲,接收时用一个与发射信号共轭时间翻转的滤波器做匹配,把宽脉冲在时间轴上压成一个窄峰,这就是脉冲压缩。

对线性调频信号 s(t) = exp(jπKt²),匹配滤波器系数是 h(t) = s*(-t)。这里有两个动作不能省:一是共轭,二是时间翻转。很多第一次接触匹配滤波的人只做了翻转没做共轭,或者只做共轭没翻转,输出直接变成一个很宽的平台。用 Python 可以非常直观地演示这个过程:

import numpy as np fs = 200e6 # 采样率 200 MHz tau_p = 5e-6 # 脉冲宽度 5 us B = 10e6 # 带宽 10 MHz K = B / tau_p # 调频斜率 t = np.arange(int(tau_p * fs)) / fs s_tx = np.exp(1j * np.pi * K * t**2) # 发射 LFM 模板 # 匹配滤波系数:时间翻转 + 共轭 h = np.conj(s_tx[::-1]) # 构造一个带噪声的延时回波 delay = int(20e-6 * fs) echo = np.zeros(int(80e-6 * fs), dtype=complex) echo[delay:delay + len(s_tx)] += 0.5 * s_tx echo += (np.random.randn(len(echo)) + 1j * np.random.randn(len(echo))) * 0.01 y = np.convolve(echo, h) peak_pos = np.argmax(np.abs(y))

这段代码里,s_tx 是发射的线性调频基带信号,h 是匹配滤波器的冲激响应。np.convolve 做的是线性卷积,相当于把回波与模板做相关运算。峰值位置与真实延迟之间的关系不是直接相等,而是 peak_pos ≈ delay + len(s_tx) - 1,因为线性卷积会把模板长度带来的延迟算进去。这个偏移在后面的距离换算里必须减掉,否则距离会整体偏大一个脉宽对应的长度。

匹配滤波的理论意义在于它让输出信噪比最大化,同时把主瓣宽度压到约 1/B。脉宽 5us、带宽 10MHz 时,主瓣约 0.1us,对应距离分辨力 c/(2B) = 15 米,而原始宽脉冲对应 750 米。差了 50 倍,这就是为什么现代脉冲雷达几乎都会用匹配滤波做脉冲压缩。

注意这段代码里的随机噪声用的是 randn 直接叠加,真实回波里噪声是系统噪声和外部噪声的混合,信噪比不会这么好看。做算法验证时,我一般会把噪声功率设成与回波功率可比,否则匹配滤波的峰值太好找,掩盖了真实处理中的很多问题。

3. 把 single.zip 变成一维距离像:回波读取、脉冲压缩与距离门重排的落地流程

3.1 先确认数据格式:single.zip 里的采样序列与发射模板

从同事手里接过一个 single.zip 这样的工程包,我不会解压完立刻跑脚本,而是先做三件事:看回波数据的形状、看数据类型、看参数表里有没有 fs 和脉宽。雷达回波数据最常见的格式是复数基带 IQ,dtype 可能是 complex64、complex128,也有不少系统为了压存储直接用 int16 交错存放 I/Q。如果是 int16 交错,必须自己先拆成复数,否则后续匹配滤波全乱。

我一般会把工程包解压后统一成下面这种结构:raw_echo.npy 存放单脉冲回波,tmplt.npy 存放发射模板,meta.json 存放采样率和脉宽。数据自查的代码可以这样写:

import json import numpy as np data = np.load("raw_echo.npy") template = np.load("tmplt.npy") with open("meta.json", "r") as f: meta = json.load(f) fs = meta["fs"] tau_p = meta["pulse_width"] print(data.shape, data.dtype, template.shape) print(f"fs = {fs/1e6:.1f} MHz, tau_p = {tau_p*1e6:.2f} us")

先打印 shape 和 dtype 是为了在进入匹配滤波前拦住两类典型错误:一类是数据其实是 int16 I/Q 交错,被当成 float 读进来后复数值不对;另一类是模板长度与 fs×tau_p 对不上,说明参数表与数据不是同一份。meta 里的 fs 如果缺失,只能用已知目标回波反推,这属于事后补救,误差很大。

模板本身必须是发射脉冲的基带波形,不能是调制前的方波。很多系统里模板是从发射耦合通道直接采样出来的,带着发射机的实际畸变,这种情况下匹配滤波反而比用理想 LFM 更稳,因为发射畸变也被当成模板的一部分匹配掉了。

3.2 匹配滤波压缩:把 5MHz LFM 脉冲压成 0.1us 主瓣

数据确认无误后,下一步就是脉冲压缩。直接用 np.convolve 在小数据量下没问题,但雷达回波一段就是上百万个点,时域卷积太慢。常见做法是转成频域相乘再反变换,也就是快速卷积。代码可以这样组织:

template = np.asarray(template, dtype=complex) h = np.conj(template[::-1]) # 匹配滤波系数 # 频域快速卷积 N = len(data) + len(h) - 1 Nfft = 1 << int(np.ceil(np.log2(N))) # 找到不小于 N 的 2 的幂 E = np.fft.fft(data, Nfft) H = np.fft.fft(h, Nfft) y = np.fft.ifft(E * H, Nfft)[:N]

这段代码把两个信号都补零到 Nfft,然后频域相乘,最后反变换截取有效长度 N。Nfft 取 2 的幂是为了让 FFT 计算效率最高,如果数据长度本身已经接近 2 的幂,这一步实际省不了多少时间,但养成习惯没有坏处。y 就是脉冲压缩后的输出,它的长度是 len(data) + len(h) - 1,比原始回波长一个模板长度,后面做距离门重排时要把这些尾巴处理好。

如果模板没有归一化,匹配滤波输出的幅度会带上模板能量。为了让压缩后的幅度直接反映目标回波幅度,我通常会在构造 h 时除以模板能量:

h = np.conj(template[::-1]) / np.sum(np.abs(template)**2)

这样归一化后,匹配滤波峰值就约等于回波中目标分量的复幅度,后面做 CFAR 检测时阈值计算不需要再额外补偿模板增益。代价是如果模板本身有幅度起伏,归一化会把起伏也带进输出,但大多数工程场景下影响不大。

频域实现的一个细节是,数据是复数基带,不能用 np.fft.rfft,必须用 np.fft.fft。很多人在这一步顺手用了 rfft,结果复数信号的负频谱被丢掉,压缩后目标位置偏移,幅度也变了。这个坑在后面专门讲。

3.3 距离门重排:把一维回波切成"距离门×门内样本"矩阵

脉冲压缩做完,数据还是一长串。这个时候做距离门重排:根据 R0、R1 和距离门宽度,把压缩后的回波切成若干段,每段是一个距离门,按距离从近到远排成矩阵行。矩阵的行号就是距离门号,列是门内的采样点,后续每个门取峰值或做相干累加,就得到一维距离像。

重排代码的核心是索引计算和 reshape。我一般这样写:

c = 3e8 start_idx = int(np.floor(2 * R0 * fs / c)) stop_idx = int(np.ceil(2 * R1 * fs / c)) gate_len = int(np.round(1.2 * tau_p * fs)) segment = y[start_idx:stop_idx] num_full_gates = len(segment) // gate_len # 丢弃最后不满一个门的尾巴,保证 reshape 不报错 segment = segment[:num_full_gates * gate_len] gates = segment.reshape(num_full_gates, gate_len) # 每个距离门的起始距离 distance_axis = (start_idx + np.arange(num_full_gates) * gate_len) / fs * c / 2.0

这里 start_idx 对应最近距离的回波起点,stop_idx 对应最远距离的回波终点。门长 gate_len 是每个距离门内的样本点数。reshape 要求 segment 长度必须能整除 gate_len,所以先截成整数倍,末尾不足一个门的数据直接丢弃,这个操作符合距离门的定义:不在观测范围内的回波本来就不该进后续处理。

distance_axis 的计算要特别注意,start_idx 除以 fs 得到的是回波到达时刻,再乘 c/2 才是单程距离。很多人这里忘了除 2,目标距离直接翻倍,这是距离门重排里最容易出现的坐标错误。

重排之后,gates[i, :] 是第 i 个距离门内的压缩后波形。取每个门的最大幅度,就能得到一维距离像:

range_profile = np.max(np.abs(gates), axis=1)

但要注意,如果距离门宽度比压缩主瓣宽很多,直接取最大值会丢失相位信息。对需要做多普勒处理的系统,我一般会在每个门里先做相干累加或取主瓣峰值复数值,而不是只取幅度,这样相位信息还能留下来。这个选择会直接影响后面多普勒处理能拿到什么样的数据。

4. 参数联动:脉冲宽度、采样率、距离门宽度和重排索引怎么一次算对

4.1 距离分辨力与最大不模糊距离:一张参数表说清取舍

雷达回波处理里没有免费午餐。脉冲宽度 τ_p 加宽,发射平均功率变大、探测距离变远,但时域主瓣变宽,匹配滤波前距离分辨力退化。带宽 B 加大,匹配滤波后主瓣变窄、距离分辨力提升,但对采样率和存储带宽的要求同步提高。采样率 fs 不够,频带边缘的信号会混叠,压缩后主瓣出现假峰;采样率过高,数据量膨胀,处理实时性变差。

参数主要影响调大的结果调小的结果
脉冲宽度 τ_p发射能量、基础分辨力功率大、探测远,主瓣宽主瓣窄,峰值功率要求高
信号带宽 B匹配滤波后主瓣宽度分辨力好,所需采样率高分辨力差,数据率低
采样率 fs频谱完整性、门内点数数据量大,分辨率提高频谱混叠,压缩峰畸变
距离门宽度 T_gate数据组织粒度、跨门概率门内信噪比高,目标跨门少门数多,计算量增大

匹配滤波后的距离分辨力是 ΔR = c/(2B),这个公式的前提是信号带宽 B 和采样率匹配。如果 fs 只略大于 B,主瓣还能保得住,但旁瓣会变差;如果 fs 小于 B,回波频谱被截断,匹配滤波输出会像加了一个矩形窗一样出现高旁瓣。工程上 fs 取 1.2 到 2 倍带宽是常见做法,低于 1.2 倍就要仔细验证峰值位置误差。

距离门宽度在这个参数链里是一个组织参数,而不是物理参数。它应该跟随压缩后的主瓣宽度去设定。早期我看到不少人把距离门宽度直接设成发射脉宽,脉宽 5us 就设 5us,结果压缩后主瓣只有 0.1us,一个门里塞了 50 个可分辨单元,目标出现在门内哪个位置完全不知道,还容易跨门检测到。把门宽压到 0.2~0.5us,距离像才真正有意义。

4.2 重排索引计算:为什么不能只看 start_idx 和 gate_len

距离门重排最容易翻车的点就是索引计算。很多人直接把 start_idx 到 stop_idx 的数据均匀切成 N 段,然后 reshape,看起来没报错,但最后距离像的横坐标和真实距离对不上。

正确做法是先算好每个距离门的边界,再切。我习惯写一个生成索引表的函数:

def build_gate_indices(fs, R0, R1, gate_dur, c=3e8, guard=0.1): t0 = int(np.floor(2 * R0 * c / fs)) # 注意:这里顺序有误,见说明 t1 = int(np.ceil(2 * R1 * c / fs)) return t0, t1

等等,这个函数里的单位换算写错了。正确的是用回波时刻乘以 fs 得到样本索引,也就是先算 2R/c 再乘 fs。很多人在这里把公式抄反,结果索引单位变成距离除以采样率,距离像完全不可用。修正后的代码是:

def build_gate_indices(fs, R0, R1, gate_dur, c=3e8, guard=0.1): t0 = 2 * R0 / c t1 = 2 * R1 / c start = int(np.floor(t0 * fs)) stop = int(np.ceil(t1 * fs)) step = int(np.round(gate_dur * fs)) step = int(step * (1 - guard)) # 门间保护样本 indices = [] p = start while p + step <= stop: indices.append((p, p + step)) p += step return indices

这个函数返回的是每个距离门的起始和结束样本位置列表。guard 参数表示门与门之间留多少保护,常见取 0.1,也就是留 10% 样本不进入后续处理。保护样本的意义在于:目标回波如果正好落在门边界,跨门会导致同一个目标在两个门里各出现一半能量,检测时很难判定。留保护后,门与门之间的小间隙可以被后续的峰值检测容差吸收。

用索引表切片有一个好处:不用强制让整个 segment 长度恰好整除门长,因为最后一个门可能只覆盖到 stop 附近,可以用索引表里合法范围内已经算好的子区间。这与前面的 reshape 方式互补,reshape 适合门长均匀、整幅数据正好排满的情况;索引表方式适合门数和距离范围不规整的情况。工程上我更推荐索引表,因为代码一眼能看懂,后续维护时不容易改错。

4.3 失配直接表现为脉冲值不匹配:窗函数和多普勒失谐

匹配滤波有一类很隐蔽的问题叫失配。回波里的脉冲和模板不一致,压缩输出就会变差。常见现象是压缩峰变矮、变宽,甚至在主瓣旁边出现毛刺,系统检测端经常报类似"脉冲值不匹配报警"的信息。这里的脉冲值不匹配不是模拟电路问题,而是模板参数和实际回波参数不一致。

三种最常遇到的失配来源。第一,发射脉冲本身有幅度起伏,模板却用理想矩形包络;第二,目标速度快,回波载频发生多普勒偏移,匹配滤波器按零多普勒设计,峰被压低;第三,模板里没有加窗,回波本身带杂波调制,旁瓣抬高。

针对旁瓣问题,最简单有效的处理是在模板上先乘窗函数再做匹配滤波:

win = np.hanning(len(template)) h = np.conj((template * win)[::-1])

加窗之后旁瓣可以从约 -13.2dB 压到 -40dB 以下,但主瓣会展宽约 1.4 倍,距离分辨力变差。这是一个典型取舍:要旁瓣低,就得接受主瓣变宽。切比雪夫窗可以用旁瓣电平约束反推主瓣宽度,比汉宁窗更可控,适合要求严格的应用。

多普勒失谐的解决思路不是改窗,而是让匹配滤波对多普勒更鲁棒,常见做法是做多普勒通道补偿,即把回波分别搬移几个频偏后再匹配,选输出最大的那个通道。这个在单脉冲里不划算,到了多脉冲多普勒处理时再综合考虑。

5. 距离门重排常见坑:脉冲值不匹配报警、reshape 翻车与五个排查记录

5.1 压缩峰找不到,或者出现在数据开头

现象:匹配滤波输出没有明显峰值,或者峰出现在序列最前面几个样本上,换算出来的距离是负值。

原因:回波数据集里通常包含发射泄漏和接收机保护延时,数据从发射时刻开始记录,但匹配滤波的线性卷积输出里有一个模板长度的固定偏移。另一个常见原因是回波里根本没有目标,只有噪声和杂波,峰值位置随机。

解决:先把峰值索引调整回回波时基,再换算距离。峰值实际对应的回波时刻是 peak_pos - len(template) + 1,而不是 peak_pos 本身;用下面的方式换成距离:

peak_pos = np.argmax(np.abs(y)) peak_echo_idx = peak_pos - len(template) + 1 peak_range = peak_echo_idx / fs * c / 2.0

如果 peak_echo_idx 为负数,说明峰来自卷积输出的前段,对应的是模板和回波开头偶然重叠产生的伪相关,不是目标。这时候应该回到数据检查流程,看回波里是否真的有信噪比足够的目标回波。

5.2 reshape 报错:距离门长度除不尽

现象:执行 segment.reshape(num_gates, gate_len) 时抛出 ValueError,提示 cannot reshape array of size ... into shape ...。

原因:segment 的实际长度不是 gate_len 的整数倍。start_idx 和 stop_idx 是用 round 或 floor 算出来的,而门的边界和观测区间边界很难正好对齐采样点。

解决:不要直接 reshape,先截取整数倍长度,或改用 4.2 节的索引表方式。截取时优先丢尾巴,不要丢头,因为尾巴对应的是最远处那一小段观测区间,丢失一个不完整的门对近距离目标影响最小。代码已在 3.3 节给出,核心是 segment[:num_full_gates * gate_len] 这一行。

5.3 主瓣宽度比理论值宽一倍:窗和时间翻转都查一遍

现象:明明带宽 10MHz,理论主瓣 0.1us,实际压缩后峰宽约 0.2us 甚至更宽,距离分辨力明显变差。

原因:最可能是模板没有同时做共轭和时间翻转。只翻转不共轭时,输出峰值位置仍然对,但主瓣会展宽;只共轭不翻转时,匹配滤波退化成一个普通的频域加权,相位关系错乱。此外,如果加了窗函数,主瓣本身就会按窗函数展宽,汉宁窗约 1.4 倍,切比雪夫窗则看选择的旁瓣电平。

解决:先用代码打印 h 是不是 np.conj(template[::-1]),再看有没有乘窗。如果两者都正常,检查回波信号带宽是否真的接近 B。发射机带宽不足时,回波频谱本身就窄,压缩主瓣也会变宽,这个属于前端硬件问题,算法上只能通过系统辨识补偿。

5.4 距离坐标整体反了或者偏一个固定值

现象:向系统注入一个已知 1200 米处的目标,距离像上峰却在 800 米或 2400 米处,而且所有目标都偏同样的量。

原因:两个地方容易错。第一,距离换算公式忘了除 2,把往返时间当成单程,距离直接翻倍。第二,用 FFT 卷积后没有减掉模板长度偏移,导致所有距离都偏大一个脉宽对应的距离。

解决:养成用注入目标做自检的习惯。构造一个延迟对应的回波,跑完整个链路后换算距离,和真值比对。这一步能一次性暴露索引偏移、单位换算和坐标方向三类问题,比对着公式查快得多。

5.5 弱目标被强目标旁瓣淹没

现象:距离像上强目标旁边出现一个假峰,或者弱目标落在强目标旁瓣上,CFAR 检测把弱目标漏掉。

原因:LFM 信号匹配滤波的旁瓣约 -13.2dB,这个值比很多系统需要的 40dB 动态范围差得多。距离门重排后,强目标能量集中在主瓣和头几个旁瓣上,弱目标只要低 20dB 就会被盖住。

解决:加窗是第一步,把旁瓣压到 -40dB 以下。如果加窗后主瓣展宽影响距离分辨力,可以采用主瓣窄、旁瓣低的失配滤波器设计,或对距离像做旁瓣抑制处理。多脉冲系统里还有一个更有效的手段:沿慢时间做相干积累,弱目标的信噪比随脉冲数线性提升,而随机旁瓣不会同步提升,积累之后弱目标自然浮出来。

6. 进阶验证:注入已知目标自检距离门,再把单脉冲推向多普勒处理

6.1 注入已知目标自检整个处理链

拿到新数据或者改完参数,我不会直接拿真实回波去跑检测,先构造一个已知位置的目标注入链路。这个习惯帮我避免过很多次坐标错位和门宽错误。注入验证的代码很简短:

R_test = 1200.0 delay_test = int(2 * R_test / c * fs) test_echo = np.zeros_like(data) test_echo[delay_test:delay_test + len(template)] += template y_test = np.fft.ifft(np.fft.fft(test_echo, Nfft) * np.fft.fft(h, Nfft))[:len(test_echo) + len(h) - 1] peak = np.argmax(np.abs(y_test)) - len(template) + 1 peak_range = peak / fs * c / 2.0 print(f"注入距离 {R_test:.1f}m,实测距离 {peak_range:.1f}m")

如果 peak_range 和 R_test 偏差在 c/(2B) 以内,说明匹配滤波和距离门重排的索引都是对的。偏差超过一个距离分辨力,就去查 start_idx、模板长度偏移和距离公式这三处。这个自检流程每次改参数都跑一遍,基本能把 5.1 到 5.4 的坑挡在处理真实数据之前。

6.2 从单脉冲到多脉冲:距离门重排后的慢时间 FFT

距离门重排真正的价值在多脉冲系统里才能体现出来。多个脉冲的回波按采样顺序放在一起时,距离信息和慢时间信息是混在一起的。重排后,数据变成二维矩阵:一维是距离门,一维是脉冲序号。对每个距离门沿着脉冲序号做 FFT,就得到距离-多普勒图。这一步是雷达测速的基础。

# pulses 形状为 (N_pulse, 单脉冲采样点数) burst = np.stack([p[start_idx:stop_idx] for p in pulses]) burst = burst[:, :num_full_gates * gate_len] gate_map = burst.reshape(N_pulse, num_full_gates, gate_len) range_doppler = np.fft.fft(gate_map.mean(axis=2), axis=0)

到这里,距离门重排的意义就很清楚了:没有重排,慢时间 FFT 需要手动按门号抽取数据;重排一次之后,后续所有检测和处理都能直接按二维数组操作。我自己在这个环节翻过车,早期图省事跳过了重排,直接在原始采样上按固定间隔抽点做 FFT,结果多普勒谱里全是距离牵引入的假目标。后来凡是新数据,都会先注入一个已知距离目标跑一遍再上处理链,希望帮到你。

本文还有配套的精品资源,点击获取