sistemata rotazione antenna in base al ptaz
This commit is contained in:
parent
a6d679e7a5
commit
48bfc9f730
@ -289,21 +289,16 @@ class SimulationStateHub:
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
ts = float(timestamp) if timestamp is not None else time.monotonic()
|
ts = float(timestamp) if timestamp is not None else time.monotonic()
|
||||||
# Apply platform azimuth inversion: many external sources use an
|
# The antenna azimuth provided by external sources should be
|
||||||
# opposite angular convention. Store the raw value and keep the
|
# treated as raw and stored as-is (normalized to [0,360)). Do not
|
||||||
# inverted/normalized value for internal use.
|
# invert it here — only platform/heading values use the inverted
|
||||||
raw = None
|
# internal convention.
|
||||||
try:
|
raw = float(azimuth_deg)
|
||||||
raw = float(azimuth_deg)
|
az = raw % 360
|
||||||
except Exception:
|
|
||||||
raw = None
|
|
||||||
az_inverted = _invert_azimuth_deg(raw)
|
|
||||||
if az_inverted is None:
|
|
||||||
return
|
|
||||||
except Exception:
|
except Exception:
|
||||||
return
|
return
|
||||||
with self._lock:
|
with self._lock:
|
||||||
self._antenna_azimuth_deg = az_inverted
|
self._antenna_azimuth_deg = az
|
||||||
self._antenna_azimuth_ts = ts
|
self._antenna_azimuth_ts = ts
|
||||||
self._antenna_azimuth_raw = raw
|
self._antenna_azimuth_raw = raw
|
||||||
|
|
||||||
|
|||||||
@ -802,31 +802,77 @@ class MainView(tk.Tk):
|
|||||||
if self.simulation_hub:
|
if self.simulation_hub:
|
||||||
# Update antenna sweep line
|
# Update antenna sweep line
|
||||||
if self.ppi_widget.animate_antenna_var.get():
|
if self.ppi_widget.animate_antenna_var.get():
|
||||||
az_deg, _ = self.simulation_hub.get_antenna_azimuth()
|
antenna_srv, _ = self.simulation_hub.get_antenna_azimuth()
|
||||||
try:
|
|
||||||
# Debug: record the value read from the hub and hub identity
|
# Compute displayed antenna azimuth depending on display mode
|
||||||
# Log solo se l'azimuth è valido (non None)
|
# North-Up: use server-provided antenna azimuth directly
|
||||||
if az_deg is not None:
|
# Heading-Up: express antenna azimuth in body (muso) reference
|
||||||
self.logger.debug(
|
antenna_display = None
|
||||||
"MainView: read antenna az from hub -> az=%s hub_id=%s",
|
if antenna_srv is not None:
|
||||||
az_deg,
|
try:
|
||||||
id(self._hub),
|
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:
|
platform_h_raw = float(platform_h_raw) if platform_h_raw is not None else 0.0
|
||||||
pass
|
|
||||||
if az_deg is not None:
|
if mode == "North-Up":
|
||||||
self.ppi_widget.render_antenna_line(az_deg)
|
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:
|
else:
|
||||||
self.ppi_widget.render_antenna_line(None) # Hide if no data
|
self.ppi_widget.render_antenna_line(None)
|
||||||
else:
|
else:
|
||||||
self.ppi_widget.render_antenna_line(None) # Hide if animation is off
|
self.ppi_widget.render_antenna_line(None) # Hide if animation is off
|
||||||
|
|
||||||
# Update ownship state for both PPI orientation and status display
|
# 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()
|
ownship_state = self.simulation_hub.get_ownship_state()
|
||||||
if ownship_state:
|
if ownship_state:
|
||||||
ownship_heading = ownship_state.get("heading_deg", 0.0)
|
# Prefer raw heading if present
|
||||||
self.ppi_widget.update_ownship_state(ownship_heading)
|
ownship_heading_raw = ownship_state.get(
|
||||||
self.simulation_controls.update_ownship_display(ownship_state)
|
"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:
|
else:
|
||||||
# Ensure display is cleared if no ownship data is present
|
# Ensure display is cleared if no ownship data is present
|
||||||
ownship_state = {}
|
ownship_state = {}
|
||||||
|
|||||||
@ -733,32 +733,20 @@ class PPIDisplay(ttk.Frame):
|
|||||||
else:
|
else:
|
||||||
az_float = float(az_deg)
|
az_float = float(az_deg)
|
||||||
|
|
||||||
# WORKING SOLUTION confirmed by user:
|
# Treat the provided az_deg as the final absolute antenna
|
||||||
# North-Up with heading=+10°:
|
# azimuth (degrees relative to North, positive=CCW). The
|
||||||
# - Server sends ant_nav_az from +50° to -70°
|
# caller (MainView) computes North-Up vs Heading-Up logic.
|
||||||
# - Add 2×heading: result is +70° to -50° ✓ CORRECT
|
final_az_for_plot = az_float
|
||||||
#
|
|
||||||
# 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)
|
|
||||||
|
|
||||||
final_az_for_plot = az_float + (2.0 * self.ownship_heading_deg)
|
# Normalize to (-180, 180]
|
||||||
|
|
||||||
# Normalize to [-180, 180] range
|
|
||||||
while final_az_for_plot > 180:
|
while final_az_for_plot > 180:
|
||||||
final_az_for_plot -= 360
|
final_az_for_plot -= 360
|
||||||
while final_az_for_plot < -180:
|
while final_az_for_plot <= -180:
|
||||||
final_az_for_plot += 360
|
final_az_for_plot += 360
|
||||||
|
|
||||||
# Convert final angle to theta for Matplotlib (0=N, positive=CCW)
|
# Convert final angle to theta for Matplotlib (0=N, positive=CCW)
|
||||||
theta = np.deg2rad(final_az_for_plot)
|
theta = np.deg2rad(final_az_for_plot)
|
||||||
max_r = self.ax.get_ylim()[1]
|
max_r = self.ax.get_ylim()[1]
|
||||||
|
|
||||||
self._antenna_line_artist.set_data([theta, theta], [0, max_r])
|
self._antenna_line_artist.set_data([theta, theta], [0, max_r])
|
||||||
self._antenna_line_artist.set_visible(True)
|
self._antenna_line_artist.set_visible(True)
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user