Skip to content

fix(geo): discard bogus near-zero GPS coordinates ("Null Island") - #124

Open
joroses wants to merge 7 commits into
zenitraM:mainfrom
joroses:pr3-gps-null-island
Open

joroses wants to merge 7 commits into
zenitraM:mainfrom
joroses:pr3-gps-null-island

Conversation

@joroses

@joroses joroses commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Summary (PR 3: Discard Bogus Near-Zero GPS Coordinates)

Fixes an issue where firmware bugs in some Meshtastic nodes emit near-zero GPS coordinates such as (0.0001, 0.0002) instead of exact (0, 0). These invalid fixes bypassed standard (0, 0) checks, placing nodes in the Gulf of Guinea ("Null Island") and severely inflating network distance metrics, map extents, and longest RF links.

PR Stack Context:
This is PR 3 of 4 in the traceroute performance & network analysis series:

  1. PR 1 (#122): Storage Layer & Backfill CLI (traceroute_routes & traceroute_hops) — Prerequisite / Merged first
  2. PR 2 (#123): Materialized Traceroute Readers — Switches all views & endpoints to SQL queries
  3. PR 3 (This PR): Discard Bogus Near-Zero GPS Coordinates (Null Island) — Sanitizes firmware GPS anomalies
  4. PR 4: UI Pagination Visibility & Map Date Filter Retention

Key Changes

  1. Coordinate Validation Utility (geo_utils.py):

    • Added is_valid_position(latitude, longitude).
    • Rejects None, non-finite floats (inf, NaN), coordinates exceeding valid degree ranges ([-90, 90] and [-180, 180]), and any coordinates within a 50 km radius of (0, 0).
  2. Ingestion Filtering (mqtt_capture.py):

    • Warns on arrival when a packet contains a near-zero or invalid position report, avoiding spurious updates.
  3. Fallback to Last Known Good Position (repositories.py):

    • LocationRepository queries evaluate up to depth 5 of a node's recent position reports. When a node intermittently broadcasts a corrupt fix, queries skip the corrupt report and retain the node's previous valid fix with its original timestamp.

Commits

  • 0bfd1d6 (Discard bogus near-zero GPS coordinates):
    • Discards bogus near-zero GPS positions (e.g. (0.0001, 0.0002)) caused by firmware bugs that placed nodes in the Gulf of Guinea ("Null Island") and inflated longest links and path metrics.
    • Validates positions on arrival in MQTT capture and falls back to last known good positions in location queries.

Verification

  • Automated Tests: 15 dedicated unit tests in tests/unit/test_position_validity.py covering:
    • Boundary limits, non-finite values, and proximity to (0,0).
    • Multi-packet fallback behavior ensuring nodes do not jump to Null Island.
    • Longest-link and distance calculation guards.
  • Suite Status: All 15 tests pass 100%.

roses added 7 commits September 13, 2026 07:44
…ead of being re-read from raw packets every time a page needs them. Two new tables keep track of each route that has ever been seen and the hops between the two endpoints. This prepares for faster queries in PR2
…async restoration

Track user-edited fields in a Set so async applyURLParameters() does not
overwrite user input in form pickers if typing occurs while parameter
resolution is in flight (e.g. following a timezone toggle or page reload).
…hop tables instead of parsing thousands of raw packets on every request. Link analysis between nodes, related node lists, the hop picker, and the main traceroute table now query the database directly with fast filtering and pagination. This removes the old packet caps so busy networks can analyze full multi-day windows without missing data, and updates the table UI to display exact total counts.
…p tables instead of re-decoding raw packets on every page request. The network graph, maps, longest links, route patterns, node statistics, and packet details now query pre-calculated hops and routes, eliminating slow packet loops and repeated database lookups. Also removed obsolete legacy reader code.
…as shorter connected paths. Hop queries now keep the full route structure, and indirect connections and longest-path results are only built from hops that actually link up end to end, so distances, hop counts, and route previews stay correct.
…odes send positions like (0.0001, 0.0002) instead of exactly (0,0), which slipped past the old checks and placed nodes in the middle of the ocean, inflating longest links and paths. Positions near (0,0) or with impossible coordinates are now discarded wherever positions are read; nodes keep showing their last known good position with its original timestamp instead of jumping or disappearing. The capture log now warns when such a position arrives. Note: longest links and paths are still mostly garbage because of other unlikely positions, but this removes the biggest offender.
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