简介:面向无线传感器网络路由优化与路径规划研究,这份Matlab源码包实现了基于Dijkstra算法的路由选择,并模拟随机路点运动模型下的节点动态变化,适合通信工程、物联网方向的高年级本科生、研究生以及算法仿真人员用于课题验证和算法对比。压缩包共33个文件,其中5个.m脚本包含Dijkstra路由、能耗计算、主测试等核心程序;20个.mat数据文件保存了吞吐量、平均能耗、存活节点数等多项实验结果;7张jpg图片为运行过程与结果的可视化截图;另有1个txt简要说明文件,整体仅169KB,结构清晰便于按功能索引。目前已有138人学习下载。借助这些源码与数据,读者可以快速复现基于Dijkstra的路由流程,理解随机路点模型下路由算法的实现细节,并对照ModifiedLEACH、CORPACO等协议在能量效率、网络生命周期方面的表现,支撑后续改进与二次开发,是路径规划与无线传感器网络模拟中可直接运行的参考资料。
1. 先把场景说清楚:移动的无线传感器网络,Djisktra 算法能做路由吗
当你摊开一张 500m×500m 的仿真地图,几十个无线传感器节点按随机路点模型不停地换位置,每个节点采集到的数据要绕回角落里那个汇聚节点(sink),这时“路由”就成了一件让人头疼的事:拓扑每秒都在变,静态的路由表一眨眼就过期。标题里那个“基于 Djisktra 算法实现路由”,说的就是用图论里最经典的单源最短路径算法 Djisktra——注意这个拼写在很多源码包里就是这么写的——去给无线传感器网络(WSN)计算转发路径,再配上随机路点运动模型模拟节点真实移动,最后用 Matlab 出图和统计。这套组合拳最常见于课程设计、本科毕设和论文仿真,也适合任何一个想快速验证“最短路径路由在移动网络里能跑到什么程度”的工程师。接下来按“模型—边权—代码—避坑”的顺序,把这类压缩包里大概率会遇到的技术方案完整拆一遍。
2. 随机路点运动模型与 WSN 仿真场景:先定参数再写代码
2.1 随机路点模型的三要素:目标点、速度和暂停
随机路点模型(Random Waypoint,RWP)是移动自组织网络仿真里最常用的节点运动模型,原理不难:每个节点在当前区域内随机选一个目标点,再从速度区间里随机抽一个速度匀速走过去,到达后随机暂停一段时间,然后继续选下一个目标点。整个过程只需要三个随机量——目标坐标、速度、暂停时长——却能模拟出从“巡逻式移动”到“走走停停”的多种移动特征。
很多第一次接触的人会把随机路点模型和随机游走(Random Walk)搞混。随机游走是每一步在当前位置附近随机改变方向,轨迹像布朗运动一样碎;随机路点模型是每段路程都是匀速直线运动,中间有明确的暂停,轨迹更像配送员或巡逻车。在无线传感器网络里,后者能直观模拟出节点带着采集任务在监测区域移动的场景,也方便把每段移动距离和暂停时间纳入能耗计算。
这个模型有个反直觉的地方:长期平均速度不等于速度区间的中值。原因是慢速节点在移动相里停留的时间更长,快速节点更早到达目标点进入暂停,统计下来低速样本被加权了。跑仿真时如果想统计节点平均速度,直接取区间均值会偏高,这个问题后面避坑章还会细说。
2.2 Matlab 仿真参数表:区域、节点数、速度、时隙怎么配
参数设置是仿真第一个玄学环节,很多翻车都和参数拍脑袋有关。下面这组参数是这类 WSN 路由仿真常用的起步值,区域大小、节点密度和通信半径三者要放在一起看:
| 参数 | 常用起步值 | 说明 |
|---|---|---|
| 仿真区域 | 500m × 500m | 正方形,坐标范围 [0, 500] |
| 节点数 N | 40 ~ 80 | 节点少时路由稀疏,节点多时接近全连通 |
| 速度范围 vrange | [1, 20] m/s | 模拟步行到车辆移动,速度下限别设 0 |
| 最大暂停 pause_max | 0 s 或 10 s | 0 表示持续移动,用于最坏情况验证 |
| 通信半径 comR | 80 ~ 120 m | 决定邻接矩阵密度,建议先算连通率 |
| 仿真时长 T_total | 100 ~ 500 s | 太短冷启动影响明显,太长统计曲线冗余 |
| 时隙 dt | 1 s | 移动步长和路由重算周期的基本单位 |
通信半径的选择可以用一个粗公式估算:节点密度 × π comR² 最好不小于 1,也就是平均每个节点至少有 1 个邻居,否则网络容易不连通,Dijkstra 会出现大片不可达。以 60 个节点、500m 区域、comR=100m 为例,平均邻居数约为 60 × π × 100² / 500² ≈ 7.5,这个密度对路由仿真比较舒服。
时隙 dt 要与速度上限匹配。如果 vmax=20 m/s、dt=1s,节点每时隙最多移动 20m,而通信半径是 100m,链路不会因为一步移动就剧烈跳变;如果把 dt 改成 5s,节点一帧跑 100m,拓扑每帧面目全非,路由重算频率就必须跟着加密。一般让“最大速度 × dt”不超过通信半径的 1/5,画出的轨迹才会平滑、路由曲线也不会毛刺满天飞。
补充一个容易被忽略的量:暂停时间的期望值。均匀随机暂停时长为 [0, pause_max] 时,平均暂停是 pause_max/2。仿真平均速度与节点忙碌移动速度之间的换算,工程上常用占空比表示:移动占空比 = T_move/(T_move+T_pause),平均等效速度 = v_mean × 移动占空比。设计能耗路由时,暂停比例直接关系到节点空闲能耗与移动能耗的权重,建议在参数表里显式记录,而不是让代码写死。
2.3 为什么静态拓扑不够,要用移动模型托底
如果是给论文凑一张最短路径的静态图,固定节点的随机拓扑配合 Djisktra 算法就能出效果,很多源码包也是这样处理的。可一旦涉及无线传感器网络的真实部署——车载传感器、人员佩戴节点、灾区临时布设——节点移动才是常态,静态拓扑得到的是“某个瞬间的最优路径”,无法回答“这种路由策略在移动环境下时延和丢包表现如何”。
移动模型给路由仿真带来的额外维度是时间:拓扑每一秒都不同,路由需要周期重算,数据包可能在半路遇到下一跳失联。路径规划这个大方向下的场景其实都一样,无人机三维路径规划、AGV 路径规划、ROS2 里的导航栈,说到底都是在一个动态变化的空间里反复找可行路径,Djisktra 这类图搜索算法是共同地基。把 WSN 里的随机路点模型跑明白,后面再去做动态避障小车路径规划,思路是互通的。
3. Dijkstra 路由建模:边权怎么定义,路由表怎么生成
3.1 边权三选一:距离、链路质量、剩余能量
这一章讨论的建模都基于圆盘通信模型:只要两节点距离小于通信半径,链路就存在且对称,距离等于通信半径时仍视为连通。这个假设在真实信道里过于乐观,但作为路由算法的对照实验足够用;如果要更贴近实际,可以在此基础上叠加丢包概率,把链路质量以 1-p 的概率随机摘除,再观察路由的容错表现。
教材里的 Dijkstra 算法作用在加权图上,边权只是一个抽象数;到了无线传感器网络里,边权到底用什么值,直接决定了这条路是“最短”还是“最划算”。最常见的做法有三种:一是几何距离,也就是节点间欧氏距离,算出来的是空间最短路径,跳数少但可能集中经过某些节点;二是链路质量,丢包率或 ETX(期望传输次数)加权,路径会绕开弱链路,抗干扰强;三是能耗相关,用传播损耗或剩余能量构造权值,目的变成延长网络生命周期。
| 边权方案 | 权值公式 | 适用场景 | 主要缺点 |
|---|---|---|---|
| 几何距离 | w = d(i,j) | 基线对比、最少跳数 | 不考虑节点负载,热点容易死 |
| 链路质量 | w = 1 / 丢包率 或 w = ETX | 信道不稳的室外场景 | 需要维护实时链路统计 |
| 距离平方能耗 | w = d(i,j)² | 重点考察能耗的 WSN | 路由重算频繁,耗时长 |
| 剩余能量加权 | w = d(i,j)² / E_res | 延长网络生命周期 | 剩余能量变化导致路由抖动 |
在把源码扩展到自己的场景时,建议保留一个“权值类型”开关,先用几何距离跑通流程,再切到能量加权做对比,不要一上来就把公式写死在主循环里。这一章的代码都按几何距离实现,第 6 章会给能量感知的改进版本,方便前后对照。
3.2 用稀疏矩阵还是全矩阵:几百个节点以内的经验分界线
WSN 仿真里邻接矩阵是 N×N 的,N 是节点数。对于几十个节点,直接用全矩阵最省心;节点数超过 500,全矩阵虽然只占 2MB,但每次移动一步都要重新填一遍矩阵,Dijkstra 内部扫描邻居的find操作也会随 N² 变慢,这时就值得用稀疏矩阵。
稀疏矩阵的构建思路是只存存在的链路,不存在的边不分配内存。下面这段代码以通信半径建图,生成的是 sparse 形式的邻接矩阵:
% 基于通信半径建立稀疏邻接矩阵 % pos: N x 2 坐标矩阵; comR: 通信半径; N: 节点数 adj = sparse(N, N); for i = 1:N d2 = sum((pos - pos(i,:)).^2, 2); % 所有节点到 i 的距离平方 link = find(d2 <= comR^2 & d2 > 0); % 落在通信半径内且不是自身 if ~isempty(link) adj(i, link) = sqrt(d2(link)); end end这里用d2 > 0把自环排除掉,因为坐标重叠的节点不存在;sqrt(d2(link))把距离平方转成真实距离作为边权。注意稀疏矩阵中未存储的元素读取结果是 0,而不是无穷大,这与 Dijkstra 算法里“不连通边为 inf”的约定不一样,后面避坑章专门有一条讲这个,代码如果换了写法容易在那里翻车。
3.3 从 dist 和 prev 生成全网路由表与下一跳
WSN 的数据流多数是“多对一”:所有普通节点把数据发给 sink。这时不需要为每个节点各跑一次 Dijkstra,只要把 sink 当作源节点跑一次单源最短路径,就能得到一棵以 sink 为根的最短路径树,每个节点沿树向上就能到达 sink。
Dijkstra 结果通常用两个数组表达:dist 存每个点到源的最短距离,prev 存路径上每个节点的前驱。已知 prev 后,从目的节点一路回溯到源节点,把节点顺序反转,就是一条完整路径;路径上的第二个节点,就是当前节点要转发的下一跳。
% 从 prev 数组回溯 src 到 dst 的完整路径 % dist/prev 由 dijkstra_route 返回; src 是 sink 节点号 path = []; cur = dst; while cur ~= 0 && cur ~= src path = [cur path]; % 从 dst 往回收集,再反序 cur = prev(cur); end if cur == 0 path = []; % 不可达 else path = [src path]; % 补上源节点 end next_hop = path(2); % path(2) 就是 dst 的下一跳prev(cur)为 0 表示该点无前驱,也就是源节点不可达,此时路径为空,数据包只能丢。实际主循环里可以直接用next_hop做转发模拟,但要注意这条下一跳是在本时隙的拓扑上算出来的,下一时隙节点一动可能就失效了。路由表重算周期和节点移动速度之间的匹配,参数上按“最远邻居过期时间”估算,比如 vmax=20m/s、comR=100m,一个位于通信半径边缘的邻居最快 5s 就离开范围,重算周期设 1~2s 比较稳妥。
4. Matlab 实现随机路点 + Dijkstra 路由:可直接照抄的代码框架
4.1 随机路点模型的初始化与单步更新
随机路点模型的实现核心是 rwp_init 和 rwp_step 两个函数,前者生成初始状态,后者按 dt 推进一个时隙。初始化时节点位置从区域内均匀抽取,目标点、速度、暂停时间各自随机。预热处理放在主循环里做,先把节点按模型跑一段再开始统计,避免冷启动影响结果,这部分代码放在 4.3 的主循环里。
function pos = rwp_init(N, area) % 随机路点模型初始化:均匀分布初始位置 % N: 节点数; area: 正方形区域边长 rng(42); % 固定随机种子,确保结果可复现 pos = rand(N, 2) * area; end随机种子固定是复现仿真结果的前提。rng(42)里 42 只是示例值,参数扫描时每个种子代表一次独立实验,统计时才不把随机波动当成算法差异。这里初始位置均匀分布虽然常用,但它正是 RWP 冷启动瞬态的根源,严格做法是从稳态分布采样,工程上多数人嫌复杂,直接用后面主循环里预热 50 到 200 个时隙来烧掉这段。
单步更新函数处理两种状态:暂停中的节点只做倒计时;移动中的节点先判断本时隙能否到达目标,能到就重新选目标和暂停时间,不能到就沿方向匀速走一步。
function [pos, targets, speeds, pause_t] = rwp_step(pos, targets, speeds, pause_t, area, vrange, pause_max, dt) % 随机路点模型单步更新 % pos/targets: N x 2 坐标; speeds: N x 1 速度; pause_t: 剩余暂停时间 % dt: 时隙长度 for i = 1:size(pos, 1) if pause_t(i) > 0 pause_t(i) = pause_t(i) - dt; % 暂停期不动 continue; end dir = targets(i,:) - pos(i,:); dist = norm(dir); if dist < 1e-6 % 目标与当前位置重合,重新选目标 targets(i,:) = rand(1, 2) * area; continue; end step_len = speeds(i) * dt; if step_len >= dist % 本时隙能到达目标 pos(i,:) = targets(i,:); targets(i,:) = rand(1, 2) * area; speeds(i) = vrange(1) + (vrange(2) - vrange(1)) * rand; pause_t(i) = pause_max * rand; % 开始随机暂停 else pos(i,:) = pos(i,:) + dir / dist * step_len; end end enddir / dist * step_len是方向向量归一化后乘步长,保证每时隙移动量严格等于 speed × dt;如果直接乘在 dir 上,步长会被目标距离放大或压缩。新增的dist < 1e-6判断是为了防止目标与当前位置重合时出现除零。这里把“到达目标”和“未到达”两个分支分开写,比在循环末尾做判断更清晰,改暂停分布或速度分布时也不用动主逻辑。暂停时间用pause_max * rand生成 [0, pause_max] 的均匀随机数,如果想换成指数分布暂停(更接近真实行为),把这一行替换成exprnd(pause_max/2)即可。
4.2 Dijkstra 的最简可读实现:O(N²) 版
对于几百个节点,O(N²) 的经典实现比带二叉堆的版本更好读懂,也更容易在课程报告中解释。算法外层循环每次从未访问集合里挑一个 dist 最小的节点,然后松弛它的所有邻居;如果目标节点已经被挑出,可以提前终止。
function [dist, prev] = dijkstra_route(adj, src, dst) % dijkstra_route: 单源最短路径,返回距离与前驱数组 % adj: 邻接矩阵,不连通边为 inf; src: 源节点; dst: 目标节点 % 注意:传入稀疏矩阵前先转 full,否则 0 与 inf 的语义会出错(见避坑章) N = size(adj, 1); visited = false(N, 1); dist = inf(N, 1); prev = zeros(N, 1); dist(src) = 0; for k = 1:N % 从未访问集合中找 dist 最小的节点 unvisited = find(~visited); if isempty(unvisited), break; end [~, idx] = min(dist(unvisited)); u = unvisited(idx); if dist(u) == inf, break; end % 剩余节点不可达 visited(u) = true; if u == dst, break; end % 提前终止 % 松弛 u 的所有邻居 nbrs = find(adj(u, :) ~= inf); % 用邻接矩阵判断连通 for vi = 1:numel(nbrs) v = nbrs(vi); alt = dist(u) + adj(u, v); if alt < dist(v) dist(v) = alt; prev(v) = u; end end end endmin(dist(unvisited))得到的是压缩数组的最小值和索引,必须再用一次unvisited(idx)还原真实节点编号,这是初学者最容易写错的一行。提前终止的判断放在visited标记之后,保证目标节点被选出来时它的 dist 已经是最优。邻接矩阵在 3.2 节里已经保证不连通边是 inf,如果用稀疏矩阵且没有做转换,这里的adj(u,:) ~= inf判断会因为 0 元素误伤,翻车细节看第 5 章。
4.3 主循环:移动、建图、算路、统计、可视化
主循环把前面的函数串起来:每个时隙先让节点按随机路点模型移动一步,再重新建邻接矩阵,以 sink 为源头算一次最短路径树,然后把想看的结果存进统计数组。预热段在正式统计前执行,常见的做法是让模型空转 50 到 200 个时隙。
%% 参数区 N = 60; area = 500; vrange = [1 20]; pause_max = 10; comR = 100; T_total = 200; dt = 1; %% 初始化与预热 pos = rwp_init(N, area); targets = rand(N, 2) * area; speeds = vrange(1) + (vrange(2) - vrange(1)) * rand(N, 1); pause_t = zeros(N, 1); for t = 1:100 % 预热,丢弃冷启动段 [pos, targets, speeds, pause_t] = rwp_step(pos, targets, speeds, pause_t, area, vrange, pause_max, dt); end %% 统计准备 route_len = zeros(T_total, 1); %% 主循环 for t = 1:T_total [pos, targets, speeds, pause_t] = rwp_step(pos, targets, speeds, pause_t, area, vrange, pause_max, dt); adj = inf(N, N); % 全矩阵版,N 小于 500 够用 for i = 1:N d2 = sum((pos - pos(i,:)).^2, 2); link = find(d2 <= comR^2 & d2 > 0); adj(i, link) = sqrt(d2(link)); end [dist, prev] = dijkstra_route(adj, 1, N); % 1 号节点当 sink if isinf(dist(N)) route_len(t) = NaN; % 网络不连通,本时隙没有路径 else route_len(t) = dist(N); % 这里存的是最短路径距离 end end注意初始化里有几行看起来重复:rwp_init只给了初始 pos,而 targets 和 speeds 还要在外部手动补上。更规范的做法是把它们都包进 init 函数,这里为了读者看清每个随机量的来源,故意保留了显式写法。主循环里dist(N)存的是节点 N 到 sink 的最短路径距离,如果只想统计跳数,可以把邻接矩阵的权值全部改成 1,也就是“几何距离”换成“跳数”,再跑一次 Dijkstra,两者可以同时输出做对比。
可视化只加在需要出图的时隙,避免每次循环刷新拖慢仿真。常见做法是每统计间隔画一次当前节点位置、sink 标记和示例路径,再用 getframe 抓帧存成 GIF(保存 GIF 的坑在第 5 章)。
if mod(t, 10) == 0 % 每 10 个时隙画一次 cla; plot(pos(:,1), pos(:,2), 'bo'); hold on; plot(pos(1,1), pos(1,2), 'rp', 'MarkerSize', 14); axis([0 area 0 area]); title(sprintf('t=%d s', t)); drawnow; endmod(t, 10)控制绘图频率,绘图本身不影响统计结果;drawnow强制刷新画面,少了它 Matlab 会把绘图命令积压到最后才显示,视觉上就像仿真“卡住”了。如果想把节点 N 到 sink 的完整路径画成折线,要在主循环里保留 prev 数组,绘图段之前加一段回溯:
% 从 prev 回溯路径并画折线(放在绘图段内) path = []; cur = N; while cur ~= 0 && cur ~= 1 path = [cur path]; cur = prev(cur); end if cur ~= 0 plot(pos([1 path], 1), pos([1 path], 2), 'r-', 'LineWidth', 1.5); end提示:上面的预热段只是工程近似,正式论文里建议说明预热长度与丢弃策略;想深究可以查 RWP 稳态分布相关文献。
5. 避坑:从 Djisktra 拼写到 RWP 冷启动的 5 个高频翻车现场
这些坑不是猜的,是从这类仿真最常见的报错和异常曲线里倒推出来的。每条按现象、原因、解决三部分来排。
5.1 拼写坑:标题里的 Djisktra 不是笔误,是源码包的“事实标准”
现象:下载的压缩包里,函数名写的是Djisktra,调用正确拼写dijkstra_route后 Matlab 直接报Undefined function。更麻烦的是,同一个包里注释、文件名、调用处三处拼写可能不完全一致。
原因:最初的源码把 Dijkstra 拼错成 Djisktra,打包站点和网盘互相搬运时都沿用了错名,这个错拼反而成了这批源码的可检索特征。搜索引擎里搜 Djisktra 更容易找到同源压缩包。
解决:解压后先做一次全局文本替换,把 Djisktra 统一改成 dijkstra,再跑主脚本;如果文件名也错了,连同.m文件名一起改。自己动手写时用正确拼写,目录名也别偷懒,否则半年后回看代码自己都会绕晕。
5.2 RWP 冷启动瞬态:平均速度和生命周期曲线集体虚高
现象:把 RWP 跑完后统计节点平均速度,结果明显大于预设区间均值;生命周期曲线开头几秒下掉得异常陡峭。
原因:初始化时节点位置从区域内均匀分布抽取,等效于让节点“凭空出现在中间”,最开始的目标跨度偏大,移动速度偏高;此外 RWP 的长期平均速度本来就低于区间均值,冷启动会把两种偏差叠加。
解决:统计前加预热段,让模型空转 50 到 200 个时隙再开始采集。如果做能量感知路由,预热段同时要计入能耗,否则初始几秒能耗被错误地算成“零”。想更严谨就研究 RWP 的稳态分布初始化,但大多数课设和论文用预热已经足够。
5.3 稀疏矩阵的 0 与 inf:Dijkstra 松弛翻车现场
现象:把邻接矩阵换成 sparse 之后,Dijkstra 结果大面积异常,很多节点的距离变成 0,路径树看起来像是“全网络零距离连通”。
原因:sparse 矩阵没有存储的元素读取返回值是 0,而 Dijkstra 判断链路是否存在的条件往往是adj(u,v) ~= inf。当 0 被当作合法权值参与松弛,所有“不存在的边”都变成零距离边,算法自然失效。
解决:推荐在节点数小于 500 时直接用全矩阵;一定用 sparse,就得在建图后把不连通位置显式补 inf,或者 Dijkstra 内部读取时先w = full(adj(u, v)); if w > 0再松弛。避免用~= inf作为连通判断,改用> 0,因为 0 在权值为正的模型里只可能出现在不连通的占位里。
5.4 路由表过期与回环:别让节点带着旧地图上路
现象:仿真到中段丢包率开始跳动,路径统计里出现明显回环,数据包在几个节点之间来回转发,跳数统计一度接近 T_total。
原因:RWP 让节点持续移动,上一时隙算好的下一跳可能已经跑出通信半径,但主循环还在按旧路由表转发。这是动态拓扑仿真的共性问题,和实现语言无关。
解决:把路由重算周期 T_route 与移动步长解耦,常见做法是每 2 到 5 个时隙重算一次 Dijkstra;或者在单步移动后检查“下一跳距离是否仍小于 comR”,失联则触发重算并把当前包丢弃。统计丢包率时,把这种“路由过期导致的丢包”单独计数,分析时能看出是算法问题还是参数问题。
5.5 动画保存黑屏:drawnow 与 GIF 帧的时序坑
现象:循环里用 print 或 getframe 保存 GIF,结果每一帧都是全白或全黑,文件还不小;换成录 AVI 又遇到编码器不识别。
原因:绘制后没有及时调用 drawnow,帧缓冲里拿到的内容是上一次绘图结果;另外 Matlab 新版本的drawnow limitrate在旧版本上会直接报错,迁移脚本时容易忽略版本差异。
解决:每帧统一按“绘图 — drawnow limitrate(或 drawnow)— getframe — imwrite 追加”的顺序执行。保存 GIF 时用imwrite(frame.cdata, cmap, 'rwp_demo.gif', 'gif', 'WriteMode', 'append'),第一帧不追加、后续帧追加。GIF 不要存超过 300 帧,文件会膨胀到几十 MB,想演示流畅性建议直接录视频或用exportgraphics导出 PNG 序列。
注意:R2018a 之前的 Matlab 不支持
drawnow limitrate,脚本里直接改成drawnow即可。
6. 进阶验证:把静态最短路径改成能量感知路由,用生命周期曲线说话
到这一步,你已经能用 Matlab 在随机路点模型上跑通 Dijkstra 路由。但能出图只是起点,值不值得继续投入,要看这个方向能不能回答“你的路由策略比朴素最短路径好在哪”。最快速有效的进阶就是改成能量感知路由:边权从纯距离变成与剩余能量挂钩,让路由自动避开快没电的节点。
% 能量感知邻接矩阵:w = d^alpha / E_res,alpha 常取 2 alpha = 2; E_init = ones(N, 1); % 各节点初始能量相同 E_res = E_init; % 在主循环建图处替换 adj 构造 adj = inf(N, N); for i = 1:N d2 = sum((pos - pos(i,:)).^2, 2); link = find(d2 <= comR^2 & d2 > 0); adj(i, link) = (d2(link).^(alpha/2)) ./ E_res(link); end % 每轮转发后扣减能耗,简化模型按路径距离结算 % E_res = E_res - send_energy_per_packet;验证方法是对照实验:方案 A 用第 4 章的纯距离 Dijkstra,方案 B 用上面的能量感知权值,在相同随机路点轨迹下各跑 10 次(换 rng 种子),统计两个指标——第一个节点死亡时间(FND)和 50% 节点死亡时间;横轴画时间,纵轴画存活节点数,两条曲线对比最直观。因为 RWP 是随机过程,单次跑出来的优势说明不了问题,一定要多次取平均再下结论。
这个阶段的血泪经验是:别急着加复杂的能耗模型。先把距离权值和能量权值两条曲线跑出来对齐预期,再逐步加入丢包率、发射功率控制这些东西;一上来堆参数,结果不对劲时根本分不清是路由算法的问题还是能耗模型的问题。我自己第一次跑这类仿真时,整晚看着生命周期曲线前段下坠得离谱,最后发现只是 RWP 忘了预热,白白熬了一宿。
如果验证下来能量感知路由确实延长了生命周期,这个方向就值得继续投入:可以加链路质量维度,可以结合移动预测提前计算路由,也可以把节点死后的拓扑空洞处理加进来。这类压缩包真正有价值的地方,是提供了一个最小可复现的底座,你能在它之上改出可对比、可解释的结果。希望上面关于拼写与预热的弯路记录,能帮你在自己的仿真里省掉几个通宵——毕竟算法拼对很容易,模型和参数拼对才是真功夫。
本文还有配套的精品资源,点击获取