Files
GoldenCheetah/src/RealtimePlotWindow.cpp
Mark Liversedge c7cdffe68c Realtime Moxy Part 2b of 3
.. added moxy to the realtime plots.

last piece is to update the realtime file format to
include moxy data -- moving away from powertap csv
2014-11-01 09:27:07 +00:00

370 lines
12 KiB
C++

/*
* Copyright (c) 2010 Mark Liversedge (liversedge@gmail.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "RealtimePlotWindow.h"
#include "Athlete.h"
RealtimePlotWindow::RealtimePlotWindow(Context *context) :
GcWindow(context), context(context), active(false)
{
setContentsMargins(0,0,0,0);
setProperty("color", GColor(CTRAINPLOTBACKGROUND));
QWidget *c = new QWidget;
QVBoxLayout *cl = new QVBoxLayout(c);
setControls(c);
// setup the controls
QLabel *showLabel = new QLabel(tr("Show"), c);
cl->addWidget(showLabel);
showHr = new QCheckBox(tr("Heart Rate"), this);
showHr->setCheckState(Qt::Checked);
cl->addWidget(showHr);
showSpeed = new QCheckBox(tr("Speed"), this);
showSpeed->setCheckState(Qt::Checked);
cl->addWidget(showSpeed);
showCad = new QCheckBox(tr("Cadence"), this);
showCad->setCheckState(Qt::Checked);
cl->addWidget(showCad);
showPower = new QCheckBox(tr("Power"), this);
showPower->setCheckState(Qt::Checked);
cl->addWidget(showPower);
showAlt = new QCheckBox(tr("Alternate Power"), this);
showAlt->setCheckState(Qt::Checked);
cl->addWidget(showAlt);
showPow30s = new QCheckBox(tr("30s Power"), this);
showPow30s->setCheckState(Qt::Checked);
cl->addWidget(showPow30s);
showSmO2 = new QCheckBox(tr("SmO2"), this);
showSmO2->setCheckState(Qt::Checked);
cl->addWidget(showSmO2);
showtHb = new QCheckBox(tr("tHb"), this);
showtHb->setCheckState(Qt::Checked);
cl->addWidget(showtHb);
showO2Hb = new QCheckBox(tr("O2Hb"), this);
showO2Hb->setCheckState(Qt::Checked);
cl->addWidget(showO2Hb);
showHHb = new QCheckBox(tr("HHb"), this);
showHHb->setCheckState(Qt::Checked);
cl->addWidget(showHHb);
QLabel *smoothLabel = new QLabel(tr("Smoothing (5Hz Samples)"), this);
smoothLineEdit = new QLineEdit(this);
smoothLineEdit->setFixedWidth(40);
cl->addWidget(smoothLabel);
cl->addWidget(smoothLineEdit);
smoothSlider = new QSlider(Qt::Horizontal);
smoothSlider->setTickPosition(QSlider::TicksBelow);
smoothSlider->setTickInterval(10);
smoothSlider->setMinimum(1);
smoothSlider->setMaximum(150);
smoothLineEdit->setValidator(new QIntValidator(smoothSlider->minimum(),
smoothSlider->maximum(),
smoothLineEdit));
cl->addWidget(smoothSlider);
cl->addStretch();
QVBoxLayout *layout = new QVBoxLayout(this);
rtPlot = new RealtimePlot();
layout->addWidget(rtPlot);
// common controls
connect(showPower, SIGNAL(stateChanged(int)), this, SLOT(setShowPower(int)));
connect(showPow30s, SIGNAL(stateChanged(int)), this, SLOT(setShowPow30s(int)));
connect(showHr, SIGNAL(stateChanged(int)), this, SLOT(setShowHr(int)));
connect(showSpeed, SIGNAL(stateChanged(int)), this, SLOT(setShowSpeed(int)));
connect(showCad, SIGNAL(stateChanged(int)), this, SLOT(setShowCad(int)));
connect(showAlt, SIGNAL(stateChanged(int)), this, SLOT(setShowAlt(int)));
connect(showSmO2, SIGNAL(stateChanged(int)), this, SLOT(setShowSmO2(int)));
connect(showtHb, SIGNAL(stateChanged(int)), this, SLOT(setShowtHb(int)));
connect(showO2Hb, SIGNAL(stateChanged(int)), this, SLOT(setShowO2Hb(int)));
connect(showHHb, SIGNAL(stateChanged(int)), this, SLOT(setShowHHb(int)));
connect(smoothSlider, SIGNAL(valueChanged(int)), this, SLOT(setSmoothingFromSlider()));
connect(smoothLineEdit, SIGNAL(editingFinished()), this, SLOT(setSmoothingFromLineEdit()));
// get updates..
connect(context, SIGNAL(telemetryUpdate(RealtimeData)), this, SLOT(telemetryUpdate(RealtimeData)));
// lets initialise all the smoothing variables
hrtot = hrindex = cadtot = cadindex = spdtot = spdindex = alttot = altindex = powtot = powindex = 0;
smo2tot = smo2index = thbtot = thbindex = o2hbtot = o2hbindex = hhbtot = hhbindex = 0;
for(int i=0; i<150; i++) {
powHist[i] = altHist[i] = spdHist[i] = cadHist[i] = hrHist[i] = 0;
smo2Hist[i] = thbHist[i] = o2hbHist[i] = hhbHist[i] = 0;
}
// set to zero
telemetryUpdate(RealtimeData());
}
void
RealtimePlotWindow::start()
{
// lets initialise all the smoothing variables
hrtot = hrindex = cadtot = cadindex = spdtot = spdindex = alttot = altindex = powtot = powindex = 0;
smo2tot = smo2index = thbtot = thbindex = o2hbtot = o2hbindex = hhbtot = hhbindex = 0;
for(int i=0; i<150; i++) {
powHist[i] = altHist[i] = spdHist[i] = cadHist[i] = hrHist[i] = 0;
smo2Hist[i] = thbHist[i] = o2hbHist[i] = hhbHist[i] = 0;
}
}
void
RealtimePlotWindow::stop()
{
// lets initialise all the smoothing variables
hrtot = hrindex = cadtot = cadindex = spdtot = spdindex = alttot = altindex = powtot = powindex = 0;
smo2tot = smo2index = thbtot = thbindex = o2hbtot = o2hbindex = hhbtot = hhbindex = 0;
for(int i=0; i<150; i++) {
powHist[i] = altHist[i] = spdHist[i] = cadHist[i] = hrHist[i] = 0;
smo2Hist[i] = thbHist[i] = o2hbHist[i] = hhbHist[i] = 0;
}
}
void
RealtimePlotWindow::pause()
{
}
void
RealtimePlotWindow::telemetryUpdate(RealtimeData rtData)
{
// lets apply smoothing if we have to
if (rtPlot->smooth > 0) {
// Heartrate
double hr = rtData.value(RealtimeData::HeartRate);
hrtot += hr;
hrtot -= hrHist[hrindex];
hrHist[hrindex] = hr;
hrindex++;
if (hrindex >= rtPlot->smooth) hrindex = 0;
hr = hrtot / rtPlot->smooth;
rtPlot->hrData->addData(hr);
// Speed
double spd= rtData.value(RealtimeData::Speed);
spdtot += spd; spdtot -= spdHist[spdindex]; spdHist[spdindex] = spd;
spdindex++; if (spdindex >= rtPlot->smooth) spdindex = 0;
spd = spdtot / rtPlot->smooth;
if (!context->athlete->useMetricUnits) spd *= MILES_PER_KM;
rtPlot->spdData->addData(spd);
// Power
double pow = rtData.value(RealtimeData::Watts);
powtot += pow; powtot -= powHist[powindex]; powHist[powindex] = pow;
powindex++; if (powindex >= rtPlot->smooth) powindex = 0;
pow = powtot / rtPlot->smooth;
rtPlot->pwrData->addData(pow);
// Alternate Power
double alt = rtData.value(RealtimeData::AltWatts);
alttot += alt; alttot -= altHist[altindex]; altHist[altindex] = alt;
altindex++; if (altindex >= rtPlot->smooth) altindex = 0;
alt = alttot / rtPlot->smooth;
rtPlot->altPwrData->addData(alt);
// Cadence
double cad = rtData.value(RealtimeData::Cadence);
cadtot += cad; cadtot -= cadHist[cadindex]; cadHist[cadindex] = cad;
cadindex++; if (cadindex >= rtPlot->smooth) cadindex = 0;
cad = cadtot / rtPlot->smooth;
rtPlot->cadData->addData(cad);
// SmO2
double smo2 = rtData.value(RealtimeData::SmO2);
smo2tot += smo2; smo2tot -= smo2Hist[smo2index]; smo2Hist[smo2index] = smo2;
smo2index++; if (smo2index >= rtPlot->smooth) smo2index = 0;
smo2 = smo2tot / rtPlot->smooth;
rtPlot->smo2Data->addData(smo2);
// tHb
double thb = rtData.value(RealtimeData::tHb);
thbtot += thb; thbtot -= thbHist[thbindex]; thbHist[thbindex] = thb;
thbindex++; if (thbindex >= rtPlot->smooth) thbindex = 0;
thb = thbtot / rtPlot->smooth;
rtPlot->thbData->addData(thb);
// O2Hb
double o2hb = rtData.value(RealtimeData::O2Hb);
o2hbtot += o2hb; o2hbtot -= o2hbHist[o2hbindex]; o2hbHist[o2hbindex] = o2hb;
o2hbindex++; if (o2hbindex >= rtPlot->smooth) o2hbindex = 0;
o2hb = o2hbtot / rtPlot->smooth;
rtPlot->o2hbData->addData(o2hb);
// HHb
double hhb = rtData.value(RealtimeData::HHb);
hhbtot += hhb; hhbtot -= hhbHist[hhbindex]; hhbHist[hhbindex] = hhb;
hhbindex++; if (hhbindex >= rtPlot->smooth) hhbindex = 0;
hhb = hhbtot / rtPlot->smooth;
rtPlot->hhbData->addData(hhb);
// its smoothed to 30s anyway
rtPlot->pwr30Data->addData(rtData.value(RealtimeData::Watts));
} else {
rtPlot->pwrData->addData(rtData.value(RealtimeData::Watts));
rtPlot->altPwrData->addData(rtData.value(RealtimeData::AltWatts));
rtPlot->pwr30Data->addData(rtData.value(RealtimeData::Watts));
rtPlot->cadData->addData(rtData.value(RealtimeData::Cadence));
rtPlot->spdData->addData(rtData.value(RealtimeData::Speed));
rtPlot->hrData->addData(rtData.value(RealtimeData::HeartRate));
rtPlot->smo2Data->addData(rtData.value(RealtimeData::SmO2));
rtPlot->thbData->addData(rtData.value(RealtimeData::tHb));
rtPlot->o2hbData->addData(rtData.value(RealtimeData::O2Hb));
rtPlot->hhbData->addData(rtData.value(RealtimeData::HHb));
}
rtPlot->replot(); // redraw
}
void
RealtimePlotWindow::setSmoothingFromSlider()
{
// active tells us we have been triggered by
// the setSmoothingFromLineEdit which will also
// recalculates smoothing, lets not double up...
if (active) return;
else active = true;
if (rtPlot->smooth != smoothSlider->value()) {
setSmoothing(smoothSlider->value());
smoothLineEdit->setText(QString("%1").arg(rtPlot->smooth));
}
active = false;
}
void
RealtimePlotWindow::setSmoothingFromLineEdit()
{
// active tells us we have been triggered by
// the setSmoothingFromSlider which will also
// recalculates smoothing, lets not double up...
if (active) return;
else active = true;
int value = smoothLineEdit->text().toInt();
if (value != rtPlot->smooth) {
smoothSlider->setValue(value);
setSmoothing(value);
}
active = false;
}
void
RealtimePlotWindow::setShowPow30s(int value)
{
showPow30s->setChecked(value);
rtPlot->showPow30s(value);
rtPlot->replot();
}
void
RealtimePlotWindow::setShowPower(int value)
{
showPower->setChecked(value);
rtPlot->showPower(value);
rtPlot->replot();
}
void
RealtimePlotWindow::setShowSmO2(int value)
{
showSmO2->setChecked(value);
rtPlot->showSmO2(value);
rtPlot->replot();
}
void
RealtimePlotWindow::setShowtHb(int value)
{
showtHb->setChecked(value);
rtPlot->showtHb(value);
rtPlot->replot();
}
void
RealtimePlotWindow::setShowO2Hb(int value)
{
showO2Hb->setChecked(value);
rtPlot->showO2Hb(value);
rtPlot->replot();
}
void
RealtimePlotWindow::setShowHHb(int value)
{
showHHb->setChecked(value);
rtPlot->showHHb(value);
rtPlot->replot();
}
void
RealtimePlotWindow::setShowHr(int value)
{
showHr->setChecked(value);
rtPlot->showHr(value);
rtPlot->replot();
}
void
RealtimePlotWindow::setShowSpeed(int value)
{
showSpeed->setChecked(value);
rtPlot->showSpeed(value);
rtPlot->replot();
}
void
RealtimePlotWindow::setShowCad(int value)
{
showCad->setChecked(value);
rtPlot->showCad(value);
rtPlot->replot();
}
void
RealtimePlotWindow::setShowAlt(int value)
{
showAlt->setChecked(value);
rtPlot->showAlt(value);
rtPlot->replot();
}
void
RealtimePlotWindow::setSmoothing(int value)
{
hrtot = hrindex = cadtot = cadindex = spdtot = spdindex = alttot = altindex = powtot = powindex = 0;
smoothSlider->setValue(value);
rtPlot->setSmoothing(value);
}