open-space-toolkit-astrodynamics 17.2.0__py312-none-manylinux2014_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. open_space_toolkit_astrodynamics-17.2.0.dist-info/METADATA +30 -0
  2. open_space_toolkit_astrodynamics-17.2.0.dist-info/RECORD +151 -0
  3. open_space_toolkit_astrodynamics-17.2.0.dist-info/WHEEL +5 -0
  4. open_space_toolkit_astrodynamics-17.2.0.dist-info/top_level.txt +1 -0
  5. open_space_toolkit_astrodynamics-17.2.0.dist-info/zip-safe +1 -0
  6. ostk/__init__.py +1 -0
  7. ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-312-x86_64-linux-gnu.so +0 -0
  8. ostk/astrodynamics/__init__.py +11 -0
  9. ostk/astrodynamics/__init__.pyi +720 -0
  10. ostk/astrodynamics/access.pyi +577 -0
  11. ostk/astrodynamics/conjunction/__init__.pyi +121 -0
  12. ostk/astrodynamics/conjunction/close_approach.pyi +89 -0
  13. ostk/astrodynamics/conjunction/message/__init__.pyi +3 -0
  14. ostk/astrodynamics/conjunction/message/ccsds.pyi +705 -0
  15. ostk/astrodynamics/converters.py +130 -0
  16. ostk/astrodynamics/converters.pyi +58 -0
  17. ostk/astrodynamics/data/__init__.pyi +3 -0
  18. ostk/astrodynamics/data/provider.pyi +22 -0
  19. ostk/astrodynamics/dataframe.py +597 -0
  20. ostk/astrodynamics/display.py +281 -0
  21. ostk/astrodynamics/dynamics.pyi +311 -0
  22. ostk/astrodynamics/eclipse.pyi +70 -0
  23. ostk/astrodynamics/estimator.pyi +268 -0
  24. ostk/astrodynamics/event_condition.pyi +910 -0
  25. ostk/astrodynamics/flight/__init__.pyi +626 -0
  26. ostk/astrodynamics/flight/profile/__init__.pyi +99 -0
  27. ostk/astrodynamics/flight/profile/model.pyi +179 -0
  28. ostk/astrodynamics/flight/system.pyi +268 -0
  29. ostk/astrodynamics/guidance_law.pyi +416 -0
  30. ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.17 +0 -0
  31. ostk/astrodynamics/pytrajectory/__init__.py +1 -0
  32. ostk/astrodynamics/pytrajectory/__init__.pyi +3 -0
  33. ostk/astrodynamics/pytrajectory/pystate.py +263 -0
  34. ostk/astrodynamics/pytrajectory/pystate.pyi +66 -0
  35. ostk/astrodynamics/solver.pyi +432 -0
  36. ostk/astrodynamics/test/__init__.py +1 -0
  37. ostk/astrodynamics/test/access/__init__.py +1 -0
  38. ostk/astrodynamics/test/access/test_generator.py +319 -0
  39. ostk/astrodynamics/test/access/test_visibility_criterion.py +201 -0
  40. ostk/astrodynamics/test/conftest.py +119 -0
  41. ostk/astrodynamics/test/conjunction/close_approach/__init__.py +0 -0
  42. ostk/astrodynamics/test/conjunction/close_approach/test_generator.py +228 -0
  43. ostk/astrodynamics/test/conjunction/message/ccsds/__init__.py +1 -0
  44. ostk/astrodynamics/test/conjunction/message/ccsds/conftest.py +325 -0
  45. ostk/astrodynamics/test/conjunction/message/ccsds/data/cdm.json +303 -0
  46. ostk/astrodynamics/test/conjunction/message/ccsds/test_cdm.py +416 -0
  47. ostk/astrodynamics/test/conjunction/test_close_approach.py +244 -0
  48. ostk/astrodynamics/test/data/provider/test_off_nadir.py +58 -0
  49. ostk/astrodynamics/test/dynamics/__init__.py +1 -0
  50. ostk/astrodynamics/test/dynamics/data/Tabulated_Earth_Gravity.csv +565 -0
  51. ostk/astrodynamics/test/dynamics/data/Tabulated_Earth_Gravity_Truth.csv +100 -0
  52. ostk/astrodynamics/test/dynamics/test_atmospheric_drag.py +128 -0
  53. ostk/astrodynamics/test/dynamics/test_central_body_gravity.py +58 -0
  54. ostk/astrodynamics/test/dynamics/test_dynamics.py +50 -0
  55. ostk/astrodynamics/test/dynamics/test_position_derivative.py +51 -0
  56. ostk/astrodynamics/test/dynamics/test_tabulated.py +138 -0
  57. ostk/astrodynamics/test/dynamics/test_third_body_gravity.py +67 -0
  58. ostk/astrodynamics/test/dynamics/test_thruster.py +157 -0
  59. ostk/astrodynamics/test/eclipse/__init__.py +1 -0
  60. ostk/astrodynamics/test/eclipse/test_generator.py +138 -0
  61. ostk/astrodynamics/test/estimator/test_orbit_determination_solver.py +261 -0
  62. ostk/astrodynamics/test/estimator/test_tle_solver.py +216 -0
  63. ostk/astrodynamics/test/event_condition/test_angular_condition.py +113 -0
  64. ostk/astrodynamics/test/event_condition/test_boolean_condition.py +55 -0
  65. ostk/astrodynamics/test/event_condition/test_brouwer_lyddane_mean_long_condition.py +135 -0
  66. ostk/astrodynamics/test/event_condition/test_coe_condition.py +135 -0
  67. ostk/astrodynamics/test/event_condition/test_instant_condition.py +48 -0
  68. ostk/astrodynamics/test/event_condition/test_logical_condition.py +120 -0
  69. ostk/astrodynamics/test/event_condition/test_real_condition.py +50 -0
  70. ostk/astrodynamics/test/flight/__init__.py +1 -0
  71. ostk/astrodynamics/test/flight/profile/model/test_tabulated_profile.py +115 -0
  72. ostk/astrodynamics/test/flight/system/__init__.py +1 -0
  73. ostk/astrodynamics/test/flight/system/test_propulsion_system.py +64 -0
  74. ostk/astrodynamics/test/flight/system/test_satellite_system.py +83 -0
  75. ostk/astrodynamics/test/flight/system/test_satellite_system_builder.py +71 -0
  76. ostk/astrodynamics/test/flight/test_maneuver.py +231 -0
  77. ostk/astrodynamics/test/flight/test_profile.py +293 -0
  78. ostk/astrodynamics/test/flight/test_system.py +45 -0
  79. ostk/astrodynamics/test/guidance_law/test_constant_thrust.py +177 -0
  80. ostk/astrodynamics/test/guidance_law/test_guidance_law.py +60 -0
  81. ostk/astrodynamics/test/guidance_law/test_heterogeneous_guidance_law.py +164 -0
  82. ostk/astrodynamics/test/guidance_law/test_qlaw.py +209 -0
  83. ostk/astrodynamics/test/solvers/__init__.py +1 -0
  84. ostk/astrodynamics/test/solvers/test_finite_difference_solver.py +196 -0
  85. ostk/astrodynamics/test/solvers/test_least_squares_solver.py +334 -0
  86. ostk/astrodynamics/test/solvers/test_temporal_condition_solver.py +161 -0
  87. ostk/astrodynamics/test/test_access.py +128 -0
  88. ostk/astrodynamics/test/test_converters.py +290 -0
  89. ostk/astrodynamics/test/test_dataframe.py +1355 -0
  90. ostk/astrodynamics/test/test_display.py +184 -0
  91. ostk/astrodynamics/test/test_event_condition.py +80 -0
  92. ostk/astrodynamics/test/test_import.py +26 -0
  93. ostk/astrodynamics/test/test_root_solver.py +70 -0
  94. ostk/astrodynamics/test/test_trajectory.py +126 -0
  95. ostk/astrodynamics/test/test_utilities.py +338 -0
  96. ostk/astrodynamics/test/test_viewer.py +318 -0
  97. ostk/astrodynamics/test/trajectory/__init__.py +1 -0
  98. ostk/astrodynamics/test/trajectory/model/test_nadir_trajectory.py +87 -0
  99. ostk/astrodynamics/test/trajectory/model/test_tabulated_trajectory.py +303 -0
  100. ostk/astrodynamics/test/trajectory/model/test_target_scan_trajectory.py +126 -0
  101. ostk/astrodynamics/test/trajectory/orbit/__init__.py +1 -0
  102. ostk/astrodynamics/test/trajectory/orbit/message/__init__.py +1 -0
  103. ostk/astrodynamics/test/trajectory/orbit/message/spacex/__init__.py +1 -0
  104. ostk/astrodynamics/test/trajectory/orbit/message/spacex/conftest.py +18 -0
  105. ostk/astrodynamics/test/trajectory/orbit/message/spacex/data/opm_1.yaml +44 -0
  106. ostk/astrodynamics/test/trajectory/orbit/message/spacex/test_opm.py +108 -0
  107. ostk/astrodynamics/test/trajectory/orbit/models/__init__.py +1 -0
  108. ostk/astrodynamics/test/trajectory/orbit/models/kepler/__init__.py +1 -0
  109. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean.py +65 -0
  110. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean_long.py +102 -0
  111. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean_short.py +102 -0
  112. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_coe.py +305 -0
  113. ostk/astrodynamics/test/trajectory/orbit/models/sgp4/__init__.py +1 -0
  114. ostk/astrodynamics/test/trajectory/orbit/models/sgp4/test_tle.py +337 -0
  115. ostk/astrodynamics/test/trajectory/orbit/models/test_kepler.py +130 -0
  116. ostk/astrodynamics/test/trajectory/orbit/models/test_modified_equinoctial.py +142 -0
  117. ostk/astrodynamics/test/trajectory/orbit/models/test_propagated.py +234 -0
  118. ostk/astrodynamics/test/trajectory/orbit/models/test_sgp4.py +1 -0
  119. ostk/astrodynamics/test/trajectory/orbit/models/test_tabulated.py +380 -0
  120. ostk/astrodynamics/test/trajectory/orbit/test_model.py +1 -0
  121. ostk/astrodynamics/test/trajectory/orbit/test_pass.py +75 -0
  122. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_angular_velocity.py +30 -0
  123. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_attitude_quaternion.py +18 -0
  124. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_acceleration.py +136 -0
  125. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_position.py +107 -0
  126. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_velocity.py +115 -0
  127. ostk/astrodynamics/test/trajectory/state/test_coordinate_broker.py +84 -0
  128. ostk/astrodynamics/test/trajectory/state/test_coordinate_subset.py +58 -0
  129. ostk/astrodynamics/test/trajectory/state/test_numerical_solver.py +316 -0
  130. ostk/astrodynamics/test/trajectory/test_local_orbital_frame_direction.py +81 -0
  131. ostk/astrodynamics/test/trajectory/test_local_orbital_frame_factory.py +119 -0
  132. ostk/astrodynamics/test/trajectory/test_model.py +1 -0
  133. ostk/astrodynamics/test/trajectory/test_orbit.py +212 -0
  134. ostk/astrodynamics/test/trajectory/test_propagator.py +452 -0
  135. ostk/astrodynamics/test/trajectory/test_segment.py +694 -0
  136. ostk/astrodynamics/test/trajectory/test_sequence.py +550 -0
  137. ostk/astrodynamics/test/trajectory/test_state.py +629 -0
  138. ostk/astrodynamics/test/trajectory/test_state_builder.py +172 -0
  139. ostk/astrodynamics/trajectory/__init__.pyi +1982 -0
  140. ostk/astrodynamics/trajectory/model.pyi +259 -0
  141. ostk/astrodynamics/trajectory/orbit/__init__.pyi +349 -0
  142. ostk/astrodynamics/trajectory/orbit/message/__init__.pyi +3 -0
  143. ostk/astrodynamics/trajectory/orbit/message/spacex.pyi +264 -0
  144. ostk/astrodynamics/trajectory/orbit/model/__init__.pyi +648 -0
  145. ostk/astrodynamics/trajectory/orbit/model/brouwerLyddaneMean.pyi +121 -0
  146. ostk/astrodynamics/trajectory/orbit/model/kepler.pyi +709 -0
  147. ostk/astrodynamics/trajectory/orbit/model/sgp4.pyi +330 -0
  148. ostk/astrodynamics/trajectory/state/__init__.pyi +402 -0
  149. ostk/astrodynamics/trajectory/state/coordinate_subset.pyi +208 -0
  150. ostk/astrodynamics/utilities.py +396 -0
  151. ostk/astrodynamics/viewer.py +851 -0
@@ -0,0 +1,234 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ import numpy as np
6
+
7
+ from ostk.physics.time import Instant
8
+ from ostk.physics.time import DateTime
9
+ from ostk.physics.time import Scale
10
+ from ostk.physics.coordinate import Position
11
+ from ostk.physics.coordinate import Velocity
12
+ from ostk.physics.coordinate import Frame
13
+ from ostk.physics.environment.object.celestial import Earth
14
+
15
+ from ostk.astrodynamics.trajectory.state import NumericalSolver
16
+ from ostk.astrodynamics.trajectory import State
17
+ from ostk.astrodynamics.trajectory import Orbit
18
+ from ostk.astrodynamics.trajectory import Propagator
19
+ from ostk.astrodynamics import Dynamics
20
+ from ostk.astrodynamics.dynamics import CentralBodyGravity
21
+ from ostk.astrodynamics.dynamics import PositionDerivative
22
+ from ostk.astrodynamics.trajectory.orbit.model import Propagated
23
+
24
+
25
+ @pytest.fixture
26
+ def state() -> State:
27
+ frame: Frame = Frame.GCRF()
28
+ position: Position = Position.meters([7500000.0, 0.0, 0.0], frame)
29
+ velocity: Velocity = Velocity.meters_per_second(
30
+ [0.0, 5335.865450622126, 5335.865450622126], frame
31
+ )
32
+
33
+ instant: Instant = Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC)
34
+ return State(instant, position, velocity)
35
+
36
+
37
+ @pytest.fixture
38
+ def central_body_dynamics() -> CentralBodyGravity:
39
+ return CentralBodyGravity(Earth.WGS84(20, 0))
40
+
41
+
42
+ @pytest.fixture
43
+ def position_derivative() -> PositionDerivative:
44
+ return PositionDerivative()
45
+
46
+
47
+ @pytest.fixture
48
+ def dynamics(
49
+ position_derivative: PositionDerivative, central_body_dynamics: CentralBodyGravity
50
+ ) -> list:
51
+ return [position_derivative, central_body_dynamics]
52
+
53
+
54
+ @pytest.fixture
55
+ def numerical_solver() -> NumericalSolver:
56
+ return NumericalSolver(
57
+ NumericalSolver.LogType.NoLog,
58
+ NumericalSolver.StepperType.RungeKuttaFehlberg78,
59
+ 5.0,
60
+ 1.0e-15,
61
+ 1.0e-15,
62
+ )
63
+
64
+
65
+ @pytest.fixture
66
+ def propagator(numerical_solver: NumericalSolver, dynamics: list[Dynamics]) -> Propagator:
67
+ return Propagator(numerical_solver, dynamics)
68
+
69
+
70
+ @pytest.fixture
71
+ def revolution_number() -> int:
72
+ return 5
73
+
74
+
75
+ @pytest.fixture
76
+ def propagated(
77
+ propagator: Propagator, state: State, revolution_number: int
78
+ ) -> Propagated:
79
+ return Propagated(propagator, state, revolution_number)
80
+
81
+
82
+ @pytest.fixture
83
+ def earth() -> Earth:
84
+ return Earth.spherical()
85
+
86
+
87
+ @pytest.fixture
88
+ def orbit(propagated: Propagated, earth: Earth) -> Orbit:
89
+ return Orbit(propagated, earth)
90
+
91
+
92
+ class TestPropagated:
93
+ def test_constructors(
94
+ self,
95
+ propagated: Propagated,
96
+ earth: Earth,
97
+ dynamics: list,
98
+ numerical_solver: NumericalSolver,
99
+ state: State,
100
+ ):
101
+ assert propagated is not None
102
+ assert isinstance(propagated, Propagated)
103
+ assert propagated.is_defined()
104
+
105
+ orbit = Orbit(propagated, earth)
106
+
107
+ assert orbit is not None
108
+ assert isinstance(orbit, Orbit)
109
+ assert orbit.is_defined()
110
+
111
+ state_array = [state, state]
112
+ propagated_with_state_array = Propagated(
113
+ Propagator(numerical_solver, dynamics), state_array
114
+ )
115
+
116
+ assert propagated_with_state_array is not None
117
+ assert isinstance(propagated_with_state_array, Propagated)
118
+ assert propagated_with_state_array.is_defined()
119
+
120
+ def test_comparators(
121
+ self,
122
+ propagated: Propagated,
123
+ ):
124
+ assert (propagated == propagated) is True
125
+ assert (propagated != propagated) is False
126
+
127
+ def test_getters(
128
+ self,
129
+ propagated: Propagated,
130
+ state: State,
131
+ revolution_number: int,
132
+ ):
133
+ assert propagated.get_epoch() == state.get_instant()
134
+
135
+ assert propagated.get_revolution_number_at_epoch() == revolution_number
136
+
137
+ assert propagated.access_cached_state_array() == [state]
138
+
139
+ def test_calculate_state_at(
140
+ self,
141
+ propagated: Propagated,
142
+ orbit: Orbit,
143
+ ):
144
+ instant: Instant = Instant.date_time(DateTime(2018, 1, 1, 0, 10, 0), Scale.UTC)
145
+
146
+ propagated_state = propagated.calculate_state_at(instant)
147
+ propagated_state_orbit = orbit.get_state_at(instant)
148
+
149
+ assert propagated_state == propagated_state_orbit
150
+
151
+ propagated_state_position_ref = np.array(
152
+ [6265892.25765909, 3024770.94961259, 3024359.72137468]
153
+ )
154
+ propagated_state_velocity_ref = np.array(
155
+ [-3974.49168221, 4468.16996776, 4466.19232746]
156
+ )
157
+
158
+ propagated_state_position = propagated_state.get_position().get_coordinates()
159
+ propagated_state_velocity = propagated_state.get_velocity().get_coordinates()
160
+
161
+ assert all(
162
+ [
163
+ round(propagated_state_position[i], 8)
164
+ == round(propagated_state_position_ref[i], 8)
165
+ for i in range(0, len(propagated_state_position_ref))
166
+ ]
167
+ )
168
+ assert all(
169
+ [
170
+ round(propagated_state_velocity[i], 8)
171
+ == round(propagated_state_velocity_ref[i], 8)
172
+ for i in range(0, len(propagated_state_velocity_ref))
173
+ ]
174
+ )
175
+ assert propagated_state.get_instant() == instant
176
+
177
+ def test_calculate_states_at(
178
+ self,
179
+ propagated: Propagated,
180
+ orbit: Orbit,
181
+ ):
182
+ instant_array = [
183
+ Instant.date_time(DateTime(2018, 1, 1, 0, 10, 0), Scale.UTC),
184
+ Instant.date_time(DateTime(2018, 1, 1, 0, 20, 0), Scale.UTC),
185
+ ]
186
+
187
+ propagated_state_array = propagated.calculate_states_at(instant_array)
188
+ propagated_state_array_orbit = orbit.get_states_at(instant_array)
189
+
190
+ assert propagated_state_array_orbit == propagated_state_array
191
+
192
+ assert propagated_state_array_orbit[0].get_instant() == instant_array[0]
193
+ assert propagated_state_array_orbit[1].get_instant() == instant_array[1]
194
+
195
+ def test_calculate_revolution_number_at(
196
+ self,
197
+ propagated: Propagated,
198
+ orbit: Orbit,
199
+ revolution_number: int,
200
+ ):
201
+ instant: Instant = Instant.date_time(DateTime(2018, 1, 1, 0, 40, 0), Scale.UTC)
202
+
203
+ assert propagated.calculate_revolution_number_at(instant) == revolution_number + 1
204
+ assert orbit.get_revolution_number_at(instant) == revolution_number + 1
205
+
206
+ def test_access_cached_state_array(
207
+ self,
208
+ propagated: Propagated,
209
+ state: State,
210
+ ):
211
+ assert len(propagated.access_cached_state_array()) == 1
212
+ assert propagated.access_cached_state_array()[0] == state
213
+
214
+ def test_access_propagator(
215
+ self,
216
+ propagated: Propagated,
217
+ ):
218
+ assert propagated.access_propagator() is not None
219
+ assert isinstance(propagated.access_propagator(), Propagator)
220
+
221
+ def test_set_cached_state_array(
222
+ self,
223
+ propagated: Propagated,
224
+ state: State,
225
+ ):
226
+ assert len(propagated.access_cached_state_array()) == 1
227
+
228
+ propagated.set_cached_state_array([state, state, state])
229
+
230
+ assert len(propagated.access_cached_state_array()) == 1
231
+ assert propagated.access_cached_state_array()[0] == state
232
+
233
+ with pytest.raises(Exception) as e:
234
+ propagated.set_cached_state_array([])
@@ -0,0 +1 @@
1
+ # Apache License 2.0
@@ -0,0 +1,380 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ import numpy as np
6
+
7
+ from ostk.mathematics.curve_fitting import Interpolator
8
+
9
+ from ostk.physics.time import Instant
10
+ from ostk.physics.time import DateTime
11
+ from ostk.physics.time import Scale
12
+ from ostk.physics.time import Duration
13
+ from ostk.physics.coordinate import Position
14
+ from ostk.physics.coordinate import Velocity
15
+ from ostk.physics.coordinate import Frame
16
+ from ostk.physics import Environment
17
+
18
+ from ostk.astrodynamics.trajectory import State
19
+ from ostk.astrodynamics.trajectory import Orbit
20
+ from ostk.astrodynamics.trajectory.orbit.model import Tabulated
21
+
22
+
23
+ @pytest.fixture
24
+ def earth():
25
+ return Environment.default().access_celestial_object_with_name("Earth")
26
+
27
+
28
+ @pytest.fixture
29
+ def reference_states() -> list[State]:
30
+ data = [
31
+ [
32
+ "2023-04-18T08:28:32.744064",
33
+ -3310024.847608758,
34
+ -6052528.239971979,
35
+ 7626.534641683145,
36
+ -855.2088930507367,
37
+ 495.9541573743367,
38
+ 7536.520188134902,
39
+ ],
40
+ [
41
+ "2023-04-18T08:28:33.744064",
42
+ -3310878.047628086,
43
+ -6052028.610429457,
44
+ 15163.0493833017,
45
+ -851.1838953959017,
46
+ 503.31279367207185,
47
+ 7536.506322816037,
48
+ ],
49
+ [
50
+ "2023-04-18T08:28:34.744064",
51
+ -3311727.222133691,
52
+ -6051521.622540367,
53
+ 22699.545682944226,
54
+ -847.1578341126227,
55
+ 510.67087060642456,
56
+ 7536.483268627912,
57
+ ],
58
+ [
59
+ "2023-04-18T08:28:35.744064",
60
+ -3312572.370064364,
61
+ -6051007.276868478,
62
+ 30236.014351773065,
63
+ -843.1307141262514,
64
+ 518.0283791399937,
65
+ 7536.451025467619,
66
+ ],
67
+ [
68
+ "2023-04-18T08:28:36.744064",
69
+ -3313413.490363804,
70
+ -6050485.573986613,
71
+ 37772.44620082258,
72
+ -839.1025403636198,
73
+ 525.3853102358,
74
+ 7536.40959324377,
75
+ ],
76
+ [
77
+ "2023-04-18T08:28:37.744064",
78
+ -3314250.5819806806,
79
+ -6049956.514476612,
80
+ 45308.83204108345,
81
+ -835.0733177529921,
82
+ 532.7416548573802,
83
+ 7536.358971876497,
84
+ ],
85
+ [
86
+ "2023-04-18T08:28:38.744064",
87
+ -3315083.6438685474,
88
+ -6049420.098929363,
89
+ 52845.16268340493,
90
+ -831.0430512241197,
91
+ 540.0974039686765,
92
+ 7536.299161297429,
93
+ ],
94
+ [
95
+ "2023-04-18T08:28:39.744064",
96
+ -3315912.6749859042,
97
+ -6048876.327944793,
98
+ 60381.42893867038,
99
+ -827.0117457081434,
100
+ 547.4525485342174,
101
+ 7536.23016144972,
102
+ ],
103
+ [
104
+ "2023-04-18T08:28:40.744064",
105
+ -3316737.6742961914,
106
+ -6048325.2021318525,
107
+ 67917.62161760827,
108
+ -822.9794061376964,
109
+ 554.8070795189376,
110
+ 7536.1519722880375,
111
+ ],
112
+ [
113
+ "2023-04-18T08:28:41.744064",
114
+ -3317558.640767768,
115
+ -6047766.722108539,
116
+ 75453.73153099201,
117
+ -818.9460374467976,
118
+ 562.1609878883643,
119
+ 7536.064593778564,
120
+ ],
121
+ [
122
+ "2023-04-18T08:28:42.744064",
123
+ -3318375.5733739412,
124
+ -6047200.888501875,
125
+ 82989.7494894997,
126
+ -814.9116445709234,
127
+ 569.5142646084902,
128
+ 7535.968025898996,
129
+ ],
130
+ [
131
+ "2023-04-18T08:28:43.744064",
132
+ -3319188.471092942,
133
+ -6046627.7019479135,
134
+ 90525.66630384693,
135
+ -810.8762324469382,
136
+ 576.866900645898,
137
+ 7535.862268638544,
138
+ ],
139
+ [
140
+ "2023-04-18T08:28:44.744064",
141
+ -3319997.332907958,
142
+ -6046047.163091751,
143
+ 98061.47278470133,
144
+ -806.8398060131411,
145
+ 584.2188869676824,
146
+ 7535.747321997941,
147
+ ],
148
+ [
149
+ "2023-04-18T08:28:45.744064",
150
+ -3320802.157807084,
151
+ -6045459.272587514,
152
+ 105597.15974279115,
153
+ -802.8023702092072,
154
+ 591.5702145415504,
155
+ 7535.62318598943,
156
+ ],
157
+ [
158
+ "2023-04-18T08:28:46.744064",
159
+ -3321602.9447833803,
160
+ -6044864.0310983565,
161
+ 113132.71798877101,
162
+ -798.7639299762548,
163
+ 598.9208743356983,
164
+ 7535.48986063679,
165
+ ],
166
+ [
167
+ "2023-04-18T08:28:47.744064",
168
+ -3322399.692834845,
169
+ -6044261.439296465,
170
+ 120668.13833342775,
171
+ -794.7244902567405,
172
+ 606.2708573190106,
173
+ 7535.347345975296,
174
+ ],
175
+ [
176
+ "2023-04-18T08:28:48.744064",
177
+ -3323192.400964402,
178
+ -6043651.497863061,
179
+ 128203.41158748553,
180
+ -790.6840559945587,
181
+ 613.6201544608678,
182
+ 7535.195642051765,
183
+ ],
184
+ [
185
+ "2023-04-18T08:28:49.744064",
186
+ -3323981.068179951,
187
+ -6043034.207488383,
188
+ 135738.52856182377,
189
+ -786.6426321349277,
190
+ 620.9687567313651,
191
+ 7535.034748924513,
192
+ ],
193
+ [
194
+ "2023-04-18T08:28:50.744064",
195
+ -3324765.6934943097,
196
+ -6042409.568871722,
197
+ 143273.48006733102,
198
+ -782.6002236244674,
199
+ 628.3166551011666,
200
+ 7534.864666663388,
201
+ ],
202
+ [
203
+ "2023-04-18T08:28:51.744064",
204
+ -3325546.2759252544,
205
+ -6041777.582721372,
206
+ 150808.25691495842,
207
+ -778.5568354111685,
208
+ 635.6638405415614,
209
+ 7534.68539534976,
210
+ ],
211
+ ]
212
+ return [
213
+ State(
214
+ instant=Instant.date_time(DateTime.parse(row[0]), Scale.UTC),
215
+ position=Position.meters(
216
+ [float(row[1]), float(row[2]), float(row[3])], Frame.GCRF()
217
+ ),
218
+ velocity=Velocity.meters_per_second(
219
+ [float(row[4]), float(row[5]), float(row[6])], Frame.GCRF()
220
+ ),
221
+ )
222
+ for row in data
223
+ ]
224
+
225
+
226
+ @pytest.fixture
227
+ def test_states(reference_states: list[State]) -> list[State]:
228
+ return reference_states[::4]
229
+
230
+
231
+ class TestTabulated:
232
+ @pytest.mark.parametrize(
233
+ "interpolation_type",
234
+ (
235
+ (Interpolator.Type.Linear),
236
+ (Interpolator.Type.CubicSpline),
237
+ (Interpolator.Type.BarycentricRational),
238
+ ),
239
+ )
240
+ def test_constructor(
241
+ self, test_states: list[State], interpolation_type: Interpolator.Type
242
+ ):
243
+ assert (
244
+ Tabulated(
245
+ states=test_states,
246
+ initial_revolution_number=1,
247
+ interpolation_type=interpolation_type,
248
+ )
249
+ is not None
250
+ )
251
+
252
+ def test_constructor_orbit_tabulated_sucess(
253
+ self,
254
+ test_states: list[State],
255
+ earth,
256
+ ):
257
+ tabulated = Tabulated(
258
+ states=test_states,
259
+ initial_revolution_number=1,
260
+ interpolation_type=Interpolator.Type.CubicSpline,
261
+ )
262
+
263
+ orbit: Orbit = Orbit(tabulated, earth)
264
+
265
+ assert orbit is not None
266
+ assert isinstance(orbit, Orbit)
267
+
268
+ def test_get_interpolation_type(self, test_states: list[State]):
269
+ tabulated = Tabulated(
270
+ states=test_states,
271
+ initial_revolution_number=1,
272
+ interpolation_type=Interpolator.Type.CubicSpline,
273
+ )
274
+
275
+ assert tabulated.get_interpolation_type() == Interpolator.Type.CubicSpline
276
+
277
+ @pytest.mark.parametrize(
278
+ "interpolation_type,error_tolerance",
279
+ (
280
+ (Interpolator.Type.Linear, 420.0),
281
+ (Interpolator.Type.CubicSpline, 5e-3),
282
+ (Interpolator.Type.BarycentricRational, 5e-2),
283
+ ),
284
+ )
285
+ def test_calculate_state_at_success(
286
+ self,
287
+ test_states: list[State],
288
+ reference_states: list[State],
289
+ interpolation_type: Interpolator.Type,
290
+ error_tolerance: float,
291
+ ):
292
+ tabulated = Tabulated(
293
+ states=test_states,
294
+ initial_revolution_number=1,
295
+ interpolation_type=interpolation_type,
296
+ )
297
+
298
+ for reference_state in reference_states:
299
+ if not tabulated.get_interval().contains_instant(
300
+ reference_state.get_instant()
301
+ ):
302
+ continue
303
+
304
+ calculated_state: State = tabulated.calculate_state_at(
305
+ reference_state.get_instant()
306
+ )
307
+ assert np.all(
308
+ np.abs(
309
+ calculated_state.get_coordinates() - reference_state.get_coordinates()
310
+ )
311
+ < error_tolerance
312
+ )
313
+
314
+ @pytest.mark.parametrize(
315
+ "interpolation_type,error_tolerance",
316
+ (
317
+ (Interpolator.Type.Linear, 420.0),
318
+ (Interpolator.Type.CubicSpline, 5e-3),
319
+ (Interpolator.Type.BarycentricRational, 5e-2),
320
+ ),
321
+ )
322
+ def test_calculate_states_at_success(
323
+ self,
324
+ test_states: list[State],
325
+ reference_states: list[State],
326
+ interpolation_type: Interpolator.Type,
327
+ error_tolerance: float,
328
+ ):
329
+ tabulated = Tabulated(
330
+ states=test_states,
331
+ initial_revolution_number=1,
332
+ interpolation_type=interpolation_type,
333
+ )
334
+
335
+ states_within_interval: list[State] = [
336
+ state
337
+ for state in reference_states
338
+ if tabulated.get_interval().contains_instant(state.get_instant())
339
+ ]
340
+
341
+ calculated_states: list[State] = tabulated.calculate_states_at(
342
+ [state.get_instant() for state in states_within_interval]
343
+ )
344
+
345
+ for calculated_state, reference_state in zip(
346
+ calculated_states, states_within_interval
347
+ ):
348
+ assert np.all(
349
+ np.abs(
350
+ calculated_state.get_coordinates() - reference_state.get_coordinates()
351
+ )
352
+ < error_tolerance
353
+ )
354
+
355
+ @pytest.mark.parametrize(
356
+ "interpolation_type",
357
+ (
358
+ (Interpolator.Type.Linear),
359
+ (Interpolator.Type.CubicSpline),
360
+ (Interpolator.Type.BarycentricRational),
361
+ ),
362
+ )
363
+ def test_calculate_state_at_failure(
364
+ self, test_states: list[State], interpolation_type: Interpolator.Type
365
+ ):
366
+ tabulated = Tabulated(
367
+ states=test_states,
368
+ initial_revolution_number=1,
369
+ interpolation_type=interpolation_type,
370
+ )
371
+
372
+ with pytest.raises(Exception):
373
+ tabulated.calculate_state_at(
374
+ test_states[0].get_instant() - Duration.seconds(1)
375
+ )
376
+
377
+ with pytest.raises(Exception):
378
+ tabulated.calculate_state_at(
379
+ test_states[-1].get_instant() + Duration.seconds(1)
380
+ )
@@ -0,0 +1 @@
1
+ # Apache License 2.0
@@ -0,0 +1,75 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ from ostk.physics.time import Scale
6
+ from ostk.physics.time import Instant
7
+ from ostk.physics.time import Interval
8
+ from ostk.physics.time import DateTime
9
+ from ostk.physics import Environment
10
+
11
+ from ostk.astrodynamics.trajectory.orbit import Pass
12
+
13
+ earth = Environment.default().access_celestial_object_with_name("Earth")
14
+
15
+
16
+ @pytest.fixture
17
+ def pass_() -> Pass:
18
+ return Pass(
19
+ 123,
20
+ Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC),
21
+ Instant.date_time(DateTime(2018, 1, 1, 0, 15, 0), Scale.UTC),
22
+ Instant.date_time(DateTime(2018, 1, 1, 0, 30, 0), Scale.UTC),
23
+ Instant.date_time(DateTime(2018, 1, 1, 0, 45, 0), Scale.UTC),
24
+ Instant.date_time(DateTime(2018, 1, 1, 1, 0, 0), Scale.UTC),
25
+ )
26
+
27
+
28
+ class TestPass:
29
+ def test_is_defined(self, pass_: Pass):
30
+ assert pass_.is_defined()
31
+
32
+ def test_is_complete(self, pass_: Pass):
33
+ assert pass_.is_complete() is not None
34
+
35
+ def test_get_type(self, pass_: Pass):
36
+ assert pass_.get_type() is not None
37
+
38
+ def test_get_revolution_number(self, pass_: Pass):
39
+ assert pass_.get_revolution_number() is not None
40
+
41
+ def test_get_duration(self, pass_: Pass):
42
+ assert pass_.get_duration() is not None
43
+
44
+ def test_get_start_instant(self, pass_: Pass):
45
+ assert pass_.get_start_instant() is not None
46
+
47
+ def test_get_end_instant(self, pass_: Pass):
48
+ assert pass_.get_end_instant() is not None
49
+
50
+ def test_get_interval(self, pass_: Pass):
51
+ assert pass_.get_interval() is not None
52
+
53
+ def test_get_instant_at_ascending_node(self, pass_: Pass):
54
+ assert pass_.get_instant_at_ascending_node() is not None
55
+
56
+ def test_get_instant_at_north_point(self, pass_: Pass):
57
+ assert pass_.get_instant_at_north_point() is not None
58
+
59
+ def test_get_instant_at_descending_node(self, pass_: Pass):
60
+ assert pass_.get_instant_at_descending_node() is not None
61
+
62
+ def test_get_instant_at_south_point(self, pass_: Pass):
63
+ assert pass_.get_instant_at_south_point() is not None
64
+
65
+ def test_get_instant_at_pass_break(self, pass_: Pass):
66
+ assert pass_.get_instant_at_pass_break() is not None
67
+
68
+ def test_undefined(self):
69
+ assert Pass.undefined().is_defined() is False
70
+
71
+ def test_string_from_type(self):
72
+ assert Pass.string_from_type(Pass.Type.Complete) is not None
73
+
74
+ def test_string_from_phase(self):
75
+ assert Pass.string_from_phase(Pass.Phase.Ascending) is not None