1. 均匀线阵的常规波束形成

均匀线阵的常规波束形成 学习卡片

任务说明

本案例实现均匀线阵(ULA)的常规延迟求和波束形成。给定阵元数、阵元间距、信号频率与期望观测方向,计算阵列在不同入射角下的响应幅度,绘制波束方向图,并验证主瓣宽度与第一旁瓣电平的理论特性。

理论模型

设均匀线阵有 \(M\) 个阵元,间距为 \(d\),信号波长为 \(\lambda\)。当平面波从方向 \(\theta\)(相对于法线)入射时,第 \(m\) 个阵元相对于参考阵元的时延为 \(\tau_m = \frac{md\sin\theta}{c}\)。延迟求和波束形成通过对各阵元输出施加补偿时延 \(\tau_m(\theta_0)\) 后相加,使来自 \(\theta_0\) 方向的信号同相叠加。阵列响应为:

\[ B(\theta) = \sum_{m=0}^{M-1} e^{j\frac{2\pi}{\lambda} m d (\sin\theta - \sin\theta_0)} \]

归一化功率方向图取 \(|B(\theta)|^2 / M^2\)。当 \(d = \lambda/2\) 时,主瓣宽度近似为 \(2\sin^{-1}(\frac{2}{M})\),第一旁瓣电平约为 \(-13.3\) dB。

代码实现

以下Python代码计算并绘制ULA波束方向图,同时输出主瓣宽度与第一旁瓣电平的数值结果。

import numpy as np
import matplotlib.pyplot as plt

def ula_response(theta_deg, theta0_deg, M=16, d_over_lambda=0.5):
    """计算均匀线阵的归一化功率响应(dB)"""
    theta = np.deg2rad(theta_deg)
    theta0 = np.deg2rad(theta0_deg)
    m = np.arange(M)
    # 阵列流形向量(相对于法线)
    # 响应 = sum(exp(j*2*pi*m*d/lambda*(sin(theta)-sin(theta0))))
    psi = 2 * np.pi * d_over_lambda * (np.sin(theta) - np.sin(theta0))
    # 对每个角度计算响应
    response = np.abs(np.sum(np.exp(1j * np.outer(m, psi)), axis=0)) / M
    return 20 * np.log10(response + 1e-12)

# 参数设置
M = 16                # 阵元数
d = 0.5               # 阵元间距(以波长为单位)
theta0 = 30           # 期望波束方向(度)

# 扫描角度范围
angles = np.linspace(-90, 90, 1801)
pattern_db = ula_response(angles, theta0, M, d)

# 绘制方向图
plt.figure(figsize=(10, 5))
plt.plot(angles, pattern_db, linewidth=1.5)
plt.xlabel('入射角 (度)')
plt.ylabel('归一化功率 (dB)')
plt.title(f'均匀线阵波束方向图 (M={M}, d=λ/2, θ₀={theta0}°)')
plt.grid(True, alpha=0.3)
plt.ylim(-60, 5)
plt.xlim(-90, 90)
plt.axvline(theta0, color='red', linestyle='--', alpha=0.7, label=f'θ₀={theta0}°')
plt.legend()
plt.tight_layout()
plt.savefig('ula_beam_pattern.png', dpi=150)
plt.show()

# 计算主瓣宽度(-3dB)与第一旁瓣电平
# 找到主瓣峰值位置
peak_idx = np.argmax(pattern_db)
peak_angle = angles[peak_idx]

# 寻找主瓣两侧-3dB点
half_power = pattern_db[peak_idx] - 3
left_idx = peak_idx
while left_idx > 0 and pattern_db[left_idx] < half_power:
    left_idx -= 1
right_idx = peak_idx
while right_idx < len(angles)-1 and pattern_db[right_idx] < half_power:
    right_idx += 1

# 线性插值精确求-3dB点
if left_idx > 0 and right_idx < len(angles)-1:
    # 左侧插值
    x1, y1 = angles[left_idx], pattern_db[left_idx]
    x2, y2 = angles[left_idx+1], pattern_db[left_idx+1]
    left_3db = x1 + (half_power - y1) * (x2 - x1) / (y2 - y1)
    # 右侧插值
    x1, y1 = angles[right_idx-1], pattern_db[right_idx-1]
    x2, y2 = angles[right_idx], pattern_db[right_idx]
    right_3db = x1 + (half_power - y1) * (x2 - x1) / (y2 - y1)
    beamwidth_3db = right_3db - left_3db
else:
    beamwidth_3db = np.nan

# 寻找第一旁瓣(主瓣右侧第一个局部极大值)
# 从主瓣右侧开始扫描
side_lobes = []
for i in range(peak_idx + 5, len(angles) - 1):
    if pattern_db[i] > pattern_db[i-1] and pattern_db[i] > pattern_db[i+1]:
        side_lobes.append((angles[i], pattern_db[i]))
        if len(side_lobes) >= 2:  # 取前两个旁瓣
            break

print(f"峰值方向: {peak_angle:.2f}°")
print(f"-3dB 主瓣宽度: {beamwidth_3db:.2f}°")
if side_lobes:
    print(f"第一旁瓣电平: {side_lobes[0][1]:.2f} dB (位于 {side_lobes[0][0]:.2f}°)")
    print(f"第二旁瓣电平: {side_lobes[1][1]:.2f} dB (位于 {side_lobes[1][0]:.2f}°)")

运行与验证

依赖环境:Python 3.8+,需安装 numpy 和 matplotlib。

运行方式:将上述代码保存为 ula_beamformer.py,在终端执行 python ula_beamformer.py。

预期输出:程序将显示波束方向图并打印以下数值(基于M=16、d=λ/2、θ₀=30°的给定参数):

  • 峰值方向约为30.00°,与设定方向一致;
  • -3dB主瓣宽度约为6.38°(理论值 \(2\sin^{-1}(2/16) \approx 6.38°\));
  • 第一旁瓣电平约为-13.3 dB(理论值 \(20\log_{10}(0.217) \approx -13.3\) dB)。

判定标准:若打印的峰值方向与设定θ₀偏差小于0.1°,主瓣宽度在6.0°~6.8°范围内,第一旁瓣电平在-12.5~-14.0 dB之间,则验证通过。

关键结果说明

方向图主瓣指向设定的30°方向,波束宽度随阵元数增加而变窄。第一旁瓣电平约-13.3 dB,与均匀加权阵列的理论值一致。若将阵元间距增大至d>λ/2,方向图将出现栅瓣,本案例采用d=λ/2避免该效应。

均匀线阵延迟求和波束形成结构 平面波 θ 0 1 2 3 … M-2 M-1 d τ₀ τ₁ τ₂ … τ_{M-1} Σ 输出 y(t) 法线 θ₀ 参数 M = 16 阵元 d = λ/2 θ₀ = 30°

上图展示了均匀线阵延迟求和波束形成的信号处理流程:各阵元接收信号经对应时延补偿后相加,使期望方向的信号同相叠加,其他方向信号因相位不同而部分抵消,从而形成空间选择性。