Auto-pause: one definition of stopped, in Phase 2 #69

Closed
opened 2026-09-01 17:35:47 +02:00 by robert · 1 comment
robert commented 2026-09-01 17:35:47 +02:00 (Migrated from git.butzei.de)

Goal

Define "stopped" once, in the phase that first needs it.

FR-M8 (auto-pause) sat in Phase 5 as "behaviour not yet specified", while #17 in Phase 2 already needed stop detection for moving time and the moving average. Two phases apart, that becomes two different definitions of stopped - and rides where the average speed and the ride timer disagree about how long you were moving.

Acceptance criteria

  • One StopDetector, consumed by moving-time accumulation, the moving average, the GPX recording and auto-pause
  • Speed threshold specified and documented, consistent with the 0.8 m/s display clamp in #17 - state explicitly whether they are the same number and why
  • Dwell before a stop takes effect, so a traffic light is a stop and a slow corner is not
  • Resume condition specified, with hysteresis, so it does not flap at walking pace
  • Behaviour with a wheel sensor rather than GPS: the wheel sensor knows you have stopped immediately and should be preferred when live
  • Auto-pause on / off, honouring the setting in #44; when off, the same detector still drives moving time
  • Pause state reflected to the watch as RIDE_STATE, and a manual pause always beats an automatic resume
  • Unit tests from a replayed GPX with real traffic-light stops (#23), asserting moving time against a hand-checked expectation

Files

  • companion/.../ride/StopDetector.kt
  • companion/.../location/SpeedPipeline.kt

Notes

See D35. #44 keeps only the setting that turns auto-pause on and off; the behaviour lives here.

## Goal Define "stopped" once, in the phase that first needs it. FR-M8 (auto-pause) sat in Phase 5 as "behaviour not yet specified", while #17 in Phase 2 already needed stop detection for moving time and the moving average. Two phases apart, that becomes two different definitions of stopped - and rides where the average speed and the ride timer disagree about how long you were moving. ## Acceptance criteria - [ ] One `StopDetector`, consumed by moving-time accumulation, the moving average, the GPX recording and auto-pause - [ ] Speed threshold specified and documented, consistent with the 0.8 m/s display clamp in #17 - state explicitly whether they are the same number and why - [ ] Dwell before a stop takes effect, so a traffic light is a stop and a slow corner is not - [ ] Resume condition specified, with hysteresis, so it does not flap at walking pace - [ ] Behaviour with a wheel sensor rather than GPS: the wheel sensor knows you have stopped immediately and should be preferred when live - [ ] Auto-pause on / off, honouring the setting in #44; when off, the same detector still drives moving time - [ ] Pause state reflected to the watch as `RIDE_STATE`, and a manual pause always beats an automatic resume - [ ] Unit tests from a replayed GPX with real traffic-light stops (#23), asserting moving time against a hand-checked expectation ## Files - `companion/.../ride/StopDetector.kt` - `companion/.../location/SpeedPipeline.kt` ## Notes See D35. #44 keeps only the setting that turns auto-pause on and off; the behaviour lives here.
Owner

Closed by PR #100 (merged): one StopDetector (companion/core, D35) consumed by moving-time/moving-average/GPX-recording/auto-pause alike. 0.8 m/s stop threshold \u2014 deliberately the same number as #17's display clamp, since two thresholds for "stopped" is exactly the bug D35 exists to prevent. 3s dwell before a stop registers, 1.5 m/s held 1s to resume (hysteresis above walking pace). Wheel sensor (#18) gets no special-cased threshold, just feeds the same detector a cleaner signal, preferred over GPS for 5s after its last report; GPS samples are dropped outright while the wheel is live, not merely deprioritized. Manual-pause-wins reconciles with state.c's existing D43 mechanism rather than duplicating it \u2014 this PR is phone-side detection only.\n\n18 new host tests (synthetic stop-and-go scenario standing in for #23's not-yet-built GPX replay harness, since #23 doesn't exist yet) all green via a real ./gradlew :companion:core:test. D35 updated additively (a dated paragraph, not a rewrite) with the concrete numbers per D48.

Closed by PR #100 (merged): one StopDetector (companion/core, D35) consumed by moving-time/moving-average/GPX-recording/auto-pause alike. 0.8 m/s stop threshold \u2014 deliberately the same number as #17's display clamp, since two thresholds for \"stopped\" is exactly the bug D35 exists to prevent. 3s dwell before a stop registers, 1.5 m/s held 1s to resume (hysteresis above walking pace). Wheel sensor (#18) gets no special-cased threshold, just feeds the same detector a cleaner signal, preferred over GPS for 5s after its last report; GPS samples are dropped outright while the wheel is live, not merely deprioritized. Manual-pause-wins reconciles with state.c's existing D43 mechanism rather than duplicating it \u2014 this PR is phone-side detection only.\n\n18 new host tests (synthetic stop-and-go scenario standing in for #23's not-yet-built GPX replay harness, since #23 doesn't exist yet) all green via a real `./gradlew :companion:core:test`. D35 updated additively (a dated paragraph, not a rewrite) with the concrete numbers per D48.
Sign in to join this conversation.
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
robert/PedalPebble#69
No description provided.