|
|
@@ -12,6 +12,16 @@
|
|
|
|
|
|
struct auto_pause_s auto_pause;
|
|
|
|
|
|
+/* Resuming from a period of auto-pause because of apparent distance needs
|
|
|
+ * more apparent movement than triggering the pause did in the first place:
|
|
|
+ * position noise while genuinely stationary (multipath, poor sky view) can
|
|
|
+ * still occasionally clear the plain auto_pause_dist threshold over enough
|
|
|
+ * auto_pause_time windows, and unlike a false pause (which just costs one
|
|
|
+ * quiet window before the speed-based check or the next window catches the
|
|
|
+ * resume), a false resume pollutes the moving/stopped split and the
|
|
|
+ * odometer for as long as it isn't caught. */
|
|
|
+#define AUTO_PAUSE_RESUME_DIST_MULT_X100 150 /* 1.5x the configured distance threshold */
|
|
|
+
|
|
|
static void auto_unpause(void) {
|
|
|
if (!System.tracking_auto_paused)
|
|
|
return;
|
|
|
@@ -22,6 +32,12 @@ static void auto_unpause(void) {
|
|
|
|
|
|
static void auto_pause_activate(void) {
|
|
|
System.tracking_auto_paused = 1;
|
|
|
+ /* Otherwise, speed-counter progress from just before this decision (e.g.
|
|
|
+ * 2 of the 3 consecutive above-threshold samples the resume check below
|
|
|
+ * wants) could carry over and complete on the very next sample,
|
|
|
+ * instantly flip-flopping straight back out of the pause this just
|
|
|
+ * activated. */
|
|
|
+ auto_pause.speed_counter = 0;
|
|
|
log_pause_event(1);
|
|
|
beep(50, 3);
|
|
|
}
|
|
|
@@ -34,25 +50,45 @@ void auto_pause_process(void) {
|
|
|
auto_pause.speed_counter = 0;
|
|
|
return;
|
|
|
}
|
|
|
- if (System.speed >= System.conf.auto_pause_speed) { /* unpause when set speed is exceeded for 3 consecutive measurements */
|
|
|
- if (++auto_pause.speed_counter >= 3) {
|
|
|
- auto_pause.point_counter = 0;
|
|
|
+ /* A poor/invalid fix must not be read as "moving": a single noisy sample
|
|
|
+ * (e.g. a low-satellite, high-HDOP fix briefly reporting tens of km/h,
|
|
|
+ * as seen on a real hike where reception dropped for a few seconds)
|
|
|
+ * could otherwise satisfy the "3 consecutive" debounce below on its own
|
|
|
+ * and resume a logger that is actually sitting still. Such a sample is
|
|
|
+ * simply ignored - neither counted towards, nor resetting, the
|
|
|
+ * consecutive-samples debounce - so it can't itself trigger a resume,
|
|
|
+ * but also can't erase real progress made by genuine movement. */
|
|
|
+ if (gps_fix_trustworthy()) {
|
|
|
+ if (System.speed >= System.conf.auto_pause_speed) { /* unpause when set speed is exceeded for 3 consecutive measurements */
|
|
|
+ if (++auto_pause.speed_counter >= 3) {
|
|
|
+ auto_pause.point_counter = 0;
|
|
|
+ auto_pause.speed_counter = 0;
|
|
|
+ auto_unpause();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
auto_pause.speed_counter = 0;
|
|
|
- auto_unpause();
|
|
|
- return;
|
|
|
}
|
|
|
- } else {
|
|
|
- auto_pause.speed_counter = 0;
|
|
|
}
|
|
|
if (++auto_pause.point_counter < System.conf.auto_pause_time)
|
|
|
return;
|
|
|
auto_pause.point_counter = 0;
|
|
|
- if ((System.distance - auto_pause.prev_distance)/100 > System.conf.auto_pause_dist) {
|
|
|
- if (System.tracking_auto_paused)
|
|
|
+ if (System.tracking_auto_paused) {
|
|
|
+ unsigned long int resume_threshold = (unsigned long int)System.conf.auto_pause_dist
|
|
|
+ * AUTO_PAUSE_RESUME_DIST_MULT_X100 / 100;
|
|
|
+ if ((System.distance - auto_pause.prev_distance)/100 > resume_threshold)
|
|
|
auto_unpause(); /* unpause when distance exceeded */
|
|
|
} else {
|
|
|
- if (!System.tracking_auto_paused)
|
|
|
- auto_pause_activate(); /* pause otherwise */
|
|
|
+ /* Net displacement over this window can be small even while genuinely
|
|
|
+ * moving throughout it - a winding path folding back on itself, or a
|
|
|
+ * short out-and-back - and pausing on that alone, only to have the
|
|
|
+ * very next sample or two immediately satisfy the speed-based resume
|
|
|
+ * above, is itself a spurious (if brief) pause. If the logger is
|
|
|
+ * already moving fast enough to resume on its own right now, don't
|
|
|
+ * pause it in the first place. */
|
|
|
+ if ((System.distance - auto_pause.prev_distance)/100 <= System.conf.auto_pause_dist
|
|
|
+ && System.speed < System.conf.auto_pause_speed)
|
|
|
+ auto_pause_activate(); /* pause: not enough net movement, and not currently moving fast */
|
|
|
}
|
|
|
auto_pause.prev_distance = System.distance;
|
|
|
}
|