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,319 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ import numpy as np
6
+
7
+ from ostk.mathematics.object import RealInterval
8
+
9
+ from ostk.physics.unit import Length
10
+ from ostk.physics.unit import Angle
11
+ from ostk.physics.time import DateTime
12
+ from ostk.physics.time import Scale
13
+ from ostk.physics.time import Duration
14
+ from ostk.physics.time import Instant
15
+ from ostk.physics.time import Interval
16
+ from ostk.physics import Environment
17
+ from ostk.physics.coordinate import Position
18
+ from ostk.physics.coordinate import Frame
19
+ from ostk.physics.coordinate.spherical import LLA
20
+ from ostk.physics.environment.object import Celestial
21
+ from ostk.physics.environment.object.celestial import Earth
22
+
23
+ from ostk.astrodynamics import Trajectory
24
+ from ostk.astrodynamics.trajectory import Orbit
25
+ from ostk.astrodynamics.trajectory.orbit.model import Kepler
26
+ from ostk.astrodynamics.trajectory.orbit.model.kepler import COE
27
+ from ostk.astrodynamics import Access
28
+ from ostk.astrodynamics.access import Generator
29
+ from ostk.astrodynamics.access import AccessTarget
30
+ from ostk.astrodynamics.access import VisibilityCriterion
31
+
32
+
33
+ @pytest.fixture
34
+ def environment() -> Environment:
35
+ return Environment.default()
36
+
37
+
38
+ @pytest.fixture
39
+ def earth(environment: Environment) -> Celestial:
40
+ return environment.access_celestial_object_with_name("Earth")
41
+
42
+
43
+ @pytest.fixture
44
+ def generator(environment: Environment) -> Generator:
45
+ return Generator(
46
+ environment=environment,
47
+ access_filter=lambda access: True,
48
+ state_filter=None,
49
+ )
50
+
51
+
52
+ @pytest.fixture
53
+ def from_trajectory(earth: Celestial) -> Trajectory:
54
+ return Orbit(
55
+ model=Kepler(
56
+ coe=COE(
57
+ semi_major_axis=Length.kilometers(7000.0),
58
+ eccentricity=0.0,
59
+ inclination=Angle.degrees(45.0),
60
+ raan=Angle.degrees(0.0),
61
+ aop=Angle.degrees(0.0),
62
+ true_anomaly=Angle.degrees(0.0),
63
+ ),
64
+ epoch=Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC),
65
+ celestial_object=earth,
66
+ perturbation_type=Kepler.PerturbationType.No,
67
+ ),
68
+ celestial_object=earth,
69
+ )
70
+
71
+
72
+ @pytest.fixture
73
+ def to_trajectory(earth: Celestial) -> Trajectory:
74
+ return Orbit(
75
+ model=Kepler(
76
+ coe=COE(
77
+ semi_major_axis=Length.kilometers(7000.0),
78
+ eccentricity=0.0,
79
+ inclination=Angle.degrees(45.0),
80
+ raan=Angle.degrees(180.0),
81
+ aop=Angle.degrees(0.0),
82
+ true_anomaly=Angle.degrees(180.0),
83
+ ),
84
+ epoch=Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC),
85
+ celestial_object=earth,
86
+ perturbation_type=Kepler.PerturbationType.No,
87
+ ),
88
+ celestial_object=earth,
89
+ )
90
+
91
+
92
+ @pytest.fixture
93
+ def visibility_criterion(environment: Environment) -> VisibilityCriterion:
94
+ return VisibilityCriterion.from_line_of_sight(environment=environment)
95
+
96
+
97
+ @pytest.fixture
98
+ def lla() -> LLA:
99
+ return LLA.vector([0.0, 0.0, 500.0])
100
+
101
+
102
+ @pytest.fixture
103
+ def access_target(
104
+ visibility_criterion: VisibilityCriterion,
105
+ lla: LLA,
106
+ earth: Earth,
107
+ ) -> AccessTarget:
108
+ return AccessTarget.from_lla(visibility_criterion, lla, earth)
109
+
110
+
111
+ @pytest.fixture
112
+ def trajectory_target(
113
+ visibility_criterion: VisibilityCriterion,
114
+ from_trajectory: Trajectory,
115
+ ) -> AccessTarget:
116
+ return AccessTarget.from_trajectory(visibility_criterion, from_trajectory)
117
+
118
+
119
+ class TestAccessTarget:
120
+ def test_constructor_success(self, access_target: AccessTarget):
121
+ assert isinstance(access_target, AccessTarget)
122
+
123
+ def test_get_type_success(self, access_target: AccessTarget):
124
+ assert access_target.get_type() == AccessTarget.Type.Fixed
125
+
126
+ def test_get_visibility_criterion_success(self, access_target: AccessTarget):
127
+ assert access_target.get_visibility_criterion() is not None
128
+ assert isinstance(access_target.get_visibility_criterion(), VisibilityCriterion)
129
+
130
+ def test_get_trajectory_success(self, access_target: AccessTarget):
131
+ assert access_target.get_trajectory() is not None
132
+ assert isinstance(access_target.get_trajectory(), Trajectory)
133
+
134
+ def test_get_position_success(self, access_target: AccessTarget):
135
+ assert access_target.get_position() is not None
136
+ assert isinstance(access_target.get_position(), Position)
137
+
138
+ def test_get_lla_success(
139
+ self,
140
+ access_target: AccessTarget,
141
+ earth: Earth,
142
+ ):
143
+ assert access_target.get_lla(earth) is not None
144
+ assert isinstance(access_target.get_lla(earth), LLA)
145
+
146
+ def test_compute_r_sez_ecef_success(
147
+ self,
148
+ access_target: AccessTarget,
149
+ earth: Earth,
150
+ ):
151
+ assert access_target.compute_r_sez_ecef(earth) is not None
152
+ assert isinstance(access_target.compute_r_sez_ecef(earth), np.ndarray)
153
+
154
+ def test_from_lla_success(
155
+ self,
156
+ visibility_criterion: VisibilityCriterion,
157
+ lla: LLA,
158
+ earth: Earth,
159
+ ):
160
+ access_target = AccessTarget.from_lla(visibility_criterion, lla, earth)
161
+
162
+ assert access_target is not None
163
+ assert isinstance(access_target, AccessTarget)
164
+
165
+ def test_from_position_success(
166
+ self,
167
+ visibility_criterion: VisibilityCriterion,
168
+ position: Position,
169
+ ):
170
+ access_target = AccessTarget.from_position(
171
+ visibility_criterion, position.in_frame(Frame.ITRF(), Instant.J2000())
172
+ )
173
+
174
+ assert access_target is not None
175
+ assert isinstance(access_target, AccessTarget)
176
+
177
+ def test_from_trajectory_success(
178
+ self,
179
+ visibility_criterion: VisibilityCriterion,
180
+ trajectory: Trajectory,
181
+ ):
182
+ access_target = AccessTarget.from_trajectory(visibility_criterion, trajectory)
183
+
184
+ assert access_target is not None
185
+ assert isinstance(access_target, AccessTarget)
186
+
187
+
188
+ class TestGenerator:
189
+ def test_constructor_success_environment(self, environment: Environment):
190
+ generator = Generator(
191
+ environment=environment,
192
+ )
193
+
194
+ assert generator is not None
195
+ assert isinstance(generator, Generator)
196
+
197
+ def test_constructor_success_environment_access_filter(
198
+ self,
199
+ environment: Environment,
200
+ ):
201
+ generator = Generator(
202
+ environment=environment,
203
+ access_filter=lambda access: True,
204
+ )
205
+
206
+ assert generator is not None
207
+ assert isinstance(generator, Generator)
208
+
209
+ def test_constructor_success_environment_state_filter(
210
+ self,
211
+ environment: Environment,
212
+ ):
213
+ generator = Generator(
214
+ environment=environment,
215
+ state_filter=lambda state_1, state_2: True,
216
+ )
217
+
218
+ assert generator is not None
219
+ assert isinstance(generator, Generator)
220
+
221
+ def test_constructor_success_environment_step_tolerance(
222
+ self,
223
+ environment: Environment,
224
+ ):
225
+ generator = Generator(
226
+ environment=environment,
227
+ step=Duration.seconds(1.0),
228
+ tolerance=Duration.minutes(1.0),
229
+ )
230
+
231
+ assert generator is not None
232
+ assert isinstance(generator, Generator)
233
+ assert generator.get_step() == Duration.seconds(1.0)
234
+ assert generator.get_tolerance() == Duration.minutes(1.0)
235
+
236
+ def test_getters_success(self, generator: Generator):
237
+ assert generator.get_step() == Duration.minutes(1.0)
238
+ assert generator.get_tolerance() == Duration.microseconds(1.0)
239
+ assert generator.get_access_filter() is not None
240
+ assert generator.get_state_filter() is None
241
+
242
+ def test_get_condition_function_success(
243
+ self,
244
+ generator: Generator,
245
+ trajectory_target: AccessTarget,
246
+ to_trajectory: Trajectory,
247
+ ):
248
+ condition_function = generator.get_condition_function(
249
+ access_target=trajectory_target,
250
+ to_trajectory=to_trajectory,
251
+ )
252
+
253
+ assert condition_function is not None
254
+ assert (
255
+ condition_function(
256
+ Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC)
257
+ )
258
+ is True
259
+ )
260
+
261
+ def test_compute_accesses_success(
262
+ self,
263
+ generator: Generator,
264
+ trajectory_target: AccessTarget,
265
+ to_trajectory: Trajectory,
266
+ ):
267
+ accesses = generator.compute_accesses(
268
+ interval=Interval.closed(
269
+ Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC),
270
+ Instant.date_time(DateTime(2018, 1, 1, 2, 0, 0), Scale.UTC),
271
+ ),
272
+ access_target=trajectory_target,
273
+ to_trajectory=to_trajectory,
274
+ )
275
+
276
+ assert accesses is not None
277
+ assert isinstance(accesses, list)
278
+ assert accesses[0] is not None
279
+ assert isinstance(accesses[0], Access)
280
+
281
+ def test_compute_accesses_multiple_targets_success(
282
+ self,
283
+ generator: Generator,
284
+ trajectory_target: AccessTarget,
285
+ to_trajectory: Trajectory,
286
+ ):
287
+ accesses = generator.compute_accesses(
288
+ interval=Interval.closed(
289
+ Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC),
290
+ Instant.date_time(DateTime(2018, 1, 1, 2, 0, 0), Scale.UTC),
291
+ ),
292
+ access_targets=[trajectory_target],
293
+ to_trajectory=to_trajectory,
294
+ )
295
+
296
+ assert accesses is not None
297
+ assert isinstance(accesses, list)
298
+ assert accesses[0] is not None
299
+ assert isinstance(accesses[0], list)
300
+ assert isinstance(accesses[0][0], Access)
301
+
302
+ def test_set_step_success(self, generator: Generator):
303
+ generator.set_step(Duration.seconds(1.0))
304
+
305
+ def test_set_tolerance_success(self, generator: Generator):
306
+ generator.set_tolerance(Duration.seconds(1.0))
307
+
308
+ def test_set_access_filter_success(self, generator: Generator):
309
+ generator.set_access_filter(access_filter=lambda access: True)
310
+
311
+ def test_set_state_filter_success(self, generator: Generator):
312
+ generator.set_state_filter(state_filter=lambda state_1, state_2: True)
313
+
314
+ def test_undefined_success(self):
315
+ generator = Generator.undefined()
316
+
317
+ assert generator is not None
318
+ assert isinstance(generator, Generator)
319
+ assert generator.is_defined() is False
@@ -0,0 +1,201 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+ import numpy as np
5
+
6
+ from ostk.mathematics.object import RealInterval
7
+
8
+ from ostk.physics import Environment
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.unit import Angle
13
+
14
+ from ostk.astrodynamics.access import VisibilityCriterion
15
+
16
+
17
+ @pytest.fixture()
18
+ def instant() -> Instant:
19
+ return Instant.date_time(DateTime(2023, 1, 1, 0, 0, 0), Scale.UTC)
20
+
21
+
22
+ @pytest.fixture
23
+ def environment() -> Environment:
24
+ return Environment.default()
25
+
26
+
27
+ @pytest.fixture
28
+ def azimuth_interval() -> RealInterval:
29
+ return RealInterval.closed(0.0, 90.0)
30
+
31
+
32
+ @pytest.fixture
33
+ def elevation_interval() -> RealInterval:
34
+ return RealInterval.closed(0.0, 45.0)
35
+
36
+
37
+ @pytest.fixture
38
+ def range_interval() -> RealInterval:
39
+ return RealInterval.closed(0.0, 1e7)
40
+
41
+
42
+ @pytest.fixture
43
+ def aer_mask() -> dict[float, float]:
44
+ return {
45
+ 0.0: 0.0,
46
+ 90.0: 45.0,
47
+ }
48
+
49
+
50
+ class TestVisibilityCriterion:
51
+ def test_aer_interval_constructor(
52
+ self,
53
+ azimuth_interval: RealInterval,
54
+ elevation_interval: RealInterval,
55
+ range_interval: RealInterval,
56
+ ):
57
+ aer_interval = VisibilityCriterion.AERInterval(
58
+ azimuth_interval,
59
+ elevation_interval,
60
+ range_interval,
61
+ )
62
+ assert aer_interval is not None
63
+ assert isinstance(aer_interval, VisibilityCriterion.AERInterval)
64
+
65
+ def test_aer_mask_constructor(
66
+ self,
67
+ aer_mask: dict[float, float],
68
+ range_interval: RealInterval,
69
+ ):
70
+ aer_mask_criterion = VisibilityCriterion.AERMask(aer_mask, range_interval)
71
+ assert aer_mask_criterion is not None
72
+ assert isinstance(aer_mask_criterion, VisibilityCriterion.AERMask)
73
+
74
+ def test_line_of_sight_constructor(
75
+ self,
76
+ environment: Environment,
77
+ ):
78
+ line_of_sight = VisibilityCriterion.LineOfSight(environment)
79
+ assert line_of_sight is not None
80
+ assert isinstance(line_of_sight, VisibilityCriterion.LineOfSight)
81
+
82
+ def test_elevation_interval_constructor(
83
+ self,
84
+ elevation_interval: RealInterval,
85
+ ):
86
+ elevation_criterion = VisibilityCriterion.ElevationInterval(elevation_interval)
87
+ assert elevation_criterion is not None
88
+ assert isinstance(elevation_criterion, VisibilityCriterion.ElevationInterval)
89
+
90
+ def test_visibility_criterion_from_aer_interval(
91
+ self,
92
+ azimuth_interval: RealInterval,
93
+ elevation_interval: RealInterval,
94
+ range_interval: RealInterval,
95
+ ):
96
+ criterion = VisibilityCriterion.from_aer_interval(
97
+ azimuth_interval, elevation_interval, range_interval
98
+ )
99
+ assert criterion is not None
100
+ assert isinstance(criterion, VisibilityCriterion)
101
+ assert criterion.is_aer_interval()
102
+
103
+ def test_visibility_criterion_from_aer_mask(
104
+ self,
105
+ aer_mask: dict[float, float],
106
+ range_interval: RealInterval,
107
+ ):
108
+ criterion = VisibilityCriterion.from_aer_mask(aer_mask, range_interval)
109
+ assert criterion is not None
110
+ assert isinstance(criterion, VisibilityCriterion)
111
+ assert criterion.is_aer_mask()
112
+
113
+ def test_visibility_criterion_from_line_of_sight(
114
+ self,
115
+ environment: Environment,
116
+ ):
117
+ criterion = VisibilityCriterion.from_line_of_sight(environment)
118
+ assert criterion is not None
119
+ assert isinstance(criterion, VisibilityCriterion)
120
+ assert criterion.is_line_of_sight()
121
+
122
+ def test_visibility_criterion_from_elevation_interval(
123
+ self, elevation_interval: RealInterval
124
+ ):
125
+ criterion = VisibilityCriterion.from_elevation_interval(elevation_interval)
126
+ assert criterion is not None
127
+ assert isinstance(criterion, VisibilityCriterion)
128
+ assert criterion.is_elevation_interval()
129
+
130
+ def test_aer_interval_is_satisfied(
131
+ self,
132
+ azimuth_interval: RealInterval,
133
+ elevation_interval: RealInterval,
134
+ range_interval: RealInterval,
135
+ ):
136
+ aer_interval = VisibilityCriterion.AERInterval(
137
+ azimuth_interval, elevation_interval, range_interval
138
+ )
139
+ assert (
140
+ aer_interval.is_satisfied(azimuth=np.pi / 4, elevation=np.pi / 8, range=5e6)
141
+ is True
142
+ )
143
+
144
+ assert (
145
+ aer_interval.is_satisfied(azimuth=np.pi, elevation=np.pi / 2, range=1e8)
146
+ is False
147
+ )
148
+
149
+ def test_elevation_interval_is_satisfied(
150
+ self,
151
+ elevation_interval: RealInterval,
152
+ ):
153
+ elevation_criterion = VisibilityCriterion.ElevationInterval(elevation_interval)
154
+ elevation_valid = np.pi / 8 # 22.5 degrees
155
+ assert elevation_criterion.is_satisfied(elevation_valid) is True
156
+ assert elevation_criterion.is_satisfied(Angle.radians(elevation_valid)) is True
157
+
158
+ elevation_invalid = np.pi / 2 # 90 degrees
159
+ assert elevation_criterion.is_satisfied(elevation_invalid) is False
160
+ assert elevation_criterion.is_satisfied(Angle.radians(elevation_invalid)) is False
161
+
162
+ def test_line_of_sight_is_satisfied(
163
+ self,
164
+ environment: Environment,
165
+ ):
166
+ line_of_sight = VisibilityCriterion.LineOfSight(environment)
167
+ instant = Instant.now()
168
+
169
+ from_position = np.array([7000e3, 0.0, 0.0])
170
+ to_position = np.array([7005e3, 0.0, 0.0])
171
+
172
+ assert line_of_sight.is_satisfied(instant, from_position, to_position) is True
173
+
174
+ def test_visibility_criterion_type_checks(
175
+ self,
176
+ elevation_interval: RealInterval,
177
+ environment: Environment,
178
+ ):
179
+ criterion = VisibilityCriterion.from_elevation_interval(elevation_interval)
180
+ assert criterion.is_elevation_interval() is True
181
+ assert criterion.is_aer_interval() is False
182
+ assert criterion.is_line_of_sight() is False
183
+
184
+ criterion = VisibilityCriterion.from_line_of_sight(environment)
185
+ assert criterion.is_line_of_sight() is True
186
+
187
+ def test_visibility_criterion_cast(
188
+ self,
189
+ azimuth_interval: RealInterval,
190
+ elevation_interval: RealInterval,
191
+ range_interval: RealInterval,
192
+ ):
193
+ criterion = VisibilityCriterion.from_aer_interval(
194
+ azimuth_interval, elevation_interval, range_interval
195
+ )
196
+ aer_interval = criterion.as_aer_interval()
197
+ assert aer_interval is not None
198
+ assert isinstance(aer_interval, VisibilityCriterion.AERInterval)
199
+
200
+ with pytest.raises(ValueError):
201
+ criterion.as_line_of_sight()
@@ -0,0 +1,119 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ from ostk.physics import Environment
6
+ from ostk.physics.unit import Angle
7
+ from ostk.physics.unit import Length
8
+ from ostk.physics.time import Instant
9
+ from ostk.physics.time import DateTime
10
+ from ostk.physics.time import Scale
11
+ from ostk.physics.time import Interval
12
+ from ostk.physics.coordinate import Position
13
+ from ostk.physics.coordinate import Velocity
14
+ from ostk.physics.coordinate import Frame
15
+ from ostk.physics.coordinate.spherical import LLA
16
+ from ostk.physics.coordinate.spherical import AER
17
+
18
+ from ostk.astrodynamics import Trajectory
19
+ from ostk.astrodynamics.trajectory import State
20
+
21
+
22
+ @pytest.fixture
23
+ def environment() -> Environment:
24
+ return Environment.default()
25
+
26
+
27
+ @pytest.fixture
28
+ def scale() -> Scale:
29
+ return Scale.UTC
30
+
31
+
32
+ @pytest.fixture
33
+ def instant_1(scale: Scale) -> Instant:
34
+ return Instant.date_time(DateTime(2023, 1, 8, 13, 45, 34), scale)
35
+
36
+
37
+ @pytest.fixture
38
+ def instant_2(scale: Scale) -> Instant:
39
+ return Instant.date_time(DateTime(2023, 1, 8, 13, 46, 34), scale)
40
+
41
+
42
+ @pytest.fixture
43
+ def instant_3(scale: Scale) -> Instant:
44
+ return Instant.date_time(DateTime(2023, 1, 8, 13, 47, 34), scale)
45
+
46
+
47
+ @pytest.fixture
48
+ def instant(instant_1: Instant) -> Instant:
49
+ return instant_1
50
+
51
+
52
+ @pytest.fixture
53
+ def interval(instant_1: Instant, instant_2: Instant) -> Interval:
54
+ return Interval(instant_1, instant_2, Interval.Type.Closed)
55
+
56
+
57
+ @pytest.fixture
58
+ def frame() -> Frame:
59
+ return Frame.GCRF()
60
+
61
+
62
+ @pytest.fixture
63
+ def position(frame: Frame) -> Position:
64
+ return Position.meters([7000000.0, 0.0, 0.0], frame)
65
+
66
+
67
+ @pytest.fixture
68
+ def velocity(frame: Frame) -> Velocity:
69
+ return Velocity.meters_per_second([7600.0, 0.0, 0.0], frame)
70
+
71
+
72
+ @pytest.fixture
73
+ def state(instant: Instant, position: Position, velocity: Velocity) -> State:
74
+ return State(instant, position, velocity)
75
+
76
+
77
+ @pytest.fixture
78
+ def latitude() -> Angle:
79
+ return Angle(30.0, Angle.Unit.Degree)
80
+
81
+
82
+ @pytest.fixture
83
+ def longitude() -> Angle:
84
+ return Angle(-111.0, Angle.Unit.Degree)
85
+
86
+
87
+ @pytest.fixture
88
+ def altitude() -> Length:
89
+ return Length(10000.0, Length.Unit.Meter)
90
+
91
+
92
+ @pytest.fixture
93
+ def lla(latitude: Angle, longitude: Angle, altitude: Length) -> LLA:
94
+ return LLA(latitude, longitude, altitude)
95
+
96
+
97
+ @pytest.fixture
98
+ def azimuth() -> Angle:
99
+ return Angle(270.0, Angle.Unit.Degree)
100
+
101
+
102
+ @pytest.fixture
103
+ def elevation() -> Angle:
104
+ return Angle(10.45, Angle.Unit.Degree)
105
+
106
+
107
+ @pytest.fixture
108
+ def range() -> Length:
109
+ return Length(100000.0, Length.Unit.Meter)
110
+
111
+
112
+ @pytest.fixture
113
+ def aer(azimuth: Angle, elevation: Angle, range: Length) -> LLA:
114
+ return AER(azimuth, elevation, range)
115
+
116
+
117
+ @pytest.fixture
118
+ def trajectory(position: Position, instant_1: Instant) -> Trajectory:
119
+ return Trajectory.position(position.in_frame(Frame.ITRF(), instant_1))