Skip to content

Fix false storm alarm from unwrapped own-ship position node (fixes #3) - #4

Open
fakehec wants to merge 1 commit into
OpenFairWind:mainfrom
fakehec:fix-vessel-position
Open

fakehec wants to merge 1 commit into
OpenFairWind:mainfrom
fakehec:fix-vessel-position

Conversation

@fakehec

@fakehec fakehec commented Sep 9, 2026

Copy link
Copy Markdown

Fixes #3.

Problem

vessel() reads own-ship position with app.getSelfPath('navigation.position') and passes it through as { position, sog, cog }. On Signal K servers where getSelfPath returns the full node ({ value: { latitude, longitude }, timestamp, … }) rather than the bare value, vessel.position.longitude/.latitude are undefined. StormEngine.evaluate then builds vp = [undefined, undefined], distance-to-cell is null, and pathPolygonThreat degenerates to a spurious intersection — promoting distant cells to a false alarm with a 0.0 NM away, CPA NaN, intersects in 0 min message.

Self-contained reproduction is in #3.

Fix

  • vessel() now unwraps .value for position, sog and cog, so both the node and bare-value shapes work.
  • StormEngine.evaluate derives the vessel point via a small vesselPoint() helper that also unwraps .value and requires finite longitude/latitude. A missing or malformed position therefore yields vp = null (distance null ⇒ severityState returns normal) instead of a fabricated zero-distance intersection. This keeps the engine safe regardless of caller shape.

Tests

New test/storm-engine-vessel.test.js:

  • far cell is normal with a plain {latitude,longitude} position;
  • node-form {value:{…}} position is unwrapped and yields the same result (no false alarm, identical finite distance);
  • positions without finite coordinates degrade to normal with no fabricated distance;
  • a genuinely close severe cell still raises the alarm (from a node-form position).

npm test and npm run lint are clean.

Impact

Affects any storm source (including the bundled Radar-DPC HRD) on servers whose getSelfPath returns nodes. No behavior change on servers that already return bare values.

vessel() reads navigation.position/SOG/COG via app.getSelfPath and passed
the result through unchanged. On Signal K servers where getSelfPath returns
the full node ({ value, timestamp, ... }) rather than the bare value,
vessel.position.longitude/.latitude are undefined; StormEngine.evaluate then
builds vp = [undefined, undefined], distance-to-cell is null, and the
vessel-path/polygon interception check degenerates to a spurious
intersection, promoting distant cells to a false "alarm" with a
"0.0 NM away, CPA NaN" message.

- vessel(): unwrap `.value` for position, SOG and COG.
- StormEngine.evaluate: derive the vessel point via a helper that unwraps
  `.value` and requires finite longitude/latitude, so a missing or malformed
  position yields vp = null (distance null -> normal) instead of a fabricated
  zero-distance intersection.
- Add deterministic regression tests covering plain vs node-form positions,
  malformed positions, and that a genuinely close cell still alarms.

Fixes OpenFairWind#3.
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.

False storm alarm when navigation.position from getSelfPath is a full node (vessel position not unwrapped)

1 participant