sistemata visualizzazione target e scenario, aggiunta visualizzazione raw e semplificata
This commit is contained in:
parent
42f019e0a1
commit
ea7a2533c1
@ -208,7 +208,7 @@ class RisScenario(ctypes.Structure):
|
|||||||
("longitude", ctypes.c_float),
|
("longitude", ctypes.c_float),
|
||||||
("ant_nav_az", ctypes.c_float),
|
("ant_nav_az", ctypes.c_float),
|
||||||
("ant_nav_el", ctypes.c_float),
|
("ant_nav_el", ctypes.c_float),
|
||||||
("spare2", ctypes.c_uint32 * 7),
|
("spare2", ctypes.c_uint32 * 8),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -66,6 +66,38 @@ class SfpDebugWindow(tk.Toplevel):
|
|||||||
self.ip_var = tk.StringVar(value="127.0.0.1")
|
self.ip_var = tk.StringVar(value="127.0.0.1")
|
||||||
self.port_var = tk.StringVar(value="60002")
|
self.port_var = tk.StringVar(value="60002")
|
||||||
|
|
||||||
|
# Master mode names (from C++ enum ordering) — used to display readable mode
|
||||||
|
# NOTE: keep in sync with the C++ enum if it changes
|
||||||
|
self._master_mode_names = [
|
||||||
|
"idle_master_mode",
|
||||||
|
"int_bit_master_mode",
|
||||||
|
"gm_master_mode",
|
||||||
|
"dbs_master_mode",
|
||||||
|
"rws_master_mode",
|
||||||
|
"vs_master_mode",
|
||||||
|
"acm_master_mode",
|
||||||
|
"tws_master_mode",
|
||||||
|
"sea_low_master_mode",
|
||||||
|
"sea_high_master_mode",
|
||||||
|
"gmti_master_mode",
|
||||||
|
"bcn_master_mode",
|
||||||
|
"sam_master_mode",
|
||||||
|
"ta_master_mode",
|
||||||
|
"wa_master_mode",
|
||||||
|
"stt_master_mode",
|
||||||
|
"dtt_master_mode",
|
||||||
|
"sstt_master_mode",
|
||||||
|
"acq_master_mode",
|
||||||
|
"ftt_master_mode",
|
||||||
|
"agr_master_mode",
|
||||||
|
"sar_master_mode",
|
||||||
|
"invalid_master_mode_",
|
||||||
|
"xtst_dummy_mode",
|
||||||
|
"xtst_hw_validation_mode",
|
||||||
|
"boot_master_mode",
|
||||||
|
"master_mode_id_cardinality_",
|
||||||
|
]
|
||||||
|
|
||||||
# --- Connection Frame (IP / Port / Connect controls) ---
|
# --- Connection Frame (IP / Port / Connect controls) ---
|
||||||
conn_frame = ttk.Frame(self)
|
conn_frame = ttk.Frame(self)
|
||||||
conn_frame.pack(side=tk.TOP, fill=tk.X, padx=5, pady=(5, 2))
|
conn_frame.pack(side=tk.TOP, fill=tk.X, padx=5, pady=(5, 2))
|
||||||
@ -611,6 +643,27 @@ class SfpDebugWindow(tk.Toplevel):
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
struct = json.loads(payload.decode("utf-8")) if isinstance(payload, (bytes, bytearray)) else payload
|
struct = json.loads(payload.decode("utf-8")) if isinstance(payload, (bytes, bytearray)) else payload
|
||||||
|
# Debug: log keys and a short sample of the payload to help
|
||||||
|
# diagnose any label/value mismatches coming from the server.
|
||||||
|
try:
|
||||||
|
if isinstance(struct, dict):
|
||||||
|
scenario_preview = struct.get("scenario")
|
||||||
|
#self.logger.debug("RIS payload keys: %s", list(struct.keys()))
|
||||||
|
#if isinstance(scenario_preview, dict):
|
||||||
|
#self.logger.debug("RIS scenario keys: %s", list(scenario_preview.keys()))
|
||||||
|
targets_preview = struct.get("targets")
|
||||||
|
if isinstance(targets_preview, list):
|
||||||
|
sample_keys = [list(t.keys()) for t in targets_preview[:3] if isinstance(t, dict)]
|
||||||
|
#self.logger.debug("RIS targets sample keys (first 3): %s", sample_keys)
|
||||||
|
# Also put a concise message in the Raw Log widget for convenience
|
||||||
|
try:
|
||||||
|
msg = f"RIS JSON: scenario_keys={len(scenario_preview) if isinstance(scenario_preview, dict) else 0}, targets={len(targets_preview) if isinstance(targets_preview, list) else 0}"
|
||||||
|
#self._log_to_widget(msg, "DEBUG")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
except Exception:
|
||||||
|
# Never raise from debug logging
|
||||||
|
pass
|
||||||
# scenario table (field, value)
|
# scenario table (field, value)
|
||||||
for iid in self.scenario_tree.get_children():
|
for iid in self.scenario_tree.get_children():
|
||||||
self.scenario_tree.delete(iid)
|
self.scenario_tree.delete(iid)
|
||||||
@ -671,6 +724,15 @@ class SfpDebugWindow(tk.Toplevel):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return str(v)
|
return str(v)
|
||||||
|
|
||||||
|
def try_float(v):
|
||||||
|
"""Attempt to convert value to float; return None on failure."""
|
||||||
|
try:
|
||||||
|
return float(v)
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# collect rows first so we can log the exact label->value mapping
|
||||||
|
scenario_rows = []
|
||||||
for label, key, unit in order:
|
for label, key, unit in order:
|
||||||
if key in scenario:
|
if key in scenario:
|
||||||
val = scenario.get(key)
|
val = scenario.get(key)
|
||||||
@ -691,33 +753,38 @@ class SfpDebugWindow(tk.Toplevel):
|
|||||||
else:
|
else:
|
||||||
# simplified view: show converted value and unit adjacent to number
|
# simplified view: show converted value and unit adjacent to number
|
||||||
if key in ("platform_azimuth", "true_heading"):
|
if key in ("platform_azimuth", "true_heading"):
|
||||||
if isinstance(val, (int, float)):
|
fv = try_float(val)
|
||||||
conv = to_deg(val)
|
if fv is not None:
|
||||||
|
conv = to_deg(fv)
|
||||||
display_val = fmt_simplified_number(conv, "°", dec_simp)
|
display_val = fmt_simplified_number(conv, "°", dec_simp)
|
||||||
else:
|
else:
|
||||||
display_val = str(val)
|
display_val = str(val)
|
||||||
elif key in ("ant_nav_az", "ant_nav_el"):
|
elif key in ("ant_nav_az", "ant_nav_el"):
|
||||||
if isinstance(val, (int, float)):
|
fv = try_float(val)
|
||||||
conv = to_deg(val)
|
if fv is not None:
|
||||||
|
conv = to_deg(fv)
|
||||||
display_val = fmt_simplified_number(conv, "°", dec_simp)
|
display_val = fmt_simplified_number(conv, "°", dec_simp)
|
||||||
else:
|
else:
|
||||||
display_val = str(val)
|
display_val = str(val)
|
||||||
elif key in ("vx", "vy", "vz"):
|
elif key in ("vx", "vy", "vz"):
|
||||||
if isinstance(val, (int, float)):
|
fv = try_float(val)
|
||||||
conv = m_s_to_ft_s(val)
|
if fv is not None:
|
||||||
|
conv = m_s_to_ft_s(fv)
|
||||||
display_val = fmt_simplified_number(conv, "ft/s", dec_simp)
|
display_val = fmt_simplified_number(conv, "ft/s", dec_simp)
|
||||||
else:
|
else:
|
||||||
display_val = str(val)
|
display_val = str(val)
|
||||||
elif key == "baro_altitude":
|
elif key == "baro_altitude":
|
||||||
if isinstance(val, (int, float)):
|
fv = try_float(val)
|
||||||
conv = m_to_ft(val)
|
if fv is not None:
|
||||||
|
conv = m_to_ft(fv)
|
||||||
display_val = fmt_simplified_number(conv, "ft", dec_simp)
|
display_val = fmt_simplified_number(conv, "ft", dec_simp)
|
||||||
else:
|
else:
|
||||||
display_val = str(val)
|
display_val = str(val)
|
||||||
elif key in ("latitude", "longitude"):
|
elif key in ("latitude", "longitude"):
|
||||||
if isinstance(val, (int, float)):
|
fv = try_float(val)
|
||||||
|
if fv is not None:
|
||||||
# show decimal degrees with higher precision per request
|
# show decimal degrees with higher precision per request
|
||||||
display_val = f"{float(val):.{8}f} °"
|
display_val = f"{fv:.{8}f} °"
|
||||||
else:
|
else:
|
||||||
display_val = str(val)
|
display_val = str(val)
|
||||||
elif key == "flags":
|
elif key == "flags":
|
||||||
@ -726,12 +793,41 @@ class SfpDebugWindow(tk.Toplevel):
|
|||||||
except Exception:
|
except Exception:
|
||||||
display_val = str(val)
|
display_val = str(val)
|
||||||
elif key == "mode":
|
elif key == "mode":
|
||||||
display_val = str(int(val)) if isinstance(val, (int, float)) else str(val)
|
# Map numeric mode to human-friendly short name
|
||||||
|
try:
|
||||||
|
midx = int(val)
|
||||||
|
if 0 <= midx < len(self._master_mode_names):
|
||||||
|
name = self._master_mode_names[midx]
|
||||||
|
# strip trailing parts like '_master_mode' or '_mode' or trailing underscores
|
||||||
|
short = name
|
||||||
|
for suffix in ("_master_mode", "_mode", "_master_mode_", "_"):
|
||||||
|
if short.endswith(suffix):
|
||||||
|
short = short[: -len(suffix)]
|
||||||
|
# also remove any remaining 'master' parts
|
||||||
|
short = short.replace("master", "").strip("_")
|
||||||
|
display_val = short
|
||||||
|
else:
|
||||||
|
display_val = str(midx)
|
||||||
|
except Exception:
|
||||||
|
display_val = str(val)
|
||||||
else:
|
else:
|
||||||
display_val = str(val)
|
display_val = str(val)
|
||||||
|
|
||||||
# Show label without unit; unit is appended to the value in simplified view
|
# collect the pair for logging and insertion
|
||||||
self.scenario_tree.insert("", tk.END, values=(f"{label}", display_val))
|
scenario_rows.append((label, display_val))
|
||||||
|
|
||||||
|
# Log the label->value pairs for diagnosis (concise)
|
||||||
|
try:
|
||||||
|
preview = ", ".join(f"{l}={v}" for l, v in scenario_rows)
|
||||||
|
#self.logger.debug("Scenario label->value: %s", preview)
|
||||||
|
# also write a shorter message to Raw Log for visibility
|
||||||
|
#self._log_to_widget(f"Scenario preview: {preview}", "DEBUG")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Now insert collected rows into the Treeview
|
||||||
|
for l, v in scenario_rows:
|
||||||
|
self.scenario_tree.insert("", tk.END, values=(f"{l}", v))
|
||||||
|
|
||||||
# targets
|
# targets
|
||||||
for iid in self.ris_tree.get_children():
|
for iid in self.ris_tree.get_children():
|
||||||
@ -751,28 +847,37 @@ class SfpDebugWindow(tk.Toplevel):
|
|||||||
view_mode = self.scenario_view_mode.get() if hasattr(self, "scenario_view_mode") else "simplified"
|
view_mode = self.scenario_view_mode.get() if hasattr(self, "scenario_view_mode") else "simplified"
|
||||||
dec_simp = int(self.simplified_decimals.get() if hasattr(self, "simplified_decimals") else 4)
|
dec_simp = int(self.simplified_decimals.get() if hasattr(self, "simplified_decimals") else 4)
|
||||||
for t in targets:
|
for t in targets:
|
||||||
|
try:
|
||||||
|
# normalize index (accept common aliases)
|
||||||
|
idx = t.get("index")
|
||||||
|
if idx is None:
|
||||||
|
idx = t.get("idx")
|
||||||
|
if idx is None:
|
||||||
|
idx = t.get("#")
|
||||||
|
|
||||||
|
# normalize flags and format consistently
|
||||||
|
raw_flags = t.get("flags", t.get("flag", 0))
|
||||||
|
try:
|
||||||
|
flags_val = int(raw_flags)
|
||||||
|
flags_display = f"{flags_val} (0x{flags_val:X})"
|
||||||
|
except Exception:
|
||||||
|
flags_display = str(raw_flags)
|
||||||
|
|
||||||
if view_mode == "raw":
|
if view_mode == "raw":
|
||||||
# format raw with reasonable precision
|
# format raw with reasonable precision using try_float
|
||||||
try:
|
hfv = try_float(t.get("heading"))
|
||||||
heading_raw = float(t.get("heading"))
|
heading_val = f"{hfv:.6f}" if hfv is not None else str(t.get("heading"))
|
||||||
heading_val = f"{heading_raw:.6f}"
|
|
||||||
except Exception:
|
xfv = try_float(t.get("x"))
|
||||||
heading_val = str(t.get("heading"))
|
yfv = try_float(t.get("y"))
|
||||||
try:
|
zfv = try_float(t.get("z"))
|
||||||
x_raw = float(t.get("x"))
|
x_val = f"{xfv:.6f}" if xfv is not None else t.get("x")
|
||||||
y_raw = float(t.get("y"))
|
y_val = f"{yfv:.6f}" if yfv is not None else t.get("y")
|
||||||
z_raw = float(t.get("z"))
|
z_val = f"{zfv:.6f}" if zfv is not None else t.get("z")
|
||||||
x_val = f"{x_raw:.6f}"
|
|
||||||
y_val = f"{y_raw:.6f}"
|
|
||||||
z_val = f"{z_raw:.6f}"
|
|
||||||
except Exception:
|
|
||||||
x_val = t.get("x")
|
|
||||||
y_val = t.get("y")
|
|
||||||
z_val = t.get("z")
|
|
||||||
|
|
||||||
vals = (
|
vals = (
|
||||||
t.get("index"),
|
idx,
|
||||||
t.get("flags"),
|
flags_display,
|
||||||
heading_val,
|
heading_val,
|
||||||
x_val,
|
x_val,
|
||||||
y_val,
|
y_val,
|
||||||
@ -780,34 +885,44 @@ class SfpDebugWindow(tk.Toplevel):
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# simplified: converted values with units next to number
|
# simplified: converted values with units next to number
|
||||||
try:
|
hfv = try_float(t.get("heading"))
|
||||||
heading = float(t.get("heading"))
|
if hfv is not None:
|
||||||
heading_deg = heading * (180.0 / 3.141592653589793)
|
heading_deg = hfv * (180.0 / 3.141592653589793)
|
||||||
heading_val = f"{heading_deg:.{dec_simp}f} °"
|
heading_val = f"{heading_deg:.{dec_simp}f} °"
|
||||||
except Exception:
|
else:
|
||||||
heading_val = str(t.get("heading"))
|
heading_val = str(t.get("heading"))
|
||||||
try:
|
|
||||||
x = float(t.get("x"))
|
xfv = try_float(t.get("x"))
|
||||||
y = float(t.get("y"))
|
yfv = try_float(t.get("y"))
|
||||||
z_m = float(t.get("z"))
|
zfv = try_float(t.get("z"))
|
||||||
x_val = f"{x:.{dec_simp}f} m"
|
x_val = f"{xfv:.{dec_simp}f} m" if xfv is not None else str(t.get("x"))
|
||||||
y_val = f"{y:.{dec_simp}f} m"
|
y_val = f"{yfv:.{dec_simp}f} m" if yfv is not None else str(t.get("y"))
|
||||||
z_val = f"{(z_m * 3.280839895):.{dec_simp}f} ft"
|
if zfv is not None:
|
||||||
except Exception:
|
z_val = f"{(zfv * 3.280839895):.{dec_simp}f} ft"
|
||||||
x_val = str(t.get("x"))
|
else:
|
||||||
y_val = str(t.get("y"))
|
|
||||||
z_val = str(t.get("z"))
|
z_val = str(t.get("z"))
|
||||||
|
|
||||||
vals = (
|
vals = (
|
||||||
t.get("index"),
|
idx,
|
||||||
t.get("flags"),
|
flags_display,
|
||||||
heading_val,
|
heading_val,
|
||||||
x_val,
|
x_val,
|
||||||
y_val,
|
y_val,
|
||||||
z_val,
|
z_val,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# ensure we always insert a 6-tuple (Treeview expects 6 columns)
|
||||||
|
if not isinstance(vals, (list, tuple)) or len(vals) != 6:
|
||||||
|
# fallback: make a safe 6-element tuple
|
||||||
|
vals = (idx, flags_display, "", "", "", "")
|
||||||
|
|
||||||
self.ris_tree.insert("", tk.END, values=vals)
|
self.ris_tree.insert("", tk.END, values=vals)
|
||||||
|
except Exception as _e:
|
||||||
|
# on malformed target entries, insert a visible placeholder
|
||||||
|
try:
|
||||||
|
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
|
||||||
except Exception:
|
except Exception:
|
||||||
# ignore malformed JSON for now
|
# ignore malformed JSON for now
|
||||||
pass
|
pass
|
||||||
|
|||||||
17
todo.md
Normal file
17
todo.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
code da fare
|
||||||
|
|
||||||
|
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
|
||||||
|
sull'edito, se seleziono una manovra, vederla colorata di un altro colore sulla preview per capire cosa sto toccando.
|
||||||
|
aggiungere visualizzazione nell'editor su ris_status in questo modo:
|
||||||
|
1) dati raw, dati come vengono spediti, senza conversioni
|
||||||
|
2) dati convertiti secondo intefaccia gui del mission computer
|
||||||
|
3) dati dei target in range/elevation
|
||||||
|
|
||||||
|
la visualizzazione ppi in simulazione se tiene conto della rotazione del ptazimuth dovrebbe ruotare in modo che il cono di scansione dell'antenna si muove
|
||||||
|
di conseguenza. Immagino che la mappa ppi sia sempre diretta a nord, quindi quando io con l'aereo vado a nord tutto torna
|
||||||
|
se invece cambio direzione dell'aereo la mappa ruota e quindi ruotano anche le label attorno in modo che siano sempre riferite al muso dell'aereo.
|
||||||
|
Quindi dovremmo inserire una nuova legenda oltre a quella attuale che indichi che il nord è sempra. per ricordare all'utente che la ppi è verso l'alto.
|
||||||
Loading…
Reference in New Issue
Block a user