Skip to content

Instantly share code, notes, and snippets.

@rbs-tim
Last active March 12, 2023 18:53
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rbs-tim/c1e8de814a92b5c2464143c917af8735 to your computer and use it in GitHub Desktop.
Save rbs-tim/c1e8de814a92b5c2464143c917af8735 to your computer and use it in GitHub Desktop.
iss.py
# python 3.7 suggested
import datetime
import time
from skyfield.api import load, Topos, EarthSatellite
TLE_FILE = "https://celestrak.com/NORAD/elements/active.txt"
ISS_NAME = "ISS (ZARYA)"
LONGITUDE = -73.9940702
LATITUDE = 40.7546283
class SatelliteObserver:
def __init__(self, where: Topos, what: EarthSatellite):
self.where = where
self.sat = what
self.sat_name = what.name
self.ts = load.timescale(builtin=True)
@classmethod
def from_strings(cls, longitude: str or float, latitude: str or float, sat_name: str, tle_file: str) -> 'SatelliteObserver':
place = Topos(latitude, longitude)
satellites = load.tle(tle_file)
print("loaded {} sats from {}".format(len(satellites), tle_file))
_sats_by_name = {sat.name: sat for sat in satellites.values()}
satellite = _sats_by_name[sat_name]
return cls(place, satellite)
def altAzDist_at(self, at: float) -> (float, float, float):
"""
:param at: Unix time GMT (timestamp)
:return: (altitude, azimuth, distance)
"""
current_gmt = datetime.datetime.utcfromtimestamp(at)
current_ts = self.ts.utc(current_gmt.year, current_gmt.month, current_gmt.day, current_gmt.hour,
current_gmt.minute, current_gmt.second + current_gmt.microsecond / 1000000.0)
difference = self.sat - self.where
observer_to_sat = difference.at(current_ts)
altitude, azimuth, distance = observer_to_sat.altaz()
return (altitude.degrees, azimuth.degrees, distance.km)
def current_altAzDist(self) -> (float, float, float):
return self.altAzDist_at(time.mktime(time.gmtime()))
def above_horizon(self, at: float) -> bool:
"""
:param at: Unix time GMT
:return:
"""
(alt, az, dist) = self.altAzDist_at(at)
return alt > 0
def main():
iss = SatelliteObserver.from_strings(LONGITUDE, LATITUDE, ISS_NAME, TLE_FILE)
elevation, azimuth, distance = iss.current_altAzDist()
visible = "visible!" if elevation > 0 else "not visible =/"
print("ISS from latitude {}, longitude {}: azimuth {}, elevation {} ({})".format(LATITUDE, LONGITUDE, azimuth, elevation, visible))
if __name__ == "__main__":
main()
@sebling
Copy link

sebling commented Aug 9, 2020

I believe there is actually a bug in this script in the current_altAzDist method, as it feeds a UTC timestamp to altAzDist in the at parameter. The at parameter is then passed to datetime.datetime.utcfromtimestamp function which is expecting a non-timezone aware timestamp (and apparently assumes local time). This results in a timestamp that is N number of hours off actual UTC, where N is the diff between local time and UTC.
You can observe this with the simple script import datetime; datetime.datetime.utcfromtimestamp(time.mktime(time.gmtime())).
One fix is to change the time.gmtime() call in current_altAzDist method to time.localtime()
Once I made this change the script gave values that matched other tracking software.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment