intersect_bearings

intersect_bearings#

rapidtools.processing.street_localization.intersect_bearings(rays: Sequence[tuple[float, float, float]], project: Callable[[float, float], tuple[float, float]], unproject: Callable[[float, float], tuple[float, float]], max_range_m: float = 60.0, min_separation_deg: float = 8.0) → tuple[float, float, float] | None[source]#

Least-squares intersection of bearings from several camera positions.

Parameters:
  • rays – (camera_lon, camera_lat, bearing_deg) per observation.

  • project – Local metre projection from local_projection().

  • unproject – Its inverse.

  • max_range_m – Reject solutions farther than this from any camera.

  • min_separation_deg – Require at least one pair of bearings this far apart; near-parallel rays give an ill-conditioned intersection.

Returns:

tuple[float, float, float] | None – (lon, lat, rms_residual_m) or None when the rays cannot be intersected (fewer than two distinct cameras, near-parallel bearings, or a solution behind a camera).

Example

>>> project, unproject = local_projection(0.0, 0.0)
>>> # Two cameras 20 m apart both looking at a point 10 m north of the
>>> # midpoint between them:
>>> lon_a, lat_a = unproject(-10.0, 0.0)
>>> lon_b, lat_b = unproject(10.0, 0.0)
>>> lon, lat, rms = intersect_bearings(
...     [(lon_a, lat_a, 45.0), (lon_b, lat_b, 315.0)], project, unproject
... )
>>> [round(v) for v in project(lon, lat)], round(rms, 3)
([0, 10], 0.0)