aggiunta la scelta tra raw e simplied, ed il numero di decimali
This commit is contained in:
parent
36e6e8d335
commit
42f019e0a1
@ -161,6 +161,26 @@ class SfpDebugWindow(tk.Toplevel):
|
|||||||
# Save CSV button under the paned window
|
# Save CSV button under the paned window
|
||||||
btn_frame = ttk.Frame(ris_frame)
|
btn_frame = ttk.Frame(ris_frame)
|
||||||
btn_frame.pack(fill=tk.X, padx=5, pady=(0, 5))
|
btn_frame.pack(fill=tk.X, padx=5, pady=(0, 5))
|
||||||
|
# View mode for scenario/targets: raw vs simplified
|
||||||
|
self.scenario_view_mode = tk.StringVar(value="simplified")
|
||||||
|
mode_frame = ttk.Frame(btn_frame)
|
||||||
|
mode_frame.pack(side=tk.LEFT, padx=(4, 0))
|
||||||
|
ttk.Label(mode_frame, text="View:").pack(side=tk.LEFT, padx=(0, 6))
|
||||||
|
ttk.Radiobutton(mode_frame, text="Raw", value="raw", variable=self.scenario_view_mode).pack(side=tk.LEFT)
|
||||||
|
ttk.Radiobutton(mode_frame, text="Simplified", value="simplified", variable=self.scenario_view_mode).pack(side=tk.LEFT)
|
||||||
|
|
||||||
|
# Decimals control for simplified view (user-settable)
|
||||||
|
self.simplified_decimals = tk.IntVar(value=4)
|
||||||
|
ttk.Label(mode_frame, text=" Decimals:").pack(side=tk.LEFT, padx=(8, 2))
|
||||||
|
try:
|
||||||
|
# Use tk.Spinbox; ttk.Spinbox may not be available in all tkinter versions
|
||||||
|
sp = tk.Spinbox(mode_frame, from_=0, to=8, width=3, textvariable=self.simplified_decimals)
|
||||||
|
sp.pack(side=tk.LEFT)
|
||||||
|
except Exception:
|
||||||
|
# fallback to an Entry if Spinbox is not supported
|
||||||
|
e = ttk.Entry(mode_frame, textvariable=self.simplified_decimals, width=3)
|
||||||
|
e.pack(side=tk.LEFT)
|
||||||
|
|
||||||
self.ris_save_csv_btn = ttk.Button(btn_frame, text="Save CSV", command=lambda: self._on_save_ris_csv())
|
self.ris_save_csv_btn = ttk.Button(btn_frame, text="Save CSV", command=lambda: self._on_save_ris_csv())
|
||||||
self.ris_save_csv_btn.pack(side=tk.RIGHT)
|
self.ris_save_csv_btn.pack(side=tk.RIGHT)
|
||||||
|
|
||||||
@ -596,11 +616,6 @@ class SfpDebugWindow(tk.Toplevel):
|
|||||||
self.scenario_tree.delete(iid)
|
self.scenario_tree.delete(iid)
|
||||||
scenario = struct.get("scenario", {}) if isinstance(struct, dict) else {}
|
scenario = struct.get("scenario", {}) if isinstance(struct, dict) else {}
|
||||||
if scenario:
|
if scenario:
|
||||||
# Insert in deterministic order and convert to human-friendly units
|
|
||||||
# Conversions inferred from C++ implementation:
|
|
||||||
# - angles are sent in radians -> display degrees
|
|
||||||
# - velocities are m/s -> display ft/s
|
|
||||||
# - altitudes are meters -> display feet
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
def to_deg(v):
|
def to_deg(v):
|
||||||
@ -636,101 +651,162 @@ class SfpDebugWindow(tk.Toplevel):
|
|||||||
("longitude", "longitude", "°"),
|
("longitude", "longitude", "°"),
|
||||||
("true_heading", "true_heading", "°"),
|
("true_heading", "true_heading", "°"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
def fmt_raw_number(v, key_name=None):
|
||||||
|
try:
|
||||||
|
fv = float(v)
|
||||||
|
if key_name in ("latitude", "longitude"):
|
||||||
|
return f"{fv:.8f}"
|
||||||
|
return f"{fv:.6f}"
|
||||||
|
except Exception:
|
||||||
|
return str(v)
|
||||||
|
|
||||||
|
def fmt_simplified_number(v, unit_str, decimals=4):
|
||||||
|
try:
|
||||||
|
fv = float(v)
|
||||||
|
return f"{fv:.{decimals}f} {unit_str}" if unit_str else f"{fv:.{decimals}f}"
|
||||||
|
except Exception:
|
||||||
|
return str(v)
|
||||||
|
|
||||||
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)
|
||||||
# apply conversions and show raw in parentheses
|
if view_mode == "raw":
|
||||||
if key == "platform_azimuth" or key == "true_heading":
|
if key in ("platform_azimuth", "true_heading", "ant_nav_az", "ant_nav_el"):
|
||||||
if isinstance(val, (int, float)):
|
display_val = fmt_raw_number(val, key)
|
||||||
conv = to_deg(val)
|
elif key in ("vx", "vy", "vz", "baro_altitude"):
|
||||||
display_val = f"{conv:.6f} ° ({val:.6f} rad)"
|
display_val = fmt_raw_number(val, key)
|
||||||
else:
|
elif key in ("latitude", "longitude"):
|
||||||
display_val = val
|
display_val = fmt_raw_number(val, key)
|
||||||
elif key in ("ant_nav_az", "ant_nav_el"):
|
elif key == "flags":
|
||||||
# antenna angles, display degrees with raw radians
|
try:
|
||||||
if isinstance(val, (int, float)):
|
display_val = f"{int(val)} (0x{int(val):X})"
|
||||||
conv = to_deg(val)
|
except Exception:
|
||||||
display_val = f"{conv:.6f} ° ({val:.6f} rad)"
|
display_val = str(val)
|
||||||
else:
|
else:
|
||||||
display_val = val
|
display_val = str(val)
|
||||||
|
else:
|
||||||
|
# simplified view: show converted value and unit adjacent to number
|
||||||
|
if key in ("platform_azimuth", "true_heading"):
|
||||||
|
if isinstance(val, (int, float)):
|
||||||
|
conv = to_deg(val)
|
||||||
|
display_val = fmt_simplified_number(conv, "°", dec_simp)
|
||||||
|
else:
|
||||||
|
display_val = str(val)
|
||||||
|
elif key in ("ant_nav_az", "ant_nav_el"):
|
||||||
|
if isinstance(val, (int, float)):
|
||||||
|
conv = to_deg(val)
|
||||||
|
display_val = fmt_simplified_number(conv, "°", dec_simp)
|
||||||
|
else:
|
||||||
|
display_val = str(val)
|
||||||
|
elif key in ("vx", "vy", "vz"):
|
||||||
|
if isinstance(val, (int, float)):
|
||||||
|
conv = m_s_to_ft_s(val)
|
||||||
|
display_val = fmt_simplified_number(conv, "ft/s", dec_simp)
|
||||||
|
else:
|
||||||
|
display_val = str(val)
|
||||||
|
elif key == "baro_altitude":
|
||||||
|
if isinstance(val, (int, float)):
|
||||||
|
conv = m_to_ft(val)
|
||||||
|
display_val = fmt_simplified_number(conv, "ft", dec_simp)
|
||||||
|
else:
|
||||||
|
display_val = str(val)
|
||||||
|
elif key in ("latitude", "longitude"):
|
||||||
|
if isinstance(val, (int, float)):
|
||||||
|
# show decimal degrees with higher precision per request
|
||||||
|
display_val = f"{float(val):.{8}f} °"
|
||||||
|
else:
|
||||||
|
display_val = str(val)
|
||||||
elif key == "flags":
|
elif key == "flags":
|
||||||
# show flags as int and hex
|
|
||||||
try:
|
try:
|
||||||
display_val = f"{int(val)} (0x{int(val):X})"
|
display_val = f"{int(val)} (0x{int(val):X})"
|
||||||
except Exception:
|
except Exception:
|
||||||
display_val = str(val)
|
display_val = str(val)
|
||||||
elif key == "mode":
|
elif key == "mode":
|
||||||
# mode is an integer code
|
display_val = str(int(val)) if isinstance(val, (int, float)) else str(val)
|
||||||
try:
|
else:
|
||||||
display_val = str(int(val))
|
|
||||||
except Exception:
|
|
||||||
display_val = str(val)
|
display_val = str(val)
|
||||||
elif key in ("vx", "vy", "vz"):
|
|
||||||
if isinstance(val, (int, float)):
|
# Show label without unit; unit is appended to the value in simplified view
|
||||||
conv = m_s_to_ft_s(val)
|
self.scenario_tree.insert("", tk.END, values=(f"{label}", display_val))
|
||||||
display_val = f"{conv:.3f} ft/s ({val:.3f} m/s)"
|
|
||||||
else:
|
|
||||||
display_val = val
|
|
||||||
elif key == "baro_altitude":
|
|
||||||
if isinstance(val, (int, float)):
|
|
||||||
conv = m_to_ft(val)
|
|
||||||
display_val = f"{conv:.3f} ft ({val:.3f} m)"
|
|
||||||
else:
|
|
||||||
display_val = val
|
|
||||||
elif key in ("latitude", "longitude"):
|
|
||||||
if isinstance(val, (int, float)):
|
|
||||||
# Show decimal degrees and DMS (alt display)
|
|
||||||
dd = float(val)
|
|
||||||
deg = int(dd)
|
|
||||||
md = abs((dd - deg) * 60)
|
|
||||||
minutes = int(md)
|
|
||||||
seconds = (md - minutes) * 60
|
|
||||||
dms = f"{deg}°{minutes:02d}'{seconds:.3f}\""
|
|
||||||
display_val = f"{dd:.9f} ° ({dms})"
|
|
||||||
else:
|
|
||||||
display_val = val
|
|
||||||
else:
|
|
||||||
display_val = val
|
|
||||||
self.scenario_tree.insert("", tk.END, values=(f"{label} {('('+unit+')' if unit else '')}", display_val))
|
|
||||||
|
|
||||||
# targets
|
# targets
|
||||||
for iid in self.ris_tree.get_children():
|
for iid in self.ris_tree.get_children():
|
||||||
self.ris_tree.delete(iid)
|
self.ris_tree.delete(iid)
|
||||||
targets = struct.get("targets", []) if isinstance(struct, dict) else []
|
targets = struct.get("targets", []) if isinstance(struct, dict) else []
|
||||||
# Update target column headers to show units
|
# Update target column headers to show units depending on view
|
||||||
try:
|
try:
|
||||||
self.ris_tree.heading("heading", text="heading (°)")
|
view_mode = self.scenario_view_mode.get() if hasattr(self, "scenario_view_mode") else "simplified"
|
||||||
self.ris_tree.heading("x", text="x (m)")
|
# Column headers should be plain; units shown next to values
|
||||||
self.ris_tree.heading("y", text="y (m)")
|
self.ris_tree.heading("heading", text="heading")
|
||||||
self.ris_tree.heading("z", text="z (ft)")
|
self.ris_tree.heading("x", text="x")
|
||||||
|
self.ris_tree.heading("y", text="y")
|
||||||
|
self.ris_tree.heading("z", text="z")
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
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)
|
||||||
for t in targets:
|
for t in targets:
|
||||||
# Convert heading (rad->deg) and z (m->ft)
|
if view_mode == "raw":
|
||||||
|
# format raw with reasonable precision
|
||||||
try:
|
try:
|
||||||
heading = float(t.get("heading"))
|
heading_raw = float(t.get("heading"))
|
||||||
heading_deg = heading * (180.0 / 3.141592653589793)
|
heading_val = f"{heading_raw:.6f}"
|
||||||
except Exception:
|
except Exception:
|
||||||
heading_deg = t.get("heading")
|
heading_val = str(t.get("heading"))
|
||||||
try:
|
try:
|
||||||
x = float(t.get("x"))
|
x_raw = float(t.get("x"))
|
||||||
y = float(t.get("y"))
|
y_raw = float(t.get("y"))
|
||||||
z_m = float(t.get("z"))
|
z_raw = float(t.get("z"))
|
||||||
z_ft = z_m * 3.280839895
|
x_val = f"{x_raw:.6f}"
|
||||||
|
y_val = f"{y_raw:.6f}"
|
||||||
|
z_val = f"{z_raw:.6f}"
|
||||||
except Exception:
|
except Exception:
|
||||||
x = t.get("x")
|
x_val = t.get("x")
|
||||||
y = t.get("y")
|
y_val = t.get("y")
|
||||||
z_ft = t.get("z")
|
z_val = t.get("z")
|
||||||
|
|
||||||
vals = (
|
vals = (
|
||||||
t.get("index"),
|
t.get("index"),
|
||||||
t.get("flags"),
|
t.get("flags"),
|
||||||
f"{heading_deg:.3f} ° ({t.get('heading')})",
|
heading_val,
|
||||||
f"{x:.3f} m ({t.get('x')})",
|
x_val,
|
||||||
f"{y:.3f} m ({t.get('y')})",
|
y_val,
|
||||||
f"{z_ft:.3f} ft ({t.get('z')})",
|
z_val,
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
# simplified: converted values with units next to number
|
||||||
|
try:
|
||||||
|
heading = float(t.get("heading"))
|
||||||
|
heading_deg = heading * (180.0 / 3.141592653589793)
|
||||||
|
heading_val = f"{heading_deg:.{dec_simp}f} °"
|
||||||
|
except Exception:
|
||||||
|
heading_val = str(t.get("heading"))
|
||||||
|
try:
|
||||||
|
x = float(t.get("x"))
|
||||||
|
y = float(t.get("y"))
|
||||||
|
z_m = float(t.get("z"))
|
||||||
|
x_val = f"{x:.{dec_simp}f} m"
|
||||||
|
y_val = f"{y:.{dec_simp}f} m"
|
||||||
|
z_val = f"{(z_m * 3.280839895):.{dec_simp}f} ft"
|
||||||
|
except Exception:
|
||||||
|
x_val = str(t.get("x"))
|
||||||
|
y_val = str(t.get("y"))
|
||||||
|
z_val = str(t.get("z"))
|
||||||
|
|
||||||
|
vals = (
|
||||||
|
t.get("index"),
|
||||||
|
t.get("flags"),
|
||||||
|
heading_val,
|
||||||
|
x_val,
|
||||||
|
y_val,
|
||||||
|
z_val,
|
||||||
|
)
|
||||||
|
|
||||||
self.ris_tree.insert("", tk.END, values=vals)
|
self.ris_tree.insert("", tk.END, values=vals)
|
||||||
except Exception:
|
except Exception:
|
||||||
# ignore malformed JSON for now
|
# ignore malformed JSON for now
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user