open-space-toolkit-physics 11.3.0__py313-none-manylinux2014_aarch64.whl
Sign up to get free protection for your applications and to get access to all the features.
- open_space_toolkit_physics-11.3.0.dist-info/METADATA +29 -0
- open_space_toolkit_physics-11.3.0.dist-info/RECORD +104 -0
- open_space_toolkit_physics-11.3.0.dist-info/WHEEL +5 -0
- open_space_toolkit_physics-11.3.0.dist-info/top_level.txt +1 -0
- open_space_toolkit_physics-11.3.0.dist-info/zip-safe +1 -0
- ostk/__init__.py +1 -0
- ostk/physics/OpenSpaceToolkitPhysicsPy.cpython-313-aarch64-linux-gnu.so +0 -0
- ostk/physics/__init__.py +6 -0
- ostk/physics/__init__.pyi +488 -0
- ostk/physics/coordinate/__init__.pyi +1002 -0
- ostk/physics/coordinate/frame/__init__.pyi +30 -0
- ostk/physics/coordinate/frame/provider/__init__.pyi +77 -0
- ostk/physics/coordinate/frame/provider/iau.pyi +64 -0
- ostk/physics/coordinate/frame/provider/iers.pyi +584 -0
- ostk/physics/coordinate/spherical.pyi +421 -0
- ostk/physics/data/__init__.pyi +459 -0
- ostk/physics/data/provider.pyi +21 -0
- ostk/physics/environment/__init__.pyi +108 -0
- ostk/physics/environment/atmospheric/__init__.pyi +181 -0
- ostk/physics/environment/atmospheric/earth.pyi +552 -0
- ostk/physics/environment/gravitational/__init__.pyi +559 -0
- ostk/physics/environment/gravitational/earth.pyi +56 -0
- ostk/physics/environment/magnetic/__init__.pyi +171 -0
- ostk/physics/environment/magnetic/earth.pyi +56 -0
- ostk/physics/environment/object/__init__.pyi +430 -0
- ostk/physics/environment/object/celestial/__init__.pyi +248 -0
- ostk/physics/environment/object/celestial/moon.pyi +2 -0
- ostk/physics/environment/object/celestial/sun.pyi +2 -0
- ostk/physics/libopen-space-toolkit-physics.so.11 +0 -0
- ostk/physics/py.typed +0 -0
- ostk/physics/test/__init__.py +1 -0
- ostk/physics/test/coordinate/__init__.py +1 -0
- ostk/physics/test/coordinate/frame/__init__.py +1 -0
- ostk/physics/test/coordinate/frame/provider/__init__.py +1 -0
- ostk/physics/test/coordinate/frame/provider/iers/__init__.py +1 -0
- ostk/physics/test/coordinate/frame/provider/iers/conftest.py +38 -0
- ostk/physics/test/coordinate/frame/provider/iers/data/finals2000A.data +10953 -0
- ostk/physics/test/coordinate/frame/provider/iers/data/ser7.dat +524 -0
- ostk/physics/test/coordinate/frame/provider/iers/test_bulletin_a.py +108 -0
- ostk/physics/test/coordinate/frame/provider/iers/test_finals_2000a.py +93 -0
- ostk/physics/test/coordinate/frame/provider/iers/test_manager.py +205 -0
- ostk/physics/test/coordinate/spherical/__init__.py +1 -0
- ostk/physics/test/coordinate/spherical/test_aer.py +143 -0
- ostk/physics/test/coordinate/spherical/test_lla.py +514 -0
- ostk/physics/test/coordinate/test_axes.py +116 -0
- ostk/physics/test/coordinate/test_frame.py +107 -0
- ostk/physics/test/coordinate/test_position.py +201 -0
- ostk/physics/test/coordinate/test_transform.py +294 -0
- ostk/physics/test/coordinate/test_velocity.py +180 -0
- ostk/physics/test/data/conftest.py +34 -0
- ostk/physics/test/data/data/manifest.json +22 -0
- ostk/physics/test/data/provider/test_provider.py +34 -0
- ostk/physics/test/data/test_direction.py +40 -0
- ostk/physics/test/data/test_manifest.py +43 -0
- ostk/physics/test/data/test_manifest_manager.py +62 -0
- ostk/physics/test/data/test_scalar.py +54 -0
- ostk/physics/test/data/test_vector.py +70 -0
- ostk/physics/test/environment/__init__.py +1 -0
- ostk/physics/test/environment/atmospheric/__init__.py +1 -0
- ostk/physics/test/environment/atmospheric/earth/__init__.py +1 -0
- ostk/physics/test/environment/atmospheric/earth/conftest.py +67 -0
- ostk/physics/test/environment/atmospheric/earth/data/SW-Last5Years.test.csv +22 -0
- ostk/physics/test/environment/atmospheric/earth/data/SpaceWeather-All-v1.2.test.txt +811 -0
- ostk/physics/test/environment/atmospheric/earth/test_cssi_space_weather.py +126 -0
- ostk/physics/test/environment/atmospheric/earth/test_exponential.py +34 -0
- ostk/physics/test/environment/atmospheric/earth/test_manager.py +173 -0
- ostk/physics/test/environment/atmospheric/earth/test_nrlmsise00.py +34 -0
- ostk/physics/test/environment/atmospheric/test_earth.py +141 -0
- ostk/physics/test/environment/gravitational/__init__.py +1 -0
- ostk/physics/test/environment/gravitational/earth/__init__.py +1 -0
- ostk/physics/test/environment/gravitational/earth/test_manager.py +76 -0
- ostk/physics/test/environment/gravitational/test_earth.py +103 -0
- ostk/physics/test/environment/gravitational/test_moon.py +55 -0
- ostk/physics/test/environment/gravitational/test_spherical.py +36 -0
- ostk/physics/test/environment/gravitational/test_sun.py +53 -0
- ostk/physics/test/environment/magnetic/__init__.py +1 -0
- ostk/physics/test/environment/magnetic/earth/test_manager.py +64 -0
- ostk/physics/test/environment/magnetic/test_earth.py +38 -0
- ostk/physics/test/environment/object/__init__.py +1 -0
- ostk/physics/test/environment/object/celestial/__init__ .py +1 -0
- ostk/physics/test/environment/object/celestial/test_earth.py +174 -0
- ostk/physics/test/environment/object/celestial/test_moon.py +17 -0
- ostk/physics/test/environment/object/celestial/test_sun.py +17 -0
- ostk/physics/test/environment/object/test_celestial.py +12 -0
- ostk/physics/test/test_environment.py +97 -0
- ostk/physics/test/test_import.py +25 -0
- ostk/physics/test/time/__init__.py +1 -0
- ostk/physics/test/time/test_date.py +136 -0
- ostk/physics/test/time/test_date_time.py +230 -0
- ostk/physics/test/time/test_duration.py +215 -0
- ostk/physics/test/time/test_instant.py +103 -0
- ostk/physics/test/time/test_interval.py +432 -0
- ostk/physics/test/time/test_scale.py +11 -0
- ostk/physics/test/time/test_time.py +114 -0
- ostk/physics/test/unit/__init__.py +1 -0
- ostk/physics/test/unit/derived/__init__.py +1 -0
- ostk/physics/test/unit/derived/test_angle.py +368 -0
- ostk/physics/test/unit/test_derived.py +152 -0
- ostk/physics/test/unit/test_electric_current.py +5 -0
- ostk/physics/test/unit/test_length.py +297 -0
- ostk/physics/test/unit/test_mass.py +141 -0
- ostk/physics/test/unit/test_time.py +101 -0
- ostk/physics/time.pyi +1744 -0
- ostk/physics/unit.pyi +1590 -0
@@ -0,0 +1,514 @@
|
|
1
|
+
# Apache License 2.0
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
import numpy as np
|
5
|
+
|
6
|
+
from ostk.core.type import String
|
7
|
+
|
8
|
+
from ostk.physics import Environment
|
9
|
+
from ostk.physics.unit import Angle, Length
|
10
|
+
from ostk.physics.coordinate.spherical import LLA
|
11
|
+
from ostk.physics.coordinate import Frame, Position
|
12
|
+
from ostk.physics.environment.gravitational import Earth as EarthGravitationalModel
|
13
|
+
from ostk.physics.environment.object.celestial import Earth
|
14
|
+
|
15
|
+
Spherical = EarthGravitationalModel.spherical
|
16
|
+
WGS84_EGM96 = EarthGravitationalModel.WGS84_EGM96
|
17
|
+
|
18
|
+
ENVIRONMENT = Environment.default(True) # set global environment
|
19
|
+
|
20
|
+
|
21
|
+
@pytest.fixture
|
22
|
+
def latitude_deg() -> float:
|
23
|
+
return 30.0
|
24
|
+
|
25
|
+
|
26
|
+
@pytest.fixture
|
27
|
+
def longitude_deg() -> float:
|
28
|
+
return 30.0
|
29
|
+
|
30
|
+
|
31
|
+
@pytest.fixture
|
32
|
+
def altitude_deg() -> float:
|
33
|
+
return 1000.0
|
34
|
+
|
35
|
+
|
36
|
+
@pytest.fixture
|
37
|
+
def latitude(latitude_deg: float) -> Angle:
|
38
|
+
return Angle(latitude_deg, Angle.Unit.Degree)
|
39
|
+
|
40
|
+
|
41
|
+
@pytest.fixture
|
42
|
+
def longitude(longitude_deg: float) -> Angle:
|
43
|
+
return Angle(longitude_deg, Angle.Unit.Degree)
|
44
|
+
|
45
|
+
|
46
|
+
@pytest.fixture
|
47
|
+
def altitude(altitude_deg: float) -> Length:
|
48
|
+
return Length(altitude_deg, Length.Unit.Meter)
|
49
|
+
|
50
|
+
|
51
|
+
@pytest.fixture
|
52
|
+
def lla(
|
53
|
+
latitude: Angle,
|
54
|
+
longitude: Angle,
|
55
|
+
altitude: Length,
|
56
|
+
) -> LLA:
|
57
|
+
return LLA(latitude, longitude, altitude)
|
58
|
+
|
59
|
+
|
60
|
+
@pytest.fixture
|
61
|
+
def lla_point_equator_1() -> LLA:
|
62
|
+
return LLA(
|
63
|
+
Angle(0.0, Angle.Unit.Degree),
|
64
|
+
Angle(0.0, Angle.Unit.Degree),
|
65
|
+
Length(1.0, Length.Unit.Meter),
|
66
|
+
)
|
67
|
+
|
68
|
+
|
69
|
+
@pytest.fixture
|
70
|
+
def lla_point_equator_2() -> LLA:
|
71
|
+
return LLA(
|
72
|
+
Angle(0.0, Angle.Unit.Degree),
|
73
|
+
Angle(90.0, Angle.Unit.Degree),
|
74
|
+
Length(1.0, Length.Unit.Meter),
|
75
|
+
)
|
76
|
+
|
77
|
+
|
78
|
+
@pytest.fixture
|
79
|
+
def lla_point_equator_3() -> LLA:
|
80
|
+
return LLA(
|
81
|
+
Angle(0.0, Angle.Unit.Degree),
|
82
|
+
Angle(180.0, Angle.Unit.Degree),
|
83
|
+
Length(1.0, Length.Unit.Meter),
|
84
|
+
)
|
85
|
+
|
86
|
+
|
87
|
+
@pytest.fixture
|
88
|
+
def lla_north_pole() -> LLA:
|
89
|
+
return LLA(
|
90
|
+
Angle(90.0, Angle.Unit.Degree),
|
91
|
+
Angle(0.0, Angle.Unit.Degree),
|
92
|
+
Length(1.0, Length.Unit.Meter),
|
93
|
+
)
|
94
|
+
|
95
|
+
|
96
|
+
@pytest.fixture
|
97
|
+
def lla_south_pole() -> LLA:
|
98
|
+
return LLA(
|
99
|
+
Angle(-90.0, Angle.Unit.Degree),
|
100
|
+
Angle(0.0, Angle.Unit.Degree),
|
101
|
+
Length(1.0, Length.Unit.Meter),
|
102
|
+
)
|
103
|
+
|
104
|
+
|
105
|
+
class TestLLA:
|
106
|
+
def test_constructor_list_success(
|
107
|
+
self,
|
108
|
+
latitude_deg: float,
|
109
|
+
longitude_deg: float,
|
110
|
+
altitude_deg: float,
|
111
|
+
):
|
112
|
+
lla: LLA = LLA.vector([latitude_deg, longitude_deg, altitude_deg])
|
113
|
+
assert lla is not None
|
114
|
+
|
115
|
+
def test_constructor_tuple_success(
|
116
|
+
self,
|
117
|
+
latitude_deg: float,
|
118
|
+
longitude_deg: float,
|
119
|
+
altitude_deg: float,
|
120
|
+
):
|
121
|
+
lla: LLA = LLA.vector((latitude_deg, longitude_deg, altitude_deg))
|
122
|
+
assert lla is not None
|
123
|
+
|
124
|
+
def test_constructor_numpy_array_success(
|
125
|
+
self,
|
126
|
+
latitude_deg: float,
|
127
|
+
longitude_deg: float,
|
128
|
+
altitude_deg: float,
|
129
|
+
):
|
130
|
+
lla: LLA = LLA.vector(np.array((latitude_deg, longitude_deg, altitude_deg)))
|
131
|
+
assert lla is not None
|
132
|
+
|
133
|
+
def test_constructor_vector_failure_latitude(self):
|
134
|
+
with pytest.raises(RuntimeError):
|
135
|
+
lla: LLA = LLA.vector((95.0, 1.0, 1.0))
|
136
|
+
|
137
|
+
def test_constructor_vector_failure_longitude(self):
|
138
|
+
with pytest.raises(RuntimeError):
|
139
|
+
lla: LLA = LLA.vector((1.0, -181.0, 1.0))
|
140
|
+
|
141
|
+
def test_constructor_vector_success_altitude_negative(self):
|
142
|
+
lla: LLA = LLA.vector((5.0, 1.0, -1.0))
|
143
|
+
assert lla is not None
|
144
|
+
|
145
|
+
def test_constructor_cartesian_success(self):
|
146
|
+
lla: LLA = LLA.cartesian([1.0, 1.0, 1.0], Length(1.0, Length.Unit.Meter), 0.001)
|
147
|
+
assert lla is not None
|
148
|
+
|
149
|
+
def test_comparator(
|
150
|
+
self,
|
151
|
+
lla_point_equator_1: LLA,
|
152
|
+
lla_point_equator_2: LLA,
|
153
|
+
):
|
154
|
+
assert lla_point_equator_1 == lla_point_equator_1
|
155
|
+
assert lla_point_equator_2 == lla_point_equator_2
|
156
|
+
assert lla_point_equator_1 != lla_point_equator_2
|
157
|
+
|
158
|
+
def test_is_defined(
|
159
|
+
self,
|
160
|
+
lla: LLA,
|
161
|
+
):
|
162
|
+
assert lla.is_defined()
|
163
|
+
assert lla.undefined().is_defined() is False
|
164
|
+
|
165
|
+
def test_getters(
|
166
|
+
self,
|
167
|
+
latitude: Angle,
|
168
|
+
longitude: Angle,
|
169
|
+
altitude: Length,
|
170
|
+
lla: LLA,
|
171
|
+
):
|
172
|
+
assert lla.get_latitude() == latitude
|
173
|
+
assert lla.get_longitude() == longitude
|
174
|
+
assert lla.get_altitude() == altitude
|
175
|
+
|
176
|
+
def test_on_surface(
|
177
|
+
self,
|
178
|
+
lla: LLA,
|
179
|
+
):
|
180
|
+
assert lla.on_surface() is not None
|
181
|
+
|
182
|
+
def test_calculate_distance_to(
|
183
|
+
self,
|
184
|
+
lla_north_pole: LLA,
|
185
|
+
lla_south_pole: LLA,
|
186
|
+
):
|
187
|
+
zero_distance_spherical: Length = lla_north_pole.calculate_distance_to(
|
188
|
+
lla_north_pole,
|
189
|
+
Spherical.equatorial_radius,
|
190
|
+
Spherical.flattening,
|
191
|
+
)
|
192
|
+
assert zero_distance_spherical is not None
|
193
|
+
assert zero_distance_spherical.in_meters() == 0.0
|
194
|
+
|
195
|
+
distance_spherical_poles: Length = lla_south_pole.calculate_distance_to(
|
196
|
+
lla_north_pole,
|
197
|
+
Spherical.equatorial_radius,
|
198
|
+
Spherical.flattening,
|
199
|
+
)
|
200
|
+
assert (
|
201
|
+
distance_spherical_poles.in_meters()
|
202
|
+
== Spherical.equatorial_radius.in_meters() * np.pi
|
203
|
+
)
|
204
|
+
|
205
|
+
assert lla_south_pole.calculate_distance_to(lla_north_pole) is not None
|
206
|
+
|
207
|
+
def test_calculate_azimuth_to(
|
208
|
+
self,
|
209
|
+
lla_point_equator_1: LLA,
|
210
|
+
lla_point_equator_2: LLA,
|
211
|
+
):
|
212
|
+
azimuths: Angle = lla_point_equator_1.calculate_azimuth_to(
|
213
|
+
lla_point_equator_2,
|
214
|
+
Spherical.equatorial_radius,
|
215
|
+
Spherical.flattening,
|
216
|
+
)
|
217
|
+
assert azimuths is not None
|
218
|
+
assert isinstance(azimuths, tuple)
|
219
|
+
assert len(azimuths) == 2
|
220
|
+
assert isinstance(azimuths[0], Angle)
|
221
|
+
assert isinstance(azimuths[1], Angle)
|
222
|
+
|
223
|
+
assert lla_point_equator_1.calculate_azimuth_to(lla_point_equator_2) is not None
|
224
|
+
|
225
|
+
def test_calculate_intermediate_to(
|
226
|
+
self,
|
227
|
+
lla_point_equator_1: LLA,
|
228
|
+
lla_point_equator_2: LLA,
|
229
|
+
):
|
230
|
+
lla_intermediate: LLA = lla_point_equator_1.calculate_intermediate_to(
|
231
|
+
lla_point_equator_2,
|
232
|
+
0.3,
|
233
|
+
Spherical.equatorial_radius,
|
234
|
+
Spherical.flattening,
|
235
|
+
)
|
236
|
+
assert lla_intermediate is not None
|
237
|
+
assert isinstance(lla_intermediate, LLA)
|
238
|
+
|
239
|
+
assert (
|
240
|
+
lla_point_equator_1.calculate_intermediate_to(lla_point_equator_2, 0.3)
|
241
|
+
is not None
|
242
|
+
)
|
243
|
+
|
244
|
+
def test_calculate_forward(
|
245
|
+
self,
|
246
|
+
lla: LLA,
|
247
|
+
):
|
248
|
+
lla_forward: LLA = lla.calculate_forward(
|
249
|
+
Angle.degrees(0.0),
|
250
|
+
Length.meters(5000.0),
|
251
|
+
Spherical.equatorial_radius,
|
252
|
+
Spherical.flattening,
|
253
|
+
)
|
254
|
+
assert lla_forward is not None
|
255
|
+
assert isinstance(lla_forward, LLA)
|
256
|
+
|
257
|
+
assert (
|
258
|
+
lla.calculate_forward(Angle.degrees(0.0), Length.meters(5000.0)) is not None
|
259
|
+
)
|
260
|
+
|
261
|
+
def test_calculate_linspace_to(
|
262
|
+
self,
|
263
|
+
lla_point_equator_1: LLA,
|
264
|
+
lla_point_equator_2: LLA,
|
265
|
+
):
|
266
|
+
n_points: int = 10
|
267
|
+
llas: LLA = lla_point_equator_1.calculate_linspace_to(
|
268
|
+
lla_point_equator_2,
|
269
|
+
n_points,
|
270
|
+
Spherical.equatorial_radius,
|
271
|
+
Spherical.flattening,
|
272
|
+
)
|
273
|
+
assert llas is not None
|
274
|
+
assert len(llas) == n_points
|
275
|
+
|
276
|
+
assert (
|
277
|
+
lla_point_equator_1.calculate_linspace_to(lla_point_equator_2, n_points)
|
278
|
+
is not None
|
279
|
+
)
|
280
|
+
|
281
|
+
def test_to_vector(
|
282
|
+
self,
|
283
|
+
latitude_deg: float,
|
284
|
+
longitude_deg: float,
|
285
|
+
altitude_deg: float,
|
286
|
+
lla: LLA,
|
287
|
+
):
|
288
|
+
vector: np.ndarray = lla.to_vector()
|
289
|
+
|
290
|
+
assert vector[0] == latitude_deg
|
291
|
+
assert vector[1] == longitude_deg
|
292
|
+
assert vector[2] == altitude_deg
|
293
|
+
|
294
|
+
def test_to_cartesian(
|
295
|
+
self,
|
296
|
+
lla: LLA,
|
297
|
+
):
|
298
|
+
cartesian: np.ndarray = LLA.to_cartesian(lla, Length.meters(3.0), 3.0)
|
299
|
+
assert cartesian is not None
|
300
|
+
|
301
|
+
assert LLA.to_cartesian(lla) is not None
|
302
|
+
|
303
|
+
def test_conversion_string(
|
304
|
+
self,
|
305
|
+
latitude_deg: float,
|
306
|
+
longitude_deg: float,
|
307
|
+
altitude_deg: float,
|
308
|
+
lla: LLA,
|
309
|
+
):
|
310
|
+
lla_string: String = lla.to_string()
|
311
|
+
|
312
|
+
assert lla_string is not None
|
313
|
+
assert isinstance(lla_string, String)
|
314
|
+
assert (
|
315
|
+
lla_string
|
316
|
+
== f"[{latitude_deg} [deg], {longitude_deg} [deg], {altitude_deg} [m]]"
|
317
|
+
)
|
318
|
+
|
319
|
+
def test_distance_between(
|
320
|
+
self,
|
321
|
+
lla_point_equator_1: LLA,
|
322
|
+
lla_point_equator_2: LLA,
|
323
|
+
lla_point_equator_3: LLA,
|
324
|
+
lla_north_pole: LLA,
|
325
|
+
lla_south_pole: LLA,
|
326
|
+
):
|
327
|
+
zero_distance_spherical: Length = LLA.distance_between(
|
328
|
+
lla_point_equator_1,
|
329
|
+
lla_point_equator_1,
|
330
|
+
Spherical.equatorial_radius,
|
331
|
+
Spherical.flattening,
|
332
|
+
)
|
333
|
+
assert zero_distance_spherical is not None
|
334
|
+
assert zero_distance_spherical.in_meters() == 0.0
|
335
|
+
|
336
|
+
distance_spherical_equatorial_1_2: Length = LLA.distance_between(
|
337
|
+
lla_point_equator_1,
|
338
|
+
lla_point_equator_2,
|
339
|
+
Spherical.equatorial_radius,
|
340
|
+
Spherical.flattening,
|
341
|
+
)
|
342
|
+
distance_spherical_equatorial_2_1: Length = LLA.distance_between(
|
343
|
+
lla_point_equator_2,
|
344
|
+
lla_point_equator_1,
|
345
|
+
Spherical.equatorial_radius,
|
346
|
+
Spherical.flattening,
|
347
|
+
)
|
348
|
+
assert (
|
349
|
+
distance_spherical_equatorial_1_2.in_meters()
|
350
|
+
== Spherical.equatorial_radius.in_meters() * np.pi / 2
|
351
|
+
)
|
352
|
+
assert (
|
353
|
+
distance_spherical_equatorial_2_1.in_meters()
|
354
|
+
== Spherical.equatorial_radius.in_meters() * np.pi / 2
|
355
|
+
)
|
356
|
+
|
357
|
+
distance_spherical_equatorial_1_3: Length = LLA.distance_between(
|
358
|
+
lla_point_equator_1,
|
359
|
+
lla_point_equator_3,
|
360
|
+
Spherical.equatorial_radius,
|
361
|
+
Spherical.flattening,
|
362
|
+
)
|
363
|
+
distance_spherical_equatorial_3_1: Length = LLA.distance_between(
|
364
|
+
lla_point_equator_3,
|
365
|
+
lla_point_equator_1,
|
366
|
+
Spherical.equatorial_radius,
|
367
|
+
Spherical.flattening,
|
368
|
+
)
|
369
|
+
assert (
|
370
|
+
distance_spherical_equatorial_1_3.in_meters()
|
371
|
+
== Spherical.equatorial_radius.in_meters() * np.pi
|
372
|
+
)
|
373
|
+
assert (
|
374
|
+
distance_spherical_equatorial_3_1.in_meters()
|
375
|
+
== Spherical.equatorial_radius.in_meters() * np.pi
|
376
|
+
)
|
377
|
+
|
378
|
+
distance_spherical_poles: Length = LLA.distance_between(
|
379
|
+
lla_north_pole,
|
380
|
+
lla_south_pole,
|
381
|
+
Spherical.equatorial_radius,
|
382
|
+
Spherical.flattening,
|
383
|
+
)
|
384
|
+
assert distance_spherical_poles == distance_spherical_equatorial_1_3
|
385
|
+
|
386
|
+
distance_wgs84_equatorial_1_2: Length = LLA.distance_between(
|
387
|
+
lla_point_equator_1,
|
388
|
+
lla_point_equator_2,
|
389
|
+
WGS84_EGM96.equatorial_radius,
|
390
|
+
WGS84_EGM96.flattening,
|
391
|
+
)
|
392
|
+
assert (
|
393
|
+
distance_wgs84_equatorial_1_2 == distance_spherical_equatorial_1_2
|
394
|
+
) # on equator
|
395
|
+
|
396
|
+
distance_wgs84_equatorial_1_3: Length = LLA.distance_between(
|
397
|
+
lla_point_equator_1,
|
398
|
+
lla_point_equator_3,
|
399
|
+
WGS84_EGM96.equatorial_radius,
|
400
|
+
WGS84_EGM96.flattening,
|
401
|
+
) # through the poles
|
402
|
+
distance_wgs84_equatorial_3_1: Length = LLA.distance_between(
|
403
|
+
lla_point_equator_3,
|
404
|
+
lla_point_equator_1,
|
405
|
+
WGS84_EGM96.equatorial_radius,
|
406
|
+
WGS84_EGM96.flattening,
|
407
|
+
) # through the poles
|
408
|
+
distance_wgs84_equatorial_2_3: Length = LLA.distance_between(
|
409
|
+
lla_point_equator_2,
|
410
|
+
lla_point_equator_3,
|
411
|
+
WGS84_EGM96.equatorial_radius,
|
412
|
+
WGS84_EGM96.flattening,
|
413
|
+
)
|
414
|
+
|
415
|
+
assert distance_wgs84_equatorial_3_1 == distance_wgs84_equatorial_1_3
|
416
|
+
assert (
|
417
|
+
distance_wgs84_equatorial_1_3
|
418
|
+
< distance_wgs84_equatorial_1_2 + distance_wgs84_equatorial_2_3
|
419
|
+
)
|
420
|
+
|
421
|
+
distance_wgs84_1_north_pole: Length = LLA.distance_between(
|
422
|
+
lla_point_equator_1,
|
423
|
+
lla_north_pole,
|
424
|
+
WGS84_EGM96.equatorial_radius,
|
425
|
+
WGS84_EGM96.flattening,
|
426
|
+
)
|
427
|
+
assert (
|
428
|
+
distance_wgs84_1_north_pole < distance_wgs84_equatorial_1_2
|
429
|
+
) # flattened surface at poles
|
430
|
+
assert distance_wgs84_1_north_pole < distance_spherical_equatorial_1_2
|
431
|
+
|
432
|
+
def test_azimuth_between(
|
433
|
+
self,
|
434
|
+
lla_point_equator_1: LLA,
|
435
|
+
lla_point_equator_2: LLA,
|
436
|
+
):
|
437
|
+
azimuths: Angle = LLA.azimuth_between(
|
438
|
+
lla_point_equator_1,
|
439
|
+
lla_point_equator_2,
|
440
|
+
Spherical.equatorial_radius,
|
441
|
+
Spherical.flattening,
|
442
|
+
)
|
443
|
+
assert azimuths is not None
|
444
|
+
assert isinstance(azimuths, tuple)
|
445
|
+
assert len(azimuths) == 2
|
446
|
+
assert isinstance(azimuths[0], Angle)
|
447
|
+
assert isinstance(azimuths[1], Angle)
|
448
|
+
|
449
|
+
def test_intermediate_between(
|
450
|
+
self,
|
451
|
+
lla_point_equator_1: LLA,
|
452
|
+
lla_point_equator_2: LLA,
|
453
|
+
):
|
454
|
+
lla_intermediate: LLA = LLA.intermediate_between(
|
455
|
+
lla_point_equator_1,
|
456
|
+
lla_point_equator_2,
|
457
|
+
0.3,
|
458
|
+
Spherical.equatorial_radius,
|
459
|
+
Spherical.flattening,
|
460
|
+
)
|
461
|
+
assert lla_intermediate is not None
|
462
|
+
assert isinstance(lla_intermediate, LLA)
|
463
|
+
|
464
|
+
def test_forward(
|
465
|
+
self,
|
466
|
+
lla: LLA,
|
467
|
+
):
|
468
|
+
lla_forward: LLA = LLA.forward(
|
469
|
+
lla,
|
470
|
+
Angle.degrees(0.0),
|
471
|
+
Length.meters(5000.0),
|
472
|
+
Spherical.equatorial_radius,
|
473
|
+
Spherical.flattening,
|
474
|
+
)
|
475
|
+
assert lla_forward is not None
|
476
|
+
assert isinstance(lla_forward, LLA)
|
477
|
+
|
478
|
+
def test_linspace(
|
479
|
+
self,
|
480
|
+
lla_point_equator_1: LLA,
|
481
|
+
lla_point_equator_2: LLA,
|
482
|
+
):
|
483
|
+
n_points: int = 10
|
484
|
+
llas: LLA = LLA.linspace(
|
485
|
+
lla_point_equator_1,
|
486
|
+
lla_point_equator_2,
|
487
|
+
n_points,
|
488
|
+
Spherical.equatorial_radius,
|
489
|
+
Spherical.flattening,
|
490
|
+
)
|
491
|
+
assert llas is not None
|
492
|
+
assert len(llas) == n_points
|
493
|
+
|
494
|
+
def test_from_position(self):
|
495
|
+
earth = Earth.WGS84()
|
496
|
+
frame = Frame.ITRF()
|
497
|
+
position = Position.meters([6378137.0, 0.0, 0.0], frame) # Point on equator
|
498
|
+
|
499
|
+
lla = LLA.from_position(position, earth)
|
500
|
+
assert lla is not None
|
501
|
+
assert abs(float(lla.get_latitude().in_degrees())) < 1e-10 # Should be on equator
|
502
|
+
|
503
|
+
assert (
|
504
|
+
abs(float(lla.get_longitude().in_degrees())) < 1e-10
|
505
|
+
) # Should be at prime meridian
|
506
|
+
assert abs(float(lla.get_altitude().in_meters())) < 1e-6 # Should be near surface
|
507
|
+
|
508
|
+
# Test with undefined position
|
509
|
+
with pytest.raises(RuntimeError):
|
510
|
+
LLA.from_position(Position.undefined())
|
511
|
+
|
512
|
+
# Test with global environment
|
513
|
+
lla = LLA.from_position(position)
|
514
|
+
assert lla is not None
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# Apache License 2.0
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
import numpy as np
|
5
|
+
|
6
|
+
import ostk.physics as physics
|
7
|
+
|
8
|
+
Scale = physics.time.Scale
|
9
|
+
DateTime = physics.time.DateTime
|
10
|
+
Instant = physics.time.Instant
|
11
|
+
Frame = physics.coordinate.Frame
|
12
|
+
Axes = physics.coordinate.Axes
|
13
|
+
|
14
|
+
|
15
|
+
def test_coordinate_axes_constructors():
|
16
|
+
# Construct arbitrary Frame
|
17
|
+
frame: Frame = Frame.GCRF()
|
18
|
+
|
19
|
+
# Construction using python lists
|
20
|
+
vector_1 = [1.0, 0.0, 0.0]
|
21
|
+
vector_2 = [0.0, 1.0, 0.0]
|
22
|
+
vector_3 = [0.0, 0.0, 1.0]
|
23
|
+
|
24
|
+
axes: Axes = Axes(vector_1, vector_2, vector_3, frame)
|
25
|
+
|
26
|
+
assert axes is not None
|
27
|
+
assert isinstance(axes, Axes)
|
28
|
+
assert axes.is_defined() is True
|
29
|
+
|
30
|
+
# Construction using python tuples
|
31
|
+
vector_1 = (1.0, 0.0, 0.0)
|
32
|
+
vector_2 = (0.0, 1.0, 0.0)
|
33
|
+
vector_3 = (0.0, 0.0, 1.0)
|
34
|
+
|
35
|
+
axes: Axes = Axes(vector_1, vector_2, vector_3, frame)
|
36
|
+
|
37
|
+
assert axes is not None
|
38
|
+
assert isinstance(axes, Axes)
|
39
|
+
assert axes.is_defined() is True
|
40
|
+
|
41
|
+
# Construction using python numpy arrays
|
42
|
+
vector_1 = np.array(vector_1)
|
43
|
+
vector_2 = np.array(vector_2)
|
44
|
+
vector_3 = np.array(vector_3)
|
45
|
+
|
46
|
+
axes: Axes = Axes(vector_1, vector_2, vector_3, frame)
|
47
|
+
|
48
|
+
assert axes is not None
|
49
|
+
assert isinstance(axes, Axes)
|
50
|
+
assert axes.is_defined() is True
|
51
|
+
|
52
|
+
# Construction using undefined method
|
53
|
+
|
54
|
+
axes: Axes = Axes.undefined()
|
55
|
+
|
56
|
+
assert axes is not None
|
57
|
+
assert isinstance(axes, Axes)
|
58
|
+
assert axes.is_defined() is False
|
59
|
+
|
60
|
+
|
61
|
+
def test_coordinate_axes_xyz():
|
62
|
+
frame: Frame = Frame.GCRF()
|
63
|
+
vector_1 = [1.0, 0.0, 0.0]
|
64
|
+
vector_2 = [0.0, 1.0, 0.0]
|
65
|
+
vector_3 = [0.0, 0.0, 1.0]
|
66
|
+
|
67
|
+
axes: Axes = Axes(vector_1, vector_2, vector_3, frame)
|
68
|
+
|
69
|
+
x = axes.x()
|
70
|
+
y = axes.y()
|
71
|
+
z = axes.z()
|
72
|
+
|
73
|
+
assert x is not None
|
74
|
+
assert isinstance(x, np.ndarray)
|
75
|
+
assert np.array_equal(x, vector_1)
|
76
|
+
|
77
|
+
assert y is not None
|
78
|
+
assert isinstance(y, np.ndarray)
|
79
|
+
assert np.array_equal(y, vector_2)
|
80
|
+
|
81
|
+
assert z is not None
|
82
|
+
assert isinstance(z, np.ndarray)
|
83
|
+
assert np.array_equal(z, vector_3)
|
84
|
+
|
85
|
+
|
86
|
+
def test_coordinate_axes_get_frame():
|
87
|
+
frame: Frame = Frame.GCRF()
|
88
|
+
vector_1 = [1.0, 0.0, 0.0]
|
89
|
+
vector_2 = [0.0, 1.0, 0.0]
|
90
|
+
vector_3 = [0.0, 0.0, 1.0]
|
91
|
+
|
92
|
+
axes: Axes = Axes(vector_1, vector_2, vector_3, frame)
|
93
|
+
|
94
|
+
assert axes.get_frame() is not None
|
95
|
+
assert isinstance(axes.get_frame(), Frame)
|
96
|
+
assert axes.get_frame() == frame
|
97
|
+
|
98
|
+
|
99
|
+
@pytest.mark.skip
|
100
|
+
def test_coordinate_axes_in_frame():
|
101
|
+
frame: Frame = Frame.GCRF()
|
102
|
+
vector_1 = [1.0, 0.0, 0.0]
|
103
|
+
vector_2 = [0.0, 1.0, 0.0]
|
104
|
+
vector_3 = [0.0, 0.0, 1.0]
|
105
|
+
|
106
|
+
axes: Axes = Axes(vector_1, vector_2, vector_3, frame)
|
107
|
+
|
108
|
+
instant: Instant = Instant.date_time(DateTime(2020, 1, 1, 0, 0, 0), Scale.UTC)
|
109
|
+
|
110
|
+
assert axes.in_frame(Frame.GCRF(), instant) is not None
|
111
|
+
assert isinstance(axes.in_frame(Frame.GCRF(), instant), Axes)
|
112
|
+
assert axes.in_frame(Frame.GCRF(), instant) == axes
|
113
|
+
|
114
|
+
assert axes.in_frame(Frame.TEME(), instant) is not None
|
115
|
+
assert isinstance(axes.in_frame(Frame.TEME(), instant), Axes)
|
116
|
+
assert axes.in_frame(Frame.TEME(), instant) != axes
|