简介:针对室内可见光通信(VLC)系统的多径信道建模需求,这份资料面向通信与光无线传输方向的科研人员及高年级学生,可用于理解直射(LOS)、非直射(NLOS)和漫反射等路径分量的仿真方法,以及误码率(BER)统计逻辑。压缩包采用7z格式,仅1KB,内置4个m文件:主程序负责参数初始化、信号收发与系统级仿真协调;直射路径模块模拟光源到接收端的几何关系与遮挡影响;反射路径模块考虑房间布局、表面反射系数等,刻画多次反射的功率衰减与相位变化;接收端处理模块涵盖光电转换、噪声引入及误码计算。外部浏览热度已达879人,适合作为课程设计、课题起步或仿真对比的参考,初学者也能借助清晰的模块划分快速上手。通过这份资源可建立从信道建模到性能评估的完整链路认知,为后续优化VLC系统提供实用基础。
1. 室内可见光通信多径信道模型:从物理现象到仿真落点
室内可见光通信的多径信道模型,看着是光学问题,其实卡住大多数人的是通信仿真那一半。LED 灯的光在 5 米见方的房间里打到墙面、桌面再反射回光电二极管,这一路多径叠加,最后会直接拉低误码率。这套四文件工程把这件事拆成了 LOS 直射、NLOS 反射、接收处理三段可独立调试的模块,主程序再把它们装起来跑 BER。适合正在搭 VLC 仿真的研究生、毕设党,也适合想快速验证室内多径影响程度的通信工程师。它不是光学软件那种精确追迹,而是把信道冲激响应 h(t) 和误码率曲线先跑出来的快速落点方案。
2. 多径信道建模三件套:HLOS.m、RO.m 与漫反射的取舍依据
室内 VLC 信道没有标准的多径统计模型可套,这和射频完全不同。射频可以用 802.11 那种抽头延迟线直接拉随机数,VLC 因为收发端距离近、墙壁反射很强,必须按实际几何关系去算。这套资源用朗伯辐射假设作为整个模型的地基:把 LED 看作一个朗伯光源,光强随出射角按余弦的 m 次幂衰减,m 与半功率角一一对应。这样建模的精度足够支撑通信层面的 BER 仿真,又不需要像 Zemax 那样做逐光线追迹,这是它能落地成 MATLAB 脚本的根本原因。
2.1 直射分量 HLOS.m:几何关系与遮挡判断的建模逻辑
直射路径是室内 VLC 里最强的信号分量,也是决定 BER 主趋势的路径。HLOS.m 干的是这一件事:根据 LED 位置、光电二极管位置和两者的朝向,算出直射路径的直流增益,再按光速换算成一条带时延的冲激响应。直射链路的直流增益用朗伯辐射模型刻画:
$H_{LOS}(0) = \frac{m+1}{2\pi}\cdot\frac{\cos^m(\phi)\cos(\psi)}{d^2}\cdot A_{PD}$
其中 φ 是光线相对于 LED 法线的出射角,ψ 是光线相对于 PD 法线的入射角,d 是直线距离,A_PD 是接收端有效面积,m = -ln2 / ln(cos(φ_half))。HLOS.m 的代码骨架一般是这样组织的:
function [h, H0] = HLOS(led_pos, pd_pos, led_dir, pd_dir, params) % led_pos: LED 的三维坐标 % pd_pos: 光电二极管的三维坐标 % led_dir: LED 法线方向,通常朝下 [0 0 -1] % pd_dir: PD 法线方向,通常朝上 [0 0 1] % params: 结构体,含半功率角 phi_half、FOV、PD 面积 d_vec = pd_pos - led_pos; d = norm(d_vec); if d < 1e-6 h = 0; H0 = 0; return; end cos_phi = abs(dot(led_dir, d_vec / d)); % 出射角余弦 cos_psi = abs(dot(pd_dir, -d_vec / d)); % 入射角余弦 m = -log(2) / log(cosd(params.phi_half)); % 朗伯辐射阶数 % 超出视场角或背对 LED 时,这一跳不存在 if cos_psi < cosd(params.FOV) || cos_phi < 0 h = 0; H0 = 0; return; end H0 = (m + 1) / (2 * pi) * cos_phi^m * cos_psi / d^2 * params.A_PD; delay = d / 3e8; % 光速换算时延,单位秒 h = H0; h_delay = delay; end这里我把 h 和时延分开处理,原因是 MATLAB 的冲激响应按采样周期离散化,如果直接把时延写进下标,主程序里改采样率就会牵一发动全身。分开返回之后,VLC_mul_main.m 在叠加多径时按 delay 找对应采样点,逻辑会清楚很多。
注意 cos_phi 和 cos_psi 的处理方法。很多初稿在这里用 acos 再求 cos,绕了一圈还容易因为浮点误差算出 NaN,我建议直接对方向向量做点积取绝对值来得稳。半功率角 60 度对应的 m 是 1,45 度对应的 m 约是 3.3,LED 越聚焦,m 越大,直射路径对角度越敏感,这套关系在调参时会反复用到。
2.2 RO.m 反射分量:从一阶反射到多阶反射的叠加方式
直射路径只要 LED 和 PD 之间被家具挡一下就会断掉,但室内光通信很少依赖通视,因为墙面、地板和天花板都在反射光。RO.m 模拟的是非直射路径,最常见的做法是把反射面划分成小面元,让每个面元先接收 LED 的光,再像次级朗伯光源那样把光重新发出去。一阶反射的信道增益是所有面元贡献的求和:
$H_{ref}^{(1)}(0) = \sum_j \frac{m+1}{2\pi}\frac{\cos^m(\phi_1)\cos(\psi_1)}{d_1^2}\cdot A_{wall} \cdot \rho_j \cdot \frac{1}{\pi}\frac{\cos(\phi_2)\cos(\psi_2)}{d_2^2}\cdot A_{PD}$
对应的函数骨架如下:
function h = RO(wall_grid, led_pos, pd_pos, wall_norm, params, rho) % wall_grid: Kx3 矩阵,每个面元的中心坐标 % wall_norm: Kx3 矩阵,每个面元的法线方向,指向房间内部 % rho: 墙面反射系数,可标量可向量 % 每个面元都当作次级朗伯光源,向半空间重新辐射 % m、led_dir、pd_dir 从 params 中提取 h = zeros(1, params.max_delay_bins); for j = 1:size(wall_grid, 1) w = wall_grid(j, :); d1 = norm(w - led_pos); if d1 < 1e-6, continue, end d1_vec = (w - led_pos) / d1; cos_phi1 = abs(dot(led_dir, d1_vec)); % LED 到面元 cos_psi1 = abs(dot(wall_norm(j,:), d1_vec)); % 面元入射角 d2 = norm(pd_pos - w); if d2 < 1e-6, continue, end d2_vec = (pd_pos - w) / d2; cos_phi2 = abs(dot(wall_norm(j,:), -d2_vec)); % 面元出射角 cos_psi2 = abs(dot(pd_dir, d2_vec)); % PD 入射角 if cos_psi2 < cosd(params.FOV), continue, end G1 = (m + 1) / (2 * pi) * cos_phi1^m * cos_psi1 / d1^2 * params.A_wall; G2 = 1 / pi * cos_phi2 * cos_psi2 / d2^2 * params.A_PD; delay = (d1 + d2) / 3e8; if delay > params.max_delay, continue, end idx = round(delay / params.dt) + 1; h(idx) = h(idx) + G1 * rho(j) * G2; end end这套循环的核心是把墙面当漫反射体:面元收到多少功率,就按余弦分布向半空间重新辐射,而不是镜面反射。反射系数 ρ 在 0.4 到 0.8 之间是正常范围,白墙接近 0.7。A_wall 与墙面网格分辨率绑定,网格越粗能量泄漏越明显,后面避坑章节会专门说。
二阶反射的代码结构和一阶几乎一样,只是把 LED 换成一阶的面元集合。难点在复杂度:墙面划分成 20cm 网格时,5m×5m×3m 房间大约有两千多个面元,二阶反射要算两千万条路径组合,纯 for 循环非常慢。这套包的处理方式在第 6 章展开,这里先记住:一阶反射必须逐面元算,二阶以上要认真考虑计算量。
2.3 漫反射与工程近似:什么时候用等效系数糊弄过去
漫反射在三阶以上反射里占主导,但逐阶算下去代价极高。工程上常见的做法是只算到第二阶反射,然后把更高阶的贡献折算进直射和一阶结果里。这个近似在多数室内场景可接受,因为每反射一次功率要乘一次墙面反射系数和路径衰减,三阶反射的能量通常已低于直射的百分之一。
真正值得注意的是延迟扩展。反射路径比直射长,所以会形成拖尾,拖尾长度决定多径会不会干扰到下一个符号。在 5 米见方的房间里,三阶反射的最大额外延迟能达到几十纳秒,符号速率上到 100 Mbps 以后,这个拖尾就不能忽视了。这就是为什么多径信道模型一定要保留时延信息,而不是只算一个总功率。
2.4 三种分量的对比与选型口径
| 分量 | 来源 | 功率量级 | 时延 | 对遮挡的敏感度 |
|---|---|---|---|---|
| LOS 直射 | LED 直接到 PD | 强 | 最短 | 极敏感,一挡就断 |
| 一阶反射 | 墙面、地板、天花板单次反射 | 中,约 LOS 的 5%~15% | 增加 1~10 ns | 与角度强相关 |
| 二阶及以上 | 多次反射叠加 | 弱,通常低于 1% | 最长可达 50 ns | 近似均匀照亮全屋 |
选型口径上,我只在符号速率低于 50 Mbps 时忽略二阶以上反射;符号速率一旦提高,拖尾造成的码间串扰会让 BER 曲线尾部抬起来,那时再省计算量,就会出现怎么调 SNR 误码率都下不去的假象。这也是这套模型存在的核心价值:把多径拖尾完整留给后面的均衡策略去处理。
3. 跑通 VLC_mul_main.m 主循环:初始化参数、子模块调用与单步调试
整套工程的核心是 VLC_mul_main.m。它的任务不是实现某一条路径,而是把前面三个模块装进一条完整的仿真链路:生成比特、上采样、过信道、加噪声、判决、数误码。我建议先把主程序当成黑匣子跑通一次,记录默认参数下的 BER,再逐段拆开改参数。
3.1 主程序执行链路:发射、多径卷积、接收判决一条龙
主程序一般按下面这条链路组织参数初始化部分:
%% 参数初始化 clear; close all; room = [5 5 3]; % 房间尺寸 x y z,单位米 led_pos = [2.5 2.5 3.0]; % LED 坐标,贴天花板 pd_pos = [1.0 2.5 0.85]; % 接收机坐标,桌面高度 params.phi_half = 60; % LED 半功率角,单位度 params.FOV = 60; % PD 视场角,单位度 params.A_PD = 1e-4; % PD 有效面积,1 cm^2 params.rho = 0.7; % 墙面反射系数 Rb = 50e6; % 符号速率 50 Mbaud sps = 20; % 每符号采样点个数 fs = Rb * sps; % 采样率 1 GHz params.dt = 1 / fs; % 采样间隔 Nbits = 1e5; % 仿真比特数 %% 生成信道冲激响应 [h_los, h_los_delay] = HLOS(led_pos, pd_pos, [0 0 -1], [0 0 1], params); h_ref1 = RO(wall_grid, led_pos, pd_pos, wall_norm, params, params.rho); h_total = combine_h(h_los, h_los_delay, h_ref1); % 按时延对齐叠加这段代码把采样率设计成符号速率与过采样倍数的乘积,而不是随手取一个 1 GHz。sps=20 意味着每个符号采 20 个点,既能看清反射拖尾的细节,又不会让信道冲激响应矩阵大到内存吃不消。
接下来是信源和判决部分,接收端的处理通常放在 PRXLOS.m 里:
%% 发射与接收 bits = randi([0 1], Nbits, 1); tx = bits; % OOK 电平 0/1 tx_up = reshape(repmat(tx.', sps, 1), [], 1); % 上采样 h_total = h_total / sum(h_total); % 直流增益归一化 rx_up = conv(tx_up, h_total); % 过多径信道 SNR_dB = 20; P_sig = mean(rx_up.^2); sigma_n = sqrt(P_sig / (10^(SNR_dB/10))); % 按目标 SNR 反推噪声幅度 rx_noisy = rx_up + sigma_n * randn(size(rx_up)); rx_filt = conv(rx_noisy, ones(sps, 1) / sps); % 矩形窗匹配滤波 rx_sample = rx_filt(sps:sps:end); % 抽样 rx_bits = double(rx_sample > 0.5); % 阈值判决 err = sum(xor(rx_bits(1:Nbits), bits)); % 注意对齐 BER = err / Nbits;这里用的是简化 AWGN 模型。严格做 VLC 仿真时散粒噪声与信号幅度相关,需要在后面把噪声方差改成信号电平的函数,第一条主线跑通后必须记得升级这一点。归一化 h_total 的写法也容易出问题:这一步只应该做直流增益归一化,不能把各路径的相对比例改掉。
3.2 关键参数设置与调参方向
| 参数 | 默认值 | 取值方向 | 对结果的影响 |
|---|---|---|---|
| 房间尺寸 | 5×5×3 m | 按实际办公室/实验室 | 决定最大时延和多径数量 |
| LED 半功率角 | 60° | 30°~80° | m 随角度变,决定光斑覆盖范围 |
| PD 视场角 FOV | 60° | 30°~90° | 决定反射路径是否被接收 |
| PD 面积 | 1 cm² | 0.1~1 cm² | 直接缩放接收功率,影响 SNR |
| 墙面反射系数 | 0.7 | 0.4~0.8 | 决定反射路径强度和拖尾长短 |
| 符号速率 | 50 Mbaud | 10~200 Mbaud | 决定是否触发码间串扰 |
| 过采样倍数 | 20 | 10~50 | 影响时延分辨率和仿真量 |
调参的优先级有讲究:先固定房间和收发坐标,调半功率角看功率分布;再固定半功率角,调 FOV 看反射路径的接收比例;最后才动反射系数和符号速率。反过来调会出现几个参数互相抵消,定位不到问题。
3.3 用单步调试拆黑匣子:三个中间断点验证子模块正确性
直接把整条链路跑完再找问题,最浪费时间。我一般会在主程序里放三个断点,把黑匣子拆开验证。
第一个断点放在 HLOS 调用之后,检查 h_los 的峰值是否与手算的朗伯公式结果一致。把 LED 和 PD 移到同一条垂直线上,此时 cos_phi 和 cos_psi 都等于 1,直流增益就是 (m+1)/(2πd²)·A_PD,这个值能口算出来,对不上就说明坐标系方向或面积单位有问题。
第二个断点放在 RO 调用之后,检查一阶反射总能量是否在直射的 5%~15% 区间。反射能量占比与反射系数、面元划分直接相关,如果超过 30% 或者低于 1%,先怀疑 A_wall 和 grid 分辨率,再怀疑法线方向是否指向房间内部。
第三个断点放在卷积之后、加噪声之前。此时 rx_up 的幅度应该与信道增益匹配,若幅度出现量级漂移,说明 h_total 归一化或时延对齐有误。这三个断点每跑一步都验证一个明确物理量,比直接盯着 BER 曲线猜原因省力得多。
4. 多径仿真高频踩坑:反射阶数、采样率与归一化的排查顺序
这套模型跑起来之后,翻车点集中在五个方向。我按踩坑频率从高到低排列,每条都按现象、原因、解决的顺序给排查路径。
4.1 反射路径出现负数与 NaN:先查向量方向和 acos 输入
现象:RO.m 运行过程中变量 h_ref1 出现负数,或者主程序报 NaN。
原因:最常见是方向向量的正负号取反。LED 到面元这一段应该用面元坐标减 LED 坐标,面元到 PD 这一段应该用 PD 坐标减面元坐标,两个方向反过来,cos 值就是负的。另一个来源是 acos 的输入超出 [-1,1],浮点误差会把它推成 1.0000001,acos 返回 NaN。
解决:重建坐标系约定,统一用“终点减起点”做差;所有 cos 计算用 abs 包一层再判断可见性;在 RO.m 里加一行assert(all(isfinite(h))),一旦出现 NaN 立即定位。我习惯在调试阶段把 abs 去掉,保留原始正负,这样能肉眼看出哪条路径方向反了。
4.2 BER 高信噪比区出现地板:基本是码间串扰在作怪
现象:SNR 从 20 dB 加到 40 dB,BER 曲线到了 10^-5 左右就掉不下去,形成一个平台。
原因:这是多径拖尾导致的码间串扰,噪声再低也没用。h_total 的反射分量拖到下一个符号周期,前一个符号的拖尾能量叠加到当前符号上,等效于一个与噪声无关的干扰项。反射系数越大、符号速率越高,地板位置越高。
解决:先把符号速率降到 10 Mbaud,如果地板消失,说明拖尾确实跨符号了。工程做法有两种——把采样时刻对准 LOS 峰值再在判决前加均衡器;或者从信道模型侧把反射截断到两阶以内,用更干净的 h_total 验证是否均衡器设计不当。
4.3 采样率与符号速率失配:卷积后忘了按符号对齐
现象:BER 结果乱跳,改变 sps 后 BER 完全变样,甚至 0 dB 时误码率反而不高。
原因:卷积会产生额外延时,rx_filt(sps:sps:end) 的抽样点如果没对准原符号起始位置,采到的就是符号边缘而非重心。另一个常见问题是上采样后忘了匹配滤波,直接用原始长度做判决,造成抽样点错位。
解决:先用finddelay(rx_filt, tx_up)求出信道与滤波器的总延时,在抽样起点处补偿;再把 sps 固定为 20 做一组对比实验,验证抽样点取第 10 个和第 5 个的 BER 是否一致。这一步是每次改代码必做的回归项。
4.4 冲激响应能量不收敛:反射系数和网格尺寸要背锅
现象:把反射阶数从一阶加到三阶,h_total 的总能量一直涨,算到五阶还在涨,曲线无法收敛。
原因:反射系数 ρ 设得过高,比如 0.9 以上,高阶反射能量衰减过慢;另一个原因是墙面网格划分太粗,每个面元的 A_wall 过大,能量在空间上被“放大”了。
解决:先把 ρ 降到 0.7 再跑,观察能量是否按比例收敛;然后用网格减半做对比,如果总能量变化超过 10%,说明网格分辨率不足。一个经验值:墙面网格边长不要超过 0.25 m,否则反射能量分布失真。
4.5 换房间尺寸后结果猛变:先看归一化与角度是否同步更新
现象:把房间从 5×5×3 m 改成 8×6×3 m,BER 从 10^-4 飘到 10^-2,怎么调 SNR 都拉不回来。
原因:换了房间尺寸后,LED 与 PD 的相对位置分布变了,LOS 主路径的几何关系改变,反射路径的平均长度也变了。很多脚本把房间尺寸写死在多个函数里,只改了主程序的 room 变量,子模块还是老尺寸,或者半功率角和 FOV 没有跟着场景缩放。
解决:改场景前先输出 h_total 的直流增益,与理论值 H(0) 对比确认量级正常;再检查 LED 与 PD 的相对高度差、水平距离是否保持在同一比例。我一般固定 led_pos 与 pd_pos 的相对位置,只平移整体坐标,这样对比 BER 时排除了角度效应。
5. 误码率计算与信道脉冲响应校准:从光功率到 BER 的换算细节
误码率不是直接把 SNR 代入公式就能得到的,中间隔着光功率到电功率的换算。这条链路如果不校准,仿真出来的 BER 曲线会整体偏移几个 dB。
5.1 光功率、电功率与信噪比换算:把 h(t) 变成 SNR 再变 BER
信道冲激响应 h(t) 的直流增益 H(0) 等于 h(t) 对时间积分,离散化后就是对所有采样值求和乘以采样间隔。接收光功率 P_r = P_t × H(0),光电二极管把光功率变成光电流 i = R_resp × P_r,其中 R_resp 是响应度,单位 A/W,典型值 0.5 左右。
电域的 SNR 要同时考虑散粒噪声和热噪声。简化计算可以直接写成:
function SNR_dB = snr_from_h(H0, Pt, R_resp, B, RL, T) % H0: 信道直流增益 % Pt: LED 发射光功率,单位 W % R_resp: PD 响应度,A/W % B: 接收带宽,与符号速率同量级 % RL: 负载电阻,常见 50 欧姆 % T: 温度,常用 300 K Pr = Pt * H0; i_sig = R_resp * Pr; % 信号电流幅度 q = 1.6e-19; k = 1.38e-23; i_shot2 = 2 * q * i_sig * B; % 散粒噪声方差 i_therm2 = 4 * k * T * B / RL; % 热噪声方差 SNR_dB = 10 * log10(i_sig^2 / (i_shot2 + i_therm2)); end这段代码把光信道和电域噪声做了桥接。注意散粒噪声与接收光电流成正比,所以 SNR 不会随着 P_t 无限提升,高功率时散粒噪声成为主要限制,BER 曲线会出现饱和趋势,这是 VLC 和射频仿真的重要区别。做 OOK 时,双极性信号的理论 BER 约等于 Q(√SNR),单极性阈值判决会差 3 dB 左右,仿真里直接用蒙特卡洛统计可以绕开这个公式陷阱。
5.2 蒙特卡洛统计 BER:序列长度、重复次数与判决方式
BER 统计的可信度完全由误码个数决定。跑 1e5 比特,理论上能测到 1e-3 以上的误码率;想测 1e-5 量级,至少需要 1e6 比特,否则抖动量级比测量值还大。我常用的做法是分 SNR 点跑,每个点重复 5~10 次取平均:
SNR_list = 0:5:30; BER_list = zeros(size(SNR_list)); for n = 1:length(SNR_list) err_cnt = 0; for rep = 1:5 % 重新生成比特、调制、过信道、加噪、判决 err_cnt = err_cnt + err_single_run(SNR_list(n)); end BER_list(n) = err_cnt / (Nbits * 5); end这里每次重复都要重新生成随机比特和噪声,避免同一段序列的偶然性主导结果。低 SNR 区域误码多,重复次数可以少;高 SNR 区域误码少,要么加长 Nbits 到 1e6,要么把重复次数提高到 10 以上。我一般会在代码里打印每个点的误码个数,少于 10 个的 BER 点直接标记为不可信。
判决方式也会影响统计结果。OOK 用 0.5 作为固定阈值,在有码间串扰时不再是最优选择,这时候应该先做过零判决或自适应阈值。判断阈值是否合理,可以观察 rx_sample 的星座图,两个电平的分布边界是否清晰,拖尾是否把 0 电平抬高了。
5.3 用 h(t) 的能量与延迟扩展验证模型可信度
跑 BER 之前,先校验 h_total 本身是否物理合理,这一步能避免把错误的信道模型带到后面所有结果里。我每改一次参数,就强制过一遍下面三个判据。
| 判据 | 检查方法 | 合格范围 |
|---|---|---|
| 直流增益一致性 | sum(h_total) × dt 与理论 H(0) 对比 | 偏差 < 5% |
| LOS 主导性 | 最大峰值应在直射时延位置 | 占能量 60% 以上 |
| RMS 延迟扩展 | 按 h(t) 的二阶矩计算 | 5~20 ns,与房间尺寸匹配 |
延迟扩展的计算代码很简单:
t = (0:length(h_total)-1) * params.dt; P_h = h_total.^2; tau_mean = sum(t .* P_h) / sum(P_h); tau_rms = sqrt(sum((t - tau_mean).^2 .* P_h) / sum(P_h));如果 tau_rms 算出来超过 50 ns,大概率是反射系数过高或者房间尺寸异常。如果 LOS 占比低于 50%,先检查 LED 和 PD 位置,再检查 FOV 设置——这两个参数直接决定直射路径是否在接收角范围内。这三个判据通过后,BER 结果才具备和外文文献对比的基本资格。
6. 多灯源扩展与仿真效率控制:从点对点到信道矩阵
6.1 多 LED 场景:把单链路模型扩展为信道矩阵
实际办公室不可能只装一盏灯。扩展到多个 LED 时,每条发射-接收链路单独生成 h(t),再放进一个三维矩阵:
H_mat = zeros(N_led, N_pd, L); % L 为冲激响应长度 for i = 1:N_led for j = 1:N_pd H_mat(i, j, :) = generate_h(led_pos(i,:), pd_pos(j,:), params); end end多灯场景里每个 PD 收到的是多路信号的叠加。如果做的是分集接收,直接把同一符号经过各信道的输出相加;如果做 MIMO,就需要按每对链路的直流增益差异设计预编码。这里有个提升效率的技巧:墙面网格坐标只生成一次,放在 params 里供所有链路复用,不要让每条链路重新划分网格,那是纯浪费。
6.2 反射面元矩阵化:把分钟级 for 循环压到秒级
单灯一阶反射在 0.2 m 网格下要循环两千多次,如果主程序里再嵌套 4 个 LED,运行时间就到了分钟级。我一般把 RO.m 里的 for 循环改成矩阵运算:先算 LED 到所有面元的距离向量,再算所有面元到 PD 的距离向量,利用 MATLAB 的向量化一次性求出所有路径的增益和时延,最后用 accumarray 按时延合并。同样规模的计算量,矩阵化之后能压到原来的十分之一以内。
从那以后我每次跑多径模型,都强制先跑一遍 h(t) 的直流增益校验和延迟扩展计算,这两个数不过关,绝对不往 BER 曲线上去追。这套流程救回过我好几次因为反射系数设错导致的白干半天,希望这篇能帮你把同样的弯路省掉。
本文还有配套的精品资源,点击获取