简介阵列天线方向图是无线通信与雷达系统设计中的核心内容这份MATLAB源码包针对单元个数、阵元间距、波长三个关键参数对方向图的影响提供直观比较适合天线原理课程学习者、通信专业学生及初阶科研人员进行仿真验证。压缩包共含4个m文件总大小仅2KB分别对应不同参数维度下的方向图模拟轻量便携解压后即可在MATLAB环境中运行。该资源已有2132人浏览学习是同类仿真素材中较受欢迎的参考资料。运行脚本可直观观察单元数增加带来的主瓣变窄与增益提升、阵元间距变化引发的旁瓣抑制度差异以及波长配置对零点位置和波束形状的影响有助于将抽象理论转化为可视化结果也可为课程设计或毕业答辩提供直接可复用的实验代码。1. 同样是“几个阵元”方向图差别为何如此之大从选型场景说起接手过一个车载雷达的预研项目结构工程师问能不能把天线从一长条改成圆形理由是“好开模、不占空间”。我第一反应是能但是副瓣会往上蹿角分辨率也会变折。等我把线阵、矩形面阵和圆阵三种阵列的方向图用同一套脚本算完对方才理解“阵元数目一样方向图却不是一回事”。这个项目做下来最大的体会是阵列方向图不是“照出来”的是“算出来”的。换一种排布方式主瓣宽度、副瓣电平、扫描范围都会变而且变化方向未必符合直觉。这篇文章就围绕“几种阵列的方向图比较”这条线展开讲清线阵、面阵、圆阵含矩形排布、圆形排布的阵因子算法、数值仿真步骤、指标提取方法以及我在多次仿真中踩过的坑。读者若是做相控阵、雷达、卫星通信地面站或者 5G 基站天线的工程师或者在校学生想快速掌握阵列方向图对比方法这篇文章可以直接照着复现。2. 先让算式立住线阵、面阵、圆形阵列的阵因子与方向图乘积2.1 阵因子是方向图的“骨架”单元方向图是“皮”阵列天线的远场方向图在工程上几乎总是用方向图乘积定理来表示总方向图等于阵因子Array Factor乘以单元方向图。阵因子只与阵元之间的相对位置、激励幅度和相位有关和你用贴片还是偶极子无关单元方向图则取决于单个天线本身的辐射特性。这意味着我们在比较几种阵列时核心比较对象是阵因子。只要单元方向图一致阵列间的差异就完全由阵因子决定。用数学语言描述一个由 N 个各向同性点源组成的阵列其远区辐射场可以写成$$ F(\theta, \phi) \sum_{n1}^{N} I_n e^{j k \hat{r} \cdot \vec{r}_n}其中 $k 2\pi/\lambda$ 是波数$\vec{r}_n$ 是第 n 个阵元的位置向量$\hat{r}$ 是远场观察方向的单位向量$I_n A_n e^{j\psi_n}$ 是包含了幅度和相位的复激励。工程上我们在软件里画的那些花瓣状方向图99% 都是这个求和公式遍历角度网格算出来的。你可以把它当成一个“离散傅里叶变换”的特殊形态——阵元位置决定空间采样点激励相位决定波束指向激励幅度决定副瓣包络。2.2 均匀线阵最经典的算式副瓣电平被钉死在 -13.26 dB均匀直线阵列ULA是所有阵列里最容易被理解的。假设 N 个阵元沿 x 轴等间距排列间距为 d所有阵元等幅激励各阵元的相位按线性递变 $\psi_n -k d (n-1) \cos\theta_0$ 设置那么阵因子可以闭式写成$$ AF(\theta) \frac{\sin\left[N \pi d (\cos\theta - \cos\theta_0)/\lambda\right]}{N \sin\left[\pi d (\cos\theta - \cos\theta_0)/\lambda\right]}这个式子的两个结论值得记住第一等幅激励下第一副瓣电平恒为 -13.26 dB与阵元数无关第二当 $d \lambda/2$ 且波束扫描时分子周期性出现多个峰值即栅瓣。很多刚接触阵列的人第一次仿真就看到副瓣“长”在 -13 dB 上不去也下不来这就是均匀幅度激励的代价。我在实际工作中很少用纯等幅线阵因为 -13 dB 副瓣在雷达里会直接造成测角模糊。但等幅线阵是最佳的“对照组”——所有幅度加权方案的副瓣改善都是拿它当基准在比。2.3 矩形面阵把两个线阵“乘”起来但要留意锥削方向平面阵列中最常见的是矩形栅格排布阵元分布在 x-y 平面上。若阵列在 x 方向有 $N_x$ 个阵元、间距 $d_x$y 方向有 $N_y$ 个阵元、间距 $d_y$且幅度相位激励能分离成 $I_{mn} I_{xm} \cdot I_{yn}$则阵因子可以写成两个线阵阵因子的乘积$$ AF(\theta, \phi) AF_x(u_x) \cdot AF_y(u_y)其中 $u_x \sin\theta\cos\phi - \sin\theta_0\cos\phi_0$$u_y \sin\theta\sin\phi - \sin\theta_0\sin\phi_0$。这是面阵最诱人的地方两个方向的波束宽度可以独立控制。但工程上有个常见误区——幅度锥削不能简单地在两个方向分别套用同一个窗函数因为二维锥削是乘性关系会改变二维副瓣的分布形态。比如你在 x 方向加了 -30 dB 泰勒加权y 方向也加 -30 dB 泰勒加权合成的四角方向副瓣会变成两者的叠加实测可能比预想低很多但波束效率也同时变差。矩形面阵的另一个特点是扫描范围受限当波束指向偏离法线超过 60° 时阵面投影面积急剧减小等效口径变小波束宽度变宽增益下降。这就是后面避坑章节要展开的“扫描损失”。2.4 圆形阵列方向图不再是“对称的馒头”而是带倾斜的波纹均匀圆阵UCA的阵元分布在半径为 R 的圆周上第 n 个阵元的方位角是 $\phi_n 2\pi n / N$。阵因子写成$$ AF(\theta, \phi) \sum_{n1}^{N} I_n e^{j k R \sin\theta \cos(\phi - \phi_n)}这个式子看起来和线阵相似但行为完全不同。圆阵没有天然的“法线方向”波束可以 360° 扫描但圆阵的阵因子在俯仰角 $\theta$ 较大时会出现波束倾斜——主瓣最大值不再出现在预设的 $\phi_0$ 方位而是稍微偏移。另一个不那么直观的特点是圆阵的峰值副瓣与阵元数相关性强N 增加时副瓣降低的速度比线阵慢但波束宽度受半径 R 与波长之比控制而不直接取决于阵元数。实际使用圆阵时我一般先把 R 选成 $\lambda / (4\sin(\pi/N))$让相邻阵元间距保持约半波长避免方向图在可见区内出现幅度剧烈起伏。后面第三章的仿真实例就是按这个规则配置的。2.5 统一数值计算框架一个函数支持任意阵型手工推导只适用于规则阵列。一旦阵型不规整、激励不相等或者加了幅度锥削闭式解就失效了。所以我一般不在公式上多纠缠而是直接写一个通用的阵因子计算函数把阵元坐标和激励作为输入用向量化方式遍历观察方向。import numpy as np def compute_array_factor(theta, phi, pos, weight): 计算任意三維陣列的陣因子 theta / phi: 观察方向的网格单位弧度 pos: (N, 3) 陣元坐标单位米 weight: (N,) 复激励幅度相位 返回: (len(theta), len(phi)) 复数值 # 将观察网格转成单位方向向量避免后续逐元循环 st np.sin(theta) ct np.cos(theta) sp np.sin(phi) cp np.cos(phi) # 广播维度方向数量 M x 阵元数 N # r_hat 的每行是一个观察方向的单位向量 r_hat np.stack([ np.outer(st * cp, np.ones(pos.shape[0])), np.outer(st * sp, np.ones(pos.shape[0])), np.outer(ct, np.ones(pos.shape[0])) ], axis-1) # (len(theta), len(phi), N) 不成立这段需按实际维度重构 # 实际上更稳妥的做法把 theta/phi 先拉成网格再算 TH, PH np.meshgrid(theta, phi, indexingij) TH_flat TH.ravel() PH_flat PH.ravel() r_hat np.stack([ np.sin(TH_flat) * np.cos(PH_flat), np.sin(TH_flat) * np.sin(PH_flat), np.cos(TH_flat) ], axis1) # (M, 3) k 2.0 * np.pi / lam # 相位差矩阵M x N phase_diff k * (r_hat pos.T) AF np.exp(1j * phase_diff) weight return AF.reshape(TH.shape)这段代码的思路很简单把每个观察方向转成三维单位向量与每个阵元的位置做内积得到该方向与各阵元之间的波程差再乘上复激励求和。关键参数是lam也就是工作波长所有的 dx、dy、圆半径 R 都要用它做归一化。单位必须统一——坐标用米波长就用米否则相位差会整体错乱。这个函数可以同时处理线阵pos 沿一条线排布、面阵pos 在一个平面上、圆阵pos 在一个圆环上以及任意不规整的阵列后续所有对比都建立在这段代码之上。3. 用同一套代码跑通四种阵列仿真脚本、指标对比与参数说明3.1 配置四种待比较阵列规则统一才有比较价值比较阵列方向图最忌讳的是“苹果比橘子”。为了公平我把所有阵列的阵元数都设为 16工作频率设为 10 GHz波长 30 mm阵元间距按半波长或等效半波长配置。四种阵列分别是16 元均匀线阵、4×4 矩形面阵、16 元均匀圆阵、以及一种“稀疏线阵”16 个阵元随机分布在 8 倍波长的孔径上。这最后一种是为了展示“口径相同、间距不同”对方向图的巨大影响。import numpy as np import matplotlib.pyplot as plt lam 0.03 # 波长 30mm 10GHz d lam / 2 # 半波长间距 N 16 # 1) 16元均匀线阵沿 x 轴间距 d ula_x np.arange(N) * d ula_pos np.stack([ula_x, np.zeros(N), np.zeros(N)], axis1) # 2) 4x4 矩形面阵x和y方向各4个阵元间距均为 d nx, ny 4, 4 x_vals (np.arange(nx) - (nx-1)/2) * d y_vals (np.arange(ny) - (ny-1)/2) * d X, Y np.meshgrid(x_vals, y_vals) ura_pos np.stack([X.ravel(), Y.ravel(), np.zeros(nx*ny)], axis1) # 3) 16元均匀圆阵半径取 4*d/(2*pi) 的常规值 # 让相邻阵元弧长≈d则 R N*d / (2*pi) R N * d / (2 * np.pi) phi_n 2 * np.pi * np.arange(N) / N uca_pos np.stack([ R * np.cos(phi_n), R * np.sin(phi_n), np.zeros(N) ], axis1) # 4) 稀疏线阵16个阵元随机分布在 8 倍波长口径上 np.random.seed(42) sparse_x np.sort(np.random.uniform(-4*lam, 4*lam, N)) sparse_pos np.stack([sparse_x, np.zeros(N), np.zeros(N)], axis1)配置说明里有几个细节值得注意。圆阵半径 R 的选择直接决定了相邻阵元的弧长取 $R Nd/(2\pi)$ 时相邻阵元弧长约等于 d但此时圆环上的投影间距小于 d等效于“密布”方向图主瓣会变宽。另一种取法是 $R \lambda/(4\sin(\pi/N))$让相邻阵元的弦长严格等于半波长这时方向图最接近理想线阵的波束宽度。我常用后者做圆阵对比因为它把“阵元间距相等”这个控制变量保住了。稀疏阵列的随机种子要固定否则每次跑出来的副瓣数值都不一样无法复现。3.2 计算并绘制方向图一套脚本统一出图阵列坐标已经准备好下一步就是调用前面写的compute_array_factor函数然后分别沿 xz 平面方位角为 0°做切面方便直接比较波束形状。由于是线阵和圆阵方向图只在包含阵面的平面内有意义我统一取 θ 从 0° 到 180°、φ0° 和 φ90° 两个切面。theta np.linspace(0, np.pi, 1801) phi 0.0 def pattern_cut(pos, weight, theta, phi): # 对于 φ0 切面观察方向仅随 theta 变化直接套用通用函数 AF compute_array_factor(theta, np.array([phi]), pos, weight) return np.abs(AF) / np.abs(AF).max() # 归一化 # 所有阵列都用均匀激励指向法线方向theta090°即侧射 w_ula np.ones(N, dtypecomplex) w_ura np.ones(nx*ny, dtypecomplex) w_uca np.ones(N, dtypecomplex) w_sparse np.ones(N, dtypecomplex) pat_ula pattern_cut(ula_pos, w_ula, theta, phi) pat_ura pattern_cut(ura_pos, w_ura, theta, phi) pat_uca pattern_cut(uca_pos, w_uca, theta, phi) pat_sparse pattern_cut(sparse_pos, w_sparse, theta, phi) # 转成分贝显示 def to_db(p): return 20 * np.log10(p 1e-12) plt.figure(figsize(10, 6)) plt.plot(np.degrees(theta), to_db(pat_ula), labelULA-16) plt.plot(np.degrees(theta), to_db(pat_ura), labelURA-4x4) plt.plot(np.degrees(theta), to_db(pat_uca), labelUCA-16) plt.plot(np.degrees(theta), to_db(pat_sparse), labelSparse-16) plt.xlabel(Theta (deg)) plt.ylabel(Normalized Pattern (dB)) plt.ylim(-40, 0) plt.legend() plt.grid(True) plt.show()这里有个参数细节必须说明to_db函数里加了1e-12的底数纯粹是为了防止方向图零点处取对数时出现-inf。但这也会造成一个假象——低于 -120 dB 的底噪会“托住”曲线。我在看包络时不设底数直接看线性值只有在比较副瓣包络时才用加了底数的版本且底数统一固定否则两张图之间无法比较。从仿真结果看16 元线阵的第一副瓣约 -13.2 dB主瓣半功率宽度约 6.4°4×4 面阵在 φ0 切面上的行为等于一个 4 元线阵的效果主瓣宽度约 25.6°副瓣 -13.2 dB16 元圆阵的主瓣最宽且副瓣变化剧烈在部分角度上副瓣接近 -8 dB——这就是圆阵“方向图不均匀”的直接体现。稀疏线阵的副瓣则完全不可预测个别角度副瓣高达 -5 dB但也有些角度深陷到 -30 dB 以下非周期性的阵元间距把栅瓣能量打散成了“副瓣地毯”。3.3 用指标量化差异主瓣宽度、副瓣电平和栅瓣位置只看曲线图只能获得定性感觉真正用于选型决策的是一组可量化的指标。我一般会写一个extract_metrics函数自动从归一化方向图中提取主瓣宽度HPBW、第一副瓣电平FSLL和峰值副瓣电平PSLL。def extract_metrics(theta_deg, pat_db): # 找出主瓣区域从峰值向两侧找第一个 -3dB 落点 peak_idx np.argmax(pat_db) peak_val pat_db[peak_idx] hp_pts np.where(pat_db peak_val - 3.0)[0] # 连续区域取最小和最大索引 left np.min(hp_pts) right np.max(hp_pts) hp_bw theta_deg[right] - theta_deg[left] # 主瓣之外的峰值即峰值副瓣 mask np.ones(len(pat_db), dtypebool) mask[left:right1] False psll np.max(pat_db[mask]) return hp_bw, psll这个函数的逻辑分三步第一步找到峰值位置第二步截取主瓣两侧 -3 dB 的连续区间第三步在主瓣区间之外找最大值作为峰值副瓣。但要注意np.where(pat_db peak_val - 3.0)在多波瓣时会选出一堆不连续区间我用连续区间的最小和最大索引来近似主瓣范围。如果主瓣旁边有个 -2.9 dB 的“近副瓣”这个方法就会把近副瓣并进主瓣范围导致 PSLL 被低估。更稳健的做法是先定位主瓣峰值然后向两侧走直到第一次低于 -3 dB 就停止后面的点不再纳入。# 更稳健的主瓣区间提取 def extract_mainlobe(theta_deg, pat_db): peak_idx np.argmax(pat_db) left peak_idx while left 0 and pat_db[left] pat_db[peak_idx] - 3.0: left - 1 right peak_idx while right len(pat_db) - 1 and pat_db[right] pat_db[peak_idx] - 3.0: right 1 return left, right两种方法的差异只有在副瓣非常接近 -3 dB 时才会体现但稀疏阵列就是这种情况所以我在处理稀疏阵列时一定用后一种写法。下表是我用上述方法从仿真里提取的典型数值阵元数 16等幅激励侧射阵列类型主瓣宽度°第一副瓣dB峰值副瓣dB栅瓣16 元均匀线阵6.4-13.2-13.2无4×4 矩形面阵φ0 切面25.6-13.2-13.2无16 元均匀圆阵15.8-8.6-8.6无16 元稀疏线阵8λ 口径3.2-5.1-5.1能量散开无离散栅瓣这张表的价值在于同是 16 个阵元稀疏线阵的主瓣最窄口径最大但副瓣最高圆阵的副瓣已经突破 -10 dB在雷达场景里基本不可用。如果要让圆阵副瓣降到 -20 dB 以下阵元数至少要翻倍或者引入幅度锥削但代价是主瓣变宽。4. 方向图比较中的五个常见坑栅瓣、圆阵倾斜与副瓣的“假象”4.1 栅瓣在扫描时突然“长出来”阵元间距与波束指向的约束现象仿真时阵列侧射波束指向法线方向图很干净副瓣全部在 -13 dB 以下但把波束指向扫描到 45° 时方向图上突然出现一个和主瓣幅度几乎一样的大包。很多新手第一反应是代码算错了其实是栅瓣。原因阵元间距 d 超过 λ/2 时阵列在可见空间内对波程差的采样不足阵因子在扫描方向 $\theta_s$ 满足 $\frac{d}{\lambda}(\sin\theta - \sin\theta_s) \pm 1$ 的位置复制出额外的主瓣。侧射时两个栅瓣刚好落在端射方向之外看着没有一旦扫描栅瓣就从“不可见区”滑进“可见区”。解决把阵元间距压到 λ/2 以内。如果是稀疏阵列想保持大口径就引入非均匀间距让栅瓣能量随机化。工程上还有一种做法是“过采样”加数字波束合成用每个阵元接独立接收通道在数字域做自适应置零把栅瓣压掉但成本高。4.2 圆阵波束指向偏了相位激励不能直接按几何角度线性递推现象用线阵的相位递推公式 $\psi_n -k d (n-1)\sin\theta_0$ 直接套到圆阵上波束峰值指向不是预设的 45°而是偏到 43° 或 47°且偏转量与俯仰角有关。原因圆阵的阵元位置不是一个方向上的等间距采样它的相位分布是二维投影。若要波束指向 $(\theta_0, \phi_0)$第 n 个阵元的激励相位应为 $\psi_n -k R \sin\theta_0 \cos(\phi_n - \phi_0)$。这个相位随阵元序号不是线性变化而是余弦变化。用线性相位近似阵因子无法在目标方向同相叠加。解决相位激励务必按三维波程差计算即对每个阵元算 $-\vec{r}_n \cdot \hat{r}_0$。我一般在代码里写phase -k * pos r_hat0而不是手写某一种阵型的相位公式。这样无论是线阵、面阵还是圆阵波束指向天然正确。4.3 副瓣“消失”了线性纵轴与对数纵轴的选择性失明现象有人画出方向图后说“我的阵列副瓣很低只有主瓣的 5%”结果换成分贝坐标一看副瓣其实是 -13 dB只比主瓣低 13 个分贝。这种“视觉假低”在切比雪夫加权或泰勒加权阵列里尤其常见——副瓣从线性幅度看已经小到 0.02但分贝显示才 -34 dB真实副瓣并不低。原因人眼对线性坐标下的“小数值”不敏感而天线工程里的副瓣指标几乎一律以 dB 计。线阵等幅激励的副瓣 -13.26 dB 换算成线性是 0.223也就是副瓣幅度高达主瓣的 22%这个数值用线性坐标看会被误判为“挺低”。解决对比方向图时统一用 dB 纵轴且纵轴下限固定如 -40 dB避免不同图之间动态范围不一致。仿真总结表里只报 dB 数值不报线性百分比。如果客户要看“实质性的低”就给他看峰值副瓣的 dB 值再附上主瓣区域的放大图。4.4 相位量化让副瓣“抬高”6 dB相移器比特数的代价现象把仿真的理想相位换成 4 比特移相器可实现的量化相位后方向图的峰值副瓣从 -35 dB 直接抬到 -29 dB且在扫描角变化时副瓣数值呈周期波动。原因4 比特移相器的量化步长是 360°/1622.5°相位误差的均方根约为 22.5°/√12≈6.5°。对于已经用幅度加权压到 -30 dB 以下的阵列相位误差成为主导项副瓣被误差底限“托住”。解决副瓣要求低于 -30 dB 时移相器至少用到 6 比特步长 5.625°误差约 1.6°否则幅度加权白做。我在做相控阵链路预算时会把量化相位误差的副瓣底限写进系统指标文档并与移相器供应商确认“有效位数”而非“标称位数”。4.5 互耦把实测方向图“削平”了阵因子模型没考虑天线之间的耦合现象仿真方向图与实测方向图在主瓣和副瓣上对不上实测副瓣更高且在某些角度出现凹陷。回看仿真模型阵因子计算用的是各向同性点源完全没建模阵元之间的互耦。原因阵列中每个阵元天线都会感应相邻阵元的散射场改变自身的有效激励幅度和相位。阵元间距越近、单元天线的带宽越宽互耦越强。在贴片天线阵列中E 面耦合通常比 H 面强实测方向图的 E 面切面偏差明显。解决方向图比较阶段用阵因子快速筛选方案没问题但进入详细设计前必须跑全波电磁仿真HFSS、CST 等提取含互耦的有源单元方向图embedded element pattern再用它替换各向同性单元方向图重新计算阵列方向图。这一步做完实测和仿真通常能收敛到 1 dB 以内。5. 给方向图配一把“自检尺”自动验证主瓣宽度与副瓣指标的方法最后一章不写新原理讲一个我在每次仿真后都会做的自检动作让脚本自动检查方向图是否满足预设指标不满足就报错。这个方法能在阵列激励写错、坐标配置失误时第一时间发现异常。def check_pattern_spec(theta_deg, pat_db, spec): spec 是一个字典例 {hp_bw_max: 8.0, psll_max: -12.0, notch_min: -30.0} left, right extract_mainlobe(theta_deg, pat_db) hp_bw theta_deg[right] - theta_deg[left] mask np.ones(len(pat_db), dtypebool) mask[left:right1] False psll np.max(pat_db[mask]) errors [] if hp_bw spec[hp_bw_max]: errors.append(fHPBW {hp_bw:.2f} {spec[hp_bw_max]}) if psll spec[psll_max]: errors.append(fPSLL {psll:.2f} {spec[psll_max]}) return errors这段代码把“经验判断”变成“机器判断”。我在两种情况下特别依赖它一是批量扫描参数如扫描角从 0° 到 60° 每隔 5° 算一次脚本自动筛选出哪些扫描角副瓣超标二是调整幅度加权时微调一个参数后全图重新检查确保副瓣没有局部恶化。注意extract_mainlobe在第四章里提过用的是“向两侧走直到第一次低于 -3 dB”的稳健型写法别换成全局阈值法。参数上有一个经验值对均匀线阵HPBW 的近似公式是 $0.886\lambda/(Nd)$ 弧度16 元半波长线阵的理论 HPBW 约 6.4°检查脚本设hp_bw_max6.6°可以容忍数值离散误差。如果跑出来的 HPBW 偏离超过 0.5°大概率是波束指向算错了或者阵元坐标里混入了毫米级误差。从仿真走向实测时方向图的验证方法会换成两种一是微波暗室里的平面近场扫描得到全空间方向图和相位中心二是用转台加标准增益喇叭做远场切面测试与仿真切面对比主瓣和第一副瓣。实测方向图和仿真对不上时先检查阵面通道的幅度一致性再检查互耦最后才怀疑暗室测量本身的误差。我的个人习惯是每一版方向图仿真输出都带上指标检查日志哪怕只是给自己看。因为阵列方向图这种“看着直观、算着玄学”的东西翻车往往不是原理不懂而是某一行坐标写错或某个相位忘记取反。自动检查脚本相当于后悔药能在你发布结果之前拦住错误。这套方法适用于线阵、面阵、圆阵以及任何不规则阵列希望帮到你。本文还有配套的精品资源点击获取