open-space-toolkit-astrodynamics 1.2.1__py310-none-any.whl → 4.2.0__py310-none-any.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-1.2.1.dist-info → open_space_toolkit_astrodynamics-4.2.0.dist-info}/METADATA +2 -2
- open_space_toolkit_astrodynamics-4.2.0.dist-info/RECORD +25 -0
- ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-310-x86_64-linux-gnu.so +0 -0
- ostk/astrodynamics/__init__.py +6 -0
- ostk/astrodynamics/{libopen-space-toolkit-astrodynamics.so.1 → libopen-space-toolkit-astrodynamics.so.4} +0 -0
- ostk/astrodynamics/pytrajectory/pystate.py +36 -0
- ostk/astrodynamics/test/test_access.py +2 -6
- ostk/astrodynamics/test/test_converters.py +1 -3
- ostk/astrodynamics/test/test_event_condition.py +24 -41
- ostk/astrodynamics/test/test_import.py +3 -3
- ostk/astrodynamics/test/test_viewer.py +1 -2
- ostk/astrodynamics/viewer.py +1 -1
- open_space_toolkit_astrodynamics-1.2.1.dist-info/RECORD +0 -72
- ostk/astrodynamics/test/access/__init__.py +0 -1
- ostk/astrodynamics/test/access/test_generator.py +0 -248
- ostk/astrodynamics/test/conjunction/messages/ccsds/__init__.py +0 -1
- ostk/astrodynamics/test/conjunction/messages/ccsds/conftest.py +0 -325
- ostk/astrodynamics/test/conjunction/messages/ccsds/data/cdm.json +0 -303
- ostk/astrodynamics/test/conjunction/messages/ccsds/test_cdm.py +0 -418
- ostk/astrodynamics/test/event_condition/test_coe_condition.py +0 -95
- ostk/astrodynamics/test/event_condition/test_conjunctive.py +0 -64
- ostk/astrodynamics/test/event_condition/test_disjunctive.py +0 -63
- ostk/astrodynamics/test/event_condition/test_duration_condition.py +0 -36
- ostk/astrodynamics/test/event_condition/test_logical_connective.py +0 -37
- ostk/astrodynamics/test/flight/__init__.py +0 -1
- ostk/astrodynamics/test/flight/profile/__init__.py +0 -1
- ostk/astrodynamics/test/flight/profile/test_state.py +0 -144
- ostk/astrodynamics/test/flight/system/__init__.py +0 -1
- ostk/astrodynamics/test/flight/system/dynamics/__init__.py +0 -1
- ostk/astrodynamics/test/flight/system/dynamics/test_atmospheric_drag.py +0 -86
- ostk/astrodynamics/test/flight/system/dynamics/test_central_body_gravity.py +0 -57
- ostk/astrodynamics/test/flight/system/dynamics/test_position_derivative.py +0 -49
- ostk/astrodynamics/test/flight/system/dynamics/test_third_body_gravity.py +0 -65
- ostk/astrodynamics/test/flight/system/test_satellite_system.py +0 -77
- ostk/astrodynamics/test/flight/test_profile.py +0 -147
- ostk/astrodynamics/test/flight/test_system.py +0 -55
- ostk/astrodynamics/test/solvers/__init__.py +0 -1
- ostk/astrodynamics/test/solvers/test_temporal_condition_solver.py +0 -153
- ostk/astrodynamics/test/test_numerical_solver.py +0 -248
- ostk/astrodynamics/test/trajectory/__init__.py +0 -1
- ostk/astrodynamics/test/trajectory/orbit/__init__.py +0 -1
- ostk/astrodynamics/test/trajectory/orbit/messages/__init__.py +0 -1
- ostk/astrodynamics/test/trajectory/orbit/messages/spacex/__init__.py +0 -1
- ostk/astrodynamics/test/trajectory/orbit/messages/spacex/conftest.py +0 -18
- ostk/astrodynamics/test/trajectory/orbit/messages/spacex/data/opm_1.yaml +0 -44
- ostk/astrodynamics/test/trajectory/orbit/messages/spacex/test_opm.py +0 -108
- ostk/astrodynamics/test/trajectory/orbit/models/__init__.py +0 -1
- ostk/astrodynamics/test/trajectory/orbit/models/kepler/__init__.py +0 -1
- ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_coe.py +0 -108
- ostk/astrodynamics/test/trajectory/orbit/models/sgp4/__init__.py +0 -1
- ostk/astrodynamics/test/trajectory/orbit/models/sgp4/test_tle.py +0 -332
- ostk/astrodynamics/test/trajectory/orbit/models/test_kepler.py +0 -130
- ostk/astrodynamics/test/trajectory/orbit/models/test_propagated.py +0 -197
- ostk/astrodynamics/test/trajectory/orbit/models/test_sgp4.py +0 -1
- ostk/astrodynamics/test/trajectory/orbit/models/test_tabulated.py +0 -383
- ostk/astrodynamics/test/trajectory/orbit/test_model.py +0 -1
- ostk/astrodynamics/test/trajectory/orbit/test_pass.py +0 -55
- ostk/astrodynamics/test/trajectory/test_model.py +0 -1
- ostk/astrodynamics/test/trajectory/test_orbit.py +0 -92
- ostk/astrodynamics/test/trajectory/test_propagator.py +0 -233
- ostk/astrodynamics/test/trajectory/test_state.py +0 -70
- {open_space_toolkit_astrodynamics-1.2.1.dist-info → open_space_toolkit_astrodynamics-4.2.0.dist-info}/WHEEL +0 -0
- {open_space_toolkit_astrodynamics-1.2.1.dist-info → open_space_toolkit_astrodynamics-4.2.0.dist-info}/top_level.txt +0 -0
- {open_space_toolkit_astrodynamics-1.2.1.dist-info → open_space_toolkit_astrodynamics-4.2.0.dist-info}/zip-safe +0 -0
- /ostk/{__init__.py → astrodynamics/pytrajectory/__init__.py} +0 -0
@@ -1,55 +0,0 @@
|
|
1
|
-
# Apache License 2.0
|
2
|
-
|
3
|
-
import pytest
|
4
|
-
|
5
|
-
import numpy as np
|
6
|
-
|
7
|
-
import ostk.mathematics as mathematics
|
8
|
-
|
9
|
-
import ostk.physics as physics
|
10
|
-
|
11
|
-
import ostk.astrodynamics as astrodynamics
|
12
|
-
|
13
|
-
Cuboid = mathematics.geometry.d3.objects.Cuboid
|
14
|
-
Composite = mathematics.geometry.d3.objects.Composite
|
15
|
-
Point = mathematics.geometry.d3.objects.Point
|
16
|
-
|
17
|
-
Mass = physics.units.Mass
|
18
|
-
|
19
|
-
System = astrodynamics.flight.System
|
20
|
-
|
21
|
-
|
22
|
-
@pytest.fixture
|
23
|
-
def system_default_inputs():
|
24
|
-
mass = Mass(90.0, Mass.Unit.Kilogram)
|
25
|
-
geometry = Composite(
|
26
|
-
Cuboid(
|
27
|
-
Point(0.0, 0.0, 0.0),
|
28
|
-
[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]],
|
29
|
-
[1.0, 0.0, 0.0],
|
30
|
-
)
|
31
|
-
)
|
32
|
-
|
33
|
-
return (mass, geometry)
|
34
|
-
|
35
|
-
|
36
|
-
@pytest.fixture
|
37
|
-
def system(system_default_inputs) -> System:
|
38
|
-
return System(*system_default_inputs)
|
39
|
-
|
40
|
-
|
41
|
-
class TestSatelliteSystem:
|
42
|
-
def test_constructors(self, system: System):
|
43
|
-
assert system is not None
|
44
|
-
assert isinstance(system, System)
|
45
|
-
assert system.is_defined()
|
46
|
-
|
47
|
-
def test_comparators(self, system: System):
|
48
|
-
assert (system == system) is True
|
49
|
-
assert (system != system) is False
|
50
|
-
|
51
|
-
def test_getters(self, system_default_inputs, system: System):
|
52
|
-
(mass, geometry) = system_default_inputs
|
53
|
-
|
54
|
-
assert system.get_mass() == mass
|
55
|
-
assert system.get_geometry() == geometry
|
@@ -1 +0,0 @@
|
|
1
|
-
# Apache License 2.0
|
@@ -1,153 +0,0 @@
|
|
1
|
-
# Apache License 2.0
|
2
|
-
|
3
|
-
import pytest
|
4
|
-
|
5
|
-
from ostk.physics.units import Length
|
6
|
-
from ostk.physics.units import Angle
|
7
|
-
from ostk.physics.time import Instant
|
8
|
-
from ostk.physics.time import Duration
|
9
|
-
from ostk.physics.time import Interval
|
10
|
-
from ostk.physics.time import DateTime
|
11
|
-
from ostk.physics.time import Scale
|
12
|
-
from ostk.physics import Environment
|
13
|
-
|
14
|
-
from ostk.astrodynamics.trajectory import Orbit
|
15
|
-
from ostk.astrodynamics.trajectory.orbit.models import Kepler
|
16
|
-
from ostk.astrodynamics.trajectory.orbit.models.kepler import COE
|
17
|
-
from ostk.astrodynamics.access import Generator
|
18
|
-
from ostk.astrodynamics.solvers import TemporalConditionSolver
|
19
|
-
|
20
|
-
|
21
|
-
@pytest.fixture
|
22
|
-
def temporal_condition_solver() -> TemporalConditionSolver:
|
23
|
-
return TemporalConditionSolver(
|
24
|
-
time_step=Duration.seconds(30.0),
|
25
|
-
tolerance=Duration.milliseconds(1.0),
|
26
|
-
maximum_iteration_count=1234,
|
27
|
-
)
|
28
|
-
|
29
|
-
|
30
|
-
@pytest.fixture
|
31
|
-
def interval() -> Interval:
|
32
|
-
return Interval.closed(
|
33
|
-
Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC),
|
34
|
-
Instant.date_time(DateTime(2018, 1, 1, 2, 0, 0), Scale.UTC),
|
35
|
-
)
|
36
|
-
|
37
|
-
|
38
|
-
class TestTemporalConditionSolver:
|
39
|
-
def test_constructor_success(self):
|
40
|
-
temporal_condition_solver = TemporalConditionSolver(
|
41
|
-
time_step=Duration.seconds(30.0),
|
42
|
-
tolerance=Duration.milliseconds(1.0),
|
43
|
-
maximum_iteration_count=1234,
|
44
|
-
)
|
45
|
-
|
46
|
-
assert isinstance(temporal_condition_solver, TemporalConditionSolver)
|
47
|
-
|
48
|
-
def test_getters_success(
|
49
|
-
self,
|
50
|
-
temporal_condition_solver: TemporalConditionSolver,
|
51
|
-
):
|
52
|
-
assert temporal_condition_solver.get_time_step() == Duration.seconds(30.0)
|
53
|
-
assert temporal_condition_solver.get_tolerance() == Duration.milliseconds(1.0)
|
54
|
-
assert temporal_condition_solver.get_maximum_iteration_count() == 1234
|
55
|
-
|
56
|
-
def test_solve_success_one_condition_always_true(
|
57
|
-
self,
|
58
|
-
temporal_condition_solver: TemporalConditionSolver,
|
59
|
-
interval: Interval,
|
60
|
-
):
|
61
|
-
solution: list[Interval] = temporal_condition_solver.solve(
|
62
|
-
condition=lambda _: True,
|
63
|
-
interval=interval,
|
64
|
-
)
|
65
|
-
|
66
|
-
assert isinstance(solution, list)
|
67
|
-
assert solution == [interval]
|
68
|
-
|
69
|
-
def test_solve_success_one_condition_always_false(
|
70
|
-
self,
|
71
|
-
temporal_condition_solver: TemporalConditionSolver,
|
72
|
-
interval: Interval,
|
73
|
-
):
|
74
|
-
solution: list[Interval] = temporal_condition_solver.solve(
|
75
|
-
condition=lambda _: False,
|
76
|
-
interval=interval,
|
77
|
-
)
|
78
|
-
|
79
|
-
assert isinstance(solution, list)
|
80
|
-
assert solution == []
|
81
|
-
|
82
|
-
def test_solve_success_multiple_conditions_always_true(
|
83
|
-
self,
|
84
|
-
temporal_condition_solver: TemporalConditionSolver,
|
85
|
-
interval: Interval,
|
86
|
-
):
|
87
|
-
solution: list[Interval] = temporal_condition_solver.solve(
|
88
|
-
conditions=[
|
89
|
-
lambda _: True,
|
90
|
-
lambda _: True,
|
91
|
-
],
|
92
|
-
interval=interval,
|
93
|
-
)
|
94
|
-
|
95
|
-
assert isinstance(solution, list)
|
96
|
-
assert solution == [interval]
|
97
|
-
|
98
|
-
def test_solve_success_multiple_conditions_one_always_false(
|
99
|
-
self,
|
100
|
-
temporal_condition_solver: TemporalConditionSolver,
|
101
|
-
interval: Interval,
|
102
|
-
):
|
103
|
-
solution: list[Interval] = temporal_condition_solver.solve(
|
104
|
-
conditions=[
|
105
|
-
lambda _: True,
|
106
|
-
lambda _: False,
|
107
|
-
],
|
108
|
-
interval=interval,
|
109
|
-
)
|
110
|
-
|
111
|
-
assert isinstance(solution, list)
|
112
|
-
assert solution == []
|
113
|
-
|
114
|
-
def test_solve_success_using_access_generator(
|
115
|
-
self,
|
116
|
-
temporal_condition_solver: TemporalConditionSolver,
|
117
|
-
interval: Interval,
|
118
|
-
):
|
119
|
-
environment = Environment.default()
|
120
|
-
|
121
|
-
generator = Generator(
|
122
|
-
environment=environment,
|
123
|
-
)
|
124
|
-
|
125
|
-
earth = environment.access_celestial_object_with_name("Earth")
|
126
|
-
|
127
|
-
trajectory = Orbit(
|
128
|
-
model=Kepler(
|
129
|
-
coe=COE(
|
130
|
-
semi_major_axis=Length.kilometers(7000.0),
|
131
|
-
eccentricity=0.0,
|
132
|
-
inclination=Angle.degrees(45.0),
|
133
|
-
raan=Angle.degrees(0.0),
|
134
|
-
aop=Angle.degrees(0.0),
|
135
|
-
true_anomaly=Angle.degrees(0.0),
|
136
|
-
),
|
137
|
-
epoch=Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC),
|
138
|
-
celestial_object=earth,
|
139
|
-
perturbation_type=Kepler.PerturbationType.No,
|
140
|
-
),
|
141
|
-
celestial_object=earth,
|
142
|
-
)
|
143
|
-
|
144
|
-
solution: list[Interval] = temporal_condition_solver.solve(
|
145
|
-
condition=generator.get_condition_function(
|
146
|
-
from_trajectory=trajectory,
|
147
|
-
to_trajectory=trajectory,
|
148
|
-
),
|
149
|
-
interval=interval,
|
150
|
-
)
|
151
|
-
|
152
|
-
assert isinstance(solution, list)
|
153
|
-
assert solution == [interval]
|
@@ -1,248 +0,0 @@
|
|
1
|
-
# Apache License 2.0
|
2
|
-
|
3
|
-
import pytest
|
4
|
-
|
5
|
-
import numpy as np
|
6
|
-
import math
|
7
|
-
|
8
|
-
from ostk.astrodynamics import NumericalSolver, EventCondition
|
9
|
-
|
10
|
-
|
11
|
-
def oscillator(x, dxdt, _):
|
12
|
-
dxdt[0] = x[1]
|
13
|
-
dxdt[1] = -x[0]
|
14
|
-
return dxdt
|
15
|
-
|
16
|
-
|
17
|
-
def get_state_vec(time: float) -> np.ndarray:
|
18
|
-
return np.array([math.sin(time), math.cos(time)])
|
19
|
-
|
20
|
-
|
21
|
-
@pytest.fixture
|
22
|
-
def initial_state_vec() -> np.ndarray:
|
23
|
-
return get_state_vec(0.0)
|
24
|
-
|
25
|
-
|
26
|
-
@pytest.fixture
|
27
|
-
def custom_condition() -> EventCondition:
|
28
|
-
class CustomCondition(EventCondition):
|
29
|
-
def __init__(self, target: float, criteria: EventCondition.Criteria):
|
30
|
-
super().__init__("Custom", criteria)
|
31
|
-
self._target = target
|
32
|
-
|
33
|
-
def evaluate(self, state_vector, time: float) -> bool:
|
34
|
-
return time - self._target
|
35
|
-
|
36
|
-
return CustomCondition(5.0, EventCondition.Criteria.StrictlyPositive)
|
37
|
-
|
38
|
-
|
39
|
-
@pytest.fixture
|
40
|
-
def numerical_solver_default_inputs() -> (
|
41
|
-
tuple[NumericalSolver.LogType, NumericalSolver.StepperType, float, float, float]
|
42
|
-
):
|
43
|
-
log_type = NumericalSolver.LogType.NoLog
|
44
|
-
stepper_type = NumericalSolver.StepperType.RungeKuttaCashKarp54
|
45
|
-
initial_time_step = 5.0
|
46
|
-
relative_tolerance = 1.0e-15
|
47
|
-
absolute_tolerance = 1.0e-15
|
48
|
-
|
49
|
-
return (
|
50
|
-
log_type,
|
51
|
-
stepper_type,
|
52
|
-
initial_time_step,
|
53
|
-
relative_tolerance,
|
54
|
-
absolute_tolerance,
|
55
|
-
)
|
56
|
-
|
57
|
-
|
58
|
-
@pytest.fixture
|
59
|
-
def numerical_solver(numerical_solver_default_inputs) -> NumericalSolver:
|
60
|
-
return NumericalSolver(*numerical_solver_default_inputs)
|
61
|
-
|
62
|
-
|
63
|
-
@pytest.fixture
|
64
|
-
def numerical_solver_conditional() -> NumericalSolver:
|
65
|
-
return NumericalSolver(
|
66
|
-
NumericalSolver.LogType.NoLog,
|
67
|
-
NumericalSolver.StepperType.RungeKuttaDopri5,
|
68
|
-
5.0,
|
69
|
-
1.0e-15,
|
70
|
-
1.0e-15,
|
71
|
-
)
|
72
|
-
|
73
|
-
|
74
|
-
class TestNumericalSolver:
|
75
|
-
def test_constructors(self, numerical_solver: NumericalSolver):
|
76
|
-
assert numerical_solver is not None
|
77
|
-
assert isinstance(numerical_solver, NumericalSolver)
|
78
|
-
assert numerical_solver.is_defined()
|
79
|
-
|
80
|
-
numericalsolver_2: NumericalSolver = NumericalSolver(numerical_solver)
|
81
|
-
|
82
|
-
assert numericalsolver_2 is not None
|
83
|
-
assert isinstance(numericalsolver_2, NumericalSolver)
|
84
|
-
assert numericalsolver_2.is_defined()
|
85
|
-
|
86
|
-
def test_comparators(self, numerical_solver: NumericalSolver):
|
87
|
-
assert numerical_solver == numerical_solver
|
88
|
-
assert (numerical_solver != numerical_solver) is False
|
89
|
-
|
90
|
-
def test_get_types(
|
91
|
-
self,
|
92
|
-
numerical_solver_default_inputs: tuple[
|
93
|
-
NumericalSolver.LogType, NumericalSolver.StepperType, float, float, float
|
94
|
-
],
|
95
|
-
numerical_solver: NumericalSolver,
|
96
|
-
):
|
97
|
-
(
|
98
|
-
log_type,
|
99
|
-
stepper_type,
|
100
|
-
initial_time_step,
|
101
|
-
relative_tolerance,
|
102
|
-
absolute_tolerance,
|
103
|
-
) = numerical_solver_default_inputs
|
104
|
-
|
105
|
-
assert numerical_solver.get_log_type() == log_type
|
106
|
-
assert numerical_solver.get_stepper_type() == stepper_type
|
107
|
-
assert numerical_solver.get_time_step() == initial_time_step
|
108
|
-
assert numerical_solver.get_relative_tolerance() == relative_tolerance
|
109
|
-
assert numerical_solver.get_absolute_tolerance() == absolute_tolerance
|
110
|
-
assert numerical_solver.get_root_solver() is not None
|
111
|
-
|
112
|
-
def test_get_string_from_types(self):
|
113
|
-
assert (
|
114
|
-
NumericalSolver.string_from_stepper_type(
|
115
|
-
NumericalSolver.StepperType.RungeKutta4
|
116
|
-
)
|
117
|
-
== "RungeKutta4"
|
118
|
-
)
|
119
|
-
assert (
|
120
|
-
NumericalSolver.string_from_stepper_type(
|
121
|
-
NumericalSolver.StepperType.RungeKuttaCashKarp54
|
122
|
-
)
|
123
|
-
== "RungeKuttaCashKarp54"
|
124
|
-
)
|
125
|
-
assert (
|
126
|
-
NumericalSolver.string_from_stepper_type(
|
127
|
-
NumericalSolver.StepperType.RungeKuttaFehlberg78
|
128
|
-
)
|
129
|
-
== "RungeKuttaFehlberg78"
|
130
|
-
)
|
131
|
-
assert (
|
132
|
-
NumericalSolver.string_from_log_type(NumericalSolver.LogType.NoLog)
|
133
|
-
== "NoLog"
|
134
|
-
)
|
135
|
-
assert (
|
136
|
-
NumericalSolver.string_from_log_type(NumericalSolver.LogType.LogConstant)
|
137
|
-
== "LogConstant"
|
138
|
-
)
|
139
|
-
assert (
|
140
|
-
NumericalSolver.string_from_log_type(NumericalSolver.LogType.LogAdaptive)
|
141
|
-
== "LogAdaptive"
|
142
|
-
)
|
143
|
-
|
144
|
-
def test_integrate_duration(
|
145
|
-
self, numerical_solver: NumericalSolver, initial_state_vec: np.ndarray
|
146
|
-
):
|
147
|
-
integration_duration: float = 100.0
|
148
|
-
|
149
|
-
state_vector, _ = numerical_solver.integrate_duration(
|
150
|
-
initial_state_vec, integration_duration, oscillator
|
151
|
-
)
|
152
|
-
|
153
|
-
assert 5e-9 >= abs(state_vector[0] - math.sin(integration_duration))
|
154
|
-
assert 5e-9 >= abs(state_vector[1] - math.cos(integration_duration))
|
155
|
-
|
156
|
-
integration_durations = np.arange(100.0, 1000.0, 50.0)
|
157
|
-
solutions = numerical_solver.integrate_duration(
|
158
|
-
initial_state_vec, integration_durations, oscillator
|
159
|
-
)
|
160
|
-
|
161
|
-
for solution, integration_duration in zip(solutions, integration_durations):
|
162
|
-
state_vector, _ = solution
|
163
|
-
|
164
|
-
assert 5e-9 >= abs(state_vector[0] - math.sin(integration_duration))
|
165
|
-
assert 5e-9 >= abs(state_vector[1] - math.cos(integration_duration))
|
166
|
-
|
167
|
-
def test_integrate_time(self, numerical_solver: NumericalSolver):
|
168
|
-
start_time: float = 500.0
|
169
|
-
end_time: float = start_time + 100.0
|
170
|
-
|
171
|
-
initial_state_vec = get_state_vec(start_time)
|
172
|
-
|
173
|
-
state_vector, _ = numerical_solver.integrate_time(
|
174
|
-
initial_state_vec, start_time, end_time, oscillator
|
175
|
-
)
|
176
|
-
|
177
|
-
assert 5e-9 >= abs(state_vector[0] - math.sin(end_time))
|
178
|
-
assert 5e-9 >= abs(state_vector[1] - math.cos(end_time))
|
179
|
-
|
180
|
-
end_times = np.arange(600.0, 1000.0, 50.0)
|
181
|
-
solutions = numerical_solver.integrate_time(
|
182
|
-
initial_state_vec, start_time, end_times, oscillator
|
183
|
-
)
|
184
|
-
|
185
|
-
for solution, end_time in zip(solutions, end_times):
|
186
|
-
state_vector, _ = solution
|
187
|
-
|
188
|
-
assert 5e-9 >= abs(state_vector[0] - math.sin(end_time))
|
189
|
-
assert 5e-9 >= abs(state_vector[1] - math.cos(end_time))
|
190
|
-
|
191
|
-
def test_integrate_duration_with_condition(
|
192
|
-
self,
|
193
|
-
numerical_solver_conditional: NumericalSolver,
|
194
|
-
initial_state_vec: np.ndarray,
|
195
|
-
custom_condition: EventCondition,
|
196
|
-
):
|
197
|
-
integration_duration: float = 100.0
|
198
|
-
|
199
|
-
condition_solution = numerical_solver_conditional.integrate_duration(
|
200
|
-
initial_state_vec, integration_duration, oscillator, custom_condition
|
201
|
-
)
|
202
|
-
|
203
|
-
assert condition_solution.condition_is_satisfied
|
204
|
-
assert (
|
205
|
-
condition_solution.iteration_count
|
206
|
-
< numerical_solver_conditional.get_root_solver().get_maximum_iteration_count()
|
207
|
-
)
|
208
|
-
|
209
|
-
state_vector, time = condition_solution.solution
|
210
|
-
|
211
|
-
assert abs(time - custom_condition._target) < 1e-6
|
212
|
-
|
213
|
-
assert 5e-9 >= abs(state_vector[0] - math.sin(time))
|
214
|
-
assert 5e-9 >= abs(state_vector[1] - math.cos(time))
|
215
|
-
|
216
|
-
def test_integrate_time_with_condition(
|
217
|
-
self,
|
218
|
-
numerical_solver_conditional: NumericalSolver,
|
219
|
-
custom_condition: EventCondition,
|
220
|
-
):
|
221
|
-
start_time: float = 500.0
|
222
|
-
end_time: float = start_time + 100.0
|
223
|
-
|
224
|
-
initial_state_vec = get_state_vec(start_time)
|
225
|
-
|
226
|
-
condition_solution = numerical_solver_conditional.integrate_time(
|
227
|
-
initial_state_vec, start_time, end_time, oscillator, custom_condition
|
228
|
-
)
|
229
|
-
|
230
|
-
assert condition_solution.condition_is_satisfied
|
231
|
-
assert (
|
232
|
-
condition_solution.iteration_count
|
233
|
-
< numerical_solver_conditional.get_root_solver().get_maximum_iteration_count()
|
234
|
-
)
|
235
|
-
|
236
|
-
state_vector, time = condition_solution.solution
|
237
|
-
|
238
|
-
assert abs(time - start_time - custom_condition._target) < 1e-6
|
239
|
-
|
240
|
-
assert 5e-9 >= abs(state_vector[0] - math.sin(time))
|
241
|
-
assert 5e-9 >= abs(state_vector[1] - math.cos(time))
|
242
|
-
|
243
|
-
def test_default(self):
|
244
|
-
assert NumericalSolver.default() is not None
|
245
|
-
|
246
|
-
def test_undefined(self):
|
247
|
-
assert NumericalSolver.undefined() is not None
|
248
|
-
assert NumericalSolver.undefined().is_defined() is False
|
@@ -1 +0,0 @@
|
|
1
|
-
# Apache License 2.0
|
@@ -1 +0,0 @@
|
|
1
|
-
# Apache License 2.0
|
@@ -1 +0,0 @@
|
|
1
|
-
# Apache License 2.0
|
@@ -1 +0,0 @@
|
|
1
|
-
# Apache License 2.0
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# Apache License 2.0
|
2
|
-
|
3
|
-
import pytest
|
4
|
-
|
5
|
-
import pathlib
|
6
|
-
|
7
|
-
from ostk.core.filesystem import Path
|
8
|
-
from ostk.core.filesystem import File
|
9
|
-
|
10
|
-
|
11
|
-
@pytest.fixture
|
12
|
-
def data_directory_path() -> str:
|
13
|
-
return f"{pathlib.Path(__file__).parent.absolute()}/data"
|
14
|
-
|
15
|
-
|
16
|
-
@pytest.fixture
|
17
|
-
def opm_file(data_directory_path: str) -> File:
|
18
|
-
return File.path(Path.parse(f"{data_directory_path}/opm_1.yaml"))
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# Dummy SpaceX OPM output
|
2
|
-
|
3
|
-
# Notes:
|
4
|
-
# - ECEF velocity is Earth relative
|
5
|
-
# - Apogee/Perigee altitude assumes a spherical Earth, 6378.137 km radius
|
6
|
-
# - Orbital elements are computed in an inertial frame realized by inertially
|
7
|
-
# freezing the WGS84 ECEF frame at time of current state
|
8
|
-
# - State is post-deployment, so includes separation delta-velocity
|
9
|
-
|
10
|
-
|
11
|
-
header:
|
12
|
-
generation_date: 2020-01-01T12:34:56.789Z
|
13
|
-
launch_date: 2020-01-02T12:34:56.789Z
|
14
|
-
|
15
|
-
|
16
|
-
deployments:
|
17
|
-
|
18
|
-
- name: satellite_a
|
19
|
-
sequence_number: 1
|
20
|
-
mission_time_s: 3600.0
|
21
|
-
date: 2020-01-02T13:34:56.789Z
|
22
|
-
r_ecef_m: [693289.644, 6876578.628, -133035.288]
|
23
|
-
v_ecef_m_per_s: [1305.783, 39.783, 7525.920]
|
24
|
-
mean_perigee_altitude_km: 526.768
|
25
|
-
mean_apogee_altitude_km: 568.430
|
26
|
-
mean_inclination_deg: 97.123
|
27
|
-
mean_argument_of_perigee_deg: -179.513
|
28
|
-
mean_longitude_ascending_node_deg: 85.057
|
29
|
-
mean_mean_anomaly_deg: 179.263
|
30
|
-
ballistic_coef_kg_per_m2: 47.55
|
31
|
-
|
32
|
-
- name: satellite_b
|
33
|
-
sequence_number: 2
|
34
|
-
mission_time_s: 7200.0
|
35
|
-
date: 2020-01-02T14:34:56.789Z
|
36
|
-
r_ecef_m: [699863.059, 6875647.517, -123777.595]
|
37
|
-
v_ecef_m_per_s: [1504.658, 6.705, 7538.669]
|
38
|
-
mean_perigee_altitude_km: 536.779
|
39
|
-
mean_apogee_altitude_km: 529.851
|
40
|
-
mean_inclination_deg: 97.124
|
41
|
-
mean_argument_of_perigee_deg: 136.875
|
42
|
-
mean_longitude_ascending_node_deg: 85.032
|
43
|
-
mean_mean_anomaly_deg: -127.164
|
44
|
-
ballistic_coef_kg_per_m2: 44.26
|
@@ -1,108 +0,0 @@
|
|
1
|
-
# Apache License 2.0
|
2
|
-
|
3
|
-
import pytest
|
4
|
-
|
5
|
-
from datetime import datetime
|
6
|
-
|
7
|
-
from ostk.core.containers import Dictionary
|
8
|
-
from ostk.core.filesystem import Path
|
9
|
-
from ostk.core.filesystem import File
|
10
|
-
|
11
|
-
from ostk.physics.units import Length
|
12
|
-
from ostk.physics.units import Angle
|
13
|
-
from ostk.physics.time import Instant
|
14
|
-
from ostk.physics.time import Scale
|
15
|
-
from ostk.physics.time import Duration
|
16
|
-
from ostk.physics.coordinate import Position
|
17
|
-
from ostk.physics.coordinate import Velocity
|
18
|
-
from ostk.physics.coordinate import Frame
|
19
|
-
|
20
|
-
from ostk.astrodynamics.trajectory.orbit.messages.spacex import OPM
|
21
|
-
|
22
|
-
|
23
|
-
@pytest.fixture
|
24
|
-
def opm() -> OPM:
|
25
|
-
return OPM(
|
26
|
-
header=OPM.Header(
|
27
|
-
generation_date=Instant.date_time(datetime(2020, 1, 2, 3, 4, 5), Scale.UTC),
|
28
|
-
launch_date=Instant.date_time(datetime(2020, 1, 3, 3, 4, 5), Scale.UTC),
|
29
|
-
),
|
30
|
-
deployments=[
|
31
|
-
OPM.Deployment(
|
32
|
-
name="A",
|
33
|
-
sequence_number=1,
|
34
|
-
mission_time=Duration.hours(3600.0),
|
35
|
-
date=Instant.date_time(datetime(2020, 1, 4, 3, 4, 5), Scale.UTC),
|
36
|
-
position=Position.meters((1.0, 2.0, 3.0), Frame.ITRF()),
|
37
|
-
velocity=Velocity.meters_per_second((4.0, 5.0, 6.0), Frame.ITRF()),
|
38
|
-
mean_perigee_altitude=Length.kilometers(500.0),
|
39
|
-
mean_apogee_altitude=Length.kilometers(500.0),
|
40
|
-
mean_inclination=Angle.degrees(1.0),
|
41
|
-
mean_argument_of_perigee=Angle.degrees(2.0),
|
42
|
-
mean_longitude_ascending_node=Angle.degrees(3.0),
|
43
|
-
mean_mean_anomaly=Angle.degrees(4.0),
|
44
|
-
ballistic_coefficient=123.456,
|
45
|
-
),
|
46
|
-
],
|
47
|
-
)
|
48
|
-
|
49
|
-
|
50
|
-
class TestOPM:
|
51
|
-
def test_constructor(self, opm: OPM):
|
52
|
-
assert opm is not None
|
53
|
-
|
54
|
-
def test_get_header(self, opm: OPM):
|
55
|
-
assert opm.get_header() is not None
|
56
|
-
|
57
|
-
def test_get_deployments(self, opm: OPM):
|
58
|
-
assert len(opm.get_deployments()) == 1
|
59
|
-
|
60
|
-
def test_get_deployment_at(self, opm: OPM):
|
61
|
-
assert opm.get_deployment_at(index=0).name == "A"
|
62
|
-
|
63
|
-
def test_get_deployment_with_name(self, opm: OPM):
|
64
|
-
assert opm.get_deployment_with_name(name="A").name == "A"
|
65
|
-
|
66
|
-
def test_undefined(self):
|
67
|
-
assert OPM.undefined().is_defined() is False
|
68
|
-
|
69
|
-
def test_dictionary(self):
|
70
|
-
dictionary = Dictionary(
|
71
|
-
{
|
72
|
-
"header": {
|
73
|
-
"generation_date": "2020-01-01T12:34:56.789Z",
|
74
|
-
"launch_date": "2020-01-02T12:34:56.789Z",
|
75
|
-
},
|
76
|
-
"deployments": [
|
77
|
-
{
|
78
|
-
"name": "satellite_a",
|
79
|
-
"sequence_number": 1,
|
80
|
-
"mission_time_s": 3600.0,
|
81
|
-
"date": "2020-01-02T13:34:56.789Z",
|
82
|
-
"r_ecef_m": [693289.644, 6876578.628, -133035.288],
|
83
|
-
"v_ecef_m_per_s": [1305.783, 39.783, 7525.920],
|
84
|
-
"mean_perigee_altitude_km": 526.768,
|
85
|
-
"mean_apogee_altitude_km": 568.430,
|
86
|
-
"mean_inclination_deg": 97.123,
|
87
|
-
"mean_argument_of_perigee_deg": -179.513,
|
88
|
-
"mean_longitude_ascending_node_deg": 85.057,
|
89
|
-
"mean_mean_anomaly_deg": 179.263,
|
90
|
-
"ballistic_coef_kg_per_m2": 47.55,
|
91
|
-
}
|
92
|
-
],
|
93
|
-
}
|
94
|
-
)
|
95
|
-
|
96
|
-
assert OPM.dictionary(dictionary) is not None
|
97
|
-
|
98
|
-
def test_parse(self, opm_file: File):
|
99
|
-
with open(str(opm_file.get_path().to_string()), "r") as stream:
|
100
|
-
assert OPM.parse(string=stream.read()) is not None
|
101
|
-
|
102
|
-
def test_load(self, opm_file: File):
|
103
|
-
assert OPM.load(file=opm_file) is not None
|
104
|
-
|
105
|
-
|
106
|
-
class TestOPMDeployment:
|
107
|
-
def test_to_state(self, opm: OPM):
|
108
|
-
assert opm.get_deployment_with_name(name="A").to_state() is not None
|
@@ -1 +0,0 @@
|
|
1
|
-
# Apache License 2.0
|
@@ -1 +0,0 @@
|
|
1
|
-
# Apache License 2.0
|