QCustomPlot Discussion and Comments

Odd graphing bug - help!Return to overview

I've been using QCustomPlot for many years now, and I'm currently encountering a really odd bug. The bug could be my doing, but I've spent half the day trying figure it out to no avail. I have a customPlot window with 8 QCPAxisRects. In one of the rects I'm plotting 10 temperatures. Temperatures 5-10 are plotting as expected, but temperatures 1-4 are alternately plotting their value, then zero, then their value, then zero. To diagnose this I've hard-coded the value of each temperature to be 1, 2, 3..10. I should see ten flat lines with values 1, 2, 3..10, but instead temperatures 1-4 look, essentially, like a sawtooth because they alternate from their value, back to zero instead of being flat lines.

In all the other axisRects, every graph line behaves exactly as expected. I'm currently printing out the temperature values in my plotting method to verify that the values are good, and they are. All of the QCPAxisRects, graphs, etc - everything, is setup in an identical way. It's baffling me why this one group of graphs is acting this way.

Note: it's the igbtRect and igbtGraphs that are the issue.

Here's how I'm setting up the QCPAxisRects

   
  // one QCPAxisRect for each plot
  // first row
  QCPAxisRect *heatersRectDupe = new QCPAxisRect(ui->customPlot);
  heatersRectDupe->setupFullAxesBox(true);
  heatersRectDupe->setMarginGroup(QCP::msLeft | QCP::msRight, group);

  QCPAxisRect *heatExchangersRectDupe = new QCPAxisRect(ui->customPlot);
  heatExchangersRectDupe->setupFullAxesBox(true);
  heatExchangersRectDupe->setMarginGroup(QCP::msLeft | QCP::msRight, group);

  // second row
  QCPAxisRect *heatersRect = new QCPAxisRect(ui->customPlot);
  heatersRect->setupFullAxesBox(true);
  heatersRect->setMarginGroup(QCP::msLeft | QCP::msRight, group);

  QCPAxisRect *heatExchangersRect = new QCPAxisRect(ui->customPlot);
  heatExchangersRect->setupFullAxesBox(true);
  heatExchangersRect->setMarginGroup(QCP::msLeft | QCP::msRight, group);

  // third row
  QCPAxisRect *ambSkinRect = new QCPAxisRect(ui->customPlot);
  ambSkinRect->setupFullAxesBox(true);
  ambSkinRect->setMarginGroup(QCP::msLeft | QCP::msRight, group);

  QCPAxisRect *igbtRect = new QCPAxisRect(ui->customPlot);
  igbtRect->setupFullAxesBox(true);
  igbtRect->setMarginGroup(QCP::msLeft | QCP::msRight, group);

  // fourth row
  QCPAxisRect *pressureRect = new QCPAxisRect(ui->customPlot);
  pressureRect->setupFullAxesBox(true);
  pressureRect->setMarginGroup(QCP::msLeft | QCP::msRight, group);

  QCPAxisRect *imuRect = new QCPAxisRect(ui->customPlot);
  imuRect->setupFullAxesBox(true);
  imuRect->setMarginGroup(QCP::msLeft | QCP::msRight, group);

  // add each axis rectangle to row, column
  ui->customPlot->plotLayout()->expandTo(4, 2); // make 4 rows, 2 cols

  // first row
  ui->customPlot->plotLayout()->addElement(0, 0, heatersRectDupe);
  ui->customPlot->plotLayout()->addElement(0, 1, heatExchangersRectDupe);
  // second row
  ui->customPlot->plotLayout()->addElement(1, 0, heatersRect);
  ui->customPlot->plotLayout()->addElement(1, 1, heatExchangersRect);
  // third row
  ui->customPlot->plotLayout()->addElement(2, 0, ambSkinRect);
  ui->customPlot->plotLayout()->addElement(2, 1, igbtRect);
  // fourth row
  ui->customPlot->plotLayout()->addElement(3, 0, pressureRect);
  ui->customPlot->plotLayout()->addElement(3, 1, imuRect);
 


Here's an example of a working graph (IMU yaw, pitch, roll)

  // IMU pitch and yaw, load cell graphs
  for (int i = 0; i < NUM_IMU; i++) { // 4 items
    imuLoadGraph[i] = ui->customPlot->addGraph(imuRect->axis(QCPAxis::atBottom),
                                               imuRect->axis(QCPAxis::atLeft));
    imuLoadGraph[i]->valueAxis()->setRange(-100, +100);
    imuLoadGraph[i]->keyAxis()->setRange(0, xAxisRange, Qt::AlignRight);
    imuLoadGraph[i]->valueAxis()->setLabel("IMU Roll/Pitch/Yaw + Loadcell");
    imuLoadGraph[i]->keyAxis()->setTicker(dateTicker);
    graphPen.setColor(Qt::red);
    graphPen.setStyle(Qt::SolidLine);
    imuLoadGraph[i]->setPen(graphPen);
    // imuLoadGraph->setName("Pitch/Yaw + Loadcell");
  }


Here's my "broken" IGBT temperature graphs.

   // IGBT temperature graphs
  for (int i = 0; i < NUM_IGBT; i++) {

    igbtGraph[i] = ui->customPlot->addGraph(igbtRect->axis(QCPAxis::atBottom),
                                            igbtRect->axis(QCPAxis::atLeft));

    graphPen.setColor(Qt::red);
    graphPen.setStyle(Qt::SolidLine);
    igbtGraph[i]->setPen(graphPen);
    // igbtGraph[i]->setName(ADCnames[i]);
    igbtGraph[i]->valueAxis()->setRange(-15, 110);
    igbtGraph[i]->keyAxis()->setRange(0, xAxisRange, Qt::AlignRight);
    igbtGraph[i]->valueAxis()->setLabel("IGBT \u2103");
    igbtGraph[i]->keyAxis()->setTicker(dateTicker);
    // igbtGraph[i]->addToLegend(legend0);
  } 

Here's a snippet of my updatePlot method

   
// 10 IGBTs 
  for (int i = 0; i < NUM_IGBT; i++) {
    igbtGraph[i]->addData(key, engData.igbtTempC[i]);
    qDebug() << "igbt" << i << engData.igbtTempC[i];
  } 

  // third row (only need to call moveRange() on one graph per rect)
  ambSkinGraph[0]->keyAxis()->moveRange(1);
  igbtGraph[0]->keyAxis()->moveRange(1);


  ui->customPlot->replot();

I have screen shot I'll try to link to show what I'm seeing.

Here's a screen shot of a portion of my plot window. Note how the IMU yaw/pitch/roll plots as expected (I even tilted the hardware so you can see there's a smooth plot). And igbt temperatures 5-10 plot normally. But 1-4 are messed up. The plots are updated once per second. The "bad" plots are plotting expected values, then zero values, causing each "tick" of the plot to draw a sawtooth feature. It makes no sense that half the plots in the igbt rect would plot normal and half of them would be messed up like this. Everything is done is for() loops, so half the plots can't have been setup or have data being added to them in a different way!

https://postimg.cc/nCRLqywr

Solved!
Oh good lord. I figured it out. With 8 rects, and something like 50 odd graphs I was bound to make a bug. I was, essentially, writing outside of an array because I'd entered the wrong range . It wasn't crashing my app, but it was somehow writing into the igbt graphs' memory space.