☰
MATLAB直线天线阵仿真:从阵因子到波束扫描的完整实现
2026/10/13 4:56:40 网站建设 项目流程

简介:这份资源面向电子工程、通信与雷达方向的学生和研究人员,提供基于MATLAB的直线天线阵仿真完整案例,帮助理解阵元间距、馈电相位与频率对阵列辐射特性的影响。压缩包共9个文件,约1.1MB,包含1个m脚本文件与8个png图像文件:脚本用于构建偶极子天线单元、定义直线阵列几何结构并执行频率扫描与方向图绘制,图像则直观呈现不同配置下的二维与三维远场辐射结果,便于对照分析主瓣宽度、旁瓣电平与增益变化。已有611人学习下载,说明该案例在相关课程设计与科研入门中具有一定参考价值。读者可借助脚本与结果图快速复现仿真流程,掌握antennaArray、analyzeArray、pattern等函数的实际用法,并在此基础上调整阵列参数进行迭代优化,为天线阵列系统的设计与验证提供可复用的分析思路。

1. 直线天线阵仿真为什么值得用 MATLAB 从头搭一遍

很多人第一次接触阵列天线,是从教科书上那张“均匀直线阵”的波束方向图开始的:几个阵元排成一条线,等间距、等幅、等相位馈电,方向图就出现主瓣和一堆副瓣。但真到要验证一个加权方案、比较不同阵元间距对栅瓣的影响、或者给某个波束赋形算法做快速原型时,光看公式是不够的——你需要一个能改参数、能立刻出图、能反复试错的仿真环境。基于 MATLAB 的直线天线阵仿真,解决的正是这件事:用几十行代码把阵因子、方向图、波束宽度、副瓣电平、栅瓣条件全部算出来并画出来,让“调参看效果”变成几秒钟的事。它适合三类人:正在学天线阵列但被公式绕晕的学生、需要快速验证加权/扫描方案的算法工程师、以及要给更复杂系统做前期可行性摸底的研究者。下面我按自己实际搭这套仿真的顺序,把选型、代码、参数和踩过的坑讲清楚。

2. 先把阵因子模型立住:从物理到可计算表达式

2.1 为什么直线阵的核心是阵因子而不是单个阵元

直线天线阵的总方向图,在忽略阵元间互耦的理想情况下,可以写成“阵元方向图 × 阵因子”的形式。阵元方向图描述单个辐射单元自身的空间响应,阵因子则完全由阵元的排列方式、间距、馈电幅度和相位决定。做仿真时,如果你关心的是波束指向、副瓣电平、栅瓣这些阵列层面的行为,阵因子就是主战场;阵元方向图可以先用各向同性(全向)代替,等阵列行为验证无误后再乘上真实的阵元方向图。这样做的理由是:阵因子是解析可算的,改一个参数立刻能看到方向图变化,而阵元方向图往往需要电磁仿真软件或实测才能拿到,前期没必要卡在那里。

均匀直线阵的阵因子标准形式是:

AF(θ) = Σ_{n=0}^{N-1} a_n · exp(j·n·(k·d·cosθ + β))

其中 N 是阵元数,a_n 是第 n 个阵元的激励幅度,k = 2π/λ 是波数,d 是阵元间距,θ 是从阵列轴线量起的角度(注意不同教材对角度定义有差异,后面避坑章节会专门说),β 是相邻阵元之间的递变相位。如果取 a_n = 1、β = 0,就是最基础的均匀激励、边射阵;如果 β 取非零值,主瓣就会偏离边射方向,实现波束扫描。

2.2 用 MATLAB 把阵因子写成可复用函数

我一般不会把公式直接塞在主脚本里,而是先写一个独立的阵因子函数,输入角度、阵元数、间距(以波长为单位)、幅度加权向量和递变相位,输出归一化后的阵因子幅度。这样后面换加权、换扫描角,只改调用参数就行。

function af = array_factor(theta, N, d_lambda, amp, beta) % array_factor 计算均匀直线阵的阵因子 % theta : 观察角度向量,单位弧度 % N : 阵元数 % d_lambda : 阵元间距,以波长为单位 % amp : 激励幅度向量,长度必须为 N % beta : 相邻阵元递变相位,单位弧度 if length(amp) ~= N error('幅度向量长度必须等于阵元数 N'); end k = 2 * pi; % 波数,已按波长归一化 n = (0:N-1).'; % 阵元索引列向量 psi = k * d_lambda * cos(theta) + beta; % 相邻阵元相位差 % 对每个角度,计算所有阵元的贡献并求和 af = zeros(size(theta)); for idx = 1:length(theta) af(idx) = sum(amp .* exp(1j * n * psi(idx))); end af = abs(af) / max(abs(af)); % 归一化 end

这段代码里几个关键点:d_lambda用波长归一化,是为了让间距的影响与频率解耦,换频率时只需改波长对应的实际间距;psi是相邻阵元在给定观察方向上的总相位差,包含空间相位k·d·cosθ和馈电相位β;循环求和虽然可以向量化,但写成循环更直观,且对于几百个角度点和几十个阵元的规模,速度完全够用。归一化放在函数内部,是为了让不同参数下的方向图可以直接比较主瓣和副瓣的相对关系。

2.3 最小可跑脚本:8 阵元均匀边射阵

有了函数,主脚本就非常短。下面这段画出一个 8 阵元、半波长间距、均匀激励、边射(β=0)的直线阵方向图。

N = 8; d_lambda = 0.5; amp = ones(1, N); beta = 0; theta = linspace(0, pi, 3601); % 0 到 180 度,步进 0.05 度 af = array_factor(theta, N, d_lambda, amp, beta); figure; plot(theta * 180 / pi, 20 * log10(af + eps)); xlabel('角度 (度)'); ylabel('归一化幅度 (dB)'); title('8 阵元均匀直线阵方向图 (d=0.5\lambda, 边射)'); grid on; ylim([-40, 0]);

运行后你会看到主瓣在 90 度方向,第一副瓣大约在 -13 dB 附近,这是均匀激励直线阵的典型值。eps是为了避免对零取对数。角度范围取 0 到 180 度,对应从阵列一端到另一端的可见空间;如果你把角度定义成从阵列法线量起,范围就是 -90 到 90 度,这一点在避坑章节会展开。

3. 参数扫描与加权:把“调参看效果”变成流水线

3.1 阵元间距对栅瓣的影响:什么时候会翻车

阵元间距 d 是直线阵里最容易出问题的参数。d 太小,阵元间互耦增强,且主瓣变宽;d 太大,可见空间内会出现与主瓣幅度相当的栅瓣,导致能量分散甚至方向模糊。栅瓣出现的条件可以从阵因子相位差入手:当相邻阵元相位差 ψ 在可见空间内跨越 ±2π 时,就会出现多个同相叠加的方向。对于边射阵,不出现栅瓣的条件是 d < λ。但如果你做波束扫描,条件会更严:d < λ / (1 + |cosθ_max|),其中 θ_max 是最大扫描角偏离边射的角度。

我一般会写一个扫描脚本,把 d 从 0.3λ 扫到 1.2λ,看方向图怎么变。

N = 8; amp = ones(1, N); beta = 0; theta = linspace(0, pi, 3601); d_list = [0.3, 0.5, 0.7, 1.0, 1.2]; figure; hold on; for d_lambda = d_list af = array_factor(theta, N, d_lambda, amp, beta); plot(theta * 180 / pi, 20 * log10(af + eps), ... 'DisplayName', sprintf('d = %.1f\\lambda', d_lambda)); end xlabel('角度 (度)'); ylabel('归一化幅度 (dB)'); title('不同阵元间距下的方向图对比 (N=8, 边射)'); legend('Location', 'best'); grid on; ylim([-40, 0]); hold off;

跑完你会看到:d=0.3λ 和 0.5λ 时只有主瓣和副瓣;d=0.7λ 时副瓣开始抬高;d=1.0λ 时在 0 度和 180 度附近出现与主瓣同量级的栅瓣;d=1.2λ 时栅瓣更明显。这就是“间距不能随便取大”的血泪经验——很多人为了追求高增益把间距拉到 λ 以上,结果方向图直接翻车。

3.2 幅度加权:用泰勒窗和切比雪夫窗压副瓣

均匀激励的副瓣只有 -13 dB 左右,很多场景不够用。常见做法是给阵元加幅度加权,让中间阵元激励大、边缘阵元激励小,从而压低副瓣,代价是主瓣变宽。MATLAB 里可以直接用taylorwin和chebwin生成加权向量。

N = 16; d_lambda = 0.5; beta = 0; theta = linspace(0, pi, 3601); amp_uniform = ones(1, N); amp_taylor = taylorwin(N, 5, -30).'; % 5 个副瓣,目标 -30 dB amp_cheb = chebwin(N, 30).'; % 副瓣 -30 dB af1 = array_factor(theta, N, d_lambda, amp_uniform, beta); af2 = array_factor(theta, N, d_lambda, amp_taylor, beta); af3 = array_factor(theta, N, d_lambda, amp_cheb, beta); figure; plot(theta * 180 / pi, 20 * log10(af1 + eps), 'DisplayName', '均匀'); hold on; plot(theta * 180 / pi, 20 * log10(af2 + eps), 'DisplayName', '泰勒 -30dB'); plot(theta * 180 / pi, 20 * log10(af3 + eps), 'DisplayName', '切比雪夫 -30dB'); xlabel('角度 (度)'); ylabel('归一化幅度 (dB)'); title('不同幅度加权下的方向图 (N=16, d=0.5\lambda)'); legend('Location', 'best'); grid on; ylim([-50, 0]); hold off;

这里taylorwin(N, nbar, sll)的nbar控制副瓣数量,sll是目标副瓣电平;chebwin(N, sll)则给出等副瓣特性。注意加权向量需要转置成行向量或列向量与函数内部维度匹配,否则会报维度错误。跑完对比可以看到:泰勒和切比雪夫都能把副瓣压到 -30 dB,但主瓣宽度比均匀激励明显增加,这是绕不开的取舍。

3.3 波束扫描:改 β 就能让主瓣动起来

直线阵的波束扫描靠的是相邻阵元递变相位 β。对于边射阵,β=0,主瓣在 90 度(如果角度从阵列轴线量起)。要让主瓣指向 θ0,需要 β = -k·d·cosθ0。在 MATLAB 里改一个参数就能看到主瓣移动。

N = 8; d_lambda = 0.5; amp = ones(1, N); theta = linspace(0, pi, 3601); theta0_list = [90, 60, 45, 30]; % 目标扫描角,单位度 figure; hold on; for theta0 = theta0_list beta = -2 * pi * d_lambda * cosd(theta0); af = array_factor(theta, N, d_lambda, amp, beta); plot(theta * 180 / pi, 20 * log10(af + eps), ... 'DisplayName', sprintf('\\theta_0 = %d^\\circ', theta0)); end xlabel('角度 (度)'); ylabel('归一化幅度 (dB)'); title('波束扫描方向图 (N=8, d=0.5\lambda)'); legend('Location', 'best'); grid on; ylim([-40, 0]); hold off;

注意cosd是角度制余弦,和前面cos的弧度制区分开。扫描角越大,主瓣越宽,且副瓣电平会略微上升。当扫描到接近端射(θ0 接近 0 或 180 度)时,主瓣会明显展宽,这是直线阵的固有特性。

4. 避坑与排查:直线阵仿真里最容易翻车的五个点

4.1 角度定义混乱导致方向图“镜像”

现象:你按公式算出来的方向图,主瓣位置和预期关于 90 度对称,或者扫描方向反了。原因:不同教材对 θ 的定义不同,有的从阵列轴线量起,有的从阵列法线量起,导致cosθ和sinθ混用。解决:在代码开头用注释明确写清角度定义,并统一用cos或sin。我一般固定用“从阵列轴线量起”,这样边射阵主瓣在 90 度,端射在 0 或 180 度,不容易混。

4.2 间距单位没归一化,换频率就失效

现象:你按实际间距(比如 0.15 米)代入,在 2 GHz 下调好了,换到 3 GHz 方向图完全变了。原因:阵因子的相位差取决于电尺寸 d/λ,而不是物理尺寸。解决:始终用波长归一化间距d_lambda = d / lambda,物理间距只在最后换算时用一次。这样换频率只需改lambda,阵列行为不变。

4.3 加权向量维度不匹配导致报错或结果错误

现象:调用array_factor时报“矩阵维度必须一致”,或者结果明显不对。原因:amp是行向量,而函数内部n是列向量,MATLAB 的隐式扩展在某些版本行为不同。解决:在函数内部统一用amp(:).'转成行向量,或者显式检查length(amp) == N。我习惯在函数入口加一个维度检查,出错时直接给出明确提示。

4.4 归一化方式不同导致副瓣电平读数偏差

现象:你算出来的副瓣是 -13 dB,别人论文里写 -13.2 dB,差一点。原因:归一化方式不同,有的按主瓣最大值归一化,有的按总功率归一化。解决:在比较前确认双方归一化基准一致。我一般按主瓣最大值归一化,并在图注里写明,避免误读。

4.5 忽略互耦导致实测与仿真差距大

现象:仿真副瓣 -30 dB,实测只有 -20 dB。原因:阵元间互耦改变了各阵元的实际激励和方向图,理想阵因子模型没有考虑。解决:如果只是做算法原型,理想模型够用;如果要预测实测性能,需要用电磁仿真软件提取有源方向图,或者至少留出 3 到 5 dB 的余量。这一点在项目前期就要想清楚,别等实测翻车再找后悔药。

5. 进阶技巧:用方向图乘积和可见空间验证你的结果

5.1 把阵元方向图乘回去

前面所有仿真都假设阵元是全向的。实际阵元(比如半波振子)有自身方向图。常见做法是先把阵因子算好,再乘以阵元方向图。以半波振子为例,其方向图在包含振子轴线的平面内是cos(π/2·cosθ)/sinθ。你可以在array_factor输出后直接乘上这个因子,再归一化。

theta = linspace(0.01, pi-0.01, 3601); % 避开 0 和 pi 的奇异点 N = 8; d_lambda = 0.5; amp = ones(1, N); beta = 0; af = array_factor(theta, N, d_lambda, amp, beta); element = abs(cos(pi/2 * cos(theta)) ./ sin(theta)); % 半波振子方向图 total = af .* element; total = total / max(total); figure; plot(theta * 180 / pi, 20 * log10(total + eps)); xlabel('角度 (度)'); ylabel('归一化幅度 (dB)'); title('8 阵元半波振子直线阵方向图 (d=0.5\lambda, 边射)'); grid on; ylim([-40, 0]);

注意theta避开了 0 和 π,因为半波振子方向图在这两个点有 0/0 奇异,实际极限是 0。乘完之后你会看到端射方向被压低,这是阵元方向图带来的额外选择性。

5.2 用可见空间区域检查栅瓣

可见空间是阵列能实际辐射的区域,对应|cosθ| ≤ 1。在归一化相位差 ψ 的图上,可见空间对应 ψ 从-2πd/λ + β到2πd/λ + β。如果这个区间内出现多个 ψ = 2πm 的点,就有栅瓣。我一般会画一张 ψ 域的阵因子图,标出可见空间边界,一眼就能看出栅瓣风险。

N = 8; d_lambda = 0.7; beta = 0; psi = linspace(-4*pi, 4*pi, 4001); af_psi = abs(sin(N * psi / 2) ./ (N * sin(psi / 2) + eps)); af_psi = af_psi / max(af_psi); figure; plot(psi / pi, 20 * log10(af_psi + eps)); hold on; % 可见空间边界 psi_vis = 2 * pi * d_lambda; xline(psi_vis / pi, 'r--', '可见空间上界'); xline(-psi_vis / pi, 'r--', '可见空间下界'); xlabel('\psi / \pi'); ylabel('归一化幅度 (dB)'); title('\psi 域阵因子与可见空间 (N=8, d=0.7\lambda)'); grid on; ylim([-40, 0]); hold off;

这张图能帮你快速判断:可见空间内除了主瓣对应的 ψ=0,还有没有其他 2π 整数倍的点。如果有,就是栅瓣。这个方法比反复扫角度更直观,也是我调间距时最常用的验证手段。

5.3 一个我常犯的错:忘了检查扫描时的栅瓣条件

最后说一个我自己的教训。早期做波束扫描仿真时,我只盯着边射阵的 d < λ 条件,把间距设成 0.9λ 就开始扫描,结果扫到 60 度时栅瓣直接冒出来,方向图惨不忍睹。后来才养成习惯:只要涉及扫描,先算d < λ / (1 + |cosθ_max|),再决定间距。比如最大扫描 60 度,|cos60°| = 0.5,间距必须小于 0.67λ。这个条件我一般会写成一个检查函数,在扫描脚本开头调用,不满足就直接报错,省得后面看图才发现问题。

function check_scan_grating(N, d_lambda, theta_max_deg) % 检查扫描时是否满足无栅瓣条件 theta_max = deg2rad(theta_max_deg); d_max = 1 / (1 + abs(cos(theta_max))); if d_lambda >= d_max warning('间距 %.2f\\lambda 超过无栅瓣上限 %.2f\\lambda,扫描到 %d 度会出现栅瓣', ... d_lambda, d_max, theta_max_deg); else fprintf('间距检查通过:%.2f\\lambda < %.2f\\lambda\n', d_lambda, d_max); end end

把这个函数放在扫描脚本最前面,改参数时先跑一遍,能省下大量看图找问题的时间。希望帮到你。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询