Source code for openlr_dereferencer.decoding.scoring

"""Scoring functions and default weights for candidate line rating

FOW_WEIGHT + FRC_WEIGHT + GEO_WEIGHT + BEAR_WEIGHT should always be `1`.

The result of the scoring functions will be floats from 0.0 to 1.0,
with `1.0` being an exact match and 0.0 being a non-match."""

from logging import debug
from openlr import FRC, FOW, LocationReferencePoint
from ..maps.wgs84 import distance
from .tools import coords, PointOnLine
from .configuration import Config
from .tools import compute_bearing


[docs]def score_frc(wanted: FRC, actual: FRC) -> float: "Return a score for a FRC value" return 1.0 - abs(actual - wanted) / 7
[docs]def score_geolocation(wanted: LocationReferencePoint, actual: PointOnLine, radius: float) -> float: """Scores the geolocation of a candidate. A distance of `radius` or more will result in a 0.0 score.""" debug(f"Candidate coords are {actual.position()}") dist = distance(coords(wanted), actual.position()) if dist < radius: return 1.0 - dist / radius return 0.0
[docs]def angle_difference(angle1: float, angle2: float) -> float: """The difference of two angle values. Args: angle1, angle2: The values are expected in degrees. Returns: A value in the range [-180.0, 180.0]""" return (abs(angle1 - angle2) + 180) % 360 - 180
[docs]def score_angle_difference(angle1: float, angle2: float) -> float: """Helper for `score_bearing` which scores the angle difference. Args: angle1, angle2: angles, in degrees. Returns: The similarity of angle1 and angle2, from 0.0 (180° difference) to 1.0 (0° difference) """ difference = angle_difference(angle1, angle2) return 1 - abs(difference) / 180
[docs]def score_bearing( wanted: LocationReferencePoint, actual: PointOnLine, is_last_lrp: bool, bear_dist: float ) -> float: """Scores the difference between expected and actual bearing angle. A difference of 0° will result in a 1.0 score, while 180° will cause a score of 0.0.""" bear = compute_bearing(wanted, actual, is_last_lrp, bear_dist) return score_angle_difference(wanted.bear, bear)
[docs]def score_lrp_candidate( wanted: LocationReferencePoint, candidate: PointOnLine, config: Config, is_last_lrp: bool ) -> float: """Scores the candidate (line) for the LRP. This is the average of fow, frc, geo and bearing score.""" debug(f"scoring {candidate} with config {config}") geo_score = config.geo_weight * score_geolocation(wanted, candidate, config.search_radius) fow_score = config.fow_weight * config.fow_standin_score[wanted.fow][candidate.line.fow] frc_score = config.frc_weight * score_frc(wanted.frc, candidate.line.frc) bear_score = score_bearing(wanted, candidate, is_last_lrp, config.bear_dist) bear_score *= config.bear_weight score = fow_score + frc_score + geo_score + bear_score debug(f"Score: geo {geo_score} + fow {fow_score} + frc {frc_score} " f"+ bear {bear_score} = {score}") return score