2026/10/22 18:47:32

无线传感器网络仿真:Matlab与Python生成五种拓扑结构源码

无线传感器网络仿真:Matlab与Python生成五种拓扑结构源码 简介本资源面向无线传感器网络课程学习、仿真实验与毕业设计人群提供基于Matlab与Python双语言实现的完整仿真代码与数据。内容覆盖RSSI测距多边定位、五种网络拓扑结构生成、CSMA/CA五种退避策略对比、粒子群算法优化节点覆盖率以及改进LEACH路由协议与经典LEACH的仿真比较适合具备一定编程基础、需要复现或拓展WSN实验的读者。压缩包共85个文件约1.46MB以png结果图、py与m源码、md说明文档为主另含mat数据、npy数组与xml配置等便于直接运行与二次开发。目前已有602人学习下载。各实验模块均配有独立说明读者可据此快速搭建仿真环境、对比算法性能、分析覆盖率与定位误差并借助现成脚本完成从拓扑生成到协议验证的完整流程节省重复编码时间。1. 无线传感器网络仿真里拓扑结构为什么决定了后面所有事做无线传感器网络WSN仿真的人迟早会撞上同一个问题节点撒下去之后路由协议跑出来的结果跟论文里对不上。十有八九问题不在协议本身而在拓扑结构。随机撒点和网格部署在同样的 MAC 层和路由层下端到端时延能差出好几倍能量消耗曲线更是完全两种形状。这就是为什么一套能生成五种网络拓扑结构的仿真源码比单个协议实现更有复用价值——它把「场景」这个变量先固定住你才有资格去谈协议优劣。这个标题讲的是用 Matlab 和 Python 两套工具生成 WSN 仿真里最常见的五类拓扑随机均匀、网格、分簇、环形、星型并配套数据输出。它解决的是仿真实验「场景不可复现」的痛点适合做协议对比、覆盖优化、能量分析的研究生和一线验证工程师。下面按「先立概念、再动手、最后避坑」的顺序拆开讲。2. 五种拓扑结构到底在仿真什么先分清部署模型和逻辑结构2.1 随机均匀、网格、分簇、环形、星型的物理含义很多人把拓扑结构当成画图问题其实它同时约束了三件事节点的空间分布、节点间的可达关系、以及数据汇聚的方向。随机均匀部署Random Uniform模拟的是飞机撒点或环境不可控的场景节点坐标服从均匀分布连通性靠通信半径阈值判定是最接近真实又最难复现的一类。网格部署Grid把节点放在规则格点上适合做覆盖和定位算法的基准测试因为理论覆盖面积可以直接算。分簇结构Cluster先选簇头再挂成员本质是两层逻辑拓扑考察的是簇头选举和轮换策略。环形Ring让数据沿环逐跳传递用来验证多跳转发和时延累积。星型Star所有节点直连汇聚节点是单跳场景的极端对照。这五种不是随便凑的它们覆盖了从单跳到多跳、从规则到随机、从平面到分层的完整谱系。你在做协议对比时至少要选三种拓扑交叉验证否则结论很容易只在某一种分布下成立。2.2 为什么 Matlab 和 Python 要各做一遍Matlab 的优势在矩阵运算和内置绘图生成坐标矩阵、算距离矩阵、画拓扑图几行就够适合快速验证算法逻辑。Python 的优势在生态和可扩展性生成的数据能直接喂给网络仿真库或机器学习流程也方便做批量实验和参数扫描。两套实现共用同一套拓扑定义和随机种子约定才能保证「同一拓扑在两边跑出同样的邻接矩阵」。常见做法是Matlab 负责算法原型和可视化Python 负责批量生成数据集和后续分析中间用统一的坐标与邻接矩阵格式对接。2.3 统一的数据契约坐标矩阵、邻接矩阵、通信半径不管哪种拓扑输出必须统一成三样东西节点坐标矩阵 N×2、邻接矩阵 N×N、以及通信半径 R。邻接矩阵的生成规则是两节点欧氏距离小于等于 R 则置 1否则置 0。这一步是后面所有路由和能量计算的地基写错了整个仿真就是空中楼阁。下面给出 Python 侧的通用生成框架五种拓扑都挂在这个契约上。import numpy as np def build_adjacency(coords, radius): 根据坐标和通信半径生成邻接矩阵 n coords.shape[0] adj np.zeros((n, n), dtypeint) for i in range(n): for j in range(i 1, n): dist np.linalg.norm(coords[i] - coords[j]) if dist radius: adj[i, j] adj[j, i] 1 return adj def random_uniform(n, area, radius, seed42): 随机均匀部署 rng np.random.default_rng(seed) coords rng.uniform(0, area, size(n, 2)) return coords, build_adjacency(coords, radius)逻辑说明build_adjacency用双重循环算两两距离对称置位保证无向图。参数上n是节点数area是正方形边长radius是通信半径seed固定随机种子保证可复现。节点数一般取 50 到 200半径按面积和节点数估算保证平均度在 6 到 10 之间比较接近真实网络。种子不固定你每次跑出来的图都不一样实验就没法对比这是新手最容易忽略的一点。3. 用 Matlab 生成五种拓扑坐标矩阵与邻接矩阵的最小实现3.1 网格与环形拓扑的确定性生成网格和环形是确定性的不需要随机种子适合做基准。网格把节点排在 sqrt(n)×sqrt(n) 的格点上环形把节点均匀放在圆周上。Matlab 里用 meshgrid 和 linspace 就能搞定。function [coords, adj] grid_topology(n, area, radius) % 网格拓扑节点排在规则格点上 side ceil(sqrt(n)); [X, Y] meshgrid(linspace(0, area, side), linspace(0, area, side)); coords [X(:), Y(:)]; coords coords(1:n, :); % 截断到 n 个节点 adj build_adj(coords, radius); end function [coords, adj] ring_topology(n, radius_ring, comm_radius) % 环形拓扑节点均匀分布在圆周上 theta linspace(0, 2*pi, n1); theta(end) []; coords [radius_ring*cos(theta), radius_ring*sin(theta)]; adj build_adj(coords, comm_radius); end function adj build_adj(coords, radius) n size(coords, 1); adj zeros(n, n); for i 1:n for j i1:n if norm(coords(i,:) - coords(j,:)) radius adj(i,j) 1; adj(j,i) 1; end end end end逻辑说明grid_topology先生成完整格点再截断保证节点数精确等于 n。ring_topology用角度均分radius_ring是环半径comm_radius是通信半径两者要匹配——环半径太大而通信半径太小环就断成孤岛。参数上网格的area和radius决定连通度环形的comm_radius至少要大于相邻节点弧长否则连不成环。这两个函数都不依赖随机数跑一百次结果完全一致适合做回归测试。3.2 分簇与星型拓扑的汇聚节点处理分簇和星型都涉及一个特殊节点汇聚节点Sink。星型里所有普通节点直连 Sink分簇里普通节点先连簇头、簇头再连 Sink。实现上要把 Sink 单独放在坐标矩阵最后一行邻接矩阵对应行单独处理。function [coords, adj, cluster_id] cluster_topology(n, k, area, radius, seed) % 分簇拓扑k 个簇头其余为成员 rng(seed); coords rand(n, 2) * area; head_idx randperm(n, k); % 随机选 k 个簇头 cluster_id zeros(n, 1); for i 1:n dists vecnorm(coords(head_idx,:) - coords(i,:), 2, 2); [~, cluster_id(i)] min(dists); % 就近入簇 end adj build_adj(coords, radius); % 强制簇内连通成员只与同簇节点和簇头相连 for i 1:n for j 1:n if cluster_id(i) ~ cluster_id(j) ... ~ismember(i, head_idx) ~ismember(j, head_idx) adj(i,j) 0; end end end end逻辑说明head_idx随机选簇头cluster_id记录每个节点归属vecnorm算到各簇头的距离取最近。强制簇内连通的循环是关键——物理上距离够近但不同簇的节点在逻辑拓扑里不应该直接通信否则分簇就失去意义。参数上k一般取节点数的 5% 到 10%radius要保证簇头能覆盖成员。星型更简单把 Sink 放最后一行所有节点只与 Sink 建边即可这里不重复贴代码。3.3 把坐标和邻接矩阵导出成可复用的数据文件仿真做完要留数据否则下次没法复现。Matlab 侧用 save 存成 .matPython 侧用 numpy 存成 .npz 或 .csv两边字段名对齐。coords_list {}; adj_list {}; labels {}; [coords_list{1}, adj_list{1}] random_uniform(n, area, radius, 42); [coords_list{2}, adj_list{2}] grid_topology(n, area, radius); % ... 其余三种 labels {random,grid,cluster,ring,star}; save(wsn_topology_data.mat, coords_list, adj_list, labels);逻辑说明用 cell 数组存五种拓扑labels记录类型名方便后续按名索引。存成单个 .mat 文件比散落多个文件好管理。参数上文件名和字段名一旦定下就别改Python 侧读取时按同样字段名解析避免对接时字段错位。数据文件里建议同时存下生成时的n、area、radius、seed否则过两周你自己都不记得这组数据是怎么来的。4. 避坑与排查拓扑生成最容易翻车的五个地方4.1 通信半径设错导致全连通或全孤立现象邻接矩阵要么全是 1要么全是 0仿真跑出来毫无区分度。原因通信半径 R 与部署面积、节点数不匹配。R 太大任意两点都可达退化成全连通图R 太小节点互相够不着网络直接分裂。解决先估算平均度公式是平均度约等于 n×π×R²/area目标控制在 6 到 10。按这个反推 R再微调。别凭感觉设 R这是血泪经验。4.2 随机种子没固定实验无法复现现象同样的代码跑两次拓扑图不一样协议指标对不上。原因随机部署用了系统时间做种子。解决所有涉及随机的函数显式传入 seedMatlab 用 rng(seed)Python 用 default_rng(seed)。种子值写进数据文件论文里也要注明。这一步不做你的实验就是一次性的没有后悔药。4.3 分簇时簇头选到边缘节点现象分簇拓扑里某些簇只有一个成员或者簇头在角落覆盖不到成员。原因簇头纯随机选没考虑空间分布。解决改用 k-means 初始化或按密度加权选簇头保证簇头之间有一定间距。简单做法是选完簇头后检查每个簇的成员数低于阈值就重选。参数上最小簇成员数建议不低于 n/(2k)。4.4 Matlab 和 Python 的坐标顺序不一致现象同一组数据在两边画出来的图是镜像的。原因Matlab 的 meshgrid 默认是 (x,y) 而某些 Python 写法是 (row,col)索引顺序反了。解决约定统一用 N×2 的 [x, y] 格式导出前用 assert 检查维度。对接时先拿 5 个节点的小样本对一遍坐标确认无误再跑大批量。4.5 邻接矩阵对称性被破坏现象路由算法跑出单向链路数据包有去无回。原因建边时只置了 adj(i,j) 忘了 adj(j,i)或者分簇裁剪时只裁了一个方向。解决建边后强制对称adj max(adj, adj)或者写完检查 issymmetric(adj)。这个检查加在函数末尾成本极低能省掉大量调试时间。5. 进阶用拓扑数据做协议对比与批量实验拓扑生成只是起点真正体现价值的是拿它做批量对比。我一般会固定五种拓扑每种跑 30 个随机种子统计端到端时延、能量消耗、丢包率的均值和方差。这样得出的结论才站得住而不是挑一个好看的种子说事。具体做法是写一个实验驱动脚本外层循环拓扑类型内层循环种子每次生成拓扑后调用路由协议把指标写进结果表。Python 侧用 pandas 汇总Matlab 侧用 table 汇总最后画箱线图对比。下面是一个批量实验的骨架。import pandas as pd from topology import random_uniform, grid_topology # 假设已实现 results [] for topo_name, gen_func in [(random, random_uniform), (grid, grid_topology)]: for seed in range(30): coords, adj gen_func(n100, area100, radius25, seedseed) # 这里接入你的路由协议返回指标字典 metrics run_routing(adj, coords) metrics.update({topology: topo_name, seed: seed}) results.append(metrics) df pd.DataFrame(results) summary df.groupby(topology).agg([mean, std]) summary.to_csv(topology_comparison.csv)逻辑说明外层遍历拓扑内层遍历种子run_routing是你自己的协议入口返回时延、能耗等指标。groupby按拓扑聚合均值和标准差to_csv落盘。参数上种子数 30 是经验值少于 20 方差估计不稳多于 50 收益递减。指标里一定要带 seed 列方便回溯异常样本。验证方法上有个简单但有效的自检对每种拓扑检查邻接矩阵的连通分量数。随机拓扑在 R 合适时应该只有 1 个连通分量网格和环形同理星型天然 1 个分簇要保证簇头之间连通。连通分量数大于 1说明你的 R 或簇头选择有问题先修拓扑再谈协议。最后说个习惯每次生成拓扑后先把坐标和邻接矩阵画出来看一眼再往下跑。图上一眼能看出的问题代码里可能要调半天。这个习惯帮我省过无数次返工。希望帮到你。本文还有配套的精品资源点击获取