Fix: periodic SOI rescan when no crossing found in look-ahead window

- SEARCH_ORBITS increased from 5 to 10
- Added last_scan_end tracking: when sim_time passes the end of the
  current scan window with no crossing pending, automatically rescans
  the next SEARCH_ORBITS ahead
- Title bar now shows 'rescan in Xs' instead of just 'No upcoming SOI
  crossing', making the system's state visible
- Fixes bug #3: asteroid entering SOI undetected because the scan
  window had expired
This commit is contained in:
2026-05-21 20:51:01 +02:00
parent e2c706ecb0
commit 377dc68795

View File

@@ -47,7 +47,7 @@ ASTEROID_SUN = OrbitalElements(
a=380.0, e=0.35, omega=2.5, M0=0.8, epoch=0.0, mu=MU_SUN,
)
SEARCH_ORBITS = 5
SEARCH_ORBITS = 10
# ═══════════════════════════════════════════════════════════════
# Display
@@ -155,6 +155,7 @@ def main() -> None:
sun_crossings = find_soi_crossings(
ASTEROID_SUN, PLANET, SOI_RADIUS, 0.0, window, n_steps=1000,
)
last_scan_end: float = window # when this scan window expires
print(f"Found {len(sun_crossings)} SOI crossing(s):")
for i, (enter, exit_) in enumerate(sun_crossings):
print(f" [{i}] enter={enter:.1f}s (sun-frame)")
@@ -204,6 +205,26 @@ def main() -> None:
if not paused:
sim_time += dt * sim_speed
# ── Periodic rescan when no crossing is pending ──
if (not in_soi and soi_enter_time is None
and sim_time >= last_scan_end):
window = SEARCH_ORBITS * max(asteroid_sun.period, PLANET.period)
sun_crossings = find_soi_crossings(
asteroid_sun, PLANET, SOI_RADIUS,
sim_time + 0.1, sim_time + window, n_steps=1000,
)
last_scan_end = sim_time + window
cross_idx = 0
soi_enter_time = sun_crossings[0][0] if sun_crossings else None
if sun_crossings:
print(f"\n[rescan @ t={sim_time:.0f}s] "
f"found {len(sun_crossings)} crossing(s), "
f"next enter at t={sun_crossings[0][0]:.0f}s")
else:
print(f"\n[rescan @ t={sim_time:.0f}s] "
f"no crossings in next {window:.0f}s, "
f"will rescan at t={last_scan_end:.0f}s")
# ── SOI state machine ─────────────────────────────
# Check entry
if (not in_soi and soi_enter_time is not None
@@ -259,7 +280,9 @@ def main() -> None:
asteroid_sun, PLANET, SOI_RADIUS,
sim_time + 0.1, sim_time + window, n_steps=1000,
)
print(f" Re-scanned: found {len(sun_crossings)} future crossing(s)")
last_scan_end = sim_time + window
print(f" Re-scanned: found {len(sun_crossings)} future crossing(s) "
f"(window ends at t={last_scan_end:.0f}s)")
for i, (enter, _) in enumerate(sun_crossings):
print(f" [{i}] enter={enter:.1f}s")
@@ -343,7 +366,9 @@ def main() -> None:
title = (f"SOI entry in {countdown:.1f}s "
f"(crossing {cross_idx + 1}/{len(sun_crossings)})")
else:
title = "No upcoming SOI crossing"
rescan_in = last_scan_end - sim_time
title = (f"No SOI crossing in window — "
f"rescan in {rescan_in:.0f}s")
pygame.display.set_caption(title)
# ── HUD ───────────────────────────────────────────