Qt5 互动地图,实现无人机地面站效果

一、概述

本文主要通过Qt5+opmapcontrol实现一个简单的无人机地面站效果。opmapcontrol是一个比较古老的QT开源地面站库,可选择谷歌地图,必应地图, 雅虎地图,GIS等。可直接使用源码,也可以编译生成库进行调用。
实现效果:
在这里插入图片描述

二、环境

Qt:5.15.2
编译器: Qt 5.15.2 MinGW 64-bit
系统:windows 10

三. 功能特点

(1) 支持缓存地图
(2)支持选择各厂商地图,以及切换街道地图
(3)支持地图互动:拖动、放大缩小
(4)支持添加航点,以及航点的编辑、删除、保存、加载、航点信息显示
(5)支持设置home,以及安全区域
(6)支持显示运动轨迹

四.opmapcontrol

从github上下载下来的源码包调用的时候,不同版本的Qt会有些小bug,可以直接搜opmapcontrol。
CSDN免积分下载链接(包含编译好的库、和简单的调用demo):
https://download.csdn.net/download/ever__ever/89290882?spm=1001.2014.3001.5503
(以下为opmapcontrol中mapwidget子项目各个类的功能讲解,只想知道如何使用的话可以跳过本节,直接前往第五节)
这个库中我们主要看mapwidget子项目,里面提供了对地图、无人机、航点、轨迹、home等相关操作的接口。

  1. OPMapWidget类

这个类主要继承QGraphicsView,提供一个地图交互场景视图。
(1)void SetShowDiagnostics(bool const & value)
设置是否显示诊断信息。当传入的值为true时,会创建定时器用于刷新诊断信息,同时创建GPS对象(如果不存在),并设置透明度。当传入的值为false时,会清除诊断信息、定时器、GPS对象等。
(2)void SetUavPic(QString UAVPic)
用于设置无人机的图片。如果无人机对象存在,会调用其SetUavPic函数设置图片。
(3)UAVItem* AddUAV(int id)
用于添加一个新的无人机对象,并将其添加到地图中。它返回指向新添加的无人机对象的指针。
(4)void AddUAV(int id, UAVItem* uav)
用于添加一个已存在的无人机对象,并将其添加到地图中。
(5)void DeleteUAV(int id)
用于删除指定ID的无人机对象。
(6)UAVItem* GetUAV(int id)
用于获取指定ID的无人机对象。
(7)const QList<UAVItem*> GetUAVS()
用于获取所有无人机对象的列表。
(8)WayPointLine *WPLineCreate(WayPointItem *from, WayPointItem *to, QColor color, bool dashed, int width)
用于创建两个航点之间的连线。
(9)WayPointLine *WPLineCreate(HomeItem *from, WayPointItem *to, QColor color, bool dashed, int width)
用于创建Home点到航点之间的连线。

  1. Configuration类
    它主要用于集中管理地图控件的大部分配置选项。

这个类包含了一些成员变量,如EmptytileBrushEmptyTileTextEmptyTileBorders等,用于配置地图空白瓦片的绘制、文本、边框等样式。同时,它还包含了一些成员函数,用于设置和获取地图的访问模式、语言、内存缓存使用情况、缓存文件的位置等。
总的来说,Configuration类的作用是提供一个集中管理地图控件配置选项的地方,使得在代码中可以方便地对这些配置进行设置和获取。

  1. GPSItem类

继承自QObjectQGraphicsItem的类,用于在地图上表示一个无人机(UAV)。提供了一系列函数用于管理无人机的位置、轨迹以及到达状态等属性,以及相应的信号与槽机制用于与其他对象进行交互。
这个类的作用主要有以下几点:

  • **表示无人机:**GPSItem类用于在地图上绘制表示无人机的图形元素,可以根据给定的参数设置无人机的位置、高度和朝向。
  • **设置无人机轨迹:**可以根据不同的轨迹类型设置无人机的轨迹显示方式,包括按时间间隔绘制轨迹点或按距离间隔绘制轨迹点等。
  • **管理轨迹显示:**可以设置是否显示无人机的轨迹以及轨迹线,并提供相应的函数来控制轨迹的显示和清除。
  • **自动设置到达状态:**可以设置无人机自动根据距离到达航点,并根据设定的距离自动设置航点到达状态。
  1. HomeItem类

继承自QObjectQGraphicsItem的类,用于在地图上表示一个home点的位置。提供了一系列函数用于管理home的位置、安全区域以及相应的交互功能。
这个类的作用主要有以下几点:

  • **表示home的位置:**HomeItem类用于在地图上绘制表示home的图形元素,可以设置home的位置坐标和海拔高度。
  • **显示安全区域:**可以设置是否显示home的安全区域,并提供相应的函数进行控制。
  • **提供信号与槽机制:**通过信号与槽机制,可以实现当home的位置发生变化时通知其他对象,以及当home位置被双击时触发相应的事件。
  • **提供鼠标事件处理:**可以处理鼠标的移动、按下、释放和双击等事件,以便实现交互功能。
  1. MapGraphicItem类
    MapGraphicItem
    类是一个用于地图显示和交互的主要图形项。它是一个继承自 QObjectQGraphicsItem 的类,是地图小部件中核心的图形项,负责管理地图的显示和交互,以及地图相关的逻辑处理。

这个类的作用主要有以下几点:

  • **显示地图:**负责在地图小部件上绘制地图,并处理地图的显示逻辑。
  • **地图交互:**处理鼠标事件(移动、点击、滚动等)和键盘事件,以实现地图的交互功能,如拖拽、缩放、选择区域等。
  • **地图坐标转换:**提供方法将经纬度坐标转换为本地坐标,以及将本地坐标转换为经纬度坐标。
  • **地图操作:**包括设置地图的缩放级别、旋转角度、地图类型等。
  • **地图重绘:**在需要更新地图显示时,负责重新绘制地图。
  • **地图逻辑:**处理地图的逻辑操作,如获取地图类型、设置当前位置、设置鼠标滚轮缩放类型等。
  1. TrailItem类

用于在地图上显示路径轨迹的图形项,它可以根据传入的经纬度坐标和颜色刷,在地图上绘制路径。

  1. UAVItem类

表示无人机(UAV)的图形项,用于在地图上显示无人机的位置、航向、速度等信息。可以根据无人机的位置和状态信息进行绘制,同时提供了一系列方法和信号,用于处理与无人机相关的逻辑。
这个类的作用主要有以下几点:

  • **初始化无人机项:**通过构造函数初始化无人机项,传入地图图形项、父部件指针和无人机图片路径等参数。
  • **设置无人机信息:**提供一系列方法,用于设置无人机的位置、NED(北东地)坐标、地面速度、空速、航向角速度等信息。
  • **绘制无人机:**实现 paint 方法,用于在地图上绘制无人机。绘制时可以根据当前无人机的位置、航向等信息进行绘制。
  • **边界矩形:**实现 boundingRect 方法,返回无人机项的边界矩形,用于在场景中定位无人机项的位置。
  • **类型标识:**定义了 type 方法,返回无人机项的类型标识,方便识别无人机项。
  • **信号与槽:**提供多个槽函数,用于处理无人机位置更新、透明度设置等操作。还定义了一些信号,用于与其他部件进行通信,如当无人机达到航点时发出信号等。
  1. WayPointItem类

表示航点的图形项,用于在地图上显示航点的位置、描述和相关信息。可以根据航点的位置和状态信息进行绘制,同时提供了一系列方法和信号,用于处理与航点相关的逻辑。
这个类的作用主要有以下几点:

  • **初始化航点项:**提供多个构造函数,用于初始化航点项,可以传入航点的经纬度坐标、海拔高度、描述信息等参数。
  • **设置航点信息:**提供一系列方法,用于设置和获取航点的描述、是否到达、航点编号、经纬度坐标、海拔高度等信息。
  • **绘制航点:**实现 paint 方法,用于在地图上绘制航点的图标,并根据航点是否到达以及是否显示航点编号进行绘制。
  • **边界矩形:**实现 boundingRect 方法,返回航点项的边界矩形,用于在场景中定位航点项的位置。
  • **类型标识:**定义了 type 方法,返回航点项的类型标识,方便识别航点项。

五.主程序结构

├── UAVMapDemo
├── UAVMapDemo.pro
├── main.cpp (程序入口:加载样式表)
├── mainwindow.h (主界面,没什么操作)
├── mainwindow.cpp
├── mainwindow.ui
├── 3rdparty (包括opmapcontrol的头文件和库文件)
│ ├── opmapcontrol
│ │ └── include
│ │ └── MinGW
├── MapControl
│ ├── MapControl.pri
│ ├── MapWidget.h (继承OPMapWidget,调用opmapwidget相关接口实现地图和无人机操作)
│ ├── MapWidget.cpp
│ ├── UAS_types.h (存放一些数据类型和转化)
│ ├── UAS_types.cpp
├── Robot
│ ├── Robot.pri
│ ├── uavmanagerwidget.h (无人机地面站界面,实现模型飞行、起飞、降落等接口)
│ ├── uavmanagerwidget.cpp
│ ├── uavmanagerwidget.ui
│ ├── mapsetmiddleform.h (一个小界面,不用关心)
│ ├── mapsetmiddleform.h
│ ├── mapsetmiddleform.h
├── res
│ ├── image (图片资源)
│ ├── styleSheet (样式资源)
│ │ └── default.qss

六.程序源码主要部分说明

  1. pro文件

添加opmapcontrol相关头文件和库文件

CONFIG(debug, debug|release){
    win32-g++ {
    }
    else:msvc {
        }
}
else {
    win32-g++ {
        INCLUDEPATH += $$PWD/3rdparty/opmapcontrol/include/mapwidget

            LIBS += -L$$PWD/3rdparty/opmapcontrol/MinGW -lopmapwidget
            }
    else:msvc {
        }
}
  1. UAVManagerWidget 无人机地面站界面

initWidget() : 新建一个配置文件,存放经纬度、home点经纬度、缩放比例、添加一个无人机类,编号为0,不显示无人信息,设置无人机的位置为home位置。
handleUISignals() : 处理界面上的一些ui信号,加了一个定时器,用于模拟飞行。
flySimulation() : 模拟飞行,随机经纬度。

void UAVManagerWidget::initWidget()
{
    m_mapSetForm = new MapSetMiddleForm();
    m_mapSetForm->setRobotBtnName(u8"无人机");

    m_conf = new QSettings("./MapControl/data/UAV.ini", QSettings::IniFormat);

    int zoom;
    m_homeLat = m_conf->value("mapWidget_home_lat", 34.257287).toDouble();
    m_homeLng = m_conf->value("mapWidget_home_lng", 108.888931).toDouble();
    m_uavLat = m_homeLat;
    m_uavLng = m_homeLng;
    zoom = m_conf->value("lastZoom", 13).toInt();

    internals::PointLatLng p(m_homeLat, m_homeLng);
    ui->widget_map->SetCurrentPosition(p);
    ui->widget_map->SetZoom(zoom);
    ui->widget_map->setConf(m_conf);

    uav = ui->widget_map->AddUAV(0);
    uav->SetNumber(0);
    uav->SetShowUAVInfo(false);
    uav->SetMapFollowType(mapcontrol::UAVMapFollowType::Types::CenterMap);
    uav->SetUAVPos(p, 10);
}

void UAVManagerWidget::handleUISignals()
{
    // 连接
    connect(ui->btn_connect, &QPushButton::clicked, this, &UAVManagerWidget::connectUav);
    // 起飞
    connect(ui->btn_takeoff, &QPushButton::clicked, this, &UAVManagerWidget::uavTakeoff);
    // 降落
    connect(ui->btn_land, &QPushButton::clicked, this, &UAVManagerWidget::uavLand);
    // 返回
    connect(ui->btn_back, &QPushButton::clicked, this, &UAVManagerWidget::uavGoHome);
    // plan
    connect(ui->btn_plan, &QPushButton::clicked, this, &UAVManagerWidget::flyByWaypoint);
    // 地图中心点
    connect(ui->btn_home, &QPushButton::clicked, this, [=]() {
        m_mapSetForm->setCurrentPos(ui->widget_map->CurrentPosition().Lng(),
            ui->widget_map->CurrentPosition().Lat());

        QPoint buttonPos = ui->btn_home->mapToGlobal(ui->btn_home->rect().center());
        int dialogX = buttonPos.x() + ui->btn_home->width() - 15;
        int dialogY = buttonPos.y() - m_mapSetForm->height() / 2;
        m_mapSetForm->showWidget(QPoint(dialogX, dialogY));
    });
    // 置于home
    connect(m_mapSetForm, &MapSetMiddleForm::signal_setHome, this, [=]() {
        ui->widget_map->SetCurrentPosition(internals::PointLatLng(m_homeLat, m_homeLng));
    });
    // 置于无人机
    connect(m_mapSetForm, &MapSetMiddleForm::signal_setRobot, this, [=]() {
        if (uav) {
            ui->widget_map->SetCurrentPosition(internals::PointLatLng(m_uavLat, m_uavLng));
        }
    });
    // 置于自定义中心
    connect(m_mapSetForm, &MapSetMiddleForm::signal_setCustom, this, [=](double lng, double lat) {
        if (uav) {
            ui->widget_map->SetCurrentPosition(internals::PointLatLng(lat, lng));
        }
    });
    // 无人机超出home设定安全范围
    connect(uav,
        SIGNAL(UAVLeftSafetyBouble(internals::PointLatLng)),
        this,
        SLOT(uavWarnning(internals::PointLatLng)));

    // 用于模拟飞行的定时器,随机生成无人机位置
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(flySimulation()));
    // 模拟飞行按钮
    connect(ui->btn_simFly, &QPushButton::clicked, this, [=]() {
        if (ui->btn_simFly->isChecked()) {
            timer->start(100);
        } else {
            timer->stop();
        }
    });
}

void UAVManagerWidget::flySimulation()
{
    m_uavLat += 0.000001;
    m_uavLng += QRandomGenerator::global()->bounded(0.000001) - 0.000005;
    internals::PointLatLng ll(m_uavLat, m_uavLng);
    uav->SetUAVPos(ll, 10);
}
  1. MapWidget 地图窗口,继承OPMapwidget。

MapWidget() : 构造函数,选择必应地图,其他的需要科学上网。

MapWidget::MapWidget(QWidget* parent)
    : mapcontrol::OPMapWidget(parent)
{
    m_conf = NULL;

    configuration->SetAccessMode(core::AccessMode::CacheOnly);
    configuration->SetTileMemorySize(200);
    configuration->SetCacheLocation("./data/");

    SetZoom(4);
    SetMinZoom(4);
    // 地图选择必应
    SetMapType(MapType::BingHybrid);
    // 显示罗盘
    SetShowCompass(true);
    // set initial values
    m_bSelectArea = 0;
    m_pSelectArea1.SetLat(-9999);
    m_pSelectArea1.SetLng(-9999);
    m_pSelectArea2.SetLat(-9999);
    m_pSelectArea2.SetLng(-9999);

    m_homeShow = 1;
    m_homeAlt = 440;
    m_homePos.SetLat(-9999);
    m_homePos.SetLng(-9999);
    m_homeSafearea = 100;

    m_flightHeight = 20;

    // setup menus
    setupMenu();
}

*setConf(QSettings conf) : **配置文件设置,地图加载接口(服务器、缓存)、地图类型、缓存位置、home点和安全区域设置。


void MapWidget::setConf(QSettings* conf)
{
    m_conf = conf;

    if (m_conf == NULL)
        return;

    // map type & access mode
    {
        MapType::Types mapType;
        core::AccessMode::Types accessMode;
        QString cacheLocation;

        // load settings
        accessMode = (core::AccessMode::Types)m_conf->value("mapWidget_accessMode",
                                                        (int)(core::AccessMode::CacheOnly))
                         .toInt();
        mapType = (MapType::Types)m_conf->value("mapWidget_mapType",
                                            (int)(MapType::GoogleSatellite))
                      .toInt();
        cacheLocation = m_conf->value("mapWidget_cacheLocation", "./MapControl/data/").toString();

        // set configurations
        configuration->SetAccessMode(accessMode);
        configuration->SetCacheLocation(cacheLocation);
        SetMapType(mapType);

        // set accessMode actions
        if (accessMode == core::AccessMode::ServerAndCache) {
            m_actMapAccess_ServerAndCache->setChecked(true);
            m_actMapAccess_Cache->setChecked(false);
        } else if (accessMode == core::AccessMode::CacheOnly) {
            m_actMapAccess_ServerAndCache->setChecked(false);
            m_actMapAccess_Cache->setChecked(true);
        }
    }

    // home & safe area
    {
        m_homeShow = m_conf->value("mapWidget_home_show", m_homeShow).toInt();
        m_homePos.SetLat(m_conf->value("mapWidget_home_lat", m_homePos.Lat()).toDouble());
        m_homePos.SetLng(m_conf->value("mapWidget_home_lng", m_homePos.Lng()).toDouble());
        m_homeAlt = m_conf->value("mapWidget_home_alt", m_homeAlt).toDouble();
        m_homeSafearea = m_conf->value("mapWidget_home_safeArea", m_homeSafearea).toDouble();

        m_flightHeight = m_conf->value("mapWidget_flightHeight", m_flightHeight).toDouble();

        if (m_homeShow) {
            this->SetShowHome(true);
            this->Home->SetCoord(m_homePos);
            this->Home->SetAltitude((int)(m_homeAlt));
            this->Home->SetSafeArea((int)(m_homeSafearea));

            m_actHome_ShowHide->setChecked(true);
        } else {
            m_actHome_ShowHide->setChecked(false);
        }
    }
}

**setupMenu() **: 右键菜单,提供对地图、航点、home、安全区域等各个功能的接口。

int MapWidget::setupMenu(void)
{
    // setup actions
    m_actMapType = new QAction(tr(u8"地图类型"), this);
    connect(m_actMapType, SIGNAL(triggered()), this, SLOT(actMapType_SelectMap()));

    m_actMapAccess_ServerAndCache = new QAction(tr(u8"服务器和缓存"), this);
    m_actMapAccess_ServerAndCache->setCheckable(true);
    m_actMapAccess_ServerAndCache->setChecked(false);
    connect(m_actMapAccess_ServerAndCache, SIGNAL(triggered()),
        this, SLOT(actMapAccess_ServerAndCache()));

    m_actMapAccess_Cache = new QAction(tr(u8"缓存"), this);
    m_actMapAccess_Cache->setCheckable(true);
    m_actMapAccess_Cache->setChecked(true);
    connect(m_actMapAccess_Cache, SIGNAL(triggered()), this, SLOT(actMapAccess_Cache()));

    m_actWaypoint_add = new QAction(tr(u8"航点添加"), this);
    connect(m_actWaypoint_add, SIGNAL(triggered()), this, SLOT(actWaypoint_add()));
    m_actWaypoint_del = new QAction(tr(u8"航点删除"), this);
    connect(m_actWaypoint_del, SIGNAL(triggered()), this, SLOT(actWaypoint_del()));
    m_actWaypoint_edit = new QAction(tr(u8"航点编辑"), this);
    connect(m_actWaypoint_edit, SIGNAL(triggered()), this, SLOT(actWaypoint_edit()));
    m_actWaypoint_clear = new QAction(tr(u8"航点清除"), this);
    connect(m_actWaypoint_clear, SIGNAL(triggered()), this, SLOT(actWaypoint_clear()));
    m_actWaypoint_save = new QAction(tr(u8"航点保存"), this);
    connect(m_actWaypoint_save, SIGNAL(triggered()), this, SLOT(actWaypoint_save()));
    m_actWaypoint_load = new QAction(tr(u8"航点加载"), this);
    connect(m_actWaypoint_load, SIGNAL(triggered()), this, SLOT(actWaypoint_load()));

    m_actSelectArea_beg = new QAction(tr(u8"选择区域起点"), this);
    connect(m_actSelectArea_beg, SIGNAL(triggered()), this, SLOT(actSelectArea_beg()));
    m_actSelectArea_end = new QAction(tr(u8"选择区域终点"), this);
    connect(m_actSelectArea_end, SIGNAL(triggered()), this, SLOT(actSelectArea_end()));
    m_actSelectArea_clear = new QAction(tr(u8"选择区域清除"), this);
    connect(m_actSelectArea_clear, SIGNAL(triggered()), this, SLOT(actSelectArea_clear()));

    m_actHome_Set = new QAction(tr(u8"设置Home"), this);
    connect(m_actHome_Set, SIGNAL(triggered()), this, SLOT(actHome_Set()));
    m_actHome_Safearea = new QAction(tr(u8"设置Home安全区域"), this);
    connect(m_actHome_Safearea, SIGNAL(triggered()), this, SLOT(actHome_Safearea()));
    m_actHome_ShowHide = new QAction(tr(u8"显示/隐藏Home"), this);
    m_actHome_ShowHide->setCheckable(true);
    m_actHome_ShowHide->setChecked(true);
    connect(m_actHome_ShowHide, SIGNAL(triggered()), this, SLOT(actHome_ShowHide()));

    m_actCacheMap = new QAction(tr(u8"缓存地图"), this);
    connect(m_actCacheMap, SIGNAL(triggered()), this, SLOT(actCacheMap()));

    m_actTrail_clear = new QAction(tr(u8"清除轨迹"), this);
    connect(m_actTrail_clear, SIGNAL(triggered()), this, SLOT(actClearTrail()));

    // setup menu
    m_popupMenu = new QMenu("Menu");

    QMenu* menuAccessMode = m_popupMenu->addMenu(u8"接口类型");
    m_popupMenu->addAction(m_actMapType);
    m_popupMenu->addAction(m_actCacheMap);
    m_popupMenu->addSeparator();
    m_popupMenu->addAction(m_actTrail_clear);
    m_popupMenu->addSeparator();
    m_popupMenu->addAction(m_actWaypoint_add);
    m_popupMenu->addAction(m_actWaypoint_del);
    m_popupMenu->addAction(m_actWaypoint_edit);
    m_popupMenu->addAction(m_actWaypoint_clear);
    m_popupMenu->addAction(m_actWaypoint_save);
    m_popupMenu->addAction(m_actWaypoint_load);
    m_popupMenu->addSeparator();
    m_popupMenu->addAction(m_actSelectArea_beg);
    m_popupMenu->addAction(m_actSelectArea_end);
    m_popupMenu->addAction(m_actSelectArea_clear);
    m_popupMenu->addSeparator();
    m_popupMenu->addAction(m_actHome_Set);
    m_popupMenu->addAction(m_actHome_Safearea);
    m_popupMenu->addAction(m_actHome_ShowHide);

    menuAccessMode->addAction(m_actMapAccess_ServerAndCache);
    menuAccessMode->addAction(m_actMapAccess_Cache);

    return 0;
}

七.最终效果

20240510_164348 00_00_00-00_00_30.gif

八.源代码链接

https://download.csdn.net/download/ever__ever/89291117?spm=1001.2014.3001.5503

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/625087.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

技艺高超的魔法师:Java运算符

在Java编程的世界里&#xff0c;运算符是连接变量和表达式的关键纽带&#xff0c;它们使得程序能够执行计算、比较、赋值等一系列操作。 一&#xff0c;基本概念 1&#xff0c;运算符是什么&#xff1f; 运算符是操作变量的符号。 2&#xff0c;分类 Java中的主要运算符类…

openlayer实现ImageStatic扩展支持平铺Wrapx

地图平铺&#xff08;Tiling&#xff09;是地图服务中常见的技术&#xff0c;用于将大尺寸的地图数据分割成许多小块&#xff08;瓦片&#xff09;&#xff0c;便于高效加载和展示。这种技术特别适用于网络环境&#xff0c;因为它允许浏览器只加载当前视图窗口内所需的地图瓦片…

摸鱼大数据——Linux搭建大数据环境(集群免密码登录和安装Hadoop)二

集群设置免密登录 克隆node1虚拟机的前置条件&#xff1a;node1虚拟机存在且处于关闭状态 1.克隆出node2虚拟机 1.node1虚拟机: 右键 -> "管理" -> "克隆" 2.图形化弹窗中: "下一页"->"下一页"->选择"创建完整克隆&…

蓝鹏测控:扩大出口,勇拓海外市场

蓝鹏测控自2012年成立以来&#xff0c;始终专注于工业测量仪器的研发、生产与销售。公司坚持经验与创新并存&#xff0c;长期与华北电力大学、河北大学等多所知名院校深度合作&#xff0c;拥有一支技术力量雄厚的研发团队。经过多年的努力&#xff0c;蓝鹏测控已研发出多款具有…

使用C++实时读取串口数据(window使用已编译LibModbus库并用QT实现一个实时读取串口数据)

先看这篇文章&#xff0c;写得很详细: QT应用篇 四、window编译LibModbus库并用QT编写一个Modbus主机 手把手教学 编译好的LibModbus库可以在上面文章里下载&#xff0c;也可以在我的链接里下载&#xff1a; 为了在Qt Creator中创建新项目并嵌入上述C代码&#xff0c;请执行以…

算法-卡尔曼滤波之卡尔曼滤波的第二个方程:预测方程(状态外推方程)

在上一节中&#xff0c;使用了静态模型&#xff0c;我们推导出了卡尔曼滤波的状态更新方程&#xff0c;但是在实际情况下&#xff0c;系统都是动态&#xff0c;预测阶段&#xff0c;前后时刻的状态是改变的&#xff0c;此时我们引入预测方程&#xff0c;也叫状态外推方程&#…

冯喜运:5.14今日黄金原油涨跌走势分析操作建议

【黄金消息面分析】&#xff1a;本周黄金市场将迎来关键的美国通胀数据&#xff0c;包括周二的生产者价格指数(PPI)和周三的消费者物价指数(CPI)。这些数据对美联储的政策路径至关重要&#xff0c;可能会影响市场对利率调整的预期。目前&#xff0c;现货黄金价格小幅上涨&#…

Redis知识总结

文章目录 1. NoSQL2. Redis介绍3. Redis的下载与安装3.1 Windows版3.2 Linux版 4. Redis的数据类型5. Redis常用命令5.1 操作字符串的命令5.2 操作哈希结构的命令5.3 操作列表的命令5.4 操作set集合的命令5.5 操作zset集合的命令5.6 Redis通用命令5.7 其他命令 6. 在Java中操作…

【Python |基础入门】入门必备知识(基础各方面全覆盖)

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; &#x1f388;丠丠64-CSDN博客&#x1f388; ✨✨ 帅哥美女们&#xff0c;我们共同加油&#xff01;一起…

Linux系统运行级别

Linux系统运行级别&#xff1a;linux系统共有7个运行级别&#xff0c;不同的级别运行的程序和功能都是不一样的而linux系统默认是运行在一个标准级别上&#xff0c;系统运行级别文件/etc/inittab 运行级别0&#xff1a;所有进程被终止&#xff0c;机器将有序的停止&#xff0c;…

C语言学习【常量和C预处理器】

C语言学习【常量和C预处理器】 符号常量(symbolic constant) C预处理器可以用来定义常量 就像这样 #define TAXRATE 0.015/* 通用格式 末尾不加分号 */ /* 大写表示符号常量是 C 语言一贯的传统 */ #define NAME value编译程序时&#xff0c;程序中所有TAXRATE都会被替换成0.…

天锐绿盾|设计院图纸透明加密软件、制造业文件资料防止外泄

#图纸加密软件# 天锐绿盾是一家专注于数据安全解决方案的提供商&#xff0c;其产品主要为企业级用户设计&#xff0c;旨在保护敏感信息和知识产权免遭未经授权的访问或泄露。"天锐绿盾"的图纸透明加密软件和机械制造业文件资料防止外泄系统&#xff0c;是专为设计院…

Properties配置文件和源码

先对测试类进行get方法复写得到getReqType 判断caseinfo等于get时&#xff0c;就是get请求&#xff0c;反之就不是 这里的url和param都是xxx代替&#xff0c;如果直接写内容&#xff0c;每次都会请求 三目运算优化 为什么要用配置文件 test里时url,可以将ip和端口写在配置文…

Flink CDC 原理

简介 Flink CDC&#xff08;Change Data Capture&#xff09;是 Apache Flink 提供的一个变更数据捕获工具集。它可以监控数据库的变更&#xff0c;并将这些变更实时地以流的形式提供给下游系统&#xff0c;这些变更包括插入、更新和删除操作。 Flink CDC 适用于需要实时数据…

利用matplotlib和KNeighborsClassifier,进行DBSACN聚类算法

代码&#xff1a; # -*- coding: utf-8 -*- """ Created on Sat May 11 10:23:50 2024author: admin """ # 调用库 import numpy as np import matplotlib.pyplot as plt # 调用人工智能模型库 from sklearn.neighbors import KNeighborsClassi…

自定义el-select下拉菜单的内容以及数据回显的内容

最终的效果 下拉选项的自定义内容好实现&#xff0c;因为他有默认插槽&#xff0c;所以直接在el-option标签里面写自定义内容就可以实现 <el-selectref"seriesBorderTypeRef"class"series-border-type"change"changeSeriesBorderType"v-model…

如何轻松获得稳定的静态IP?

在当今互联网时代&#xff0c;静态IP地址对于许多领域至关重要。无论是个人用户还是企业&#xff0c;拥有一个稳定的静态IP地址都能够提供诸多便利。静态IP地址与动态IP地址相比&#xff0c;具有不变性和可追溯性&#xff0c;适用于需要长期稳定通信和追踪的场景。了解静态IP的…

【前端】打砖块游戏:实现细节介绍

打砖块游戏:实现细节介绍 在本文中,我将详细介绍如何使用HTML、CSS和JavaScript技术构建一个简单的打砖块游戏。我们将重点讨论游戏的三个核心技术方面:碰撞检测、画图和事件监听。 完整代码我放在:github可以直接拉取代码测试。 游戏概览 打砖块游戏中,玩家通过控制底…

[Cesium]Cesium基础学习——Primitive

Cesium开发高级篇 | 01空间数据可视化之Primitive - 知乎 Primitive由两部分组成&#xff1a;几何体&#xff08;Geometry&#xff09;和外观&#xff08;Appearance&#xff09;。几何体定义了几何类型、位置和颜色&#xff0c;例如三角形、多边形、折线、点、标签等&#xf…

Linux之·网络编程·I/O复用·select

系列文章目录 文章目录 前言一、概述1.1 介绍IO复用的概念和作用1.1.1 I/O复用具体使用的场景1.1.2 I/O复用常用函数 二、select函数的重要性和用途2.1 基本的select函数2.2 如何使用FD_SET、FD_CLR等宏来设置和清除文件描述符集合2.3 select()函数函数整体使用框架&#xff1a…