-
Notifications
You must be signed in to change notification settings - Fork 0
/
ISS_loc.py
138 lines (103 loc) · 4.2 KB
/
ISS_loc.py
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
135
136
137
138
from PIL import Image
from colorama import Fore, init, Style
from typing import Tuple
import os, requests, time, math, copy
# https://www.esa.int/Science_Exploration/Human_and_Robotic_Exploration/International_Space_Station/Where_is_the_International_Space_Station
init(autoreset=True)
img = Image.open("map.png")
width, height = img.size
ratio = height / width
MAP_Width = 342
MAP_Height = int(ratio * MAP_Width * 0.55)
call_freq = 10 # seconds
history_queue = []
history_queue_max_size = 10800 / call_freq # 3 hrs (2 orbits), ISS orbits the Earth every 90 minutes
def lat_lon_to_mercator(lat, lon, MAP_Width, MAP_Height) -> Tuple[int, int]: # lat lon
longitude_radians = lon * math.pi / 180
latitude_radians = lat * math.pi / 180
x_scale = MAP_Width / 2 / math.pi
# Mercator projection stretches north-south, theoretically ranges from -infinity to +infinity, so we need to dynamic scale it to try to get the relative correct range from 0 to 1
# Too far north or south and the map distorts, Google Map supports up to 85 degrees north and south
# min_lat = -85 * math.pi / 180
# max_lat = 85 * math.pi / 180
# min_mercator = math.log(math.tan((math.pi / 4) + (min_lat / 2)))
# max_mercator = math.log(math.tan((math.pi / 4) + (max_lat / 2)))
# y_scale = MAP_Height / (max_mercator - min_mercator)
y_scale = MAP_Height / 2 / math.pi
x = MAP_Width / 2 + x_scale * longitude_radians
# y = MAP_Height / 2 - y_scale * (math.log(math.tan((math.pi / 4) + (latitude_radians / 2))))
y = MAP_Height / 2 - y_scale * math.log((1 + math.sin(latitude_radians)) / (1 - math.sin(latitude_radians)))
return int(y), int(x)
def ISS_loc(lat: float, lon: float) -> list:
if MAP_Width <= 200:
side = 0
elif MAP_Width <= 540:
side = 1
else:
side = 2
loc = []
for i in range(-side, side+1):
if lat+i >= 0 and lat+i < MAP_Height and lon+i >= 0 and lon+i < MAP_Width:
loc.append([lat-i, lon+i, '*'])
loc.append([lat-i, lon-i, '*'])
loc.append([lat+i, lon, '*'])
loc.append([lat, lon+i, '*'])
return loc
img = img.resize((MAP_Width, int(MAP_Height)))
img = img.convert('L') # grey scale
pixels = img.getdata()
ascii_str = ''
for pixel_value in pixels:
ascii_str += ' .,*aY=#+PA%BDJ@'[pixel_value // 17] # pixel value 0-255
#@JDB%AP+#=Ya*,.
# Convert the string to a 2D array (lat, lon)
ascii_img = []
for i in range(0, len(ascii_str), MAP_Width):
ascii_img.append([char for char in ascii_str[i:i+MAP_Width]])
ascii_backup = copy.deepcopy(ascii_img)
url = 'http://api.open-notify.org/iss-now.json'
while True:
os.system("cls")
try:
response = requests.get(url).json()
except Exception as e:
print(e)
time.sleep(10)
continue
LAT = float(response['iss_position']['latitude'])
LON = float(response['iss_position']['longitude'])
x, y = lat_lon_to_mercator(LAT, LON, MAP_Width, MAP_Height)
# x, y = MAP_Height - int(LAT + 90 % 180), int(LON + 180 % 360)
print(LAT, LON)
print(x, y)
print('Map size: ', MAP_Width, MAP_Height)
history_queue.insert(0, [x, y])
if len(history_queue) > history_queue_max_size:
pop_loc = history_queue.pop()
ascii_img[pop_loc[0]][pop_loc[1]] = Style.RESET_ALL + ascii_backup[pop_loc[0]][pop_loc[1]]
# Draw 2hr history
for idx, h in enumerate(history_queue):
# if first half, be cyan, else yellow
try:
if idx < history_queue_max_size // 2:
ascii_img[h[0]][h[1]] = Fore.CYAN + '>' + Fore.RESET
else:
ascii_img[h[0]][h[1]] = Fore.YELLOW + '>' + Fore.RESET
except:
pass
# ascii_img[x][y] = Fore.RED + '&' + Fore.RESET
# Draw ISS location
for loc in ISS_loc(x, y):
try:
ascii_img[loc[0]][loc[1]] = Fore.LIGHTYELLOW_EX + loc[2] + Fore.RESET
except:
pass
for row in ascii_img:
print(''.join(row))
# restore the map
for loc in ISS_loc(x, y):
try:
ascii_img[loc[0]][loc[1]] = Style.RESET_ALL + ascii_backup[loc[0]][loc[1]]
except:
pass
time.sleep(call_freq)