Speed pipeline: smoothing, stop clamping, distance, moving average #17
Labels
No labels
area:companion
area:docs
area:shared
area:tooling
area:watchapp
blocker
kind:chore
kind:feature
kind:spike
kind:test
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Blocks
Depends on
#19 Speed-source arbitration and GPS quality reporting
robert/PedalPebble
#22 Unit tests: speed smoothing, CSC wraparound, distance accumulation
robert/PedalPebble
#69 Auto-pause: one definition of stopped, in Phase 2
robert/PedalPebble
Reference
robert/PedalPebble#17
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal
Turn raw fixes into numbers that look right on the handlebars.
Acceptance criteria
FusedLocationProviderClientat 1 s, high accuracyLocation.getSpeed()used where available, distance/dt as fallbackFiles
companion/.../location/SpeedPipeline.ktUpdate — 2026-09-01: "stopped" is defined in #69, not here
Moving time and the moving average both need stop detection, and FR-M8 (auto-pause) sat two phases
away in Phase 5 as "behaviour not yet specified". Two phases apart, that becomes two definitions of
stopped and rides where the average speed and the ride timer disagree.
StopDetectorfrom #69 rather than defining stopped locallyand why
See D35.
Closed by PR #101 (merged): extends #69's SpeedPipeline.kt (not a fork) with a real onGpsFix() \u2014 30m accuracy gate (with a genuinely-caught NaN edge case: Location.hasAccuracy()==false surfaces as NaN, and NaN > threshold is false under IEEE 754, so a naive check would have let unknown-accuracy fixes through undetected), has-speed vs. position-delta/dt fallback, 3-sample/~3s moving-average smoothing, real haversine distance between accepted fixes, and a display clamp to exactly 0.0 once StopDetector confirms STOPPED (the 0.8 m/s number itself still lives in exactly one place). Rejected fixes are counted and surfaced (rejectedFixCount/lastRejectedFix), never silently dropped.\n\nCorrectly did not add FusedLocationProviderClient despite the issue's literal wording \u2014 found that #15 (merged earlier tonight) already deliberately uses LocationManager's modern LocationRequest.Builder instead, a documented D19 decision enabled by minSdk 31. Respected the existing architecture rather than blindly implementing stale issue text.\n\nVerified for real: new SpeedPipelineTest cases (accuracy gate incl. the NaN case, has-speed precedence, dt-fallback smoothing convergence, wheel-live drops not counted as rejections, display clamp) all green via
./gradlew :companion:core:test;./gradlew :companion:assembleDebugclean. No GPS hardware in this sandbox \u2014 the live location callback is compiled, not exercised.