mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-24 03:35:53 +01:00
Use NMEA speed data if available
Now using median speed filtering
This commit is contained in:
parent
da42f3ab33
commit
405c1d2dde
40
src/gpx.cpp
40
src/gpx.cpp
@ -3,9 +3,12 @@
|
|||||||
#include "ll.h"
|
#include "ll.h"
|
||||||
#include "gpx.h"
|
#include "gpx.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
|
||||||
|
#define ALPHA 0.5
|
||||||
|
#define WINDOW 5
|
||||||
|
|
||||||
#define ALPHA_E 0.5
|
|
||||||
#define ALPHA_S 0.1
|
|
||||||
|
|
||||||
bool GPX::loadFile(const QString &fileName)
|
bool GPX::loadFile(const QString &fileName)
|
||||||
{
|
{
|
||||||
@ -38,14 +41,25 @@ void GPX::elevationGraph(QVector<QPointF> &graph) const
|
|||||||
for (int i = 1; i < _data.size(); i++) {
|
for (int i = 1; i < _data.size(); i++) {
|
||||||
dist += llDistance(_data.at(i).coordinates, _data.at(i-1).coordinates);
|
dist += llDistance(_data.at(i).coordinates, _data.at(i-1).coordinates);
|
||||||
dh = _data.at(i).elevation;
|
dh = _data.at(i).elevation;
|
||||||
acc = (i == 1) ? dh : (ALPHA_E * dh) + (1.0 - ALPHA_E) * acc;
|
acc = (i == 1) ? dh : (ALPHA * dh) + (1.0 - ALPHA) * acc;
|
||||||
graph.append(QPointF(dist, acc));
|
graph.append(QPointF(dist, acc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool lt(const QPointF &p1, const QPointF &p2)
|
||||||
|
{
|
||||||
|
return p1.y() < p2.y();
|
||||||
|
}
|
||||||
|
|
||||||
|
static qreal median(QVector<QPointF> v)
|
||||||
|
{
|
||||||
|
qSort(v.begin(), v.end(), lt);
|
||||||
|
return v.at(v.size() / 2).y();
|
||||||
|
}
|
||||||
|
|
||||||
void GPX::speedGraph(QVector<QPointF> &graph) const
|
void GPX::speedGraph(QVector<QPointF> &graph) const
|
||||||
{
|
{
|
||||||
qreal dist = 0, v, ds, dt, acc;
|
qreal dist = 0, v, ds, dt;
|
||||||
|
|
||||||
if (!_data.size())
|
if (!_data.size())
|
||||||
return;
|
return;
|
||||||
@ -54,13 +68,21 @@ void GPX::speedGraph(QVector<QPointF> &graph) const
|
|||||||
for (int i = 1; i < _data.size(); i++) {
|
for (int i = 1; i < _data.size(); i++) {
|
||||||
ds = llDistance(_data.at(i).coordinates, _data.at(i-1).coordinates);
|
ds = llDistance(_data.at(i).coordinates, _data.at(i-1).coordinates);
|
||||||
dt = _data.at(i-1).timestamp.msecsTo(_data.at(i).timestamp) / 1000.0;
|
dt = _data.at(i-1).timestamp.msecsTo(_data.at(i).timestamp) / 1000.0;
|
||||||
if (dt == 0)
|
|
||||||
continue;
|
|
||||||
dist += ds;
|
dist += ds;
|
||||||
v = ds / dt;
|
|
||||||
acc = (i == 1) ? v : (ALPHA_S * v) + (1.0 - ALPHA_S) * acc;
|
if (_data.at(i).speed < 0) {
|
||||||
graph.append(QPointF(dist, acc));
|
if (dt == 0)
|
||||||
|
continue;
|
||||||
|
v = ds / dt;
|
||||||
|
} else
|
||||||
|
v = _data.at(i).speed;
|
||||||
|
|
||||||
|
graph.append(QPointF(dist, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (graph.size() > WINDOW)
|
||||||
|
for (int i = WINDOW/2; i < graph.size() - WINDOW/2; i++)
|
||||||
|
graph[i].setY(median(graph.mid(i - WINDOW/2, WINDOW)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPX::track(QVector<QPointF> &track) const
|
void GPX::track(QVector<QPointF> &track) const
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
|
||||||
|
void Parser::handleExtensionData(QVector<TrackPoint> &data,
|
||||||
|
QStringRef element, const QString &value)
|
||||||
|
{
|
||||||
|
if (element == "speed")
|
||||||
|
data.last().speed = value.toDouble();
|
||||||
|
}
|
||||||
|
|
||||||
void Parser::handleTrekPointData(QVector<TrackPoint> &data,
|
void Parser::handleTrekPointData(QVector<TrackPoint> &data,
|
||||||
QStringRef element, const QString &value)
|
QStringRef element, const QString &value)
|
||||||
@ -19,11 +28,23 @@ void Parser::handleTrekPointAttributes(QVector<TrackPoint> &data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Parser::extensions(QVector<TrackPoint> &data)
|
||||||
|
{
|
||||||
|
while (_reader.readNextStartElement()) {
|
||||||
|
if (_reader.name() == "speed")
|
||||||
|
handleExtensionData(data, _reader.name(), _reader.readElementText());
|
||||||
|
else
|
||||||
|
_reader.skipCurrentElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Parser::trekPointData(QVector<TrackPoint> &data)
|
void Parser::trekPointData(QVector<TrackPoint> &data)
|
||||||
{
|
{
|
||||||
while (_reader.readNextStartElement()) {
|
while (_reader.readNextStartElement()) {
|
||||||
if (_reader.name() == "ele" || _reader.name() == "time")
|
if (_reader.name() == "ele" || _reader.name() == "time")
|
||||||
handleTrekPointData(data, _reader.name(), _reader.readElementText());
|
handleTrekPointData(data, _reader.name(), _reader.readElementText());
|
||||||
|
else if (_reader.name() == "extensions")
|
||||||
|
extensions(data);
|
||||||
else
|
else
|
||||||
_reader.skipCurrentElement();
|
_reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,9 @@ struct TrackPoint
|
|||||||
QPointF coordinates;
|
QPointF coordinates;
|
||||||
QDateTime timestamp;
|
QDateTime timestamp;
|
||||||
qreal elevation;
|
qreal elevation;
|
||||||
|
qreal speed;
|
||||||
|
|
||||||
|
TrackPoint() {speed = -1;}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Parser
|
class Parser
|
||||||
@ -23,12 +26,15 @@ private:
|
|||||||
void gpx(QVector<TrackPoint> &data);
|
void gpx(QVector<TrackPoint> &data);
|
||||||
void trek(QVector<TrackPoint> &data);
|
void trek(QVector<TrackPoint> &data);
|
||||||
void trekPoints(QVector<TrackPoint> &data);
|
void trekPoints(QVector<TrackPoint> &data);
|
||||||
|
void extensions(QVector<TrackPoint> &data);
|
||||||
void trekPointData(QVector<TrackPoint> &data);
|
void trekPointData(QVector<TrackPoint> &data);
|
||||||
|
|
||||||
void handleTrekPointAttributes(QVector<TrackPoint> &data,
|
void handleTrekPointAttributes(QVector<TrackPoint> &data,
|
||||||
const QXmlStreamAttributes &attr);
|
const QXmlStreamAttributes &attr);
|
||||||
void handleTrekPointData(QVector<TrackPoint> &data, QStringRef element,
|
void handleTrekPointData(QVector<TrackPoint> &data, QStringRef element,
|
||||||
const QString &value);
|
const QString &value);
|
||||||
|
void handleExtensionData(QVector<TrackPoint> &data, QStringRef element,
|
||||||
|
const QString &value);
|
||||||
|
|
||||||
QXmlStreamReader _reader;
|
QXmlStreamReader _reader;
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "speedgraph.h"
|
#include "speedgraph.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
SpeedGraph::SpeedGraph()
|
SpeedGraph::SpeedGraph()
|
||||||
{
|
{
|
||||||
_max = 0;
|
_max = 0;
|
||||||
@ -14,26 +16,35 @@ SpeedGraph::SpeedGraph()
|
|||||||
|
|
||||||
void SpeedGraph::loadData(const QVector<QPointF> &data)
|
void SpeedGraph::loadData(const QVector<QPointF> &data)
|
||||||
{
|
{
|
||||||
qreal max = 0, sum = 0, avg, distance, w;
|
qreal max = 0, sum = 0, w = 0, avg;
|
||||||
|
qreal dist;
|
||||||
|
|
||||||
|
if (data.size() < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dist = data.at(data.size() - 1).x() - data.at(0).x();
|
||||||
|
|
||||||
distance = (data.at(data.size() - 1).x() - data.at(0).x());
|
|
||||||
|
|
||||||
for (int i = 1; i < data.size(); i++) {
|
for (int i = 1; i < data.size(); i++) {
|
||||||
qreal val = data.at(i).y();
|
QPointF cur = data.at(i);
|
||||||
|
QPointF prev = data.at(i-1);
|
||||||
|
qreal ds = cur.x() - prev.x();
|
||||||
|
|
||||||
sum += val;
|
if (cur.y() == 0)
|
||||||
|
continue;
|
||||||
|
sum += ds;
|
||||||
|
w += ds / cur.y();
|
||||||
|
|
||||||
if (val > max)
|
max = qMax(max, cur.y());
|
||||||
max = val;
|
|
||||||
}
|
}
|
||||||
avg = sum / data.size();
|
avg = sum / w;
|
||||||
|
|
||||||
_avg.append(QPointF(avg, distance));
|
_avg.append(QPointF(dist, avg));
|
||||||
|
|
||||||
sum = 0; w = 0;
|
sum = 0; w = 0;
|
||||||
for (QList<QPointF>::iterator it = _avg.begin(); it != _avg.end(); it++) {
|
for (QList<QPointF>::iterator it = _avg.begin(); it != _avg.end(); it++) {
|
||||||
sum += it->x() * it->y();
|
sum += it->y() * it->x();
|
||||||
w += it->y();
|
w += it->x();
|
||||||
}
|
}
|
||||||
avg = sum / w;
|
avg = sum / w;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user