Skip to content

feat: drop implausible-speed (teleport) locations via heuristic filter#2266

Open
mvanhorn wants to merge 1 commit into
owntracks:masterfrom
mvanhorn:feat/2034-implausible-speed-filter
Open

feat: drop implausible-speed (teleport) locations via heuristic filter#2266
mvanhorn wants to merge 1 commit into
owntracks:masterfrom
mvanhorn:feat/2034-implausible-speed-filter

Conversation

@mvanhorn

Copy link
Copy Markdown

Summary

Adds an opt-in implausible-speed (teleport) filter to LocationProcessor.publishLocationMessage. When a new fix would imply travel faster than a configurable maximum ground speed relative to the last published location, the fix is dropped before it is queued for sending or persisted as the current published location.

The filter is gated by a new config-import-only integer preference maxImplausibleSpeedKmh, defaulting to 0, which disables the filter and preserves current behaviour. It sits alongside the existing accuracy and network-vs-gps discard heuristics and follows the same Result.failure plus Timber logging pattern.

Why this matters

Users on the OSS (F-Droid/AOSP) flavour report occasional random published locations several miles from the device's true position while the phone is stationary, drawing long straight-line artifacts on the recorder map (#2034, also referenced in #2053). These come from the network/cell-tower provider supplying low-quality fixes that the OSS build forwards without the aggregation Play Services would normally apply.

On 2026-04-30 maintainer @growse scoped the work into two tracked items: (1) Kalman filtering of non-Play-Services locations, and (2) a heuristic to figure out if something looks weirdly wrong and optionally filter it out. This change implements item 2 only. A teleport fix implies an impossible ground speed relative to the previous fix, so dropping fixes above a user-set km/h ceiling removes the artifacts without touching plausible movement.

Behaviour details:

  • Strictly opt-in: maxImplausibleSpeedKmh = 0 (the default) disables the filter.
  • Never blocks the first fix (no previous published location to compare against).
  • Skips USER and CIRCULAR triggered reports so on-demand and region reports are never suppressed.
  • Guards against zero and negative time deltas, so there is no divide-by-zero and a non-advancing clock never drops a fix.

The pure decision lives in an isImplausibleSpeed(distanceMeters, timeDeltaMillis, maxSpeedKmh) helper so it can be unit tested without Android dependencies.

Testing

Added LocationProcessorTest with JVM-pure unit tests for the decision helper covering: disabled threshold, a plausible slow move, a teleport (about 15 miles in 5 seconds, implying roughly 17,000 km/h), a zero time delta, and a negative time delta.

Gradle was not run locally because this machine has no Java runtime; CI will validate the build and tests.

Refs #2034

Add an opt-in implausible-speed filter in LocationProcessor.publishLocationMessage
that drops a new fix when it implies travel faster than a configurable maximum
ground speed relative to the last published location. Gated by a new
config-import-only integer preference maxImplausibleSpeedKmh, defaulting to 0
(disabled) so existing behaviour is unchanged.

The filter sits alongside the existing accuracy and network-vs-gps discard
heuristics, skips USER and CIRCULAR triggered reports, never blocks the first
fix, and guards against zero or negative time deltas. The pure decision lives in
an isImplausibleSpeed helper with JVM unit tests.

Refs owntracks#2034

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ye471qeNk1R7b7aQsZF5s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant