From db645b13ce3077798fc5887e6113e968793d3643 Mon Sep 17 00:00:00 2001 From: VALLONGOL Date: Tue, 21 Oct 2025 09:38:43 +0200 Subject: [PATCH] aggiunta la visualizzazione ppi in debug --- settings.json | 6 +- target_simulator/core/command_builder.py | 8 +++ target_simulator/gui/ppi_display.py | 60 ++++++++++++++-- target_simulator/gui/sfp_debug_window.py | 92 ++++++++++++++++++++++-- todo.md | 7 +- 5 files changed, 157 insertions(+), 16 deletions(-) diff --git a/settings.json b/settings.json index de89fe0..6325c39 100644 --- a/settings.json +++ b/settings.json @@ -2,7 +2,7 @@ "general": { "scan_limit": 60, "max_range": 100, - "geometry": "1200x1024+85+163", + "geometry": "1200x1024+501+367", "last_selected_scenario": "scenario2", "connection": { "target": { @@ -76,8 +76,10 @@ "maneuver_type": "Fly to Point", "duration_s": 10.0, "target_range_nm": 10.0, - "target_azimuth_deg": 1.0, + "target_azimuth_deg": -3.0, "target_altitude_ft": 10000.0, + "target_velocity_fps": 0.0, + "target_heading_deg": 0.0, "longitudinal_acceleration_g": 0.0, "lateral_acceleration_g": 0.0, "vertical_acceleration_g": 0.0, diff --git a/target_simulator/core/command_builder.py b/target_simulator/core/command_builder.py index 92898d1..44c141f 100644 --- a/target_simulator/core/command_builder.py +++ b/target_simulator/core/command_builder.py @@ -75,6 +75,14 @@ def build_tgtset_selective(target_id: int, updates: Dict[str, Any]) -> str: ] params = [str(updates.get(key, "*")) for key in param_order] command_parts = ["tgtset", str(target_id)] + params + + qualifiers = [] + if "active" in updates: + qualifiers.append("/s" if updates["active"] else "/-s") + if "traceable" in updates: + qualifiers.append("/t" if updates["traceable"] else "/-t") + command_parts.extend(qualifiers) + full_command = " ".join(command_parts) logger.debug(f"Built selective command: {full_command!r}") return full_command diff --git a/target_simulator/gui/ppi_display.py b/target_simulator/gui/ppi_display.py index 2700b93..31b879e 100644 --- a/target_simulator/gui/ppi_display.py +++ b/target_simulator/gui/ppi_display.py @@ -24,9 +24,10 @@ class PPIDisplay(ttk.Frame): super().__init__(master) self.max_range = max_range_nm self.scan_limit_deg = scan_limit_deg - - # Artists for dynamic target display + # Artists for dynamic target display (dots, lines) self.target_artists = [] + # Artists for numeric labels next to targets + self.target_label_artists = [] self.active_targets: List[Target] = [] # Artists for trajectory preview display @@ -147,22 +148,51 @@ class PPIDisplay(ttk.Frame): def update_targets(self, targets: List[Target]): """Updates the display with the current state of active targets.""" + # Keep only active targets self.active_targets = [t for t in targets if t.active] # Clear previous target artists for artist in self.target_artists: artist.remove() self.target_artists.clear() + # Clear previous numeric label artists (avoid label accumulation) + for l in getattr(self, "target_label_artists", []): + try: + l.remove() + except Exception: + pass + self.target_label_artists.clear() - vector_len_nm = self.range_var.get() / 20.0 # Length of heading vector + vector_len_nm = max(1.0, self.range_var.get() / 20.0) # Length of heading vector + + # Ensure plot radial limit matches selected range + try: + current_range = self.range_var.get() + self.ax.set_ylim(0, current_range) + self._update_scan_lines() + except Exception: + pass + + # Diagnostic logging (kept lightweight) + try: + import logging + logger = logging.getLogger(__name__) + logger.debug("PPIDisplay.update_targets: received %d active target(s)", len(self.active_targets)) + for t in self.active_targets: + try: + logger.debug("PPIDisplay target id=%s r_nm=%.2f az=%.2f hdg=%.2f", getattr(t, 'target_id', None), getattr(t, 'current_range_nm', 0.0), getattr(t, 'current_azimuth_deg', 0.0), getattr(t, 'current_heading_deg', 0.0)) + except Exception: + pass + except Exception: + pass for target in self.active_targets: # Target's polar coordinates r_nm = target.current_range_nm theta_rad = np.deg2rad(target.current_azimuth_deg) - # Draw the target dot - (dot,) = self.ax.plot(theta_rad, r_nm, "o", markersize=6, color="red") + # Draw the target dot (slightly larger for visibility) + (dot,) = self.ax.plot(theta_rad, r_nm, "o", markersize=8, color="red") self.target_artists.append(dot) # Draw the heading vector @@ -182,7 +212,25 @@ class PPIDisplay(ttk.Frame): ) self.target_artists.append(line) - self.canvas.draw_idle() + # Add numeric label near the dot showing target id (if available) + try: + tid = getattr(target, "target_id", None) + if tid is not None: + # place label slightly outward from the dot + label_r = r_nm + (vector_len_nm * 0.7) + txt = self.ax.text(theta_rad, label_r, f"{tid}", color="white", fontsize=8, ha="center", va="center") + self.target_label_artists.append(txt) + except Exception: + pass + + # Force immediate redraw to make sure UI shows the changes + try: + self.canvas.draw() + except Exception: + try: + self.canvas.draw_idle() + except Exception: + pass def draw_trajectory_preview(self, waypoints: List[Waypoint], use_spline: bool): """ diff --git a/target_simulator/gui/sfp_debug_window.py b/target_simulator/gui/sfp_debug_window.py index 5d963c2..9714fbe 100644 --- a/target_simulator/gui/sfp_debug_window.py +++ b/target_simulator/gui/sfp_debug_window.py @@ -180,11 +180,11 @@ class SfpDebugWindow(tk.Toplevel): self.logger.exception("Toggle PPI failed") def update_ppi_targets(self, targets): - if self._ppi_visible: - try: + try: + if self.ris_ppi_widget: self.ris_ppi_widget.update_targets(targets) - except Exception: - self.logger.exception("Failed to update RIS PPI targets") + except Exception: + self.logger.exception("Failed to update RIS PPI targets") def on_ris_status_update(self, ris_status_payload): # Convert RIS targets to Target objects (minimal, for display) @@ -203,6 +203,7 @@ class SfpDebugWindow(tk.Toplevel): t.current_azimuth_deg = math.degrees(math.atan2(ris_tgt.x, ris_tgt.y)) t.current_altitude_ft = ris_tgt.z t.current_heading_deg = getattr(ris_tgt, 'heading', 0.0) + t.active = True targets.append(t) self.update_ppi_targets(targets) @@ -1000,6 +1001,89 @@ class SfpDebugWindow(tk.Toplevel): self.ris_tree.insert("", tk.END, values=(None, None, str(t.get("heading")), str(t.get("x")), str(t.get("y")), str(t.get("z")))) except Exception: pass + # --- Update PPI with active targets that fit the current PPI scale/sector --- + try: + # Only proceed if we have a PPI widget available + ppi = getattr(self, "ris_ppi_widget", None) + if ppi is not None: + ppi_targets = [] + METERS_PER_NM = 1852.0 + # Determine current display range from the PPI widget + current_range = ppi.range_var.get() if hasattr(ppi, "range_var") else ppi.max_range + # Debug: show parsed target count and sample raw values + try: + self._log_to_widget(f"PPI: parsed {len(targets)} JSON target(s); current_range={current_range}", "DEBUG") + for i, tt in enumerate(targets[:6]): + try: + fx = tt.get('flags', None) + tx = tt.get('x', None) + ty = tt.get('y', None) + tz = tt.get('z', None) + # compute derived quantities + try: + xm = float(tx) + ym = float(ty) + zm = float(tz) + rng_m = (xm * xm + ym * ym) ** 0.5 + rng_nm = rng_m / 1852.0 + az_deg = math.degrees(math.atan2(xm, ym)) + # elevation from z and slant range + elev_rad = math.atan2(zm, rng_m) if rng_m > 0 else 0.0 + elev_deg = math.degrees(elev_rad) + except Exception: + rng_m = rng_nm = az_deg = elev_deg = None + msg = f"PPI RAW[{i}]: flags={fx} x={tx} y={ty} z={tz} | range_m={rng_m:.1f} range_nm={rng_nm:.2f} az={az_deg:.2f}° elev={elev_deg:.2f}°" if rng_m is not None else f"PPI RAW[{i}]: flags={fx} x={tx} y={ty} z={tz}" + self._log_to_widget(msg, "DEBUG") + except Exception: + pass + except Exception: + pass + for t in targets: + raw_flags = t.get("flags", 0) + # Only show enabled/active targets (non-zero flags) + if int(raw_flags) == 0: + continue + x = float(t.get("x", 0.0)) + y = float(t.get("y", 0.0)) + z = float(t.get("z", 0.0)) + # Compute range in NM assuming x/y are meters + range_nm = ((x ** 2 + y ** 2) ** 0.5) / METERS_PER_NM + if range_nm > current_range: + continue + # Compute azimuth in degrees using same convention as PPIDisplay + az_deg = math.degrees(math.atan2(x, y)) + # Heading in JSON is in radians -> convert to degrees + heading = t.get("heading", 0.0) + try: + hdg_deg = float(heading) * (180.0 / math.pi) + except Exception: + hdg_deg = 0.0 + + tgt = Target(target_id=int(t.get("index", 0)), trajectory=[], active=True, traceable=True) + tgt.current_range_nm = range_nm + tgt.current_azimuth_deg = az_deg + tgt.current_heading_deg = hdg_deg + # convert altitude from meters to feet + try: + tgt.current_altitude_ft = float(z) * 3.280839895 + except Exception: + tgt.current_altitude_ft = 0.0 + tgt.active = True + ppi_targets.append(tgt) + # Push to PPI (log debug info) + try: + self._log_to_widget(f"PPI: prepared {len(ppi_targets)} target(s) for display", "DEBUG") + if ppi_targets: + for pt in ppi_targets[:5]: + self._log_to_widget( + 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) + except Exception: + self.logger.exception("Failed to push targets to PPI") + except Exception: + self.logger.exception("Error while preparing RIS targets for PPI") except Exception: pass self.after(self.GUI_POLL_INTERVAL_MS, self._process_latest_payloads) diff --git a/todo.md b/todo.md index 01ec219..293c6fe 100644 --- a/todo.md +++ b/todo.md @@ -3,13 +3,12 @@ ## bachi quando faccio la traiettoria ad alti 9 sbaglia a disegnare la curva, rivedere il caso specifico ed anche con o senza spline - +La traiettoria a 9 g viene reindirizzataa scatti invece che con una curva ## sviluppi - - +fare in modo di aggiornare la label della simulazione per evitare la scia. +girare le label sulla ppi a sinistra sono gli azimuth positivi, a destra i negativi leggere le informazioni dell'antenna del messaggio di stato -leggere la flag per capire se il target è attivo scomporre il campo flag in bit per avere le informazioni dello stato del target (attivo, tracable) fare simulazione con moviumento dell'aereo letto da protocollo visualizzare informaizoni dinamiche dell'areo durante la simulazione