open-space-toolkit-astrodynamics 13.1.0__py313-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.
Files changed (100) hide show
  1. open_space_toolkit_astrodynamics-13.1.0.dist-info/METADATA +30 -0
  2. open_space_toolkit_astrodynamics-13.1.0.dist-info/RECORD +100 -0
  3. open_space_toolkit_astrodynamics-13.1.0.dist-info/WHEEL +5 -0
  4. open_space_toolkit_astrodynamics-13.1.0.dist-info/top_level.txt +1 -0
  5. open_space_toolkit_astrodynamics-13.1.0.dist-info/zip-safe +1 -0
  6. ostk/__init__.py +1 -0
  7. ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-313-aarch64-linux-gnu.so +0 -0
  8. ostk/astrodynamics/__init__.py +11 -0
  9. ostk/astrodynamics/converters.py +130 -0
  10. ostk/astrodynamics/dataframe.py +479 -0
  11. ostk/astrodynamics/display.py +222 -0
  12. ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.13 +0 -0
  13. ostk/astrodynamics/pytrajectory/__init__.py +1 -0
  14. ostk/astrodynamics/pytrajectory/pystate.py +251 -0
  15. ostk/astrodynamics/test/__init__.py +1 -0
  16. ostk/astrodynamics/test/access/__init__.py +1 -0
  17. ostk/astrodynamics/test/access/test_generator.py +248 -0
  18. ostk/astrodynamics/test/conftest.py +119 -0
  19. ostk/astrodynamics/test/conjunction/message/ccsds/__init__.py +1 -0
  20. ostk/astrodynamics/test/conjunction/message/ccsds/conftest.py +325 -0
  21. ostk/astrodynamics/test/conjunction/message/ccsds/data/cdm.json +303 -0
  22. ostk/astrodynamics/test/conjunction/message/ccsds/test_cdm.py +416 -0
  23. ostk/astrodynamics/test/dynamics/__init__.py +1 -0
  24. ostk/astrodynamics/test/dynamics/data/Tabulated_Earth_Gravity.csv +565 -0
  25. ostk/astrodynamics/test/dynamics/data/Tabulated_Earth_Gravity_Truth.csv +100 -0
  26. ostk/astrodynamics/test/dynamics/test_atmospheric_drag.py +128 -0
  27. ostk/astrodynamics/test/dynamics/test_central_body_gravity.py +58 -0
  28. ostk/astrodynamics/test/dynamics/test_dynamics.py +50 -0
  29. ostk/astrodynamics/test/dynamics/test_position_derivative.py +51 -0
  30. ostk/astrodynamics/test/dynamics/test_tabulated.py +138 -0
  31. ostk/astrodynamics/test/dynamics/test_third_body_gravity.py +67 -0
  32. ostk/astrodynamics/test/dynamics/test_thruster.py +142 -0
  33. ostk/astrodynamics/test/event_condition/test_angular_condition.py +113 -0
  34. ostk/astrodynamics/test/event_condition/test_boolean_condition.py +55 -0
  35. ostk/astrodynamics/test/event_condition/test_coe_condition.py +87 -0
  36. ostk/astrodynamics/test/event_condition/test_instant_condition.py +48 -0
  37. ostk/astrodynamics/test/event_condition/test_logical_condition.py +120 -0
  38. ostk/astrodynamics/test/event_condition/test_real_condition.py +50 -0
  39. ostk/astrodynamics/test/flight/__init__.py +1 -0
  40. ostk/astrodynamics/test/flight/system/__init__.py +1 -0
  41. ostk/astrodynamics/test/flight/system/test_propulsion_system.py +73 -0
  42. ostk/astrodynamics/test/flight/system/test_satellite_system.py +91 -0
  43. ostk/astrodynamics/test/flight/system/test_satellite_system_builder.py +71 -0
  44. ostk/astrodynamics/test/flight/test_maneuver.py +212 -0
  45. ostk/astrodynamics/test/flight/test_profile.py +253 -0
  46. ostk/astrodynamics/test/flight/test_system.py +55 -0
  47. ostk/astrodynamics/test/guidance_law/test_constant_thrust.py +91 -0
  48. ostk/astrodynamics/test/guidance_law/test_qlaw.py +138 -0
  49. ostk/astrodynamics/test/solvers/__init__.py +1 -0
  50. ostk/astrodynamics/test/solvers/test_finite_difference_solver.py +181 -0
  51. ostk/astrodynamics/test/solvers/test_temporal_condition_solver.py +153 -0
  52. ostk/astrodynamics/test/test_access.py +128 -0
  53. ostk/astrodynamics/test/test_converters.py +290 -0
  54. ostk/astrodynamics/test/test_dataframe.py +875 -0
  55. ostk/astrodynamics/test/test_display.py +114 -0
  56. ostk/astrodynamics/test/test_event_condition.py +78 -0
  57. ostk/astrodynamics/test/test_import.py +26 -0
  58. ostk/astrodynamics/test/test_root_solver.py +70 -0
  59. ostk/astrodynamics/test/test_trajectory.py +118 -0
  60. ostk/astrodynamics/test/test_utilities.py +106 -0
  61. ostk/astrodynamics/test/test_viewer.py +129 -0
  62. ostk/astrodynamics/test/trajectory/__init__.py +1 -0
  63. ostk/astrodynamics/test/trajectory/orbit/__init__.py +1 -0
  64. ostk/astrodynamics/test/trajectory/orbit/message/__init__.py +1 -0
  65. ostk/astrodynamics/test/trajectory/orbit/message/spacex/__init__.py +1 -0
  66. ostk/astrodynamics/test/trajectory/orbit/message/spacex/conftest.py +18 -0
  67. ostk/astrodynamics/test/trajectory/orbit/message/spacex/data/opm_1.yaml +44 -0
  68. ostk/astrodynamics/test/trajectory/orbit/message/spacex/test_opm.py +108 -0
  69. ostk/astrodynamics/test/trajectory/orbit/models/__init__.py +1 -0
  70. ostk/astrodynamics/test/trajectory/orbit/models/kepler/__init__.py +1 -0
  71. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean.py +65 -0
  72. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean_long.py +102 -0
  73. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean_short.py +102 -0
  74. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_coe.py +201 -0
  75. ostk/astrodynamics/test/trajectory/orbit/models/sgp4/__init__.py +1 -0
  76. ostk/astrodynamics/test/trajectory/orbit/models/sgp4/test_tle.py +331 -0
  77. ostk/astrodynamics/test/trajectory/orbit/models/test_kepler.py +130 -0
  78. ostk/astrodynamics/test/trajectory/orbit/models/test_propagated.py +234 -0
  79. ostk/astrodynamics/test/trajectory/orbit/models/test_sgp4.py +1 -0
  80. ostk/astrodynamics/test/trajectory/orbit/models/test_tabulated.py +380 -0
  81. ostk/astrodynamics/test/trajectory/orbit/test_model.py +1 -0
  82. ostk/astrodynamics/test/trajectory/orbit/test_pass.py +75 -0
  83. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_angular_velocity.py +30 -0
  84. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_attitude_quaternion.py +18 -0
  85. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_position.py +107 -0
  86. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_velocity.py +115 -0
  87. ostk/astrodynamics/test/trajectory/state/test_coordinate_broker.py +84 -0
  88. ostk/astrodynamics/test/trajectory/state/test_coordinate_subset.py +46 -0
  89. ostk/astrodynamics/test/trajectory/state/test_numerical_solver.py +314 -0
  90. ostk/astrodynamics/test/trajectory/test_local_orbital_frame_direction.py +81 -0
  91. ostk/astrodynamics/test/trajectory/test_local_orbital_frame_factory.py +108 -0
  92. ostk/astrodynamics/test/trajectory/test_model.py +1 -0
  93. ostk/astrodynamics/test/trajectory/test_orbit.py +205 -0
  94. ostk/astrodynamics/test/trajectory/test_propagator.py +458 -0
  95. ostk/astrodynamics/test/trajectory/test_segment.py +403 -0
  96. ostk/astrodynamics/test/trajectory/test_sequence.py +530 -0
  97. ostk/astrodynamics/test/trajectory/test_state.py +543 -0
  98. ostk/astrodynamics/test/trajectory/test_state_builder.py +171 -0
  99. ostk/astrodynamics/utilities.py +247 -0
  100. 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