target rosso per real, target verde per simulato

This commit is contained in:
VALLONGOL 2025-10-22 10:22:00 +02:00
parent 5c0731f0b4
commit 323e3dfdac
3 changed files with 40 additions and 6 deletions

View File

@ -38,6 +38,8 @@
}
}
}
,
"ppi_trail_length": 100
},
"debug": {
"enable_io_trace": true,

View File

@ -26,7 +26,7 @@ class PPIDisplay(ttk.Frame):
"""
TRAIL_LENGTH = 100 # Number of historical points to show in a target's trail
def __init__(self, master, max_range_nm: int = 100, scan_limit_deg: int = 60):
def __init__(self, master, max_range_nm: int = 100, scan_limit_deg: int = 60, trail_length: int = None):
super().__init__(master)
self.max_range = max_range_nm
self.scan_limit_deg = scan_limit_deg
@ -38,10 +38,14 @@ class PPIDisplay(ttk.Frame):
self.real_trail_artists = []
self.target_label_artists = []
# Data store for target trails
# Data store for target trails. Use a bounded deque per-target whose
# max length is configurable (via constructor). The widget no longer
# supports an unbounded "full trail" mode — use a sufficiently large
# trail_length if you need a longer history.
self.trail_length = trail_length or self.TRAIL_LENGTH
self._trails = {
"simulated": collections.defaultdict(lambda: collections.deque(maxlen=self.TRAIL_LENGTH)),
"real": collections.defaultdict(lambda: collections.deque(maxlen=self.TRAIL_LENGTH))
"simulated": collections.defaultdict(lambda: collections.deque(maxlen=self.trail_length)),
"real": collections.defaultdict(lambda: collections.deque(maxlen=self.trail_length)),
}
# Artists for trajectory preview
@ -156,6 +160,22 @@ class PPIDisplay(ttk.Frame):
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
self._update_scan_lines()
def _init_trails(self):
"""(Removed) kept for historical reasons but no longer used."""
# This method is intentionally left as a no-op. Trails are initialized
# during construction and are always bounded by `trail_length`.
return
def _on_full_trail_toggled(self):
"""Toggle between bounded trail and full trail while preserving data.
When switching modes we transfer existing points into the new structure
to avoid losing history unexpectedly.
"""
# Full-trail toggling has been removed. Keep the method present so
# callers won't fail if they still reference it, but do nothing.
return
def update_targets(self, targets_data: Union[List[Target], Dict[str, List[Target]]]):
"""
Updates the display with the current state of targets.

View File

@ -415,7 +415,15 @@ class SfpDebugWindow(tk.Toplevel):
paned.add(right, weight=2)
# Create PPI widget inside ris_ppi_container but keep it hidden
try:
self.ris_ppi_widget = PPIDisplay(self.ris_ppi_container, max_range_nm=100)
# Determine trail length from the configuration manager if available
gm = getattr(self.master, "config_manager", None)
trail_len = None
try:
general = gm.get_general_settings() if gm else {}
trail_len = general.get("ppi_trail_length") if isinstance(general, dict) else None
except Exception:
trail_len = None
self.ris_ppi_widget = PPIDisplay(self.ris_ppi_container, max_range_nm=100, trail_length=trail_len)
self.ris_ppi_widget.pack(fill=tk.BOTH, expand=True)
except Exception:
self.ris_ppi_widget = None
@ -1331,7 +1339,11 @@ class SfpDebugWindow(tk.Toplevel):
f"PPI target sample: id={getattr(pt, 'target_id', None)} r_nm={getattr(pt,'current_range_nm',None):.2f} az={getattr(pt,'current_azimuth_deg',None):.2f} hdg={getattr(pt,'current_heading_deg',None):.2f}",
"DEBUG",
)
self.update_ppi_targets(ppi_targets)
# Mark these as server-sent 'real' targets so
# PPIDisplay will draw them using the 'real'
# styling (red). Use the dict form expected
# by PPIDisplay to distinguish origins.
self.update_ppi_targets({"real": ppi_targets})
except Exception:
self.logger.exception(
"Failed to push targets to PPI"