ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

瑞利衰落与莱斯衰落信道模型:公式推导与可运行代码实现

瑞利衰落与莱斯衰落信道模型:公式推导与可运行代码实现 简介这份资源面向无线通信方向的研究者、工程师与学生聚焦多径传播环境下的信道建模问题提供瑞利衰落与莱斯衰落两种经典模型的代码实现。瑞利模型适用于城市短距离移动通信中无直射分量的场景莱斯模型则刻画含主导直射路径的开阔地带、微波链路与雷达环境二者是分析信号强度波动、评估系统性能的基础工具。压缩包共4个文件以3个m脚本文件为主分别实现瑞利与莱斯信道的仿真与绘图另附1张jpg示意图辅助理解模型差异整体约23KB轻量易运行。目前已有1362人学习下载。通过运行脚本并调整参数读者可直观观察多径衰落对信号幅度的影响为分集接收、均衡、纠错编码及OFDM等算法设计提供验证依据适合作为课程实验与课题研究的参考素材。1. 瑞利衰落与莱斯衰落信道模型从公式到可运行代码一次讲透做无线通信仿真的人迟早会撞上信道建模这堵墙。你搭好了调制解调、写完了均衡器结果发现误码率曲线怎么都不对——十有八九是信道模型出了问题。瑞利衰落和莱斯衰落是无线信道建模里最基础、也最常被误用的两个模型。瑞利衰落描述的是没有直射路径、信号全靠反射散射到达接收端的场景比如城市密集楼宇间的非视距通信莱斯衰落则在瑞利的基础上叠加了一条直射分量对应视距通信场景比如郊区基站到屋顶天线。这两个模型不是学术玩具它们直接决定了你仿真出来的误码率、中断概率、分集增益是否可信。这篇内容面向做物理层仿真、链路预算、通信系统验证的工程师从模型公式出发给出可直接运行的代码再把参数怎么设、坑在哪一条条拆开。2. 瑞利衰落信道从包络分布到仿真代码2.1 瑞利衰落的物理来源与数学表达瑞利衰落的物理前提是发射机和接收机之间没有直射路径接收信号是大量独立反射波、散射波的叠加。根据中心极限定理当散射体数量足够多时接收信号的同相分量和正交分量都服从零均值高斯分布合成信号的包络服从瑞利分布。包络的概率密度函数为$$f(r) \frac{r}{\sigma^2} \exp\left(-\frac{r^2}{2\sigma^2}\right), \quad r \geq 0$$其中 $\sigma$ 是散射分量的均方根值$2\sigma^2$ 是接收信号的平均功率。这个公式说明一件事瑞利衰落的包络没有直射分量撑腰深衰落出现的概率不可忽略——包络低于某个门限的概率随门限降低呈平方级下降。相位则服从 $[0, 2\pi)$ 上的均匀分布这一点在仿真里经常被忽略。很多人只生成了幅度衰落忘了相位也在随机旋转结果在相干解调仿真里对不上。从工程角度看瑞利模型适用的典型场景包括城市微蜂窝非视距链路、室内多径环境、以及任何直射路径被完全遮挡的通信链路。判断标准很简单——如果接收端看不到发射端且周围散射体足够丰富就用瑞利。2.2 用正弦波叠加法生成瑞利衰落序列瑞利衰落仿真的核心需求是生成时间相关的复高斯随机过程。最常用的方法是正弦波叠加法Sum of Sinusoids, SoS也叫 Jakes 模型或其改进版本。思路是用有限个不同频率、不同相位的正弦波叠加来逼近理想瑞利过程。下面是一段可直接运行的 Python 代码用改进的 Jakes 模型生成瑞利衰落系数import numpy as np def rayleigh_fading(N, fd, Ts, N08): 生成瑞利衰落信道系数序列 N: 采样点数 fd: 最大多普勒频移 (Hz) Ts: 采样间隔 (s) N0: 正弦波振荡器数量通常取8或16 返回: 复衰落系数数组长度为N t np.arange(N) * Ts # 振荡器角度参数 alpha np.pi * np.arange(1, N0 1) / N0 # 多普勒频率分量 wn 2 * np.pi * fd * np.cos(alpha) # 初始相位均匀随机 phi np.random.uniform(0, 2 * np.pi, N0) # 同相分量 h_I np.zeros(N) # 正交分量 h_Q np.zeros(N) for n in range(N0): h_I np.cos(wn[n] * t phi[n]) h_Q np.sin(wn[n] * t phi[n]) # 归一化保证平均功率为1 h (h_I 1j * h_Q) / np.sqrt(2 * N0) return h # 参数设置 N 10000 # 采样点数 fd 100 # 最大多普勒频移对应车速约54km/h 2GHz Ts 1e-4 # 采样间隔对应10kHz采样率 h rayleigh_fading(N, fd, Ts, N016) # 验证包络分布 envelope np.abs(h) print(f平均功率: {np.mean(envelope**2):.4f}) print(f包络均值: {np.mean(envelope):.4f}) print(f包络方差: {np.var(envelope):.4f})这段代码的逻辑说明alpha是入射波角度均匀分布在 $(0, \pi]$ 上wn是对应的多普勒频移由最大多普勒频移 $f_d$ 和入射角决定phi是随机初始相位每次运行结果不同这是瑞利衰落的随机性来源。最后除以 $\sqrt{2N_0}$ 是为了归一化平均功率到1方便后续链路预算。参数怎么设fd由载波频率和移动速度决定$f_d v f_c / c$其中 $v$ 是速度$f_c$ 是载波频率$c$ 是光速。Ts要满足采样定理至少是最大多普勒频移的倒数再除以10以上。N0取8到16就够再大对统计特性改善有限反而增加计算量。2.3 验证瑞利衰落的统计特性生成衰落序列后必须验证包络是否服从瑞利分布、相位是否均匀。这一步很多人跳过结果仿真结果不可信。import matplotlib.pyplot as plt from scipy.stats import rayleigh # 包络直方图与理论瑞利分布对比 fig, axes plt.subplots(1, 2, figsize(12, 4)) # 包络分布 axes[0].hist(envelope, bins50, densityTrue, alpha0.7, label仿真) r np.linspace(0, 3, 100) sigma np.sqrt(0.5) # 平均功率为1时sigma^2 0.5 axes[0].plot(r, rayleigh.pdf(r, scalesigma), r-, label理论) axes[0].set_xlabel(包络) axes[0].set_ylabel(概率密度) axes[0].legend() # 相位分布 phase np.angle(h) axes[1].hist(phase, bins50, densityTrue, alpha0.7) axes[1].set_xlabel(相位 (rad)) axes[1].set_ylabel(概率密度) axes[1].axhline(y1/(2*np.pi), colorr, linestyle--, label均匀分布) axes[1].legend() plt.tight_layout() plt.show()如果包络直方图和理论瑞利分布对不上常见原因有三个N0太小导致叠加波数量不足fd和Ts不匹配导致频率分辨率不够归一化系数算错导致平均功率偏离1。相位分布如果不均匀检查phi是否用了均匀随机分布以及h_Q的符号是否正确。3. 莱斯衰落信道直射分量怎么加、K因子怎么调3.1 莱斯衰落的模型结构与K因子定义莱斯衰落就是在瑞利衰落的基础上加一条直射路径。接收信号可以写成$$r(t) \sqrt{\frac{K}{K1}} \cdot e^{j(2\pi f_d \cos\theta_0 t \phi_0)} \sqrt{\frac{1}{K1}} \cdot h_{rayleigh}(t)$$其中 $K$ 是莱斯因子定义为直射分量功率与散射分量功率之比。$K0$ 时退化为瑞利衰落$K \to \infty$ 时退化为纯直射信道。直射分量的多普勒频移由直射路径的到达角 $\theta_0$ 决定通常取 $\theta_0 0$ 对应最大多普勒频移。K因子的典型取值郊区视距场景 $K$ 约 6-12 dB城市微蜂窝视距场景 $K$ 约 3-8 dB室内视距场景 $K$ 约 4-10 dB。这些数值不是拍脑袋来的是大量实测统计的结果。做仿真时如果拿不准先取 $K6$ dB 试再根据场景调整。3.2 莱斯衰落序列的生成代码基于前面的瑞利衰落生成函数加直射分量即可def rician_fading(N, fd, Ts, K_dB, N016, theta00): 生成莱斯衰落信道系数序列 N: 采样点数 fd: 最大多普勒频移 (Hz) Ts: 采样间隔 (s) K_dB: 莱斯因子 (dB) N0: 正弦波数量 theta0: 直射路径到达角 (rad) 返回: 复衰落系数数组 K 10 ** (K_dB / 10) # dB转线性 t np.arange(N) * Ts # 散射分量瑞利部分 h_scatter rayleigh_fading(N, fd, Ts, N0) # 直射分量 f_direct fd * np.cos(theta0) h_los np.exp(1j * (2 * np.pi * f_direct * t)) # 按功率比合成 h np.sqrt(K / (K 1)) * h_los \ np.sqrt(1 / (K 1)) * h_scatter return h # 生成不同K因子下的莱斯衰落 K_values [0, 3, 6, 10] # dB fig, axes plt.subplots(2, 2, figsize(12, 8)) for ax, K_dB in zip(axes.flat, K_values): h_rician rician_fading(N, fd, Ts, K_dB) env_rician np.abs(h_rician) ax.plot(t[:2000], 20*np.log10(env_rician[:2000] 1e-10)) ax.set_title(fK {K_dB} dB) ax.set_xlabel(时间 (s)) ax.set_ylabel(幅度 (dB)) ax.grid(True) plt.tight_layout() plt.show()逻辑说明K从 dB 转线性后直射分量乘以 $\sqrt{K/(K1)}$散射分量乘以 $\sqrt{1/(K1)}$这样合成信号的总平均功率仍然为1。theta0控制直射路径的到达角取0时直射分量经历最大多普勒频移取 $\pi/2$ 时直射分量没有多普勒频移。参数说明K_dB是核心参数决定了衰落的深度和分布形态。theta0影响直射分量的时间变化速率在高速移动场景下这个参数对误码率影响很大。N0和瑞利部分一样取16足够。3.3 K因子对系统性能的影响分析K因子直接决定了信道有多“恶劣”。K越小信道越接近瑞利深衰落越频繁误码率曲线下降越慢。K越大直射分量越强信道越接近高斯信道性能越好。做链路预算时如果已知场景的K因子可以用它来估算所需的衰落余量。经验公式是衰落余量约等于 $10\log_{10}(K1)$ 再减去一个与中断概率相关的修正项。但更可靠的做法是直接仿真——生成莱斯衰落序列跑蒙特卡洛统计中断概率。def outage_probability(K_dB, threshold_dB, N100000): 蒙特卡洛估计中断概率 K_dB: 莱斯因子 threshold_dB: 中断门限 (dB) N: 仿真次数 K 10 ** (K_dB / 10) threshold 10 ** (threshold_dB / 10) # 生成大量独立衰落样本 # 散射分量复高斯 h_scatter (np.random.randn(N) 1j * np.random.randn(N)) / np.sqrt(2) # 直射分量恒定幅度 h_los np.ones(N) # 合成 h np.sqrt(K/(K1)) * h_los np.sqrt(1/(K1)) * h_scatter power np.abs(h) ** 2 outage np.mean(power threshold) return outage # 对比不同K因子下的中断概率 threshold_dB -10 # 中断门限比平均功率低10dB for K_dB in [0, 3, 6, 10]: p_out outage_probability(K_dB, threshold_dB) print(fK {K_dB} dB, 中断概率 {p_out:.6f})这段代码用蒙特卡洛方法估计中断概率。注意这里生成的是独立样本不包含时间相关性适合做静态链路预算。如果要考虑时间相关性需要用前面的正弦波叠加法生成时间序列再统计低于门限的持续时间。4. 避坑与排查信道仿真里最容易翻车的五个地方4.1 平均功率没归一化误码率曲线整体偏移现象仿真出来的误码率曲线和理论值形状相似但整体平移了几个dB。原因衰落系数没有归一化到单位平均功率。瑞利衰落序列如果直接使用其平均功率是 $2N_0$ 而不是1导致信噪比定义混乱。解决生成衰落系数后务必除以 $\sqrt{2N_0}$ 或显式归一化。验证方法是计算np.mean(np.abs(h)**2)确认接近1。如果不为1检查归一化步骤。4.2 多普勒频移设得太大采样率跟不上现象衰落序列看起来像噪声没有时间相关性或者频谱明显混叠。原因Ts太大采样率低于 $2f_d$导致多普勒频谱混叠。或者fd设得过大超出了采样率能表示的范围。解决确保 $1/T_s \geq 10 f_d$一般取20倍以上更安全。如果fd 100HzTs应该小于等于1e-4s。检查方法是对衰落序列做FFT看频谱是否在 $[-f_d, f_d]$ 内。4.3 莱斯衰落的直射分量相位没设对现象K因子很大时衰落序列的幅度几乎恒定但误码率曲线和理论高斯信道对不上。原因直射分量的初始相位没有随机化或者直射分量的多普勒频移计算错误。在莱斯衰落中直射分量的相位 $\phi_0$ 通常取随机值但如果仿真中固定为0会导致特定时刻的相位对齐问题。解决直射分量的初始相位应该随机生成每次蒙特卡洛运行都不同。另外检查theta0是否合理如果直射路径到达角不是0多普勒频移要相应调整。4.4 正弦波数量太少统计特性不收敛现象包络分布直方图和理论瑞利分布有明显偏差尤其是尾部。原因N0取4或更小叠加波数量不足中心极限定理不成立。解决N0至少取8推荐16。如果计算资源允许取32更接近理想。验证方法是增加N0看包络分布是否收敛到理论曲线。4.5 混淆了衰落系数和信道增益现象在MIMO仿真中信道矩阵的维度或功率关系不对。原因把标量衰落系数直接当成信道增益用忽略了天线配置和功率分配。解决明确衰落系数是描述单条链路的复增益。在MIMO中每个发射-接收天线对都需要独立的衰落系数且要保证总发射功率约束。如果做波束赋形信道矩阵的归一化方式会直接影响性能对比。5. 进阶技巧用时间相关性验证模型是否可信信道模型建完之后怎么判断它是不是靠谱我的习惯是看时间自相关函数。瑞利衰落的理论自相关函数是 $J_0(2\pi f_d \tau)$其中 $J_0$ 是第一类零阶贝塞尔函数。莱斯衰落的自相关函数则是直射分量和散射分量自相关函数的加权和。from scipy.special import j0 def autocorrelation_verify(h, Ts, fd, max_lag100): 验证衰落序列的时间自相关 h: 衰落系数序列 Ts: 采样间隔 fd: 最大多普勒频移 max_lag: 最大滞后点数 h h - np.mean(h) # 去均值 R np.correlate(h, h, modefull) R R[len(R)//2:] / R[len(R)//2] # 归一化 lags np.arange(max_lag) * Ts R_theory j0(2 * np.pi * fd * lags) plt.plot(lags, np.abs(R[:max_lag]), b-, label仿真) plt.plot(lags, np.abs(R_theory), r--, label理论) plt.xlabel(滞后时间 (s)) plt.ylabel(归一化自相关) plt.legend() plt.grid(True) plt.show() # 计算均方误差 mse np.mean((np.abs(R[:max_lag]) - np.abs(R_theory))**2) print(f自相关均方误差: {mse:.6f}) return mse # 验证 mse autocorrelation_verify(h, Ts, fd, max_lag200)这段代码的逻辑先对衰落序列去均值然后计算自相关再和理论贝塞尔函数对比。如果均方误差在 $10^{-3}$ 量级以下说明模型的时间相关性是对的。如果误差大检查N0是否够大、fd和Ts是否匹配。对于莱斯衰落自相关函数要加上直射分量的贡献$$R(\tau) \frac{K}{K1} e^{j2\pi f_d \cos\theta_0 \tau} \frac{1}{K1} J_0(2\pi f_d \tau)$$验证时分别对比实部和虚部或者只看包络的自相关。我一般会跑三组不同K因子的对比K0、K6、K20看自相关曲线是否随K增大逐渐向直射分量的纯相位旋转靠拢。还有一个实用技巧用多组独立生成的衰落序列做蒙特卡洛统计误码率曲线的置信区间。如果置信区间太宽说明仿真次数不够或者衰落序列的随机性不足。我通常跑至少1000次独立衰落实现取误码率的均值和95%置信区间这样出来的曲线才敢往论文或报告里放。做信道仿真这些年最大的教训就是不要相信任何没有经过统计验证的衰落序列。公式再漂亮代码跑出来不对就是不对。每次生成完衰落系数先看包络分布、再看自相关、最后看误码率三步都过了再往下做。这个习惯帮我省了无数返工的时间。希望帮到你。本文还有配套的精品资源点击获取
返回列表