open-space-toolkit-astrodynamics 2.4.0__py39-none-any.whl → 3.0.0__py39-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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: open-space-toolkit-astrodynamics
3
- Version: 2.4.0
3
+ Version: 3.0.0
4
4
  Summary: Orbit, attitude, access.
5
5
  Author: Open Space Collective
6
6
  Author-email: contact@open-space-collective.org
@@ -1,9 +1,9 @@
1
1
  ostk/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
2
- ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-39-x86_64-linux-gnu.so,sha256=p8Q2kmoC_eidYT-XofoL3k0H5SjWzAHrPZZFxyvJp7A,1414584
2
+ ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-39-x86_64-linux-gnu.so,sha256=YXAEb6MOEWwW1KOz7sCniXUmonQS-SHeg8LryEQRLCo,1447384
3
3
  ostk/astrodynamics/__init__.py,sha256=BE7yyrOnPqFCTPT3GhYEI4IWR5nzs96VSjKphhQ09ew,97
4
4
  ostk/astrodynamics/converters.py,sha256=sBZ3_JMjowWbQ9gBPA2cSEkbBfAwXmt1IBbLks76-Vk,3502
5
5
  ostk/astrodynamics/display.py,sha256=y9FnoQbPFGM6LzkUdgXgeqtuVGhv57GuTKbeDdcFPgw,6306
6
- ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.2,sha256=3Zkok2yopaE5WjopTGYXl_oIh65GrnI7W8unc0jUkCk,69730504
6
+ ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.3,sha256=6Q6q--9IL9_hOCb-ooRA_zUBP_GsZe33716f0OfkZzU,72418128
7
7
  ostk/astrodynamics/utilities.py,sha256=NbeKN_CtcCRHIinhoNWTEosBMR7xc924S-ZFD97mduw,4478
8
8
  ostk/astrodynamics/viewer.py,sha256=_4uucNtZrIADtKtEYHbiu91RVVvKRG3vPULUAshPLJU,8912
9
9
  ostk/astrodynamics/test/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
@@ -40,20 +40,21 @@ ostk/astrodynamics/test/flight/system/test_satellite_system.py,sha256=-5KOGVTWRI
40
40
  ostk/astrodynamics/test/flight/system/dynamics/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
41
41
  ostk/astrodynamics/test/flight/system/dynamics/test_atmospheric_drag.py,sha256=bTFDvI1riLFlgKzs3TRt8dafFtb--L_AMEDuuRWEgGc,3793
42
42
  ostk/astrodynamics/test/flight/system/dynamics/test_central_body_gravity.py,sha256=r3JIIX7cD63BhrgvLtjFaK7ew1BqHdKP5_VxwGmuv1Q,1818
43
- ostk/astrodynamics/test/flight/system/dynamics/test_dynamics.py,sha256=arNkAOj2y4CDmc9CXxItbFtC4QYjaByuJefdi5S6alw,914
43
+ ostk/astrodynamics/test/flight/system/dynamics/test_dynamics.py,sha256=eD5lpF8C8b-AMrLOXlQSo-j00-5AHTaQOybbSJJmvGc,1254
44
44
  ostk/astrodynamics/test/flight/system/dynamics/test_position_derivative.py,sha256=ZVVewpqZwqiBLDqoNQDHDgDodtj6_M0J6ZmgHe_1gz8,1646
45
45
  ostk/astrodynamics/test/flight/system/dynamics/test_third_body_gravity.py,sha256=Z8OkM-EFafFpWziu3bfatlSlZA4Tic2fsVLU35rDp5E,1915
46
- ostk/astrodynamics/test/flight/system/dynamics/thruster/test_constant_thrust.py,sha256=MP6ocA0umkASJfidTni62APX9tmSxxXFQ4dxvMTKrH4,4480
46
+ ostk/astrodynamics/test/flight/system/dynamics/thruster/test_constant_thrust.py,sha256=EdEI0tMXXJVtaj7XogLuCkfK24iX9J1sxx6rr7_y-1o,4464
47
47
  ostk/astrodynamics/test/solvers/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
48
48
  ostk/astrodynamics/test/solvers/test_temporal_condition_solver.py,sha256=s7r7VelXx1_b-6wO_GyOlmxlsfA4I_zpxrWojriQls8,4867
49
49
  ostk/astrodynamics/test/trajectory/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
50
- ostk/astrodynamics/test/trajectory/test_local_orbital_frame_direction.py,sha256=DJltOvRcxaEJbZsH_PQe7oPdN9KRE6ufXmJ1kqUw6O4,2518
50
+ ostk/astrodynamics/test/trajectory/test_local_orbital_frame_direction.py,sha256=d72J50UGG9m0Atei0UQ8sITU1WdJmws5xgUiacLZMbw,2515
51
51
  ostk/astrodynamics/test/trajectory/test_local_orbital_frame_factory.py,sha256=FziYh9XxD2FEuj6WhnqOe5mF9twLTQtvcem8KzQZKXg,1864
52
52
  ostk/astrodynamics/test/trajectory/test_model.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
53
53
  ostk/astrodynamics/test/trajectory/test_orbit.py,sha256=SlCBZ_broPaJ6L8khMuvbdPem9-zmqG6IZwxr9cECB4,3155
54
- ostk/astrodynamics/test/trajectory/test_propagator.py,sha256=e_fmvvaoMhYs0ApqCgbzfBYrYPaGOIuzouo-6x2jbK4,12504
55
- ostk/astrodynamics/test/trajectory/test_state.py,sha256=Ohjc_cQ28XoOtEY4mP-EuyrCKirRf0-RxJNzFVFqiJ4,3699
56
- ostk/astrodynamics/test/trajectory/test_trajectory_segment.py,sha256=eOCI9GLcAnMrwXkdaHbd0thnyNDCyBgAemhuMO6B7xY,3863
54
+ ostk/astrodynamics/test/trajectory/test_propagator.py,sha256=ct4Sg8l3R-PQus0NYBviu5ExUXQC5f8TcPGqJiYUA_0,12208
55
+ ostk/astrodynamics/test/trajectory/test_segment.py,sha256=T4OJ25z4-ogAV8WN9W7CEM_EMQtvVmGD8-Iql4NjJY8,5060
56
+ ostk/astrodynamics/test/trajectory/test_sequence.py,sha256=n-B2_h7EYNd--Slw0680U4IRPnhbNYzcXOzNNBALyiU,10350
57
+ ostk/astrodynamics/test/trajectory/test_state.py,sha256=Kr4IbGBc1TNGdEOsXFLGSQGC9SwCER-lJ6E-xumqgN4,3829
57
58
  ostk/astrodynamics/test/trajectory/orbit/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
58
59
  ostk/astrodynamics/test/trajectory/orbit/test_model.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
59
60
  ostk/astrodynamics/test/trajectory/orbit/test_pass.py,sha256=MtPRKhVz4hCzfFuE0p1x89Ps68M9s7miT7VtPIDVeOo,1898
@@ -76,8 +77,8 @@ ostk/astrodynamics/test/trajectory/state/test_coordinates_subset.py,sha256=eMmif
76
77
  ostk/astrodynamics/test/trajectory/state/test_numerical_solver.py,sha256=ZTWRSVFOJnjzQP7JDsHZxvZ4ldyDHmXTptG2csC7_ic,7480
77
78
  ostk/astrodynamics/test/trajectory/state/coordinates_subset/test_cartesian_position.py,sha256=V5d7UnV6KIJjJvh5R0i3imRfyN04JCDvCUsKdvfKmhE,2708
78
79
  ostk/astrodynamics/test/trajectory/state/coordinates_subset/test_cartesian_velocity.py,sha256=5a7yeOVt7gY4oQdINSElb_U2jznJmuWPrT_YJrI6KaM,3070
79
- open_space_toolkit_astrodynamics-2.4.0.dist-info/METADATA,sha256=R8ipuXPGkD7i4U6XXBZxvb8nJrsbXWQIw03RKlBdSyE,1779
80
- open_space_toolkit_astrodynamics-2.4.0.dist-info/WHEEL,sha256=x0YL6OSV_WitIuMP0HsTpwBgQTKZeHzZKOAyhSZVN4o,93
81
- open_space_toolkit_astrodynamics-2.4.0.dist-info/top_level.txt,sha256=zOR18699uDYnafgarhL8WU_LmTZY_5NVqutv-flp_x4,5
82
- open_space_toolkit_astrodynamics-2.4.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
83
- open_space_toolkit_astrodynamics-2.4.0.dist-info/RECORD,,
80
+ open_space_toolkit_astrodynamics-3.0.0.dist-info/METADATA,sha256=tIw96qI_UMBkuf9PFsOjObKhca4j9kWzWQoAOFi2BM4,1779
81
+ open_space_toolkit_astrodynamics-3.0.0.dist-info/WHEEL,sha256=x0YL6OSV_WitIuMP0HsTpwBgQTKZeHzZKOAyhSZVN4o,93
82
+ open_space_toolkit_astrodynamics-3.0.0.dist-info/top_level.txt,sha256=zOR18699uDYnafgarhL8WU_LmTZY_5NVqutv-flp_x4,5
83
+ open_space_toolkit_astrodynamics-3.0.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
84
+ open_space_toolkit_astrodynamics-3.0.0.dist-info/RECORD,,
@@ -2,6 +2,8 @@
2
2
 
3
3
  import pytest
4
4
 
5
+ from ostk.physics import Environment
6
+
5
7
  from ostk.astrodynamics.flight.system import Dynamics
6
8
  from ostk.astrodynamics.trajectory.state.coordinates_subset import CartesianPosition
7
9
 
@@ -11,6 +13,11 @@ def name() -> str:
11
13
  return "MyDynamics"
12
14
 
13
15
 
16
+ @pytest.fixture
17
+ def environment() -> Environment:
18
+ return Environment.default()
19
+
20
+
14
21
  @pytest.fixture
15
22
  def dynamics(name: str) -> Dynamics:
16
23
  class MyDynamics(Dynamics):
@@ -35,3 +42,9 @@ class TestDynamics:
35
42
 
36
43
  def test_get_name(self, dynamics: Dynamics, name: str):
37
44
  assert dynamics.get_name() == name
45
+
46
+ def test_from_environment(self, environment: Environment):
47
+ dynamics: list[Dynamics] = Dynamics.from_environment(environment)
48
+
49
+ assert dynamics is not None
50
+ assert isinstance(dynamics, list)
@@ -12,8 +12,6 @@ from ostk.physics.units import Mass
12
12
  from ostk.physics.time import Instant
13
13
  from ostk.physics.time import DateTime
14
14
  from ostk.physics.time import Scale
15
- from ostk.physics.coordinate import Position
16
- from ostk.physics.coordinate import Velocity
17
15
  from ostk.physics.coordinate import Frame
18
16
 
19
17
  from ostk.astrodynamics.trajectory import LocalOrbitalFrameFactory
@@ -34,8 +32,8 @@ from ostk.astrodynamics.flight.system.dynamics.thruster import ConstantThrust
34
32
  @pytest.fixture
35
33
  def local_orbital_frame_direction() -> LocalOrbitalFrameDirection:
36
34
  return LocalOrbitalFrameDirection(
37
- [1.0, 0.0, 0.0],
38
- LocalOrbitalFrameFactory.VNC(Frame.GCRF()),
35
+ vector=[1.0, 0.0, 0.0],
36
+ local_orbital_frame_factory=LocalOrbitalFrameFactory.VNC(Frame.GCRF()),
39
37
  )
40
38
 
41
39
 
@@ -77,9 +75,9 @@ def dynamics(
77
75
  local_orbital_frame_direction: LocalOrbitalFrameDirection,
78
76
  ) -> ConstantThrust:
79
77
  return ConstantThrust(
80
- satellite_system,
81
- local_orbital_frame_direction,
82
- "Constant Thrust Thruster Dynamics",
78
+ satellite_system=satellite_system,
79
+ thrust_direction=local_orbital_frame_direction,
80
+ name="Constant Thrust Thruster Dynamics",
83
81
  )
84
82
 
85
83
 
@@ -2,7 +2,6 @@
2
2
 
3
3
  import pytest
4
4
 
5
- from ostk.physics.time import Instant
6
5
  from ostk.physics.coordinate import Frame
7
6
 
8
7
  from ostk.astrodynamics.trajectory import LocalOrbitalFrameFactory
@@ -25,8 +24,8 @@ def local_orbital_frame_direction(
25
24
  local_orbital_frame_factory: LocalOrbitalFrameFactory,
26
25
  ) -> LocalOrbitalFrameDirection:
27
26
  return LocalOrbitalFrameDirection(
28
- direction_vector,
29
- local_orbital_frame_factory,
27
+ vector=direction_vector,
28
+ local_orbital_frame_factory=local_orbital_frame_factory,
30
29
  )
31
30
 
32
31
 
@@ -372,16 +372,9 @@ class TestPropagator:
372
372
  self,
373
373
  numerical_solver: NumericalSolver,
374
374
  environment: Environment,
375
- satellite_system: SatelliteSystem,
376
375
  ):
377
376
  assert Propagator.from_environment(numerical_solver, environment) is not None
378
377
 
379
- assert (
380
- Propagator.from_environment(numerical_solver, environment, satellite_system)
381
- is not None
382
- )
383
-
384
- def test_default(self, environment: Environment, satellite_system: SatelliteSystem):
378
+ def test_default(self, environment: Environment):
385
379
  assert Propagator.default()
386
380
  assert Propagator.default(environment) is not None
387
- assert Propagator.default(environment, satellite_system) is not None
@@ -13,10 +13,14 @@ from ostk.physics.coordinate import Frame
13
13
  from ostk.physics.environment.objects.celestial_bodies import Earth
14
14
 
15
15
  from ostk.astrodynamics.trajectory.state import NumericalSolver
16
+ from ostk.astrodynamics.flight.system import SatelliteSystem
16
17
  from ostk.astrodynamics.flight.system.dynamics import CentralBodyGravity
17
18
  from ostk.astrodynamics.flight.system.dynamics import PositionDerivative
19
+ from ostk.astrodynamics.flight.system.dynamics.thruster import ConstantThrust
20
+ from ostk.astrodynamics.trajectory import LocalOrbitalFrameDirection
21
+ from ostk.astrodynamics.trajectory import LocalOrbitalFrameFactory
18
22
  from ostk.astrodynamics.trajectory import State
19
- from ostk.astrodynamics.trajectory import TrajectorySegment
23
+ from ostk.astrodynamics.trajectory import Segment
20
24
  from ostk.astrodynamics.event_condition import InstantCondition
21
25
 
22
26
 
@@ -84,45 +88,82 @@ def coast_duration_segment(
84
88
  dynamics: list,
85
89
  numerical_solver: NumericalSolver,
86
90
  ):
87
- return TrajectorySegment.coast(name, instant_condition, dynamics, numerical_solver)
91
+ return Segment.coast(name, instant_condition, dynamics, numerical_solver)
88
92
 
89
93
 
90
- class TestTrajectorySegment:
91
- def test_get_name(self, coast_duration_segment: TrajectorySegment, name: str):
94
+ @pytest.fixture
95
+ def thruster_dynamics() -> ConstantThrust:
96
+ return ConstantThrust(
97
+ satellite_system=SatelliteSystem.default(),
98
+ thrust_direction=LocalOrbitalFrameDirection(
99
+ vector=[1.0, 0.0, 0.0],
100
+ local_orbital_frame_factory=LocalOrbitalFrameFactory.VNC(Frame.GCRF()),
101
+ ),
102
+ )
103
+
104
+
105
+ class TestSegment:
106
+ def test_get_name(self, coast_duration_segment: Segment, name: str):
92
107
  assert coast_duration_segment.get_name() == name
93
108
 
94
109
  def test_get_event_condition(
95
110
  self,
96
111
  instant_condition: InstantCondition,
97
- coast_duration_segment: TrajectorySegment,
112
+ coast_duration_segment: Segment,
98
113
  ):
99
114
  assert coast_duration_segment.get_event_condition() == instant_condition
100
115
 
101
116
  def test_get_dynamics(
102
117
  self,
103
118
  dynamics: list,
104
- coast_duration_segment: TrajectorySegment,
119
+ coast_duration_segment: Segment,
105
120
  ):
106
121
  assert len(coast_duration_segment.get_dynamics()) == len(dynamics)
107
122
 
108
123
  def test_get_numerical_solver(
109
124
  self,
110
125
  numerical_solver: NumericalSolver,
111
- coast_duration_segment: TrajectorySegment,
126
+ coast_duration_segment: Segment,
112
127
  ):
113
128
  assert coast_duration_segment.get_numerical_solver() == numerical_solver
114
129
 
115
130
  def test_get_type(
116
131
  self,
117
- coast_duration_segment: TrajectorySegment,
132
+ coast_duration_segment: Segment,
118
133
  ):
119
- assert coast_duration_segment.get_type() == TrajectorySegment.Type.Coast
134
+ assert coast_duration_segment.get_type() == Segment.Type.Coast
135
+
136
+ def test_coast(
137
+ self,
138
+ name: str,
139
+ instant_condition: InstantCondition,
140
+ dynamics: list,
141
+ numerical_solver: NumericalSolver,
142
+ ):
143
+ assert (
144
+ Segment.coast(name, instant_condition, dynamics, numerical_solver) is not None
145
+ )
146
+
147
+ def test_maneuver(
148
+ self,
149
+ name: str,
150
+ instant_condition: InstantCondition,
151
+ thruster_dynamics: ConstantThrust,
152
+ dynamics: list,
153
+ numerical_solver: NumericalSolver,
154
+ ):
155
+ assert (
156
+ Segment.maneuver(
157
+ name, instant_condition, thruster_dynamics, dynamics, numerical_solver
158
+ )
159
+ is not None
160
+ )
120
161
 
121
162
  def test_solve(
122
163
  self,
123
164
  state: State,
124
165
  end_instant: Instant,
125
- coast_duration_segment: TrajectorySegment,
166
+ coast_duration_segment: Segment,
126
167
  ):
127
168
  solution = coast_duration_segment.solve(state)
128
169
 
@@ -0,0 +1,379 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ import numpy as np
6
+
7
+ from ostk.mathematics.geometry.d3.objects import Composite
8
+ from ostk.mathematics.geometry.d3.objects import Cuboid
9
+ from ostk.mathematics.geometry.d3.objects import Point
10
+
11
+ from ostk.physics import Environment
12
+ from ostk.physics.coordinate import Frame
13
+ from ostk.physics.environment.atmospheric import Earth as EarthAtmosphericModel
14
+ from ostk.physics.environment.gravitational import Earth as EarthGravitationalModel
15
+ from ostk.physics.environment.magnetic import Earth as EarthMagneticModel
16
+ from ostk.physics.environment.objects.celestial_bodies import Earth
17
+ from ostk.physics.time import DateTime
18
+ from ostk.physics.time import Duration
19
+ from ostk.physics.time import Instant
20
+ from ostk.physics.time import Scale
21
+ from ostk.physics.units import Derived
22
+ from ostk.physics.units import Length
23
+ from ostk.physics.units import Mass
24
+
25
+ from ostk.astrodynamics.event_condition import COECondition
26
+ from ostk.astrodynamics.event_condition import InstantCondition
27
+ from ostk.astrodynamics.event_condition import RealCondition
28
+ from ostk.astrodynamics.flight.system import Dynamics
29
+ from ostk.astrodynamics.flight.system import PropulsionSystem
30
+ from ostk.astrodynamics.flight.system import SatelliteSystem
31
+ from ostk.astrodynamics.flight.system.dynamics.thruster import ConstantThrust
32
+ from ostk.astrodynamics.trajectory import LocalOrbitalFrameDirection
33
+ from ostk.astrodynamics.trajectory import LocalOrbitalFrameFactory
34
+ from ostk.astrodynamics.trajectory import Segment
35
+ from ostk.astrodynamics.trajectory import Sequence
36
+ from ostk.astrodynamics.trajectory import State
37
+ from ostk.astrodynamics.trajectory.state import CoordinatesBroker
38
+ from ostk.astrodynamics.trajectory.state import CoordinatesSubset
39
+ from ostk.astrodynamics.trajectory.state import NumericalSolver
40
+ from ostk.astrodynamics.trajectory.state.coordinates_subset import CartesianPosition
41
+ from ostk.astrodynamics.trajectory.state.coordinates_subset import CartesianVelocity
42
+
43
+
44
+ @pytest.fixture
45
+ def propulsion_system() -> PropulsionSystem:
46
+ return PropulsionSystem(
47
+ 1.0,
48
+ 1500.0,
49
+ )
50
+
51
+
52
+ @pytest.fixture
53
+ def dry_mass() -> Mass:
54
+ return Mass.kilograms(100.0)
55
+
56
+
57
+ @pytest.fixture
58
+ def wet_mass() -> Mass:
59
+ return Mass.kilograms(10.0)
60
+
61
+
62
+ @pytest.fixture
63
+ def cross_sectional_surface_area() -> float:
64
+ return 1.0
65
+
66
+
67
+ @pytest.fixture
68
+ def drag_coefficient() -> float:
69
+ return 2.2
70
+
71
+
72
+ @pytest.fixture
73
+ def satellite_system(
74
+ dry_mass: Mass,
75
+ cross_sectional_surface_area: float,
76
+ drag_coefficient: float,
77
+ propulsion_system: PropulsionSystem,
78
+ ) -> SatelliteSystem:
79
+ satellite_geometry = Composite(
80
+ Cuboid(
81
+ Point(0.0, 0.0, 0.0),
82
+ [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]],
83
+ [1.0, 0.0, 0.0],
84
+ )
85
+ )
86
+ inertia_tensor = np.ndarray(shape=(3, 3))
87
+
88
+ return SatelliteSystem(
89
+ dry_mass,
90
+ satellite_geometry,
91
+ inertia_tensor,
92
+ cross_sectional_surface_area,
93
+ drag_coefficient,
94
+ propulsion_system,
95
+ )
96
+
97
+
98
+ @pytest.fixture
99
+ def environment() -> Environment:
100
+ return Environment(
101
+ Instant.J2000(),
102
+ [
103
+ Earth.from_models(
104
+ EarthGravitationalModel(EarthGravitationalModel.Type.Spherical),
105
+ EarthMagneticModel(EarthMagneticModel.Type.Undefined),
106
+ EarthAtmosphericModel(EarthAtmosphericModel.Type.Exponential),
107
+ )
108
+ ],
109
+ )
110
+
111
+
112
+ @pytest.fixture
113
+ def coordinates_broker() -> CoordinatesBroker:
114
+ return CoordinatesBroker(
115
+ [
116
+ CartesianPosition.default(),
117
+ CartesianVelocity.default(),
118
+ CoordinatesSubset.mass(),
119
+ CoordinatesSubset.surface_area(),
120
+ CoordinatesSubset.drag_coefficient(),
121
+ ]
122
+ )
123
+
124
+
125
+ @pytest.fixture
126
+ def cartesian_coordinates() -> list[float]:
127
+ return [
128
+ 717094.039086306,
129
+ -6872433.2241124,
130
+ 46175.9696673281,
131
+ -970.650826004612,
132
+ -45.4598114773158,
133
+ 7529.82424886455,
134
+ ]
135
+
136
+
137
+ @pytest.fixture
138
+ def state(
139
+ cartesian_coordinates: list[float],
140
+ dry_mass: Mass,
141
+ wet_mass: Mass,
142
+ cross_sectional_surface_area: float,
143
+ drag_coefficient: float,
144
+ coordinates_broker: CoordinatesBroker,
145
+ ) -> State:
146
+ frame: Frame = Frame.GCRF()
147
+ instant: Instant = Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC)
148
+ coordinates = [
149
+ *cartesian_coordinates,
150
+ dry_mass.in_kilograms() + wet_mass.in_kilograms(),
151
+ cross_sectional_surface_area,
152
+ drag_coefficient,
153
+ ]
154
+
155
+ return State(
156
+ instant,
157
+ [
158
+ 717094.039086306,
159
+ -6872433.2241124,
160
+ 46175.9696673281,
161
+ -970.650826004612,
162
+ -45.4598114773158,
163
+ 7529.82424886455,
164
+ dry_mass.in_kilograms() + wet_mass.in_kilograms(),
165
+ cross_sectional_surface_area,
166
+ drag_coefficient,
167
+ ],
168
+ frame,
169
+ coordinates_broker,
170
+ )
171
+
172
+
173
+ @pytest.fixture
174
+ def dynamics(environment: Environment) -> list:
175
+ return Dynamics.from_environment(environment)
176
+
177
+
178
+ @pytest.fixture
179
+ def numerical_solver() -> NumericalSolver:
180
+ return NumericalSolver.default_conditional()
181
+
182
+
183
+ @pytest.fixture
184
+ def duration() -> Duration:
185
+ return Duration.minutes(5.0)
186
+
187
+
188
+ @pytest.fixture
189
+ def instant_condition(state: State, duration: Duration) -> InstantCondition:
190
+ return InstantCondition(
191
+ RealCondition.Criterion.AnyCrossing, state.get_instant() + duration
192
+ )
193
+
194
+
195
+ @pytest.fixture
196
+ def sma() -> Length:
197
+ return Length.kilometers(6907.000)
198
+
199
+
200
+ @pytest.fixture
201
+ def gravitational_parameter() -> Derived:
202
+ return EarthGravitationalModel.spherical.gravitational_parameter
203
+
204
+
205
+ @pytest.fixture
206
+ def constant_thrust(satellite_system: SatelliteSystem) -> ConstantThrust:
207
+ return ConstantThrust(
208
+ satellite_system=satellite_system,
209
+ thrust_direction=LocalOrbitalFrameDirection(
210
+ vector=[1.0, 0.0, 0.0],
211
+ local_orbital_frame_factory=LocalOrbitalFrameFactory.VNC(Frame.GCRF()),
212
+ ),
213
+ )
214
+
215
+
216
+ @pytest.fixture
217
+ def sma_condition(sma: Length, gravitational_parameter: Derived) -> COECondition:
218
+ return COECondition.semi_major_axis(
219
+ criterion=RealCondition.Criterion.AnyCrossing,
220
+ frame=Frame.GCRF(),
221
+ semi_major_axis=sma,
222
+ gravitational_parameter=gravitational_parameter,
223
+ )
224
+
225
+
226
+ @pytest.fixture
227
+ def coast_duration_segment(
228
+ instant_condition: InstantCondition,
229
+ dynamics: list[Dynamics],
230
+ numerical_solver: NumericalSolver,
231
+ ):
232
+ return Segment.coast(
233
+ name="duration coast",
234
+ event_condition=instant_condition,
235
+ dynamics=dynamics,
236
+ numerical_solver=numerical_solver,
237
+ )
238
+
239
+
240
+ @pytest.fixture
241
+ def coast_sma_segment(
242
+ sma_condition: COECondition,
243
+ dynamics: list[Dynamics],
244
+ numerical_solver: NumericalSolver,
245
+ ):
246
+ return Segment.coast(
247
+ name="sma coast",
248
+ event_condition=sma_condition,
249
+ dynamics=dynamics,
250
+ numerical_solver=numerical_solver,
251
+ )
252
+
253
+
254
+ @pytest.fixture
255
+ def thrust_segment(
256
+ sma_condition: RealCondition,
257
+ constant_thrust: ConstantThrust,
258
+ dynamics: list[Dynamics],
259
+ numerical_solver: NumericalSolver,
260
+ ):
261
+ return Segment.maneuver(
262
+ name="duration thrust",
263
+ event_condition=sma_condition,
264
+ thruster_dynamics=constant_thrust,
265
+ dynamics=dynamics,
266
+ numerical_solver=numerical_solver,
267
+ )
268
+
269
+
270
+ @pytest.fixture
271
+ def segments(
272
+ coast_duration_segment: Segment,
273
+ thrust_segment: Segment,
274
+ ) -> list[Segment]:
275
+ return [coast_duration_segment, thrust_segment]
276
+
277
+
278
+ @pytest.fixture
279
+ def maximum_propagation_duration() -> Duration:
280
+ return Duration.days(2.0)
281
+
282
+
283
+ @pytest.fixture
284
+ def repetition_count() -> int:
285
+ return 1
286
+
287
+
288
+ @pytest.fixture
289
+ def sequence(
290
+ segments: list[Segment],
291
+ repetition_count: int,
292
+ numerical_solver: NumericalSolver,
293
+ dynamics: list,
294
+ maximum_propagation_duration: Duration,
295
+ ):
296
+ return Sequence(
297
+ segments=segments,
298
+ repetition_count=repetition_count,
299
+ dynamics=dynamics,
300
+ numerical_solver=numerical_solver,
301
+ maximum_propagation_duration=maximum_propagation_duration,
302
+ )
303
+
304
+
305
+ class TestSequence:
306
+ def test_get_segments(
307
+ self,
308
+ sequence: Sequence,
309
+ segments: list[Segment],
310
+ ):
311
+ assert len(sequence.get_segments()) == len(segments)
312
+
313
+ def test_get_numerical_solver(
314
+ self,
315
+ sequence: Sequence,
316
+ numerical_solver: NumericalSolver,
317
+ ):
318
+ assert sequence.get_numerical_solver() == numerical_solver
319
+
320
+ def test_get_dynamics(
321
+ self,
322
+ sequence: Sequence,
323
+ dynamics: list,
324
+ ):
325
+ assert len(sequence.get_dynamics()) == len(dynamics)
326
+
327
+ def test_get_maximum_propagation_duration(
328
+ self,
329
+ sequence: Sequence,
330
+ maximum_propagation_duration: Duration,
331
+ ):
332
+ assert sequence.get_maximum_propagation_duration() == maximum_propagation_duration
333
+
334
+ def test_add_segment(
335
+ self,
336
+ sequence: Sequence,
337
+ coast_duration_segment: Segment,
338
+ ):
339
+ segments_count: int = len(sequence.get_segments())
340
+
341
+ sequence.add_segment(coast_duration_segment)
342
+
343
+ assert len(sequence.get_segments()) == segments_count + 1
344
+
345
+ segments_count = len(sequence.get_segments())
346
+
347
+ sequence.add_segment([coast_duration_segment, coast_duration_segment])
348
+
349
+ assert len(sequence.get_segments()) == segments_count + 2
350
+
351
+ def test_add_coast_segment(
352
+ self,
353
+ sequence: Sequence,
354
+ instant_condition: InstantCondition,
355
+ ):
356
+ segments_count: int = len(sequence.get_segments())
357
+
358
+ sequence.add_coast_segment(instant_condition)
359
+
360
+ assert len(sequence.get_segments()) == segments_count + 1
361
+
362
+ def test_add_maneuver_segment(
363
+ self,
364
+ sequence: Sequence,
365
+ instant_condition: InstantCondition,
366
+ constant_thrust: ConstantThrust,
367
+ ):
368
+ segments_count: int = len(sequence.get_segments())
369
+
370
+ sequence.add_maneuver_segment(instant_condition, constant_thrust)
371
+
372
+ assert len(sequence.get_segments()) == segments_count + 1
373
+
374
+ def test_solve(self, state: State, sequence: Sequence, segments: list[Segment]):
375
+ solution = sequence.solve(state)
376
+
377
+ assert len(solution.segment_solutions) == len(segments)
378
+
379
+ assert solution.get_states() is not None
@@ -102,6 +102,7 @@ class TestState:
102
102
  position: Position,
103
103
  velocity: Velocity,
104
104
  frame: Frame,
105
+ coordinates_broker: CoordinatesBroker,
105
106
  ):
106
107
  assert state.get_instant() == instant
107
108
  assert state.get_position() == position
@@ -111,6 +112,7 @@ class TestState:
111
112
  state.get_coordinates()
112
113
  == np.append(position.get_coordinates(), velocity.get_coordinates())
113
114
  ).all()
115
+ assert state.get_coordinates_subsets() == coordinates_broker.get_subsets()
114
116
 
115
117
  def test_in_frame(
116
118
  self,