简介:均匀直线阵常规波束形成(CBF)是阵列信号处理中的基础技术,常用于无线通信、雷达与声纳系统,通过控制各阵元相位差实现信号定向增强与干扰抑制。该资源面向学习天线阵列与波束形成的初学者或工程师,提供可直接运行的MATLAB脚本,用于演示方位谱图分析、权矢量计算及波束扫描等核心流程。压缩包共2个文件,均为.m格式,包含时域CBF与主程序两个模块,整体仅2KB,轻量易读,适合快速上手和修改实验。已有1695人学习下载,实用性得到初步验证。通过运行代码,读者可直观理解均匀直线阵的相位控制原理,观察不同指向下的波束形成效果,并以此为基础拓展到更复杂的自适应波束形成算法。
1. 均匀直线阵的常规波束形成:为什么“对准”一个方向,其他方向的声音就变小了
把几个麦克风排成一条直线,不做任何 fancy 处理,只把每路信号加个延迟再求和——这就是常规波束形成(Conventional Beamforming, CBF)。听起来像个“加法和延迟”的小把戏,但它是阵列信号处理里最底层的基石:一个 8 元均匀直线阵(ULA),阵元间距半波长,就能把某个方向的来波增益抬高到 8 倍,同时把正交方向的增益压到接近零。这个现象反直觉的地方在于:系统里没有任何一个滤波器在“削”信号,你只是把同一份声音的多个副本对齐相加,干涉本身就完成了空间滤波。
CBF 值得搞懂,不仅因为它是 MVDR、自适应波束形成、ESPRIT 这类高级算法的起点,更因为它的“缺陷”非常说明问题:主瓣宽度由阵列孔径决定、栅瓣由阵元间距决定、旁瓣电平由窗函数决定。这三个结论,没有一个是靠“调参”能绕过去的,它们刻在阵列的物理几何里。这篇文章从“为什么延迟求和能定向”讲起,一直拆到 CBF 的数学结构、仿真实现、以及那些让你在工程里翻车的细节。
2. 从“延迟求和”到空间滤波:CBF 的核心机制
2.1 远场模型:为什么一个来波可以看成一束平行线
均匀直线阵的经典假设是远场:声源距离阵列足够远,波前到达阵列时近似为平面波。这意味着从某个方向来的信号,到达每个阵元的路径差只取决于方向角和阵元间距,与声源距离无关。设阵元间距为 (d),来波方向与阵列法线的夹角为 (\theta),那么相邻阵元的波程差是 (d \sin\theta)。
这个几何关系是整篇分析的出发点。用复数基带表示,第 (m) 个阵元收到的信号可以写成:
[ x_m(t) = s(t) e^{j 2\pi f (m d \sin\theta / c)} ]
其中 (c) 是声速,(f) 是频率。把全部 (M) 个阵元的接收信号堆成向量,就得到了阵列流形向量(steering vector):
[ \mathbf{a}(\theta) = \left[ 1,\ e^{j 2\pi f d \sin\theta / c},\ e^{j 2\pi f \cdot 2d \sin\theta / c},\ \dots,\ e^{j 2\pi f (M-1)d \sin\theta / c} \right]^T ]
这个向量编码了“从 (\theta) 方向来的单位幅度信号,在阵列上会呈现什么相位分布”。注意它只与方向、频率和阵列几何有关,与信号内容无关。这是波束形成里最核心的量:所谓“对准某个方向”,本质就是构造一个与 (\mathbf{a}(\theta)) 共轭匹配的加权向量。
我一般会这么理解:阵列流形向量就是阵列的“空间指纹”。不同方向的来波,在阵列上留下不同的相位指纹,波束形成器做的事情就是拿一组加权系数去“识别”这个指纹。识别对了,信号同相叠加;识别错了,信号相互抵消——定向能力就来自这个干涉。
2.2 常规波束形成的数学结构:加权、求和、输出
CBF 的输出是对阵元信号做复加权再求和:
[ y(t) = \mathbf{w}^H \mathbf{x}(t) ]
其中 (\mathbf{w}) 是 (M \times 1) 的复权重向量。常规波束形成的权重取为:
[ \mathbf{w}_{\text{CBF}} = \frac{1}{M} \mathbf{a}(\theta_0) ]
也就是直接用目标方向的阵列流形向量作为权重。当来波方向与 (\theta_0) 一致时:
[ y(t) = \frac{1}{M} \sum_{m=0}^{M-1} s(t) e^{j 2\pi f m d \sin\theta_0 / c} e^{-j 2\pi f m d \sin\theta_0 / c} = s(t) ]
每个阵元的相位延迟被权重里的共轭相位完全补偿,M 路信号同相相加,幅度变成 M 倍,功率变成 M² 倍;除以 M 做归一化后,输出就等于原始信号。这就是“对准”的数学含义:不是放大信号,而是让各路副本相干叠加。
当来波方向偏离 (\theta_0) 时,相位补偿不完整,各路信号存在残余相位差,求和时发生部分抵消,输出幅度下降。这个“输出幅度随来波方向变化”的函数就是波束图(beam pattern):
[ B(\theta) = \left| \mathbf{w}^H \mathbf{a}(\theta) \right| = \frac{1}{M} \left| \sum_{m=0}^{M-1} e^{-j 2\pi f m d (\sin\theta - \sin\theta_0)/c} \right| ]
这是一个 Dirichlet 核的形式,主瓣方向和零点位置全部由指数项的相位差决定。你可以从两个角度理解:时域里,这是一个 FIR 滤波器,只不过抽头延迟换成了空间延迟;频域里,波束图就是空间频率响应的模——空间采样定理换了个马甲。
2.3 栅瓣出现的条件:空间采样定理的直观重述
波束图里最值得警惕的是栅瓣(grating lobe):在某些非目标方向,输出幅度与主瓣一样大。原因很简单:相位差以 (2\pi) 为周期,当其他方向的波程差恰好也凑成整数倍波长时,各路信号再次同相叠加。
数学上看,栅瓣出现在满足以下条件的方向:
[ \frac{2\pi f d (\sin\theta - \sin\theta_0)}{c} = 2\pi k,\quad k = \pm 1, \pm 2, \dots ]
想让整个可视区域内没有栅瓣,需要:
[ d \leq \frac{c}{2f} = \frac{\lambda}{2} ]
即阵元间距不超过半波长。这个条件在教材里通常被直接给出,但它本质上是空间采样定理:阵元是对连续孔径的空间采样,采样间隔大于半波长,波数域就会混叠。注意这里说的是“波数域混叠”,不是频谱混叠——你在时域做 ADC 时如果采样率不够,高频分量会折叠回低频;在空间域,如果阵元间距太大,某些方向的来波会伪装成其他方向的来波。
一个常见的直觉错误是“加大阵列尺寸就能提高分辨率”。阵列孔径确实决定主瓣宽度,但如果你通过拉大阵元间距来增加孔径,栅瓣也会随之出现。主瓣变窄和栅瓣出现是同一个几何公式的两个侧面。仿真里把间距设成 (d = \lambda) 跑一下 CBF,你会看到波束图里冒出两个一样高的峰——这不是 bug,是空间混叠。
2.4 主瓣宽度与旁瓣电平:窗函数为什么在这里也适用
CBF 的波束图可以改写成:
[ B(\theta) = \left| \frac{1}{M} \sum_{m=0}^{M-1} w_m e^{-j 2\pi f m d (\sin\theta - \sin\theta_0)/c} \right| ]
如果 (w_m) 不全取 1,而是取一个窗序列(Hamming、Blackman 等),波束图的主瓣会变宽、旁瓣会降低。这和时域 FIR 滤波器的窗函数设计完全同构:均匀加权对应矩形窗,第一旁瓣约 -13.3 dB;加 Hamming 窗后第一旁瓣降到约 -43 dB,但主瓣宽度从 (0.886\lambda/(Md)) 展宽到约 (1.3\lambda/(Md))。
这就是分辨率与干扰抑制的经典权衡。主瓣越窄,你区分两个相近方向的能力越强;但旁瓣越高,来自非目标方向的强干扰越容易泄漏进输出。CBF 里没有“既窄又低旁瓣”的自由参数——窗函数只能在这两个指标之间滑动,这是傅里叶变换的测不准原理在空间域的投影。
我用一个身边的例子来记这个结论:矩形窗的波束图在 (\sin\theta) 轴上的形状是 (\text{sinc}) 函数,主瓣两侧各有一个明显的负瓣。若你在阵列正前方放一个强干扰源,它的能量会透过这个旁瓣进入输出,而你丝毫不觉——波束图是功率响应,负瓣的相位信息在取模后完全消失,你看到的只是“不该有的能量”。
3. 从权重到实现:CBF 的复基带仿真与参数细节
3.1 为什么仿真里必须用复基带而不是实信号
很多初学者第一次写 CBF 仿真,直接把实正弦信号加延迟求和,跑出来的波束图却与理论不符。问题出在“延迟”的实现方式上:对实信号做延迟,需要在时域做插值滤波,或者用 FFT 搬移相位;而在复基带表示里,延迟就是乘一个复指数,干净利落。
复基带的约定是:把窄带信号表示为 (s(t)e^{j2\pi f_c t}),其中 (s(t)) 是复包络。阵列流形向量里的相位项 (e^{j2\pi f m d \sin\theta / c}) 只与载波频率有关,与基带信号的内容无关。仿真时你可以直接用 Python 生成这些复指数,矩阵运算一次完成。以下是一个最简实现:
import numpy as np # 参数设置 M = 8 # 阵元数 d = 0.5 # 阵元间距,单位:波长 theta0 = 30 # 期望方向,单位:度 theta = np.linspace(-90, 90, 1801) # 扫描角度 # 构造阵列流形矩阵 def array_manifold(M, d, theta): # theta: 角度数组(度) # 返回形状 (theta_len, M) 的复数矩阵 theta_rad = np.deg2rad(theta) kd = 2 * np.pi * d # 波数乘间距,假设频率为载波频率 m = np.arange(M) # 每一行对应一个方向 manifold = np.exp(1j * kd * np.outer(np.sin(theta_rad), m)) return manifold A = array_manifold(M, d, theta) # 构造 CBF 权重 theta0_rad = np.deg2rad(theta0) w = np.exp(1j * 2 * np.pi * d * np.sin(theta0_rad) * np.arange(M)) / M # 计算波束图 beam = np.abs(A @ w) # 复数内积的模 beam_db = 20 * np.log10(beam + 1e-12) # 打印主瓣附近的零点位置 peak_idx = np.argmax(beam_db) print(f"主瓣峰值角度: {theta[peak_idx]:.1f} 度")代码的核心只有两行:A @ w计算所有扫描方向的阵列响应,np.abs取模得到幅度波束图。np.outer(np.sin(theta_rad), m)生成的是 (M) 个阵元的相位累加项,每条扫描方向对应一行。
注意kd = 2 * np.pi * d这里频率不是显式参数,因为整个分析在“以波长为单位”的约定下进行:阵元间距 (d) 直接写成波长的倍数,载波频率被归一化掉了。如果你想仿真不同频率的行为,需要把 (kd) 改成 (2\pi f d / c),让频率显式参与。
3.2 参数变化时看什么:主瓣零点、栅瓣、还有那些“看不见”的量
跑完上面的代码后,你手上有一张波束图。不要只看“主瓣在 30 度”就完事。我一般会按顺序检查四个量:
主瓣宽度。从峰值往两侧找到第一个零点,两点之间的角度就是主瓣零点宽度。理论上它是 (2 \arcsin(\lambda/(M d))) 的近似。把 (M) 从 8 改成 16,零点宽度缩一半——这是阵列孔径带来的分辨率提升。
栅瓣位置。把d = 0.5改成d = 1.5,波束图上会出现两个等高的峰。一个在 30 度,另一个大约在 (\arcsin(\sin 30^\circ - 1/1.5) \approx -14.5) 度。此时你会直观看到“空间混叠”:来自 -14.5 度的信号,会被系统当成 30 度的信号完全接收。
旁瓣电平。均匀加权时第一旁瓣固定在约 -13.3 dB,这是矩形窗的 Fourier 变换性质。加 Hamming 窗后,旁瓣降低但主瓣变宽。在代码里给权重乘一个窗序列,两行就能完成。
但有一个量是波束图上看不见的:输出信噪比。CBF 对不相关噪声有 (M) 倍的功率增益(输出 SNR 提升 (10\log_{10} M) dB),但波束图只描述了对方向性信号的响应。当阵元噪声彼此独立时,CBF 的阵列增益是固定的,与波束形状无关。曾被这个问题坑过——仿真里只看波束图,以为旁瓣高 SNR 就差,实际上对白噪声而言,旁瓣高度不影响阵列增益。
3.3 “指向”到底在调什么:CBF 权重与转向向量的相位关系
CBF 的权重向量看似简单,但工程实现里有一个容易搞反的细节:用 (\mathbf{a}(\theta_0)) 还是 (\mathbf{a}^*(\theta_0)) 作为权重。不同的阵列流形定义方式(信号模型用 (e^{+j\phi}) 还是 (e^{-j\phi}))会导致共轭位置不同,符号错了波束图指向变成 (-\theta_0)。
一个稳妥的做法是,在代码里用同一个函数生成“发射”和“接收”两个阵列流形向量,然后让权重的相位与目标方向流形向量的相位共轭匹配。例如上面的实现:
w = np.conj(A_target) / M # A_target 是目标方向的流形向量这里的conj不是装饰,而是 CBF 的本质操作:乘以共轭相位来抵消传播延迟,把不同阵元上的信号“搬回”到同一相位基准。如果漏掉这一步,输出的相位关系就是错的,波束图会完全镜像翻转。
另一个常见问题是把 CBF 理解成“给每个阵元一个固定增益”。实际上 CBF 权重是频率的函数(相位随频率线性变化),宽带信号下必须做频域处理或真延迟线,否则波束方向会随频率漂移,即波束色散。仿真里如果直接对宽带信号用复权重,输出会出现明显失真——这不是 CBF 的缺陷,而是窄带假设被突破后的自然结果。
4. 避坑指南:CBF 仿真里的五个经典翻车现场
4.1 现象:波束图主瓣不在期望方向
原因:阵列流形向量的符号约定不一致。某个函数里用np.exp(-1j * kd * sin(theta) * m),权重里用np.exp(1j * ...),两者混用,结果主瓣出现在镜像方向。
解决:统一约定。在项目开头定义一个函数生成 steering vector,全代码只调用它。并在测试里加一条断言:beam_argmax == theta0。如果断不过,优先检查符号,而不是去调角度。
4.2 现象:d = 0.5 时波束图在端点处冒出一个等高的“假峰”
原因:这通常不是栅瓣,而是端射方向((\theta = \pm 90^\circ))的视在响应。半波长间距在端射方向上的等效相位差不是零,但端射方向本身的投影面积小,波束图计算没有考虑阵元指向性。
解决:如果你要仿真全向阵元,确认波束图公式里没有混入阵元方向图因子;如果你用的是实际麦克风(有心形指向),需要把阵元方向图乘进去。单独的 CBF 标准模型假设阵元全向,端射响应偏高是模型特性,不是错误。
4.3 现象:把阵元间距从 0.5 改成 0.49,波束图“变差”了
原因:你没看错,间距略小于半波长不会导致栅瓣,但主瓣会更宽。这不是 bug,而是孔径缩小的必然结果。问题的本质是你在试图“用更短的阵列达到同样的分辨率”,这不可能。
解决:把期望的分辨率转成最小孔径需求,再倒推阵元数和间距。公式是主瓣零点宽度 (\Delta\theta \approx 2\arcsin(\lambda/(M d))),先用它算孔径 (L = M d),再在无栅瓣约束((d \le \lambda/2))下选 (M)。
4.4 现象:仿真信号用了实正弦,结果波束图“抖动”
原因:实信号包含正负频率成分,CBF 的复权重只对正频率分量正确,负频率分量的相位是共轭的,导致周期性畸变。典型表现是波束图在某些角度出现与理论不符的波纹。
解决:改用复解析信号。工程里常见的做法是用scipy.signal.hilbert把实信号转成解析信号再处理,或者直接在频域做单边带处理。窄带仿真从源头就用复指数,省掉这一层麻烦。
4.5 现象:加窗之后主瓣“变胖”,但旁瓣没有明显降低
原因:你可能把窗乘在时间快拍上,而不是乘在阵元维度上。CBF 里的窗作用于空间域(阵元序号方向),不是时间域。两个维度都叫“窗”,但作用对象完全不同。
解决:确认窗序列的长度是M,且在权重向量上有w = w * window。检查波束图的第一旁瓣是否接近 -43 dB(Hamming):如果不是,检查窗是不是乘反了维度。另一个隐蔽错误是窗函数作用在 steering vector 上,而不是权重上——数学上等效,但代码结构上容易让人误判。
5. 窄带 CBF 到宽带波束形成:为什么“延迟”两个字没那么简单
5.1 窄带假说什么时候失效
前面所有分析都假设窄带:信号带宽远小于载波频率,阵列流形向量在每个频率上近似相同。但真实声学信号(语音、机械噪声)往往是宽带,带宽可以占中心频率的 30% 以上。此时如果还用单一频率的权重,各个频率分量经过阵列时的延迟相位不同,波束方向在每个频率上都不一样,输出信号会出现幅度和相位畸变。
一个直观的验证方法:把一段宽带信号送入窄带 CBF,观察输出频谱。你会发现高频分量和低频分量的增益不同,波束图变成一个随频率变化的曲面,而不是一条曲线。这就是波束色散。解决思路有两个方向:频域分带处理,或者时域真延迟线。
5.2 时域真延迟与频域子带分解的权衡
时域方案:把每个阵元的复权重换成一组 FIR 滤波器,每个滤波器设计为“带通 + 真延迟”。优点是一步到位,适用于实时处理;缺点是 FIR 阶数随带宽和阵列规模增大,计算量大。
频域方案:把信号分帧做 FFT,在每一个频点上独立计算 CBF 权重,然后 IFFT 合成。优点是每个频点都能精确控制相位,实现简单;缺点是频域分辨率受帧长限制,低频频点上的波束主瓣宽度会被帧长拖累。
工程上两者都常用。雷达和声呐倾向于频域,因为窄带本身就多;麦克风阵列实时语音处理倾向于时域 FIR,因为延迟小、逐样本输出。选择时有一个关键指标:你要的波束主瓣宽度对应多少个波长,如果低频分量波长太长,阵列电尺寸不够,主瓣会很宽——这不是算法能救的,和第二章的孔径结论是同一件事。
5.3 频域 CBF 的一个参数级细节:子带权重别忘掉归一化
频域实现时,每个频点 (f_k) 的权重为:
[ \mathbf{w}(f_k) = \frac{1}{M} \mathbf{a}(f_k, \theta_0) ]
注意这里的归一化系数 (1/M) 与频率无关,但如果你在不同频点分别做归一化,输出的宽带信号幅度在不同频率上会不一致,导致频谱倾斜。正确做法是把参考频点(如中心频率)的归一化系数固定下来,其他频点只做相位补偿,幅度归一化统一在参考频点做。
我曾在这个细节上栽过:频域 CBF 的输出频谱从低频到高频逐渐抬高,一开始以为是窗函数的问题,排查半天才发现是每个频点都乘了 (1/M),宽带能量被频率加权了。把归一化挪到参考频点后,频谱恢复正常。这类问题波束图上看不见,只能在输出信号的频域检查里发现。
6. 回到设计取舍:CBF 的“最优”与“次优”,以及窗函数教给我们的哲学
CBF 在数学上有一个明确的最优性:当噪声是空间白噪声(各阵元独立同分布)时,CBF 是最大输出信噪比波束形成器。这个结论常被忽略,因为大家更关心干扰抑制,但它是理解自适应波束形成的一把钥匙。MVDR 之所以在 CBF 之上,是因为它针对的是“非白”噪声场——存在方向性干扰时,CBF 的旁瓣会漏进干扰能量,而 MVDR 可以自适应地在干扰方向放置零点。两者的关系不是“先进替代落后”,而是“白噪声环境下 CBF 已经最优,不需要更复杂的东西”。
但问题的另一面是:MVDR 的干扰抑制能力来自对协方差矩阵的估计,而这个估计需要数据支撑。快拍数不足,矩阵求逆就会放大噪声,波束图变成一团糟。CBF 虽然没有自适应能力,但它对协方差矩阵的估计误差完全不敏感——权重里没有数据依赖,只有几何关系。这是 CBF 至今没有退出工程舞台的根本原因:鲁棒性是一种设计取舍,而不是缺陷。
窗函数的选择也体现了同样的哲学。均匀权重给你最窄的主瓣,但换来 -13.3 dB 的旁瓣;Hamming 窗把旁瓣压到 -43 dB,主瓣却宽了接近一半。在空间谱估计(比如 DOA 扫描)里,主瓣越窄越好;在干扰抑制里,旁瓣越低越好。没有哪个窗是“最好”的,你选的其实是“你对哪种失败更容忍”。
从那以后,我每设计一个新阵列的第一件事就是跑一遍 CBF 基线:白噪声环境下,CBF 的 SNR 增益是否达到 (10\log_{10} M) dB;加窗后旁瓣是否与窗函数的理论值一致;改变扫描方式后主瓣指向是否依然精确对着目标方向。基线过了,才敢上 MVDR,才敢谈自适应。这个习惯救了我很多次——阵列信号处理里,90% 的“高级算法翻车”都源自基线没打牢。希望这篇文章能帮你在自己的项目里少走一段弯路,先用 CBF 把几何、采样、干涉这三件事吃透,再往深水区走。
这份资源里的代码和说明,恰好覆盖了我上面提到的所有关键点:从阵列流形向量的构造、CBF 权重的推导、波束图的可视化,到栅瓣、加窗、宽带扩展的全部流程。值得作为你跑通第一个阵列仿真、理解空间采样定理的起点。
本文还有配套的精品资源,点击获取