0
$\begingroup$

I'm using Qt C++, QCustomPlot to read and display realtime value from an IMU. This is how I set the realtimeDataSlot:

void Settings::realtimeDataSlot(double x_acceleration_g, double y_acceleration_g, double z_acceleration_g, double z_acceleration_gnew)
{
    static QTime time(QTime::currentTime());
    // calculate two new data points:
    double key = time.elapsed()/1000.0; // time elapsed since start of demo, in seconds
    static double lastPointKey = 0;
    if (key-lastPointKey > 0.02) // at most add point every 20 ms
    {
      // add data to lines:
        ui->customPlot->graph(0)->addData(key, x_acceleration_g); // X axis
        ui->customPlot->graph(1)->addData(key, y_acceleration_g); // Y axis
        ui->customPlot->graph(2)->addData(key, z_acceleration_g); // Z axis
        ui->customPlot->graph(3)->addData(key, z_acceleration_gnew);

      lastPointKey = key;
    }
    // make key axis range scroll with the data (at a constant range size of 8):
    ui->customPlot->xAxis->setRange(key, 8, Qt::AlignRight);
    ui->customPlot->replot();

    // calculate frames per second:
    static double lastFpsKey;
    static int frameCount;
    ++frameCount;
    if (key-lastFpsKey >2) // average fps over 2 seconds
    {
      ui->statusbar->showMessage(
            QString("%1 FPS, Total Data points: %2")
            .arg(frameCount/(key-lastFpsKey), 0, 'f', 0)
            .arg(ui->customPlot->graph(0)->data()->size()+ui->customPlot->graph(1)->data()->size())
            , 0);
      lastFpsKey = key;
      frameCount = 0;
    }
}

which shows me as follows:

enter image description here

As a next step, I need to detect the peaks in any axis, say for example in the above figure in the Y axis there are peak values which I need to detect and count.

I marked in the peaks by hand in the figure. I define peak as the figure that value (positive values) more than 0.25 g at high rate.

Can somebody show me a way to do this realtime?

$\endgroup$
0
$\begingroup$

In order to detect peaks, the simplest method will be to take the difference of adjacent samples and check for zero crossing. You may also want to smooth out the data before taking difference to prevent spurious peaks due to noise. An outline of the procedure here would be like this

  1. Smooth out the data using Moving average filtering. It is a simple filtering where you take average of, say, 5 neighboring samples to arrive at sample value.
  2. For the above filtered signal take the adjacent sample difference ($y[n] = x[n] - x[n-1]) and save the sample indices where difference hits zero (or near zero).
  3. To differentiate positive peaks from negative peaks, also check for sign of sample values around these indices. Eliminate negative peaks, and remaining ones indicate positions where positive peaks occur.
  4. You may not get exact zero crossing, so you may want to keep a threshold. Also, the position may have offset due to filter delay. A 5-sample MA filter will delay your sample train by ceil(5)=3 samples.
  5. There are ways to combine MA filtering and taking difference. Look for filters which do differentiation (https://www.dsprelated.com/showarticle/35.php)
$\endgroup$
1
  • $\begingroup$ Thanks a lot :) , Could you provide pseudocode? In my case, the data is real time , for ex. calling sample->acceleration_g[0] gives me data at a rate of 100Hz. I'm beginner , not quite understood how to do all the steps you mentioned on a realtime data. $\endgroup$ – tcv Mar 6 '20 at 11:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.