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,177 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ import numpy as np
6
+
7
+ from ostk.physics.time import DateTime
8
+ from ostk.physics.time import Duration
9
+ from ostk.physics.time import Instant
10
+ from ostk.physics.time import Scale
11
+ from ostk.physics.unit import Angle
12
+ from ostk.physics.coordinate import Frame
13
+
14
+ from ostk.astrodynamics.trajectory import LocalOrbitalFrameFactory
15
+ from ostk.astrodynamics.trajectory import LocalOrbitalFrameDirection
16
+
17
+ from ostk.astrodynamics import GuidanceLaw
18
+ from ostk.astrodynamics.flight import Maneuver
19
+ from ostk.astrodynamics.guidance_law import ConstantThrust
20
+ from ostk.astrodynamics.trajectory import State
21
+ from ostk.astrodynamics.trajectory.state import CoordinateSubset
22
+ from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianPosition
23
+ from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianVelocity
24
+ from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianAcceleration
25
+
26
+
27
+ @pytest.fixture
28
+ def local_orbital_frame_direction() -> LocalOrbitalFrameDirection:
29
+ return LocalOrbitalFrameDirection(
30
+ vector=[1.0, 0.0, 0.0],
31
+ local_orbital_frame_factory=LocalOrbitalFrameFactory.VNC(Frame.GCRF()),
32
+ )
33
+
34
+
35
+ @pytest.fixture
36
+ def guidance_law(
37
+ local_orbital_frame_direction: LocalOrbitalFrameDirection,
38
+ ) -> ConstantThrust:
39
+ return ConstantThrust(thrust_direction=local_orbital_frame_direction)
40
+
41
+
42
+ @pytest.fixture
43
+ def instant() -> Instant:
44
+ return Instant.date_time(DateTime(2021, 3, 20, 12, 0, 0), Scale.UTC)
45
+
46
+
47
+ @pytest.fixture
48
+ def position_coordinates() -> list[float]:
49
+ return [7000000.0, 0.0, 0.0]
50
+
51
+
52
+ @pytest.fixture
53
+ def velocity_coordinates() -> list[float]:
54
+ return [0.0, 7546.05329, 0.0]
55
+
56
+
57
+ @pytest.fixture
58
+ def thrust_acceleration() -> float:
59
+ return 1.0 / 105.0
60
+
61
+
62
+ @pytest.fixture
63
+ def frame() -> Frame:
64
+ return Frame.GCRF()
65
+
66
+
67
+ @pytest.fixture
68
+ def instants() -> list[Instant]:
69
+ return [
70
+ Instant.J2000(),
71
+ Instant.J2000() + Duration.seconds(30.0),
72
+ Instant.J2000() + Duration.seconds(35.0),
73
+ Instant.J2000() + Duration.seconds(37.0),
74
+ ]
75
+
76
+
77
+ @pytest.fixture
78
+ def acceleration_profile() -> list[np.ndarray]:
79
+ return [
80
+ np.array([1.0e-3, 0.0e-3, 0.0e-3]),
81
+ np.array([0.0e-3, 1.0e-3, 0.0e-3]),
82
+ np.array([0.0e-3, 0.0e-3, 1.0e-3]),
83
+ np.array([1.0e-3, 1.0e-3, 1.0e-3]),
84
+ ]
85
+
86
+
87
+ @pytest.fixture
88
+ def mass_flow_rate_profile() -> list[float]:
89
+ return [-1.0e-5, -1.1e-5, -0.9e-5, -1.0e-5]
90
+
91
+
92
+ @pytest.fixture
93
+ def coordinate_subsets() -> list[CoordinateSubset]:
94
+ return [
95
+ CartesianPosition.default(),
96
+ CartesianVelocity.default(),
97
+ CartesianAcceleration.thrust_acceleration(),
98
+ CoordinateSubset.mass_flow_rate(),
99
+ ]
100
+
101
+
102
+ @pytest.fixture
103
+ def maneuver(
104
+ instants: list[Instant],
105
+ acceleration_profile: list[np.ndarray],
106
+ mass_flow_rate_profile: list[float],
107
+ frame: Frame,
108
+ coordinate_subsets: list[CoordinateSubset],
109
+ ) -> Maneuver:
110
+ states = []
111
+ for instant, acceleration, mass_flow_rate in zip(
112
+ instants, acceleration_profile, mass_flow_rate_profile
113
+ ):
114
+ states.append(
115
+ State(
116
+ instant,
117
+ [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, *acceleration, mass_flow_rate],
118
+ frame,
119
+ coordinate_subsets,
120
+ )
121
+ )
122
+ return Maneuver(states)
123
+
124
+
125
+ class TestConstantThrust:
126
+ def test_constructors(self, guidance_law: ConstantThrust):
127
+ assert guidance_law is not None
128
+ assert isinstance(guidance_law, ConstantThrust)
129
+ assert isinstance(guidance_law, GuidanceLaw)
130
+
131
+ def test_getters(self, guidance_law: ConstantThrust):
132
+ assert guidance_law.get_local_thrust_direction() is not None
133
+
134
+ def test_static_constructors(self):
135
+ assert ConstantThrust.intrack() is not None
136
+
137
+ assert ConstantThrust.intrack(velocity_direction=False) is not None
138
+
139
+ assert ConstantThrust.intrack(velocity_direction=True) is not None
140
+
141
+ def test_compute_acceleration_success(
142
+ self,
143
+ guidance_law: ConstantThrust,
144
+ instant: Instant,
145
+ position_coordinates: list[float],
146
+ velocity_coordinates: list[float],
147
+ thrust_acceleration: float,
148
+ frame: Frame,
149
+ ):
150
+ contribution = guidance_law.calculate_thrust_acceleration_at(
151
+ instant=instant,
152
+ position_coordinates=position_coordinates,
153
+ velocity_coordinates=velocity_coordinates,
154
+ thrust_acceleration=thrust_acceleration,
155
+ output_frame=frame,
156
+ )
157
+
158
+ assert len(contribution) == 3
159
+ assert contribution == pytest.approx([0.0, 0.009523809523809525, 0.0], abs=5e-11)
160
+
161
+ def test_from_maneuver(self, maneuver: Maneuver):
162
+ constant_thrust = ConstantThrust.from_maneuver(
163
+ maneuver=maneuver,
164
+ local_orbital_frame_factory=LocalOrbitalFrameFactory.TNW(Frame.GCRF()),
165
+ )
166
+ assert isinstance(constant_thrust, ConstantThrust)
167
+
168
+ constant_thrust_with_maximum_allowed_angular_offset = (
169
+ ConstantThrust.from_maneuver(
170
+ maneuver=maneuver,
171
+ local_orbital_frame_factory=LocalOrbitalFrameFactory.TNW(Frame.GCRF()),
172
+ maximum_allowed_angular_offset=Angle.degrees(180.0),
173
+ )
174
+ )
175
+ assert isinstance(
176
+ constant_thrust_with_maximum_allowed_angular_offset, ConstantThrust
177
+ )
@@ -0,0 +1,60 @@
1
+ # Apache License 2.0
2
+
3
+ import numpy as np
4
+
5
+ import pytest
6
+
7
+ from ostk.physics.time import Instant
8
+ from ostk.physics.coordinate import Frame
9
+ from ostk.astrodynamics import GuidanceLaw
10
+
11
+
12
+ @pytest.fixture
13
+ def guidance_law() -> GuidanceLaw:
14
+ class MyGuidanceLaw(GuidanceLaw):
15
+
16
+ def __init__(
17
+ self,
18
+ name: str,
19
+ ):
20
+ super().__init__(name)
21
+
22
+ def calculate_thrust_acceleration_at(
23
+ self,
24
+ instant: Instant,
25
+ position_coordinates: np.array,
26
+ velocity_coordinates: np.array,
27
+ thrust_acceleration: float,
28
+ output_frame: Frame,
29
+ ) -> np.array:
30
+ return np.array([0.0, 0.0, 0.0])
31
+
32
+ return MyGuidanceLaw("My Guidance Law")
33
+
34
+
35
+ class TestGuidanceLaw:
36
+ def test_subclass(
37
+ self,
38
+ guidance_law: GuidanceLaw,
39
+ ):
40
+ assert isinstance(guidance_law, GuidanceLaw)
41
+
42
+ def test_get_name(
43
+ self,
44
+ guidance_law: GuidanceLaw,
45
+ ):
46
+ assert guidance_law.get_name() == "My Guidance Law"
47
+
48
+ def test_calculate_thrust_acceleration_at(
49
+ self,
50
+ guidance_law: GuidanceLaw,
51
+ ):
52
+ thrust_acceleration: np.array = guidance_law.calculate_thrust_acceleration_at(
53
+ instant=Instant.J2000(),
54
+ position_coordinates=np.array([0.0, 0.0, 0.0]),
55
+ velocity_coordinates=np.array([0.0, 0.0, 0.0]),
56
+ thrust_acceleration=1.0,
57
+ output_frame=Frame.GCRF(),
58
+ )
59
+
60
+ assert np.array_equal(thrust_acceleration, np.array([0.0, 0.0, 0.0]))
@@ -0,0 +1,164 @@
1
+ # Apache License 2.0
2
+
3
+ import numpy as np
4
+
5
+ import pytest
6
+
7
+ from ostk.physics.coordinate import Frame
8
+ from ostk.physics.time import Instant
9
+ from ostk.physics.time import Duration
10
+ from ostk.physics.time import Interval
11
+ from ostk.astrodynamics import GuidanceLaw
12
+ from ostk.astrodynamics.guidance_law import HeterogeneousGuidanceLaw
13
+
14
+
15
+ @pytest.fixture
16
+ def interval_1() -> Interval:
17
+ return Interval.closed(
18
+ start_instant=Instant.J2000(),
19
+ end_instant=Instant.J2000() + Duration.seconds(100.0),
20
+ )
21
+
22
+
23
+ @pytest.fixture
24
+ def guidance_law_1() -> GuidanceLaw:
25
+ class GuidanceLaw1(GuidanceLaw):
26
+
27
+ def __init__(
28
+ self,
29
+ name: str,
30
+ ):
31
+ super().__init__(name)
32
+
33
+ def calculate_thrust_acceleration_at(
34
+ self,
35
+ instant: Instant,
36
+ position_coordinates: np.array,
37
+ velocity_coordinates: np.array,
38
+ thrust_acceleration: float,
39
+ output_frame: Frame,
40
+ ) -> np.array:
41
+ return np.array([1.0, 2.0, 3.0])
42
+
43
+ return GuidanceLaw1("My Guidance Law 1")
44
+
45
+
46
+ @pytest.fixture
47
+ def interval_2() -> Interval:
48
+ return Interval.closed(
49
+ start_instant=Instant.J2000() + Duration.seconds(200.0),
50
+ end_instant=Instant.J2000() + Duration.seconds(300.0),
51
+ )
52
+
53
+
54
+ @pytest.fixture
55
+ def guidance_law_2() -> GuidanceLaw:
56
+ class GuidanceLaw2(GuidanceLaw):
57
+
58
+ def __init__(
59
+ self,
60
+ name: str,
61
+ ):
62
+ super().__init__(name)
63
+
64
+ def calculate_thrust_acceleration_at(
65
+ self,
66
+ instant: Instant,
67
+ position_coordinates: np.array,
68
+ velocity_coordinates: np.array,
69
+ thrust_acceleration: float,
70
+ output_frame: Frame,
71
+ ) -> np.array:
72
+ return np.array([4.0, 5.0, 6.0])
73
+
74
+ return GuidanceLaw2("My Guidance Law 2")
75
+
76
+
77
+ @pytest.fixture
78
+ def heterogeneous_guidance_law(
79
+ interval_1: Interval,
80
+ guidance_law_1: GuidanceLaw,
81
+ interval_2: Interval,
82
+ guidance_law_2: GuidanceLaw,
83
+ ) -> HeterogeneousGuidanceLaw:
84
+ return HeterogeneousGuidanceLaw(
85
+ guidance_laws_with_intervals=[
86
+ (guidance_law_1, interval_1),
87
+ (guidance_law_2, interval_2),
88
+ ],
89
+ )
90
+
91
+
92
+ class TestHeterogeneousGuidanceLaw:
93
+ def test_constructor_and_getters(
94
+ self,
95
+ interval_1: Interval,
96
+ guidance_law_1: GuidanceLaw,
97
+ interval_2: Interval,
98
+ guidance_law_2: GuidanceLaw,
99
+ ):
100
+ heterogeneous_guidance_law = HeterogeneousGuidanceLaw(
101
+ guidance_laws_with_intervals=[
102
+ (guidance_law_1, interval_1),
103
+ (guidance_law_2, interval_2),
104
+ ],
105
+ )
106
+ assert heterogeneous_guidance_law is not None
107
+ assert isinstance(heterogeneous_guidance_law, HeterogeneousGuidanceLaw)
108
+ assert heterogeneous_guidance_law.get_guidance_laws_with_intervals() == [
109
+ (guidance_law_1, interval_1),
110
+ (guidance_law_2, interval_2),
111
+ ]
112
+
113
+ def test_add_guidance_law(
114
+ self,
115
+ interval_1: Interval,
116
+ guidance_law_1: GuidanceLaw,
117
+ interval_2: Interval,
118
+ guidance_law_2: GuidanceLaw,
119
+ ):
120
+ heterogeneous_guidance_law = HeterogeneousGuidanceLaw()
121
+
122
+ assert isinstance(heterogeneous_guidance_law, HeterogeneousGuidanceLaw)
123
+ assert heterogeneous_guidance_law.get_guidance_laws_with_intervals() == []
124
+
125
+ heterogeneous_guidance_law.add_guidance_law(guidance_law_1, interval_1)
126
+ assert heterogeneous_guidance_law.get_guidance_laws_with_intervals() == [
127
+ (guidance_law_1, interval_1),
128
+ ]
129
+
130
+ heterogeneous_guidance_law.add_guidance_law(guidance_law_2, interval_2)
131
+ assert heterogeneous_guidance_law.get_guidance_laws_with_intervals() == [
132
+ (guidance_law_1, interval_1),
133
+ (guidance_law_2, interval_2),
134
+ ]
135
+
136
+ @pytest.mark.parametrize(
137
+ (
138
+ "instant",
139
+ "expected_thrust_acceleration",
140
+ ),
141
+ [
142
+ (Instant.J2000() - Duration.seconds(50.0), np.array([0.0, 0.0, 0.0])),
143
+ (Instant.J2000() + Duration.seconds(50.0), np.array([1.0, 2.0, 3.0])),
144
+ (Instant.J2000() + Duration.seconds(150.0), np.array([0.0, 0.0, 0.0])),
145
+ (Instant.J2000() + Duration.seconds(250.0), np.array([4.0, 5.0, 6.0])),
146
+ (Instant.J2000() + Duration.seconds(350.0), np.array([0.0, 0.0, 0.0])),
147
+ ],
148
+ )
149
+ def test_calculate_thrust_acceleration_at(
150
+ self,
151
+ heterogeneous_guidance_law: HeterogeneousGuidanceLaw,
152
+ instant: Instant,
153
+ expected_thrust_acceleration: np.array,
154
+ ):
155
+ assert np.array_equal(
156
+ heterogeneous_guidance_law.calculate_thrust_acceleration_at(
157
+ instant=instant,
158
+ position_coordinates=np.array([0.0, 0.0, 0.0]),
159
+ velocity_coordinates=np.array([0.0, 0.0, 0.0]),
160
+ thrust_acceleration=1.0,
161
+ output_frame=Frame.GCRF(),
162
+ ),
163
+ expected_thrust_acceleration,
164
+ )
@@ -0,0 +1,209 @@
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.coordinate import Frame
9
+ from ostk.physics.coordinate import Position
10
+ from ostk.physics.coordinate import Velocity
11
+ from ostk.physics.unit import Derived
12
+ from ostk.physics.environment.gravitational import Earth as EarthGravitationalModel
13
+ from ostk.physics.time import Instant
14
+ from ostk.physics.unit import Length
15
+ from ostk.physics.unit import Angle
16
+
17
+
18
+ from ostk.astrodynamics.trajectory.orbit.model.kepler import COE
19
+ from ostk.astrodynamics import GuidanceLaw
20
+ from ostk.astrodynamics.guidance_law import QLaw
21
+ from ostk.astrodynamics.trajectory import State
22
+
23
+
24
+ @pytest.fixture
25
+ def target_COE() -> COE:
26
+ return COE(
27
+ Length.meters(42000.0e3),
28
+ 0.01,
29
+ Angle.degrees(0.05),
30
+ Angle.degrees(0.0),
31
+ Angle.degrees(0.0),
32
+ Angle.degrees(0.0),
33
+ )
34
+
35
+
36
+ @pytest.fixture
37
+ def gravitational_parameter() -> Derived:
38
+ return Derived(
39
+ 3.986004418e14,
40
+ EarthGravitationalModel.EGM2008.gravitational_parameter.get_unit(),
41
+ )
42
+
43
+
44
+ @pytest.fixture
45
+ def parameters() -> QLaw.Parameters:
46
+ return QLaw.Parameters(
47
+ element_weights={
48
+ COE.Element.SemiMajorAxis: (1.0, 100.0),
49
+ COE.Element.Eccentricity: (1.0, 1e-3),
50
+ },
51
+ m=5,
52
+ n=6,
53
+ r=7,
54
+ b=0.08,
55
+ k=9,
56
+ periapsis_weight=0.1,
57
+ minimum_periapsis_radius=Length.kilometers(7000.0),
58
+ absolute_effectivity_threshold=0.2,
59
+ relative_effectivity_threshold=0.3,
60
+ )
61
+
62
+
63
+ @pytest.fixture
64
+ def gradient_strategy() -> QLaw.GradientStrategy:
65
+ return QLaw.GradientStrategy.FiniteDifference
66
+
67
+
68
+ @pytest.fixture
69
+ def q_law(
70
+ target_COE: COE,
71
+ gravitational_parameter: Derived,
72
+ parameters: QLaw.Parameters,
73
+ gradient_strategy: QLaw.GradientStrategy,
74
+ ) -> QLaw:
75
+ return QLaw(
76
+ target_coe=target_COE,
77
+ gravitational_parameter=gravitational_parameter,
78
+ parameters=parameters,
79
+ coe_domain=QLaw.COEDomain.Osculating,
80
+ gradient_strategy=gradient_strategy,
81
+ )
82
+
83
+
84
+ @pytest.fixture
85
+ def thrust_acceleration() -> float:
86
+ return 1.0 / 300.0
87
+
88
+
89
+ @pytest.fixture
90
+ def frame() -> Frame:
91
+ return Frame.GCRF()
92
+
93
+
94
+ @pytest.fixture
95
+ def position_coordinates() -> list[float]:
96
+ return [6930000.0, 0.0, 0.0]
97
+
98
+
99
+ @pytest.fixture
100
+ def velocity_coordinates() -> list[float]:
101
+ return [0.0, 7621.89248591193, 6.65135764404186]
102
+
103
+
104
+ @pytest.fixture
105
+ def instant() -> Instant:
106
+ return Instant.J2000()
107
+
108
+
109
+ @pytest.fixture
110
+ def position(frame: Frame, position_coordinates: list[float]) -> Position:
111
+ return Position.meters(position_coordinates, frame)
112
+
113
+
114
+ @pytest.fixture
115
+ def velocity(frame: Frame, velocity_coordinates: list[float]) -> Velocity:
116
+ return Velocity.meters_per_second(velocity_coordinates, frame)
117
+
118
+
119
+ @pytest.fixture
120
+ def state(instant: Instant, position: Position, velocity: Velocity) -> State:
121
+ return State(instant=instant, position=position, velocity=velocity)
122
+
123
+
124
+ class TestQLawParameters:
125
+ def test_constructors(self, parameters: QLaw.Parameters):
126
+ assert parameters is not None
127
+ assert isinstance(parameters, QLaw.Parameters)
128
+
129
+ def test_getters(self, parameters: QLaw.Parameters):
130
+ assert parameters.get_control_weights() is not None
131
+ assert parameters.get_convergence_thresholds() is not None
132
+ assert parameters.m == 5
133
+ assert parameters.n == 6
134
+ assert parameters.r == 7
135
+ assert parameters.b == 0.08
136
+ assert parameters.k == 9
137
+ assert parameters.periapsis_weight == 0.1
138
+ assert parameters.get_minimum_periapsis_radius() == Length.kilometers(7000.0)
139
+ assert parameters.absolute_effectivity_threshold == 0.2
140
+ assert parameters.relative_effectivity_threshold == 0.3
141
+
142
+
143
+ class TestQLaw:
144
+ def test_constructors(
145
+ self,
146
+ target_COE: COE,
147
+ gravitational_parameter: Derived,
148
+ parameters: QLaw.Parameters,
149
+ gradient_strategy: QLaw.GradientStrategy,
150
+ ):
151
+ qlaw: QLaw = QLaw(
152
+ target_coe=target_COE,
153
+ gravitational_parameter=gravitational_parameter,
154
+ parameters=parameters,
155
+ coe_domain=QLaw.COEDomain.BrouwerLyddaneMeanLong,
156
+ gradient_strategy=gradient_strategy,
157
+ )
158
+
159
+ assert qlaw is not None
160
+ assert isinstance(qlaw, QLaw)
161
+ assert isinstance(qlaw, GuidanceLaw)
162
+
163
+ def test_getters(self, q_law: QLaw):
164
+ assert q_law.get_parameters() is not None
165
+ assert q_law.get_target_coe() is not None
166
+ assert q_law.get_gradient_strategy() is not None
167
+ assert q_law.get_coe_domain() is not None
168
+
169
+ def test_calculate_thrust_acceleration_at(
170
+ self,
171
+ q_law: QLaw,
172
+ position_coordinates: list[float],
173
+ velocity_coordinates: list[float],
174
+ thrust_acceleration: float,
175
+ instant: Instant,
176
+ frame: Frame,
177
+ ):
178
+ assert pytest.approx(
179
+ q_law.calculate_thrust_acceleration_at(
180
+ instant=instant,
181
+ position_coordinates=position_coordinates,
182
+ velocity_coordinates=velocity_coordinates,
183
+ thrust_acceleration=thrust_acceleration,
184
+ output_frame=frame,
185
+ )
186
+ ) == np.array([0.0, 0.0033333320640941645, 2.9088817174504986e-06])
187
+
188
+ def test_compute_effectivity(
189
+ self,
190
+ q_law: QLaw,
191
+ state: State,
192
+ thrust_acceleration: float,
193
+ ):
194
+ assert (
195
+ q_law.compute_effectivity(
196
+ state=state,
197
+ thrust_acceleration=thrust_acceleration,
198
+ )
199
+ is not None
200
+ )
201
+
202
+ assert (
203
+ q_law.compute_effectivity(
204
+ state=state,
205
+ thrust_acceleration=thrust_acceleration,
206
+ discretization_step_count=15,
207
+ )
208
+ is not None
209
+ )
@@ -0,0 +1 @@
1
+ # Apache License 2.0