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.
- open_space_toolkit_astrodynamics-17.2.0.dist-info/METADATA +30 -0
- open_space_toolkit_astrodynamics-17.2.0.dist-info/RECORD +151 -0
- open_space_toolkit_astrodynamics-17.2.0.dist-info/WHEEL +5 -0
- open_space_toolkit_astrodynamics-17.2.0.dist-info/top_level.txt +1 -0
- open_space_toolkit_astrodynamics-17.2.0.dist-info/zip-safe +1 -0
- ostk/__init__.py +1 -0
- ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-312-x86_64-linux-gnu.so +0 -0
- ostk/astrodynamics/__init__.py +11 -0
- ostk/astrodynamics/__init__.pyi +720 -0
- ostk/astrodynamics/access.pyi +577 -0
- ostk/astrodynamics/conjunction/__init__.pyi +121 -0
- ostk/astrodynamics/conjunction/close_approach.pyi +89 -0
- ostk/astrodynamics/conjunction/message/__init__.pyi +3 -0
- ostk/astrodynamics/conjunction/message/ccsds.pyi +705 -0
- ostk/astrodynamics/converters.py +130 -0
- ostk/astrodynamics/converters.pyi +58 -0
- ostk/astrodynamics/data/__init__.pyi +3 -0
- ostk/astrodynamics/data/provider.pyi +22 -0
- ostk/astrodynamics/dataframe.py +597 -0
- ostk/astrodynamics/display.py +281 -0
- ostk/astrodynamics/dynamics.pyi +311 -0
- ostk/astrodynamics/eclipse.pyi +70 -0
- ostk/astrodynamics/estimator.pyi +268 -0
- ostk/astrodynamics/event_condition.pyi +910 -0
- ostk/astrodynamics/flight/__init__.pyi +626 -0
- ostk/astrodynamics/flight/profile/__init__.pyi +99 -0
- ostk/astrodynamics/flight/profile/model.pyi +179 -0
- ostk/astrodynamics/flight/system.pyi +268 -0
- ostk/astrodynamics/guidance_law.pyi +416 -0
- ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.17 +0 -0
- ostk/astrodynamics/pytrajectory/__init__.py +1 -0
- ostk/astrodynamics/pytrajectory/__init__.pyi +3 -0
- ostk/astrodynamics/pytrajectory/pystate.py +263 -0
- ostk/astrodynamics/pytrajectory/pystate.pyi +66 -0
- ostk/astrodynamics/solver.pyi +432 -0
- ostk/astrodynamics/test/__init__.py +1 -0
- ostk/astrodynamics/test/access/__init__.py +1 -0
- ostk/astrodynamics/test/access/test_generator.py +319 -0
- ostk/astrodynamics/test/access/test_visibility_criterion.py +201 -0
- ostk/astrodynamics/test/conftest.py +119 -0
- ostk/astrodynamics/test/conjunction/close_approach/__init__.py +0 -0
- ostk/astrodynamics/test/conjunction/close_approach/test_generator.py +228 -0
- ostk/astrodynamics/test/conjunction/message/ccsds/__init__.py +1 -0
- ostk/astrodynamics/test/conjunction/message/ccsds/conftest.py +325 -0
- ostk/astrodynamics/test/conjunction/message/ccsds/data/cdm.json +303 -0
- ostk/astrodynamics/test/conjunction/message/ccsds/test_cdm.py +416 -0
- ostk/astrodynamics/test/conjunction/test_close_approach.py +244 -0
- ostk/astrodynamics/test/data/provider/test_off_nadir.py +58 -0
- ostk/astrodynamics/test/dynamics/__init__.py +1 -0
- ostk/astrodynamics/test/dynamics/data/Tabulated_Earth_Gravity.csv +565 -0
- ostk/astrodynamics/test/dynamics/data/Tabulated_Earth_Gravity_Truth.csv +100 -0
- ostk/astrodynamics/test/dynamics/test_atmospheric_drag.py +128 -0
- ostk/astrodynamics/test/dynamics/test_central_body_gravity.py +58 -0
- ostk/astrodynamics/test/dynamics/test_dynamics.py +50 -0
- ostk/astrodynamics/test/dynamics/test_position_derivative.py +51 -0
- ostk/astrodynamics/test/dynamics/test_tabulated.py +138 -0
- ostk/astrodynamics/test/dynamics/test_third_body_gravity.py +67 -0
- ostk/astrodynamics/test/dynamics/test_thruster.py +157 -0
- ostk/astrodynamics/test/eclipse/__init__.py +1 -0
- ostk/astrodynamics/test/eclipse/test_generator.py +138 -0
- ostk/astrodynamics/test/estimator/test_orbit_determination_solver.py +261 -0
- ostk/astrodynamics/test/estimator/test_tle_solver.py +216 -0
- ostk/astrodynamics/test/event_condition/test_angular_condition.py +113 -0
- ostk/astrodynamics/test/event_condition/test_boolean_condition.py +55 -0
- ostk/astrodynamics/test/event_condition/test_brouwer_lyddane_mean_long_condition.py +135 -0
- ostk/astrodynamics/test/event_condition/test_coe_condition.py +135 -0
- ostk/astrodynamics/test/event_condition/test_instant_condition.py +48 -0
- ostk/astrodynamics/test/event_condition/test_logical_condition.py +120 -0
- ostk/astrodynamics/test/event_condition/test_real_condition.py +50 -0
- ostk/astrodynamics/test/flight/__init__.py +1 -0
- ostk/astrodynamics/test/flight/profile/model/test_tabulated_profile.py +115 -0
- ostk/astrodynamics/test/flight/system/__init__.py +1 -0
- ostk/astrodynamics/test/flight/system/test_propulsion_system.py +64 -0
- ostk/astrodynamics/test/flight/system/test_satellite_system.py +83 -0
- ostk/astrodynamics/test/flight/system/test_satellite_system_builder.py +71 -0
- ostk/astrodynamics/test/flight/test_maneuver.py +231 -0
- ostk/astrodynamics/test/flight/test_profile.py +293 -0
- ostk/astrodynamics/test/flight/test_system.py +45 -0
- ostk/astrodynamics/test/guidance_law/test_constant_thrust.py +177 -0
- ostk/astrodynamics/test/guidance_law/test_guidance_law.py +60 -0
- ostk/astrodynamics/test/guidance_law/test_heterogeneous_guidance_law.py +164 -0
- ostk/astrodynamics/test/guidance_law/test_qlaw.py +209 -0
- ostk/astrodynamics/test/solvers/__init__.py +1 -0
- ostk/astrodynamics/test/solvers/test_finite_difference_solver.py +196 -0
- ostk/astrodynamics/test/solvers/test_least_squares_solver.py +334 -0
- ostk/astrodynamics/test/solvers/test_temporal_condition_solver.py +161 -0
- ostk/astrodynamics/test/test_access.py +128 -0
- ostk/astrodynamics/test/test_converters.py +290 -0
- ostk/astrodynamics/test/test_dataframe.py +1355 -0
- ostk/astrodynamics/test/test_display.py +184 -0
- ostk/astrodynamics/test/test_event_condition.py +80 -0
- ostk/astrodynamics/test/test_import.py +26 -0
- ostk/astrodynamics/test/test_root_solver.py +70 -0
- ostk/astrodynamics/test/test_trajectory.py +126 -0
- ostk/astrodynamics/test/test_utilities.py +338 -0
- ostk/astrodynamics/test/test_viewer.py +318 -0
- ostk/astrodynamics/test/trajectory/__init__.py +1 -0
- ostk/astrodynamics/test/trajectory/model/test_nadir_trajectory.py +87 -0
- ostk/astrodynamics/test/trajectory/model/test_tabulated_trajectory.py +303 -0
- ostk/astrodynamics/test/trajectory/model/test_target_scan_trajectory.py +126 -0
- ostk/astrodynamics/test/trajectory/orbit/__init__.py +1 -0
- ostk/astrodynamics/test/trajectory/orbit/message/__init__.py +1 -0
- ostk/astrodynamics/test/trajectory/orbit/message/spacex/__init__.py +1 -0
- ostk/astrodynamics/test/trajectory/orbit/message/spacex/conftest.py +18 -0
- ostk/astrodynamics/test/trajectory/orbit/message/spacex/data/opm_1.yaml +44 -0
- ostk/astrodynamics/test/trajectory/orbit/message/spacex/test_opm.py +108 -0
- ostk/astrodynamics/test/trajectory/orbit/models/__init__.py +1 -0
- ostk/astrodynamics/test/trajectory/orbit/models/kepler/__init__.py +1 -0
- ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean.py +65 -0
- ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean_long.py +102 -0
- ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean_short.py +102 -0
- ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_coe.py +305 -0
- ostk/astrodynamics/test/trajectory/orbit/models/sgp4/__init__.py +1 -0
- ostk/astrodynamics/test/trajectory/orbit/models/sgp4/test_tle.py +337 -0
- ostk/astrodynamics/test/trajectory/orbit/models/test_kepler.py +130 -0
- ostk/astrodynamics/test/trajectory/orbit/models/test_modified_equinoctial.py +142 -0
- ostk/astrodynamics/test/trajectory/orbit/models/test_propagated.py +234 -0
- ostk/astrodynamics/test/trajectory/orbit/models/test_sgp4.py +1 -0
- ostk/astrodynamics/test/trajectory/orbit/models/test_tabulated.py +380 -0
- ostk/astrodynamics/test/trajectory/orbit/test_model.py +1 -0
- ostk/astrodynamics/test/trajectory/orbit/test_pass.py +75 -0
- ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_angular_velocity.py +30 -0
- ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_attitude_quaternion.py +18 -0
- ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_acceleration.py +136 -0
- ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_position.py +107 -0
- ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_velocity.py +115 -0
- ostk/astrodynamics/test/trajectory/state/test_coordinate_broker.py +84 -0
- ostk/astrodynamics/test/trajectory/state/test_coordinate_subset.py +58 -0
- ostk/astrodynamics/test/trajectory/state/test_numerical_solver.py +316 -0
- ostk/astrodynamics/test/trajectory/test_local_orbital_frame_direction.py +81 -0
- ostk/astrodynamics/test/trajectory/test_local_orbital_frame_factory.py +119 -0
- ostk/astrodynamics/test/trajectory/test_model.py +1 -0
- ostk/astrodynamics/test/trajectory/test_orbit.py +212 -0
- ostk/astrodynamics/test/trajectory/test_propagator.py +452 -0
- ostk/astrodynamics/test/trajectory/test_segment.py +694 -0
- ostk/astrodynamics/test/trajectory/test_sequence.py +550 -0
- ostk/astrodynamics/test/trajectory/test_state.py +629 -0
- ostk/astrodynamics/test/trajectory/test_state_builder.py +172 -0
- ostk/astrodynamics/trajectory/__init__.pyi +1982 -0
- ostk/astrodynamics/trajectory/model.pyi +259 -0
- ostk/astrodynamics/trajectory/orbit/__init__.pyi +349 -0
- ostk/astrodynamics/trajectory/orbit/message/__init__.pyi +3 -0
- ostk/astrodynamics/trajectory/orbit/message/spacex.pyi +264 -0
- ostk/astrodynamics/trajectory/orbit/model/__init__.pyi +648 -0
- ostk/astrodynamics/trajectory/orbit/model/brouwerLyddaneMean.pyi +121 -0
- ostk/astrodynamics/trajectory/orbit/model/kepler.pyi +709 -0
- ostk/astrodynamics/trajectory/orbit/model/sgp4.pyi +330 -0
- ostk/astrodynamics/trajectory/state/__init__.pyi +402 -0
- ostk/astrodynamics/trajectory/state/coordinate_subset.pyi +208 -0
- ostk/astrodynamics/utilities.py +396 -0
- 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))
|
|
File without changes
|