From a6aa5547d4ec3fa984b55a6ba5f32e4813611cd5 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Date: Sun, 29 May 2016 14:20:19 -0300 Subject: [PATCH] Changed Interval generation for Lap swimming FIT files Simpler and more robust lap alignment Fixed for empty lengths due to false starts and pauses in some devices s.t. Garmin 910xt Added 2 contributed test files --- src/FileIO/FitRideFile.cpp | 98 +++++++----------- test/rides/2016-05-23_18-14-30_4_25.fit | Bin 0 -> 7000 bytes .../20160517-063148-1-1328-ANTFS-4-0.FIT | Bin 0 -> 8612 bytes 3 files changed, 36 insertions(+), 62 deletions(-) create mode 100644 test/rides/2016-05-23_18-14-30_4_25.fit create mode 100644 test/rides/20160517-063148-1-1328-ANTFS-4-0.FIT diff --git a/src/FileIO/FitRideFile.cpp b/src/FileIO/FitRideFile.cpp index 7f7fc8622..ac7a24ef9 100644 --- a/src/FileIO/FitRideFile.cpp +++ b/src/FileIO/FitRideFile.cpp @@ -32,7 +32,6 @@ #include #define FIT_DEBUG false // debug traces -#define LAPSWIM_DEBUG false #ifndef MATHCONST_PI #define MATHCONST_PI 3.141592653589793238462643383279502884L /* pi */ @@ -667,8 +666,6 @@ struct FitFileReaderState time = last_time; int i = 0; time_t this_start_time = 0; - double total_elapsed_time = 0.0; - double total_distance = 0.0; if (FIT_DEBUG) { printf( " FIT decode lap \n"); } @@ -691,12 +688,6 @@ struct FitFileReaderState case 2: this_start_time = value.v + qbase_time.toTime_t(); break; - case 7: - total_elapsed_time = value.v / 1000.0; - break; - case 9: - total_distance = value.v / 100000.0; - break; // other data (ignored at present): case 254: // lap nbr @@ -704,7 +695,9 @@ struct FitFileReaderState case 4: // start_position_lon case 5: // end_position_lat case 6: // end_position_lon + case 7: // total_elapsed_time = value.v / 1000.0; case 8: // total_timer_time + case 9: // total_distance = value.v / 100000.0; case 10: // total_cycles case 11: // total calories case 12: // total fat calories @@ -724,8 +717,6 @@ struct FitFileReaderState default: ; // ignore it } } - // don't count pauses for lap swimming - if (!isLapSwim || total_distance > 0) ++interval; if (this_start_time == 0 || this_start_time-start_time < 0) { //errors << QString("lap %1 has invalid start time").arg(interval); this_start_time = start_time; // time was corrected after lap start @@ -735,21 +726,38 @@ struct FitFileReaderState return; } } - if (rideFile->dataPoints().count()) { // no samples means no laps.. - if (isLapSwim && total_elapsed_time > 0.0) { - if (last_lap_end == 0.0) - last_lap_end = this_start_time - start_time - 1; - if (LAPSWIM_DEBUG) qDebug() << (total_distance > 0 ? "Lap" : "Rest") << interval << this_start_time - start_time << time - this_start_time << "+" << last_lap_end << total_elapsed_time << total_distance; - if (total_distance > 0) // skip pauses to avoid cluttering - rideFile->addInterval(RideFileInterval::DEVICE, - round(last_lap_end), - last_lap_end + total_elapsed_time, - QObject::tr("Lap %1").arg(interval)); - last_lap_end += total_elapsed_time; - } else { - rideFile->addInterval(RideFileInterval::DEVICE, this_start_time - start_time, time - start_time, - QObject::tr("Lap %1").arg(interval)); + if (isLapSwim) { + // Fill empty laps due to false starts or pauses in some devices + // s.t. Garmin 910xt + double secs = time - start_time; + if ((secs > last_time + 1) && + (isGarminSmartRecording.toInt() != 0) && + (secs - last_time < 100*GarminHWM.toInt())) { + double deltaSecs = secs - last_time; + for (int i = 1; i <= deltaSecs; i++) { + rideFile->appendPoint( + last_time+i, 0.0, 0.0, + last_distance, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, RideFile::NA, RideFile::NA, + 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); + } + last_time += deltaSecs; } + ++interval; + } else if (rideFile->dataPoints().count()) { // no samples means no laps + ++interval; + rideFile->addInterval(RideFileInterval::DEVICE, + this_start_time - start_time, + time - start_time, + QObject::tr("Lap %1").arg(interval)); } } @@ -1077,7 +1085,7 @@ struct FitFileReaderState start_time = 0; last_time = 0; last_distance = 0.00f; - interval = 0; + interval = 1; QString deviceType = rideFile->deviceType(); delete rideFile; rideFile = new RideFile; @@ -1158,17 +1166,9 @@ struct FitFileReaderState QDateTime t; t.setTime_t(start_time); rideFile->setStartTime(t); - rideFile->appendPoint(0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, RideFile::NA, - 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0.0, 0); + interval = 1; } - double secs = time - start_time; - // Normalize distance for the most common pool lengths, // this is a hack to avoid the need for a double pass when // pool_length comes in Session message at the end of the file. @@ -1188,29 +1188,6 @@ struct FitFileReaderState length_duration += frac_time; frac_time = modf(length_duration, &length_duration); - // No rest lengths for Garmin F910XT, add pause time - if ((rideFile->deviceType() == "Garmin FR910XT") && - (secs > last_time + 1) && (isGarminSmartRecording.toInt() != 0) && (secs - last_time < 100*GarminHWM.toInt())) { - double deltaSecs = secs - last_time; - if (LAPSWIM_DEBUG) qDebug() << "Pause" << last_time+1 << deltaSecs; - for (int i = 1; i <= deltaSecs; i++) { - rideFile->appendPoint( - last_time+i, 0.0, 0.0, - last_distance, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, RideFile::NA, RideFile::NA, - 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, 0); - } - last_time += deltaSecs; - } - // only fill 100x the maximal smart recording gap defined // in preferences - we don't want to crash / stall on bad // or corrupt files @@ -1218,7 +1195,6 @@ struct FitFileReaderState double deltaSecs = length_duration; double deltaDist = km - last_distance; kph = 3600.0 * deltaDist / deltaSecs; - if (LAPSWIM_DEBUG) qDebug() << "Length" << last_time+1 << deltaSecs << deltaDist << "type" << length_type; for (int i = 1; i <= deltaSecs; i++) { rideFile->appendPoint( last_time + i, cad, 0.0, @@ -1232,7 +1208,7 @@ struct FitFileReaderState 0.0, 0.0,0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0); + interval); } last_time += deltaSecs; last_distance += deltaDist; @@ -1440,8 +1416,6 @@ struct FitFileReaderState } } - if (LAPSWIM_DEBUG) qDebug() << "Lap" << interval << this_start_time - start_time << total_elapsed_time - << time - this_start_time << total_distance; if (this_start_time == 0 || this_start_time-start_time < 0) { //errors << QString("lap %1 has invalid start time").arg(interval); this_start_time = start_time; // time was corrected after lap start diff --git a/test/rides/2016-05-23_18-14-30_4_25.fit b/test/rides/2016-05-23_18-14-30_4_25.fit new file mode 100644 index 0000000000000000000000000000000000000000..3e247c09e8d3bffd2c2830d4793cd2da6ce97d73 GIT binary patch literal 7000 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 MVuLxxH~x404?Q;#kN^Mx literal 0 HcmV?d00001 diff --git a/test/rides/20160517-063148-1-1328-ANTFS-4-0.FIT b/test/rides/20160517-063148-1-1328-ANTFS-4-0.FIT new file mode 100644 index 0000000000000000000000000000000000000000..698f1f1409d872ebef37dc5f7287a028738a0384 GIT binary patch literal 8612 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 z