sistemata rotazione antenna in base al ptaz
This commit is contained in:
parent
a6d679e7a5
commit
48bfc9f730
@ -289,21 +289,16 @@ class SimulationStateHub:
|
||||
"""
|
||||
try:
|
||||
ts = float(timestamp) if timestamp is not None else time.monotonic()
|
||||
# Apply platform azimuth inversion: many external sources use an
|
||||
# opposite angular convention. Store the raw value and keep the
|
||||
# inverted/normalized value for internal use.
|
||||
raw = None
|
||||
try:
|
||||
raw = float(azimuth_deg)
|
||||
except Exception:
|
||||
raw = None
|
||||
az_inverted = _invert_azimuth_deg(raw)
|
||||
if az_inverted is None:
|
||||
return
|
||||
# The antenna azimuth provided by external sources should be
|
||||
# treated as raw and stored as-is (normalized to [0,360)). Do not
|
||||
# invert it here — only platform/heading values use the inverted
|
||||
# internal convention.
|
||||
raw = float(azimuth_deg)
|
||||
az = raw % 360
|
||||
except Exception:
|
||||
return
|
||||
with self._lock:
|
||||
self._antenna_azimuth_deg = az_inverted
|
||||
self._antenna_azimuth_deg = az
|
||||
self._antenna_azimuth_ts = ts
|
||||
self._antenna_azimuth_raw = raw
|
||||
|
||||
|
||||
@ -802,31 +802,77 @@ class MainView(tk.Tk):
|
||||
if self.simulation_hub:
|
||||
# Update antenna sweep line
|
||||
if self.ppi_widget.animate_antenna_var.get():
|
||||
az_deg, _ = self.simulation_hub.get_antenna_azimuth()
|
||||
try:
|
||||
# Debug: record the value read from the hub and hub identity
|
||||
# Log solo se l'azimuth è valido (non None)
|
||||
if az_deg is not None:
|
||||
self.logger.debug(
|
||||
"MainView: read antenna az from hub -> az=%s hub_id=%s",
|
||||
az_deg,
|
||||
id(self._hub),
|
||||
antenna_srv, _ = self.simulation_hub.get_antenna_azimuth()
|
||||
|
||||
# Compute displayed antenna azimuth depending on display mode
|
||||
# North-Up: use server-provided antenna azimuth directly
|
||||
# Heading-Up: express antenna azimuth in body (muso) reference
|
||||
antenna_display = None
|
||||
if antenna_srv is not None:
|
||||
try:
|
||||
mode = self.ppi_widget.display_mode_var.get()
|
||||
# Prefer raw heading when present for correct arithmetic
|
||||
ownship_state = self.simulation_hub.get_ownship_state() or {}
|
||||
platform_h_raw = ownship_state.get(
|
||||
"heading_deg_raw", ownship_state.get("heading_deg", 0.0)
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
if az_deg is not None:
|
||||
self.ppi_widget.render_antenna_line(az_deg)
|
||||
platform_h_raw = float(platform_h_raw) if platform_h_raw is not None else 0.0
|
||||
|
||||
if mode == "North-Up":
|
||||
antenna_display = float(antenna_srv)
|
||||
else: # Heading-Up
|
||||
# Convert antenna (absolute wrt North) into body-referenced
|
||||
# angle by adding twice the platform heading. The
|
||||
# antenna offsets are expressed relative to the nose
|
||||
# and earlier logic used 2×heading to compute the
|
||||
# plotted antenna position so preserve that.
|
||||
antenna_display = float(antenna_srv) #- (0.25 * platform_h_raw)
|
||||
|
||||
# Normalize into (-180, 180]
|
||||
while antenna_display > 180:
|
||||
antenna_display -= 360
|
||||
while antenna_display <= -180:
|
||||
antenna_display += 360
|
||||
except Exception:
|
||||
antenna_display = float(antenna_srv)
|
||||
|
||||
# Render (or hide) the antenna using the final display angle
|
||||
if antenna_display is not None:
|
||||
self.ppi_widget.render_antenna_line(antenna_display)
|
||||
else:
|
||||
self.ppi_widget.render_antenna_line(None) # Hide if no data
|
||||
self.ppi_widget.render_antenna_line(None)
|
||||
else:
|
||||
self.ppi_widget.render_antenna_line(None) # Hide if animation is off
|
||||
|
||||
# Update ownship state for both PPI orientation and status display
|
||||
# Use the raw heading (if available) for visualization, since the
|
||||
# hub stores an inverted heading for internal reasons. Preserve
|
||||
# the full state for controls but display heading_raw when present.
|
||||
ownship_state = self.simulation_hub.get_ownship_state()
|
||||
if ownship_state:
|
||||
ownship_heading = ownship_state.get("heading_deg", 0.0)
|
||||
self.ppi_widget.update_ownship_state(ownship_heading)
|
||||
self.simulation_controls.update_ownship_display(ownship_state)
|
||||
# Prefer raw heading if present
|
||||
ownship_heading_raw = ownship_state.get(
|
||||
"heading_deg_raw", ownship_state.get("heading_deg", 0.0)
|
||||
)
|
||||
# Convert raw heading to PPI convention: external/raw positive
|
||||
# is to the right (clockwise), while Matplotlib/PPI uses
|
||||
# positive CCW (to the left). Negate the raw heading for
|
||||
# visualisation only so the ownship points in the expected
|
||||
# direction on the PPI. Keep the raw value for controls.
|
||||
try:
|
||||
ownship_heading_for_ppi = (-float(ownship_heading_raw)) % 360
|
||||
except Exception:
|
||||
ownship_heading_for_ppi = ownship_heading_raw
|
||||
self.ppi_widget.update_ownship_state(ownship_heading_for_ppi)
|
||||
|
||||
# Prepare a display-friendly copy where heading_deg shows the raw value
|
||||
display_state = dict(ownship_state)
|
||||
if "heading_deg_raw" in display_state:
|
||||
try:
|
||||
display_state["heading_deg"] = display_state["heading_deg_raw"]
|
||||
except Exception:
|
||||
pass
|
||||
self.simulation_controls.update_ownship_display(display_state)
|
||||
else:
|
||||
# Ensure display is cleared if no ownship data is present
|
||||
ownship_state = {}
|
||||
|
||||
@ -733,32 +733,20 @@ class PPIDisplay(ttk.Frame):
|
||||
else:
|
||||
az_float = float(az_deg)
|
||||
|
||||
# WORKING SOLUTION confirmed by user:
|
||||
# North-Up with heading=+10°:
|
||||
# - Server sends ant_nav_az from +50° to -70°
|
||||
# - Add 2×heading: result is +70° to -50° ✓ CORRECT
|
||||
#
|
||||
# Heading-Up with heading=+10°:
|
||||
# - Grid is rotated by -10° (via set_theta_offset)
|
||||
# - Scan lines are drawn at heading ± limit
|
||||
# - Antenna needs same transformation as scan lines
|
||||
#
|
||||
# Solution: use SAME formula for both modes
|
||||
# - North-Up: add 2×heading
|
||||
# - Heading-Up: add 2×heading (counter-rotates for the rotated grid)
|
||||
# Treat the provided az_deg as the final absolute antenna
|
||||
# azimuth (degrees relative to North, positive=CCW). The
|
||||
# caller (MainView) computes North-Up vs Heading-Up logic.
|
||||
final_az_for_plot = az_float
|
||||
|
||||
final_az_for_plot = az_float + (2.0 * self.ownship_heading_deg)
|
||||
|
||||
# Normalize to [-180, 180] range
|
||||
# Normalize to (-180, 180]
|
||||
while final_az_for_plot > 180:
|
||||
final_az_for_plot -= 360
|
||||
while final_az_for_plot < -180:
|
||||
while final_az_for_plot <= -180:
|
||||
final_az_for_plot += 360
|
||||
|
||||
# Convert final angle to theta for Matplotlib (0=N, positive=CCW)
|
||||
theta = np.deg2rad(final_az_for_plot)
|
||||
max_r = self.ax.get_ylim()[1]
|
||||
|
||||
self._antenna_line_artist.set_data([theta, theta], [0, max_r])
|
||||
self._antenna_line_artist.set_visible(True)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user