inseriti i dati lat/lon nel file di salvataggio della simulazione

This commit is contained in:
VALLONGOL 2025-11-05 12:29:40 +01:00
parent bd12263616
commit 11dc033944
3 changed files with 109 additions and 3 deletions

View File

@ -93,7 +93,10 @@ class AnalysisWindow(tk.Toplevel):
self._update_stats_table(analysis_results[sel_id]) self._update_stats_table(analysis_results[sel_id])
self._update_plot(sel_id) self._update_plot(sel_id)
else: else:
self._clear_views() # Provide diagnostic information when analysis cannot be
# produced for the selected target (common cause: no
# overlapping timestamps between simulated and real samples).
self._show_insufficient_data_info(sel_id)
def _create_widgets(self): def _create_widgets(self):
main_pane = ttk.PanedWindow(self, orient=tk.VERTICAL) main_pane = ttk.PanedWindow(self, orient=tk.VERTICAL)
@ -305,6 +308,74 @@ class AnalysisWindow(tk.Toplevel):
self.ax.autoscale_view() self.ax.autoscale_view()
self.canvas.draw_idle() self.canvas.draw_idle()
def _show_insufficient_data_info(self, target_id: int):
"""Display helpful information in the stats table when a target
cannot be analyzed (for example because simulated and real time
ranges do not overlap). This avoids an empty UI and gives the
user actionable context.
"""
try:
# Clear previous contents
self.stats_tree.delete(*self.stats_tree.get_children())
history = self._hub.get_target_history(target_id)
if history is None:
self.stats_tree.insert("", "end", values=("Info", "Target not found", "", ""))
self._clear_views()
return
sim_times = [s[0] for s in history.get("simulated", [])]
real_times = [r[0] for r in history.get("real", [])]
sim_count = len(sim_times)
real_count = len(real_times)
sim_range = (
(min(sim_times), max(sim_times)) if sim_times else (None, None)
)
real_range = (
(min(real_times), max(real_times)) if real_times else (None, None)
)
# populate the small table with human-readable diagnostic rows
self.stats_tree.insert(
"",
"end",
values=("Info", f"Target {target_id}", "", ""),
)
self.stats_tree.insert(
"",
"end",
values=("Sim samples", str(sim_count), "", ""),
)
self.stats_tree.insert(
"",
"end",
values=("Sim time range", f"{sim_range[0]} -> {sim_range[1]}", "", ""),
)
self.stats_tree.insert(
"",
"end",
values=("Real samples", str(real_count), "", ""),
)
self.stats_tree.insert(
"",
"end",
values=("Real time range", f"{real_range[0]} -> {real_range[1]}", "", ""),
)
# keep plot cleared
self.line_x.set_data([], [])
self.line_y.set_data([], [])
self.line_z.set_data([], [])
self.ax.relim()
self.ax.autoscale_view()
self.canvas.draw_idle()
except Exception:
# Fail silently to avoid breaking the analysis window; show
# the cleared view as a fallback.
self._clear_views()
def _on_close(self): def _on_close(self):
self._active = False self._active = False
self.destroy() self.destroy()

View File

@ -85,6 +85,10 @@ class PPIDisplay(ttk.Frame):
"next_ts": None, "next_ts": None,
"animating": False, "animating": False,
"tick_ms": 33, "tick_ms": 33,
# When no new antenna timestamps arrive, perform a small
# continuous idle sweep so the UI remains visually active.
# Degrees per second to rotate while idle (fallback).
"idle_rotation_deg_per_s": 30.0,
} }
self._antenna_line_artist: mpl.lines.Line2D | None = None self._antenna_line_artist: mpl.lines.Line2D | None = None
@ -533,8 +537,25 @@ class PPIDisplay(ttk.Frame):
return return
if next_ts <= last_ts: if next_ts <= last_ts:
cur = next_az # No upcoming timestamp to interpolate towards. Instead
st["animating"] = False # perform a small idle rotation so the antenna appears to
# sweep even when updates are sparse or timestamps do not
# advance. This keeps the UI lively and avoids a static
# antenna when the data source doesn't provide frequent
# azimuth samples.
try:
idle_speed = float(st.get("idle_rotation_deg_per_s", 30.0))
# rotate since last_ts using idle speed
dt = max(0.0, now - (last_ts or now))
cur = (last_az + idle_speed * dt) % 360
# update last_ts so subsequent steps continue smoothly
st["last_ts"] = now
st["last_az_deg"] = cur
# keep animating until explicit stop
st["animating"] = True
except Exception:
cur = next_az
st["animating"] = False
else: else:
frac = max(0.0, min(1.0, (now - last_ts) / (next_ts - last_ts))) frac = max(0.0, min(1.0, (now - last_ts) / (next_ts - last_ts)))
diff = ((next_az - last_az + 180) % 360) - 180 diff = ((next_az - last_az + 180) % 360) - 180

14
tools/scan_archives.py Normal file
View File

@ -0,0 +1,14 @@
import json, os
folder = r'c:\src\____GitProjects\target_simulator\archive_simulations'
for fn in os.listdir(folder):
if not fn.endswith('.json'):
continue
p = os.path.join(folder, fn)
try:
with open(p,'r',encoding='utf-8') as f:
j = json.load(f)
except Exception:
continue
n = len(j.get('simulation_results', {}))
if n >= 3:
print(fn, n)