コード例 #1
0
bool GPSDataParser::loadGPXFile(const KUrl& url)
{
    QFile gpxfile(url.path());

    if (!gpxfile.open(QIODevice::ReadOnly))
        return false;

    QDomDocument gpxDoc("gpx");
    if (!gpxDoc.setContent(&gpxfile))
        return false;

    QDomElement gpxDocElem = gpxDoc.documentElement();
    if (gpxDocElem.tagName()!="gpx")
        return false;

    for (QDomNode nTrk = gpxDocElem.firstChild();
         !nTrk.isNull(); nTrk = nTrk.nextSibling())
    {
        QDomElement trkElem = nTrk.toElement();
        if (trkElem.isNull()) continue;
        if (trkElem.tagName() != "trk") continue;

        for (QDomNode nTrkseg = trkElem.firstChild();
            !nTrkseg.isNull(); nTrkseg = nTrkseg.nextSibling())
        {
            QDomElement trksegElem = nTrkseg.toElement();
            if (trksegElem.isNull()) continue;
            if (trksegElem.tagName() != "trkseg") continue;

            for (QDomNode nTrkpt = trksegElem.firstChild();
                !nTrkpt.isNull(); nTrkpt = nTrkpt.nextSibling())
            {
                QDomElement trkptElem = nTrkpt.toElement();
                if (trkptElem.isNull()) continue;
                if (trkptElem.tagName() != "trkpt") continue;

                QDateTime ptDateTime;
                double    ptAltitude  = 0.0;
                double    ptLatitude  = 0.0;
                double    ptLongitude = 0.0;

                // Get GPS position. If not available continue to next point.
                QString lat = trkptElem.attribute("lat");
                QString lon = trkptElem.attribute("lon");
                if (lat.isEmpty() || lon.isEmpty()) continue;

                ptLatitude  = lat.toDouble();
                ptLongitude = lon.toDouble();

                // Get metadata of track point (altitude and time stamp)
                for (QDomNode nTrkptMeta = trkptElem.firstChild();
                    !nTrkptMeta.isNull(); nTrkptMeta = nTrkptMeta.nextSibling())
                {
                    QDomElement trkptMetaElem = nTrkptMeta.toElement();
                    if (trkptMetaElem.isNull()) continue;
                    if (trkptMetaElem.tagName() == QString("time"))
                    {
                        // Get GPS point time stamp. If not available continue to next point.
                        QString time = trkptMetaElem.text();
                        if (time.isEmpty()) continue;
                        ptDateTime = QDateTime::fromString(time, Qt::ISODate);
                    }
                    if (trkptMetaElem.tagName() == QString("ele"))
                    {
                        // Get GPS point altitude. If not available continue to next point.
                        QString ele = trkptMetaElem.text();
                        if (!ele.isEmpty())
                            ptAltitude  = ele.toDouble();
                    }
                }

                if (ptDateTime.isNull())
                    continue;

                GPSDataContainer gpsData(ptAltitude, ptLatitude, ptLongitude, false);
                m_GPSDataMap.insert( ptDateTime, gpsData );
            }
        }
    }

    kDebug( 51001 ) << "GPX File " << url.fileName()
                    << " parsed with " << numPoints()
                    << " points extracted" << endl;
    return true;
}
コード例 #2
0
RideFile *PolarFileReader::openRideFile(QFile &file, QStringList &errors, QList<RideFile*>*rideList) const
{
/*
* Polar HRM file format documented at www.polar.fi/files/Polar_HRM_file%20format.pdf
*/
    QRegExp metricUnits("(km|kph|km/h)", Qt::CaseInsensitive);
    QRegExp englishUnits("(miles|mph|mp/h)", Qt::CaseInsensitive);
    bool metric = true;

    QDate date;
    QString note("");

    double version=0;
    int monitor=0;

    double seconds=0;
    double distance=0;
    int interval = 0;
    int StartDelay = 0;

    bool speed = false;
    bool cadence = false;
    bool altitude = false;
    bool power = false;
    bool balance = false;
    bool haveGPX = false;
    int igpx = 0;
    int ngpx = 0;
    double lat=0,lon=0;
    int recInterval = 1;

    // Read Polar GPX file (if exist with same name as hrm file).
    RideFile *gpxresult=NULL;
    RideFilePoint *p;
    QString suffix = file.fileName();
    int dot = suffix.lastIndexOf(".");
    assert(dot >= 0);
    QFile gpxfile(suffix.left(dot)+".gpx");
    haveGPX = gpxfile.exists();

    if (haveGPX) {
        GpxFileReader reader;
        gpxresult = reader.openRideFile(gpxfile,errors,rideList);
        ngpx = gpxresult->dataPoints().count();
    }

    if (!file.open(QFile::ReadOnly)) {
        errors << ("Could not open ride file: \""
                   + file.fileName() + "\"");
        return NULL;
    }

    int lineno = 1;


    double next_interval=0;
    QList<double> intervals;

    QTextStream is(&file);
    RideFile *rideFile = new RideFile();
    QString section = NULL;

    while (!is.atEnd()) {
        // the readLine() method doesn't handle old Macintosh CR line endings
        // this workaround will load the the entire file if it has CR endings
        // then split and loop through each line
        // otherwise, there will be nothing to split and it will read each line as expected.
        QString linesIn = is.readLine();
        QStringList lines = linesIn.split('\r');
        // workaround for empty lines
        if(lines.size() == 0) {
            lineno++;
            continue;
        }
        for (int li = 0; li < lines.size(); ++li) {
            QString line = lines[li];

            if (line == "") {

            }
            else if (line.startsWith("[")) {
                //fprintf(stderr, "section : %s\n", line.toAscii().constData());
                section=line;
                if (section == "[HRData]") {
                    // Some systems, like the Tacx HRM exporter, do not add an [IntTimes] section, so we need to
                    // specify that the whole ride is one big interval.
                    if (intervals.isEmpty())
                        intervals.append(seconds);
                   next_interval = intervals.at(0);
               }
            }
            else if (section == "[Params]"){
                if (line.contains("Version=")) {
                    QString versionString = QString(line);
                    versionString.remove(0,8).insert(1, ".");
                    version = versionString.toFloat();
                    rideFile->setFileFormat("Polar HRM v"+versionString+" (hrm)");
                } else if (line.contains("Monitor=")) {
                    QString monitorString = QString(line);
                    monitorString.remove(0,8);
                    monitor = monitorString.toInt();
                    switch (monitor) {
                        case 1: rideFile->setDeviceType("Polar Sport Tester / Vantage XL"); break;
                        case 2: rideFile->setDeviceType("Polar Vantage NV (VNV)"); break;
                        case 3: rideFile->setDeviceType("Polar Accurex Plus"); break;
                        case 4: rideFile->setDeviceType("Polar XTrainer Plus"); break;
                        case 6: rideFile->setDeviceType("Polar S520"); break;
                        case 7: rideFile->setDeviceType("Polar Coach"); break;
                        case 8: rideFile->setDeviceType("Polar S210"); break;
                        case 9: rideFile->setDeviceType("Polar S410"); break;
                        case 10: rideFile->setDeviceType("Polar S510"); break;
                        case 11: rideFile->setDeviceType("Polar S610 / S610i"); break;
                        case 12: rideFile->setDeviceType("Polar S710 / S710i"); break;
                        case 13: rideFile->setDeviceType("Polar S810 / S810i"); break;
                        case 15: rideFile->setDeviceType("Polar E600"); break;
                        case 20: rideFile->setDeviceType("Polar AXN500"); break;
                        case 21: rideFile->setDeviceType("Polar AXN700"); break;
                        case 22: rideFile->setDeviceType("Polar S625X / S725X"); break;
                        case 23: rideFile->setDeviceType("Polar S725"); break;
                        case 33: rideFile->setDeviceType("Polar CS400"); break;
                        case 34: rideFile->setDeviceType("Polar CS600X"); break;
                        case 35: rideFile->setDeviceType("Polar CS600"); break;
                        case 36: rideFile->setDeviceType("Polar RS400"); break;
                        case 37: rideFile->setDeviceType("Polar RS800"); break;
                        case 38: rideFile->setDeviceType("Polar RS800X"); break;

                        default: rideFile->setDeviceType(QString("Unknown Polar Device %1").arg(monitor));
                   }
                } else if (line.contains("SMode=")) {
                    line.remove(0,6);
                    QString smode = QString(line);
                    if (smode.at(0)=='1')
                        speed = true;
                    if (smode.length()>0 && smode.at(1)=='1')
                        cadence = true;
                    if (smode.length()>1 && smode.at(2)=='1')
                        altitude = true;
                    if (smode.length()>2 && smode.at(3)=='1')
                        power = true;
                    if (smode.length()>3 && smode.at(4)=='1')
                        balance = true;
                    //if (smode.length()>4 && smode.at(5)=='1') pedaling_index = true;

                    //
                    // It appears that the Polar CS600 exports its data alays in metric when downloaded from the
                    // polar software even when English units are displayed on the unit..  It also never sets
                    // this bit low in the .hrm file.  This will have to get changed if other software downloads
                    // this differently
                    //

                    if (smode.length()>6 && smode.at(7)=='1')
                        metric = false;

                } else if (line.contains("Interval=")) {

                    recInterval = line.remove(0,9).toInt();

                    if (recInterval==238) {

                        /* This R-R data */
                        rideFile->setRecIntSecs(1);

                    } else {

                        rideFile->setRecIntSecs(recInterval);
                    }

                } else if (line.contains("Date=")) {
                    line.remove(0,5);
                    date= QDate(line.left(4).toInt(),
                                line.mid(4,2).toInt(),
                                line.mid(6,2).toInt());
                } else if (line.contains("StartTime=")) {
                    line.remove(0,10);
                    QDateTime datetime(date,
                                      QTime(line.left(2).toInt(),
                                            line.mid(3,2).toInt(),
                                            line.mid(6,2).toInt()));
                    rideFile->setStartTime(datetime);

                } else if (line.contains("StartDelay=")) {

                    StartDelay = line.remove(0,11).toInt();

                    if (recInterval==238) {
                        seconds = StartDelay/1000.0;
                    } else {
                        seconds = recInterval;
                    }
                }

            } else if (section == "[Note]") {

                note.append(line);

            } else if (section == "[IntTimes]") {

                double int_seconds = line.left(2).toInt()*60*60+line.mid(3,2).toInt()*60+line.mid(6,3).toFloat();
                intervals.append(int_seconds);

                if (lines.size()==1) {
                   is.readLine();
                   is.readLine();
                   if (version>1.05) {
                       is.readLine();
                       is.readLine();
                   }
                } else {
                   li+=2;
                   if (version>1.05)
                      li+=2;
                }

            } else if (section == "[HRData]") {

                double nm=0,kph=0,watts=0,km=0,cad=0,hr=0,alt=0,hrm=0;
                double lrbalance=RideFile::NA;

                int i=0;
                hrm = line.section('\t', i, i).toDouble();
                i++;

                if (speed) {
                    kph = line.section('\t', i, i).toDouble()/10;
                    distance += kph/60/60*recInterval;
                    km = distance;
                    i++;
                }
                if (cadence) {
                    cad = line.section('\t', i, i).toDouble();
                    i++;
                }
                if (altitude) {
                    alt = line.section('\t', i, i).toDouble();
                    i++;
                }
                if (power) {
                    watts = line.section('\t', i, i).toDouble();
                    i++;
                }
                if (balance) {
                    // Power LRB + PI:  The value contains :
                    //  - Left Right Balance (LRB) and
                    //  - Pedaling Index (PI)
                    //
                    // in the following formula:
                    // value = PI * 256 + LRB   PI bits 15-8  LRB bits 7-0
                    // LRB is the value of left foot
                    // for example if LRB = 45, actual balance is L45 - 55R.
                    // PI values are percentages from 0 to 100.
                    // For example value 12857 (= 40 * 256 + 47)
                    // means: PI = 40 and LRB = 47 => L47 - 53R

                    lrbalance = line.section('\t', i, i).toInt() & 0xff;
                    i++;
                }

                if (next_interval < seconds) {
                    interval = intervals.indexOf(next_interval);
                    if (intervals.count()>interval+1){
                        interval++;
                        next_interval = intervals.at(interval);
                    }
                }

                if (!metric) {
                    km *= KM_PER_MILE;
                    kph *= KM_PER_MILE;
                    alt *= METERS_PER_FOOT;
                }

                if (recInterval==238){
                    hr = 60000.0/hrm;
                } else {
                    hr = hrm;
                }

                if (haveGPX && gpxresult && (igpx<ngpx)) {

                    p = gpxresult->dataPoints()[igpx];

                    // Use previous value if GPS is momentarely
                    // lost. Should have option for interpolating.
                    if (p->lat!=0.0 && p->lon!=0.0) {

                        lat = p->lat;
                        lon = p->lon;

                        // Must check if current HRM speed is zero while
                        // we have GPX speed
                        if (kph==0.0 && p->kph>1.0) {

                            kph = p->kph;
                            distance += kph/60/60*recInterval;
                            km = distance;
                        }
                    }

                    if (seconds>=p->secs) igpx += 1;
                }

                rideFile->appendPoint(seconds, cad, hr, km, kph, nm, watts, alt, lon, lat,
                                      0.0, 0.0,
                                      RideFile::NA, lrbalance,
                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0, 0.0, 0.0,
                                      0.0, 0.0,
                                      0.0, 0.0, 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);
                if (recInterval==238) {
                    seconds += hrm / 1000.0;
                } else {
                    seconds += recInterval;
                }
            }

            ++lineno;
        }
    }

    rideFile->setTag("Notes", note);
    QRegExp rideTime("^.*/(\\d\\d\\d\\d)_(\\d\\d)_(\\d\\d)_"
                     "(\\d\\d)_(\\d\\d)_(\\d\\d)\\.hrm$");
    if (rideTime.indexIn(file.fileName()) >= 0) {
        QDateTime datetime(QDate(rideTime.cap(1).toInt(),
                                 rideTime.cap(2).toInt(),
                                 rideTime.cap(3).toInt()),
                           QTime(rideTime.cap(4).toInt(),
                                 rideTime.cap(5).toInt(),
                                 rideTime.cap(6).toInt()));


        rideFile->setStartTime(datetime);
    }
    file.close();

    return rideFile;
}