aboutsummaryrefslogtreecommitdiff
path: root/ride/moving_time.go
diff options
context:
space:
mode:
Diffstat (limited to 'ride/moving_time.go')
-rw-r--r--ride/moving_time.go19
1 files changed, 16 insertions, 3 deletions
diff --git a/ride/moving_time.go b/ride/moving_time.go
index ea9ec24..c98e6b1 100644
--- a/ride/moving_time.go
+++ b/ride/moving_time.go
@@ -2,18 +2,22 @@ package ride
import "time"
-const MovingTimeAlgorithmVersion = "v1"
+const MovingTimeAlgorithmVersion = "v2"
// movingTimeMinSpeedMps is the minimum implied speed between two consecutive
// track points for the interval to count as moving (0.4 km/h).
const movingTimeMinSpeedMps = 0.4 / 3.6
+// movingTimeMinPowerW is the minimum power output for an interval to count as
+// moving when GPS speed is below the minimum speed.
+const movingTimeMinPowerW = 20
+
// 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.
+// absMean 2.4%, stderr 0.2, p50 0.7, p75 2.9, p90 6.7, p95 9.6, p99 19.9.
func MovingTime(r Ride) time.Duration {
return movingTime(r, movingTimeMinSpeedMps, movingTimeMaxGap)
}
@@ -26,7 +30,16 @@ func movingTime(r Ride, minSpeedMps float64, maxGap time.Duration) time.Duration
continue
}
dd := r.DistanceM(i) - r.DistanceM(i-1)
- if dd/dt.Seconds() > minSpeedMps {
+ gpsMoving := dd/dt.Seconds() > minSpeedMps
+ powerMoving := false
+ if power, ok := r.PowerW(i); ok {
+ powerMoving = power >= movingTimeMinPowerW
+ }
+ cadenceMoving := false
+ if cadence, ok := r.CadenceRpm(i); ok {
+ cadenceMoving = cadence > 0
+ }
+ if gpsMoving || powerMoving || cadenceMoving {
moving += dt
}
}