mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-11-11 04:33:06 +00:00
skyplot: split satellite tracks at horizon crossings to avoid linking disjoint passes
Added logic to segment satellite trajectories whenever elevation drops below 5 degrees, preventing lines from connecting points across horizon gaps. Each segment is plotted independently with its own arrow and label
This commit is contained in:
@@ -405,19 +405,16 @@ def plot_satellite_tracks(satellites, obs_lat, obs_lon, obs_alt,
|
|||||||
for prn, ephemeris_list in satellites.items():
|
for prn, ephemeris_list in satellites.items():
|
||||||
color = system_colors.get(prn[0], 'purple') # Default to purple for unknown systems
|
color = system_colors.get(prn[0], 'purple') # Default to purple for unknown systems
|
||||||
|
|
||||||
# Get the most recent ephemeris
|
|
||||||
if not ephemeris_list:
|
if not ephemeris_list:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
mid_time = start_time + (end_time - start_time) / 2
|
mid_time = start_time + (end_time - start_time) / 2
|
||||||
prev_eph = [e for e in ephemeris_list if e['epoch'] <= mid_time] # Previous ephemeris
|
prev_eph = [e for e in ephemeris_list if e['epoch'] <= mid_time]
|
||||||
|
if prev_eph:
|
||||||
if prev_eph: # Pick the most recent ephemeris before or at the midpoint
|
|
||||||
ephemeris = max(prev_eph, key=lambda e: e['epoch'])
|
ephemeris = max(prev_eph, key=lambda e: e['epoch'])
|
||||||
else: # Pick the ephemeris whose epoch is closest in time to the midpoint
|
else:
|
||||||
ephemeris = min(ephemeris_list, key=lambda e: abs((e['epoch'] - mid_time).total_seconds()))
|
ephemeris = min(ephemeris_list, key=lambda e: abs((e['epoch'] - mid_time).total_seconds()))
|
||||||
|
|
||||||
# Calculate trajectory
|
|
||||||
if start_time is None or end_time is None:
|
if start_time is None or end_time is None:
|
||||||
all_epochs = sorted({e['epoch'] for prn_data in satellites.values() for e in prn_data})
|
all_epochs = sorted({e['epoch'] for prn_data in satellites.values() for e in prn_data})
|
||||||
start_time = min(all_epochs)
|
start_time = min(all_epochs)
|
||||||
@@ -425,50 +422,54 @@ def plot_satellite_tracks(satellites, obs_lat, obs_lon, obs_alt,
|
|||||||
|
|
||||||
positions = calculate_satellite_positions(ephemeris, start_time, end_time)
|
positions = calculate_satellite_positions(ephemeris, start_time, end_time)
|
||||||
|
|
||||||
az = []
|
# Split into visible segments
|
||||||
el = []
|
segments = []
|
||||||
|
current_seg_az = []
|
||||||
|
current_seg_el = []
|
||||||
for _, x, y, z in positions:
|
for _, x, y, z in positions:
|
||||||
azimuth, elevation = ecef_to_az_el(x, y, z, obs_lat, obs_lon, obs_alt)
|
azimuth, elevation = ecef_to_az_el(x, y, z, obs_lat, obs_lon, obs_alt)
|
||||||
if elevation > 5: # Above horizon
|
if elevation > 5:
|
||||||
az.append(azimuth)
|
current_seg_az.append(azimuth)
|
||||||
el.append(elevation)
|
current_seg_el.append(elevation)
|
||||||
|
else:
|
||||||
|
if len(current_seg_az) > 1:
|
||||||
|
segments.append((current_seg_az, current_seg_el))
|
||||||
|
current_seg_az, current_seg_el = [], []
|
||||||
|
if len(current_seg_az) > 1:
|
||||||
|
segments.append((current_seg_az, current_seg_el))
|
||||||
|
|
||||||
if len(az) > 1:
|
# Plot each segment separately
|
||||||
# Convert to polar coordinates
|
for az_seg, el_seg in segments:
|
||||||
theta = np.radians(az)
|
theta = np.radians(az_seg)
|
||||||
r = 90 - np.array(el)
|
r = 90 - np.array(el_seg)
|
||||||
|
|
||||||
# Plot trajectory
|
|
||||||
ax.plot(theta, r, '-', color=color, alpha=0.7, linewidth=2.5)
|
ax.plot(theta, r, '-', color=color, alpha=0.7, linewidth=2.5)
|
||||||
|
|
||||||
# Add arrow at last point
|
# Arrow at end
|
||||||
if len(theta) >= 2: # Need at least 2 points for direction
|
if len(theta) >= 2:
|
||||||
dx = theta[-1] - theta[-2]
|
dx = theta[-1] - theta[-2]
|
||||||
dy = r[-1] - r[-2]
|
dy = r[-1] - r[-2]
|
||||||
|
|
||||||
# Extend endpoint
|
|
||||||
arrow_length_factor = 1.3
|
arrow_length_factor = 1.3
|
||||||
extended_theta = theta[-2] + dx * arrow_length_factor
|
extended_theta = theta[-2] + dx * arrow_length_factor
|
||||||
extended_r = r[-2] + dy * arrow_length_factor
|
extended_r = r[-2] + dy * arrow_length_factor
|
||||||
ax.annotate('',
|
ax.annotate('',
|
||||||
xytext=(theta[-1], r[-1]),
|
xytext=(theta[-1], r[-1]),
|
||||||
xy=(extended_theta, extended_r),
|
xy=(extended_theta, extended_r),
|
||||||
arrowprops={
|
arrowprops={
|
||||||
'arrowstyle': '->',
|
'arrowstyle': '->',
|
||||||
'color': color,
|
'color': color,
|
||||||
'alpha': 0.9,
|
'alpha': 0.9,
|
||||||
'linewidth': 1.5,
|
'linewidth': 1.5,
|
||||||
'shrinkA': 0,
|
'shrinkA': 0,
|
||||||
'shrinkB': 0
|
'shrinkB': 0
|
||||||
})
|
})
|
||||||
|
|
||||||
# Label at midpoint
|
# Label at midpoint of the segment
|
||||||
mid_idx = len(theta)//2
|
mid_idx = len(theta)//2
|
||||||
ax.text(theta[mid_idx], r[mid_idx], prn,
|
ax.text(theta[mid_idx], r[mid_idx], prn,
|
||||||
fontsize=12, ha='center', va='center',
|
fontsize=12, ha='center', va='center',
|
||||||
bbox={"facecolor": "white", "alpha": 0.8, "pad": 2})
|
bbox={"facecolor": "white", "alpha": 0.8, "pad": 2})
|
||||||
|
|
||||||
# Create legend elements only for present systems
|
# Legend for present systems
|
||||||
legend_elements = [
|
legend_elements = [
|
||||||
plt.Line2D([0], [0], marker='o', color='w',
|
plt.Line2D([0], [0], marker='o', color='w',
|
||||||
label=f'{system_names[sys]} ({sys})',
|
label=f'{system_names[sys]} ({sys})',
|
||||||
@@ -476,15 +477,11 @@ def plot_satellite_tracks(satellites, obs_lat, obs_lon, obs_alt,
|
|||||||
markersize=10)
|
markersize=10)
|
||||||
for sys in present_systems
|
for sys in present_systems
|
||||||
]
|
]
|
||||||
|
|
||||||
# Add legend if we have any systems to show
|
|
||||||
if legend_elements:
|
if legend_elements:
|
||||||
ax.legend(
|
ax.legend(handles=legend_elements,
|
||||||
handles=legend_elements,
|
loc='upper right',
|
||||||
loc='upper right',
|
bbox_to_anchor=(1.3, 1.1),
|
||||||
bbox_to_anchor=(1.3, 1.1),
|
fontsize=14)
|
||||||
fontsize=14
|
|
||||||
)
|
|
||||||
|
|
||||||
lat_deg = np.degrees(obs_lat)
|
lat_deg = np.degrees(obs_lat)
|
||||||
lon_deg = np.degrees(obs_lon)
|
lon_deg = np.degrees(obs_lon)
|
||||||
|
|||||||
Reference in New Issue
Block a user