open-space-toolkit-astrodynamics 12.2.1__py312-none-manylinux2014_aarch64.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-12.2.1.dist-info/METADATA +30 -0
- open_space_toolkit_astrodynamics-12.2.1.dist-info/RECORD +100 -0
- open_space_toolkit_astrodynamics-12.2.1.dist-info/WHEEL +5 -0
- open_space_toolkit_astrodynamics-12.2.1.dist-info/top_level.txt +1 -0
- open_space_toolkit_astrodynamics-12.2.1.dist-info/zip-safe +1 -0
- ostk/__init__.py +1 -0
- ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-312-aarch64-linux-gnu.so +0 -0
- ostk/astrodynamics/__init__.py +11 -0
- ostk/astrodynamics/converters.py +128 -0
- ostk/astrodynamics/dataframe.py +477 -0
- ostk/astrodynamics/display.py +220 -0
- ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.12 +0 -0
- ostk/astrodynamics/pytrajectory/__init__.py +1 -0
- ostk/astrodynamics/pytrajectory/pystate.py +220 -0
- ostk/astrodynamics/test/__init__.py +1 -0
- ostk/astrodynamics/test/access/__init__.py +1 -0
- ostk/astrodynamics/test/access/test_generator.py +248 -0
- ostk/astrodynamics/test/conftest.py +119 -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/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 +142 -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_coe_condition.py +87 -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/system/__init__.py +1 -0
- ostk/astrodynamics/test/flight/system/test_propulsion_system.py +73 -0
- ostk/astrodynamics/test/flight/system/test_satellite_system.py +91 -0
- ostk/astrodynamics/test/flight/system/test_satellite_system_builder.py +71 -0
- ostk/astrodynamics/test/flight/test_maneuver.py +212 -0
- ostk/astrodynamics/test/flight/test_profile.py +242 -0
- ostk/astrodynamics/test/flight/test_system.py +55 -0
- ostk/astrodynamics/test/guidance_law/test_constant_thrust.py +91 -0
- ostk/astrodynamics/test/guidance_law/test_qlaw.py +138 -0
- ostk/astrodynamics/test/solvers/__init__.py +1 -0
- ostk/astrodynamics/test/solvers/test_finite_difference_solver.py +181 -0
- ostk/astrodynamics/test/solvers/test_temporal_condition_solver.py +153 -0
- ostk/astrodynamics/test/test_access.py +128 -0
- ostk/astrodynamics/test/test_converters.py +290 -0
- ostk/astrodynamics/test/test_dataframe.py +875 -0
- ostk/astrodynamics/test/test_display.py +114 -0
- ostk/astrodynamics/test/test_event_condition.py +58 -0
- ostk/astrodynamics/test/test_import.py +26 -0
- ostk/astrodynamics/test/test_root_solver.py +70 -0
- ostk/astrodynamics/test/test_trajectory.py +118 -0
- ostk/astrodynamics/test/test_utilities.py +106 -0
- ostk/astrodynamics/test/test_viewer.py +129 -0
- ostk/astrodynamics/test/trajectory/__init__.py +1 -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 +180 -0
- ostk/astrodynamics/test/trajectory/orbit/models/sgp4/__init__.py +1 -0
- ostk/astrodynamics/test/trajectory/orbit/models/sgp4/test_tle.py +331 -0
- ostk/astrodynamics/test/trajectory/orbit/models/test_kepler.py +130 -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_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 +46 -0
- ostk/astrodynamics/test/trajectory/state/test_numerical_solver.py +314 -0
- ostk/astrodynamics/test/trajectory/test_local_orbital_frame_direction.py +81 -0
- ostk/astrodynamics/test/trajectory/test_local_orbital_frame_factory.py +108 -0
- ostk/astrodynamics/test/trajectory/test_model.py +1 -0
- ostk/astrodynamics/test/trajectory/test_orbit.py +196 -0
- ostk/astrodynamics/test/trajectory/test_propagator.py +458 -0
- ostk/astrodynamics/test/trajectory/test_segment.py +305 -0
- ostk/astrodynamics/test/trajectory/test_sequence.py +477 -0
- ostk/astrodynamics/test/trajectory/test_state.py +467 -0
- ostk/astrodynamics/test/trajectory/test_state_builder.py +171 -0
- ostk/astrodynamics/utilities.py +245 -0
- ostk/astrodynamics/viewer.py +392 -0
@@ -0,0 +1,142 @@
|
|
1
|
+
# Apache License 2.0
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
import numpy as np
|
6
|
+
|
7
|
+
from ostk.mathematics.geometry.d3.object import Cuboid
|
8
|
+
from ostk.mathematics.geometry.d3.object import Composite
|
9
|
+
from ostk.mathematics.geometry.d3.object import Point
|
10
|
+
|
11
|
+
from ostk.physics.unit import Mass
|
12
|
+
from ostk.physics.time import Instant
|
13
|
+
from ostk.physics.time import DateTime
|
14
|
+
from ostk.physics.time import Scale
|
15
|
+
from ostk.physics.coordinate import Frame
|
16
|
+
|
17
|
+
from ostk.astrodynamics.trajectory.state import CoordinateSubset
|
18
|
+
from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianPosition
|
19
|
+
from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianVelocity
|
20
|
+
from ostk.astrodynamics.trajectory.state import CoordinateBroker
|
21
|
+
|
22
|
+
from ostk.astrodynamics.trajectory import State
|
23
|
+
from ostk.astrodynamics.flight.system import PropulsionSystem
|
24
|
+
from ostk.astrodynamics.flight.system import SatelliteSystem
|
25
|
+
from ostk.astrodynamics import Dynamics
|
26
|
+
from ostk.astrodynamics.dynamics import Thruster
|
27
|
+
from ostk.astrodynamics.guidance_law import ConstantThrust
|
28
|
+
|
29
|
+
|
30
|
+
@pytest.fixture
|
31
|
+
def guidance_law() -> ConstantThrust:
|
32
|
+
return ConstantThrust.intrack(True)
|
33
|
+
|
34
|
+
|
35
|
+
@pytest.fixture
|
36
|
+
def propulsion_system() -> PropulsionSystem:
|
37
|
+
return PropulsionSystem(
|
38
|
+
1.0,
|
39
|
+
150.0,
|
40
|
+
)
|
41
|
+
|
42
|
+
|
43
|
+
@pytest.fixture
|
44
|
+
def satellite_system(propulsion_system: PropulsionSystem) -> SatelliteSystem:
|
45
|
+
mass = Mass(100.0, Mass.Unit.Kilogram)
|
46
|
+
satellite_geometry = Composite(
|
47
|
+
Cuboid(
|
48
|
+
Point(0.0, 0.0, 0.0),
|
49
|
+
[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]],
|
50
|
+
[1.0, 0.0, 0.0],
|
51
|
+
)
|
52
|
+
)
|
53
|
+
inertia_tensor = np.ndarray(shape=(3, 3))
|
54
|
+
surface_area = 0.8
|
55
|
+
drag_coefficient = 2.1
|
56
|
+
|
57
|
+
return SatelliteSystem(
|
58
|
+
mass,
|
59
|
+
satellite_geometry,
|
60
|
+
inertia_tensor,
|
61
|
+
surface_area,
|
62
|
+
drag_coefficient,
|
63
|
+
propulsion_system,
|
64
|
+
)
|
65
|
+
|
66
|
+
|
67
|
+
@pytest.fixture
|
68
|
+
def dynamics(
|
69
|
+
satellite_system: SatelliteSystem,
|
70
|
+
guidance_law: ConstantThrust,
|
71
|
+
) -> Thruster:
|
72
|
+
return Thruster(
|
73
|
+
satellite_system=satellite_system,
|
74
|
+
guidance_law=guidance_law,
|
75
|
+
name="Constant Thrust Thruster Dynamics",
|
76
|
+
)
|
77
|
+
|
78
|
+
|
79
|
+
@pytest.fixture
|
80
|
+
def coordinate_broker() -> CoordinateBroker:
|
81
|
+
return CoordinateBroker(
|
82
|
+
[
|
83
|
+
CartesianPosition.default(),
|
84
|
+
CartesianVelocity.default(),
|
85
|
+
CoordinateSubset.mass(),
|
86
|
+
]
|
87
|
+
)
|
88
|
+
|
89
|
+
|
90
|
+
@pytest.fixture
|
91
|
+
def state(coordinate_broker: CoordinateBroker) -> State:
|
92
|
+
instant: Instant = Instant.date_time(DateTime(2021, 3, 20, 12, 0, 0), Scale.UTC)
|
93
|
+
coordinates: list = [7000000.0, 0.0, 0.0, 0.0, 7546.05329, 0.0, 105.0]
|
94
|
+
|
95
|
+
return State(instant, coordinates, Frame.GCRF(), coordinate_broker)
|
96
|
+
|
97
|
+
|
98
|
+
class TestThruster:
|
99
|
+
def test_constructors(self, dynamics: Thruster):
|
100
|
+
assert dynamics is not None
|
101
|
+
assert isinstance(dynamics, Thruster)
|
102
|
+
assert isinstance(dynamics, Dynamics)
|
103
|
+
assert dynamics.is_defined()
|
104
|
+
|
105
|
+
def test_getters(self, dynamics: Thruster):
|
106
|
+
assert dynamics.get_satellite_system() is not None
|
107
|
+
assert dynamics.get_guidance_law() is not None
|
108
|
+
assert dynamics.get_read_coordinate_subsets() is not None
|
109
|
+
assert dynamics.get_write_coordinate_subsets() is not None
|
110
|
+
|
111
|
+
def test_compute_contribution_success(self, dynamics: Thruster, state: State):
|
112
|
+
contribution = dynamics.compute_contribution(
|
113
|
+
state.get_instant(), state.get_coordinates(), state.get_frame()
|
114
|
+
)
|
115
|
+
|
116
|
+
assert len(contribution) == 4
|
117
|
+
assert contribution == pytest.approx(
|
118
|
+
[0.0, 0.009523809523809525, 0.0, -0.0006798108086519521], abs=5e-11
|
119
|
+
)
|
120
|
+
|
121
|
+
def test_compute_contribution_failure_out_of_fuel(
|
122
|
+
self,
|
123
|
+
satellite_system: SatelliteSystem,
|
124
|
+
coordinate_broker: CoordinateBroker,
|
125
|
+
dynamics: Thruster,
|
126
|
+
):
|
127
|
+
instant: Instant = Instant.date_time(DateTime(2021, 3, 20, 12, 0, 0), Scale.UTC)
|
128
|
+
coordinates: list = [
|
129
|
+
7000000.0,
|
130
|
+
0.0,
|
131
|
+
0.0,
|
132
|
+
0.0,
|
133
|
+
7546.05329,
|
134
|
+
0.0,
|
135
|
+
satellite_system.get_mass().in_kilograms(),
|
136
|
+
]
|
137
|
+
state = State(instant, coordinates, Frame.GCRF(), coordinate_broker)
|
138
|
+
|
139
|
+
with pytest.raises(RuntimeError):
|
140
|
+
contribution = dynamics.compute_contribution(
|
141
|
+
state.get_instant(), state.get_coordinates(), state.get_frame()
|
142
|
+
)
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# Apache License 2.0
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
from ostk.physics.time import Instant, DateTime, Scale
|
6
|
+
from ostk.physics.coordinate import Frame, Position, Velocity
|
7
|
+
from ostk.physics.unit import Angle
|
8
|
+
|
9
|
+
from ostk.astrodynamics.trajectory import State
|
10
|
+
|
11
|
+
from ostk.astrodynamics.event_condition import AngularCondition
|
12
|
+
|
13
|
+
|
14
|
+
@pytest.fixture
|
15
|
+
def state() -> State:
|
16
|
+
frame: Frame = Frame.GCRF()
|
17
|
+
position: Position = Position.meters([7500000.0, 0.0, 0.0], frame)
|
18
|
+
velocity: Velocity = Velocity.meters_per_second(
|
19
|
+
[0.0, 5335.865450622126, 5335.865450622126], frame
|
20
|
+
)
|
21
|
+
|
22
|
+
instant: Instant = Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC)
|
23
|
+
return State(instant, position, velocity)
|
24
|
+
|
25
|
+
|
26
|
+
@pytest.fixture
|
27
|
+
def criterion() -> AngularCondition.Criterion:
|
28
|
+
return AngularCondition.Criterion.PositiveCrossing
|
29
|
+
|
30
|
+
|
31
|
+
@pytest.fixture
|
32
|
+
def evaluator():
|
33
|
+
return lambda state: state.get_coordinates()[0]
|
34
|
+
|
35
|
+
|
36
|
+
@pytest.fixture
|
37
|
+
def target_angle() -> Angle:
|
38
|
+
return Angle.degrees(0.0)
|
39
|
+
|
40
|
+
|
41
|
+
@pytest.fixture
|
42
|
+
def target_range() -> tuple[Angle, Angle]:
|
43
|
+
return (Angle.degrees(0.0), Angle.degrees(10.0))
|
44
|
+
|
45
|
+
|
46
|
+
@pytest.fixture
|
47
|
+
def event_condition(
|
48
|
+
criterion: AngularCondition.Criterion, evaluator, target_angle: Angle
|
49
|
+
) -> AngularCondition:
|
50
|
+
return AngularCondition(
|
51
|
+
"My Condition",
|
52
|
+
criterion,
|
53
|
+
evaluator,
|
54
|
+
target_angle,
|
55
|
+
)
|
56
|
+
|
57
|
+
|
58
|
+
@pytest.fixture
|
59
|
+
def within_range_condition(
|
60
|
+
evaluator, target_range: tuple[Angle, Angle]
|
61
|
+
) -> AngularCondition:
|
62
|
+
return AngularCondition.within_range("My Condition", evaluator, target_range)
|
63
|
+
|
64
|
+
|
65
|
+
class TestAngularCondition:
|
66
|
+
def test_constructor(
|
67
|
+
self,
|
68
|
+
criterion: AngularCondition.Criterion,
|
69
|
+
evaluator,
|
70
|
+
target_angle: Angle,
|
71
|
+
):
|
72
|
+
assert (
|
73
|
+
AngularCondition("My Condition", criterion, evaluator, target_angle)
|
74
|
+
is not None
|
75
|
+
)
|
76
|
+
|
77
|
+
def test_get_criterion(
|
78
|
+
self,
|
79
|
+
event_condition: AngularCondition,
|
80
|
+
criterion: AngularCondition.Criterion,
|
81
|
+
):
|
82
|
+
assert event_condition.get_criterion() == criterion
|
83
|
+
|
84
|
+
def test_get_target_angle(
|
85
|
+
self,
|
86
|
+
event_condition: AngularCondition,
|
87
|
+
within_range_condition: AngularCondition,
|
88
|
+
target_angle: Angle,
|
89
|
+
):
|
90
|
+
assert event_condition.get_target_angle() == target_angle
|
91
|
+
|
92
|
+
with pytest.raises(RuntimeError):
|
93
|
+
within_range_condition.get_target_angle()
|
94
|
+
|
95
|
+
def test_get_target_range(
|
96
|
+
self,
|
97
|
+
event_condition: AngularCondition,
|
98
|
+
within_range_condition: AngularCondition,
|
99
|
+
target_range: tuple[Angle, Angle],
|
100
|
+
):
|
101
|
+
with pytest.raises(RuntimeError):
|
102
|
+
event_condition.get_target_range()
|
103
|
+
|
104
|
+
assert within_range_condition.get_target_range() == target_range
|
105
|
+
|
106
|
+
def test_is_satisfied(self, state: State, event_condition: AngularCondition):
|
107
|
+
assert (
|
108
|
+
event_condition.is_satisfied(previous_state=state, current_state=state)
|
109
|
+
is not None
|
110
|
+
)
|
111
|
+
|
112
|
+
def test_string_from_criterion(self, criterion: AngularCondition.Criterion):
|
113
|
+
assert AngularCondition.string_from_criterion(criterion) is not None
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# Apache License 2.0
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
from ostk.physics.time import Instant, DateTime, Scale
|
6
|
+
from ostk.physics.coordinate import Frame, Position, Velocity
|
7
|
+
|
8
|
+
from ostk.astrodynamics.trajectory import State
|
9
|
+
from ostk.astrodynamics.event_condition import BooleanCondition
|
10
|
+
|
11
|
+
|
12
|
+
@pytest.fixture
|
13
|
+
def state() -> State:
|
14
|
+
frame: Frame = Frame.GCRF()
|
15
|
+
position: Position = Position.meters([7500000.0, 0.0, 0.0], frame)
|
16
|
+
velocity: Velocity = Velocity.meters_per_second(
|
17
|
+
[0.0, 5335.865450622126, 5335.865450622126], frame
|
18
|
+
)
|
19
|
+
|
20
|
+
instant: Instant = Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC)
|
21
|
+
return State(instant, position, velocity)
|
22
|
+
|
23
|
+
|
24
|
+
@pytest.fixture
|
25
|
+
def evaluator():
|
26
|
+
return lambda state: state.get_coordinates()[0]
|
27
|
+
|
28
|
+
|
29
|
+
@pytest.fixture
|
30
|
+
def is_inversed() -> bool:
|
31
|
+
return False
|
32
|
+
|
33
|
+
|
34
|
+
@pytest.fixture
|
35
|
+
def event_condition(evaluator, is_inversed: bool) -> BooleanCondition:
|
36
|
+
return BooleanCondition(
|
37
|
+
"My Condition",
|
38
|
+
BooleanCondition.Criterion.StrictlyPositive,
|
39
|
+
evaluator,
|
40
|
+
is_inversed,
|
41
|
+
)
|
42
|
+
|
43
|
+
|
44
|
+
class TestBooleanCondition:
|
45
|
+
def test_is_inversed(self, event_condition: BooleanCondition, is_inversed: bool):
|
46
|
+
assert event_condition.is_inversed() == is_inversed
|
47
|
+
|
48
|
+
def test_evaluate(self, state: State, event_condition: BooleanCondition):
|
49
|
+
assert event_condition.evaluate(state) is not None
|
50
|
+
|
51
|
+
def test_is_satisfied(self, state: State, event_condition: BooleanCondition):
|
52
|
+
assert (
|
53
|
+
event_condition.is_satisfied(previous_state=state, current_state=state)
|
54
|
+
is not None
|
55
|
+
)
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# Apache License 2.0
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
from ostk.physics.environment.gravitational import Earth
|
6
|
+
from ostk.physics.unit import Derived, Length, Angle
|
7
|
+
from ostk.physics.coordinate import Frame
|
8
|
+
|
9
|
+
from ostk.astrodynamics import EventCondition
|
10
|
+
from ostk.astrodynamics.event_condition import (
|
11
|
+
COECondition,
|
12
|
+
AngularCondition,
|
13
|
+
RealCondition,
|
14
|
+
)
|
15
|
+
|
16
|
+
|
17
|
+
@pytest.fixture
|
18
|
+
def criterion() -> AngularCondition.Criterion:
|
19
|
+
return AngularCondition.Criterion.AnyCrossing
|
20
|
+
|
21
|
+
|
22
|
+
@pytest.fixture
|
23
|
+
def gravitational_parameter() -> Derived:
|
24
|
+
return Earth.spherical.gravitational_parameter
|
25
|
+
|
26
|
+
|
27
|
+
@pytest.fixture
|
28
|
+
def frame() -> Frame:
|
29
|
+
return Frame.GCRF()
|
30
|
+
|
31
|
+
|
32
|
+
class TestCOECondition:
|
33
|
+
@pytest.mark.parametrize(
|
34
|
+
"static_constructor,target,criterion",
|
35
|
+
(
|
36
|
+
(
|
37
|
+
COECondition.semi_major_axis,
|
38
|
+
EventCondition.Target(Length.meters(7e6)),
|
39
|
+
RealCondition.Criterion.PositiveCrossing,
|
40
|
+
),
|
41
|
+
(
|
42
|
+
COECondition.eccentricity,
|
43
|
+
EventCondition.Target(0.1),
|
44
|
+
RealCondition.Criterion.PositiveCrossing,
|
45
|
+
),
|
46
|
+
(
|
47
|
+
COECondition.inclination,
|
48
|
+
EventCondition.Target(Angle.degrees(0.0)),
|
49
|
+
AngularCondition.Criterion.PositiveCrossing,
|
50
|
+
),
|
51
|
+
(
|
52
|
+
COECondition.aop,
|
53
|
+
EventCondition.Target(Angle.degrees(0.0)),
|
54
|
+
AngularCondition.Criterion.PositiveCrossing,
|
55
|
+
),
|
56
|
+
(
|
57
|
+
COECondition.raan,
|
58
|
+
EventCondition.Target(Angle.degrees(0.0)),
|
59
|
+
AngularCondition.Criterion.PositiveCrossing,
|
60
|
+
),
|
61
|
+
(
|
62
|
+
COECondition.true_anomaly,
|
63
|
+
EventCondition.Target(Angle.degrees(0.0)),
|
64
|
+
AngularCondition.Criterion.PositiveCrossing,
|
65
|
+
),
|
66
|
+
(
|
67
|
+
COECondition.mean_anomaly,
|
68
|
+
EventCondition.Target(Angle.degrees(0.0)),
|
69
|
+
AngularCondition.Criterion.PositiveCrossing,
|
70
|
+
),
|
71
|
+
(
|
72
|
+
COECondition.eccentric_anomaly,
|
73
|
+
EventCondition.Target(Angle.degrees(0.0)),
|
74
|
+
AngularCondition.Criterion.PositiveCrossing,
|
75
|
+
),
|
76
|
+
),
|
77
|
+
)
|
78
|
+
def test_static_constructors(
|
79
|
+
self,
|
80
|
+
static_constructor,
|
81
|
+
target,
|
82
|
+
criterion,
|
83
|
+
frame: Frame,
|
84
|
+
gravitational_parameter: Derived,
|
85
|
+
):
|
86
|
+
condition = static_constructor(criterion, frame, target, gravitational_parameter)
|
87
|
+
assert condition is not None
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Apache License 2.0
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
from ostk.physics.coordinate import Frame, Position, Velocity
|
6
|
+
from ostk.physics.time import DateTime, Instant, Scale
|
7
|
+
|
8
|
+
from ostk.astrodynamics.event_condition import InstantCondition
|
9
|
+
from ostk.astrodynamics.trajectory import State
|
10
|
+
|
11
|
+
|
12
|
+
@pytest.fixture
|
13
|
+
def instant() -> Instant:
|
14
|
+
return Instant.date_time(DateTime(2023, 1, 1, 0, 0, 0), Scale.UTC)
|
15
|
+
|
16
|
+
|
17
|
+
@pytest.fixture
|
18
|
+
def criterion() -> InstantCondition.Criterion:
|
19
|
+
return InstantCondition.Criterion.StrictlyPositive
|
20
|
+
|
21
|
+
|
22
|
+
@pytest.fixture
|
23
|
+
def instant_condition(
|
24
|
+
criterion: InstantCondition.Criterion, instant: Instant
|
25
|
+
) -> InstantCondition:
|
26
|
+
return InstantCondition(criterion, instant)
|
27
|
+
|
28
|
+
|
29
|
+
@pytest.fixture
|
30
|
+
def state() -> State:
|
31
|
+
frame: Frame = Frame.GCRF()
|
32
|
+
position: Position = Position.meters(
|
33
|
+
[717094.039086306, -6872433.2241124, 46175.9696673281], frame
|
34
|
+
)
|
35
|
+
velocity: Velocity = Velocity.meters_per_second(
|
36
|
+
[-970.650826004612, -45.4598114773158, 7529.82424886455], frame
|
37
|
+
)
|
38
|
+
|
39
|
+
instant: Instant = Instant.date_time(DateTime(2023, 1, 1, 0, 1, 0), Scale.UTC)
|
40
|
+
return State(instant, position, velocity)
|
41
|
+
|
42
|
+
|
43
|
+
class TestInstantCondition:
|
44
|
+
def test_get_instant(self, instant_condition: InstantCondition, instant: Instant):
|
45
|
+
assert instant_condition.get_instant() == instant
|
46
|
+
|
47
|
+
def test_evaluate(self, instant_condition: InstantCondition, state: State):
|
48
|
+
assert instant_condition.evaluate(state) == 60.0
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# Apache License 2.0
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
from ostk.physics.coordinate import Frame, Position, Velocity
|
6
|
+
from ostk.physics.time import DateTime, Instant, Scale
|
7
|
+
|
8
|
+
from ostk.astrodynamics.event_condition import RealCondition, LogicalCondition
|
9
|
+
from ostk.astrodynamics.trajectory import State
|
10
|
+
|
11
|
+
|
12
|
+
@pytest.fixture
|
13
|
+
def always_true() -> RealCondition:
|
14
|
+
return RealCondition(
|
15
|
+
"Always True Condition",
|
16
|
+
RealCondition.Criterion.StrictlyPositive,
|
17
|
+
lambda state: 1.0,
|
18
|
+
0.0,
|
19
|
+
)
|
20
|
+
|
21
|
+
|
22
|
+
@pytest.fixture
|
23
|
+
def always_false() -> RealCondition:
|
24
|
+
return RealCondition(
|
25
|
+
"Always False Condition",
|
26
|
+
RealCondition.Criterion.StrictlyPositive,
|
27
|
+
lambda state: -1.0,
|
28
|
+
0.0,
|
29
|
+
)
|
30
|
+
|
31
|
+
|
32
|
+
@pytest.fixture
|
33
|
+
def event_conditions(
|
34
|
+
always_true: RealCondition, always_false: RealCondition
|
35
|
+
) -> list[RealCondition]:
|
36
|
+
return [always_true, always_false]
|
37
|
+
|
38
|
+
|
39
|
+
@pytest.fixture
|
40
|
+
def logical_condition_type() -> LogicalCondition.Type:
|
41
|
+
return LogicalCondition.Type.And
|
42
|
+
|
43
|
+
|
44
|
+
@pytest.fixture
|
45
|
+
def state() -> State:
|
46
|
+
frame: Frame = Frame.GCRF()
|
47
|
+
position: Position = Position.meters(
|
48
|
+
[717094.039086306, -6872433.2241124, 46175.9696673281], frame
|
49
|
+
)
|
50
|
+
velocity: Velocity = Velocity.meters_per_second(
|
51
|
+
[-970.650826004612, -45.4598114773158, 7529.82424886455], frame
|
52
|
+
)
|
53
|
+
|
54
|
+
instant: Instant = Instant.date_time(DateTime(2023, 1, 1, 0, 1, 0), Scale.UTC)
|
55
|
+
return State(instant, position, velocity)
|
56
|
+
|
57
|
+
|
58
|
+
@pytest.fixture
|
59
|
+
def logical_condition(
|
60
|
+
logical_condition_type: LogicalCondition.Type, event_conditions: list[RealCondition]
|
61
|
+
) -> LogicalCondition:
|
62
|
+
return LogicalCondition("Logical", logical_condition_type, event_conditions)
|
63
|
+
|
64
|
+
|
65
|
+
class TestLogicalCondition:
|
66
|
+
@pytest.mark.parametrize(
|
67
|
+
"logical_condition_type",
|
68
|
+
(
|
69
|
+
LogicalCondition.Type.And,
|
70
|
+
LogicalCondition.Type.Or,
|
71
|
+
),
|
72
|
+
)
|
73
|
+
def test_constructor(
|
74
|
+
self,
|
75
|
+
logical_condition_type: LogicalCondition.Type,
|
76
|
+
event_conditions: list[RealCondition],
|
77
|
+
):
|
78
|
+
assert (
|
79
|
+
LogicalCondition(
|
80
|
+
"Logical Condition", logical_condition_type, event_conditions
|
81
|
+
)
|
82
|
+
is not None
|
83
|
+
)
|
84
|
+
|
85
|
+
def test_get_event_conditions(
|
86
|
+
self,
|
87
|
+
logical_condition: LogicalCondition,
|
88
|
+
event_conditions: list[RealCondition],
|
89
|
+
):
|
90
|
+
assert logical_condition.get_event_conditions() == event_conditions
|
91
|
+
|
92
|
+
def test_get_type(
|
93
|
+
self,
|
94
|
+
logical_condition: LogicalCondition,
|
95
|
+
logical_condition_type: LogicalCondition.Type,
|
96
|
+
):
|
97
|
+
assert logical_condition.get_type() == logical_condition_type
|
98
|
+
|
99
|
+
@pytest.mark.parametrize(
|
100
|
+
"logical_condition_type,expected_result",
|
101
|
+
(
|
102
|
+
(LogicalCondition.Type.And, False),
|
103
|
+
(LogicalCondition.Type.Or, True),
|
104
|
+
),
|
105
|
+
)
|
106
|
+
def test_is_satisfied(
|
107
|
+
self,
|
108
|
+
logical_condition_type: LogicalCondition.Type,
|
109
|
+
expected_result: bool,
|
110
|
+
event_conditions: list[RealCondition],
|
111
|
+
state: State,
|
112
|
+
):
|
113
|
+
logical_condition: LogicalCondition = LogicalCondition(
|
114
|
+
"Logical Condition", logical_condition_type, event_conditions
|
115
|
+
)
|
116
|
+
|
117
|
+
assert (
|
118
|
+
logical_condition.is_satisfied(previous_state=state, current_state=state)
|
119
|
+
== expected_result
|
120
|
+
)
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# Apache License 2.0
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
from ostk.physics.time import Instant, DateTime, Scale
|
6
|
+
from ostk.physics.coordinate import Frame, Position, Velocity
|
7
|
+
|
8
|
+
from ostk.astrodynamics.trajectory import State
|
9
|
+
|
10
|
+
from ostk.astrodynamics.event_condition import RealCondition
|
11
|
+
|
12
|
+
|
13
|
+
@pytest.fixture
|
14
|
+
def state() -> State:
|
15
|
+
frame: Frame = Frame.GCRF()
|
16
|
+
position: Position = Position.meters([7500000.0, 0.0, 0.0], frame)
|
17
|
+
velocity: Velocity = Velocity.meters_per_second(
|
18
|
+
[0.0, 5335.865450622126, 5335.865450622126], frame
|
19
|
+
)
|
20
|
+
|
21
|
+
instant: Instant = Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC)
|
22
|
+
return State(instant, position, velocity)
|
23
|
+
|
24
|
+
|
25
|
+
@pytest.fixture
|
26
|
+
def evaluator():
|
27
|
+
return lambda state: state.get_coordinates()[0]
|
28
|
+
|
29
|
+
|
30
|
+
@pytest.fixture
|
31
|
+
def target() -> float:
|
32
|
+
return 10.0
|
33
|
+
|
34
|
+
|
35
|
+
@pytest.fixture
|
36
|
+
def event_condition(evaluator, target: float) -> RealCondition:
|
37
|
+
return RealCondition(
|
38
|
+
"My Condition", RealCondition.Criterion.PositiveCrossing, evaluator, target
|
39
|
+
)
|
40
|
+
|
41
|
+
|
42
|
+
class TestRealCondition:
|
43
|
+
def test_evaluate(self, state: State, event_condition: RealCondition):
|
44
|
+
assert event_condition.evaluate(state) is not None
|
45
|
+
|
46
|
+
def test_is_satisfied(self, state: State, event_condition: RealCondition):
|
47
|
+
assert (
|
48
|
+
event_condition.is_satisfied(previous_state=state, current_state=state)
|
49
|
+
is not None
|
50
|
+
)
|
@@ -0,0 +1 @@
|
|
1
|
+
# Apache License 2.0
|
@@ -0,0 +1 @@
|
|
1
|
+
# Apache License 2.0
|
@@ -0,0 +1,73 @@
|
|
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
|
+
Mass = physics.unit.Mass
|
14
|
+
|
15
|
+
PropulsionSystem = astrodynamics.flight.system.PropulsionSystem
|
16
|
+
|
17
|
+
|
18
|
+
@pytest.fixture
|
19
|
+
def propulsion_system() -> PropulsionSystem:
|
20
|
+
return PropulsionSystem(
|
21
|
+
1.0,
|
22
|
+
150.0,
|
23
|
+
)
|
24
|
+
|
25
|
+
|
26
|
+
@pytest.fixture
|
27
|
+
def mass() -> Mass:
|
28
|
+
return Mass(90.0, Mass.Unit.Kilogram)
|
29
|
+
|
30
|
+
|
31
|
+
class TestPropulsionSystem:
|
32
|
+
def test_constructors(
|
33
|
+
self,
|
34
|
+
propulsion_system: PropulsionSystem,
|
35
|
+
):
|
36
|
+
assert propulsion_system is not None
|
37
|
+
assert isinstance(propulsion_system, PropulsionSystem)
|
38
|
+
assert propulsion_system.is_defined()
|
39
|
+
|
40
|
+
def test_comparators(
|
41
|
+
self,
|
42
|
+
propulsion_system: PropulsionSystem,
|
43
|
+
):
|
44
|
+
assert (propulsion_system == propulsion_system) is True
|
45
|
+
assert (propulsion_system != propulsion_system) is False
|
46
|
+
|
47
|
+
def test_is_defined(
|
48
|
+
self,
|
49
|
+
propulsion_system: PropulsionSystem,
|
50
|
+
):
|
51
|
+
assert propulsion_system.is_defined()
|
52
|
+
|
53
|
+
def test_getters(
|
54
|
+
self,
|
55
|
+
propulsion_system: PropulsionSystem,
|
56
|
+
mass: Mass,
|
57
|
+
):
|
58
|
+
assert propulsion_system.get_thrust() == 1.0
|
59
|
+
assert propulsion_system.get_specific_impulse() == 150.0
|
60
|
+
assert propulsion_system.get_mass_flow_rate() is not None
|
61
|
+
assert propulsion_system.get_acceleration(mass) is not None
|
62
|
+
|
63
|
+
def test_static_methods(
|
64
|
+
self,
|
65
|
+
mass: Mass,
|
66
|
+
):
|
67
|
+
assert PropulsionSystem.undefined().is_defined() is False
|
68
|
+
|
69
|
+
assert PropulsionSystem.default().is_defined() is True
|
70
|
+
assert PropulsionSystem.default().get_thrust() is not None
|
71
|
+
assert PropulsionSystem.default().get_specific_impulse() is not None
|
72
|
+
assert PropulsionSystem.default().get_mass_flow_rate() is not None
|
73
|
+
assert PropulsionSystem.default().get_acceleration(mass) is not None
|