Qt无人机姿态模拟

这个是我实训做的项目,是模拟对无人机姿态的控制,实现对无人机飞行数据的分析,项目主要分为登录窗口,客户端和服务器端
项目主题界面:
在这里插入图片描述

需求分析:

1、设计本地登录界面及云端平台界面。
2、根据用户登录信息的不同,选择不同的云端用户级别,具体为user和vip。
3、普通用户只能查看实时数据、自动给出实时建议,超级用户可以查看实时数据、历史数据、统计数据判断是否危险飞行、生成事故报告
4、创建数据库,保存两张表,表1判断云端用户级别及用户登录验证,表2记录一定时间内的飞机姿态数据
5、事故报告以文档(word、pdf)形式生成

功能分析:

1、可以根据用户级别的不同授权不同的内容查看。
2、可以使用模拟终端(滑动按钮)来改变机身角度的值。
3、通过计算机网络将数据进行传输。
4、可以实时改变验证平台上图形的状态。
5、可以实时记录机身角度改变的内容并保存到数据库中

总体设计:

在这里插入图片描述
我先从登录界面开始说起吧

登录界面的设计:

在这里插入图片描述
在这里插入图片描述
登录界面主要分为用户登录和管理员登录,运用了Sqlite轻量级数据库,可实现账号的注册,在普通用户界面加了一个验证码的功能,其实是通过随机数来实现验证,主要的代码如下:
创建数据库和表

 //创建数据库
    QSqlDatabase db=QSqlDatabase::addDatabase("QSQLITE");
    //QSqlDatabase db1=QSqlDatabase::addDatabase("QSQLITE");
    //设置数据库名
    db.setDatabaseName("pwd.db");
    //db1.setDatabaseName("pwd1.db");
    //打开数据
    if(db.open())
    {
        qDebug()<<"open database success";
    }else
    {
        qDebug()<<"open database fail";
    }
    //创建一个存储用户名密码的数据库表
    QString tableuser="create table userinfo(username varchar(64),password varchar(64))";
    QString tableadmin="create table userinfo1(username1 varchar(64),password1 varchar(64))";

实现注册:

 QString username=ui->useredit->text();
    QString password=ui->passedit->text();
    QString cmd=QString("insert into userinfo values('%1','%2')")
            .arg(username).arg(password);
    QSqlQuery query;
    if(username==NULL||password==NULL)
    {
        QMessageBox::information(this,"注册提示","用户名或密码不能为空");

    }
    else if(query.exec(cmd))
    {
        QMessageBox::information(this,"注册提示","注册成功");

    }

服务器的实现:

在这里插入图片描述
服务器界面就是一个模拟无人机的圆
在这里插入图片描述
这里运用了Qpainter来绘制三角,圆等形状来实现对无人机的模拟,服务器接收来自客户端的消息,来进行角度的改变,接收来自客户端连接的信号:

if(svr->hasPendingConnections()){
        socket = svr->nextPendingConnection();
        connect(socket,SIGNAL(readyRead()),this,SLOT(slotRecv()));
        qDebug() << "有设备连接";
    }

接收客户端数据:

  QByteArray array = socket->readAll();
    QString str = QString::fromUtf8(array);
    QString tmp;
    int j = 0;
    while(j<str.size()){
        tmp.clear();
        int k = 0;
        for(j;j<str.length();j++)
        {
            if(str[j]>='0'&&str[j]<='9'||str[j]=='-'){
                tmp.append(str[j]);
            }
            if(str[j]==" "){
                k++;
                if(k == 1){
                    angle_spin = tmp.toInt();
                    tmp.clear();
                }else if(k==2) {
                    angle_dir = tmp.toInt();
                    tmp.clear();
                }
            }
            if(str[j]=="e"){
                j++;
                angle_pit = tmp.toInt();
                break;
            }
        }
        this->setWindowTitle("偏转角:"+QString::number(angle_spin)+"°俯仰角:"+QString::number(angle_dir)+"°方向:"+QString::number(angle_pit)+"°");
        update();
    }

客户端的实现:

在这里插入图片描述
客户端主要通过三个Slider来实现对角度的控制,在tableView控件里来显示历史数据,tableView里还有一个事故,我这里设置的是三个角度大于60度就会报警,一般报警就是事故变为1.0并且图标发生改变:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
然后就是散点图的绘制:


    chart = new QChart();

    chart->setTitle("无人机飞行角度"); //设置表格标题

    QScatterSeries *scatterSeries1 = new QScatterSeries(chart);
    QScatterSeries *scatterSeries2 = new QScatterSeries(chart);
    QScatterSeries *scatterSeries3 = new QScatterSeries(chart);


    scatterSeries1->setName("偏航角度");
    scatterSeries1->setPointLabelsFormat("@yPoint");
    scatterSeries1->setPointLabelsVisible();
    scatterSeries1->setMarkerSize(16); // 设置节点大小

    scatterSeries2->setName("横滚角度");
    scatterSeries2->setPointLabelsFormat("@yPoint");
    scatterSeries2->setPointLabelsVisible();
    scatterSeries2->setMarkerSize(16);

    scatterSeries3->setName("俯视角度");
    scatterSeries3->setPointLabelsFormat("@yPoint");
    scatterSeries3->setPointLabelsVisible();
    scatterSeries3->setMarkerSize(16);


    QSqlQuery sql_query;
    QString select_sql = "select * from info3";// order by 字段名 +asc 递增方式
    if(!sql_query.exec(select_sql))
    {
        qDebug()<<"错误";
    }
    else
    {
        while(sql_query.next())//判断下个查询数据是否可用
        {
            static int i=1,j=1,k=1;
            int a = sql_query.value(0).toDouble();//打印某行第一列
            int b = sql_query.value(1).toDouble();
            int c=sql_query.value(2).toDouble();


            scatterSeries1->append(i,a);

            scatterSeries2->append(j,b);
            scatterSeries3->append(k,c);
            i++;
            j++;
            k++;
            if(i==90){
                i=-90;
            }
            if(j==90){
                j=-90;
            }
            if(k==0){
                k=-90;
            }


        }
    }


    // 添加节点
    //    scatterSeries1->append(0,6);
    //    scatterSeries1->append(1,10);
    //    scatterSeries1->append(4,12);
    //    scatterSeries1->append(6,5);
    //    scatterSeries2->append(0,18);
    //    scatterSeries2->append(3,13);
    //    scatterSeries2->append(5,7);
    //    scatterSeries2->append(6,2);
    chart->addSeries(scatterSeries1);
    chart->addSeries(scatterSeries2);
    chart->addSeries(scatterSeries3);
    //设置动画效果
    chart->setAnimationOptions(QChart::AllAnimations);

    chart->createDefaultAxes();//设置网格线
    chart->axes(Qt::Horizontal).first()->setRange(-90,90);// x轴范围
    chart->axes(Qt::Vertical).first()->setRange(-90,90);// y轴范围
    // Add space to label to add space between labels and axis在标签和轴之间加空格
    QValueAxis *axisY = qobject_cast<QValueAxis*>(chart->axes(Qt::Vertical).first());
    Q_ASSERT(axisY);
    axisY->setLabelFormat("%.1f  ");


    chart->setTheme(QChart::ChartThemeDark);

    QChartView *chartView;

    chartView = new QChartView(chart);

    zt++;
    ui->widget1->insertWidget(0,chartView,0,Qt::Alignment());
    if(zt==1){
        ui->widget1->removeWidget(chartView);
        zt=0;
    }

可以实现数据的清空,一旦清空所有数据都会删除,散点图也会清除:
在这里插入图片描述
全部重置是对Slider的重置,导出数据是保存历史数据到csv文件:
在这里插入图片描述
导出pdf是保存历史数据到pdf中:
在这里插入图片描述

保存pdf代码:

 QFile pdfFile("D:\\test1.pdf");//输出文件名
    if(!pdfFile.open(QIODevice::WriteOnly))
    {
        QMessageBox::warning(this,tr("write File"),tr("Cannot open file:\n%1").arg("d:\\test.pdf"));
        return;
    }
    QPdfWriter *pdfWriter = new QPdfWriter(&pdfFile);               //实例化QPdfWriter 可以设置PDF文件的一些参数
    pdfWriter->setPageSize(QPagedPaintDevice::A4);                  //设置纸张为A4纸
    pdfWriter->setResolution(QPrinter::ScreenResolution);           //设置分辨率 屏幕分辨率 打印机分辨率 高分辨率
    pdfWriter->setPageMargins(QMarginsF(40, 40, 40, 40));           //设置页边距 顺序是:左上右下

    QPainter *pdfPainter = new QPainter(pdfWriter);                //qt绘制工具

    //设置标题
    QTextOption option(Qt::AlignCenter);                           //标题居中显示
    option.setWrapMode(QTextOption::WordWrap);                     //标题自动换行

    // 设置标题字体 需要使用QT的QFont
    QFont font;
    font.setFamily("Microsoft YaHei");                            //设置字体 微软雅黑、宋体之类的
    font.setPointSize(22);                                        //设置字体大小
    //font.setItalic(true);//斜体
    //font.setUnderline(true);//设置下划线
    //    font.setBold(true);                                           //加粗
    pdfPainter->setFont(font);
    pdfPainter->drawText(QRect(3000, 0, 2100, 450), QString::QString::fromUtf8("历史数据"), option);//距离左边3000,上面0,标题字宽度2100,标题字高450(如果字显示不全,可以适当调整)

    //设置内容
    option.setAlignment(Qt::AlignLeft);
    font.setPointSize(14);                                       //字体大小14
    pdfPainter->setFont(font);

    pdfPainter->drawRect(200, 250, 2000, 1);
    pdfPainter->drawRect(200, 700, 2000, 4);

    pdfPainter->setFont(QFont("NSimSun", 12, QFont::Normal));


    pdfPainter->setFont(QFont("NSimSun", 14, QFont::Normal));
    option.setAlignment(Qt::AlignLeft);
    font.setPointSize(10);                                       //字体大小14
    pdfPainter->setFont(font);

    pdfPainter->drawText(200, 2000, QString::fromUtf8("偏移角度"));
    pdfPainter->drawText(1200, 2000, QString::fromUtf8("横滚角度"));
    pdfPainter->drawText(2200, 2000, QString::fromUtf8("俯视角度"));
    pdfPainter->drawText(3200, 2000, QString::fromUtf8("事故"));

    QString str = "select * from info3";
    QSqlQuery query;
    query.exec(str);

    int i=0;
    while(query.next())//依次取出下一行数据
    {
        i++;
        QString x1 = query.value(0).toString();
        QString x = query.value(1).toString();
        QString y = query.value(2).toString();
        QString z = query.value(3).toString();

        pdfPainter->drawText(200, 2000+i*200, x1);
        pdfPainter->drawText(1200, 2000+i*200, y);
        pdfPainter->drawText(2200, 2000+i*200, x);
        pdfPainter->drawText(3200, 2000+i*200, z);

        if(2000+i*200>12000)
        {
            i=i-50;
            pdfWriter->newPage();
            pdfPainter->drawText(200, 2000+i*200, x1);
            pdfPainter->drawText(1200, 2000+i*200, y);
            pdfPainter->drawText(2200, 2000+i*200, x);
            pdfPainter->drawText(3200, 2000+i*200, z);


        }
    }
    delete pdfPainter;
    delete pdfWriter;
    QDesktopServices::openUrl(QUrl::fromLocalFile("D:\\test1.pdf"));

整体的项目就是这样,最后由衷地感谢我的小组团队,以及实训的所有老师
想要例子的可以添加zrccode

  • 4
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值