-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtracker.py
More file actions
134 lines (113 loc) · 4.82 KB
/
tracker.py
File metadata and controls
134 lines (113 loc) · 4.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
""" Project Description
ISS Insight: Real-Time International Space Station Tracker
This script tracks the International Space Station (more specifically, it tracks ZARYA module of the ISS)
and displays its current position by visualizing its trajectory on the map.
It also predicts the ISS's orbit for the next 90 minutes.
Author: Mohammad Bazargan
Source: https://github.com/BazarganDev/ISS-Insight
"""
# Import necessary modules
from datetime import datetime, timedelta
from skyfield.iokit import parse_tle_file
from skyfield.api import load
from selenium import webdriver
import folium
import time
import os
# Constants
TLE_FILENAME = "data_files/iss_zarya_tle.tle"
TLE_URL = "https://celestrak.org/NORAD/elements/gp.php?CATNR=25544&FORMAT=TLE"
MAP_FILENAME = "map/tracker_map.html"
MAP_ZOOM_START = 2
ORBIT_DURATION_MINUTES = 90
UPDATE_INTERVAL_SECONDS = 60
# Functions
def download_tle_file():
"""
If the ISS (ZARYA) TLE file is missing and is outdated, download the latest data.
"""
if not load.exists(TLE_FILENAME) or load.days_old(TLE_FILENAME) > 1.0:
try:
load.download(TLE_URL, filename=TLE_FILENAME)
except Exception as e:
print(f"ERROR: Failed to download the TLE data.{e}")
exit(1)
def load_satellite_data():
"""
Load the satellite data from the TLE file.
"""
with load.open(TLE_FILENAME) as f:
satellites = list(parse_tle_file(f, load.timescale()))
# Index ISS (ZARYA) by NORADID number.
return {sat.model.satnum: sat for sat in satellites}[25544]
def create_map(sat_lat, sat_lon):
"""
Create a new map with the ISS's current position.
Args:
sat_lat: Satellite latitude.
sat_lon: Satellite longitude.
Return:
sat_map: Visualized location of the satellite map
"""
# Create a map centered onto the ISS position.
sat_map = folium.Map(location=[sat_lat, sat_lon], zoom_start=MAP_ZOOM_START)
# Pinpoint the satellite's current position on the map.
folium.Marker(
location=[sat_lat, sat_lon],
tooltip=f"ISS (Lat: {sat_lat}, Lon: {sat_lon})",
popup="International Space Station (ZARYA)",
icon=folium.Icon(color="red", icon="satellite", prefix="fa")
).add_to(sat_map)
return sat_map
def predict_orbit(satellite, current_time):
"""
Predict the orbit of the satellite by predicting its future poitions.
ISS completes one orbit around the Earth in approximately 90 minutes.
Args:
satellite:
current_time:
Returns:
orbit_coordinates:
"""
# Add current position of the satellite
current_sat_lat = satellite.at(current_time).subpoint().latitude.degrees
current_sat_lon = satellite.at(current_time).subpoint().longitude.degrees
orbit_coordinates = [(current_sat_lat, current_sat_lon)]
for i in range(1, ORBIT_DURATION_MINUTES + 1):
future_time = current_time + timedelta(minutes=i)
future_geocentric_pos = satellite.at(future_time)
future_sub_pos = future_geocentric_pos.subpoint()
future_sat_lat = future_sub_pos.latitude.degrees
future_sat_lon = future_sub_pos.longitude.degrees
# Longitude Adjustment: Check for large jumps in longitude, handling the International Date Line (IDL) problem.
if abs(future_sat_lon - orbit_coordinates[-1][1]) > 180:
future_sat_lon += 360 if future_sat_lon < orbit_coordinates[-1][1] else -360
# Add the fixed coordinates to the list of orbit coordinates.
orbit_coordinates.append((future_sat_lat, future_sat_lon))
return orbit_coordinates
def main():
download_tle_file()
satellite = load_satellite_data()
driver = webdriver.Firefox()
driver.get(f"file:///{os.path.abspath(MAP_FILENAME)}")
while True:
current_time = datetime.utcnow()
t = load.timescale().utc(current_time.year, current_time.month, current_time.day, current_time.hour, current_time.minute, current_time.second)
geocentric_pos = satellite.at(t) # Geocentric Position: Position of the satellite in the vincity of the Earth from its center of mass.
sub_pos = geocentric_pos.subpoint() # Subpoint Position: Position of the satellite projected onto the Earth's surface.
sat_lat = sub_pos.latitude.degrees # Satellite Latitude
sat_lon = sub_pos.longitude.degrees # Satellite Longitude
iss_map = create_map(sat_lat, sat_lon)
orbit_coordinates = predict_orbit(satellite, t)
folium.PolyLine(
locations=orbit_coordinates,
color="black",
weight=1,
dash_array="5"
).add_to(iss_map)
iss_map.save(MAP_FILENAME)
driver.refresh()
time.sleep(UPDATE_INTERVAL_SECONDS)
# Ensure the "main" function is only executed when the script is run directly.
if __name__ == "__main__":
main()