3. 常规波束形成(CBF)方向图绘制

常规波束形成(CBF)方向图绘制 学习卡片

任务说明

本案例实现常规波束形成器(Conventional Beamforming, CBF),针对均匀线阵(ULA),绘制不同阵元数 \(N\) 与阵元间距 \(d\)(以波长 \(\lambda\) 归一化)下的波束方向图。通过方向图主瓣宽度与栅瓣出现条件,直观验证阵列设计参数对空间滤波性能的影响。

核心原理与实现

均匀线阵的导向矢量为 \(\mathbf{a}(\theta) = [1, e^{j2\pi d\cos\theta/\lambda}, \ldots, e^{j2\pi (N-1)d\cos\theta/\lambda}]^T\)。常规波束形成器对各阵元接收信号进行相位补偿后同相叠加,其方向图(阵列响应)为:

\[ B(\theta) = \left| \mathbf{w}^H \mathbf{a}(\theta) \right|, \quad \mathbf{w} = \mathbf{a}(\theta_0) \]

其中 \(\theta_0\) 为波束指向角。本实现中令 \(\theta_0 = 90^\circ\)(阵列法线方向),扫描角度范围为 \(0^\circ \sim 180^\circ\)(端射方向到端射方向)。代码直接计算不同参数组合下的方向图并绘制对比曲线。

CBF方向图计算与参数影响分析流程 输入参数 N ∈ {8, 16} d/λ ∈ {0.5, 1.0} θ₀ = 90° 导向矢量计算 a(θ) = [1, e^{j2πdcosθ/λ}, …, e^{j2π(N-1)dcosθ/λ}]ᵀ θ 扫描范围 0°~180° CBF波束形成 w = a(θ₀) B(θ) = |wᴴa(θ)| 归一化: 20log₁₀(B/Bmax) 方向图 关键观测点 • 主瓣宽度:N增大或d/λ增大时,主瓣变窄(波束更锐利) • 栅瓣条件:当 d/λ > 0.5 且扫描角较大时,出现栅瓣(如 d=λ, θ→0°或180°) • 副瓣电平:N变化不影响副瓣相对电平(约-13.3dB),d变化影响栅瓣位置 • 验证方法:对比N=8与N=16的3dB带宽,观察d=λ时方向图在端射方向是否出现等幅栅瓣

代码实现

import numpy as np
import matplotlib.pyplot as plt

def cbf_ula_pattern(N, d_over_lambda, theta0_deg=90.0):
    """
    计算均匀线阵常规波束形成方向图(线性幅度)
    
    参数:
        N: 阵元数量
        d_over_lambda: 阵元间距与波长之比 d/λ
        theta0_deg: 波束指向角(度),默认90°(法线方向)
    
    返回:
        theta_deg: 扫描角度数组 (0~180度)
        pattern_lin: 归一化方向图线性幅度 (最大值=1)
    """
    theta_deg = np.linspace(0, 180, 1801)  # 0.1°步进
    theta_rad = np.deg2rad(theta_deg)
    theta0_rad = np.deg2rad(theta0_deg)
    
    # 阵元位置(以波长为单位)
    positions = np.arange(N) * d_over_lambda
    
    # 导向矢量矩阵: shape (N, len(theta))
    # a_n(theta) = exp(j*2*pi*position_n*cos(theta))
    steering = np.exp(1j * 2 * np.pi * np.outer(positions, np.cos(theta_rad)))
    
    # 波束形成权重: 指向theta0的导向矢量
    w = np.exp(1j * 2 * np.pi * positions * np.cos(theta0_rad))
    
    # 阵列响应: w^H * a(theta)
    response = np.conj(w) @ steering  # 复数内积
    pattern_lin = np.abs(response) / N  # 归一化到最大值为1
    
    return theta_deg, pattern_lin

# ===== 参数设置 =====
configs = [
    {'N': 8,  'd': 0.5, 'label': 'N=8,  d=0.5λ'},
    {'N': 16, 'd': 0.5, 'label': 'N=16, d=0.5λ'},
    {'N': 8,  'd': 1.0, 'label': 'N=8,  d=1.0λ'},
]

# ===== 绘制方向图 =====
plt.figure(figsize=(10, 6))
for cfg in configs:
    theta, pat = cbf_ula_pattern(cfg['N'], cfg['d'])
    # 转换为dB,限制动态范围
    pat_db = 20 * np.log10(pat + 1e-12)
    pat_db = np.clip(pat_db, -60, 0)
    plt.plot(theta, pat_db, lw=1.8, label=cfg['label'])

plt.xlabel('扫描角度 θ (度)', fontsize=12)
plt.ylabel('归一化幅度 (dB)', fontsize=12)
plt.title('常规波束形成方向图对比 (波束指向90°)', fontsize=14)
plt.ylim(-60, 5)
plt.xlim(0, 180)
plt.grid(True, alpha=0.3)
plt.legend(fontsize=11)
plt.tight_layout()
plt.savefig('cbf_patterns.png', dpi=150)
plt.show()

# ===== 验证:打印主瓣宽度与栅瓣位置 =====
print("=== 参数验证 ===")
for cfg in configs:
    theta, pat = cbf_ula_pattern(cfg['N'], cfg['d'])
    # 找到主瓣3dB宽度(在90°附近)
    mainlobe = pat > 0.707  # -3dB点
    # 从90°向两侧搜索
    idx_center = np.argmin(np.abs(theta - 90))
    left_idx = idx_center
    while left_idx > 0 and pat[left_idx] > 0.707:
        left_idx -= 1
    right_idx = idx_center
    while right_idx < len(theta)-1 and pat[right_idx] > 0.707:
        right_idx += 1
    bw_deg = theta[right_idx] - theta[left_idx]
    
    # 检测栅瓣(除主瓣外幅度>0.5的峰值)
    grating = []
    for i in range(1, len(theta)-1):
        if pat[i] > 0.5 and pat[i] > pat[i-1] and pat[i] > pat[i+1]:
            if abs(theta[i] - 90) > 5:  # 排除主瓣
                grating.append(theta[i])
    
    print(f"{cfg['label']}: 3dB主瓣宽度≈{bw_deg:.1f}°, 栅瓣数量={len(grating)}")
    if grating:
        print(f"  栅瓣位置: {[f'{g:.0f}°' for g in grating]}")

运行与验证

运行方式:将代码保存为 cbf_pattern.py,在已安装 numpy 和 matplotlib 的Python环境中执行 python cbf_pattern.py。

预期输出与判定标准:

  • 程序生成 cbf_patterns.png,包含三条方向图曲线,波束指向均为90°。
  • 观察曲线:N=16的曲线主瓣明显窄于N=8(相同d=0.5λ时);d=1.0λ的曲线在0°和180°附近出现与主瓣等高的栅瓣。
  • 控制台打印的3dB主瓣宽度应满足:N=16约为N=8的一半(理论值约5.1° vs 10.2°);d=1.0λ时栅瓣数量为2(位于0°和180°)。
  • 若打印的栅瓣数量与理论一致且主瓣宽度随N增大而减半,则验证通过。

判定标准:方向图中d=1.0λ曲线在端射方向出现完整栅瓣(幅度接近0dB),且N=16主瓣宽度约为N=8的一半,即证明CBF实现正确,参数影响符合阵列信号处理理论。