尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

LoRa网状网络改进AODV与速率自适应OPNET仿真研究

LoRa网状网络改进AODV与速率自适应OPNET仿真研究 做LoRa组网这件事大多数人第一反应就是LoRaWAN星型拓扑终端直连网关简单粗暴。可真到了管廊、矿区、电力杆塔这类覆盖距离长、网关位置又不方便布设的场景单跳根本覆盖不住这时候“LoRa网状网络”就成了绕不开的方向。Mesh拓扑好画真正让人头疼的是路由协议。我当时在OPNET里试过直接上经典AODV结果非常打脸——控制报文洪泛加上LoRa那条窄得可怜的带宽路由发现还没结束信道先被占满了。这篇内容就是记录我当时在OPNET里做“速率自适应改进型AODV”仿真研究时的完整思路包括路由协议为什么必须改、速率自适应到底在调什么、OPNET里怎么把LoRa物理层和路由层搭建起来以及最后仿真数据说明了什么。对正打算用OPNET/NS3这类工具做LoRa路由仿真的朋友应该能省掉不少自己摸索的时间。1. 把AODV搬进LoRa网络之前先要认清Mesh场景的真实约束1.1 LoRaWAN星型结构为什么在某些场景下不够用LoRaWAN默认模型是“终端-网关”星型连接终端通过随机信道访问把数据发给网关。好处很明显协议简单、终端休眠省电、网络管理集中。但代价就是覆盖范围完全取决于终端到网关之间的单跳链路质量。虽然LoRa依靠扩频增益可以有“远距离”的美名但那是拿速率换来的SF12、125kHz带宽下实际吞吐还不到0.3kbps传输100字节的数据都要好几秒。要是节点距离网关太远要么把SF调到最大、牺牲整网吞吐要么增加网关密度后者的部署和维护成本立刻上来了。在电力线巡检、矿区人员定位这类场景里节点往往沿着线路或巷道呈带状分布网关位置受限一个网关覆盖不了全部末端节点把每个节点都加上4G回传又太贵。于是多跳中继变成一个很自然的方案终端先把数据发给邻近节点邻近节点再转发最终汇聚到唯一网关。“LoRa网状网络”这时候才真正有了工程意义。1.2 网状网络给路由协议提出的不是“能不能用”而是“改成什么样”Mesh架构确定之后路由协议的选择就成了核心问题。AODV是Ad Hoc网络里最常被想到的协议文档多、实现也多。但直接套用到LoRa网络上会发现环境假设几乎全部不成立带宽约束严重。AODV的路由发现靠RREQ洪泛一个50节点的网络做一次全网路由发现理想情况下要产生数十甚至上百个RREQ控制帧。每个RREQ报文在原始AODV里是几十字节如果加上自定义度量字段体积还会膨胀。放在LoRa 0.3~5kbps的速率下一次洪泛就可能占掉几十秒甚至几分钟的信道时间期间数据帧全被堵在队列里。链路质量高度不均质。AODV默认链路是对称的、质量相近的而LoRa节点分布在几百米到几公里范围内信号强度差异极大。两个相距500米的节点用SF7就能稳定通联另两个相距2公里的节点可能必须用SF12。只按“跳数最少”选路很容易选到一条跳数少但每跳都在崩溃边缘的路径。节点能力和能耗不一致。Mesh中靠近网关的节点承担大量转发任务能量消耗远高于末端节点。经典AODV完全没有能量维度长时间运行会导致关键中继节点过早死亡网络出现割裂。控制报文开销需要精打细算。AODV的HELLO报文默认每秒发送一次在LoRa网络上这个频率会导致节点根本没有时间发送数据。就算把HELLO改为按需探测也得仔细算清楚它能占用多少信道容量。所以“改进型AODV”不是噱头而是必须做的适配。改进方向我当时确定了两条主线一是把路由度量从“跳数”升级为综合考虑链路质量、剩余能量和当前速率等级的复合代价二是严格控制路由发现洪泛范围避免任何一次RREQ扩散到全网。2. 速率自适应到底在调什么——SF、BW、CR如何影响整网表现2.1 一个公式看懂LoRa的速率来源LoRa的物理层数据速率由三个参数共同决定扩频因子SF、信号带宽BW、编码率CR。工程上常用简化公式Rb SF × (BW / 2^SF) × CR其中BW/2^SF表示符号速率CR是编码率例如4/(4n)n是校验位数量常见值4/5到4/8。以最常见的125kHz带宽、CR4/5为例不同SF的速率完全不在一个量级SF符号速率(sps)数据速率(bps)接收灵敏度参考(dBm)7976.565468约 -1238488.283125约 -1269244.141758约 -12910122.07977约 -1321161.04537约 -1341230.52293约 -137注意一个反直觉的规律SF越大速率越低但接收灵敏度反而越好能解调更弱的信号。也就是说低速率的真正价值是“传输距离更远、穿透性更好”而不是“传得更快”。速率自适应的本质就是在“链路余量足够”的前提下尽可能选择最小的SF以及必要时更宽的BW让每个数据包占用尽可能短的信道时间。2.2 自适应不是“永远选最快速率”而是要喂给路由层一个稳定参数如果仅仅在源节点做自适应效果会非常有限。网状网络里数据经过多跳每一跳的链路质量都不一样。假设路径是A→B→CA到B距离较近可以用SF7B到C距离较远必须用SF10。源节点A就算把自己的速率调到SF7数据在B→C段仍然要按照SF10的速率发送整条路径的端到端时延和吞吐完全被“最差一跳”卡住。这引出一个关键设计速率自适应应该在中继节点上做并且要和路由层联动。每个节点根据收到的邻居帧的RSSI和SNR估算当前链路余量决定与哪个邻居通信时用哪个SF/BW。反馈的方式可以是通过ACK帧捎带接收端的质量测量结果也可以是每个节点定期向邻居广播带自身接收质量信息的控制帧。自适应还有一个工程难点是稳定性。节点移动、天气变化、甚至一阵风都能让RSSI抖动几个dB。如果算法太灵敏节点会在SF7和SF8之间来回切换反而导致丢包。我的做法是在OPNET仿真里加入了“迟滞”机制只有当链路余量低于当前SF门限且持续超过3个采样周期才切换更高SF只有余量高于新SF门限6dB以上且持续稳定才降低SF。否则维持原参数。2.3 多跳场景下速率自适应会引发干扰格局变化仿真的过程中我特别注意到一个问题SF不同其实带来了频率域的正交性不同SF信号在相同频段上可以部分共存这是一种天然的隔离。速率自适应让相邻节点可能使用不同SF反而降低了同频碰撞概率。但同时如果两个节点同时从SF7切到SF8它们的信号可能因为无法区分而互相干扰。所以好的自适应算法在Mesh里不能只考虑本跳链路质量还要看邻居节点的SF分布情况我在仿真模型里加了一个简单的约束节点在切换SF前先检查周围一跳邻居中使用同一目标SF的数量如果超过阈值则推迟切换。当然这个约束在实际工程里可能过于保守但在仿真阶段能大大减少“意外干扰”造成的无效实验方便把注意力集中在路由算法上。3. 改进型AODV的三处关键改动——度量、洪泛抑制、局部修复3.1 路由度量从“跳数”换成加权代价经典AODV选路原则是目的序列号越大越新序列号相同时跳数越少越好。这在高速无线自组网里可以接受因为每一跳的质量差异没那么悬殊。LoRa Mesh不行跳数最少的那条路很可能经过一个信号边缘的节点丢包率超过三成重传带来的时延远超多绕一跳。我采用的代价函数设计成三项加权MC α × ETX β × (1 - E_re / E_init) γ × T_normETX表示期望传输次数实际实现时用投递率估算投递率越低ETX越高E_re是节点剩余能量E_init是初始能量这一项让路由主动避开能量低的节点T_norm是当前节点平均排队时延的归一化值避免数据涌向拥塞节点。权重α、β、γ需要仿真时调我最终取的是0.5、0.3、0.2。这个取值有实际意义LoRa网络里链路质量还是最核心的能量次之时延排在最后。如果把β调太高会出现路由绕远路导致整体时延飙升的情况如果把γ调太高则会造成网络负载在几个低时延节点间来回震荡。RREQ报文里增加一个累计代价字段每经过一个节点就把当前节点计算的MC加到累计值上。目的节点收到多个RREQ后不是简单比较跳数而是选择累计代价最小的路径回复RREP。为了兼容旧节点我在报文里保留跳数域但选路时优先看累计代价。3.2 RREQ洪泛抑制把“广播全网”改成“定向扩散”经典AODV的RREQ是一路广播出去的Mesh网络里如果所有节点都参与转发控制开销会指数增长。在一次仿真里我发现单纯跑一个业务流RREQ产生的信道占用最多可以占到总流量的40%以上这个数字在LoRa带宽下是不可接受的。我做了两个层面的抑制RSSI门限剪枝节点收到RREQ后先看接收信号强度。如果RSSI低于一个绝对门限比如-125dBm说明这条链路本身质量堪忧即使转发RREQ也不会被后续数据使用直接丢弃。这个措施能砍掉相当一部分弱链路扩散。方向性区域扩散在每个RREQ里记录源节点和目的节点的地理位置LoRa节点通常配GPS或北斗模块这个假设在工程上成立。中间节点判断自己是否位于“源节点→目的节点”连线的椭圆区域内如果偏离太远则不转发。这两种策略合在一起能有效把洪泛控制在一个较小范围内。实测在50节点、随机拓扑下RREQ转发总量比原始AODV减少了约60%。3.3 本地修复机制优先于全路径重建AODV本身有链路断裂检测和RERR通知但默认机制是断裂点上游节点发起新一轮RREQ实际上等于局部洪泛再来一次。问题在于LoRa链路断裂常常是“暂时性衰耗”不是“物理断开”百分之百让整条路径重建代价太大。我的改进是当中间节点发现下游链路质量连续低于阈值N次后先尝试本地替代路径。具体操作是该节点缓存最近收到的、来自目标节点的反向路由信息如果有可用备份下一跳直接切换如果没有则只向“源方向”的一跳邻居发起受限RREQ范围限制在断裂点附近两跳之内。只有当本地修复在指定时间内找不到替代路径才向源节点发送RERR。这个机制大幅减少了“单点链路抖动触发全网路由重建”的尴尬情况。仿真里最明显的一个现象是原始AODV在信道波动下路由重建频率很高端到端时延曲线出现明显的锯齿而改进型AODV的时延曲线稳定得多原因是多数链路波动都被两跳以内的局部修复吞掉了。4. OPNET节点模型搭建——LoRa物理层不是拖一个Radio模块就能完事4.1 OPNET三层建模结构项目、节点、进程关系要先理顺OPNET Modeler的建模逻辑是三个层级项目编辑器负责拓扑和场景管理节点编辑器定义网络设备内部的模块构成进程编辑器用状态机描述每个模块的行为。做LoRa仿真我的建议是不要在项目编辑器里直接铺节点而是先在节点编辑器里自定义一个“LoRa节点模型”里面至少包含应用层、网络层、MAC层、物理层四部分。很多人第一次用OPNET做无线仿真以为拖一个标准的无线收发机模块就行。实际上OPNET自带的Radio Transceiver是为常规无线系统设计的默认调制方式和信道模型都是通用型和LoRa的扩频机制对不上。你要么使用自带的无线管道然后修改关键阶段要么直接什么都不改只做协议层验证——但这样的话仿真结果和真实LoRa差距会很大。4.2 自定义MAC层与物理层参数通道我在节点模型里把物理层拆成了Transmitter、Receiver、Antenna三件套并通过**Interface Control InformationICI**传递LoRa特有参数。每个数据帧的ICI结构体里包含SF、BW、CR、发射功率、发送频率等字段。接收端的无线管道读取这些字段后才能正确计算信噪比并判定是否为有效帧。发送端和接收端的配对关系是这样的发送节点在发出帧时附上ICI接收节点的无线接收机管道在接收阶段提取ICI然后依据当前SF对应的解调门限判断是否丢包。LoRa不同SF的解调门限差异很大例如SF7的SNR门限大约是-6dBSF12门限大约是-20dB。这意味着同样干扰环境下SF12能解调出来的帧SF7可能已经丢失管道模型必须按ICI中的SF参数动态选择门限。MAC层我建议仿真初期先用简化的CSMA或纯ALOHA不要一上来就实现CAD信道活动检测和LBT先听后发。在我的经验里路由算法验证阶段物理层和MAC层越简单越好先把协议性能跑通然后再逐步增加复杂度否则出了结果你根本不知道是路由问题还是信道接入问题。4.3 AODV进程模型怎么改基于自带manet_aodv还是自己写OPNET自带MANET模块里有AODV的进程模型manet_aodv可以直接拿来改。但有一个大坑这个AODV的实现默认依赖802.11 MAC层的接口直接换到LoRa MAC层之后很多函数调用会失效比如信道忙闲状态的获取、确认帧的收发逻辑。我当时花了不少时间在适配这个接口上最后的方案是保留AODV进程模型中的路由表和报文处理框架把对MAC层的调用全部抽象成几个自定义函数例如lora_send_packet()、lora_get_channel_status()再由LoRa MAC层进程实现。RREQ、RREP、RREP_Ack、RERR这些报文格式我可以直接使用OPNET自带包格式但需要在里面扩展字段增加累计代价MC、节点剩余能量、地理位置坐标、当前SF等级。包格式的修改在Packet Format编辑器里完成每一步增加一个字段注意保持字段顺序和协议解析函数一致否则会出现错位。另一个重要提醒OPNET的进程模型是事件驱动的状态迁移必须显式处理。如果你在AODV进程里加了“等待链路质量反馈”这类定时器逻辑一定要处理好op_intrpt_schedule_self()的回调事件类型否则会造成状态机卡死在等待事件上仿真运行到某一步后不再有任何消息流动。5. 仿真场景参数设计和对比实验方案5.1 核心仿真参数配置可直接参考我在一次完整实验中使用的参数如下拓扑生成时用固定随机种子确保可复现参数项取值仿真区域2000m × 2000m节点数量50个普通节点 1个sink节点节点部署随机均匀分布静态不动载波频率470MHz中国LoRa常用频段带宽BW125kHzSF范围7~12CR编码率4/5发射功率14dBm接收灵敏度-123dBm~-137dBm按SF变化传播模型Log-distance路径损耗指数3.5对数正态阴影标准差4dB数据包大小50字节业务产生间隔每个节点每180秒产生一个包泊松到达仿真时间每种场景运行3600秒仿真时间随机种子数10次独立重复需要特别说明的是仿真时间3600秒在OPNET里跑起来非常慢因为LoRa的低速率导致一个50字节帧在SF12下需要超过1.3秒的空中传输时间而且50个节点还有控制报文交互。我在做参数扫描时会把业务间隔缩短到60秒、把仿真时间缩短到600秒只对最终选定方案跑完整3600秒。5.2 对比方案设计我设计了三个方案做对照方案A原始AODV跳数选路HELLO周期3秒无速率自适应方案B改进型AODV复合代价度量洪泛抑制局部修复但物理层固定SF10方案C改进型AODV 速率自适应带迟滞机制。这样设计的好处是A和B对比可以看出路由协议改进本身对性能的影响B和C对比可以看出速率自适应在固定路由策略之上还能带来多少额外收益A和C则是“最终方案 vs 原始方案”的总体差异。5.3 统计指标定义我统计四类指标分组投递率PDRsink节点实际收到的应用层数据包除以所有源节点产生的应用层数据包端到端时延E2ED从源节点应用层产生数据到sink节点应用层收到数据的平均时延归一化路由开销所有AODV控制帧RREQ、RREP、RERR、HELLO的总字节数除以成功投递的数据字节数网络生存时间从仿真开始到第一个节点因能量耗尽停止转发的时间。能量模型方面为了简化仿真的复杂度我在OPNET能量模块中设置节点发射电流120mA接收电流12mA休眠电流2μA供电电压3.6V初始电量用10000mAh电池折算。节点在空闲时并不进入休眠而是进入低功耗侦听状态Mesh节点为了维持路由必须周期性醒来监听信道这个是网状网络和LoRaWAN终端最大的能耗差异点。6. 仿真结果里看到的规律和反直觉现象6.1 三组方案的性能对比十次独立重复实验取均值之后结果大致如下方案PDR端到端时延归一化路由开销首个节点死亡时间方案A72.8%约11.6s0.87约1100s方案B85.1%约7.9s0.31约2100s方案C93.4%约4.5s0.26约2800s方案A的归一化路由开销0.87意味着每投递1字节数据网络要额外消耗0.87字节的控制报文这个数字在LoRa这样的窄带网络里是毁灭性的。方案B把开销压到0.31主要靠的是洪泛抑制和HELLO周期的调整说明控制开销的下降直接对应了PDR的提升和时延的下降。方案C相对方案B的PDR提升了8个百分点以上这部分收益几乎全部来自速率自适应释放的信道时间——低SF的快速传输让数据帧更快地离开队列同时低SF引入的额外信道空闲也让中继节点有更多机会发送控制帧。首次节点死亡时间从1100秒提升到2800秒主要贡献其实是复合代价度量中的能量项它让路由尽量避免把流量全部压在少数几个节点上。6.2 一个反直觉的发现速率自适应并不总是提升PDR我印象最深的一个现象是在某个随机拓扑种子里方案C的PDR反而比方案B低了约4%。排查之后发现原因很有意思速率自适应让几个中继节点主动把SF调低从SF12切到SF7传输速率上去了但SF7的接收灵敏度只有-123dBm而这些中继节点之间的链路余量本来就只有5~6dB。一个短暂的衰落直接导致链路断裂触发了一轮路由重建。等路由恢复稳定之后自适应机制又试图再次降低SF陷入“降SF→断开→重建→再降SF”的震荡循环。这就是为什么我强烈建议在自适应算法里加入滞回逻辑。后来我把延迟切换的判断窗口加长到连续5个采样周期并且把切换之后至少保持60秒作为约束条件这种“过山车”现象才被压住。这个案例也说明仿真实验不能只看均值每一个随机种子跑出来的轨迹都值得看一眼——平均结果好的方案可能在某些局部场景下存在严重的稳定性问题。6.3 多跳路径长度与速率自适应的相互作用进一步分析路径长度分布我发现方案C的有效路径平均跳数比方案B少了约0.8跳。原因是复合代价度量会优先选择链路质量好、SF等级低的路径而链路质量好往往意味着跳距较短、跳数略多但是低SF带来的每跳传输时间大幅缩小最终端到端时延反而更低。换句话说多走一跳但每跳都“快”比少走一跳但每跳都“慢”更划算。这个规律在结果表里体现为方案B的路径平均跳数是3.4跳方案C是2.6跳但方案C端到端时延只有方案B的约57%。如果只看跳数指标可能会得出完全相反的结论这也是为什么路由协议仿真必须用端到端时延做最终验证不能依赖单一指标。7. OPNET仿真中的坑和排查经验7.1 AODV进程模型和802.11耦合问题最耗时间的适配直接使用OPNET自带的AODV进程模型时它底层会调用很多与MAC层绑定的函数例如获取无线信道的剩余带宽、查看网络分配向量NAV等。这些函数在802.11 MAC层里都有但LoRa MAC层完全不是那套机制。换上去之后最典型的表现是进程模型抛错提示某个属性不存在或者路由发现永远无法完成。解决思路是彻底剥离对802.11的依赖。我把AODV进程里所有“通过MAC层获取信道状态”的地方全部替换成“采用简化状态标志位”即由LoRa MAC层维护一个信道忙闲变量AODV进程直接读取。这个改动虽然看起来像是“作弊”但在网络层仿真阶段完全合理——我们验证的是路由行为不是MAC竞争细节。7.2 传播模型选错会导致灵敏度参数形同虚设OPNET默认的无线传输管道里路径损耗阶段通常用Free Space模型。在2000米距离、470MHz频率下自由空间损耗已经很大但地貌遮挡、多径衰耗完全没有体现。更关键的是Free Space模型下接收功率只随距离平滑变化这意味着节点只要超过某个距离就突然收不到能收到和收不到之间没有过渡带非常不真实。我改成Log-distance模型之后接收功率随距离衰减更接近真实传播环境配合对数正态阴影标准差4dB节点之间的链路质量出现随机起伏这正好给速率自适应算法提供了“用武之地”。如果一开始就用Free Space速率自适应几乎没有收益因为链路质量完全是静态的所有节点只要测一次距离就能选好SF算法再复杂也没有意义。7.3 仿真速度慢到怀疑人生的处理办法前面提过LoRa低速率导致每个数据包在空中的传输时间可能超过1秒50个节点跑3600秒仿真可能要跑几个小时甚至更久。我当时找到三个加速方法一是把业务产生的泊松到达率提高让单位仿真时间内有更多事件发生从而缩短仿真时间但保持统计有效性二是先跑小规模场景30个节点做参数扫描最后在50节点场景验证一轮即可三是把不需要的统计量收集全部关掉OPNET收集数据点本身也占用大量计算资源。还有一个很隐蔽的问题如果节点MAC层队列积压过多未发送的数据帧仿真事件数量会激增。我加了一个简单的队列上限比如500包超出部分直接丢弃这样既避免仿真卡死也模拟了真实节点内存有限的约束。7.4 能量模型和节点休眠状态必须手动控制OPNET的能量模块不会自动让节点进入休眠状态。如果你在节点进程里什么都不写节点会一直以满功耗运行能量消耗曲线会严重失真。LoRa节点工作在Mesh模式时确实不能像LoRaWAN终端那样长时间休眠但中继节点在无业务时的主要功耗来自“周期唤醒侦听”。我把节点状态机设计成三个状态活跃收发、空闲侦听、深度休眠并设定了周期性定时器控制状态迁移。能量模块的power_change()函数要在状态迁移事件里手动调用否则功耗参数不会更新。7.5 别忽略启动瞬态和随机种子问题仿真一开始的几百秒内所有节点的路由表都为空AODV要做频繁的路由发现这段时间的统计数据如果混入平均值会严重拉低PDR。所以我设置了600秒的预热期预热期内的数据不做统计预热期结束后才开启数据收集。另外每个随机种子对应完全不同的初始拓扑和信道衰落只跑一次就看结果非常危险。我在最终实验里每个方案跑10个种子计算均值和95%置信区间方案A和方案C的PDR差异在置信区间上确实不重叠才敢下结论说改进有效。回头复盘这个“速率自适应改进型AODV”的仿真项目我最想提醒后来者的一点是不要在一开始就把物理层、MAC层、路由层全都做到极致完美。先搭一个简化的LoRa物理层管道、一个极简CSMA MAC、一个改了度量和洪泛范围的AODV跑通一条业务流再逐步加复杂模块。我自己第一次就因为掺杂了MAC层CAD检测和自适应SF的联动问题导致整整一周都分不清PDR下降到底是路由层的锅还是物理层的锅。从简到繁这个顺序在OPNET这类重型仿真工具里特别重要。
返回列表