diff --git a/target_simulator/core/sfp_structures.py b/target_simulator/core/sfp_structures.py index 390e763..5619adb 100644 --- a/target_simulator/core/sfp_structures.py +++ b/target_simulator/core/sfp_structures.py @@ -220,7 +220,9 @@ class RisTargetsBlock(ctypes.Structure): class SfpRisStatusPayload(ctypes.Structure): _pack_ = 1 _fields_ = [ + ("scenario_tag", DataTag), ("scenario", RisScenario), + ("target_tag", DataTag), ("tgt", RisTargetsBlock), ] diff --git a/target_simulator/gui/sfp_debug_window.py b/target_simulator/gui/sfp_debug_window.py index 1d8e226..c4e6031 100644 --- a/target_simulator/gui/sfp_debug_window.py +++ b/target_simulator/gui/sfp_debug_window.py @@ -591,34 +591,95 @@ class SfpDebugWindow(tk.Toplevel): self.scenario_tree.delete(iid) scenario = struct.get("scenario", {}) if isinstance(struct, dict) else {} if scenario: - # Insert in deterministic order + # 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 + + def to_deg(v): + try: + return float(v) * (180.0 / math.pi) + except Exception: + return v + + def m_s_to_ft_s(v): + try: + return float(v) * 3.280839895 + except Exception: + return v + + def m_to_ft(v): + try: + return float(v) * 3.280839895 + except Exception: + return v + order = [ - ("timetag", "timetag"), - ("platform_azimuth", "platform_azimuth"), - ("vx", "vx"), - ("vy", "vy"), - ("vz", "vz"), - ("baro_altitude", "baro_altitude"), - ("latitude", "latitude"), - ("longitude", "longitude"), - ("true_heading", "true_heading"), + ("timetag", "timetag", ""), + ("platform_azimuth", "platform_azimuth", "°"), + ("vx", "vx", "ft/s"), + ("vy", "vy", "ft/s"), + ("vz", "vz", "ft/s"), + ("baro_altitude", "baro_altitude", "ft"), + ("latitude", "latitude", "°"), + ("longitude", "longitude", "°"), + ("true_heading", "true_heading", "°"), ] - for label, key in order: + for label, key, unit in order: if key in scenario: - self.scenario_tree.insert("", tk.END, values=(label, scenario.get(key))) + val = scenario.get(key) + # apply conversions + if key == "platform_azimuth" or key == "true_heading": + display_val = f"{to_deg(val):.6f} {unit}" if isinstance(val, (int, float)) else val + elif key in ("vx", "vy", "vz"): + display_val = f"{m_s_to_ft_s(val):.3f} {unit}" if isinstance(val, (int, float)) else val + elif key == "baro_altitude": + display_val = f"{m_to_ft(val):.3f} {unit}" if isinstance(val, (int, float)) else val + elif key in ("latitude", "longitude"): + display_val = f"{val:.9f} {unit}" if isinstance(val, (int, float)) else val + else: + display_val = val + self.scenario_tree.insert("", tk.END, values=(f"{label} {('('+unit+')' if unit else '')}", display_val)) # targets for iid in self.ris_tree.get_children(): self.ris_tree.delete(iid) targets = struct.get("targets", []) if isinstance(struct, dict) else [] + # Update target column headers to show units + try: + self.ris_tree.heading("heading", text="heading (°)") + self.ris_tree.heading("x", text="x (m)") + self.ris_tree.heading("y", text="y (m)") + self.ris_tree.heading("z", text="z (ft)") + except Exception: + pass + for t in targets: + # Convert heading (rad->deg) and z (m->ft) + try: + heading = float(t.get("heading")) + heading_deg = heading * (180.0 / 3.141592653589793) + except Exception: + heading_deg = t.get("heading") + try: + x = float(t.get("x")) + y = float(t.get("y")) + z_m = float(t.get("z")) + z_ft = z_m * 3.280839895 + except Exception: + x = t.get("x") + y = t.get("y") + z_ft = t.get("z") + vals = ( t.get("index"), t.get("flags"), - f"{t.get('heading'):.3f}", - f"{t.get('x'):.3f}", - f"{t.get('y'):.3f}", - f"{t.get('z'):.3f}", + f"{heading_deg:.3f}", + f"{x:.3f}", + f"{y:.3f}", + f"{z_ft:.3f}", ) self.ris_tree.insert("", tk.END, values=vals) except Exception: