-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathiss.py
135 lines (110 loc) · 3.96 KB
/
iss.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
import datetime
import json
import subprocess
from math import cos, degrees, pi, radians, sin
import ephem
import geocoder
import matplotlib.pyplot as plt
import numpy as np
import requests
import scipy
OPEN_NOTIFY = "http://api.open-notify.org/iss-now.json"
CELESTRAK = "http://celestrak.com/NORAD/elements/stations.txt"
ELEV_QUERY = (
"https://www.nationalmap.gov/epqs/pqs.php?x={}&y={}&units=Meters&output=json"
)
CURL = ["curl", "-X", "GET"]
EARTH_RADIUS = 6.3781e6
def latlong2ecef(lat, long, elev):
dist = EARTH_RADIUS + elev
z = dist * sin(radians(lat))
x = dist * cos(radians(lat)) * cos(radians(long))
y = dist * cos(radians(lat)) * sin(radians(long))
return x, y, z
def rotate_y(theta, state=None):
Yrot = np.zeros((3, 3))
Yrot[:, 0] = [cos(radians(theta)), 0, -sin(radians(theta))]
Yrot[:, 1] = [0, 1, 0]
Yrot[:, 2] = [sin(radians(theta)), 0, cos(radians(theta))]
if state is None:
return Yrot
else:
return Yrot * state
def rotate_z(theta, state=None):
Zrot = np.zeros((3, 3))
Zrot[:, 0] = [cos(radians(theta)), sin(radians(theta)), 0]
Zrot[:, 1] = [-sin(radians(theta)), cos(radians(theta)), 0]
Zrot[:, 2] = [0, 0, 1]
if state is None:
return Zrot
else:
return Zrot * state
def translate_point(point, origin):
return point - origin
def nedframe_rotmat(lat, long, point=None):
rot_mat = rotate_z(long) @ rotate_y(-lat) @ rotate_y(-90)
if point is None:
return rot_mat
else:
return rot_mat @ point
def main():
my_angles = np.zeros((3,))
my_xyz = np.zeros((3,))
g = geocoder.ip("me")
my_angles[:2] = g.latlng
CURL.append(ELEV_QUERY.format(my_angles[1], my_angles[0]))
elev_str = subprocess.check_output(CURL)
elev_data = json.loads(elev_str)
my_angles[2] = float(
elev_data["USGS_Elevation_Point_Query_Service"]["Elevation_Query"]["Elevation"]
)
print(
"\nMy Lat: {}, My Long: {}, My Elevation: {}".format(
my_angles[0], my_angles[1], my_angles[2]
)
)
my_xyz[:] = latlong2ecef(my_angles[0], my_angles[1], my_angles[2])
print("My X: {}, My Y: {}, My Z: {}".format(my_xyz[0], my_xyz[1], my_xyz[2]))
ned_rotmat = nedframe_rotmat(my_angles[0], my_angles[1])
print("My NED Frame Rotation Matrix:\n{}\n".format(ned_rotmat))
celes_req = requests.get(CELESTRAK)
txtdata = celes_req.text.split("\r\n")
for i in range(0, 3, len(txtdata)):
if "ISS" in txtdata[i]:
line0 = txtdata[i].strip()
line1 = txtdata[i + 1].strip()
line2 = txtdata[i + 2].strip()
break
print("ISS Ephemeris Data (TLE)")
print(line0)
print(line1)
print(line2)
iss_angles = np.zeros((3,))
iss_xyz = np.zeros((3,))
iss = ephem.readtle(line0, line1, line2)
now = datetime.datetime.utcnow()
iss.compute(now)
iss_angles[:] = degrees(iss.sublat), degrees(iss.sublong), iss.elevation
print(
"ISS Lat: {}, ISS Lon: {}, ISS Elevation: {}".format(
iss_angles[0], iss_angles[1], iss_angles[2]
)
)
iss_xyz[:] = latlong2ecef(iss_angles[0], iss_angles[1], iss_angles[2])
print(
"ISS X: {}, ISS Y: {}, ISS Z: {}\n".format(iss_xyz[0], iss_xyz[1], iss_xyz[2])
)
# ISS In Observer NED (North-East-Down) Frame.
# This is a Local Tangent Plane for an observer on the Earth's surface.
# First, translate ECEF coordinates of ISS to observer origin reference frame
# Then, rotate the result by the NED rotation matrix
iss_translate = translate_point(iss_xyz, my_xyz)
print(
"ISS translated to observer origin reference frame:\n{}".format(iss_translate)
)
iss_rotate = ned_rotmat.T @ iss_translate
print("ISS rotated to observer NED frame:\n{}".format(iss_rotate))
iss_direction = iss_rotate / np.linalg.norm(iss_rotate)
print("Direction unit vector of ISS from observer:\n{}\n".format(iss_direction))
if __name__ == "__main__":
main()