diff options
| author | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-08-20 16:05:20 +0200 |
|---|---|---|
| committer | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-08-20 16:05:20 +0200 |
| commit | 15ce334f357ca4f061977ad342292b21c5e60ea6 (patch) | |
| tree | 72d144d875203322897d1c03a5f801fa20cb10a0 /ride | |
| parent | 57e48b23987630936c84300d87ea5be682cb64bd (diff) | |
fix(ride): improve moving time against Strava
Diffstat (limited to 'ride')
| -rw-r--r-- | ride/moving_time.go | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/ride/moving_time.go b/ride/moving_time.go index 8403772..ea9ec24 100644 --- a/ride/moving_time.go +++ b/ride/moving_time.go @@ -5,24 +5,30 @@ import "time" const MovingTimeAlgorithmVersion = "v1" // movingTimeMinSpeedMps is the minimum implied speed between two consecutive -// track points for the interval to count as moving (1 km/h). -const movingTimeMinSpeedMps = 1.0 / 3.6 +// track points for the interval to count as moving (0.4 km/h). +const movingTimeMinSpeedMps = 0.4 / 3.6 -// Baseline backtest (356 rides, `-backtest`): mean err 3.9% (stderr 0.4), -// p50 1.6, p75 4.6, p90 8.4, p95 12.1, p99 44.9. -// Worst offenders overcount stationary GPS jitter (lunch stops) and -// undercount trainer rides with little GPS movement. Tuned in future commits. +// movingTimeMaxGap is the maximum time gap between consecutive track points +// that can count as moving. Longer gaps are pauses (stops, lost signal). +const movingTimeMaxGap = 120 * time.Second + +// Bench (356 rides, `-backtest`): +// absMean 2.5%, bias -1.3, p50 0.8, p75 2.9, p90 6.0, p95 9.3, p99 26.2. func MovingTime(r Ride) time.Duration { + return movingTime(r, movingTimeMinSpeedMps, movingTimeMaxGap) +} + +func movingTime(r Ride, minSpeedMps float64, maxGap time.Duration) time.Duration { var moving time.Duration for i := 1; i < r.Len(); i++ { dt := r.Timestamp(i).Sub(r.Timestamp(i - 1)) - if dt <= 0 { + if dt <= 0 || dt > maxGap { continue } - dd := r.DistanceM(i) - r.DistanceM(i - 1) - if dd/dt.Seconds() > movingTimeMinSpeedMps { + dd := r.DistanceM(i) - r.DistanceM(i-1) + if dd/dt.Seconds() > minSpeedMps { moving += dt } } return moving -}
\ No newline at end of file +} |
