open-space-toolkit-physics 11.3.0__py310-none-manylinux2014_x86_64.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. open_space_toolkit_physics-11.3.0.dist-info/METADATA +29 -0
  2. open_space_toolkit_physics-11.3.0.dist-info/RECORD +104 -0
  3. open_space_toolkit_physics-11.3.0.dist-info/WHEEL +5 -0
  4. open_space_toolkit_physics-11.3.0.dist-info/top_level.txt +1 -0
  5. open_space_toolkit_physics-11.3.0.dist-info/zip-safe +1 -0
  6. ostk/__init__.py +1 -0
  7. ostk/physics/OpenSpaceToolkitPhysicsPy.cpython-310-x86_64-linux-gnu.so +0 -0
  8. ostk/physics/__init__.py +6 -0
  9. ostk/physics/__init__.pyi +488 -0
  10. ostk/physics/coordinate/__init__.pyi +1002 -0
  11. ostk/physics/coordinate/frame/__init__.pyi +30 -0
  12. ostk/physics/coordinate/frame/provider/__init__.pyi +77 -0
  13. ostk/physics/coordinate/frame/provider/iau.pyi +64 -0
  14. ostk/physics/coordinate/frame/provider/iers.pyi +584 -0
  15. ostk/physics/coordinate/spherical.pyi +421 -0
  16. ostk/physics/data/__init__.pyi +459 -0
  17. ostk/physics/data/provider.pyi +21 -0
  18. ostk/physics/environment/__init__.pyi +108 -0
  19. ostk/physics/environment/atmospheric/__init__.pyi +181 -0
  20. ostk/physics/environment/atmospheric/earth.pyi +552 -0
  21. ostk/physics/environment/gravitational/__init__.pyi +559 -0
  22. ostk/physics/environment/gravitational/earth.pyi +56 -0
  23. ostk/physics/environment/magnetic/__init__.pyi +171 -0
  24. ostk/physics/environment/magnetic/earth.pyi +56 -0
  25. ostk/physics/environment/object/__init__.pyi +430 -0
  26. ostk/physics/environment/object/celestial/__init__.pyi +248 -0
  27. ostk/physics/environment/object/celestial/moon.pyi +2 -0
  28. ostk/physics/environment/object/celestial/sun.pyi +2 -0
  29. ostk/physics/libopen-space-toolkit-physics.so.11 +0 -0
  30. ostk/physics/py.typed +0 -0
  31. ostk/physics/test/__init__.py +1 -0
  32. ostk/physics/test/coordinate/__init__.py +1 -0
  33. ostk/physics/test/coordinate/frame/__init__.py +1 -0
  34. ostk/physics/test/coordinate/frame/provider/__init__.py +1 -0
  35. ostk/physics/test/coordinate/frame/provider/iers/__init__.py +1 -0
  36. ostk/physics/test/coordinate/frame/provider/iers/conftest.py +38 -0
  37. ostk/physics/test/coordinate/frame/provider/iers/data/finals2000A.data +10953 -0
  38. ostk/physics/test/coordinate/frame/provider/iers/data/ser7.dat +524 -0
  39. ostk/physics/test/coordinate/frame/provider/iers/test_bulletin_a.py +108 -0
  40. ostk/physics/test/coordinate/frame/provider/iers/test_finals_2000a.py +93 -0
  41. ostk/physics/test/coordinate/frame/provider/iers/test_manager.py +205 -0
  42. ostk/physics/test/coordinate/spherical/__init__.py +1 -0
  43. ostk/physics/test/coordinate/spherical/test_aer.py +143 -0
  44. ostk/physics/test/coordinate/spherical/test_lla.py +514 -0
  45. ostk/physics/test/coordinate/test_axes.py +116 -0
  46. ostk/physics/test/coordinate/test_frame.py +107 -0
  47. ostk/physics/test/coordinate/test_position.py +201 -0
  48. ostk/physics/test/coordinate/test_transform.py +294 -0
  49. ostk/physics/test/coordinate/test_velocity.py +180 -0
  50. ostk/physics/test/data/conftest.py +34 -0
  51. ostk/physics/test/data/data/manifest.json +22 -0
  52. ostk/physics/test/data/provider/test_provider.py +34 -0
  53. ostk/physics/test/data/test_direction.py +40 -0
  54. ostk/physics/test/data/test_manifest.py +43 -0
  55. ostk/physics/test/data/test_manifest_manager.py +62 -0
  56. ostk/physics/test/data/test_scalar.py +54 -0
  57. ostk/physics/test/data/test_vector.py +70 -0
  58. ostk/physics/test/environment/__init__.py +1 -0
  59. ostk/physics/test/environment/atmospheric/__init__.py +1 -0
  60. ostk/physics/test/environment/atmospheric/earth/__init__.py +1 -0
  61. ostk/physics/test/environment/atmospheric/earth/conftest.py +67 -0
  62. ostk/physics/test/environment/atmospheric/earth/data/SW-Last5Years.test.csv +22 -0
  63. ostk/physics/test/environment/atmospheric/earth/data/SpaceWeather-All-v1.2.test.txt +811 -0
  64. ostk/physics/test/environment/atmospheric/earth/test_cssi_space_weather.py +126 -0
  65. ostk/physics/test/environment/atmospheric/earth/test_exponential.py +34 -0
  66. ostk/physics/test/environment/atmospheric/earth/test_manager.py +173 -0
  67. ostk/physics/test/environment/atmospheric/earth/test_nrlmsise00.py +34 -0
  68. ostk/physics/test/environment/atmospheric/test_earth.py +141 -0
  69. ostk/physics/test/environment/gravitational/__init__.py +1 -0
  70. ostk/physics/test/environment/gravitational/earth/__init__.py +1 -0
  71. ostk/physics/test/environment/gravitational/earth/test_manager.py +76 -0
  72. ostk/physics/test/environment/gravitational/test_earth.py +103 -0
  73. ostk/physics/test/environment/gravitational/test_moon.py +55 -0
  74. ostk/physics/test/environment/gravitational/test_spherical.py +36 -0
  75. ostk/physics/test/environment/gravitational/test_sun.py +53 -0
  76. ostk/physics/test/environment/magnetic/__init__.py +1 -0
  77. ostk/physics/test/environment/magnetic/earth/test_manager.py +64 -0
  78. ostk/physics/test/environment/magnetic/test_earth.py +38 -0
  79. ostk/physics/test/environment/object/__init__.py +1 -0
  80. ostk/physics/test/environment/object/celestial/__init__ .py +1 -0
  81. ostk/physics/test/environment/object/celestial/test_earth.py +174 -0
  82. ostk/physics/test/environment/object/celestial/test_moon.py +17 -0
  83. ostk/physics/test/environment/object/celestial/test_sun.py +17 -0
  84. ostk/physics/test/environment/object/test_celestial.py +12 -0
  85. ostk/physics/test/test_environment.py +97 -0
  86. ostk/physics/test/test_import.py +25 -0
  87. ostk/physics/test/time/__init__.py +1 -0
  88. ostk/physics/test/time/test_date.py +136 -0
  89. ostk/physics/test/time/test_date_time.py +230 -0
  90. ostk/physics/test/time/test_duration.py +215 -0
  91. ostk/physics/test/time/test_instant.py +103 -0
  92. ostk/physics/test/time/test_interval.py +432 -0
  93. ostk/physics/test/time/test_scale.py +11 -0
  94. ostk/physics/test/time/test_time.py +114 -0
  95. ostk/physics/test/unit/__init__.py +1 -0
  96. ostk/physics/test/unit/derived/__init__.py +1 -0
  97. ostk/physics/test/unit/derived/test_angle.py +368 -0
  98. ostk/physics/test/unit/test_derived.py +152 -0
  99. ostk/physics/test/unit/test_electric_current.py +5 -0
  100. ostk/physics/test/unit/test_length.py +297 -0
  101. ostk/physics/test/unit/test_mass.py +141 -0
  102. ostk/physics/test/unit/test_time.py +101 -0
  103. ostk/physics/time.pyi +1744 -0
  104. 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