open-space-toolkit-astrodynamics 16.8.0__py313-none-manylinux2014_aarch64.whl → 16.9.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.
- {open_space_toolkit_astrodynamics-16.8.0.dist-info → open_space_toolkit_astrodynamics-16.9.0.dist-info}/METADATA +1 -1
- {open_space_toolkit_astrodynamics-16.8.0.dist-info → open_space_toolkit_astrodynamics-16.9.0.dist-info}/RECORD +17 -16
- ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-313-aarch64-linux-gnu.so +0 -0
- ostk/astrodynamics/__init__.pyi +4 -4
- ostk/astrodynamics/dynamics.pyi +1 -1
- ostk/astrodynamics/flight/__init__.pyi +29 -1
- ostk/astrodynamics/guidance_law.pyi +82 -7
- ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.16 +0 -0
- ostk/astrodynamics/test/dynamics/test_thruster.py +21 -6
- ostk/astrodynamics/test/flight/test_maneuver.py +37 -3
- ostk/astrodynamics/test/guidance_law/test_constant_thrust.py +87 -1
- ostk/astrodynamics/test/guidance_law/test_heterogeneous_guidance_law.py +164 -0
- ostk/astrodynamics/test/trajectory/test_segment.py +107 -2
- ostk/astrodynamics/trajectory/__init__.pyi +24 -0
- {open_space_toolkit_astrodynamics-16.8.0.dist-info → open_space_toolkit_astrodynamics-16.9.0.dist-info}/WHEEL +0 -0
- {open_space_toolkit_astrodynamics-16.8.0.dist-info → open_space_toolkit_astrodynamics-16.9.0.dist-info}/top_level.txt +0 -0
- {open_space_toolkit_astrodynamics-16.8.0.dist-info → open_space_toolkit_astrodynamics-16.9.0.dist-info}/zip-safe +0 -0
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
ostk/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
|
|
2
|
-
ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-313-aarch64-linux-gnu.so,sha256=
|
|
2
|
+
ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-313-aarch64-linux-gnu.so,sha256=A8Qv3TCkK7bZUxzT1ZaSXgGslyBF8RNv4-FArg6smQo,2693512
|
|
3
3
|
ostk/astrodynamics/__init__.py,sha256=3gWyqFIbhAfcdeMhmfBPQPlPQTmaOzm-6flkJe745Zk,251
|
|
4
|
-
ostk/astrodynamics/__init__.pyi,sha256=
|
|
4
|
+
ostk/astrodynamics/__init__.pyi,sha256=wUzGQSogTjxlQuTfsfV5CkW1PHTiA2zBY0O7_nd8bGA,32224
|
|
5
5
|
ostk/astrodynamics/access.pyi,sha256=pp2t81kKH4sP4BcGb8nAZHmpwhISjFODMpbZ4ucLFAw,25157
|
|
6
6
|
ostk/astrodynamics/converters.py,sha256=luPh30qMp9bzEkN7hUccmxlLf7zRp_AzqmBe8IUjPhU,3314
|
|
7
7
|
ostk/astrodynamics/converters.pyi,sha256=tTUT0xGbiUkKxUj79Hq5EEtxV3b2uR6Wsnj_vwyj-mk,1625
|
|
8
8
|
ostk/astrodynamics/dataframe.py,sha256=v-36rBHKdf7kQw1jdvJWrvkR-ZjW5DKRchtTEJWhdxk,25012
|
|
9
9
|
ostk/astrodynamics/display.py,sha256=D9PrX1G-XmXk2j3Jl7Na7q52PTc4WKWB1-oRFJPT6w0,8606
|
|
10
|
-
ostk/astrodynamics/dynamics.pyi,sha256=
|
|
10
|
+
ostk/astrodynamics/dynamics.pyi,sha256=12t5esJJ18YmCeD2-8Glcb4JPOs6vl2c6QeUaDCel9E,13308
|
|
11
11
|
ostk/astrodynamics/eclipse.pyi,sha256=Q8fzdukA7fyxbUM3wjEXAHukT-Ovl4FM00NbjsMPnUM,3211
|
|
12
12
|
ostk/astrodynamics/estimator.pyi,sha256=MnahWzp8aACxrNKWlYRsgQr5zpBxogNr-yPm7hJob5k,14000
|
|
13
13
|
ostk/astrodynamics/event_condition.pyi,sha256=2c_1Sq7tkYKeAA_aRWBi43KDQXXxu6EMSmUpEWz_Fa4,45814
|
|
14
|
-
ostk/astrodynamics/guidance_law.pyi,sha256=
|
|
15
|
-
ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.16,sha256=
|
|
14
|
+
ostk/astrodynamics/guidance_law.pyi,sha256=Xtqneu5PLpidOoSH4YIAY3D8rWZ0QH_ESqEdfbiTBVQ,16936
|
|
15
|
+
ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.16,sha256=64f3DTQELHsOR76LlOG8924thWDsmLMbodCKz2JgDQM,4036632
|
|
16
16
|
ostk/astrodynamics/solver.pyi,sha256=dRdR9RLqwSaBBX_ZRmpeBv06WvM_BFNo3WUdNzorYTY,17805
|
|
17
17
|
ostk/astrodynamics/utilities.py,sha256=y8mr3M46J5z-GhS1oIEnuEJA6otwcyJ9YDhvn_5JxHM,6976
|
|
18
18
|
ostk/astrodynamics/viewer.py,sha256=SlKyOWKjaF3V9HFB3I7ZgHy7n_GLeHTWM9q2wXkpxe8,27077
|
|
@@ -21,7 +21,7 @@ ostk/astrodynamics/conjunction/message/__init__.pyi,sha256=5H__sg_QUx7ybf9jtVWvX
|
|
|
21
21
|
ostk/astrodynamics/conjunction/message/ccsds.pyi,sha256=1Peto19hRqlD7KHf1cyLP3CT4OAKzwtemqvO6_4FZ0g,28162
|
|
22
22
|
ostk/astrodynamics/data/__init__.pyi,sha256=4l_mfVbnU_L7wImwgTCe8fVI81gK_tUmd0z7BY9lLi8,81
|
|
23
23
|
ostk/astrodynamics/data/provider.pyi,sha256=O4Lg9FBq9itufgATnic5SMg90pn8vJJJMUdNcWP72NI,1492
|
|
24
|
-
ostk/astrodynamics/flight/__init__.pyi,sha256=
|
|
24
|
+
ostk/astrodynamics/flight/__init__.pyi,sha256=VL6OTS5uFz9xEVQ-enHz5FinFTS283nBAztEn4uGNJw,25865
|
|
25
25
|
ostk/astrodynamics/flight/system.pyi,sha256=WVxy6Oe4q3C81c0AOxSwAmnwUHcpXO7JCEvESjs2g4A,10508
|
|
26
26
|
ostk/astrodynamics/flight/profile/__init__.pyi,sha256=WBTG17V59UwD-X1r6TOrXT_rA3WjKY-2ML1cWfji_4g,3688
|
|
27
27
|
ostk/astrodynamics/flight/profile/model.pyi,sha256=wwnVaTjTytxPqKyNo1tpdZRedabQlIHgyxfT0nivO5M,7777
|
|
@@ -56,7 +56,7 @@ ostk/astrodynamics/test/dynamics/test_dynamics.py,sha256=4VHL3Khbh8qTBKZw7m-4gSU
|
|
|
56
56
|
ostk/astrodynamics/test/dynamics/test_position_derivative.py,sha256=JRuq-oRrJfisbN75OnE-ldm6TeYcIc0qYaGVMflbn2g,1610
|
|
57
57
|
ostk/astrodynamics/test/dynamics/test_tabulated.py,sha256=qFHA7nmcvJtWucpCOYHAFmNRtImhTGlAZ0CHGEadeX8,4029
|
|
58
58
|
ostk/astrodynamics/test/dynamics/test_third_body_gravity.py,sha256=7xBOKbVio-zZ2-QQaje152cP38n_ALAaR5x6QIdBmXE,1879
|
|
59
|
-
ostk/astrodynamics/test/dynamics/test_thruster.py,sha256=
|
|
59
|
+
ostk/astrodynamics/test/dynamics/test_thruster.py,sha256=MJicjTLJCiULNgBk10ZVrZF5Bi3nRb3UZPWVcrpnxz8,4746
|
|
60
60
|
ostk/astrodynamics/test/dynamics/data/Tabulated_Earth_Gravity.csv,sha256=jJWOMJcQ83Vy1Wrb9PTh3ffOdoDF98kk6w5b-_E0uWg,47419
|
|
61
61
|
ostk/astrodynamics/test/dynamics/data/Tabulated_Earth_Gravity_Truth.csv,sha256=f4x-zmxZADxD_doAbACt24k36VSTp3rSIJiSzuSroKs,8377
|
|
62
62
|
ostk/astrodynamics/test/eclipse/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
|
|
@@ -71,7 +71,7 @@ ostk/astrodynamics/test/event_condition/test_instant_condition.py,sha256=Qr5dN6n
|
|
|
71
71
|
ostk/astrodynamics/test/event_condition/test_logical_condition.py,sha256=09h5TYWtwGt4NQW3k_tziiVs0Q2981rNII9wyKg7p2Q,3321
|
|
72
72
|
ostk/astrodynamics/test/event_condition/test_real_condition.py,sha256=tle6HVzMFMIIkfRY7CuaA0mPtw3riJBG_JQkc1L0dpk,1374
|
|
73
73
|
ostk/astrodynamics/test/flight/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
|
|
74
|
-
ostk/astrodynamics/test/flight/test_maneuver.py,sha256=
|
|
74
|
+
ostk/astrodynamics/test/flight/test_maneuver.py,sha256=7ZiMHrmGfSopjXm2Z3L1fXvDCJ646zVRcVyTk8f7rxY,6905
|
|
75
75
|
ostk/astrodynamics/test/flight/test_profile.py,sha256=U1l7pbFYrUjjxYBotQ3ujrvBxnBcyWgTrKwVHHClStc,8602
|
|
76
76
|
ostk/astrodynamics/test/flight/test_system.py,sha256=5kJCULHdpkwAC7i6xLV7vdJnGfOdrOuhi0G22p_L160,1224
|
|
77
77
|
ostk/astrodynamics/test/flight/profile/model/test_tabulated_profile.py,sha256=NZVa9dXzp4UDmohAlBaYeY594CPbqIv5j3VSEzlbYHk,3168
|
|
@@ -79,8 +79,9 @@ ostk/astrodynamics/test/flight/system/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5n
|
|
|
79
79
|
ostk/astrodynamics/test/flight/system/test_propulsion_system.py,sha256=SoxOt-fjHvs_86f6Xb3jAsHDOShJ6Puz7eO5wrqibaM,1835
|
|
80
80
|
ostk/astrodynamics/test/flight/system/test_satellite_system.py,sha256=dCFcl2RKiLxDKLI0sytPBXr3vHOFQIVNNCzpw5WzlAA,2437
|
|
81
81
|
ostk/astrodynamics/test/flight/system/test_satellite_system_builder.py,sha256=QCk70dPcptvdpWQOxtYR0-iGnlbtOIx2V6oO0UhYIQ0,2426
|
|
82
|
-
ostk/astrodynamics/test/guidance_law/test_constant_thrust.py,sha256=
|
|
82
|
+
ostk/astrodynamics/test/guidance_law/test_constant_thrust.py,sha256=y7VaKuJ8oCVEDeZL62oWepcmmYKG-9Za2Ebjn8lVR7Y,5381
|
|
83
83
|
ostk/astrodynamics/test/guidance_law/test_guidance_law.py,sha256=4ElWLS9ovnYBcj5HwJI3a6R9wrSLxyb_VMvxcCLDrKE,1560
|
|
84
|
+
ostk/astrodynamics/test/guidance_law/test_heterogeneous_guidance_law.py,sha256=qqIahgqFNhBjAe6RrztR0mR1XQ7ztXO-q7_pkpiKLWo,5076
|
|
84
85
|
ostk/astrodynamics/test/guidance_law/test_qlaw.py,sha256=kZaBZeU_J8Qk2nFnnpSuu-2NXT_13g3vLamG--eZfeU,3634
|
|
85
86
|
ostk/astrodynamics/test/solvers/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
|
|
86
87
|
ostk/astrodynamics/test/solvers/test_finite_difference_solver.py,sha256=0tcarIg2HTpcdzItWlL5Kd6q2nHcDBA8ZE0D3ugUN_s,5953
|
|
@@ -92,7 +93,7 @@ ostk/astrodynamics/test/trajectory/test_local_orbital_frame_factory.py,sha256=s1
|
|
|
92
93
|
ostk/astrodynamics/test/trajectory/test_model.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
|
|
93
94
|
ostk/astrodynamics/test/trajectory/test_orbit.py,sha256=EwqQejhcSqYhKPCAkjxyBLgEc82fOhrh1zrJ86RGO9Q,7011
|
|
94
95
|
ostk/astrodynamics/test/trajectory/test_propagator.py,sha256=ALjMvzndO9r6dVVXllk0iqu61tEoqu2j25MtzEitDIQ,14076
|
|
95
|
-
ostk/astrodynamics/test/trajectory/test_segment.py,sha256=
|
|
96
|
+
ostk/astrodynamics/test/trajectory/test_segment.py,sha256=u4AdttP27r2usLaaBthoSivofxKUyoQdH7dAeKEc9-E,16046
|
|
96
97
|
ostk/astrodynamics/test/trajectory/test_sequence.py,sha256=4piYpMZ9C_eCXxaOcdz2We67wZxhsNBnETgKwvq6dl0,15083
|
|
97
98
|
ostk/astrodynamics/test/trajectory/test_state.py,sha256=JO-SnUCRZ6sfVNwB5soT5c1f8c5DXuFN5lHZkiiTcYc,18119
|
|
98
99
|
ostk/astrodynamics/test/trajectory/test_state_builder.py,sha256=LpCCYdCaLu_D2npm9wgA2sMlcekrtbRqP-afe5IE5L4,4871
|
|
@@ -128,7 +129,7 @@ ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_attitude_quatern
|
|
|
128
129
|
ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_acceleration.py,sha256=1p37_FYN85d9SrOqO3iCkNecovJJayhnFeZ4QCOw2ao,3528
|
|
129
130
|
ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_position.py,sha256=XvHdk1KjacTwtkgx2jUAc9I9N3nvjPDv03FAanpv8jQ,2702
|
|
130
131
|
ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_velocity.py,sha256=-kd5TZO5TICihbkqDTew2i_tDpggdpe3Yf23046FATM,3057
|
|
131
|
-
ostk/astrodynamics/trajectory/__init__.pyi,sha256=
|
|
132
|
+
ostk/astrodynamics/trajectory/__init__.pyi,sha256=W7m5x95ofyR-GnBdVVrBf4uQQ9_GfXXzheDtlXq9ZgA,78464
|
|
132
133
|
ostk/astrodynamics/trajectory/model.pyi,sha256=SIneZx3pQ6XAo6iBccr4B1OsATbs1PEsCngtaTvja00,10473
|
|
133
134
|
ostk/astrodynamics/trajectory/orbit/__init__.pyi,sha256=wbuRK7Yp_NYBr3ta5-NpnJYMX4baUl7yIlUWhaRlR4o,12899
|
|
134
135
|
ostk/astrodynamics/trajectory/orbit/message/__init__.pyi,sha256=-GNBlYPrsjelhKxWorYQYhIWzFsibiIQNZvMXjhRpfM,77
|
|
@@ -139,8 +140,8 @@ ostk/astrodynamics/trajectory/orbit/model/kepler.pyi,sha256=KL-FwPbG4OUkPjhQb1Pa
|
|
|
139
140
|
ostk/astrodynamics/trajectory/orbit/model/sgp4.pyi,sha256=OhFzoPPQHlYy7m3LiZ8TXF89M4uBTfNk6tGsBEp0sjI,14235
|
|
140
141
|
ostk/astrodynamics/trajectory/state/__init__.pyi,sha256=bq__Fii35czVrTeNxc9eQVjXdqwbbQxUdNQWK3vLrMo,17649
|
|
141
142
|
ostk/astrodynamics/trajectory/state/coordinate_subset.pyi,sha256=kYMfMwEjCqO1NepMYFT4QS6kIPBkVL6sGCLeLbogcMw,10176
|
|
142
|
-
open_space_toolkit_astrodynamics-16.
|
|
143
|
-
open_space_toolkit_astrodynamics-16.
|
|
144
|
-
open_space_toolkit_astrodynamics-16.
|
|
145
|
-
open_space_toolkit_astrodynamics-16.
|
|
146
|
-
open_space_toolkit_astrodynamics-16.
|
|
143
|
+
open_space_toolkit_astrodynamics-16.9.0.dist-info/METADATA,sha256=gBHINQ0oyiWejSohb8XPjnxzlfl27qPJf5UrIM4YD-k,1913
|
|
144
|
+
open_space_toolkit_astrodynamics-16.9.0.dist-info/WHEEL,sha256=SoYeZtqoiLCL_G4rzH07IDMwRvSqG334rWZuI48h-Rk,111
|
|
145
|
+
open_space_toolkit_astrodynamics-16.9.0.dist-info/top_level.txt,sha256=zOR18699uDYnafgarhL8WU_LmTZY_5NVqutv-flp_x4,5
|
|
146
|
+
open_space_toolkit_astrodynamics-16.9.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
147
|
+
open_space_toolkit_astrodynamics-16.9.0.dist-info/RECORD,,
|
|
Binary file
|
ostk/astrodynamics/__init__.pyi
CHANGED
|
@@ -5,8 +5,8 @@ from ostk.astrodynamics.trajectory import State as PyState
|
|
|
5
5
|
from ostk import core as OpenSpaceToolkitCorePy
|
|
6
6
|
from ostk.core import container
|
|
7
7
|
from ostk.core import filesystem
|
|
8
|
-
from ostk.core import type
|
|
9
8
|
import ostk.core.type
|
|
9
|
+
from ostk.core import type
|
|
10
10
|
from ostk import io as OpenSpaceToolkitIOPy
|
|
11
11
|
from ostk.io import URL
|
|
12
12
|
from ostk.io import ip
|
|
@@ -14,18 +14,18 @@ from ostk import mathematics as OpenSpaceToolkitMathematicsPy
|
|
|
14
14
|
from ostk.mathematics import curve_fitting
|
|
15
15
|
from ostk.mathematics import geometry
|
|
16
16
|
from ostk.mathematics import object
|
|
17
|
-
from ostk import physics as OpenSpaceToolkitPhysicsPy
|
|
18
17
|
import ostk.physics
|
|
18
|
+
from ostk import physics as OpenSpaceToolkitPhysicsPy
|
|
19
19
|
from ostk.physics import Environment
|
|
20
20
|
from ostk.physics import Manager
|
|
21
21
|
from ostk.physics import Unit
|
|
22
|
-
import ostk.physics.coordinate
|
|
23
22
|
from ostk.physics import coordinate
|
|
23
|
+
import ostk.physics.coordinate
|
|
24
24
|
import ostk.physics.coordinate.spherical
|
|
25
25
|
from ostk.physics import environment
|
|
26
26
|
import ostk.physics.environment.object
|
|
27
|
-
from ostk.physics import time
|
|
28
27
|
import ostk.physics.time
|
|
28
|
+
from ostk.physics import time
|
|
29
29
|
from ostk.physics import unit
|
|
30
30
|
import ostk.physics.unit
|
|
31
31
|
import typing
|
ostk/astrodynamics/dynamics.pyi
CHANGED
|
@@ -270,7 +270,7 @@ class Thruster(ostk.astrodynamics.Dynamics):
|
|
|
270
270
|
Args:
|
|
271
271
|
satellite_system (SatelliteSystem): The satellite system.
|
|
272
272
|
guidance_law (GuidanceLaw): The guidance law used to compute the acceleration vector.
|
|
273
|
-
name (str): The name of the thruster.
|
|
273
|
+
name (str, optional): The name of the thruster. Defaults to String.empty().
|
|
274
274
|
"""
|
|
275
275
|
def __repr__(self) -> str:
|
|
276
276
|
...
|
|
@@ -84,6 +84,16 @@ class Maneuver:
|
|
|
84
84
|
Returns:
|
|
85
85
|
float: The delta-v value (m/s).
|
|
86
86
|
"""
|
|
87
|
+
def calculate_mean_thrust_direction_and_maximum_angular_offset(self, local_orbital_frame_factory: ostk.astrodynamics.trajectory.LocalOrbitalFrameFactory) -> tuple[ostk.astrodynamics.trajectory.LocalOrbitalFrameDirection, ostk.physics.unit.Angle]:
|
|
88
|
+
"""
|
|
89
|
+
Calculate the mean thrust direction in the Local Orbital Frame and its maximum angular offset w.r.t. the maneuver's thrust acceleration directions.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
local_orbital_frame_factory (LocalOrbitalFrameFactory): The local orbital frame factory.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
Tuple[LocalOrbitalFrameDirection, Angle]: The mean thrust direction and its maximum angular offset.
|
|
96
|
+
"""
|
|
87
97
|
def get_interval(self) -> ostk.physics.time.Interval:
|
|
88
98
|
"""
|
|
89
99
|
Get the interval of the maneuver.
|
|
@@ -105,6 +115,24 @@ class Maneuver:
|
|
|
105
115
|
Returns:
|
|
106
116
|
bool: True if the maneuver is defined, False otherwise. (Always returns true).
|
|
107
117
|
"""
|
|
118
|
+
def to_constant_local_orbital_frame_direction_maneuver(self, local_orbital_frame_factory: ostk.astrodynamics.trajectory.LocalOrbitalFrameFactory, maximum_allowed_angular_offset: ostk.physics.unit.Angle = ...) -> Maneuver:
|
|
119
|
+
"""
|
|
120
|
+
Create a maneuver with a constant thrust acceleration direction in the Local Orbital Frame.
|
|
121
|
+
|
|
122
|
+
The new Maneuver contains the same states as the original Maneuver, but the thrust acceleration direction is
|
|
123
|
+
constant in the Local Orbital Frame. Said direction is the mean direction of the thrust acceleration directions
|
|
124
|
+
in the Local Orbital Frame of the original Maneuver. The thrust acceleration magnitude profile is the same as the original.
|
|
125
|
+
|
|
126
|
+
If defined, a runtime error will be thrown if the maximum allowed angular offset between the original thrust acceleration direction
|
|
127
|
+
and the mean thrust direction is violated.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
local_orbital_frame_factory (LocalOrbitalFrameFactory): The local orbital frame factory.
|
|
131
|
+
maximum_allowed_angular_offset (Angle, optional): The maximum allowed angular offset to consider (if any). Defaults to Undefined.
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
Maneuver: The constant local orbital frame direction maneuver.
|
|
135
|
+
"""
|
|
108
136
|
def to_tabulated_dynamics(self, frame: ostk.physics.coordinate.Frame = ..., interpolation_type: ostk.mathematics.curve_fitting.Interpolator.Type = ...) -> ...:
|
|
109
137
|
"""
|
|
110
138
|
Convert the maneuver to tabulated dynamics.
|
|
@@ -200,7 +228,7 @@ class Profile:
|
|
|
200
228
|
Constructor.
|
|
201
229
|
|
|
202
230
|
Args:
|
|
203
|
-
orientation_profile (list[
|
|
231
|
+
orientation_profile (list[tuple[Instant, Vector3d]]): The orientation profile.
|
|
204
232
|
axis (Profile.Axis): The axis.
|
|
205
233
|
anti_direction (bool): True if the direction is flipped, False otherwise. Defaults to False.
|
|
206
234
|
"""
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
import numpy
|
|
3
3
|
import ostk.astrodynamics
|
|
4
|
+
import ostk.astrodynamics.flight
|
|
4
5
|
import ostk.astrodynamics.trajectory
|
|
5
6
|
import ostk.astrodynamics.trajectory.orbit.model.kepler
|
|
6
7
|
import ostk.core.type
|
|
@@ -8,26 +9,43 @@ import ostk.physics.coordinate
|
|
|
8
9
|
import ostk.physics.time
|
|
9
10
|
import ostk.physics.unit
|
|
10
11
|
import typing
|
|
11
|
-
__all__ = ['ConstantThrust', 'QLaw']
|
|
12
|
+
__all__ = ['ConstantThrust', 'HeterogeneousGuidanceLaw', 'QLaw']
|
|
12
13
|
class ConstantThrust(ostk.astrodynamics.GuidanceLaw):
|
|
13
14
|
"""
|
|
14
15
|
|
|
15
|
-
Constant Thrust, Constant Direction
|
|
16
|
+
Constant Thrust, Constant Direction guidance law.
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
"""
|
|
19
20
|
@staticmethod
|
|
21
|
+
def from_maneuver(maneuver: ostk.astrodynamics.flight.Maneuver, local_orbital_frame_factory: ostk.astrodynamics.trajectory.LocalOrbitalFrameFactory, maximum_allowed_angular_offset: ostk.physics.unit.Angle = ...) -> ConstantThrust:
|
|
22
|
+
"""
|
|
23
|
+
Create a constant thrust guidance law from a maneuver.
|
|
24
|
+
|
|
25
|
+
The local orbital frame maneuver's mean thrust direction is calculated and used to create a
|
|
26
|
+
constant thrust guidance law in said direction.
|
|
27
|
+
|
|
28
|
+
If defined, a runtime error will be thrown if the maximum allowed angular offset between the original thrust acceleration
|
|
29
|
+
direction and the mean thrust direction is violated.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
maneuver (Maneuver): The maneuver.
|
|
33
|
+
local_orbital_frame_factory (LocalOrbitalFrameFactory): The local orbital frame factory.
|
|
34
|
+
maximum_allowed_angular_offset (Angle, optional): The maximum allowed angular offset to consider (if any). Defaults to Undefined.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
ConstantThrust: The constant thrust guidance law.
|
|
38
|
+
"""
|
|
39
|
+
@staticmethod
|
|
20
40
|
def intrack(velocity_direction: bool = True) -> ConstantThrust:
|
|
21
41
|
"""
|
|
22
|
-
Create a constant thrust in the in-track direction.
|
|
42
|
+
Create a constant thrust guidance law in the in-track direction.
|
|
23
43
|
|
|
24
44
|
Args:
|
|
25
|
-
|
|
26
|
-
velocity_direction (bool, optional): If True, the thrust is applied in the velocity direction. Otherwise, it is applied in the opposite direction.
|
|
27
|
-
frame (Frame, optional): The reference frame.
|
|
45
|
+
velocity_direction (bool, optional): If True, the thrust is applied in the velocity direction. Otherwise, it is applied in the opposite direction. Defaults to True.
|
|
28
46
|
|
|
29
47
|
Returns:
|
|
30
|
-
ConstantThrust: The constant thrust.
|
|
48
|
+
ConstantThrust: The constant thrust guidance law in the in-track direction.
|
|
31
49
|
"""
|
|
32
50
|
def __init__(self, thrust_direction: ostk.astrodynamics.trajectory.LocalOrbitalFrameDirection) -> None:
|
|
33
51
|
"""
|
|
@@ -61,6 +79,63 @@ class ConstantThrust(ostk.astrodynamics.GuidanceLaw):
|
|
|
61
79
|
Returns:
|
|
62
80
|
LocalOrbitalFrameDirection: The local thrust direction.
|
|
63
81
|
"""
|
|
82
|
+
class HeterogeneousGuidanceLaw(ostk.astrodynamics.GuidanceLaw):
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
A guidance law that sequences multiple guidance laws over specific time intervals.
|
|
86
|
+
|
|
87
|
+
At each point in time, the applicable guidance law is selected and used to calculate
|
|
88
|
+
the thrust acceleration. Guidance laws don't need to be contiguous, and can be added
|
|
89
|
+
in any order. If the instant does not fall within any of the intervals, the thrust
|
|
90
|
+
acceleration is zero. The guidance law intervals must not intersect each other.
|
|
91
|
+
|
|
92
|
+
"""
|
|
93
|
+
def __init__(self, guidance_laws_with_intervals: list[tuple[ostk.astrodynamics.GuidanceLaw, ostk.physics.time.Interval]] = []) -> None:
|
|
94
|
+
"""
|
|
95
|
+
Constructor.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
guidance_laws_with_intervals (list[tuple[GuidanceLaw, Interval]], optional): Array of tuples containing the guidance laws and their corresponding intervals. Defaults to empty array.
|
|
99
|
+
|
|
100
|
+
Raises:
|
|
101
|
+
RuntimeError: If any interval is undefined, if the guidance law is null or if the interval intersects with an existing interval.
|
|
102
|
+
"""
|
|
103
|
+
def __repr__(self) -> str:
|
|
104
|
+
...
|
|
105
|
+
def __str__(self) -> str:
|
|
106
|
+
...
|
|
107
|
+
def add_guidance_law(self, guidance_law: ostk.astrodynamics.GuidanceLaw, interval: ostk.physics.time.Interval) -> None:
|
|
108
|
+
"""
|
|
109
|
+
Add a guidance law with its corresponding interval.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
guidance_law (GuidanceLaw): The guidance law to add.
|
|
113
|
+
interval (Interval): The interval during which the guidance law is active.
|
|
114
|
+
|
|
115
|
+
Raises:
|
|
116
|
+
RuntimeError: If the interval is undefined, if the guidance law is null or if the interval intersects with an existing interval.
|
|
117
|
+
"""
|
|
118
|
+
def calculate_thrust_acceleration_at(self, instant: ostk.physics.time.Instant, position_coordinates: numpy.ndarray[numpy.float64[3, 1]], velocity_coordinates: numpy.ndarray[numpy.float64[3, 1]], thrust_acceleration: ostk.core.type.Real, output_frame: ostk.physics.coordinate.Frame) -> numpy.ndarray[numpy.float64[3, 1]]:
|
|
119
|
+
"""
|
|
120
|
+
Calculate thrust acceleration at a given instant and state.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
instant (Instant): The instant.
|
|
124
|
+
position_coordinates (numpy.ndarray): The position coordinates.
|
|
125
|
+
velocity_coordinates (numpy.ndarray): The velocity coordinates.
|
|
126
|
+
thrust_acceleration (float): The thrust acceleration magnitude.
|
|
127
|
+
output_frame (Frame): The frame in which the acceleration is expressed.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
numpy.ndarray: The acceleration vector at the provided coordinates.
|
|
131
|
+
"""
|
|
132
|
+
def get_guidance_laws_with_intervals(self) -> list[tuple[ostk.astrodynamics.GuidanceLaw, ostk.physics.time.Interval]]:
|
|
133
|
+
"""
|
|
134
|
+
Get the guidance laws with their corresponding intervals.
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
list[tuple[GuidanceLaw, Interval]]: Array of tuples containing the guidance laws and their corresponding intervals.
|
|
138
|
+
"""
|
|
64
139
|
class QLaw(ostk.astrodynamics.GuidanceLaw):
|
|
65
140
|
"""
|
|
66
141
|
|
|
Binary file
|
|
@@ -22,7 +22,6 @@ from ostk.astrodynamics.trajectory.state import CoordinateBroker
|
|
|
22
22
|
from ostk.astrodynamics.trajectory import State
|
|
23
23
|
from ostk.astrodynamics.flight.system import PropulsionSystem
|
|
24
24
|
from ostk.astrodynamics.flight.system import SatelliteSystem
|
|
25
|
-
from ostk.astrodynamics import Dynamics
|
|
26
25
|
from ostk.astrodynamics.dynamics import Thruster
|
|
27
26
|
from ostk.astrodynamics.guidance_law import ConstantThrust
|
|
28
27
|
|
|
@@ -96,11 +95,27 @@ def state(coordinate_broker: CoordinateBroker) -> State:
|
|
|
96
95
|
|
|
97
96
|
|
|
98
97
|
class TestThruster:
|
|
99
|
-
def test_constructors(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
98
|
+
def test_constructors(
|
|
99
|
+
self,
|
|
100
|
+
guidance_law: ConstantThrust,
|
|
101
|
+
satellite_system: SatelliteSystem,
|
|
102
|
+
):
|
|
103
|
+
thrusters = [
|
|
104
|
+
Thruster(
|
|
105
|
+
satellite_system=satellite_system,
|
|
106
|
+
guidance_law=guidance_law,
|
|
107
|
+
),
|
|
108
|
+
Thruster(
|
|
109
|
+
satellite_system=satellite_system,
|
|
110
|
+
guidance_law=guidance_law,
|
|
111
|
+
name="A name",
|
|
112
|
+
),
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
for thruster in thrusters:
|
|
116
|
+
assert thruster is not None
|
|
117
|
+
assert isinstance(thruster, Thruster)
|
|
118
|
+
assert thruster.is_defined()
|
|
104
119
|
|
|
105
120
|
def test_getters(self, dynamics: Thruster):
|
|
106
121
|
assert dynamics.get_satellite_system() is not None
|
|
@@ -4,16 +4,18 @@ import pytest
|
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
|
|
7
|
-
|
|
8
7
|
from ostk.physics.time import Instant
|
|
9
8
|
from ostk.physics.time import Interval
|
|
10
9
|
from ostk.physics.time import Duration
|
|
11
10
|
from ostk.physics.coordinate import Frame
|
|
12
11
|
from ostk.physics.unit import Mass
|
|
12
|
+
from ostk.physics.unit import Angle
|
|
13
13
|
|
|
14
|
+
from ostk.astrodynamics.dynamics import Tabulated as TabulatedDynamics
|
|
14
15
|
from ostk.astrodynamics.flight import Maneuver
|
|
16
|
+
from ostk.astrodynamics.trajectory import LocalOrbitalFrameDirection
|
|
17
|
+
from ostk.astrodynamics.trajectory import LocalOrbitalFrameFactory
|
|
15
18
|
from ostk.astrodynamics.trajectory import State
|
|
16
|
-
from ostk.astrodynamics.dynamics import Tabulated as TabulatedDynamics
|
|
17
19
|
from ostk.astrodynamics.trajectory.state import CoordinateSubset
|
|
18
20
|
from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianPosition
|
|
19
21
|
from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianVelocity
|
|
@@ -184,12 +186,44 @@ class TestManeuver:
|
|
|
184
186
|
|
|
185
187
|
assert tabulated_dynamics.access_frame() == frame
|
|
186
188
|
|
|
189
|
+
def test_calculate_mean_thrust_direction_and_maximum_angular_offset(
|
|
190
|
+
self,
|
|
191
|
+
maneuver: Maneuver,
|
|
192
|
+
):
|
|
193
|
+
mean_thrust_direction_and_maximum_angular_offset = (
|
|
194
|
+
maneuver.calculate_mean_thrust_direction_and_maximum_angular_offset(
|
|
195
|
+
local_orbital_frame_factory=LocalOrbitalFrameFactory.TNW(Frame.GCRF()),
|
|
196
|
+
)
|
|
197
|
+
)
|
|
198
|
+
assert isinstance(
|
|
199
|
+
mean_thrust_direction_and_maximum_angular_offset[0],
|
|
200
|
+
LocalOrbitalFrameDirection,
|
|
201
|
+
)
|
|
202
|
+
assert isinstance(mean_thrust_direction_and_maximum_angular_offset[1], Angle)
|
|
203
|
+
|
|
204
|
+
def test_to_constant_local_orbital_frame_direction_maneuver(
|
|
205
|
+
self,
|
|
206
|
+
maneuver: Maneuver,
|
|
207
|
+
):
|
|
208
|
+
maneuver: Maneuver = maneuver.to_constant_local_orbital_frame_direction_maneuver(
|
|
209
|
+
local_orbital_frame_factory=LocalOrbitalFrameFactory.TNW(Frame.GCRF()),
|
|
210
|
+
)
|
|
211
|
+
assert maneuver.is_defined()
|
|
212
|
+
|
|
213
|
+
maneuver_with_maximum_allowed_angular_offset: Maneuver = (
|
|
214
|
+
maneuver.to_constant_local_orbital_frame_direction_maneuver(
|
|
215
|
+
local_orbital_frame_factory=LocalOrbitalFrameFactory.TNW(Frame.GCRF()),
|
|
216
|
+
maximum_allowed_angular_offset=Angle.degrees(180.0),
|
|
217
|
+
)
|
|
218
|
+
)
|
|
219
|
+
assert maneuver_with_maximum_allowed_angular_offset.is_defined()
|
|
220
|
+
|
|
187
221
|
def test_from_constant_mass_flow_rate(
|
|
188
222
|
self,
|
|
189
223
|
states: list[State],
|
|
190
224
|
):
|
|
191
225
|
mass_flow_rate: float = -1.0e-5
|
|
192
|
-
maneuver = Maneuver.constant_mass_flow_rate_profile(
|
|
226
|
+
maneuver: Maneuver = Maneuver.constant_mass_flow_rate_profile(
|
|
193
227
|
states=states,
|
|
194
228
|
mass_flow_rate=mass_flow_rate,
|
|
195
229
|
)
|
|
@@ -2,16 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
6
7
|
from ostk.physics.time import DateTime
|
|
8
|
+
from ostk.physics.time import Duration
|
|
9
|
+
from ostk.physics.time import Instant
|
|
7
10
|
from ostk.physics.time import Scale
|
|
11
|
+
from ostk.physics.unit import Angle
|
|
8
12
|
from ostk.physics.coordinate import Frame
|
|
9
13
|
|
|
10
14
|
from ostk.astrodynamics.trajectory import LocalOrbitalFrameFactory
|
|
11
15
|
from ostk.astrodynamics.trajectory import LocalOrbitalFrameDirection
|
|
12
16
|
|
|
13
17
|
from ostk.astrodynamics import GuidanceLaw
|
|
18
|
+
from ostk.astrodynamics.flight import Maneuver
|
|
14
19
|
from ostk.astrodynamics.guidance_law import ConstantThrust
|
|
20
|
+
from ostk.astrodynamics.trajectory import State
|
|
21
|
+
from ostk.astrodynamics.trajectory.state import CoordinateSubset
|
|
22
|
+
from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianPosition
|
|
23
|
+
from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianVelocity
|
|
24
|
+
from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianAcceleration
|
|
15
25
|
|
|
16
26
|
|
|
17
27
|
@pytest.fixture
|
|
@@ -54,6 +64,64 @@ def frame() -> Frame:
|
|
|
54
64
|
return Frame.GCRF()
|
|
55
65
|
|
|
56
66
|
|
|
67
|
+
@pytest.fixture
|
|
68
|
+
def instants() -> list[Instant]:
|
|
69
|
+
return [
|
|
70
|
+
Instant.J2000(),
|
|
71
|
+
Instant.J2000() + Duration.seconds(30.0),
|
|
72
|
+
Instant.J2000() + Duration.seconds(35.0),
|
|
73
|
+
Instant.J2000() + Duration.seconds(37.0),
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@pytest.fixture
|
|
78
|
+
def acceleration_profile() -> list[np.ndarray]:
|
|
79
|
+
return [
|
|
80
|
+
np.array([1.0e-3, 0.0e-3, 0.0e-3]),
|
|
81
|
+
np.array([0.0e-3, 1.0e-3, 0.0e-3]),
|
|
82
|
+
np.array([0.0e-3, 0.0e-3, 1.0e-3]),
|
|
83
|
+
np.array([1.0e-3, 1.0e-3, 1.0e-3]),
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@pytest.fixture
|
|
88
|
+
def mass_flow_rate_profile() -> list[float]:
|
|
89
|
+
return [-1.0e-5, -1.1e-5, -0.9e-5, -1.0e-5]
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@pytest.fixture
|
|
93
|
+
def coordinate_subsets() -> list[CoordinateSubset]:
|
|
94
|
+
return [
|
|
95
|
+
CartesianPosition.default(),
|
|
96
|
+
CartesianVelocity.default(),
|
|
97
|
+
CartesianAcceleration.thrust_acceleration(),
|
|
98
|
+
CoordinateSubset.mass_flow_rate(),
|
|
99
|
+
]
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@pytest.fixture
|
|
103
|
+
def maneuver(
|
|
104
|
+
instants: list[Instant],
|
|
105
|
+
acceleration_profile: list[np.ndarray],
|
|
106
|
+
mass_flow_rate_profile: list[float],
|
|
107
|
+
frame: Frame,
|
|
108
|
+
coordinate_subsets: list[CoordinateSubset],
|
|
109
|
+
) -> Maneuver:
|
|
110
|
+
states = []
|
|
111
|
+
for instant, acceleration, mass_flow_rate in zip(
|
|
112
|
+
instants, acceleration_profile, mass_flow_rate_profile
|
|
113
|
+
):
|
|
114
|
+
states.append(
|
|
115
|
+
State(
|
|
116
|
+
instant,
|
|
117
|
+
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, *acceleration, mass_flow_rate],
|
|
118
|
+
frame,
|
|
119
|
+
coordinate_subsets,
|
|
120
|
+
)
|
|
121
|
+
)
|
|
122
|
+
return Maneuver(states)
|
|
123
|
+
|
|
124
|
+
|
|
57
125
|
class TestConstantThrust:
|
|
58
126
|
def test_constructors(self, guidance_law: ConstantThrust):
|
|
59
127
|
assert guidance_law is not None
|
|
@@ -89,3 +157,21 @@ class TestConstantThrust:
|
|
|
89
157
|
|
|
90
158
|
assert len(contribution) == 3
|
|
91
159
|
assert contribution == pytest.approx([0.0, 0.009523809523809525, 0.0], abs=5e-11)
|
|
160
|
+
|
|
161
|
+
def test_from_maneuver(self, maneuver: Maneuver):
|
|
162
|
+
constant_thrust = ConstantThrust.from_maneuver(
|
|
163
|
+
maneuver=maneuver,
|
|
164
|
+
local_orbital_frame_factory=LocalOrbitalFrameFactory.TNW(Frame.GCRF()),
|
|
165
|
+
)
|
|
166
|
+
assert isinstance(constant_thrust, ConstantThrust)
|
|
167
|
+
|
|
168
|
+
constant_thrust_with_maximum_allowed_angular_offset = (
|
|
169
|
+
ConstantThrust.from_maneuver(
|
|
170
|
+
maneuver=maneuver,
|
|
171
|
+
local_orbital_frame_factory=LocalOrbitalFrameFactory.TNW(Frame.GCRF()),
|
|
172
|
+
maximum_allowed_angular_offset=Angle.degrees(180.0),
|
|
173
|
+
)
|
|
174
|
+
)
|
|
175
|
+
assert isinstance(
|
|
176
|
+
constant_thrust_with_maximum_allowed_angular_offset, ConstantThrust
|
|
177
|
+
)
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# Apache License 2.0
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from ostk.physics.coordinate import Frame
|
|
8
|
+
from ostk.physics.time import Instant
|
|
9
|
+
from ostk.physics.time import Duration
|
|
10
|
+
from ostk.physics.time import Interval
|
|
11
|
+
from ostk.astrodynamics import GuidanceLaw
|
|
12
|
+
from ostk.astrodynamics.guidance_law import HeterogeneousGuidanceLaw
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@pytest.fixture
|
|
16
|
+
def interval_1() -> Interval:
|
|
17
|
+
return Interval.closed(
|
|
18
|
+
start_instant=Instant.J2000(),
|
|
19
|
+
end_instant=Instant.J2000() + Duration.seconds(100.0),
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@pytest.fixture
|
|
24
|
+
def guidance_law_1() -> GuidanceLaw:
|
|
25
|
+
class GuidanceLaw1(GuidanceLaw):
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
name: str,
|
|
30
|
+
):
|
|
31
|
+
super().__init__(name)
|
|
32
|
+
|
|
33
|
+
def calculate_thrust_acceleration_at(
|
|
34
|
+
self,
|
|
35
|
+
instant: Instant,
|
|
36
|
+
position_coordinates: np.array,
|
|
37
|
+
velocity_coordinates: np.array,
|
|
38
|
+
thrust_acceleration: float,
|
|
39
|
+
output_frame: Frame,
|
|
40
|
+
) -> np.array:
|
|
41
|
+
return np.array([1.0, 2.0, 3.0])
|
|
42
|
+
|
|
43
|
+
return GuidanceLaw1("My Guidance Law 1")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@pytest.fixture
|
|
47
|
+
def interval_2() -> Interval:
|
|
48
|
+
return Interval.closed(
|
|
49
|
+
start_instant=Instant.J2000() + Duration.seconds(200.0),
|
|
50
|
+
end_instant=Instant.J2000() + Duration.seconds(300.0),
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@pytest.fixture
|
|
55
|
+
def guidance_law_2() -> GuidanceLaw:
|
|
56
|
+
class GuidanceLaw2(GuidanceLaw):
|
|
57
|
+
|
|
58
|
+
def __init__(
|
|
59
|
+
self,
|
|
60
|
+
name: str,
|
|
61
|
+
):
|
|
62
|
+
super().__init__(name)
|
|
63
|
+
|
|
64
|
+
def calculate_thrust_acceleration_at(
|
|
65
|
+
self,
|
|
66
|
+
instant: Instant,
|
|
67
|
+
position_coordinates: np.array,
|
|
68
|
+
velocity_coordinates: np.array,
|
|
69
|
+
thrust_acceleration: float,
|
|
70
|
+
output_frame: Frame,
|
|
71
|
+
) -> np.array:
|
|
72
|
+
return np.array([4.0, 5.0, 6.0])
|
|
73
|
+
|
|
74
|
+
return GuidanceLaw2("My Guidance Law 2")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@pytest.fixture
|
|
78
|
+
def heterogeneous_guidance_law(
|
|
79
|
+
interval_1: Interval,
|
|
80
|
+
guidance_law_1: GuidanceLaw,
|
|
81
|
+
interval_2: Interval,
|
|
82
|
+
guidance_law_2: GuidanceLaw,
|
|
83
|
+
) -> HeterogeneousGuidanceLaw:
|
|
84
|
+
return HeterogeneousGuidanceLaw(
|
|
85
|
+
guidance_laws_with_intervals=[
|
|
86
|
+
(guidance_law_1, interval_1),
|
|
87
|
+
(guidance_law_2, interval_2),
|
|
88
|
+
],
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class TestHeterogeneousGuidanceLaw:
|
|
93
|
+
def test_constructor_and_getters(
|
|
94
|
+
self,
|
|
95
|
+
interval_1: Interval,
|
|
96
|
+
guidance_law_1: GuidanceLaw,
|
|
97
|
+
interval_2: Interval,
|
|
98
|
+
guidance_law_2: GuidanceLaw,
|
|
99
|
+
):
|
|
100
|
+
heterogeneous_guidance_law = HeterogeneousGuidanceLaw(
|
|
101
|
+
guidance_laws_with_intervals=[
|
|
102
|
+
(guidance_law_1, interval_1),
|
|
103
|
+
(guidance_law_2, interval_2),
|
|
104
|
+
],
|
|
105
|
+
)
|
|
106
|
+
assert heterogeneous_guidance_law is not None
|
|
107
|
+
assert isinstance(heterogeneous_guidance_law, HeterogeneousGuidanceLaw)
|
|
108
|
+
assert heterogeneous_guidance_law.get_guidance_laws_with_intervals() == [
|
|
109
|
+
(guidance_law_1, interval_1),
|
|
110
|
+
(guidance_law_2, interval_2),
|
|
111
|
+
]
|
|
112
|
+
|
|
113
|
+
def test_add_guidance_law(
|
|
114
|
+
self,
|
|
115
|
+
interval_1: Interval,
|
|
116
|
+
guidance_law_1: GuidanceLaw,
|
|
117
|
+
interval_2: Interval,
|
|
118
|
+
guidance_law_2: GuidanceLaw,
|
|
119
|
+
):
|
|
120
|
+
heterogeneous_guidance_law = HeterogeneousGuidanceLaw()
|
|
121
|
+
|
|
122
|
+
assert isinstance(heterogeneous_guidance_law, HeterogeneousGuidanceLaw)
|
|
123
|
+
assert heterogeneous_guidance_law.get_guidance_laws_with_intervals() == []
|
|
124
|
+
|
|
125
|
+
heterogeneous_guidance_law.add_guidance_law(guidance_law_1, interval_1)
|
|
126
|
+
assert heterogeneous_guidance_law.get_guidance_laws_with_intervals() == [
|
|
127
|
+
(guidance_law_1, interval_1),
|
|
128
|
+
]
|
|
129
|
+
|
|
130
|
+
heterogeneous_guidance_law.add_guidance_law(guidance_law_2, interval_2)
|
|
131
|
+
assert heterogeneous_guidance_law.get_guidance_laws_with_intervals() == [
|
|
132
|
+
(guidance_law_1, interval_1),
|
|
133
|
+
(guidance_law_2, interval_2),
|
|
134
|
+
]
|
|
135
|
+
|
|
136
|
+
@pytest.mark.parametrize(
|
|
137
|
+
(
|
|
138
|
+
"instant",
|
|
139
|
+
"expected_thrust_acceleration",
|
|
140
|
+
),
|
|
141
|
+
[
|
|
142
|
+
(Instant.J2000() - Duration.seconds(50.0), np.array([0.0, 0.0, 0.0])),
|
|
143
|
+
(Instant.J2000() + Duration.seconds(50.0), np.array([1.0, 2.0, 3.0])),
|
|
144
|
+
(Instant.J2000() + Duration.seconds(150.0), np.array([0.0, 0.0, 0.0])),
|
|
145
|
+
(Instant.J2000() + Duration.seconds(250.0), np.array([4.0, 5.0, 6.0])),
|
|
146
|
+
(Instant.J2000() + Duration.seconds(350.0), np.array([0.0, 0.0, 0.0])),
|
|
147
|
+
],
|
|
148
|
+
)
|
|
149
|
+
def test_calculate_thrust_acceleration_at(
|
|
150
|
+
self,
|
|
151
|
+
heterogeneous_guidance_law: HeterogeneousGuidanceLaw,
|
|
152
|
+
instant: Instant,
|
|
153
|
+
expected_thrust_acceleration: np.array,
|
|
154
|
+
):
|
|
155
|
+
assert np.array_equal(
|
|
156
|
+
heterogeneous_guidance_law.calculate_thrust_acceleration_at(
|
|
157
|
+
instant=instant,
|
|
158
|
+
position_coordinates=np.array([0.0, 0.0, 0.0]),
|
|
159
|
+
velocity_coordinates=np.array([0.0, 0.0, 0.0]),
|
|
160
|
+
thrust_acceleration=1.0,
|
|
161
|
+
output_frame=Frame.GCRF(),
|
|
162
|
+
),
|
|
163
|
+
expected_thrust_acceleration,
|
|
164
|
+
)
|
|
@@ -10,6 +10,7 @@ from ostk.physics.time import Scale
|
|
|
10
10
|
from ostk.physics.time import Duration
|
|
11
11
|
from ostk.physics.coordinate import Frame
|
|
12
12
|
from ostk.physics.environment.object.celestial import Earth
|
|
13
|
+
from ostk.physics.unit import Angle
|
|
13
14
|
|
|
14
15
|
from ostk.astrodynamics.flight.system import SatelliteSystem
|
|
15
16
|
from ostk.astrodynamics import Dynamics
|
|
@@ -17,6 +18,7 @@ from ostk.astrodynamics.dynamics import CentralBodyGravity
|
|
|
17
18
|
from ostk.astrodynamics.dynamics import PositionDerivative
|
|
18
19
|
from ostk.astrodynamics.dynamics import Thruster
|
|
19
20
|
from ostk.astrodynamics.guidance_law import ConstantThrust
|
|
21
|
+
from ostk.astrodynamics.trajectory import LocalOrbitalFrameFactory
|
|
20
22
|
from ostk.astrodynamics.trajectory import State
|
|
21
23
|
from ostk.astrodynamics.trajectory import Segment
|
|
22
24
|
from ostk.astrodynamics.event_condition import InstantCondition
|
|
@@ -75,6 +77,11 @@ def dynamics(
|
|
|
75
77
|
]
|
|
76
78
|
|
|
77
79
|
|
|
80
|
+
@pytest.fixture
|
|
81
|
+
def local_orbital_frame_factory() -> LocalOrbitalFrameFactory:
|
|
82
|
+
return LocalOrbitalFrameFactory.VNC(Frame.GCRF())
|
|
83
|
+
|
|
84
|
+
|
|
78
85
|
@pytest.fixture
|
|
79
86
|
def numerical_solver() -> NumericalSolver:
|
|
80
87
|
return NumericalSolver.default_conditional()
|
|
@@ -122,6 +129,51 @@ def maneuver_segment(
|
|
|
122
129
|
)
|
|
123
130
|
|
|
124
131
|
|
|
132
|
+
@pytest.fixture
|
|
133
|
+
def maximum_allowed_angular_offset() -> Angle:
|
|
134
|
+
return Angle.degrees(180.0)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@pytest.fixture
|
|
138
|
+
def constant_local_orbital_frame_direction_maneuver_segment(
|
|
139
|
+
name: str,
|
|
140
|
+
instant_condition: InstantCondition,
|
|
141
|
+
thruster_dynamics: Thruster,
|
|
142
|
+
dynamics: list,
|
|
143
|
+
numerical_solver: NumericalSolver,
|
|
144
|
+
local_orbital_frame_factory: LocalOrbitalFrameFactory,
|
|
145
|
+
) -> Segment:
|
|
146
|
+
return Segment.constant_local_orbital_frame_direction_maneuver(
|
|
147
|
+
name=name,
|
|
148
|
+
event_condition=instant_condition,
|
|
149
|
+
thruster_dynamics=thruster_dynamics,
|
|
150
|
+
dynamics=dynamics,
|
|
151
|
+
numerical_solver=numerical_solver,
|
|
152
|
+
local_orbital_frame_factory=local_orbital_frame_factory,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@pytest.fixture
|
|
157
|
+
def constant_local_orbital_frame_direction_maneuver_segment_with_maximum_allowed_angular_offset(
|
|
158
|
+
name: str,
|
|
159
|
+
instant_condition: InstantCondition,
|
|
160
|
+
thruster_dynamics: Thruster,
|
|
161
|
+
dynamics: list,
|
|
162
|
+
numerical_solver: NumericalSolver,
|
|
163
|
+
local_orbital_frame_factory: LocalOrbitalFrameFactory,
|
|
164
|
+
maximum_allowed_angular_offset: Angle,
|
|
165
|
+
) -> Segment:
|
|
166
|
+
return Segment.constant_local_orbital_frame_direction_maneuver(
|
|
167
|
+
name=name,
|
|
168
|
+
event_condition=instant_condition,
|
|
169
|
+
thruster_dynamics=thruster_dynamics,
|
|
170
|
+
dynamics=dynamics,
|
|
171
|
+
numerical_solver=numerical_solver,
|
|
172
|
+
local_orbital_frame_factory=local_orbital_frame_factory,
|
|
173
|
+
maximum_allowed_angular_offset=maximum_allowed_angular_offset,
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
|
|
125
177
|
@pytest.fixture
|
|
126
178
|
def instants(state: State) -> list[Instant]:
|
|
127
179
|
return [state.get_instant(), state.get_instant() + Duration.minutes(1.0)]
|
|
@@ -293,6 +345,41 @@ class TestSegment:
|
|
|
293
345
|
is not None
|
|
294
346
|
)
|
|
295
347
|
|
|
348
|
+
def test_constant_local_orbital_frame_direction_maneuver(
|
|
349
|
+
self,
|
|
350
|
+
name: str,
|
|
351
|
+
instant_condition: InstantCondition,
|
|
352
|
+
thruster_dynamics: ConstantThrust,
|
|
353
|
+
dynamics: list,
|
|
354
|
+
numerical_solver: NumericalSolver,
|
|
355
|
+
local_orbital_frame_factory: LocalOrbitalFrameFactory,
|
|
356
|
+
maximum_allowed_angular_offset: Angle,
|
|
357
|
+
):
|
|
358
|
+
assert (
|
|
359
|
+
Segment.constant_local_orbital_frame_direction_maneuver(
|
|
360
|
+
name=name,
|
|
361
|
+
event_condition=instant_condition,
|
|
362
|
+
thruster_dynamics=thruster_dynamics,
|
|
363
|
+
dynamics=dynamics,
|
|
364
|
+
numerical_solver=numerical_solver,
|
|
365
|
+
local_orbital_frame_factory=local_orbital_frame_factory,
|
|
366
|
+
)
|
|
367
|
+
is not None
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
assert (
|
|
371
|
+
Segment.constant_local_orbital_frame_direction_maneuver(
|
|
372
|
+
name=name,
|
|
373
|
+
event_condition=instant_condition,
|
|
374
|
+
thruster_dynamics=thruster_dynamics,
|
|
375
|
+
dynamics=dynamics,
|
|
376
|
+
numerical_solver=numerical_solver,
|
|
377
|
+
local_orbital_frame_factory=local_orbital_frame_factory,
|
|
378
|
+
maximum_allowed_angular_offset=maximum_allowed_angular_offset,
|
|
379
|
+
)
|
|
380
|
+
is not None
|
|
381
|
+
)
|
|
382
|
+
|
|
296
383
|
def test_create_solution(
|
|
297
384
|
self,
|
|
298
385
|
dynamics: list,
|
|
@@ -310,7 +397,7 @@ class TestSegment:
|
|
|
310
397
|
|
|
311
398
|
assert segment_solution is not None
|
|
312
399
|
|
|
313
|
-
def
|
|
400
|
+
def test_solve_maneuver_segment(
|
|
314
401
|
self,
|
|
315
402
|
state: State,
|
|
316
403
|
end_instant: Instant,
|
|
@@ -318,7 +405,7 @@ class TestSegment:
|
|
|
318
405
|
instants: list[Instant],
|
|
319
406
|
numerical_solver: NumericalSolver,
|
|
320
407
|
):
|
|
321
|
-
solution = maneuver_segment.solve(state)
|
|
408
|
+
solution: Segment.Solution = maneuver_segment.solve(state)
|
|
322
409
|
|
|
323
410
|
assert (
|
|
324
411
|
pytest.approx(
|
|
@@ -400,3 +487,21 @@ class TestSegment:
|
|
|
400
487
|
solution.get_dynamics_acceleration_contribution(
|
|
401
488
|
solution.dynamics[0], state.get_frame()
|
|
402
489
|
)
|
|
490
|
+
|
|
491
|
+
def test_solve_constant_local_orbital_frame_direction_maneuver_segment(
|
|
492
|
+
self,
|
|
493
|
+
state: State,
|
|
494
|
+
constant_local_orbital_frame_direction_maneuver_segment: Segment,
|
|
495
|
+
constant_local_orbital_frame_direction_maneuver_segment_with_maximum_allowed_angular_offset: Segment,
|
|
496
|
+
):
|
|
497
|
+
solution: Segment.Solution = (
|
|
498
|
+
constant_local_orbital_frame_direction_maneuver_segment.solve(state)
|
|
499
|
+
)
|
|
500
|
+
assert solution is not None
|
|
501
|
+
|
|
502
|
+
solution_with_maximum_allowed_angular_offset: Segment.Solution = (
|
|
503
|
+
constant_local_orbital_frame_direction_maneuver_segment_with_maximum_allowed_angular_offset.solve(
|
|
504
|
+
state
|
|
505
|
+
)
|
|
506
|
+
)
|
|
507
|
+
assert solution_with_maximum_allowed_angular_offset is not None
|
|
@@ -1094,6 +1094,30 @@ class Segment:
|
|
|
1094
1094
|
Segment: The coast segment.
|
|
1095
1095
|
"""
|
|
1096
1096
|
@staticmethod
|
|
1097
|
+
def constant_local_orbital_frame_direction_maneuver(name: ostk.core.type.String, event_condition: typing.Any, thruster_dynamics: typing.Any, dynamics: list[...], numerical_solver: state.NumericalSolver, local_orbital_frame_factory: LocalOrbitalFrameFactory, maximum_allowed_angular_offset: ostk.physics.unit.Angle = ...) -> Segment:
|
|
1098
|
+
"""
|
|
1099
|
+
Create a maneuvering segment that produces maneuvers with a constant direction in the local orbital frame.
|
|
1100
|
+
|
|
1101
|
+
The provided thruster dynamics are used to solve the segment at first. The maneuvers produced by this segement solution
|
|
1102
|
+
are then used to create a new thruster dynamics with a constant direction in the local orbital frame. This new thruster dynamics
|
|
1103
|
+
is then used to actually solve the segment.
|
|
1104
|
+
|
|
1105
|
+
If defined, a runtime error will be thrown if the maximum allowed angular offset between the original thruster dynamics
|
|
1106
|
+
and the mean thrust direction is violated.
|
|
1107
|
+
|
|
1108
|
+
Args:
|
|
1109
|
+
name (str): The name of the segment.
|
|
1110
|
+
event_condition (EventCondition): The event condition.
|
|
1111
|
+
thruster_dynamics (ThrusterDynamics): The thruster dynamics.
|
|
1112
|
+
dynamics (Dynamics): The dynamics.
|
|
1113
|
+
numerical_solver (NumericalSolver): The numerical solver.
|
|
1114
|
+
local_orbital_frame_factory (LocalOrbitalFrameFactory): The local orbital frame factory.
|
|
1115
|
+
maximum_allowed_angular_offset (Angle, optional): The maximum allowed angular offset to consider (if any). Defaults to Angle.undefined().
|
|
1116
|
+
|
|
1117
|
+
Returns:
|
|
1118
|
+
Segment: The maneuver segment.
|
|
1119
|
+
"""
|
|
1120
|
+
@staticmethod
|
|
1097
1121
|
def maneuver(name: ostk.core.type.String, event_condition: typing.Any, thruster_dynamics: typing.Any, dynamics: list[...], numerical_solver: state.NumericalSolver) -> Segment:
|
|
1098
1122
|
"""
|
|
1099
1123
|
Create a maneuver segment.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|