QCustomPlot动态画图与低通滤波


前言

工业控制中通常需要测量系统的实时状态,并通过曲线进行显示。在有噪声的情况下,还需要对其进行滤波。本篇文章首先介绍了如何使用QCustomPlot绘制实时显示的动态曲线。其次介绍了两种滤波方法,巴特沃斯滤波器和跟踪微分器,并在Qt中对其进行了实现。详细程序见我上传的资源《 使用QCustomPlot绘制实时动态曲线并对数据进行滤波》。

一、QCustomPlot绘制实时显示的动态曲线

程序运行界面

使用QCustomPlot之前,需要在官网下载相应的头文件和源文件http://www.qcustomplot.com/index.php/download。
下载好之后,放到工程文件下面。
使用步骤如下:
1.在QtCreator中右击工程文件名,添加现有文件,将qcustomplot.h和qcustomplot.cpp添加进工程中,然后在.pro文件中添加QT += widgets printsupport,最后在对应窗口头文件中#include“qcustomplot.h”。
2.在ui界面中拖入一个widget容器,右击
->然后提升为qcustomplot->添加后提升。
在这里插入图片描述
3.定义一个qCustomPlot类,并使其与ui界面的相关联。
代码如下:

qCustomPlot = ui->customPlot;

4.在构造函数中设置相应曲线,每添加一条曲线addGraph一次,设置相应曲线颜色,设置坐标轴范围为时间。

 qCustomPlot->addGraph();//每画一条曲线都需要添加一次addGraph
    qCustomPlot->graph(0)->setPen(QPen(QColor(40, 110, 255)));//输入信号
    qCustomPlot->graph(0)->setName("输入信号");
    qCustomPlot->addGraph();
    qCustomPlot->graph(1)->setPen(QPen(QColor(255, 110, 40)));//红线
    qCustomPlot->graph(1)->setName("巴特沃斯滤波");
    qCustomPlot->addGraph();
    qCustomPlot->graph(2)->setPen(QPen(QColor(0, 0, 0)));//跟踪微分器滤波
    qCustomPlot->graph(2)->setName("跟踪微分器滤波");
    qCustomPlot->legend->setVisible(true);//使能图例
    qCustomPlot->axisRect()->insetLayout()->setInsetAlignment(0,Qt::AlignRight|Qt::AlignTop);//设置图例位置
    //坐标轴使用时间刻度
    QSharedPointer<QCPAxisTickerTime> timeTicker(new QCPAxisTickerTime);//使用秒作为横坐标刻度
    timeTicker->setTimeFormat("%s");
    qCustomPlot->xAxis->setTicker(timeTicker);
    //四边安上坐标轴
    qCustomPlot->axisRect()->setupFullAxesBox();
    //使对称坐标轴相同范围
    connect(qCustomPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), qCustomPlot->xAxis2, SLOT(setRange(QCPRange)));
    connect(qCustomPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), qCustomPlot->yAxis2, SLOT(setRange(QCPRange)));
    //支持鼠标拖拽轴的范围、滚动缩放轴的范围,
    qCustomPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
    //连接定时器和对应槽函数
    connect(timer0,SIGNAL(timeout()),this,SLOT(Timer0Out()));

5.在定时器中给相应曲线添加数据。

    static QTime time(QTime::currentTime());
    double currentTime = time.elapsed() / 1000.0;//单位毫秒
    static double lastTime = 0;
    if(currentTime - lastTime > 0.001)//每0.001秒刷新一次图像
    {
        //向graph中添加数据,曲线0为带随机噪声的正弦函数
        qCustomPlot->graph(0)->addData(currentTime,1000 * qSin(currentTime) + qrand()%50 );// (double)RAND_MAX*1*qSin(currentTime/0.3843)
        //qCustomPlot->graph(1)->addData(currentTime,qCos(currentTime));
        //曲线1为对曲线0进行巴特沃斯2阶滤波后的曲线
        qCustomPlot->graph(1)->addData(currentTime,transfer(filter1,(1000 * qSin(currentTime) + qrand()%50)));
        //曲线2为对曲线0通过跟踪微分器滤波后滤波的函数
        qCustomPlot->graph(2)->addData(currentTime,TrackingDifference(1000 * qSin(currentTime) + qrand()%50));
        lastTime = currentTime;
        //qDebug()<<QString::number(TrackingDifference(1000 * qSin(currentTime) + qrand()%50));
        //当界面中动态画图勾选框被勾选,X轴自己滚动,X轴长度为8秒
        if(ui->checkBoxRoll->isChecked() == true)
        {
            qCustomPlot->xAxis->setRange(currentTime,8,Qt::AlignRight);
        }
    }

6.使用qCustomPlot->replot()绘制曲线。

二、巴特沃斯滤波器的实现

代码如下:

/巴特沃斯二阶滤波器,选取不同的参数过滤不同的噪声
double Widget::butter2jie(double x[3],double y[2])
{
    double ycurrent;
//    double b[3]={ 0.206572083826148,0.413144167652296,0.206572083826148};//200Hz
//    double a[3]={ 1.000000000000000,-0.369527377351241,0.195815712655833};//200Hz
    //double b[3]={0.020083365564211,0.040166731128423,0.020083365564211};//50Hz
    //double a[3]={1.000000000000000,-1.561018075800718,0.641351538057563};//50Hz
//    double a[3]={1.0000000000,-1.9955571243,0.9955669721};//频率为0.5
//    double b[3]={0.0000024619,0.0000049239,0.0000024619};//频率为0.5
    double b[3]={0.000944691843840,0.001889383687680,0.000944691843840};//5Hz
    double a[3]={1.000000000000000,-1.911197067426073,0.914975834801434};//5Hz
    ycurrent=b[0]*x[2]+b[1]*x[1]+b[2]*x[0]-a[1]*y[1]-a[2]*y[0];
    return ycurrent;
}
//配合巴特沃斯二阶滤波器使用函数,Rdata为需要被滤波的数据
double Widget::transfer(double *interimarray,double Rdata)
{
    int i=0;
    double c=0;
    double a[3]={0};
    double b[2]={0};
    for (i=0;i<2;i++)
    {
        interimarray[i]=interimarray[i+1];
    }
    interimarray[2]=Rdata;
    for (i=0;i<3;i++)
    {
        a[i]=interimarray[i];
    }
    for (i=0;i<2;i++)
    {
        b[i]=interimarray[i+3];
    }
    c = butter2jie(a,b);
    for (i=0;i<1;i++)
    {
        interimarray[i+3]=interimarray[i+4];
    }
    interimarray[4]=c;
    return c;
}

三、跟踪微分器的实现

代码如下:

//跟踪微分器滤波,realData
double Widget::TrackingDifference(double realData)
{
    static double temp = 0;
    static double x[2] = {0};
    x[0] = x[0] + 0.001 * x[1];
    x[1] = x[1] + 0.001 * fhan(x,realData);
    temp = x[0];
    return temp;
}
//最速跟踪函数
double Widget::fhan(double x[2],double rD)
{
    static double r0 = 0;
    static double h = 0.001;
    //static double x[2] = {0};
    static double d = 0;
    static double a0 = 0;
    static double y = 0;
    static double a1 = 0;
    static double a2 = 0;
    static double a = 0;
    static double f = 0;
    r0 = 60000.00;
    h = 0.001;
    d = r0 * h * h;
    a0 = h * x[1];
    y = x[0] - rD + a0;//x[0] - rD   x[1]
    a1 = (double)sqrtf((d + 8 * (double)fabs(y)) * d);
    a2 = a0 + sign(y) * (a1 - d) / 2;
    a = (a0 + y) * (sign( y+ d) - sign(y - d)) / 2 + a2 * (1 - (sign(y + d) - sign(y - d)) / 2);
    f = -r0 * (a / d) * (sign(a + d) - sign(a - d)) / 2 - r0 * sign(a) * (1 - (sign(a + d) - sign(a - d)) / 2);
    return  f;
}
//符号函数
double Widget::sign(double a)
{
    double c = 0;
    if(a > 0)
    {
        c = 1;
    }
    if(a < 0 )
    {
        c = -1;
    }
    if(a == 0)
    {
        c = 0;
    }
    qDebug()<<QString::number(c);
    return  c;
}

总结

本文提供了常规的动态画图曲线DEMO,其可以左键选取局部放大,可以通过勾选框充满纵轴,可以显示需要画的曲线、可以清空数据。还提供了两个常规滤波的方法,供大家借鉴。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值