当前位置: 首页 > news >正文

C++/Qt 模拟sensornetwork的工作

C++/Qt 可视化模拟sensornetwork的工作

C++/Qt 模拟sensornetwork的工作

  • C++/Qt 可视化模拟sensornetwork的工作
    • 内容简介
    • (一) 需求和规格说明
      • (1)问题描述
      • (2)设计目的
      • (3)基本要求
      • (4)实现提示
    • (二) 设计
      • (1)框架设计
        • DataCollector(数据收集类):
        • Graph(图类):
        • SensorNode(传感器节点):
        • SensorNetwork(网络管理):
        • Widget(图形界面):
      • (2)界面设计
      • (3)类与属性说明
      • (4)重点函数说明:
        • 4.1 最优路径规划—迪杰斯特拉算法实现
        • 4.2 最短路径查找
    • (三) 用户手册
      • 初始化设置
      • 参数配置
      • 查找节点
      • 节点信息
      • 信息总览
      • 阻塞比例调整
      • 节点定位
    • (四) 调试及测试
    • (五) 运行实例:
    • (六)进一步改进

在这里插入图片描述

内容简介

Sensornetwork是一种新型的网络,其基本结构如下图所示:该网络由两部分组成,Sensornode集和DataCollector。Sensornode(可简称为Sensor)能够完成感知环境数据并将其发往DataCollector的功能。DataCollector完成Sensor采集数据的收集,它就是一台带有无线接收功能的计算机。

本课程设计以Qt为框架实现了对sensornetwork的工作模拟,包括传感器节点的随机生成,传感器的数据模拟产生,节点网络的构建与图形化展示,节点最短路径的查找等,采用迪杰斯特拉算法作为路由算法,基本完整模拟了sensornetwork的工作流程,拥有良好的交互界面,包括查找定位,数据修改,规则制定等。

(一) 需求和规格说明

(1)问题描述

Sensornetwork是一种新型的网络,其基本结构如下图所示:该网络由两部分组成,Sensornode集和DataCollector。Sensornode(可简称为Sensor)能够完成感知环境数据并将其发往DataCollector的功能。DataCollector完成Sensor采集数据的收集,它就是一台带有无线接收功能的计算机。
在这里插入图片描述
Sensornetwork可应用到很多实际领域中,如在战争中将Sensor散播在防线的前沿,可以收集敌人的一些情报(如大规模的部队转移等)。Sensor散播的地方称为Interestedarea,Sensor在这个区域内采集各自所在位置的数据,然后将采集到的数据传送到DataCollector。各个Sensor之间通过无线广播通讯,由于Sensor广播能力的限制,它只能和位于自身的一定广播半径内的Sensor进行通讯,所以有些Sensor就需通过其它Sensor,经过多次路由后才能到达DataCollector(如上图)。如何路由由Sensor内保存的简单路由表来决定。DataCollector的位置就在InterstedArea的边缘,且固定不动。

(2)设计目的

应用数据结构知识模拟一个新型网络系统。

(3)基本要求

①应用数据结构在单机上模拟Sensornetwork的工作。
②用VC++(C也可以)实现模拟系统,N个Sensor和1个DataCollector,其具体位置随机确定,InterestArea就是屏幕。N可配置,缺省为100。
③Sensor进行周期性采集,其采集周期可配置。
④Sensor的广播半径固定,也是可配置的参数。
⑤路由算法自行选择或设计。

(4)实现提示

Sensor集可组织成数组,它采集及收到的数据包用队列存储。具体细节也可参阅有关资料。

(二) 设计

(1)框架设计

由上述需求可知,我们需要设计的是一个模拟传感器的网络系统,这个网路系统的主题由图构成,因此应该使用图形界面将图显示,直观的描绘出传感器节点(SensorNode),边(Edge),数据收集器(DataCollector)之间的相互关系,可以用图形化的界面表达出算法的运行。故选用Qt这种跨平台应用程序开发框架作为主体框架,在Qt框架的基础上进行进一步的设计。

DataCollector(数据收集类):
  • 作为传感器网络的核心节点,负责收集和处理传感器节点的数据。
  • 实现与传感器节点之间的通信和数据交换。
  • 具备管理传感器节点的功能,如初始化、数据请求等。
Graph(图类):
  • 负责存储传感器网络的拓扑结构,包括节点和边。
  • 支持基本的图操作,如添加节点、添加边、删除节点、删除边等。
  • 实现图算法,如Dijkstra算法,用于计算从DataCollector到各个传感器节点的最短路径。
SensorNode(传感器节点):
  • 表示传感器网络中的单个传感器节点。
  • 具备基本属性,如位置(x, y坐标)、ID、数据等。
  • 支持与DataCollector和其他传感器节点的通信。
SensorNetwork(网络管理):
  • 负责管理整个传感器网络,包括传感器节点和数据收集器。
  • 维护传感器网络的整体状态,并提供对外接口用于操作网络。
  • 包含数据收集周期、广播半径等可配置参数。
Widget(图形界面):
  • 使用Qt进行界面设计,负责绘制传感器网络的图形表示。
  • 显示传感器节点、数据收集器和边的图形元素。
  • 提供用户交互功能,如添加节点、删除节点、执行算法并显示结果等。

(2)界面设计

在这里插入图片描述

(3)类与属性说明

类名属性类型/返回值名称
DataCollector变量
xdouble
ydouble
modelQStandardItemModel *
方法
addItem(TData data)void
removeItem(TData data)void
Edge变量
toint
weightdouble
typeint
desisterdouble
方法
Set(int a)void
Graph变量
adjListunordered_map<int, std::vector>
方法
addEdge(int from, int to, double weight)void
findEdge(int from, int to)Edge
Data变量
finalbool
distdouble
pathint
方法
Set(bool f, double d, int p)void
SensorNetwork变量
sensorsQList<SensorNode*>
dataCollectorDataCollector *
sensorCountint
broadcastRadiusdouble
Tint
graphGraph
multipleint
PathMapunordered_map<int, Data>
方法
getShortestPath(int targetNode)QPair<double, QList>
printPathMap()void
initializeNetwork()void
Dijkstra()void
initEdgeType()void
StartT()void
GetNew()void
GetNewD()void
TData变量
fromNodeint
dataint
typeQString
currentDateTimeQDateTime
方法
toString()QString
SensorNode变量
aint
xdouble
ydouble
typeint
broadcastRadiusdouble
dataQueueQQueue
modelQStandardItemModel *
方法
receiveData(const TData &data)void
collectData()void
SetType(int a)void
Widget变量
sensorNetworkSensorNetwork*
timerQTimer*
sensorCountint
broadcastRadiusdouble
Tint
T2int
Judgebool
timer1QTimer *
timer2QTimer *
lastClickedSensorIndexint
nowNodeint
方法
paintEvent(QPaintEvent *event)void
collect()void
Send()void
mousePressEvent(QMouseEvent *event)void
on_pushButton_clicked()void
on_pushButton_2_clicked()void

(4)重点函数说明:

4.1 最优路径规划—迪杰斯特拉算法实现
void SensorNetwork::Dijkstra() {// 初始化路径表for (int i = 0; i <= sensorCount; i++) {PathMap[i].Set(false, std::numeric_limits<double>::infinity(), -1); // 将距离设为无穷大}// 放入第一个节点PathMap[sensorCount].Set(true, 0, -1);// 初始化第一个节点的邻接节点的距离for (const Edge& edge : graph.adjList.at(sensorCount)) {PathMap[edge.to].Set(false, edge.weight, sensorCount);}for (int i = 0; i < sensorCount; i++) {// 找到未处理节点中距离最短的节点int minNode = -1;double minDist = std::numeric_limits<double>::infinity();for (const auto& entry : PathMap) {if (!entry.second.final && entry.second.dist < minDist) {minDist = entry.second.dist;minNode = entry.first;}}//if (minNode == -1) {//    break; // 所有节点已处理完毕//}PathMap[minNode].final = true; // 将该节点标记为已处理// 更新该节点邻接节点的距离for (const Edge& edge : graph.adjList[minNode]) {if (!PathMap[edge.to].final && PathMap[minNode].dist + edge.weight < PathMap[edge.to].dist) {PathMap[edge.to].Set(false, PathMap[minNode].dist + edge.weight, minNode);}}}
}

初始化路径表:

  • 为每个节点创建一个记录,包含三个部分:是否已处理 (final)、距离 (dist)、和前驱节点 (prev)。
  • 使用一个特殊的值(无穷大)初始化所有节点的距离,表示这些节点当前还不可达。
  • 对数据收集器节点(假设为 sensorCount)初始化距离为0,前驱节点为-1,标记为已处理。
  • 初始化第一个节点的邻接节点:
  • 遍历数据收集器节点的邻接节点,并初始化这些节点的距离。
  • 将这些邻接节点的前驱节点设置为数据收集器节点。
  • 主循环(处理所有节点):
  • 找到未处理节点中距离最短的节点 minNode。这是Dijkstra算法的核心部分,确保每次选择的节点是当前已知最短路径的节点。
  • 将该节点标记为已处理。
  • 遍历该节点的所有邻接节点,更新这些邻接节点的距离(如果通过当前节点找到的路径更短)。
  • 更新操作:如果通过 minNode 达到某个邻接节点的距离小于之前记录的距离,则更新该邻接节点的距离,并将其前驱节点更新为 minNode。
4.2 最短路径查找
QPair<double, QList<int>> SensorNetwork::getShortestPath(int targetNode) {QList<int> path;double totalDistance = PathMap[targetNode].dist;// 检查目标节点是否可达if (totalDistance == std::numeric_limits<double>::infinity()) {return qMakePair(totalDistance, path); // 返回空路径和无穷距离}// 使用堆栈逆序构建路径QStack<int> stack;int currentNode = targetNode;while (currentNode != -1) {stack.push(currentNode);currentNode = PathMap[currentNode].path;}// 将堆栈中的路径顺序放入 QList 中while (!stack.isEmpty()) {path.append(stack.pop());}return qMakePair(totalDistance, path);
}

初始化:

  • 创建一个 QList 来存储路径节点。
  • 获取目标节点的总距离 totalDistance。
  • 检查目标节点可达性:
  • 如果目标节点的总距离为无穷大,表示目标节点不可达。此时,返回总距离为无穷大和空路径。
  • 逆序构建路径:
  • 使用 QStack 堆栈存储路径节点,方便之后顺序输出路径。
  • 从目标节点开始,逐步追踪其前驱节点 path,将节点压入堆栈,直到到达数据收集器节点(即 path 为 -1)。
  • 构建有序路径:
  • 从堆栈中弹出所有节点,并按顺序放入 QList 中,形成正确顺序的路径。
  • 返回结果:
  • 返回一个 QPair<double, QList>,包含总距离和节点路径。

(三) 用户手册

开始运行时会按照设定的默认值初始化传感器节点数字为100,广播半径为150,采集周期为5,发送间隔为2。可以在自己设置这些参数后点击配置按钮,及可按照输入的配置信息配置图像,在查找前的输入框中输入查找内容,可以查找到节点并在图形展示区将节点该节点变为红色并显示该节点到收集站的路径,将路径展示为红色,在节点信息栏显示节点的信息并实时更新,显示出当前节点上储存的信息与节点距离与信息多少。在最左边为信息总览,包含所有节点传输到收集站的信息,并可以修改。最左边的滑轮可以设置阻塞比例,调整距离与阻塞对边权重的影响。可以直接点击图中的节点,及定位到此节点。

初始化设置

启动程序时,系统会根据以下默认值进行初始化:

  • 传感器节点数量:100
  • 广播半径:150
  • 采集周期:5
  • 发送间隔:2

参数配置

用户可以在设置这些参数后点击“配置”按钮,系统将根据输入的配置信息重新配置图像。

查找节点

在查找前的输入框中输入节点信息,可以查找到对应节点,并在图形展示区将该节点标记为红色。系统还会显示该节点到数据收集站的路径,路径以红色展示。

节点信息

在节点信息栏中显示节点的详细信息并实时更新,包括:

  • 当前节点上存储的信息
  • 节点与数据收集站的距离
  • 信息的数量

信息总览

界面最左侧显示信息总览,包含所有节点传输到数据收集站的信息。用户可以在此修改信息。

阻塞比例调整

界面左侧的滑轮可以设置阻塞比例,调整距离与阻塞对边权重的影响。

节点定位

用户可以直接点击图中的节点,系统将自动定位到该节点。

(四) 调试及测试

在这里插入图片描述

(五) 运行实例:

初始化后,将节点数改为150,采集周期改为10,发送间隔改为1

手动配置:

在这里插入图片描述
输入节点106,查找节点位置与最短路径。
查找节点:
在这里插入图片描述
修改总数据中的条数据信息。
数据修改:
在这里插入图片描述

点击图中节点,自动定位节点与路径。
点击选择节点:
在这里插入图片描述

(六)进一步改进

现在的实现有一个问题,当随机产生的节点有节点无法加入网络时,在遍历寻找时会报错导致程序奔溃,在后期优化要将不能加入网络的节点异常处理。
现在的界面有些单调,确实点美感,在后期需要对显示中的图点与边进行优化。
当前缺少直接在总数据中查找数据的功能,对收集到的数据没有处理,在后期可以加入对收集到的数据进行数据分析的功能。
目前实现只是用了迪杰斯特拉算法一种,比较单调,可以尝试是用多种算法实现这个功能。

相关源码:https://github.com/HeJiguang/StudyNotions/tree/main/Another/%E6%A8%A1%E6%8B%9Fsensornetwork%E7%9A%84%E5%B7%A5%E4%BD%9C


http://www.mrgr.cn/news/97231.html

相关文章:

  • (八)PMSM驱动控制学习---无感控制之滑膜观测器
  • Redis数据结构之Hash
  • 简单多状态dp问题 + 总结(一)
  • #SVA语法滴水穿石# (012)关于 first_match、throughout、within 的用法
  • Redis数据结构之List
  • 搭建K8S-1.23
  • Python菜鸟教程(小程序)
  • (二)使用Android Studio开发基于Java+xml的安卓app之环境搭建
  • Redis数据结构之String
  • vue2项目中,多个固定的请求域名 和 通过url动态获取到的ip域名 封装 axios
  • 量化交易----从0到1
  • 前端布局难题:父元素padding导致子元素无法全屏?3种解决方案
  • 增益调度控制 —— 理论、案例与交互式 GUI 实现
  • 【数学建模】(时间序列模型)ARIMA时间序列模型
  • #SVA语法滴水穿石# (013)关于内建系统函数
  • 实践:用Ollama+DeepSeek-R1搭建AI知识库
  • 博途 TIA Portal之1200做主站与200SMART的S7通讯
  • Axure RP9.0教程: 查询条件隐藏与显示(综合了动态面板状态切换及展开收缩效果实现)
  • C++ KMP算法
  • #SVA语法滴水穿石# (013)关于 disable iff、matched 、expect 的用法