Skip to content

Fix map drift on tab return, speed cold start, mark OpenSky tracks#107

Merged
d3mocide merged 2 commits into
mainfrom
claude/map-perf-data-fallback-9r68uv
Jun 13, 2026
Merged

Fix map drift on tab return, speed cold start, mark OpenSky tracks#107
d3mocide merged 2 commits into
mainfrom
claude/map-perf-data-fallback-9r68uv

Conversation

@d3mocide

Copy link
Copy Markdown
Owner

Summary

Addresses map performance, the "icons drift away then catch up" behavior after switching tabs, and smoother multi-source ADS-B fallback (Beast → OpenSky).

1. Drift-on-tab-return (root cause fix)

The motion system (Projective Velocity Blending, pvb.ts) extrapolates each aircraft forward from its last server report by wall-clock elapsed time. The rAF loop in MapOverlay.tsx used Date.now() with no clamp and no Page Visibility handling. When a tab is backgrounded the browser pauses/throttles requestAnimationFrame while the WebSocket keeps delivering updates — so on return, every plane got projected forward by the entire away-window (the drift), then snapped to truth (the catch-up).

  • Add a visibilitychange handler that re-anchors PVB to current server positions on resume (clears stale anchors so applyPVB re-seeds at reported position).
  • Clamp the pulse dt so a throttled rAF can't fast-forward the animation phase.
  • Add a hard MAX_PROJECT_MS (30s) ceiling on extrapolation as a backstop for any large gap (WS reconnects, etc.). Set above the widest blend window so normal motion is never clipped.

2. Slow loading

Initial map state previously arrived only after the WS handshake and the poller's first snapshot tick (up to a few seconds). Added a REST prefetch of /entities in useWebSocket.ts so the map renders immediately. Guarded on an empty store so it never clobbers live WS data that may have already arrived.

3. Beast → OpenSky fallback (fast handover + visual marker)

The multi-source supplement machinery already exists in poller/pollers/adsb.py (priority beast > ultrafeeder > opensky, gap-fill via holdoff window). This PR makes the fast + visual marker behavior the user requested:

  • OpenSky-supplemented aircraft now render dimmed (buildEntityLayers.ts) so it's clear a track is lower-fidelity gap-fill rather than the local BEAST feed. The frontend already re-anchors PVB cleanly on source flips, so handover is smooth.
  • Documented the recommended authenticated OpenSky config in .env.example (interval 30s → ~30s gap handover), with the effective-handover-window formula and rate-limit guidance.

Testing

  • npx tsc --noEmit passes.
  • Poller logic unchanged at runtime; .env.example is documentation only.

Notes

  • With anonymous OpenSky (240s polling) gap-fill is inherently ~90s; smooth fallback requires authenticated credentials (which the operator has).

https://claude.ai/code/session_01HS4mM3wZUW76r7PLHcwHFV


Generated by Claude Code

claude added 2 commits June 13, 2026 16:29
Map animation / perf and multi-source fallback improvements:

- Fix aircraft "drift away then snap back" after the browser tab is
  backgrounded. The rAF loop pauses while hidden but the WebSocket keeps
  delivering updates, so on return PVB extrapolated each track forward by
  the entire away-window. Add a visibilitychange handler that re-anchors
  motion smoothing to current server truth on resume, clamp the pulse dt,
  and add a hard MAX_PROJECT_MS ceiling on extrapolation as a backstop.

- Speed up cold start with a REST prefetch of /entities so the map
  renders immediately instead of waiting for the WS handshake + first
  poller snapshot. Guarded on an empty store so it never clobbers live
  WS data.

- Visually mark OpenSky-supplemented aircraft (dimmed icon) so it is
  clear when a track is lower-fidelity gap-fill rather than the local
  BEAST feed.

- Document the recommended authenticated OpenSky setup for smooth
  ~30s Beast-gap handover in .env.example.
- Eliminate the icon "jiggle/swim" during pan & zoom. The standalone Deck
  instance on a separate canvas was synced to MapLibre by pushing viewState
  every rAF, leaving the two canvases a frame out of phase. Replace it with
  @deck.gl/mapbox MapboxOverlay added as a map control, so Deck renders in
  lockstep with the base map's render loop. Removes the per-frame viewState
  push and manual canvas resize; preserves the deck-overlay-canvas id so the
  snapshot export keeps working, and routes picking through overlay.pickObject.

- Memoize static / slow-changing layer groups (custom, geofence, observation
  rings, mesh, stream gauges, cameras, annotations) so they rebuild only when
  their inputs change instead of on every animation frame. Reused Layer
  instances let deck.gl skip re-diffing them; only the PVB/pulse-animated
  entity, trail, event and lightning layers rebuild each frame.

- Enable the OpenSky supplement by default with a 30s cadence and 25s gap
  handover (assumes a free OpenSky account, which most users register).
  Anonymous users are advised to raise the interval or disable it.
@d3mocide d3mocide marked this pull request as ready for review June 13, 2026 17:30
@d3mocide d3mocide merged commit ccf3867 into main Jun 13, 2026
6 checks passed
@d3mocide d3mocide deleted the claude/map-perf-data-fallback-9r68uv branch June 13, 2026 17:30
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.

2 participants