Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

find_events on highly elliptical orbit satellite inconsistent #1017

Open
ecdaero opened this issue Nov 5, 2024 · 0 comments
Open

find_events on highly elliptical orbit satellite inconsistent #1017

ecdaero opened this issue Nov 5, 2024 · 0 comments

Comments

@ecdaero
Copy link

ecdaero commented Nov 5, 2024

Hi! Thanks for the work you've done on Skyfield. I'm using it to find rise/set times of objects, and recently came across this corner case(?) where the find_events method is giving incomplete results.

The track of the object that I noticed this on:

I wrote a small program to demo this behavior:

#!/usr/bin/env python3

import datetime as dt
from datetime import datetime

from skyfield.api import EarthSatellite, Time, load, load_file, wgs84
from skyfield.toposlib import GeographicPosition
from skyfield.vectorlib import VectorSum


def main():
    """Attempt to find rise/set events for an example pass."""
    planets = load_file("de421.bsp")

    ts = load.timescale(builtin=True)

    site_latitude = 33
    site_longitude = -118
    site_altitude = 30
    min_elevation_angle = 10

    site = wgs84.latlon(site_latitude, site_longitude, elevation_m=site_altitude)

    # This object has a highly elliptical orbit:
    sat_target = EarthSatellite(
        "1 17328U 87008A   24305.23833080  .00000500  00000-0  22722-2 0  9997",
        "2 17328  63.0833   7.8955 7415190 253.9972  19.6892  2.00632911273252",
        "MOLNIYA 3-31",
        ts,
    )

    earth = planets["earth"]
    groundstation = earth + site
    satellite = earth + sat_target

    # This is an example pass where we noticed we weren't getting the right rise/sets
    obs_start_time = datetime(2024, 10, 31, 5, 28, 6, 0, tzinfo=dt.timezone.utc)
    obs_end_time = datetime(2024, 10, 31, 5, 40, 6, 0, tzinfo=dt.timezone.utc)
    t0 = ts.from_datetime(obs_start_time)
    t1 = ts.from_datetime(obs_end_time)

    event_times, events = find_events(site, groundstation, sat_target, satellite, t0, t1, min_elevation_angle)

    print("This should have found a 'rise':")
    print(events, event_times)
    print("...but it has not found a rise event.\n")

    # However, this *does* work:
    obs_start_time = datetime(2024, 10, 31, 2, 28, 6, 0, tzinfo=dt.timezone.utc)
    obs_end_time = datetime(2024, 10, 31, 7, 40, 6, 0, tzinfo=dt.timezone.utc)
    t0 = ts.from_datetime(obs_start_time)
    t1 = ts.from_datetime(obs_end_time)

    event_times, events = find_events(site, groundstation, sat_target, satellite, t0, t1, min_elevation_angle)

    print("Expand the boundary, and it finds events:")
    print(events, event_times)
    print("...including a rise and culmination.\n")

    obs_long_end_time = datetime(2024, 10, 31, 16, 40, 6, 0, tzinfo=dt.timezone.utc)
    t2 = ts.from_datetime(obs_long_end_time)

    event_times, events = find_events(site, groundstation, sat_target, satellite, t0, t2, min_elevation_angle)

    print("Expand it further, and it should have found a rise, culmination, and set:")
    print(events, event_times)
    print("...but it found a rise, two culminates, and no set.\n")

    # note: adjust the range fidelity to see more detail on the track
    track_time = ts.utc(2024, 10, 31, 5, range(20, 710, 4))
    print_track(groundstation, satellite, track_time)


def find_events(
    site: GeographicPosition,
    site_vector: VectorSum,
    satellite: EarthSatellite,
    sat_vector: VectorSum,
    t0: Time,
    t1: Time,
    min_elevation: float,
) -> tuple:
    alt_initial, az_initial, ssb_dist = site_vector.at(t0).observe(sat_vector).apparent().altaz()
    alt_final, az_final, ssb_dist = site_vector.at(t1).observe(sat_vector).apparent().altaz()
    print(f"Start/End (Az/El): {az_initial.degrees:.5f} / {alt_initial.degrees:.5f} ----> {az_final.degrees:.5f} / {alt_final.degrees:.5f}")

    # This fails to find the "rise" above 10 degrees elevation.
    event_times, events = satellite.find_events(site, t0, t1, altitude_degrees=min_elevation)

    return event_times, events


def print_track(groundstation: VectorSum, satellite: EarthSatellite, track_time: Time) -> None:
    """Print a minute-by-minute track of a satellite."""
    print("Propagated track:")
    for obs_time in track_time:
        ssb_alt, ssb_az, ssb_dist = groundstation.at(obs_time).observe(satellite).apparent().altaz()
        print(f"{obs_time.utc_strftime('%Y-%m-%d %H:%M')}: {ssb_az.degrees:.5f} / {ssb_alt.degrees:.5f}")


if __name__ == "__main__":
    main()

The output, trimmed a bit for brevity:

Start/End (Az/El): 187.17892 / 3.56302 ----> 181.04224 / 31.75064
This should have found a 'rise':
[] <Time tt=[]>
...but it has not found a rise event.

Start/End (Az/El): 8.53929 / -5.12598 ----> 342.28175 / 80.02753
Expand the boundary, and it finds events:
[0 1] <Time tt=[2460614.73033378 2460614.79156628]>
...including a rise and culmination.

Start/End (Az/El): 8.53929 / -5.12598 ----> 153.81261 / 25.31236
Expand it further, and it should have found a rise, culmination, and set:
[0 1 1] <Time tt=[2460614.73033391 2460614.79156647 2460615.17820007]>
...but it found a rise, two culminates, and no set.

Propagated track:
2024-10-31 05:20: 192.82956 / -19.59808
2024-10-31 05:24: 189.81945 / -7.95510
2024-10-31 05:28: 187.23907 / 3.29044
2024-10-31 05:32: 184.96974 / 13.76284
2024-10-31 05:36: 182.93587 / 23.21467
2024-10-31 05:40: 181.08645 / 31.55621
2024-10-31 05:44: 179.38535 / 38.82250
2024-10-31 05:48: 177.80579 / 45.11913
2024-10-31 05:52: 176.32707 / 50.57753
2024-10-31 05:56: 174.93248 / 55.32799
2024-10-31 06:00: 173.60790 / 59.48724
2024-10-31 06:04: 172.34077 / 63.15455
2024-10-31 06:08: 171.11921 / 66.41212
2024-10-31 06:12: 169.93118 / 69.32710
2024-10-31 06:16: 168.76358 / 71.95414
2024-10-31 06:20: 167.60085 / 74.33764
2024-10-31 06:24: 166.42309 / 76.51380
2024-10-31 06:28: 165.20258 / 78.51223
2024-10-31 06:32: 163.89761 / 80.35721
2024-10-31 06:36: 162.43976 / 82.06872
2024-10-31 06:40: 160.70536 / 83.66305
2024-10-31 06:44: 158.44144 / 85.15312
2024-10-31 06:48: 155.03239 / 86.54776
2024-10-31 06:52: 148.50069 / 87.84690
2024-10-31 06:56: 128.13765 / 89.00029
2024-10-31 07:00: 39.69036 / 89.30654
2024-10-31 07:04: 3.38661 / 88.37322
2024-10-31 07:08: 354.56943 / 87.32850
2024-10-31 07:12: 350.60919 / 86.30500
2024-10-31 07:16: 348.25847 / 85.31556
2024-10-31 07:20: 346.63795 / 84.36104
2024-10-31 07:24: 345.41435 / 83.43988
2024-10-31 07:28: 344.43383 / 82.55000
2024-10-31 07:32: 343.61550 / 81.68929
2024-10-31 07:36: 342.91262 / 80.85572
2024-10-31 07:40: 342.29623 / 80.04743
2024-10-31 07:44: 341.74737 / 79.26273
2024-10-31 07:48: 341.25300 / 78.50008
2024-10-31 07:52: 340.80385 / 77.75808
2024-10-31 07:56: 340.39309 / 77.03548
2024-10-31 08:00: 340.01557 / 76.33114
2024-10-31 08:04: 339.66727 / 75.64402
2024-10-31 08:08: 339.34503 / 74.97318
2024-10-31 08:12: 339.04628 / 74.31778
2024-10-31 08:16: 338.76892 / 73.67704
...
2024-10-31 12:32: 339.18931 / 51.25362
2024-10-31 12:36: 339.32071 / 51.16099
2024-10-31 12:40: 339.45316 / 51.07786
2024-10-31 12:44: 339.58656 / 51.00441
2024-10-31 12:48: 339.72082 / 50.94083
2024-10-31 12:52: 339.85584 / 50.88734
2024-10-31 12:56: 339.99152 / 50.84416
2024-10-31 13:00: 340.12775 / 50.81152
2024-10-31 13:04: 340.26446 / 50.78967
2024-10-31 13:08: 340.40153 / 50.77889
2024-10-31 13:12: 340.53889 / 50.77946
2024-10-31 13:16: 340.67642 / 50.79169
2024-10-31 13:20: 340.81404 / 50.81590
2024-10-31 13:24: 340.95166 / 50.85244
2024-10-31 13:28: 341.08918 / 50.90169
2024-10-31 13:32: 341.22653 / 50.96405
2024-10-31 13:36: 341.36361 / 51.03994
2024-10-31 13:40: 341.50034 / 51.12985
2024-10-31 13:44: 341.63665 / 51.23427
2024-10-31 13:48: 341.77246 / 51.35374
2024-10-31 13:52: 341.90769 / 51.48884
...
2024-10-31 15:48: 346.96691 / 69.50775
2024-10-31 15:52: 347.66689 / 71.36404
2024-10-31 15:56: 348.66738 / 73.45936
2024-10-31 16:00: 350.20602 / 75.84171
2024-10-31 16:04: 352.83769 / 78.56846
2024-10-31 16:08: 358.20033 / 81.69377
2024-10-31 16:12: 13.60105 / 85.15166
2024-10-31 16:16: 81.85831 / 87.11603
2024-10-31 16:20: 134.10787 / 83.04728
2024-10-31 16:24: 145.82440 / 76.28422
2024-10-31 16:28: 150.17777 / 67.48542
2024-10-31 16:32: 152.25411 / 56.25051
2024-10-31 16:36: 153.31592 / 42.23893
2024-10-31 16:40: 153.80583 / 25.74685
2024-10-31 16:44: 153.90416 / 8.11710
2024-10-31 16:48: 153.67806 / -8.82336

I would prefer to continue using Skyfield for finding rise and set events, and I don't think I'm doing anything wrong. Is this a bug/limitation in Skyfield? Are there intentional limitations here that I should work around?

Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant