birdcage/src/travler_rotor/leapfrog.py
Ryan Malloy c93bbef26d Initial travler-rotor library scaffolding
Extract Gabe Emerson's Trav'ler rotor scripts into a proper Python
library with firmware protocol abstraction (HAL 2.05 + HAL 0.0.00),
Hamlib rotctld TCP server, Click CLI, and isolated leap-frog algorithm
with the elevation copy-paste bug fixed.
2026-02-11 04:10:17 -07:00

51 lines
1.8 KiB
Python

"""Leap-frog prediction algorithm for mechanical lag compensation.
The Trav'ler dish has inherent mechanical lag — by the time the motors
reach the commanded position, a satellite in motion has already moved on.
This module applies a small predictive overshoot so the dish "leaps ahead"
of the target, reducing tracking error during a pass.
"""
def apply_leapfrog(
target_az: float,
target_el: float,
current_az: float,
current_el: float,
) -> tuple[float, float]:
"""Apply predictive overshoot to compensate for mechanical lag.
For each axis, if the delta exceeds a threshold, the target is nudged
further in the direction of travel. This keeps the dish slightly ahead
of fast-moving satellites.
Args:
target_az: Desired azimuth from tracking software (degrees).
target_el: Desired elevation from tracking software (degrees).
current_az: Last-known azimuth of the dish (degrees).
current_el: Last-known elevation of the dish (degrees).
Returns:
Adjusted (azimuth, elevation) with overshoot applied.
Note:
The original upstream code had a copy-paste bug where the elevation
delta adjustments modified target_az instead of target_el.
See docs/bugs.md for details.
"""
# Azimuth compensation
az_delta = target_az - current_az
if abs(az_delta) > 2:
target_az += 1.0 if az_delta > 0 else -1.0
elif abs(az_delta) > 1:
target_az += 0.5 if az_delta > 0 else -0.5
# Elevation compensation (bug fix: original modified target_az here)
el_delta = target_el - current_el
if abs(el_delta) > 2:
target_el += 1.0 if el_delta > 0 else -1.0
elif abs(el_delta) > 1:
target_el += 0.5 if el_delta > 0 else -0.5
return target_az, target_el