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,550 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ import numpy as np
6
+
7
+ from ostk.mathematics.geometry.d3.object import Composite
8
+ from ostk.mathematics.geometry.d3.object import Cuboid
9
+ from ostk.mathematics.geometry.d3.object import Point
10
+
11
+ from ostk.physics import Environment
12
+ from ostk.physics.coordinate import Frame
13
+ from ostk.physics.environment.atmospheric import Earth as EarthAtmosphericModel
14
+ from ostk.physics.environment.gravitational import Earth as EarthGravitationalModel
15
+ from ostk.physics.environment.magnetic import Earth as EarthMagneticModel
16
+ from ostk.physics.environment.object.celestial import Earth
17
+ from ostk.physics.time import DateTime
18
+ from ostk.physics.time import Duration
19
+ from ostk.physics.time import Instant
20
+ from ostk.physics.time import Scale
21
+ from ostk.physics.unit import Derived
22
+ from ostk.physics.unit import Length
23
+ from ostk.physics.unit import Mass
24
+
25
+ from ostk.astrodynamics.event_condition import COECondition
26
+ from ostk.astrodynamics.event_condition import InstantCondition
27
+ from ostk.astrodynamics.event_condition import RealCondition
28
+ from ostk.astrodynamics import Dynamics
29
+ from ostk.astrodynamics import EventCondition
30
+ from ostk.astrodynamics.dynamics import Thruster
31
+ from ostk.astrodynamics.guidance_law import ConstantThrust
32
+ from ostk.astrodynamics.flight.system import PropulsionSystem
33
+ from ostk.astrodynamics.flight.system import SatelliteSystem
34
+ from ostk.astrodynamics.trajectory import LocalOrbitalFrameDirection
35
+ from ostk.astrodynamics.trajectory import LocalOrbitalFrameFactory
36
+ from ostk.astrodynamics.trajectory import Segment
37
+ from ostk.astrodynamics.trajectory import Sequence
38
+ from ostk.astrodynamics.trajectory import State
39
+ from ostk.astrodynamics.trajectory.state import CoordinateBroker
40
+ from ostk.astrodynamics.trajectory.state import CoordinateSubset
41
+ from ostk.astrodynamics.trajectory.state import NumericalSolver
42
+ from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianPosition
43
+ from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianVelocity
44
+
45
+
46
+ @pytest.fixture
47
+ def propulsion_system() -> PropulsionSystem:
48
+ return PropulsionSystem(
49
+ 1.0,
50
+ 1500.0,
51
+ )
52
+
53
+
54
+ @pytest.fixture
55
+ def dry_mass() -> Mass:
56
+ return Mass.kilograms(100.0)
57
+
58
+
59
+ @pytest.fixture
60
+ def wet_mass() -> Mass:
61
+ return Mass.kilograms(10.0)
62
+
63
+
64
+ @pytest.fixture
65
+ def cross_sectional_surface_area() -> float:
66
+ return 1.0
67
+
68
+
69
+ @pytest.fixture
70
+ def drag_coefficient() -> float:
71
+ return 2.2
72
+
73
+
74
+ @pytest.fixture
75
+ def satellite_system(
76
+ dry_mass: Mass,
77
+ cross_sectional_surface_area: float,
78
+ drag_coefficient: float,
79
+ propulsion_system: PropulsionSystem,
80
+ ) -> SatelliteSystem:
81
+ satellite_geometry = Composite(
82
+ Cuboid(
83
+ Point(0.0, 0.0, 0.0),
84
+ [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]],
85
+ [1.0, 0.0, 0.0],
86
+ )
87
+ )
88
+ inertia_tensor = np.ndarray(shape=(3, 3))
89
+
90
+ return SatelliteSystem(
91
+ dry_mass,
92
+ satellite_geometry,
93
+ inertia_tensor,
94
+ cross_sectional_surface_area,
95
+ drag_coefficient,
96
+ propulsion_system,
97
+ )
98
+
99
+
100
+ @pytest.fixture
101
+ def environment() -> Environment:
102
+ return Environment(
103
+ Instant.J2000(),
104
+ [
105
+ Earth.from_models(
106
+ EarthGravitationalModel(EarthGravitationalModel.Type.Spherical),
107
+ EarthMagneticModel(EarthMagneticModel.Type.Undefined),
108
+ EarthAtmosphericModel(EarthAtmosphericModel.Type.Exponential),
109
+ )
110
+ ],
111
+ )
112
+
113
+
114
+ @pytest.fixture
115
+ def coordinate_broker() -> CoordinateBroker:
116
+ return CoordinateBroker(
117
+ [
118
+ CartesianPosition.default(),
119
+ CartesianVelocity.default(),
120
+ CoordinateSubset.mass(),
121
+ CoordinateSubset.surface_area(),
122
+ CoordinateSubset.drag_coefficient(),
123
+ ]
124
+ )
125
+
126
+
127
+ @pytest.fixture
128
+ def cartesian_coordinates() -> list[float]:
129
+ return [
130
+ 717094.039086306,
131
+ -6872433.2241124,
132
+ 46175.9696673281,
133
+ -970.650826004612,
134
+ -45.4598114773158,
135
+ 7529.82424886455,
136
+ ]
137
+
138
+
139
+ @pytest.fixture
140
+ def state(
141
+ cartesian_coordinates: list[float],
142
+ dry_mass: Mass,
143
+ wet_mass: Mass,
144
+ cross_sectional_surface_area: float,
145
+ drag_coefficient: float,
146
+ coordinate_broker: CoordinateBroker,
147
+ ) -> State:
148
+ frame: Frame = Frame.GCRF()
149
+ instant: Instant = Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC)
150
+ coordinates = [
151
+ *cartesian_coordinates,
152
+ dry_mass.in_kilograms() + wet_mass.in_kilograms(),
153
+ cross_sectional_surface_area,
154
+ drag_coefficient,
155
+ ]
156
+
157
+ return State(
158
+ instant,
159
+ coordinates,
160
+ frame,
161
+ coordinate_broker,
162
+ )
163
+
164
+
165
+ @pytest.fixture
166
+ def state_2(
167
+ cartesian_coordinates: list[float],
168
+ dry_mass: Mass,
169
+ wet_mass: Mass,
170
+ cross_sectional_surface_area: float,
171
+ drag_coefficient: float,
172
+ coordinate_broker: CoordinateBroker,
173
+ ) -> State:
174
+ frame: Frame = Frame.GCRF()
175
+ instant: Instant = Instant.date_time(DateTime(2018, 1, 1, 0, 1, 0), Scale.UTC)
176
+ coordinates = [
177
+ *cartesian_coordinates,
178
+ dry_mass.in_kilograms() + wet_mass.in_kilograms(),
179
+ cross_sectional_surface_area,
180
+ drag_coefficient,
181
+ ]
182
+
183
+ return State(
184
+ instant,
185
+ coordinates,
186
+ frame,
187
+ coordinate_broker,
188
+ )
189
+
190
+
191
+ @pytest.fixture
192
+ def states(state: State, state_2: State) -> list[State]:
193
+ return [state, state_2]
194
+
195
+
196
+ @pytest.fixture
197
+ def dynamics(environment: Environment) -> list:
198
+ return Dynamics.from_environment(environment)
199
+
200
+
201
+ @pytest.fixture
202
+ def numerical_solver() -> NumericalSolver:
203
+ return NumericalSolver.default_conditional()
204
+
205
+
206
+ @pytest.fixture
207
+ def duration() -> Duration:
208
+ return Duration.minutes(5.0)
209
+
210
+
211
+ @pytest.fixture
212
+ def instant_condition(state: State, duration: Duration) -> InstantCondition:
213
+ return InstantCondition(
214
+ RealCondition.Criterion.AnyCrossing, state.get_instant() + duration
215
+ )
216
+
217
+
218
+ @pytest.fixture
219
+ def sma() -> Length:
220
+ return Length.kilometers(6907.000)
221
+
222
+
223
+ @pytest.fixture
224
+ def gravitational_parameter() -> Derived:
225
+ return EarthGravitationalModel.spherical.gravitational_parameter
226
+
227
+
228
+ @pytest.fixture
229
+ def constant_thrust() -> ConstantThrust:
230
+ return ConstantThrust(
231
+ thrust_direction=LocalOrbitalFrameDirection(
232
+ vector=[1.0, 0.0, 0.0],
233
+ local_orbital_frame_factory=LocalOrbitalFrameFactory.VNC(Frame.GCRF()),
234
+ )
235
+ )
236
+
237
+
238
+ @pytest.fixture
239
+ def thruster_dynamics(
240
+ satellite_system: SatelliteSystem, constant_thrust: ConstantThrust
241
+ ) -> ConstantThrust:
242
+ return Thruster(
243
+ satellite_system=satellite_system,
244
+ guidance_law=constant_thrust,
245
+ )
246
+
247
+
248
+ @pytest.fixture
249
+ def sma_target(sma: Length) -> EventCondition.Target:
250
+ return EventCondition.Target(sma)
251
+
252
+
253
+ @pytest.fixture
254
+ def sma_condition(
255
+ sma_target: EventCondition.Target, gravitational_parameter: Derived
256
+ ) -> COECondition:
257
+ return COECondition.semi_major_axis(
258
+ criterion=RealCondition.Criterion.AnyCrossing,
259
+ frame=Frame.GCRF(),
260
+ semi_major_axis=sma_target,
261
+ gravitational_parameter=gravitational_parameter,
262
+ )
263
+
264
+
265
+ @pytest.fixture
266
+ def coast_duration_segment(
267
+ instant_condition: InstantCondition,
268
+ dynamics: list[Dynamics],
269
+ numerical_solver: NumericalSolver,
270
+ ):
271
+ return Segment.coast(
272
+ name="duration coast",
273
+ event_condition=instant_condition,
274
+ dynamics=dynamics,
275
+ numerical_solver=numerical_solver,
276
+ )
277
+
278
+
279
+ @pytest.fixture
280
+ def coast_sma_segment(
281
+ sma_condition: COECondition,
282
+ dynamics: list[Dynamics],
283
+ numerical_solver: NumericalSolver,
284
+ ):
285
+ return Segment.coast(
286
+ name="sma coast",
287
+ event_condition=sma_condition,
288
+ dynamics=dynamics,
289
+ numerical_solver=numerical_solver,
290
+ )
291
+
292
+
293
+ @pytest.fixture
294
+ def thrust_segment(
295
+ sma_condition: RealCondition,
296
+ thruster_dynamics: Thruster,
297
+ dynamics: list[Dynamics],
298
+ numerical_solver: NumericalSolver,
299
+ ):
300
+ return Segment.maneuver(
301
+ name="duration thrust",
302
+ event_condition=sma_condition,
303
+ thruster_dynamics=thruster_dynamics,
304
+ dynamics=dynamics,
305
+ numerical_solver=numerical_solver,
306
+ )
307
+
308
+
309
+ @pytest.fixture
310
+ def segments(
311
+ coast_duration_segment: Segment,
312
+ thrust_segment: Segment,
313
+ ) -> list[Segment]:
314
+ return [coast_duration_segment, thrust_segment]
315
+
316
+
317
+ @pytest.fixture
318
+ def maximum_propagation_duration() -> Duration:
319
+ return Duration.days(2.0)
320
+
321
+
322
+ @pytest.fixture
323
+ def repetition_count() -> int:
324
+ return 1
325
+
326
+
327
+ @pytest.fixture
328
+ def dynamics_with_thruster(
329
+ dynamics: list[Dynamics], thruster_dynamics: Thruster
330
+ ) -> list[Dynamics]:
331
+ return dynamics + [thruster_dynamics]
332
+
333
+
334
+ @pytest.fixture
335
+ def sequence(
336
+ segments: list[Segment],
337
+ numerical_solver: NumericalSolver,
338
+ dynamics: list[Dynamics],
339
+ maximum_propagation_duration: Duration,
340
+ ):
341
+ sequence: Sequence = Sequence(
342
+ segments=segments,
343
+ dynamics=dynamics,
344
+ numerical_solver=numerical_solver,
345
+ maximum_propagation_duration=maximum_propagation_duration,
346
+ )
347
+
348
+ return sequence
349
+
350
+
351
+ @pytest.fixture
352
+ def segment_solution(
353
+ dynamics_with_thruster: list[Dynamics],
354
+ states: list[State],
355
+ ):
356
+ return Segment.Solution(
357
+ name="A Segment Solution",
358
+ dynamics=dynamics_with_thruster,
359
+ states=states,
360
+ condition_is_satisfied=True,
361
+ segment_type=Segment.Type.Maneuver,
362
+ )
363
+
364
+
365
+ @pytest.fixture
366
+ def instants(state: State) -> list[Instant]:
367
+ return [state.get_instant(), state.get_instant() + Duration.minutes(1.0)]
368
+
369
+
370
+ @pytest.fixture
371
+ def sequence_solution(
372
+ segment_solution: Segment.Solution,
373
+ ):
374
+ return Sequence.Solution(
375
+ segment_solutions=[
376
+ segment_solution,
377
+ ],
378
+ execution_is_complete=True,
379
+ )
380
+
381
+
382
+ class TestSequenceSolution:
383
+ def test_properties(
384
+ self,
385
+ sequence_solution: Sequence.Solution,
386
+ ):
387
+ assert sequence_solution is not None
388
+ assert len(sequence_solution.segment_solutions) == 1
389
+ assert sequence_solution.execution_is_complete
390
+
391
+ def test_getters_and_accessors(
392
+ self,
393
+ sequence_solution: Sequence.Solution,
394
+ ):
395
+ assert sequence_solution.access_start_instant() is not None
396
+ assert sequence_solution.access_end_instant() is not None
397
+
398
+ assert sequence_solution.get_states() is not None
399
+ assert sequence_solution.get_initial_mass() is not None
400
+ assert sequence_solution.get_final_mass() is not None
401
+ assert sequence_solution.get_propagation_duration() is not None
402
+
403
+ assert sequence_solution.compute_delta_mass() is not None
404
+ assert sequence_solution.compute_delta_v(1500.0) is not None
405
+
406
+ def test_extract_maneuvers(
407
+ self,
408
+ sequence_solution: Sequence.Solution,
409
+ ):
410
+ assert sequence_solution.extract_maneuvers(Frame.GCRF()) is not None
411
+ assert len(sequence_solution.extract_maneuvers(Frame.GCRF())) == 1
412
+
413
+ def test_calculate_states_at(
414
+ self,
415
+ sequence_solution: Sequence.Solution,
416
+ numerical_solver: NumericalSolver,
417
+ ):
418
+ instants: list[Instant] = sequence_solution.get_interval().generate_grid(
419
+ Duration.seconds(10.0)
420
+ )
421
+ states: list[State] = sequence_solution.calculate_states_at(
422
+ instants,
423
+ numerical_solver,
424
+ )
425
+
426
+ assert states is not None
427
+ assert len(states) == len(instants)
428
+
429
+
430
+ class TestSequence:
431
+ def test_get_segments(
432
+ self,
433
+ sequence: Sequence,
434
+ segments: list[Segment],
435
+ ):
436
+ assert len(sequence.get_segments()) == len(segments)
437
+
438
+ def test_get_numerical_solver(
439
+ self,
440
+ sequence: Sequence,
441
+ numerical_solver: NumericalSolver,
442
+ ):
443
+ assert sequence.get_numerical_solver() == numerical_solver
444
+
445
+ def test_get_dynamics(
446
+ self,
447
+ sequence: Sequence,
448
+ dynamics: list,
449
+ ):
450
+ assert len(sequence.get_dynamics()) == len(dynamics)
451
+
452
+ def test_get_maximum_propagation_duration(
453
+ self,
454
+ sequence: Sequence,
455
+ maximum_propagation_duration: Duration,
456
+ ):
457
+ assert sequence.get_maximum_propagation_duration() == maximum_propagation_duration
458
+
459
+ def test_add_segment(
460
+ self,
461
+ sequence: Sequence,
462
+ coast_duration_segment: Segment,
463
+ ):
464
+ segments_count: int = len(sequence.get_segments())
465
+
466
+ sequence.add_segment(coast_duration_segment)
467
+
468
+ assert len(sequence.get_segments()) == segments_count + 1
469
+
470
+ segments_count = len(sequence.get_segments())
471
+
472
+ sequence.add_segments([coast_duration_segment, coast_duration_segment])
473
+
474
+ assert len(sequence.get_segments()) == segments_count + 2
475
+
476
+ def test_add_coast_segment(
477
+ self,
478
+ sequence: Sequence,
479
+ instant_condition: InstantCondition,
480
+ ):
481
+ segments_count: int = len(sequence.get_segments())
482
+
483
+ sequence.add_coast_segment(instant_condition)
484
+
485
+ assert len(sequence.get_segments()) == segments_count + 1
486
+
487
+ def test_add_maneuver_segment(
488
+ self,
489
+ sequence: Sequence,
490
+ instant_condition: InstantCondition,
491
+ thruster_dynamics: Thruster,
492
+ ):
493
+ segments_count: int = len(sequence.get_segments())
494
+
495
+ sequence.add_maneuver_segment(instant_condition, thruster_dynamics)
496
+
497
+ assert len(sequence.get_segments()) == segments_count + 1
498
+
499
+ def test_solve(
500
+ self,
501
+ state: State,
502
+ repetition_count: int,
503
+ sequence: Sequence,
504
+ segments: list[Segment],
505
+ instants: list[Instant],
506
+ numerical_solver: NumericalSolver,
507
+ ):
508
+ solution = sequence.solve(
509
+ state=state,
510
+ repetition_count=repetition_count,
511
+ )
512
+
513
+ assert len(solution.segment_solutions) == len(segments)
514
+
515
+ assert solution.execution_is_complete
516
+
517
+ assert solution.access_start_instant() is not None
518
+ assert solution.access_end_instant() is not None
519
+
520
+ assert solution.get_states() is not None
521
+ assert solution.get_initial_mass() is not None
522
+ assert solution.get_final_mass() is not None
523
+ assert solution.get_propagation_duration() is not None
524
+
525
+ assert solution.compute_delta_mass() is not None
526
+ assert solution.compute_delta_v(1500.0) is not None
527
+
528
+ propagated_states = solution.calculate_states_at(
529
+ instants,
530
+ numerical_solver,
531
+ )
532
+
533
+ assert propagated_states is not None
534
+ assert len(propagated_states) == len(instants)
535
+
536
+ def test_solve_to_condition(
537
+ self,
538
+ state: State,
539
+ sequence: Sequence,
540
+ instant_condition: InstantCondition,
541
+ ):
542
+ assert sequence.solve_to_condition(state, instant_condition) is not None
543
+ assert (
544
+ sequence.solve_to_condition(
545
+ state=state,
546
+ event_condition=instant_condition,
547
+ maximum_propagation_duration_limit=Duration.hours(1.0),
548
+ )
549
+ is not None
550
+ )