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,231 @@
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 Interval
9
+ from ostk.physics.time import Duration
10
+ from ostk.physics.coordinate import Frame
11
+ from ostk.physics.unit import Mass
12
+ from ostk.physics.unit import Angle
13
+
14
+ from ostk.astrodynamics.dynamics import Tabulated as TabulatedDynamics
15
+ from ostk.astrodynamics.flight import Maneuver
16
+ from ostk.astrodynamics.trajectory import LocalOrbitalFrameDirection
17
+ from ostk.astrodynamics.trajectory import LocalOrbitalFrameFactory
18
+ from ostk.astrodynamics.trajectory import State
19
+ from ostk.astrodynamics.trajectory.state import CoordinateSubset
20
+ from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianPosition
21
+ from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianVelocity
22
+ from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianAcceleration
23
+
24
+
25
+ @pytest.fixture
26
+ def instants() -> list[Instant]:
27
+ return [
28
+ Instant.J2000(),
29
+ Instant.J2000() + Duration.seconds(30.0),
30
+ Instant.J2000() + Duration.seconds(35.0),
31
+ Instant.J2000() + Duration.seconds(37.0),
32
+ ]
33
+
34
+
35
+ @pytest.fixture
36
+ def acceleration_profile() -> list[np.ndarray]:
37
+ return [
38
+ np.array([1.0e-3, 0.0e-3, 0.0e-3]),
39
+ np.array([0.0e-3, 1.0e-3, 0.0e-3]),
40
+ np.array([0.0e-3, 0.0e-3, 1.0e-3]),
41
+ np.array([1.0e-3, 1.0e-3, 1.0e-3]),
42
+ ]
43
+
44
+
45
+ @pytest.fixture
46
+ def frame() -> Frame:
47
+ return Frame.GCRF()
48
+
49
+
50
+ @pytest.fixture
51
+ def mass_flow_rate_profile() -> list[float]:
52
+ return [-1.0e-5, -1.1e-5, -0.9e-5, -1.0e-5]
53
+
54
+
55
+ @pytest.fixture
56
+ def coordinate_subsets() -> list[CoordinateSubset]:
57
+ return [
58
+ CartesianPosition.default(),
59
+ CartesianVelocity.default(),
60
+ CartesianAcceleration.thrust_acceleration(),
61
+ CoordinateSubset.mass_flow_rate(),
62
+ ]
63
+
64
+
65
+ @pytest.fixture
66
+ def states(
67
+ instants: list[Instant],
68
+ acceleration_profile: list[np.ndarray],
69
+ mass_flow_rate_profile: list[float],
70
+ frame: Frame,
71
+ coordinate_subsets: list[CoordinateSubset],
72
+ ) -> list[State]:
73
+ states = []
74
+ for instant, acceleration, mass_flow_rate in zip(
75
+ instants, acceleration_profile, mass_flow_rate_profile
76
+ ):
77
+ states.append(
78
+ State(
79
+ instant,
80
+ [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, *acceleration, mass_flow_rate],
81
+ frame,
82
+ coordinate_subsets,
83
+ )
84
+ )
85
+ return states
86
+
87
+
88
+ @pytest.fixture
89
+ def maneuver(
90
+ states: list[State],
91
+ ) -> Maneuver:
92
+ return Maneuver(states)
93
+
94
+
95
+ @pytest.fixture
96
+ def tabulated_dynamics(
97
+ tabulated_instants: list[Instant],
98
+ tabulated_contribution_profile: np.ndarray,
99
+ tabulated_coordinate_subsets: list[CoordinateSubset],
100
+ frame: Frame,
101
+ ) -> TabulatedDynamics:
102
+ return TabulatedDynamics(
103
+ tabulated_instants,
104
+ tabulated_contribution_profile,
105
+ tabulated_coordinate_subsets,
106
+ frame,
107
+ )
108
+
109
+
110
+ class TestManeuver:
111
+ def test_constructor(
112
+ self,
113
+ maneuver: Maneuver,
114
+ ):
115
+ assert maneuver is not None
116
+ assert isinstance(maneuver, Maneuver)
117
+ assert maneuver.is_defined()
118
+
119
+ def test_comparators(
120
+ self,
121
+ maneuver: Maneuver,
122
+ ):
123
+ assert (maneuver == maneuver) is True
124
+ assert (maneuver != maneuver) is False
125
+
126
+ def test_getters(
127
+ self,
128
+ maneuver: Maneuver,
129
+ states: list[State],
130
+ ):
131
+ assert maneuver.is_defined()
132
+
133
+ assert maneuver.get_states() == states
134
+
135
+ assert maneuver.get_interval() == Interval.closed(
136
+ states[0].get_instant(), states[-1].get_instant()
137
+ )
138
+
139
+ def test_calculators(
140
+ self,
141
+ maneuver: Maneuver,
142
+ ):
143
+ assert maneuver.calculate_delta_v() is not None
144
+ assert maneuver.calculate_delta_mass().in_kilograms() is not None
145
+ assert (
146
+ maneuver.calculate_average_thrust(
147
+ initial_spacecraft_mass=Mass(100.0, Mass.Unit.Kilogram)
148
+ )
149
+ is not None
150
+ )
151
+ assert (
152
+ maneuver.calculate_average_specific_impulse(
153
+ initial_spacecraft_mass=Mass(100.0, Mass.Unit.Kilogram)
154
+ )
155
+ is not None
156
+ )
157
+
158
+ def test_to_tabulated_dynamics(
159
+ self,
160
+ maneuver: Maneuver,
161
+ instants: list[Instant],
162
+ acceleration_profile: list[np.ndarray],
163
+ frame: Frame,
164
+ mass_flow_rate_profile: list[float],
165
+ ):
166
+ tabulated_dynamics: TabulatedDynamics = maneuver.to_tabulated_dynamics(
167
+ frame=frame
168
+ )
169
+
170
+ assert tabulated_dynamics.is_defined()
171
+ assert tabulated_dynamics.access_instants() == [
172
+ state.get_instant() for state in maneuver.get_states()
173
+ ]
174
+
175
+ contribution_profile: np.ndarray = (
176
+ tabulated_dynamics.access_contribution_profile()
177
+ )
178
+
179
+ for i in range(len(instants)):
180
+ assert contribution_profile[i][0:3] == pytest.approx(
181
+ acceleration_profile[i], rel=1e-15
182
+ )
183
+ assert contribution_profile[i][3] == pytest.approx(
184
+ mass_flow_rate_profile[i], rel=1e-15
185
+ )
186
+
187
+ assert tabulated_dynamics.access_frame() == frame
188
+
189
+ def test_calculate_mean_thrust_direction_and_maximum_angular_offset(
190
+ self,
191
+ maneuver: Maneuver,
192
+ ):
193
+ mean_thrust_direction_and_maximum_angular_offset = (
194
+ maneuver.calculate_mean_thrust_direction_and_maximum_angular_offset(
195
+ local_orbital_frame_factory=LocalOrbitalFrameFactory.TNW(Frame.GCRF()),
196
+ )
197
+ )
198
+ assert isinstance(
199
+ mean_thrust_direction_and_maximum_angular_offset[0],
200
+ LocalOrbitalFrameDirection,
201
+ )
202
+ assert isinstance(mean_thrust_direction_and_maximum_angular_offset[1], Angle)
203
+
204
+ def test_to_constant_local_orbital_frame_direction_maneuver(
205
+ self,
206
+ maneuver: Maneuver,
207
+ ):
208
+ maneuver: Maneuver = maneuver.to_constant_local_orbital_frame_direction_maneuver(
209
+ local_orbital_frame_factory=LocalOrbitalFrameFactory.TNW(Frame.GCRF()),
210
+ )
211
+ assert maneuver.is_defined()
212
+
213
+ maneuver_with_maximum_allowed_angular_offset: Maneuver = (
214
+ maneuver.to_constant_local_orbital_frame_direction_maneuver(
215
+ local_orbital_frame_factory=LocalOrbitalFrameFactory.TNW(Frame.GCRF()),
216
+ maximum_allowed_angular_offset=Angle.degrees(180.0),
217
+ )
218
+ )
219
+ assert maneuver_with_maximum_allowed_angular_offset.is_defined()
220
+
221
+ def test_from_constant_mass_flow_rate(
222
+ self,
223
+ states: list[State],
224
+ ):
225
+ mass_flow_rate: float = -1.0e-5
226
+ maneuver: Maneuver = Maneuver.constant_mass_flow_rate_profile(
227
+ states=states,
228
+ mass_flow_rate=mass_flow_rate,
229
+ )
230
+
231
+ assert maneuver.is_defined()
@@ -0,0 +1,293 @@
1
+ # Apache License 2.0
2
+
3
+ from datetime import datetime
4
+
5
+ import pytest
6
+
7
+ from ostk.mathematics.geometry.d3.transformation.rotation import Quaternion
8
+ from ostk.mathematics.curve_fitting import Interpolator
9
+
10
+ from ostk.physics import Environment
11
+ from ostk.physics.time import DateTime
12
+ from ostk.physics.time import Duration
13
+ from ostk.physics.time import Time
14
+ from ostk.physics.time import Scale
15
+ from ostk.physics.time import Instant
16
+ from ostk.physics.unit import Length
17
+ from ostk.physics.unit import Angle
18
+ from ostk.physics.coordinate import Transform
19
+ from ostk.physics.coordinate import Position
20
+ from ostk.physics.coordinate import Velocity
21
+ from ostk.physics.coordinate import Frame
22
+ from ostk.physics.coordinate import Axes
23
+ from ostk.physics.coordinate.frame.provider import Dynamic as DynamicProvider
24
+
25
+ from ostk.astrodynamics import Trajectory
26
+ from ostk.astrodynamics.trajectory import Orbit
27
+ from ostk.astrodynamics.trajectory import State
28
+ from ostk.astrodynamics.flight import Profile
29
+ from ostk.astrodynamics.flight.profile.model import Transform as TransformModel
30
+ from ostk.astrodynamics.flight.profile.model import Tabulated as TabulatedModel
31
+
32
+
33
+ @pytest.fixture
34
+ def instant() -> Instant:
35
+ return Instant.date_time(DateTime(2020, 1, 1, 0, 0, 30), Scale.UTC)
36
+
37
+
38
+ @pytest.fixture
39
+ def environment() -> Environment:
40
+ return Environment.default()
41
+
42
+
43
+ @pytest.fixture
44
+ def orbit(instant: Instant, environment: Environment) -> Orbit:
45
+ return Orbit.sun_synchronous(
46
+ epoch=instant,
47
+ altitude=Length.kilometers(500.0),
48
+ local_time_at_descending_node=Time(14, 0, 0),
49
+ celestial_object=environment.access_celestial_object_with_name("Earth"),
50
+ )
51
+
52
+
53
+ @pytest.fixture
54
+ def transform_model() -> TransformModel:
55
+ def dynamic_provider_generator(instant: Instant):
56
+ return Transform.identity(instant)
57
+
58
+ return TransformModel(
59
+ dynamic_provider=DynamicProvider(dynamic_provider_generator),
60
+ frame=Frame.GCRF(),
61
+ )
62
+
63
+
64
+ @pytest.fixture
65
+ def tabulated_model() -> TabulatedModel:
66
+ return TabulatedModel(
67
+ states=[
68
+ State(
69
+ instant=Instant.date_time(datetime(2020, 1, 1, 0, 0, 0), Scale.UTC),
70
+ position=Position.meters((0.0, 0.0, 0.0), Frame.GCRF()),
71
+ velocity=Velocity.meters_per_second((0.0, 0.0, 0.0), Frame.GCRF()),
72
+ attitude=Quaternion.unit(),
73
+ angular_velocity=(0.0, 0.0, 0.0),
74
+ attitude_frame=Frame.GCRF(),
75
+ ),
76
+ State(
77
+ instant=Instant.date_time(datetime(2020, 1, 1, 0, 1, 0), Scale.UTC),
78
+ position=Position.meters((0.0, 0.0, 0.0), Frame.GCRF()),
79
+ velocity=Velocity.meters_per_second((0.0, 0.0, 0.0), Frame.GCRF()),
80
+ attitude=Quaternion.unit(),
81
+ angular_velocity=(0.0, 0.0, 0.0),
82
+ attitude_frame=Frame.GCRF(),
83
+ ),
84
+ ],
85
+ interpolator_type=Interpolator.Type.Linear,
86
+ )
87
+
88
+
89
+ @pytest.fixture(
90
+ params=[
91
+ "transform_model",
92
+ "tabulated_model",
93
+ ]
94
+ )
95
+ def profile(request) -> Profile:
96
+ model: TransformModel | TabulatedModel = request.getfixturevalue(request.param)
97
+ return Profile(model=model)
98
+
99
+
100
+ # TODO: Add test for target_sliding_ground_velocity
101
+ @pytest.fixture(
102
+ params=[
103
+ # Axis-based constructors
104
+ Profile.Target(Profile.TargetType.GeocentricNadir, Profile.Axis.X),
105
+ Profile.TrajectoryTarget.target_position(
106
+ Trajectory.position(Position.meters((7000000.0, 0.0, 0.0), Frame.ITRF())),
107
+ Profile.Axis.X,
108
+ ),
109
+ Profile.TrajectoryTarget.target_velocity(
110
+ Trajectory.position(Position.meters((7000000.0, 0.0, 0.0), Frame.ITRF())),
111
+ Profile.Axis.X,
112
+ ),
113
+ Profile.OrientationProfileTarget(
114
+ [
115
+ (Instant.J2000(), [1.0, 0.0, 0.0]),
116
+ (Instant.J2000() + Duration.minutes(1.0), [1.0, 0.0, 0.0]),
117
+ (Instant.J2000() + Duration.minutes(2.0), [1.0, 0.0, 0.0]),
118
+ (Instant.J2000() + Duration.minutes(3.0), [1.0, 0.0, 0.0]),
119
+ ],
120
+ Profile.Axis.X,
121
+ False,
122
+ Interpolator.Type.Linear,
123
+ ),
124
+ Profile.CustomTarget(
125
+ lambda state: [1.0, 0.0, 0.0],
126
+ Profile.Axis.X,
127
+ ),
128
+ # Vector3d-based constructors
129
+ Profile.Target(Profile.TargetType.GeocentricNadir, [1.0, 0.0, 0.0]),
130
+ Profile.TrajectoryTarget.target_position(
131
+ Trajectory.position(Position.meters((7000000.0, 0.0, 0.0), Frame.ITRF())),
132
+ [1.0, 0.0, 0.0],
133
+ ),
134
+ Profile.TrajectoryTarget.target_velocity(
135
+ Trajectory.position(Position.meters((7000000.0, 0.0, 0.0), Frame.ITRF())),
136
+ [1.0, 0.0, 0.0],
137
+ ),
138
+ Profile.OrientationProfileTarget(
139
+ [
140
+ (Instant.J2000(), [1.0, 0.0, 0.0]),
141
+ (Instant.J2000() + Duration.minutes(1.0), [1.0, 0.0, 0.0]),
142
+ (Instant.J2000() + Duration.minutes(2.0), [1.0, 0.0, 0.0]),
143
+ (Instant.J2000() + Duration.minutes(3.0), [1.0, 0.0, 0.0]),
144
+ ],
145
+ [1.0, 0.0, 0.0],
146
+ Interpolator.Type.Linear,
147
+ ),
148
+ Profile.CustomTarget(
149
+ lambda state: [1.0, 0.0, 0.0],
150
+ [0.0, 0.0, 1.0],
151
+ ),
152
+ ]
153
+ )
154
+ def alignment_target(request) -> Profile.Target:
155
+ return request.param
156
+
157
+
158
+ @pytest.fixture
159
+ def clocking_target() -> Profile.Target:
160
+ return Profile.Target(Profile.TargetType.VelocityECI, Profile.Axis.Y)
161
+
162
+
163
+ class TestProfile:
164
+ def test_constructors(self, profile: Profile):
165
+ assert profile is not None
166
+ assert isinstance(profile, Profile)
167
+
168
+ def test_profile_target(self, alignment_target: Profile.Target):
169
+ assert alignment_target is not None
170
+ assert isinstance(alignment_target, Profile.Target)
171
+
172
+ def test_access_model(self, profile: Profile):
173
+ model = profile.access_model()
174
+
175
+ assert model is not None
176
+
177
+ if model.is_transform():
178
+ assert model.as_transform() is not None
179
+
180
+ if model.is_tabulated():
181
+ assert model.as_tabulated() is not None
182
+
183
+ def test_get_state_at(self, profile: Profile, instant: Instant):
184
+ state: State = profile.get_state_at(instant)
185
+
186
+ assert state is not None
187
+ assert isinstance(state, State)
188
+ state.is_defined()
189
+
190
+ def test_get_states_at(self, profile: Profile, instant: Instant):
191
+ states = profile.get_states_at([instant, instant])
192
+
193
+ assert states is not None
194
+
195
+ def test_get_axes_at(self, profile: Profile, instant: Instant):
196
+ axes = profile.get_axes_at(instant)
197
+
198
+ assert axes is not None
199
+ assert isinstance(axes, Axes)
200
+
201
+ def test_construct_body_frame(self, profile: Profile):
202
+ frame_name: str = "test_construct_body_frame"
203
+
204
+ if Frame.exists(frame_name):
205
+ Frame.destruct(frame_name)
206
+
207
+ frame: Frame = profile.construct_body_frame(frame_name)
208
+ assert frame is not None
209
+
210
+ frame_2: Frame = profile.construct_body_frame(frame_name, True)
211
+ assert frame_2 is not None
212
+
213
+ def test_undefined(self):
214
+ profile: Profile = Profile.undefined()
215
+
216
+ assert profile is not None
217
+ assert isinstance(profile, Profile)
218
+ assert profile.is_defined() is False
219
+
220
+ def test_inertial_pointing(self):
221
+ quaternion: Quaternion = Quaternion([0.0, 0.0, 0.0, 1.0], Quaternion.Format.XYZS)
222
+
223
+ trajectory: Trajectory = Trajectory.position(
224
+ Position.meters((0.0, 0.0, 0.0), Frame.ITRF())
225
+ )
226
+
227
+ profile: Profile = Profile.inertial_pointing(trajectory, quaternion)
228
+
229
+ assert profile is not None
230
+ assert isinstance(profile, Profile)
231
+ assert profile.is_defined()
232
+
233
+ def test_local_orbital_frame_pointing(
234
+ self,
235
+ orbit: Orbit,
236
+ ):
237
+ profile: Profile = Profile.local_orbital_frame_pointing(
238
+ orbit, Orbit.FrameType.VVLH
239
+ )
240
+
241
+ assert profile is not None
242
+ assert isinstance(profile, Profile)
243
+ assert profile.is_defined()
244
+
245
+ def test_align_and_constrain(
246
+ self,
247
+ orbit: Orbit,
248
+ instant: Instant,
249
+ alignment_target: Profile.Target,
250
+ clocking_target: Profile.Target,
251
+ ):
252
+ orientation = Profile.align_and_constrain(
253
+ alignment_target=alignment_target,
254
+ clocking_target=clocking_target,
255
+ )
256
+
257
+ assert orientation is not None
258
+ assert orientation(orbit.get_state_at(instant)) is not None
259
+
260
+ def test_custom_pointing(
261
+ self,
262
+ orbit: Orbit,
263
+ alignment_target: Profile.Target,
264
+ clocking_target: Profile.Target,
265
+ ):
266
+ profile = Profile.custom_pointing(
267
+ orbit=orbit,
268
+ orientation_generator=Profile.align_and_constrain(
269
+ alignment_target, clocking_target
270
+ ),
271
+ )
272
+
273
+ assert profile is not None
274
+ assert profile.is_defined()
275
+
276
+ profile = Profile.custom_pointing(
277
+ orbit=orbit,
278
+ alignment_target=alignment_target,
279
+ clocking_target=clocking_target,
280
+ )
281
+
282
+ assert profile is not None
283
+ assert profile.is_defined()
284
+
285
+ profile = Profile.custom_pointing(
286
+ orbit=orbit,
287
+ alignment_target=alignment_target,
288
+ clocking_target=clocking_target,
289
+ angular_offset=Angle.degrees(90.0),
290
+ )
291
+
292
+ assert profile is not None
293
+ assert profile.is_defined()
@@ -0,0 +1,45 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ from ostk.mathematics.geometry.d3.object import Cuboid
6
+ from ostk.mathematics.geometry.d3.object import Composite
7
+ from ostk.mathematics.geometry.d3.object import Point
8
+ from ostk.physics.unit import Mass
9
+ from ostk.astrodynamics.flight import System
10
+
11
+
12
+ @pytest.fixture
13
+ def system_default_inputs():
14
+ mass = Mass(90.0, Mass.Unit.Kilogram)
15
+ geometry = Composite(
16
+ Cuboid(
17
+ Point(0.0, 0.0, 0.0),
18
+ [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]],
19
+ [1.0, 0.0, 0.0],
20
+ )
21
+ )
22
+
23
+ return (mass, geometry)
24
+
25
+
26
+ @pytest.fixture
27
+ def system(system_default_inputs) -> System:
28
+ return System(*system_default_inputs)
29
+
30
+
31
+ class TestSatelliteSystem:
32
+ def test_constructors(self, system: System):
33
+ assert system is not None
34
+ assert isinstance(system, System)
35
+ assert system.is_defined()
36
+
37
+ def test_comparators(self, system: System):
38
+ assert (system == system) is True
39
+ assert (system != system) is False
40
+
41
+ def test_getters(self, system_default_inputs, system: System):
42
+ (mass, geometry) = system_default_inputs
43
+
44
+ assert system.get_mass() == mass
45
+ assert system.get_geometry() == geometry