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 | 变量 | ||
| x | double | ||
| y | double | ||
| model | QStandardItemModel * | ||
| 方法 | |||
| addItem(TData data) | void | ||
| removeItem(TData data) | void | ||
| Edge | 变量 | ||
| to | int | ||
| weight | double | ||
| type | int | ||
| desister | double | ||
| 方法 | |||
| Set(int a) | void | ||
| Graph | 变量 | ||
| adjList | unordered_map<int, std::vector> | ||
| 方法 | |||
| addEdge(int from, int to, double weight) | void | ||
| findEdge(int from, int to) | Edge | ||
| Data | 变量 | ||
| final | bool | ||
| dist | double | ||
| path | int | ||
| 方法 | |||
| Set(bool f, double d, int p) | void | ||
| SensorNetwork | 变量 | ||
| sensors | QList<SensorNode*> | ||
| dataCollector | DataCollector * | ||
| sensorCount | int | ||
| broadcastRadius | double | ||
| T | int | ||
| graph | Graph | ||
| multiple | int | ||
| PathMap | unordered_map<int, Data> | ||
| 方法 | |||
| getShortestPath(int targetNode) | QPair<double, QList> | ||
| printPathMap() | void | ||
| initializeNetwork() | void | ||
| Dijkstra() | void | ||
| initEdgeType() | void | ||
| StartT() | void | ||
| GetNew() | void | ||
| GetNewD() | void | ||
| TData | 变量 | ||
| fromNode | int | ||
| data | int | ||
| type | QString | ||
| currentDateTime | QDateTime | ||
| 方法 | |||
| toString() | QString | ||
| SensorNode | 变量 | ||
| a | int | ||
| x | double | ||
| y | double | ||
| type | int | ||
| broadcastRadius | double | ||
| dataQueue | QQueue | ||
| model | QStandardItemModel * | ||
| 方法 | |||
| receiveData(const TData &data) | void | ||
| collectData() | void | ||
| SetType(int a) | void | ||
| Widget | 变量 | ||
| sensorNetwork | SensorNetwork* | ||
| timer | QTimer* | ||
| sensorCount | int | ||
| broadcastRadius | double | ||
| T | int | ||
| T2 | int | ||
| Judge | bool | ||
| timer1 | QTimer * | ||
| timer2 | QTimer * | ||
| lastClickedSensorIndex | int | ||
| nowNode | int | ||
| 方法 | |||
| 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
相关文章:
C++/Qt 模拟sensornetwork的工作
C/Qt 可视化模拟sensornetwork的工作 C/Qt 模拟sensornetwork的工作 C/Qt 可视化模拟sensornetwork的工作内容简介(一) 需求和规格说明(1)问题描述(2)设计目的(3)基本要求࿰…...
ffmpeg音频分析
对一个16k 单声道音频,生成频谱图 ./ffmpeg -i input.wav -lavfi "showspectrumpics800x400:modecombined:scalelin:gain1.5" spectrum.png...
【多线程】CAS机制
目录 一. CAS的概念 二. CAS的原理 三.标准库中的CAS 四. CAS的应用 (1)原子类的使用 (2) 自旋锁的实现 五. CAS的ABA问题 一. CAS的概念 CAS(Compare And Swap)机制是一种无锁的并发控制技术&#…...
音视频(四)android编译
前言 前面已经讲了在windows上应用了,这章主要讲述android上编译 1:环境 git 如果失败 直接跑到相应网站 手动下载 ubuntu22.* android ndk r21e download:https://developer.android.google.cn/ndk/downloads/index.html?hluk 为什么用这个࿰…...
Chapter07_图像压缩编码
文章目录 图像压缩编码图像压缩编码基础图像压缩的基本概念信息相关信息冗余信源编码及其分类 图像编码模型信源编码器模型信源解码器模型 数字图像的信息熵信源符号码字平均长度信息熵信息量 变长编码费诺码霍夫曼编码 位平面编码格雷码 图像压缩编码 数字图像的压缩是指在满…...
团体设计程序天梯赛L2-025 # 分而治之
文章目录 题目解读输入格式输出格式 思路Ac Code参考 题目解读 在战争中,我们希望首先攻下敌方的部分城市,使其剩余的城市变成孤立无援,然后再分头各个击破。为此参谋部提供了若干打击方案。本题就请你编写程序,判断每个方案的可…...
Linux网络套接字
Socket 编程 UDP 本章将函数介绍和代码编写实战一起使用。 IPv4 的 socket 网络编程,sockaddr_in 中的成员 struct in_addr.sin_addr 表示 32 位 的 IP 地址 但是我们通常用点分十进制的字符串表示 IP 地址,以下函数可以在字符串表示和in_addr 表示之间转换; 字符串转 in_addr…...
看爬山虎学本领 软爬机器人来创新 各种场景能适应
*本文只做阅读笔记分享* 一、灵感来源:向植物取经 大家好!今天来聊一款超酷的软爬机器人,它的灵感来自会攀爬的植物——爬山虎。 大家都知道,爬墙高手爬山虎能在各种复杂墙面轻松生长攀爬,可现有的攀爬机器人在复杂…...
1-Docker安装
1.准备环境 1.第一步:创建以自己的姓名全拼的用户名 [roothadoop ~]# useradd qiwenyong [roothadoop ~]# passwd qiwenyong Changing password for user qiwenyong. New password: BAD PASSWORD: The password is shorter than 7 characters Retype new passwor…...
WPS JS宏编程教程(从基础到进阶)-- 第三部分:JS宏编程语言开发基础
第三部分:JS宏编程语言开发基础 @[TOC](第三部分:JS宏编程语言开发基础)**第三部分:JS宏编程语言开发基础**1. 变量与数据类型**变量声明:三种方式****示例代码****数据类型判断****实战:动态处理单元格类型**2. 运算符全解析**算术运算符****易错点:字符串拼接 vs 数值相…...
BT-Basic函数之首字母T
BT-Basic函数之首字母T 文章目录 BT-Basic函数之首字母Ttabtesttest conttest monitortest on boardstest scanworkstest shortstesthead cleanuptesthead configurationtesthead istesthead power on/offtesthead statustestjet print level istestordertestplan generationth…...
经典算法 约数之和
原题目链接 问题描述 假设现在有两个自然数 A 和 B,设 S 为 A^B 的所有约数之和。 请你计算:S mod 9901 的值。 输入格式 在一行中输入两个用空格隔开的整数 A 和 B。 输出格式 输出一个整数,表示 S mod 9901 的值。 数据范围 0 ≤ A, …...
Flinksql--订单宽表
参考: https://chbxw.blog.csdn.net/article/details/115078261 (datastream 实现) 一、ODS 模拟订单表及订单明细表 CREATE TABLE orders (order_id STRING,user_id STRING,order_time TIMESTAMP(3),-- 定义事件时间及 Watermark(允许5秒乱序&#x…...
C# 窗体应用(.FET Framework ) 打开文件操作
一、 打开文件或文件夹加载数据 1. 定义一个列表用来接收路径 public List<string> paths new List<string>();2. 打开文件选择一个文件并将文件放入列表中 OpenFileDialog open new OpenFileDialog(); // 过滤 open.Filter "(*.jpg;*.jpge;*.bmp;*.png…...
极客天成NVFile:无缓存直击存储性能天花板,重新定义AI时代并行存储新范式
在AI算力需求呈指数级爆发的今天,存储系统正面临一场前所未有的范式革命。传统存储架构中复杂的缓存机制、冗余的数据路径、僵化的扩展能力,已成为制约千卡GPU集群算力释放的重要因素。极客天成NVFile并行文件存储系统以全栈并行化架构设计和无缓存直通数…...
Java实现N皇后问题的双路径探索:递归回溯与迭代回溯算法详解
N皇后问题要求在NN的棋盘上放置N个皇后,使得她们无法互相攻击。本文提供递归和循环迭代两种解法,并通过图示解释核心逻辑。 一、算法核心思想 使用回溯法逐行放置皇后,通过冲突检测保证每行、每列、对角线上只有一个皇后。发现无效路径时回退…...
【代码艺廊】pyside6桌面应用范例:homemade-toolset
在研发测试日常工作中,通常会遇到很多琐碎的事情,占用我们工作的时间和精力,从而导致我们不能把大部分的注意力放在主要的工作上面。为了解决这个问题,除了加人之外,我们通常会开发一些日常用的效率工具,比…...
LeetCode 3047 求交集区域内的最大正方形面积
探寻矩形交集中的最大正方形面积 在算法与数据结构的探索之路上,二维平面几何问题一直占据着独特的地位,它们不仅考验我们的空间思维能力,还要求我们能够巧妙地运用算法逻辑。今天,我们将深入剖析一道极具代表性的二维平面几何算…...
谷歌开源单个 GPU 可运行的Gemma 3 模型,27B 超越 671B 参数的 DeepSeek
自从 DeepSeek 把训练成本打下来之后,各个模型厂家现在不再堆参数进行模型的能力对比。而是转向了训练成本优化方面,且还要保证模型能力不减反增的效果。包括使用较少的模型参数,降低 GPU 使用数量,降低模型内存占用等等技术手段。…...
C++_类和对象(下)
【本节目标】 再谈构造函数Static成员友元内部类匿名对象拷贝对象时的一些编译器优化再次理解封装 1. 再谈构造函数 1.1 构造函数体赋值 在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。 class Date { public:Date(in…...
《Java实战:素数检测算法优化全解析——从暴力枚举到筛法进阶》
文章目录 摘要一、需求分析二、基础实现代码与问题原始代码(暴力枚举法)问题分析 三、优化版代码与解析优化1:平方根范围剪枝优化2:偶数快速跳过完整优化代码 四、性能对比五、高阶优化:埃拉托斯特尼筛法算法思想代码实…...
基于Python+Flask的服装零售商城APP方案,用到了DeepSeek AI、个性化推荐和AR虚拟试衣功能
首先创建项目结构: fashion_store/ ├── backend/ │ ├── app/ │ │ ├── __init__.py │ │ ├── models/ │ │ ├── routes/ │ │ ├── services/ │ │ └── utils/ │ ├── config.py │ ├── requirements.t…...
二,<FastApi>FastApi的两个核心组件
FastAPI的两个核心组件Pydantic和Starlette。 Starlette 负责Web部分(Asyncio),Starlette Starlette是一个轻量级的ASGI框架/工具包,非常适合在Python构建异步Web服务。 它已经准备好生产,并为您提供以下内容: 轻巧的低复杂性HTTP Web框架。W…...
Docker设置代理
目录 前言创建代理文件重载守护进程并重启Docker检查代理验证 前言 拉取flowable/flowable-ui失败,用DaoCloud源也没拉下来,不知道是不是没同步。索性想用代理拉镜像。在此记录一下。 创建代理文件 创建docker代理配置 sudo mkdir -p /etc/systemd/s…...
一键自动备份:数据安全的双重保障
随着数字化时代的到来,数据已成为企业和个人不可或缺的核心资产。在享受数据带来的便捷与高效的同时,数据丢失的风险也随之增加。因此,备份文件的重要性不言而喻。本文将深入探讨备份文件的重要性,并介绍两种实用的自动备份方法&a…...
HeidiSQL:多数据库管理工具
HeidiSQL 是一款广受欢迎的免费开源数据库管理工具,专为数据库管理员及开发者设计。无论您是刚接触数据库领域的新手,还是需要同时处理多种数据库系统的专业开发者,该工具都能凭借其直观的界面和强大的功能,助您轻松完成数据管理任…...
医药档案区块链系统
1. 医生用户模块 目标用户:医护人员 核心功能: 检索档案:通过关键词或筛选条件快速定位患者健康档案。请求授权:向个人用户发起档案访问权限申请,需经对方确认。查看档案…...
【Python学习】列表/元组等容器的常用内置函数详解
文章目录 map使用示例: filter示例:注意事项: sortedsorted() 与 list.sort() 的区别: any示例: all示例: any 与 all 的对比zip示例:常见用途: enumerate示例:常见用途&…...
蓝桥云客--浓缩咖啡液
4.浓缩咖啡液【算法赛】 - 蓝桥云课 问题描述 蓝桥杯备赛选手小蓝最近刷题刷到犯困,决定靠咖啡续命。他手上有 N 种浓缩咖啡液,浓度分别是 A1%, A2%, …, AN%,每种存货都是无限的。为了提神又不炸脑,小蓝需要按比例混合这…...
SQLark(百灵连接):一款面向信创应用开发者的数据库开发和管理工具
SQLark(百灵连接)是一款面向信创应用开发者的数据库开发和管理工具,用于快速查询、创建和管理不同类型的数据库系统。 目前可以支持达梦数据库、Oracle 以及 MySQL。 SQL 智能编辑器 基于语法语义解析实现代码补全能力,为你提供…...
