Skip to content

Commit c65674e

Browse files
authored
Created "iss_tracker" folder, Added "tracker.py" script
1 parent 4d3ad1d commit c65674e

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed

iss_tracker/tracker.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Import necessary modules
2+
from datetime import datetime, timedelta
3+
from skyfield.iokit import parse_tle_file
4+
from skyfield.api import load
5+
from selenium import webdriver
6+
import folium
7+
import time
8+
import os
9+
10+
11+
# Constants
12+
TLE_FILENAME = "data_files/iss_zarya_tle.tle"
13+
TLE_URL = "https://celestrak.org/NORAD/elements/gp.php?CATNR=25544&FORMAT=TLE"
14+
MAP_FILENAME = "map/tracker_map.html"
15+
MAP_ZOOM_START = 2
16+
ORBIT_DURATION_MINUTES = 90
17+
UPDATE_INTERVAL_SECONDS = 60
18+
19+
20+
# Functions
21+
def download_tle_file():
22+
"""
23+
If the TLE file is missing or is outdated, download the latest data.
24+
"""
25+
if not load.exists(TLE_FILENAME) or load.days_old(TLE_FILENAME) > 1.0:
26+
try:
27+
load.download(TLE_URL, filename=TLE_FILENAME)
28+
except Exception as e:
29+
print(f"ERROR: Failed to download the TLE data.{e}")
30+
exit(1)
31+
32+
33+
def load_satellite_data():
34+
"""
35+
Load the satellite data from the TLE file.
36+
"""
37+
with load.open(TLE_FILENAME) as f:
38+
satellites = list(parse_tle_file(f, load.timescale()))
39+
# Index ISS (ZARYA) by NORADID number.
40+
return {sat.model.satnum: sat for sat in satellites}[25544]
41+
42+
43+
def create_map(sat_lat, sat_lon):
44+
"""
45+
Create a new map with the ISS's current position.
46+
"""
47+
# Create a map centered onto the ISS position.
48+
iss_map = folium.Map(
49+
location=[sat_lat, sat_lon],
50+
zoom_start=MAP_ZOOM_START
51+
)
52+
# Pinpoint the satellite's current position on the map.
53+
folium.Marker(
54+
location=[sat_lat, sat_lon],
55+
tooltip=f"ISS (Lat: {sat_lat}, Lon: {sat_lon})",
56+
popup="International Space Station (ZARYA)",
57+
icon=folium.Icon(color="red", icon="satellite", prefix="fa")
58+
).add_to(iss_map)
59+
return iss_map
60+
61+
62+
def predict_orbit(satellite, current_time):
63+
"""
64+
Predict the orbit of the satellite by predicting its future poitions.
65+
ISS completes one orbit around the Earth in approximately 90 minutes.
66+
"""
67+
# Add current position of the satellite
68+
current_sat_lat = satellite.at(current_time).subpoint().latitude.degrees
69+
current_sat_lon = satellite.at(current_time).subpoint().longitude.degrees
70+
orbit_coordinates = [(current_sat_lat, current_sat_lon)]
71+
for i in range(1, ORBIT_DURATION_MINUTES + 1):
72+
future_time = current_time + timedelta(minutes=i)
73+
future_geocentric_pos = satellite.at(future_time)
74+
future_sub_pos = future_geocentric_pos.subpoint()
75+
future_sat_lat = future_sub_pos.latitude.degrees
76+
future_sat_lon = future_sub_pos.longitude.degrees
77+
# Longitude Adjustment: Check for large jumps in longitude.
78+
if abs(future_sat_lon - orbit_coordinates[-1][1]) > 180:
79+
if future_sat_lon < orbit_coordinates[-1][1]:
80+
future_sat_lon += 360
81+
else:
82+
future_sat_lon -= 360
83+
# Add the fixed coordinates to the list of orbit coordinates.
84+
orbit_coordinates.append((future_sat_lat, future_sat_lon))
85+
return orbit_coordinates
86+
87+
88+
def main():
89+
download_tle_file()
90+
satellite = load_satellite_data()
91+
driver = webdriver.Firefox()
92+
driver.get(f"file:///{os.path.abspath(MAP_FILENAME)}")
93+
while True:
94+
current_time = datetime.utcnow()
95+
t = load.timescale().utc(
96+
current_time.year,
97+
current_time.month,
98+
current_time.day,
99+
current_time.hour,
100+
current_time.minute,
101+
current_time.second
102+
)
103+
geocentric_pos = satellite.at(t)
104+
sub_pos = geocentric_pos.subpoint()
105+
sat_lat = sub_pos.latitude.degrees
106+
sat_lon = sub_pos.longitude.degrees
107+
iss_map = create_map(sat_lat, sat_lon)
108+
orbit_coordinates = predict_orbit(satellite, t)
109+
folium.PolyLine(
110+
locations=orbit_coordinates,
111+
color="black",
112+
weight=1,
113+
dash_array="5"
114+
).add_to(iss_map)
115+
iss_map.save(MAP_FILENAME)
116+
driver.refresh()
117+
time.sleep(UPDATE_INTERVAL_SECONDS)
118+
119+
120+
# Ensure the "main" function is only executed when the script is run directly.
121+
if __name__ == "__main__":
122+
main()

0 commit comments

Comments
 (0)