prop/lib/microwaveprop/rover/link_margin.ex

45 lines
1.5 KiB
Elixir
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

defmodule Microwaveprop.Rover.LinkMargin do
@moduledoc """
Per-link SNR-margin math for the rover planner.
Maps a propagation grid score (0-100) into a predicted SNR using the
linear calibration `(score 50) × 0.5`, then subtracts the mode's
required SNR threshold to yield "dB above decode".
"""
alias Microwaveprop.Propagation.ModeThresholds
alias Microwaveprop.Propagation.ScoresFile
@spec score_to_db(integer() | nil) :: float() | nil
def score_to_db(nil), do: nil
def score_to_db(score) when is_integer(score), do: (score - 50) * 0.5
@doc """
Pure helper: compute the link margin from an already-resolved
grid score and a mode atom. Used by tests and `Rover.Compute`,
which fetches the score itself.
"""
@spec link_margin_from_score(integer() | nil, ModeThresholds.mode()) :: float() | nil
def link_margin_from_score(nil, _mode), do: nil
def link_margin_from_score(score, mode) when is_integer(score) do
score_to_db(score) - ModeThresholds.required_snr_db(mode)
end
@doc """
Look up the score for the candidate cell and return the link margin.
"""
@spec link_margin_db(
non_neg_integer(),
DateTime.t(),
{float(), float()},
{float(), float()},
ModeThresholds.mode()
) :: float() | nil
def link_margin_db(band_mhz, %DateTime{} = valid_time, {c_lat, c_lon}, {_s_lat, _s_lon}, mode) do
case ScoresFile.read_point(band_mhz, valid_time, c_lat, c_lon) do
nil -> nil
score -> link_margin_from_score(score, mode)
end
end
end