GPS support in RideFile

RideFile data points now include lon and lat members for the longitude
degrees and latitute degrees from the source ride files. As a result
most of the RideFile readers now set longitude and latitude to zero for
each data point, except for:

* Gc Format Files - now support read/write
* Wko Format Files - now support read
* Tcx Format Files - now support read (smoothed if smart recording)

Although there are no features within GC at this point in time that use
positioning data this may change over time. Critically, as users save
files to the new GC file format whilst adding interval data it is
important that this positioning data is not discarded before new
features arrive.
This commit is contained in:
Mark Liversedge
2009-12-14 18:16:06 +00:00
committed by Sean Rhea
parent 2745291f59
commit 45d7d3c610
14 changed files with 50 additions and 31 deletions

View File

@@ -225,7 +225,7 @@ RideFile *Computrainer3dpFileReader::openRideFile(QFile & file,
// special case first data point
rideFile->appendPoint((double) ms/1000, (double) cad,
(double) hr, km, speed, 0.0, watts,
altitude, 0, 0);
altitude, 0, 0, 0, 0);
}
// while loop since an interval in the .3dp file might
// span more than one CT_EMIT_MS interval
@@ -271,6 +271,8 @@ RideFile *Computrainer3dpFileReader::openRideFile(QFile & file,
0.0,
((double) watts_sum) / CT_EMIT_MS,
interpol_alt,
0, // lon
0, // lat
0,
0);

View File

@@ -202,7 +202,7 @@ RideFile *CsvFileReader::openRideFile(QFile &file, QStringList &errors) const
watts = 0;
rideFile->appendPoint(minutes * 60.0, cad, hr, km,
kph, nm, watts, alt, interval);
kph, nm, watts, alt, 0.0, 0.0, interval);
}
++lineno;
}

View File

@@ -86,7 +86,7 @@ GcFileReader::openRideFile(QFile &file, QStringList &errors) const
bool recIntSet = false;
for (QDomElement sample = samples.firstChildElement("sample");
!sample.isNull(); sample = sample.nextSiblingElement("sample")) {
double secs, cad, hr, km, kph, nm, watts, alt;
double secs, cad, hr, km, kph, nm, watts, alt, lon, lat;
secs = sample.attribute("secs", "0.0").toDouble();
cad = sample.attribute("cad", "0.0").toDouble();
hr = sample.attribute("hr", "0.0").toDouble();
@@ -95,9 +95,11 @@ GcFileReader::openRideFile(QFile &file, QStringList &errors) const
nm = sample.attribute("nm", "0.0").toDouble();
watts = sample.attribute("watts", "0.0").toDouble();
alt = sample.attribute("alt", "0.0").toDouble();
lon = sample.attribute("lon", "0.0").toDouble();
lat = sample.attribute("lat", "0.0").toDouble();
while ((interval < intervalStops.size()) && (secs >= intervalStops[interval]))
++interval;
rideFile->appendPoint(secs, cad, hr, km, kph, nm, watts, alt, interval);
rideFile->appendPoint(secs, cad, hr, km, kph, nm, watts, alt, lon, lat, interval);
if (!recIntSet) {
rideFile->setRecIntSecs(sample.attribute("len").toDouble());
recIntSet = true;
@@ -165,6 +167,8 @@ GcFileReader::writeRideFile(const RideFile *ride, QFile &file) const
add_sample(nm);
add_sample(watts);
add_sample(alt);
add_sample(lon);
add_sample(lat);
sample.setAttribute("len", QString("%1").arg(ride->recIntSecs()));
}
}

View File

@@ -110,7 +110,7 @@ RideFile *ManualFileReader::openRideFile(QFile &file, QStringList &errors) const
interval = 0;
rideFile->appendPoint(minutes * 60.0, cad, hr, km,
kph, nm, watts, alt, interval, bs);
kph, nm, watts, alt, 0.0, 0.0, interval, bs);
rideSec = minutes * 60.0;
}

View File

@@ -200,7 +200,7 @@ this differently
next_interval = intervals.at(interval);
}
}
rideFile->appendPoint(seconds, cad, hr, km, kph, nm, watts, alt, interval);
rideFile->appendPoint(seconds, cad, hr, km, kph, nm, watts, alt, 0.0, 0.0, interval);
//fprintf(stderr, " %f, %f, %f, %f, %f, %f, %f, %d\n", seconds, cad, hr, km, kph, nm, watts, alt, interval);
}

View File

@@ -52,7 +52,7 @@ QuarqParser::incrementTime( const double new_time )
while (time_diff > seconds_from_start) {
rideFile->appendPoint(seconds_from_start, cad, hr, km,
kph, nm, watts, 0, 0, 0);
kph, nm, watts, 0, 0.0, 0.0, 0, 0);
seconds_from_start += SAMPLE_INTERVAL;
}
@@ -114,7 +114,7 @@ QuarqParser::endElement( const QString&, const QString&, const QString& qName)
// flush one last data point
if (qName == "Qollector") {
rideFile->appendPoint(seconds_from_start, cad, hr, km,
kph, nm, watts, 0, 0, 0);
kph, nm, watts, 0, 0.0, 0.0, 0, 0);
}
return TRUE;

View File

@@ -70,7 +70,7 @@ time_cb(struct tm *, time_t since_epoch, void *context)
double secs = since_epoch - state->start_since_epoch;
state->rideFile->appendPoint(secs, 0.0, 0.0,
state->last_miles * KM_PER_MILE, 0.0,
0.0, 0.0, 0.0, state->last_interval);
0.0, 0.0, 0.0, 0.0, 0.0, state->last_interval);
state->last_secs = secs;
}
@@ -84,7 +84,7 @@ data_cb(double secs, double nm, double mph, double watts, double miles, double a
ReadState *state = (ReadState*) context;
state->rideFile->appendPoint(secs, cad, hr, miles * KM_PER_MILE,
mph * KM_PER_MILE, nm, watts, alt, interval);
mph * KM_PER_MILE, nm, watts, alt, 0.0, 0.0, interval);
state->last_secs = secs;
state->last_miles = miles;
state->last_interval = interval;

View File

@@ -200,10 +200,10 @@ QStringList RideFileFactory::listRideFiles(const QDir &dir) const
void RideFile::appendPoint(double secs, double cad, double hr, double km,
double kph, double nm, double watts, double alt,
int interval, double bs)
double lon, double lat, int interval, double bs)
{
dataPoints_.append(new RideFilePoint(secs, cad, hr, km, kph,
nm, watts, alt, interval,bs));
nm, watts, alt, lon, lat, interval,bs));
dataPresent.secs |= (secs != 0);
dataPresent.cad |= (cad != 0);
dataPresent.hr |= (hr != 0);
@@ -212,5 +212,7 @@ void RideFile::appendPoint(double secs, double cad, double hr, double km,
dataPresent.nm |= (nm != 0);
dataPresent.watts |= (watts != 0);
dataPresent.alt |= (alt != 0);
dataPresent.lon |= (lon != 0);
dataPresent.lat |= (lat != 0);
dataPresent.interval |= (interval != 0);
}

View File

@@ -43,24 +43,24 @@
struct RideFilePoint
{
double secs, cad, hr, km, kph, nm, watts, alt;
double secs, cad, hr, km, kph, nm, watts, alt, lon, lat;;
int interval;
double bs; // to init in order
RideFilePoint() : secs(0.0), cad(0.0), hr(0.0), km(0.0), kph(0.0),
nm(0.0), watts(0.0), alt(0.0), interval(0), bs(0.0) {}
nm(0.0), watts(0.0), alt(0.0), lon(0.0), lat(0.0), interval(0), bs(0.0) {}
RideFilePoint(double secs, double cad, double hr, double km, double kph,
double nm, double watts, double alt, int interval, double bs) :
double nm, double watts, double alt, double lon, double lat, int interval, double bs) :
secs(secs), cad(cad), hr(hr), km(km), kph(kph), nm(nm),
watts(watts), alt(alt), interval(interval), bs(bs) {}
watts(watts), alt(alt), lon(lon), lat(lat), interval(interval), bs(bs) {}
};
struct RideFileDataPresent
{
bool secs, cad, hr, km, kph, nm, watts, alt, interval;
bool secs, cad, hr, km, kph, nm, watts, alt, lon, lat, interval;
// whether non-zero data of each field is present
RideFileDataPresent():
secs(false), cad(false), hr(false), km(false),
kph(false), nm(false), watts(false), alt(false), interval(false) {}
kph(false), nm(false), watts(false), alt(false), lon(false), lat(false), interval(false) {}
};
struct RideFileInterval
@@ -107,7 +107,7 @@ class RideFile
void appendPoint(double secs, double cad, double hr, double km,
double kph, double nm, double watts, double alt,
int interval, double bs=0.0);
double lon, double lat, int interval, double bs=0.0);
const QList<RideFileInterval> &intervals() const { return intervals_; }
void addInterval(double start, double stop, const QString &name) {

View File

@@ -139,7 +139,7 @@ SplitRideDialog::CreateNewRideFile(const RideFile *ride, int nRecStart, int nRec
{
RideFilePoint *pPoint = ride->dataPoints().at(nItem);
newRideFile->appendPoint(pPoint->secs-pointStart->secs, pPoint->cad, pPoint->hr, pPoint->km - pointStart->km,
pPoint->kph, pPoint->nm, pPoint->watts, pPoint->alt, pPoint->interval-pointStart->interval);
pPoint->kph, pPoint->nm, pPoint->watts, pPoint->alt, pPoint->lon, pPoint->lat, pPoint->interval-pointStart->interval);
}
QString fileName;

View File

@@ -202,7 +202,7 @@ RideFile *SrmFileReader::openRideFile(QFile &file, QStringList &errorStrings) co
km += result->recIntSecs() * kph / 3600.0;
double nm = watts / 2.0 / PI / cad * 60.0;
result->appendPoint(secs, cad, hr, km, kph, nm, watts, alt, interval);
result->appendPoint(secs, cad, hr, km, kph, nm, watts, alt, 0.0, 0.0, interval);
++blkidx;
if ((blkidx == blockhdrs[blknum].chunkcnt) && (blknum + 1 < blockcnt)) {

View File

@@ -89,6 +89,14 @@ TcxParser::endElement( const QString&, const QString&, const QString& qName)
{
alt = buffer.toDouble();
}
else if (qName == "LongitudeDegrees")
{
lon = buffer.toDouble();
}
else if (qName == "LatitudeDegrees")
{
lat = buffer.toDouble();
}
else if (qName == "Trackpoint")
{
// nh - there are track points that don't have any distance info. We need to ignore them
@@ -135,7 +143,7 @@ TcxParser::endElement( const QString&, const QString&, const QString& qName)
if(rideFile->dataPoints().empty()) {
// first point
rideFile->appendPoint(secs, cadence, hr, distance,
speed, torque, power, alt, lap);
speed, torque, power, alt, lon, lat, lap);
}
else {
// assumption that the change in ride is linear... :)
@@ -148,10 +156,12 @@ TcxParser::endElement( const QString&, const QString&, const QString& qName)
double deltaTorque = torque - prevPoint->nm;
double deltaPower = power - prevPoint->watts;
double deltaAlt = alt - prevPoint->alt;
double deltaLon = lon - prevPoint->lon;
double deltaLat = lat - prevPoint->lat;
if(deltaSecs == 1) {
// no smart recording, just insert the data
rideFile->appendPoint(secs, cadence, hr, distance,
speed, torque, power, alt, lap);
speed, torque, power, alt, lon, lat, lap);
}
else {
for(int i = 1; i <= deltaSecs; i++) {
@@ -161,6 +171,8 @@ TcxParser::endElement( const QString&, const QString&, const QString& qName)
kph = kph > 0.35 ? kph : 0;
double cad = prevPoint->cad + (deltaCad * weight);
cad = cad > 0.35 ? cad : 0;
double lat = prevPoint->lat + (deltaLat * weight);
double lon = prevPoint->lon + (deltaLon * weight);
rideFile->appendPoint(
prevPoint->secs + (deltaSecs * weight),
prevPoint->cad + (deltaCad * weight),
@@ -170,6 +182,8 @@ TcxParser::endElement( const QString&, const QString&, const QString& qName)
prevPoint->nm + (deltaTorque * weight),
prevPoint->watts + (deltaPower * weight),
prevPoint->alt + (deltaAlt * weight),
lon, // lon
lat, // lat
lap);
}
prevPoint = rideFile->dataPoints().back();

View File

@@ -54,6 +54,8 @@ private:
double hr;
double lastAltitude;
double alt;
double lat;
double lon;
};
#endif // _TcxParser_h

View File

@@ -39,7 +39,7 @@
// global variable called WKO_HOMEDIR.
//
// 2. UNUSED GRAPHS
// Windspeed, Temperature, GPS and other data is available from WKO
// Windspeed, Temperature, Slope et al are available from WKO
// data files but is discarded currently since it is not supported by RideFile
//
// 3. GOTO
@@ -50,10 +50,6 @@
// Shared between a number of functions to simplify parameter passing and avoid
// refactoring as a class.
//
// 5. METRIC/IMPERIAL CONVERSION
// Code is available to support conversion from WKO standard of all metric but it is not
// enabled -- need to understand how metric/imperial conversion is supposed to be managed
//
#include "WkoRideFile.h"
#include <QRegExp>
@@ -160,7 +156,7 @@ RideFile *WkoFileReader::openRideFile(QFile &file, QStringList &errors) const
WKO_UCHAR *WkoParseRawData(WKO_UCHAR *fb, RideFile *rideFile, QStringList &errors)
{
WKO_ULONG WKO_xormasks[32]; // xormasks used all over
double cad, hr, km, kph, nm, watts, alt, interval;
double cad=0, hr=0, km=0, kph=0, nm=0, watts=0, alt=0, lon=0, lat=0, interval=0;
int isnull=0;
WKO_ULONG records, data;
@@ -367,7 +363,6 @@ WKO_UCHAR *WkoParseRawData(WKO_UCHAR *fb, RideFile *rideFile, QStringList &error
case 'G' : /* two longs */
{
signed long llat, llon;
double lat,lon;
char slat[20], slon[20];
// stored 2s complement
@@ -420,7 +415,7 @@ WKO_UCHAR *WkoParseRawData(WKO_UCHAR *fb, RideFile *rideFile, QStringList &error
// !! needs to be modified to support the new alt patch
rideFile->appendPoint((double)rtime/1000, cad, hr, km,
kph, nm, watts, alt, 0);
kph, nm, watts, alt, lon, lat, 0);
}
// increment time - even for null records (perhaps especially for null