简介:面向无线通信与信道建模研究者的WINNER信道模型实现代码,对应第三代合作伙伴项目标准中统计信道模型的升级版本,支持城区、郊区、乡村等典型传播环境下的信道系数仿真。压缩包共47个文件,以41个Matlab脚本与函数文件为主,另含4个加密代码文件、1份说明文档和1个文本注意事项,整个压缩包不足1MB,非常轻量。代码覆盖场景参数配置、移动台与基站侧角度生成、天线阵列方向图、路径损耗计算、空间相关性建模、信道冲激响应输出等关键环节,并给出示例脚本,演示从二维布局参数到最终多维信道数据的完整流程。随包文档系统阐述各模块作用与参数含义,文本文件则说明版本匹配与运行注意事项,便于快速上手和二次开发。已有1654人浏览学习,适合无线通信方向的高年级本科生、研究生以及从事链路级仿真的工程师参考。 做无线物理层仿真的同学,多半经历过这个阶段:一开始只用AWGN信道,链路误码率低得离谱;后来换成瑞利衰落,感觉稍微真实了;再往后做到MIMO、波束赋形、车联网场景,发现瑞利模型根本描述不了“天线之间相关性、时延扩展、角度扩展”这些东西。我就是在那个阶段翻出winner2信道模型的matlab代码,才把仿真从“看着像”变成“真能反映场景差异”。
这篇文章不搬运官方文档,而是把我从拿到代码到跑通、再到接到OFDM链路里的完整过程梳理一遍。内容包括:WINNER II模型为什么好使、matlab代码里哪些参数是核心、怎么一步步配置一个3.5GHz城市微蜂窝MIMO场景、以及我踩过的几个版本和维度相关的坑。适合刚接触信道建模、准备做物理层算法验证、或者被课程设计逼着要用WINNER II的同学参考。
1. 为什么选winner2:不只是“多径衰落”那么简单
1.1 真实信道到底要描述什么
无线信道对通信系统的影响不是一句“多径衰落”能概括的。一个移动终端在城市里跑,接收信号至少会经历路径损耗、阴影衰落、小尺度衰落三大类。路径损耗决定平均接收功率,阴影衰落解决“绕过大楼后信号掉了一截”的问题,小尺度衰落则关注多径叠加后几微秒内的剧烈波动。
到了MIMO系统,还得再加两个维度:天线之间的空间相关性、多普勒带来的时间选择性。瑞利/莱斯模型能描述时变衰落,但描述不了“基站两根天线间隔半波长,接收端角度扩展偏小导致秩不足”这种物理现象。WINNER II把这些问题统一进了同一个框架,生成的信道系数直接包含路径损耗、时延抽头、到达角/离开角、多普勒频移,这是它最大的价值。
1.2 WINNER II如何用“几何随机”搞定空间相关性
WINNER II的核心是几何随机信道模型(GSCM)。你可以把它理解成:在基站和终端之间随机撒一些散射簇,每个簇代表建筑物、车辆、街角等反射体,簇内部又包含若干条不可分辨的射线。模型根据场景参数决定簇的数量、角度扩展、时延分布,再按照概率分布生成每条射线的幅度、相位、时延和角度。
这套方法的好处是,天线阵列是被“摆放”进这个几何场景里的。基站侧每根天线的位置不同,看到的各簇相位就不同,于是空间相关性自然就出来了。也正因如此,它特别适合做Massive MIMO和波束赋形的方案验证——不需要自己手动拟合相关矩阵,信道模型直接输出包含了空间特征的信道矩阵。
1.3 和其他模型的横向对比
很多初学者会困惑:模型这么多,到底选哪个?我常用这张表来筛选:
| 模型 | 是否支持MIMO空间相关 | 是否区分场景 | 频率范围 | 实现成本 |
|---|---|---|---|---|
| AWGN | 否 | 无 | 任意 | 极低 |
| 瑞利/莱斯 | 有限 | 无 | 任意 | 低 |
| ITU-R M.2135 | 部分 | 部分 | 2-6GHz | 中 |
| WINNER II | 是 | 多种 | 2-6GHz | 中 |
| 3GPP TR 38.901 | 是 | 多种 | 0.5-100GHz | 高 |
做6GHz以下的4G/5G中低频段仿真,WINNER II是性价比相当高的选择:文档公开、场景覆盖全、matlab代码现成。等真要做毫米波,再上38.901也不迟。
2. 动手前先摸清代码骨架
2.1 两份MATLAB代码,先分清你在用哪份
第一次搜“winner2信道模型matlab代码”,大概率会看到两种东西:一是WINNER D1.1.2发布时附带的官方MATLAB代码库,里面函数入口通常是WIM2或win2x;二是MATLAB Communications Toolbox里集成的winner2函数。两者的模型同源,但调用方式差别很大。
我建议新手直接用工具箱自带的winner2,原因是它不需要额外配置路径,错误提示也友好。如果你用的是老代码库,记得把整个目录加入MATLAB路径,并确认版本之间的函数调用差异。博文后面的示例统一用工具箱版,如果你的环境字段名不一样,先doc winner2查一下本机文档。
2.2 配置参数的“一页纸清单”
无论哪份代码,最后都要落成一个配置结构体/对象。我常用的核心参数列在下面:
- 场景编号:如B1城市微蜂窝、C1城市宏蜂窝、A1室内办公室,不同场景决定簇数和角度扩展;
- 载波频率:WINNER II覆盖2-6GHz,典型值取2.4GHz、3.5GHz、5.8GHz;
- 系统带宽/采样率:决定时延抽头的分辨率,带宽越大,可分辨的多径越多;
- 基站/终端天线数:直接影响输出信道矩阵的维度;
- 终端移动速度:决定多普勒频移,3km/h和120km/h出来的时间相关特性完全不一样;
- 天线间距:影响空间相关性,阵列稀疏相关性低,密集相关性高。
这些参数之间不是独立的。比如把场景改成宏蜂窝但天线间距设得特别小,结果未必符合物理直觉,所以每改一个变量都要想清楚它对应真实环境的哪一项。
2.3 给新手的一条启动建议
我的建议是不要一开始就翻算法文档,先把示例跑通,再通过修改参数看输出变化来反推模型行为。WINNER II的公式多、场景多,直接啃公式很容易被绕晕。跑通例子之后再回来看哪些参数直接影响时延扩展、哪些参数主导空间相关性,会快很多。
3. 从demo到可改的仿真脚本:一次完整实操
3.1 用示例配置,先把函数跑起来
我惯用的启动姿势是先建立一个默认配置对象,然后打印出来看看有哪些字段:
% 建立默认配置,具体写法以本机doc winner2为准 cfg = winner2('example'); disp(cfg);这一步的目的很简单:让代码先转起来。很多时候新手卡住不是因为不会配参数,而是第一步函数都调不通。如果这行报错,优先检查是否安装了Communications Toolbox,或者版本里函数名是不是有问题。成功disp出来之后,你会看到一大堆字段,这才是“配置全景图”。
3.2 配置一个3.5GHz城市微蜂窝MIMO场景
默认配置修改成目标场景,逻辑很直接:
cfg = winner2('example'); cfg.Scenario = 'B1'; % 城市微蜂窝 cfg.CarrierFrequency = 3.5e9; % 3.5GHz,5G中频典型值 cfg.SampleRate = 30.72e6; % 20MHz LTE/5G采样率,实际带宽略低于20MHz cfg.NumBSElements = 2; % 基站侧2根天线 cfg.NumMSElements = 2; % 终端侧2根天线 cfg.MSVelocity = 3 * 1000 / 3600; % 3km/h,步行场景 % 生成信道系数 [channelGains, ~, info] = winner2(cfg);重点理解SampleRate。这个参数直接影响时延抽头的时间分辨率,采样率越高,相邻抽头间隔越小,能分辨的多径越多。对20MHz系统来说,30.72Msps是LTE的标准采样率,可以直接沿用。MSVelocity换算成米每秒是个容易漏掉的细节,很多人直接把km/h数值填进去,导致多普勒大了近三倍。
3.3 把信道系数画出来,先看图再谈优化
生成信道系数之后,别急着接链路。先画两样东西:功率时延谱(PDP)和信道相关矩阵。
功率时延谱的计算方法是对时延维度求能量平均:
% 以channelGains维度顺序为准,画出各时延抽头的平均功率 pdp = mean(abs(channelGains).^2, [1 2 3]); % 不同版本维度顺序有差异,需实测确认 plot(10*log10(pdp + eps), 'o-'); xlabel('Tap index'); ylabel('Power (dB)');这里最要注意的是维度顺序。WINNER II不同版本对输出数组维度的定义不太一样,有的按“Tx-Rx-时延-时间”,有的按“时延-Tx-Rx-时间”。我的经验是先size(channelGains)看一眼,再对每个维度做mean,不然画出来的PDP完全错乱还找不出原因。
空间相关矩阵则可以通过对时延维度做相关性统计得到,主要用来确认这次配置的天线间距是否产生了合理的相关性衰减。如果两根天线之间的相关系数接近1,说明阵列过于紧凑或者角度扩展设置过小,MIMO增益会受影响。
3.4 把信道系数接进一个简单的OFDM链路
信道系数生成后,最常见的使用方式是作为时域信道冲激响应,与发送信号做卷积。以一个朴素OFDM链路为例:
% 假设发送信号为txSig,把信道冲激响应转成频域再做均衡 Nfft = 2048; % 子载波数 hfd = fft(channelGains(:, :, 1), Nfft, 1); % 取第一个时间块,按第一维做FFT hfd = squeeze(hfd); % 去除单例维度 % 发射端OFDM调制(省略加CP等步骤) % 接收端做单抽头频域均衡 rxSigFreq = fft(rxSig, Nfft, 1); estData = rxSigFreq ./ hfd;实际链路里还有循环前缀、导频估计、信道编码等环节,但核心套路是固定的:把winner2输出的时延抽头转换成频域响应,再对每个子载波做均衡。这一步验证通过后,你就可以把信道模型当做一个“可替换的模块”,任意配置场景来测试自己的收发算法。
4. 结果如何解读,问题如何排查
4.1 先判断参数是否合理
很多同学跑通代码之后,看着一堆复数矩阵不知道算不算成功。我的习惯是看三个指标:时延扩展的量级、多普勒扩展的量级、空间相关性的变化趋势。
城市微蜂窝B1场景在3.5GHz下,RMS时延扩展通常在几十纳秒到一两百纳秒之间,对应PDP拖尾不会太长。如果你发现时延扩展到了微秒级,大概率是采样率或场景配置有问题。多普勒方面,3km/h在3.5GHz下的最大多普勒频率大概是10Hz左右,画频谱图如果出现几十赫兹的扩展,就要回去检查速度单位。空间相关性就更直观了,天线间距变大,相关性应当逐步下降。
4.2 高频报错速查表
跑winner2过程中,下面几个问题反复出现,列成表格方便速查:
| 现象 | 大概率原因 | 解决办法 |
|---|---|---|
| 提示未定义函数winner2 | Communications Toolbox未安装或版本过老 | 检查许可证和已安装工具箱,或改用官方代码库 |
| 场景名报错 | cfg.Scenario填了不支持的名称 | 输入cfg全部字段,查看合法场景枚举 |
| 输出矩阵维度完全对不上 | 版本间维度顺序不一致 | 用size()逐维检查,再做permute调整 |
| 结果每次都不一样 | 随机种子不受控 | 在生成前写死rng(具体数值) |
| 内存不够 | 天线数和多普勒采样点数开太大 | 降低采样时间长度,或分块生成数据 |
4.3 控制变量法:一个参数一个参数改
win2模型参数多,最容易犯的错是同时改好多个参数,出了问题根本定位不了。我建议一次只改一个变量,比如只把MSVelocity从3km/h改到60km/h,观察PDP不变但时间相关性变快,这样就能把每个参数的作用记住。这个过程比较枯燥,但也是理解信道模型最快的方式。
5. 几个能直接抄的进阶套路
5.1 多组随机种子批量仿真
做链路级仿真时,需要跑很多次蒙特卡洛实验取平均,这时候一定要控制随机种子。正确做法是外层循环里使用不同的种子值,每个实验内部固定种子:
for expIdx = 1:100 rng(expIdx * 100); [channelGains, ~, info] = winner2(cfg); % 记录本次误码率/吞吐量 end这样既能保证每次实验可复现,又能让不同实验之间相互独立。千万别把所有实验放在一个循环里连续跑,那样如果中间某个实验崩溃,前面所有结果都推倒重来。
5.2 把信道矩阵存下来复用
同一组信道系数常常需要在多个算法之间对比,比如对比MMSE均衡和ZF均衡。重复生成信道既费时间又引入随机误差。我的习惯是跑一次生成后,直接存成.mat文件:
save('channel_B1_3p5GHz_20MHz.mat', 'channelGains', 'cfg');后续加载时直接读文件,保证所有算法用的是同一批信道。这在写论文时尤其重要,审稿人问起“你的对照组为什么信道条件一样”,你就能理直气壮地说所有算法跑的是同一份数据。
5.3 做波束赋形仿真时,把角度信息也导出来
winner2模型内部其实生成了每条射线的到达角和离开角,有些版本的信息结构里能把这些角度取出来。做波束赋形仿真时,这些角度信息对设计码本、计算到达角估计误差非常有用。如果你发现默认输出没有角度,可以试着查看info输出里是否有相关字段,或者回到官方代码库寻找射线级参数导出的接口。
我在实际使用中发现,winner2的强大之处不在于它“精确复现”了某条街道的传播环境,而在于它把大量随机性组织成符合物理规律的统计数据。只要你把场景、频率、移动速度这三个核心参数设对,后续算法验证基本就能在相对真实的环境中跑了。很多人想在win2里塞进自己测量的信道数据,这反而不太推荐——测量数据和模型参数融合是个大工程,宁可先用现成场景,后期再做基于测量的参数拟合。
本文还有配套的精品资源,点击获取