1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-30 22:51:16 +01:00

Added automatic pause detection

This commit is contained in:
Martin Tůma 2019-11-13 08:27:54 +01:00
parent bb238f4c7e
commit 258a9b0201
6 changed files with 78 additions and 8 deletions

View File

@ -949,6 +949,7 @@ void GUI::openOptions()
SET_TRACK_OPTION(cadenceFilter, setCadenceFilter); SET_TRACK_OPTION(cadenceFilter, setCadenceFilter);
SET_TRACK_OPTION(powerFilter, setPowerFilter); SET_TRACK_OPTION(powerFilter, setPowerFilter);
SET_TRACK_OPTION(outlierEliminate, setOutlierElimination); SET_TRACK_OPTION(outlierEliminate, setOutlierElimination);
SET_TRACK_OPTION(automaticPause, setAutomaticPause);
SET_TRACK_OPTION(pauseSpeed, setPauseSpeed); SET_TRACK_OPTION(pauseSpeed, setPauseSpeed);
SET_TRACK_OPTION(pauseInterval, setPauseInterval); SET_TRACK_OPTION(pauseInterval, setPauseInterval);
SET_TRACK_OPTION(useReportedSpeed, useReportedSpeed); SET_TRACK_OPTION(useReportedSpeed, useReportedSpeed);
@ -1798,6 +1799,8 @@ void GUI::writeSettings()
settings.setValue(POWER_FILTER_SETTING, _options.powerFilter); settings.setValue(POWER_FILTER_SETTING, _options.powerFilter);
if (_options.outlierEliminate != OUTLIER_ELIMINATE_DEFAULT) if (_options.outlierEliminate != OUTLIER_ELIMINATE_DEFAULT)
settings.setValue(OUTLIER_ELIMINATE_SETTING, _options.outlierEliminate); settings.setValue(OUTLIER_ELIMINATE_SETTING, _options.outlierEliminate);
if (_options.automaticPause != AUTOMATIC_PAUSE_DEFAULT)
settings.setValue(AUTOMATIC_PAUSE_SETTING, _options.automaticPause);
if (_options.pauseSpeed != PAUSE_SPEED_DEFAULT) if (_options.pauseSpeed != PAUSE_SPEED_DEFAULT)
settings.setValue(PAUSE_SPEED_SETTING, _options.pauseSpeed); settings.setValue(PAUSE_SPEED_SETTING, _options.pauseSpeed);
if (_options.pauseInterval != PAUSE_INTERVAL_DEFAULT) if (_options.pauseInterval != PAUSE_INTERVAL_DEFAULT)
@ -2072,6 +2075,8 @@ void GUI::readSettings()
USE_REPORTED_SPEED_DEFAULT).toBool(); USE_REPORTED_SPEED_DEFAULT).toBool();
_options.dataUseDEM = settings.value(DATA_USE_DEM_SETTING, _options.dataUseDEM = settings.value(DATA_USE_DEM_SETTING,
DATA_USE_DEM_DEFAULT).toBool(); DATA_USE_DEM_DEFAULT).toBool();
_options.automaticPause = settings.value(AUTOMATIC_PAUSE_SETTING,
AUTOMATIC_PAUSE_DEFAULT).toBool();
_options.pauseInterval = settings.value(PAUSE_INTERVAL_SETTING, _options.pauseInterval = settings.value(PAUSE_INTERVAL_SETTING,
PAUSE_INTERVAL_DEFAULT).toInt(); PAUSE_INTERVAL_DEFAULT).toInt();
_options.poiRadius = settings.value(POI_RADIUS_SETTING, POI_RADIUS_DEFAULT) _options.poiRadius = settings.value(POI_RADIUS_SETTING, POI_RADIUS_DEFAULT)
@ -2153,6 +2158,7 @@ void GUI::readSettings()
Track::setCadenceFilter(_options.cadenceFilter); Track::setCadenceFilter(_options.cadenceFilter);
Track::setPowerFilter(_options.powerFilter); Track::setPowerFilter(_options.powerFilter);
Track::setOutlierElimination(_options.outlierEliminate); Track::setOutlierElimination(_options.outlierEliminate);
Track::setAutomaticPause(_options.automaticPause);
Track::setPauseSpeed(_options.pauseSpeed); Track::setPauseSpeed(_options.pauseSpeed);
Track::setPauseInterval(_options.pauseInterval); Track::setPauseInterval(_options.pauseInterval);
Track::useReportedSpeed(_options.useReportedSpeed); Track::useReportedSpeed(_options.useReportedSpeed);

View File

@ -37,6 +37,12 @@ static QFrame *line()
#endif // Q_OS_MAC #endif // Q_OS_MAC
void OptionsDialog::automaticPauseDetectionSet(bool set)
{
_pauseInterval->setEnabled(!set);
_pauseSpeed->setEnabled(!set);
}
QWidget *OptionsDialog::createMapPage() QWidget *OptionsDialog::createMapPage()
{ {
_projection = new LimitedComboBox(200); _projection = new LimitedComboBox(200);
@ -343,10 +349,18 @@ QWidget *OptionsDialog::createDataPage()
filterTab->setLayout(filterTabLayout); filterTab->setLayout(filterTabLayout);
_automaticPause = new QRadioButton(tr("Automatic"));
_manualPause = new QRadioButton(tr("User defined"));
if (_options->automaticPause)
_automaticPause->setChecked(true);
else
_manualPause->setChecked(true);
_pauseSpeed = new QDoubleSpinBox(); _pauseSpeed = new QDoubleSpinBox();
_pauseSpeed->setDecimals(1); _pauseSpeed->setDecimals(1);
_pauseSpeed->setSingleStep(0.1); _pauseSpeed->setSingleStep(0.1);
_pauseSpeed->setMinimum(0.1); _pauseSpeed->setMinimum(0.1);
_pauseSpeed->setEnabled(_manualPause->isChecked());
if (_options->units == Imperial) { if (_options->units == Imperial) {
_pauseSpeed->setValue(_options->pauseSpeed * MS2MIH); _pauseSpeed->setValue(_options->pauseSpeed * MS2MIH);
_pauseSpeed->setSuffix(UNIT_SPACE + tr("mi/h")); _pauseSpeed->setSuffix(UNIT_SPACE + tr("mi/h"));
@ -361,10 +375,23 @@ QWidget *OptionsDialog::createDataPage()
_pauseInterval->setMinimum(1); _pauseInterval->setMinimum(1);
_pauseInterval->setSuffix(UNIT_SPACE + tr("s")); _pauseInterval->setSuffix(UNIT_SPACE + tr("s"));
_pauseInterval->setValue(_options->pauseInterval); _pauseInterval->setValue(_options->pauseInterval);
_pauseInterval->setEnabled(_manualPause->isChecked());
QFormLayout *pauseLayout = new QFormLayout(); connect(_automaticPause, SIGNAL(toggled(bool)), this,
pauseLayout->addRow(tr("Minimal speed:"), _pauseSpeed); SLOT(automaticPauseDetectionSet(bool)));
pauseLayout->addRow(tr("Minimal duration:"), _pauseInterval);
QHBoxLayout *pauseTypeLayout = new QHBoxLayout();
pauseTypeLayout->addWidget(_automaticPause);
pauseTypeLayout->addWidget(_manualPause);
pauseTypeLayout->addStretch();
QFormLayout *pauseValuesLayout = new QFormLayout();
pauseValuesLayout->addRow(tr("Minimal speed:"), _pauseSpeed);
pauseValuesLayout->addRow(tr("Minimal duration:"), _pauseInterval);
QVBoxLayout *pauseLayout = new QVBoxLayout();
pauseLayout->addLayout(pauseTypeLayout);
pauseLayout->addLayout(pauseValuesLayout);
QWidget *pauseTab = new QWidget(); QWidget *pauseTab = new QWidget();
pauseTab->setLayout(pauseLayout); pauseTab->setLayout(pauseLayout);
@ -679,6 +706,7 @@ void OptionsDialog::accept()
_options->cadenceFilter = _cadenceFilter->value(); _options->cadenceFilter = _cadenceFilter->value();
_options->powerFilter = _powerFilter->value(); _options->powerFilter = _powerFilter->value();
_options->outlierEliminate = _outlierEliminate->isChecked(); _options->outlierEliminate = _outlierEliminate->isChecked();
_options->automaticPause = _automaticPause->isChecked();
qreal pauseSpeed = (_options->units == Imperial) qreal pauseSpeed = (_options->units == Imperial)
? _pauseSpeed->value() / MS2MIH : (_options->units == Nautical) ? _pauseSpeed->value() / MS2MIH : (_options->units == Nautical)
? _pauseSpeed->value() / MS2KN : _pauseSpeed->value() / MS2KMH; ? _pauseSpeed->value() / MS2KN : _pauseSpeed->value() / MS2KMH;

View File

@ -49,6 +49,7 @@ struct Options {
int cadenceFilter; int cadenceFilter;
int powerFilter; int powerFilter;
bool outlierEliminate; bool outlierEliminate;
bool automaticPause;
qreal pauseSpeed; qreal pauseSpeed;
int pauseInterval; int pauseInterval;
bool useReportedSpeed; bool useReportedSpeed;
@ -86,6 +87,9 @@ public slots:
public: public:
OptionsDialog(Options *options, QWidget *parent = 0); OptionsDialog(Options *options, QWidget *parent = 0);
private slots:
void automaticPauseDetectionSet(bool set);
private: private:
QWidget *createMapPage(); QWidget *createMapPage();
QWidget *createAppearancePage(); QWidget *createAppearancePage();
@ -129,6 +133,9 @@ private:
OddSpinBox *_cadenceFilter; OddSpinBox *_cadenceFilter;
OddSpinBox *_powerFilter; OddSpinBox *_powerFilter;
QCheckBox *_outlierEliminate; QCheckBox *_outlierEliminate;
QRadioButton *_automaticPause;
QRadioButton *_manualPause;
QDoubleSpinBox *_pauseSpeed; QDoubleSpinBox *_pauseSpeed;
QSpinBox *_pauseInterval; QSpinBox *_pauseInterval;
QRadioButton *_computedSpeed; QRadioButton *_computedSpeed;

View File

@ -135,6 +135,8 @@
#define POWER_FILTER_DEFAULT 3 #define POWER_FILTER_DEFAULT 3
#define OUTLIER_ELIMINATE_SETTING "outlierEliminate" #define OUTLIER_ELIMINATE_SETTING "outlierEliminate"
#define OUTLIER_ELIMINATE_DEFAULT true #define OUTLIER_ELIMINATE_DEFAULT true
#define AUTOMATIC_PAUSE_SETTING "automaticPause"
#define AUTOMATIC_PAUSE_DEFAULT true
#define PAUSE_SPEED_SETTING "pauseSpeed" #define PAUSE_SPEED_SETTING "pauseSpeed"
#define PAUSE_SPEED_DEFAULT 0.5 /* m/s */ #define PAUSE_SPEED_DEFAULT 0.5 /* m/s */
#define PAUSE_INTERVAL_SETTING "pauseInterval" #define PAUSE_INTERVAL_SETTING "pauseInterval"

View File

@ -7,6 +7,7 @@ int Track::_heartRateWindow = 3;
int Track::_cadenceWindow = 3; int Track::_cadenceWindow = 3;
int Track::_powerWindow = 3; int Track::_powerWindow = 3;
bool Track::_automaticPause = true;
qreal Track::_pauseSpeed = 0.5; qreal Track::_pauseSpeed = 0.5;
int Track::_pauseInterval = 10; int Track::_pauseInterval = 10;
@ -14,6 +15,16 @@ bool Track::_outlierEliminate = true;
bool Track::_useReportedSpeed = false; bool Track::_useReportedSpeed = false;
static qreal avg(const QVector<qreal> &v)
{
qreal sum = 0;
for (int i = 0; i < v.size(); i++)
sum += v.at(i);
return sum/v.size();
}
static qreal median(QVector<qreal> &v) static qreal median(QVector<qreal> &v)
{ {
qSort(v.begin(), v.end()); qSort(v.begin(), v.end());
@ -24,8 +35,7 @@ static qreal MAD(QVector<qreal> &v, qreal m)
{ {
for (int i = 0; i < v.size(); i++) for (int i = 0; i < v.size(); i++)
v[i] = qAbs(v.at(i) - m); v[i] = qAbs(v.at(i) - m);
qSort(v.begin(), v.end()); return median(v);
return v.at(v.size() / 2);
} }
static QSet<int> eliminate(const QVector<qreal> &v) static QSet<int> eliminate(const QVector<qreal> &v)
@ -132,15 +142,30 @@ Track::Track(const TrackData &data) : _data(data), _pause(0)
} }
} }
if (!hasTime)
continue;
// get stop-points + pause duration // get stop-points + pause duration
int pauseInterval;
qreal pauseSpeed;
if (_automaticPause) {
pauseSpeed = (avg(seg.speed) > 2.8) ? 0.55 : 0.15;
pauseInterval = 10;
} else {
pauseSpeed = _pauseSpeed;
pauseInterval = _pauseInterval;
}
int ss = 0, la = 0; int ss = 0, la = 0;
for (int j = 1; j < seg.time.size(); j++) { for (int j = 1; j < seg.time.size(); j++) {
if (seg.speed.at(j) > _pauseSpeed) if (seg.speed.at(j) > pauseSpeed)
ss = -1; ss = -1;
else if (ss < 0) else if (ss < 0)
ss = j; ss = j;
if (ss >= 0 && seg.time.at(j) > seg.time.at(ss) + _pauseInterval) { if (ss >= 0 && seg.time.at(j) > seg.time.at(ss) + pauseInterval) {
int l = qMax(ss, la); int l = qMax(ss, la);
_pause += seg.time.at(j) - seg.time.at(l); _pause += seg.time.at(j) - seg.time.at(l);
for (int k = l; k <= j; k++) for (int k = l; k <= j; k++)
@ -149,7 +174,7 @@ Track::Track(const TrackData &data) : _data(data), _pause(0)
} }
} }
if (!_outlierEliminate || !hasTime) if (!_outlierEliminate)
continue; continue;

View File

@ -41,6 +41,7 @@ public:
static void setHeartRateFilter(int window) {_heartRateWindow = window;} static void setHeartRateFilter(int window) {_heartRateWindow = window;}
static void setCadenceFilter(int window) {_cadenceWindow = window;} static void setCadenceFilter(int window) {_cadenceWindow = window;}
static void setPowerFilter(int window) {_powerWindow = window;} static void setPowerFilter(int window) {_powerWindow = window;}
static void setAutomaticPause(bool set) {_automaticPause = set;}
static void setPauseSpeed(qreal speed) {_pauseSpeed = speed;} static void setPauseSpeed(qreal speed) {_pauseSpeed = speed;}
static void setPauseInterval(int interval) {_pauseInterval = interval;} static void setPauseInterval(int interval) {_pauseInterval = interval;}
static void setOutlierElimination(bool eliminate) static void setOutlierElimination(bool eliminate)
@ -68,6 +69,7 @@ private:
static int _heartRateWindow; static int _heartRateWindow;
static int _cadenceWindow; static int _cadenceWindow;
static int _powerWindow; static int _powerWindow;
static bool _automaticPause;
static qreal _pauseSpeed; static qreal _pauseSpeed;
static int _pauseInterval; static int _pauseInterval;
static bool _useReportedSpeed; static bool _useReportedSpeed;