Repository navigation
Position-aware automatic storm-source selection for vessels crossing regional radar coverage #5
Description
Motivation
stormSource is a single, static cell target (provider:PRODUCT). That works for a vessel sitting inside one radar's coverage, but the regional providers are exactly the case where a vessel doesn't: Radar-DPC covers Italy, DWD covers Germany, and (proposed in #2) AEMET covers Spain. A boat on passage crosses between them.
Concrete case: Balearic Islands → Sardinia. aemet:PM is a ~240 km disk centred near Palma (useful out to ~5.5°E); radar-dpc:HRD covers Sardinia/Italy (~8–10°E); the open sea in between is covered by neither. The relevant cell source changes with position, and today the only way to follow it is to open the plugin settings and re-pick stormSource mid-passage.
Proposal
Add a position-aware auto mode that resolves the active cell source from the vessel's current position and each source's coverage, per acquisition cycle.
Config surface
stormSource: "auto"— a new sentinel alongside the explicitprovider:PRODUCTvalues already in the enum (keeps the existing single dropdown; "Automatic (by position)" as one more option). Explicit values keep today's behaviour unchanged.stormSourceCandidates(optional array) — restrict/prioritise which cell-capable products auto considers. Default: allcells: trueproducts of enabled providers.stormSourceMaxRangeNm(optional, default0= require containment) — if the vessel is inside no coverage, allow selecting the nearest source whose coverage edge is within this range;0means "no source when uncovered".stormSourceHysteresisNm(optional) — margin to avoid flapping at a coverage boundary.
Selection algorithm (per cycle)
candidates= configured cell targets (or allcells:trueproducts).P= vessel position (unwrapped — see False storm alarm when navigation.position from getSelfPath is a full node (vessel position not unwrapped) #3).covering= candidates whose coverage containsP.- If
coveringnon-empty → pick the most local (smallest coverage area / highest resolution), or an explicit priority fromstormSourceCandidates. - Else if
stormSourceMaxRangeNm > 0→ pick the nearest candidate whose coverage edge is within that range. - Else → no active source (honest: no radar covers the vessel), surfaced as a distinct operational state rather than a silent all-clear.
- Apply hysteresis so a source already active isn't dropped until
Pis clearly outside it (margin + optional dwell).
Only the resolved source is acquired and processed that cycle, so a vessel on cellular/Starlink fetches just the one relevant radar.
Coverage model
MVP uses the product's existing bounds bbox for containment — no provider changes needed. Bbox over-approximates single-site disks (e.g. AEMET's 240 km circle fills ~64% of its bbox), so optionally let a provider expose a tighter predicate — e.g. covers(product, [lon,lat]) or a coverage(product) geometry — and fall back to bounds when absent. This keeps national mosaics (bbox) and single-site disks (circle/polygon) both correct.
Reporting
operational/health already reports source. In auto mode it should report the resolved active source plus the reason (in-coverage / nearest-within-range / no-coverage), so the operator can see which radar is driving the overlay and when they've sailed out of all coverage.
Edge cases
- No position → keep the last active source, or a configured fallback, or no-source; never fabricate.
- In the inter-coverage gap → no cells (with an explicit "no radar coverage at current position" status), unless
stormSourceMaxRangeNmopts into a nearest source. - Boundary flapping → handled by hysteresis.
Scope / compatibility
Purely additive: stormSource keeps accepting explicit provider:PRODUCT values with identical behaviour; auto is opt-in. It leans on metadata that already exists (product.bounds, per-product cells capability) and the vessel position the storm engine already consumes.
Happy to implement this — including the optional covers()/coverage() provider capability and tests — if the direction is agreeable. It pairs naturally with the AEMET provider in #2 (three regional sources make the single-source constraint the practical limiter for anyone on passage).
Activity