sistemato posizionamento in azimuth dei target

This commit is contained in:
VALLONGOL 2025-11-07 10:49:07 +01:00
parent 0a3afcaf61
commit e72aa8314e
2 changed files with 74 additions and 2 deletions

View File

@ -78,7 +78,11 @@ class DebugPayloadRouter:
ord("M"): lambda p: self._update_last_payload("MFD", p), ord("M"): lambda p: self._update_last_payload("MFD", p),
ord("S"): lambda p: self._update_last_payload("SAR", p), ord("S"): lambda p: self._update_last_payload("SAR", p),
ord("B"): lambda p: self._update_last_payload("BIN", p), ord("B"): lambda p: self._update_last_payload("BIN", p),
ord("J"): lambda p: self._update_last_payload("JSON", p), # JSON payloads may contain antenna nav fields (ant_nav_az / ant_nav_el).
# Route JSON to a dedicated handler that will both store the raw
# payload and, when possible, extract antenna az/el to update the hub
# so the PPI antenna sweep can animate even when using JSON protocol.
ord("J"): self._handle_json_payload,
ord("R"): self._handle_ris_status, ord("R"): self._handle_ris_status,
ord("r"): self._handle_ris_status, ord("r"): self._handle_ris_status,
} }
@ -341,6 +345,74 @@ class DebugPayloadRouter:
except Exception: except Exception:
self._logger.exception("Failed to generate text/JSON for RIS debug view.") self._logger.exception("Failed to generate text/JSON for RIS debug view.")
def _handle_json_payload(self, payload: bytearray):
"""
Handle JSON payloads. Store raw JSON and, if present, extract
antenna navigation fields (ant_nav_az / ant_nav_el) and propagate
them to the SimulationStateHub so the PPI antenna can animate.
"""
try:
# Always store the raw payload for debug inspection
self._update_last_payload("JSON", payload)
if not self._hub:
return
# Try to decode and parse JSON
try:
text = payload.decode("utf-8")
obj = json.loads(text)
except Exception:
return
# The JSON may follow the same structure as the RIS debug JSON
# we generate elsewhere: {"scenario": {...}, "targets": [...]}
def _find_scenario_field(dct, key):
if not isinstance(dct, dict):
return None
# Direct scenario container
sc = dct.get("scenario") or dct.get("sc") or dct
if isinstance(sc, dict) and key in sc:
return sc.get(key)
# Top-level key
if key in dct:
return dct.get(key)
# Nested search
for v in dct.values():
if isinstance(v, dict) and key in v:
return v.get(key)
return None
plat_az = _find_scenario_field(obj, "ant_nav_az") or _find_scenario_field(
obj, "platform_azimuth"
)
if plat_az is not None:
try:
# Values may be in radians or degrees; if small absolute
# value (< 2*pi) assume radians and convert.
val = float(plat_az)
if abs(val) <= (2 * math.pi + 0.01):
az_deg = math.degrees(val)
else:
az_deg = val
self._hub.set_antenna_azimuth(az_deg, timestamp=time.monotonic())
except Exception:
pass
# Optionally capture elevation for future UI use
plat_el = _find_scenario_field(obj, "ant_nav_el") or _find_scenario_field(
obj, "platform_elevation"
)
if plat_el is not None:
try:
_ = float(plat_el)
# For now we don't store elevation in the hub; leave as TODO.
except Exception:
pass
except Exception:
self._logger.exception("Error handling JSON payload")
def get_and_clear_latest_payloads(self) -> Dict[str, Any]: def get_and_clear_latest_payloads(self) -> Dict[str, Any]:
with self._lock: with self._lock:
new_payloads = self._latest_payloads new_payloads = self._latest_payloads

View File

@ -214,7 +214,7 @@ class PPIDisplay(ttk.Frame):
fig.subplots_adjust(left=0.05, right=0.95, top=0.9, bottom=0.05) fig.subplots_adjust(left=0.05, right=0.95, top=0.9, bottom=0.05)
self.ax = fig.add_subplot(111, projection="polar", facecolor="#2E2E2E") self.ax = fig.add_subplot(111, projection="polar", facecolor="#2E2E2E")
self.ax.set_theta_zero_location("N") self.ax.set_theta_zero_location("N")
self.ax.set_theta_direction(-1) # Clockwise # self.ax.set_theta_direction(-1) # Clockwise <- RIGA RIMOSSA
self.ax.set_rlabel_position(90) self.ax.set_rlabel_position(90)
self.ax.set_ylim(0, self.range_var.get()) self.ax.set_ylim(0, self.range_var.get())
angles_deg = np.arange(0, 360, 30) angles_deg = np.arange(0, 360, 30)