open-space-toolkit-astrodynamics 17.2.0__py312-none-manylinux2014_x86_64.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-17.2.0.dist-info/METADATA +30 -0
- open_space_toolkit_astrodynamics-17.2.0.dist-info/RECORD +151 -0
- open_space_toolkit_astrodynamics-17.2.0.dist-info/WHEEL +5 -0
- open_space_toolkit_astrodynamics-17.2.0.dist-info/top_level.txt +1 -0
- open_space_toolkit_astrodynamics-17.2.0.dist-info/zip-safe +1 -0
- ostk/__init__.py +1 -0
- ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-312-x86_64-linux-gnu.so +0 -0
- ostk/astrodynamics/__init__.py +11 -0
- ostk/astrodynamics/__init__.pyi +720 -0
- ostk/astrodynamics/access.pyi +577 -0
- ostk/astrodynamics/conjunction/__init__.pyi +121 -0
- ostk/astrodynamics/conjunction/close_approach.pyi +89 -0
- ostk/astrodynamics/conjunction/message/__init__.pyi +3 -0
- ostk/astrodynamics/conjunction/message/ccsds.pyi +705 -0
- ostk/astrodynamics/converters.py +130 -0
- ostk/astrodynamics/converters.pyi +58 -0
- ostk/astrodynamics/data/__init__.pyi +3 -0
- ostk/astrodynamics/data/provider.pyi +22 -0
- ostk/astrodynamics/dataframe.py +597 -0
- ostk/astrodynamics/display.py +281 -0
- ostk/astrodynamics/dynamics.pyi +311 -0
- ostk/astrodynamics/eclipse.pyi +70 -0
- ostk/astrodynamics/estimator.pyi +268 -0
- ostk/astrodynamics/event_condition.pyi +910 -0
- ostk/astrodynamics/flight/__init__.pyi +626 -0
- ostk/astrodynamics/flight/profile/__init__.pyi +99 -0
- ostk/astrodynamics/flight/profile/model.pyi +179 -0
- ostk/astrodynamics/flight/system.pyi +268 -0
- ostk/astrodynamics/guidance_law.pyi +416 -0
- ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.17 +0 -0
- ostk/astrodynamics/pytrajectory/__init__.py +1 -0
- ostk/astrodynamics/pytrajectory/__init__.pyi +3 -0
- ostk/astrodynamics/pytrajectory/pystate.py +263 -0
- ostk/astrodynamics/pytrajectory/pystate.pyi +66 -0
- ostk/astrodynamics/solver.pyi +432 -0
- ostk/astrodynamics/test/__init__.py +1 -0
- ostk/astrodynamics/test/access/__init__.py +1 -0
- ostk/astrodynamics/test/access/test_generator.py +319 -0
- ostk/astrodynamics/test/access/test_visibility_criterion.py +201 -0
- ostk/astrodynamics/test/conftest.py +119 -0
- ostk/astrodynamics/test/conjunction/close_approach/__init__.py +0 -0
- ostk/astrodynamics/test/conjunction/close_approach/test_generator.py +228 -0
- ostk/astrodynamics/test/conjunction/message/ccsds/__init__.py +1 -0
- ostk/astrodynamics/test/conjunction/message/ccsds/conftest.py +325 -0
- ostk/astrodynamics/test/conjunction/message/ccsds/data/cdm.json +303 -0
- ostk/astrodynamics/test/conjunction/message/ccsds/test_cdm.py +416 -0
- ostk/astrodynamics/test/conjunction/test_close_approach.py +244 -0
- ostk/astrodynamics/test/data/provider/test_off_nadir.py +58 -0
- ostk/astrodynamics/test/dynamics/__init__.py +1 -0
- ostk/astrodynamics/test/dynamics/data/Tabulated_Earth_Gravity.csv +565 -0
- ostk/astrodynamics/test/dynamics/data/Tabulated_Earth_Gravity_Truth.csv +100 -0
- ostk/astrodynamics/test/dynamics/test_atmospheric_drag.py +128 -0
- ostk/astrodynamics/test/dynamics/test_central_body_gravity.py +58 -0
- ostk/astrodynamics/test/dynamics/test_dynamics.py +50 -0
- ostk/astrodynamics/test/dynamics/test_position_derivative.py +51 -0
- ostk/astrodynamics/test/dynamics/test_tabulated.py +138 -0
- ostk/astrodynamics/test/dynamics/test_third_body_gravity.py +67 -0
- ostk/astrodynamics/test/dynamics/test_thruster.py +157 -0
- ostk/astrodynamics/test/eclipse/__init__.py +1 -0
- ostk/astrodynamics/test/eclipse/test_generator.py +138 -0
- ostk/astrodynamics/test/estimator/test_orbit_determination_solver.py +261 -0
- ostk/astrodynamics/test/estimator/test_tle_solver.py +216 -0
- ostk/astrodynamics/test/event_condition/test_angular_condition.py +113 -0
- ostk/astrodynamics/test/event_condition/test_boolean_condition.py +55 -0
- ostk/astrodynamics/test/event_condition/test_brouwer_lyddane_mean_long_condition.py +135 -0
- ostk/astrodynamics/test/event_condition/test_coe_condition.py +135 -0
- ostk/astrodynamics/test/event_condition/test_instant_condition.py +48 -0
- ostk/astrodynamics/test/event_condition/test_logical_condition.py +120 -0
- ostk/astrodynamics/test/event_condition/test_real_condition.py +50 -0
- ostk/astrodynamics/test/flight/__init__.py +1 -0
- ostk/astrodynamics/test/flight/profile/model/test_tabulated_profile.py +115 -0
- ostk/astrodynamics/test/flight/system/__init__.py +1 -0
- ostk/astrodynamics/test/flight/system/test_propulsion_system.py +64 -0
- ostk/astrodynamics/test/flight/system/test_satellite_system.py +83 -0
- ostk/astrodynamics/test/flight/system/test_satellite_system_builder.py +71 -0
- ostk/astrodynamics/test/flight/test_maneuver.py +231 -0
- ostk/astrodynamics/test/flight/test_profile.py +293 -0
- ostk/astrodynamics/test/flight/test_system.py +45 -0
- ostk/astrodynamics/test/guidance_law/test_constant_thrust.py +177 -0
- ostk/astrodynamics/test/guidance_law/test_guidance_law.py +60 -0
- ostk/astrodynamics/test/guidance_law/test_heterogeneous_guidance_law.py +164 -0
- ostk/astrodynamics/test/guidance_law/test_qlaw.py +209 -0
- ostk/astrodynamics/test/solvers/__init__.py +1 -0
- ostk/astrodynamics/test/solvers/test_finite_difference_solver.py +196 -0
- ostk/astrodynamics/test/solvers/test_least_squares_solver.py +334 -0
- ostk/astrodynamics/test/solvers/test_temporal_condition_solver.py +161 -0
- ostk/astrodynamics/test/test_access.py +128 -0
- ostk/astrodynamics/test/test_converters.py +290 -0
- ostk/astrodynamics/test/test_dataframe.py +1355 -0
- ostk/astrodynamics/test/test_display.py +184 -0
- ostk/astrodynamics/test/test_event_condition.py +80 -0
- ostk/astrodynamics/test/test_import.py +26 -0
- ostk/astrodynamics/test/test_root_solver.py +70 -0
- ostk/astrodynamics/test/test_trajectory.py +126 -0
- ostk/astrodynamics/test/test_utilities.py +338 -0
- ostk/astrodynamics/test/test_viewer.py +318 -0
- ostk/astrodynamics/test/trajectory/__init__.py +1 -0
- ostk/astrodynamics/test/trajectory/model/test_nadir_trajectory.py +87 -0
- ostk/astrodynamics/test/trajectory/model/test_tabulated_trajectory.py +303 -0
- ostk/astrodynamics/test/trajectory/model/test_target_scan_trajectory.py +126 -0
- ostk/astrodynamics/test/trajectory/orbit/__init__.py +1 -0
- ostk/astrodynamics/test/trajectory/orbit/message/__init__.py +1 -0
- ostk/astrodynamics/test/trajectory/orbit/message/spacex/__init__.py +1 -0
- ostk/astrodynamics/test/trajectory/orbit/message/spacex/conftest.py +18 -0
- ostk/astrodynamics/test/trajectory/orbit/message/spacex/data/opm_1.yaml +44 -0
- ostk/astrodynamics/test/trajectory/orbit/message/spacex/test_opm.py +108 -0
- ostk/astrodynamics/test/trajectory/orbit/models/__init__.py +1 -0
- ostk/astrodynamics/test/trajectory/orbit/models/kepler/__init__.py +1 -0
- ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean.py +65 -0
- ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean_long.py +102 -0
- ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean_short.py +102 -0
- ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_coe.py +305 -0
- ostk/astrodynamics/test/trajectory/orbit/models/sgp4/__init__.py +1 -0
- ostk/astrodynamics/test/trajectory/orbit/models/sgp4/test_tle.py +337 -0
- ostk/astrodynamics/test/trajectory/orbit/models/test_kepler.py +130 -0
- ostk/astrodynamics/test/trajectory/orbit/models/test_modified_equinoctial.py +142 -0
- ostk/astrodynamics/test/trajectory/orbit/models/test_propagated.py +234 -0
- ostk/astrodynamics/test/trajectory/orbit/models/test_sgp4.py +1 -0
- ostk/astrodynamics/test/trajectory/orbit/models/test_tabulated.py +380 -0
- ostk/astrodynamics/test/trajectory/orbit/test_model.py +1 -0
- ostk/astrodynamics/test/trajectory/orbit/test_pass.py +75 -0
- ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_angular_velocity.py +30 -0
- ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_attitude_quaternion.py +18 -0
- ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_acceleration.py +136 -0
- ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_position.py +107 -0
- ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_velocity.py +115 -0
- ostk/astrodynamics/test/trajectory/state/test_coordinate_broker.py +84 -0
- ostk/astrodynamics/test/trajectory/state/test_coordinate_subset.py +58 -0
- ostk/astrodynamics/test/trajectory/state/test_numerical_solver.py +316 -0
- ostk/astrodynamics/test/trajectory/test_local_orbital_frame_direction.py +81 -0
- ostk/astrodynamics/test/trajectory/test_local_orbital_frame_factory.py +119 -0
- ostk/astrodynamics/test/trajectory/test_model.py +1 -0
- ostk/astrodynamics/test/trajectory/test_orbit.py +212 -0
- ostk/astrodynamics/test/trajectory/test_propagator.py +452 -0
- ostk/astrodynamics/test/trajectory/test_segment.py +694 -0
- ostk/astrodynamics/test/trajectory/test_sequence.py +550 -0
- ostk/astrodynamics/test/trajectory/test_state.py +629 -0
- ostk/astrodynamics/test/trajectory/test_state_builder.py +172 -0
- ostk/astrodynamics/trajectory/__init__.pyi +1982 -0
- ostk/astrodynamics/trajectory/model.pyi +259 -0
- ostk/astrodynamics/trajectory/orbit/__init__.pyi +349 -0
- ostk/astrodynamics/trajectory/orbit/message/__init__.pyi +3 -0
- ostk/astrodynamics/trajectory/orbit/message/spacex.pyi +264 -0
- ostk/astrodynamics/trajectory/orbit/model/__init__.pyi +648 -0
- ostk/astrodynamics/trajectory/orbit/model/brouwerLyddaneMean.pyi +121 -0
- ostk/astrodynamics/trajectory/orbit/model/kepler.pyi +709 -0
- ostk/astrodynamics/trajectory/orbit/model/sgp4.pyi +330 -0
- ostk/astrodynamics/trajectory/state/__init__.pyi +402 -0
- ostk/astrodynamics/trajectory/state/coordinate_subset.pyi +208 -0
- ostk/astrodynamics/utilities.py +396 -0
- ostk/astrodynamics/viewer.py +851 -0
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import numpy
|
|
3
|
+
import ostk.astrodynamics
|
|
4
|
+
import ostk.astrodynamics.flight
|
|
5
|
+
import ostk.astrodynamics.trajectory
|
|
6
|
+
import ostk.astrodynamics.trajectory.orbit.model.kepler
|
|
7
|
+
import ostk.core.type
|
|
8
|
+
import ostk.physics.coordinate
|
|
9
|
+
import ostk.physics.time
|
|
10
|
+
import ostk.physics.unit
|
|
11
|
+
import typing
|
|
12
|
+
__all__ = ['ConstantThrust', 'HeterogeneousGuidanceLaw', 'QLaw']
|
|
13
|
+
class ConstantThrust(ostk.astrodynamics.GuidanceLaw):
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
Constant Thrust, Constant Direction guidance law.
|
|
17
|
+
|
|
18
|
+
|
|
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
|
|
40
|
+
def intrack(velocity_direction: bool = True) -> ConstantThrust:
|
|
41
|
+
"""
|
|
42
|
+
Create a constant thrust guidance law in the in-track direction.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
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.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
ConstantThrust: The constant thrust guidance law in the in-track direction.
|
|
49
|
+
"""
|
|
50
|
+
def __init__(self, thrust_direction: ostk.astrodynamics.trajectory.LocalOrbitalFrameDirection) -> None:
|
|
51
|
+
"""
|
|
52
|
+
Constructor.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
thrust_direction (LocalOrbitalFrameDirection): The thrust direction.
|
|
56
|
+
"""
|
|
57
|
+
def __repr__(self) -> str:
|
|
58
|
+
...
|
|
59
|
+
def __str__(self) -> str:
|
|
60
|
+
...
|
|
61
|
+
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]]:
|
|
62
|
+
"""
|
|
63
|
+
Compute the acceleration due to constant thrust.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
instant (Instant): The instant of the state vector.
|
|
67
|
+
position_coordinates (numpy.ndarray): The position coordinates.
|
|
68
|
+
velocity_coordinates (numpy.ndarray): The velocity coordinates.
|
|
69
|
+
thrust_acceleration (float): The thrust acceleration magnitude.
|
|
70
|
+
output_frame (Frame): The frame the acceleration will be expressed in.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
numpy.ndarray: The contribution of the constant thrust to the state vector.
|
|
74
|
+
"""
|
|
75
|
+
def get_local_thrust_direction(self) -> ostk.astrodynamics.trajectory.LocalOrbitalFrameDirection:
|
|
76
|
+
"""
|
|
77
|
+
Get the local thrust direction.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
LocalOrbitalFrameDirection: The local thrust direction.
|
|
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
|
+
"""
|
|
139
|
+
class QLaw(ostk.astrodynamics.GuidanceLaw):
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
This class implements the Q-law guidance law.
|
|
143
|
+
|
|
144
|
+
- Ref: https://dataverse.jpl.nasa.gov/api/access/datafile/10307?gbrecs=true
|
|
145
|
+
- Ref: https://www.researchgate.net/publication/370849580_Analytic_Calculation_and_Application_of_the_Q-Law_Guidance_Algorithm_Partial_Derivatives
|
|
146
|
+
- Ref for derivations: https://dataverse.jpl.nasa.gov/api/access/datafile/13727?gbrecs=true
|
|
147
|
+
|
|
148
|
+
The Q-law is a Lyapunov feedback control law developed by Petropoulos,
|
|
149
|
+
based on analytic expressions for maximum rates of change of the orbit elements and
|
|
150
|
+
the desired changes in the elements. Q, the proximity quotient, serves as a candidate Lyapunov
|
|
151
|
+
function. As the spacecraft approaches the target orbit, Q decreases monotonically (becoming zero at the target orbit).
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
"""
|
|
155
|
+
class COEDomain:
|
|
156
|
+
"""
|
|
157
|
+
|
|
158
|
+
Classical Orbital Elements domain.
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
Members:
|
|
162
|
+
|
|
163
|
+
Osculating : Osculating
|
|
164
|
+
|
|
165
|
+
BrouwerLyddaneMeanLong : Brouwer Lyddane Mean Long
|
|
166
|
+
|
|
167
|
+
BrouwerLyddaneMeanShort : Brouwer Lyddane Mean Short
|
|
168
|
+
"""
|
|
169
|
+
BrouwerLyddaneMeanLong: typing.ClassVar[QLaw.COEDomain] # value = <COEDomain.BrouwerLyddaneMeanLong: 1>
|
|
170
|
+
BrouwerLyddaneMeanShort: typing.ClassVar[QLaw.COEDomain] # value = <COEDomain.BrouwerLyddaneMeanShort: 2>
|
|
171
|
+
Osculating: typing.ClassVar[QLaw.COEDomain] # value = <COEDomain.Osculating: 0>
|
|
172
|
+
__members__: typing.ClassVar[dict[str, QLaw.COEDomain]] # value = {'Osculating': <COEDomain.Osculating: 0>, 'BrouwerLyddaneMeanLong': <COEDomain.BrouwerLyddaneMeanLong: 1>, 'BrouwerLyddaneMeanShort': <COEDomain.BrouwerLyddaneMeanShort: 2>}
|
|
173
|
+
def __eq__(self, other: typing.Any) -> bool:
|
|
174
|
+
...
|
|
175
|
+
def __getstate__(self) -> int:
|
|
176
|
+
...
|
|
177
|
+
def __hash__(self) -> int:
|
|
178
|
+
...
|
|
179
|
+
def __index__(self) -> int:
|
|
180
|
+
...
|
|
181
|
+
def __init__(self, value: int) -> None:
|
|
182
|
+
...
|
|
183
|
+
def __int__(self) -> int:
|
|
184
|
+
...
|
|
185
|
+
def __ne__(self, other: typing.Any) -> bool:
|
|
186
|
+
...
|
|
187
|
+
def __repr__(self) -> str:
|
|
188
|
+
...
|
|
189
|
+
def __setstate__(self, state: int) -> None:
|
|
190
|
+
...
|
|
191
|
+
def __str__(self) -> str:
|
|
192
|
+
...
|
|
193
|
+
@property
|
|
194
|
+
def name(self) -> str:
|
|
195
|
+
...
|
|
196
|
+
@property
|
|
197
|
+
def value(self) -> int:
|
|
198
|
+
...
|
|
199
|
+
class GradientStrategy:
|
|
200
|
+
"""
|
|
201
|
+
|
|
202
|
+
Gradient strategy.
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
Members:
|
|
206
|
+
|
|
207
|
+
Analytical : Analytical
|
|
208
|
+
|
|
209
|
+
FiniteDifference : Finite Differenced
|
|
210
|
+
"""
|
|
211
|
+
Analytical: typing.ClassVar[QLaw.GradientStrategy] # value = <GradientStrategy.Analytical: 0>
|
|
212
|
+
FiniteDifference: typing.ClassVar[QLaw.GradientStrategy] # value = <GradientStrategy.FiniteDifference: 1>
|
|
213
|
+
__members__: typing.ClassVar[dict[str, QLaw.GradientStrategy]] # value = {'Analytical': <GradientStrategy.Analytical: 0>, 'FiniteDifference': <GradientStrategy.FiniteDifference: 1>}
|
|
214
|
+
def __eq__(self, other: typing.Any) -> bool:
|
|
215
|
+
...
|
|
216
|
+
def __getstate__(self) -> int:
|
|
217
|
+
...
|
|
218
|
+
def __hash__(self) -> int:
|
|
219
|
+
...
|
|
220
|
+
def __index__(self) -> int:
|
|
221
|
+
...
|
|
222
|
+
def __init__(self, value: int) -> None:
|
|
223
|
+
...
|
|
224
|
+
def __int__(self) -> int:
|
|
225
|
+
...
|
|
226
|
+
def __ne__(self, other: typing.Any) -> bool:
|
|
227
|
+
...
|
|
228
|
+
def __repr__(self) -> str:
|
|
229
|
+
...
|
|
230
|
+
def __setstate__(self, state: int) -> None:
|
|
231
|
+
...
|
|
232
|
+
def __str__(self) -> str:
|
|
233
|
+
...
|
|
234
|
+
@property
|
|
235
|
+
def name(self) -> str:
|
|
236
|
+
...
|
|
237
|
+
@property
|
|
238
|
+
def value(self) -> int:
|
|
239
|
+
...
|
|
240
|
+
class Parameters:
|
|
241
|
+
"""
|
|
242
|
+
|
|
243
|
+
Q-law parameters.
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
"""
|
|
247
|
+
def __init__(self, element_weights: dict[ostk.astrodynamics.trajectory.orbit.model.kepler.COE.Element, tuple[float, float]], m: int = 3, n: int = 4, r: int = 2, b: float = 0.01, k: int = 100, periapsis_weight: float = 0.0, minimum_periapsis_radius: ostk.physics.unit.Length = ..., absolute_effectivity_threshold: ostk.core.type.Real = ..., relative_effectivity_threshold: ostk.core.type.Real = ...) -> None:
|
|
248
|
+
"""
|
|
249
|
+
Constructor.
|
|
250
|
+
|
|
251
|
+
Args:
|
|
252
|
+
element_weights (dict): Key-value pair of COE elements and the (weights, tolerances) for the targeter.
|
|
253
|
+
m (int): Scaling parameter for Semi-Major Axis delta. Default to 3.
|
|
254
|
+
n (int): Scaling parameter for Semi-Major Axis delta. Default to 4.
|
|
255
|
+
r (int): Scaling parameter for Semi-Major Axis delta. Default to 2.
|
|
256
|
+
b (float): Scaling parameter for Argument of Periapsis maximal change. Default to 0.01.
|
|
257
|
+
k (int): Penalty parameter for periapsis. Default to 100.
|
|
258
|
+
periapsis_weight (float): Periapsis weight. Default to 0.0.
|
|
259
|
+
minimum_periapsis_radius (Length): Minimum periapsis radius. Default to 6578.0 km.
|
|
260
|
+
absolute_effectivity_threshold (Real): Absolute effectivity threshold. Default to undefined (not used).
|
|
261
|
+
relative_effectivity_threshold (Real): Relative effectivity threshold. Default to undefined (not used).
|
|
262
|
+
"""
|
|
263
|
+
def get_control_weights(self) -> numpy.ndarray[numpy.float64[5, 1]]:
|
|
264
|
+
"""
|
|
265
|
+
Get the control weights.
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
np.array: The control weights.
|
|
269
|
+
"""
|
|
270
|
+
def get_convergence_thresholds(self) -> numpy.ndarray[numpy.float64[5, 1]]:
|
|
271
|
+
"""
|
|
272
|
+
Get the convergence thresholds.
|
|
273
|
+
|
|
274
|
+
Returns:
|
|
275
|
+
np.array: The convergence thresholds.
|
|
276
|
+
"""
|
|
277
|
+
def get_minimum_periapsis_radius(self) -> ostk.physics.unit.Length:
|
|
278
|
+
"""
|
|
279
|
+
Get the minimum periapsis radius.
|
|
280
|
+
|
|
281
|
+
Returns:
|
|
282
|
+
Length: The minimum periapsis radius.
|
|
283
|
+
"""
|
|
284
|
+
@property
|
|
285
|
+
def absolute_effectivity_threshold(self) -> ostk.core.type.Real:
|
|
286
|
+
"""
|
|
287
|
+
Absolute effectivity threshold.
|
|
288
|
+
|
|
289
|
+
Type:
|
|
290
|
+
Real
|
|
291
|
+
"""
|
|
292
|
+
@property
|
|
293
|
+
def b(self) -> float:
|
|
294
|
+
"""
|
|
295
|
+
Scaling parameter for Argument of Periapsis.
|
|
296
|
+
|
|
297
|
+
Type:
|
|
298
|
+
float
|
|
299
|
+
"""
|
|
300
|
+
@property
|
|
301
|
+
def k(self) -> float:
|
|
302
|
+
"""
|
|
303
|
+
Penalty parameter for periapsis.
|
|
304
|
+
|
|
305
|
+
Type:
|
|
306
|
+
int
|
|
307
|
+
"""
|
|
308
|
+
@property
|
|
309
|
+
def m(self) -> float:
|
|
310
|
+
"""
|
|
311
|
+
Scaling parameter for Semi-Major Axis delta.
|
|
312
|
+
|
|
313
|
+
Type:
|
|
314
|
+
int
|
|
315
|
+
"""
|
|
316
|
+
@property
|
|
317
|
+
def n(self) -> float:
|
|
318
|
+
"""
|
|
319
|
+
Scaling parameter for Semi-Major Axis delta.
|
|
320
|
+
|
|
321
|
+
Type:
|
|
322
|
+
int
|
|
323
|
+
"""
|
|
324
|
+
@property
|
|
325
|
+
def periapsis_weight(self) -> float:
|
|
326
|
+
"""
|
|
327
|
+
Periapsis weight.
|
|
328
|
+
|
|
329
|
+
Type:
|
|
330
|
+
float
|
|
331
|
+
"""
|
|
332
|
+
@property
|
|
333
|
+
def r(self) -> float:
|
|
334
|
+
"""
|
|
335
|
+
Scaling parameter for Semi-Major Axis delta.
|
|
336
|
+
|
|
337
|
+
Type:
|
|
338
|
+
int
|
|
339
|
+
"""
|
|
340
|
+
@property
|
|
341
|
+
def relative_effectivity_threshold(self) -> ostk.core.type.Real:
|
|
342
|
+
"""
|
|
343
|
+
Relative effectivity threshold.
|
|
344
|
+
|
|
345
|
+
Type:
|
|
346
|
+
Real
|
|
347
|
+
"""
|
|
348
|
+
def __init__(self, target_coe: ostk.astrodynamics.trajectory.orbit.model.kepler.COE, gravitational_parameter: ostk.physics.unit.Derived, parameters: QLaw.Parameters, coe_domain: QLaw.COEDomain, gradient_strategy: QLaw.GradientStrategy = ...) -> None:
|
|
349
|
+
"""
|
|
350
|
+
Constructor.
|
|
351
|
+
|
|
352
|
+
Args:
|
|
353
|
+
coe (COE): The target orbit described by Classical Orbital Elements.
|
|
354
|
+
gravitational_parameter (float): The gravitational parameter of the central body.
|
|
355
|
+
parameters (QLaw.Parameters): A set of parameters for the QLaw.
|
|
356
|
+
coe_domain (QLaw.COEDomain): The domain of the Classical Orbital Elements.
|
|
357
|
+
gradient_strategy (QLaw.GradientStrategy): The strategy used to compute the gradient dQ_dOE. Defaults to FiniteDifference.
|
|
358
|
+
"""
|
|
359
|
+
def __repr__(self) -> str:
|
|
360
|
+
...
|
|
361
|
+
def __str__(self) -> str:
|
|
362
|
+
...
|
|
363
|
+
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]]:
|
|
364
|
+
"""
|
|
365
|
+
Calculate the thrust acceleration at the provided coordinates and instant.
|
|
366
|
+
|
|
367
|
+
Args:
|
|
368
|
+
instant (Instant): Instant of computation.
|
|
369
|
+
position_coordinates (np.array): Position coordinates.
|
|
370
|
+
velocity_coordinates (np.array): Velocity coordinates.
|
|
371
|
+
thrust_acceleration (float): Thrust acceleration magnitude.
|
|
372
|
+
output_frame (Frame): The frame the acceleration is expressed in.
|
|
373
|
+
|
|
374
|
+
Returns:
|
|
375
|
+
np.array: The acceleration.
|
|
376
|
+
"""
|
|
377
|
+
def compute_effectivity(self, state: ostk.astrodynamics.trajectory.State, thrust_acceleration: ostk.core.type.Real, discretization_step_count: int = 50) -> tuple[float, float]:
|
|
378
|
+
"""
|
|
379
|
+
Compute the relative and absolute effectivity of the guidance law.
|
|
380
|
+
|
|
381
|
+
Args:
|
|
382
|
+
state (State): The state from which to extract orbital elements.
|
|
383
|
+
thrust_acceleration (float): The thrust acceleration.
|
|
384
|
+
discretization_step_count (int): The number of discretization steps for the true anomaly. Default to 50.
|
|
385
|
+
|
|
386
|
+
Returns:
|
|
387
|
+
tuple[float, float]: A tuple containing the relative and absolute effectivity.
|
|
388
|
+
"""
|
|
389
|
+
def get_coe_domain(self) -> QLaw.COEDomain:
|
|
390
|
+
"""
|
|
391
|
+
Get the COE domain.
|
|
392
|
+
|
|
393
|
+
Returns:
|
|
394
|
+
QLaw.COEDomain: The COE domain.
|
|
395
|
+
"""
|
|
396
|
+
def get_gradient_strategy(self) -> QLaw.GradientStrategy:
|
|
397
|
+
"""
|
|
398
|
+
Get the gradient strategy.
|
|
399
|
+
|
|
400
|
+
Returns:
|
|
401
|
+
QLaw.GradientStrategy: The gradient strategy.
|
|
402
|
+
"""
|
|
403
|
+
def get_parameters(self) -> QLaw.Parameters:
|
|
404
|
+
"""
|
|
405
|
+
Get the parameters.
|
|
406
|
+
|
|
407
|
+
Returns:
|
|
408
|
+
QLaw.Parameters: The parameters.
|
|
409
|
+
"""
|
|
410
|
+
def get_target_coe(self) -> ostk.astrodynamics.trajectory.orbit.model.kepler.COE:
|
|
411
|
+
"""
|
|
412
|
+
Get the target COE.
|
|
413
|
+
|
|
414
|
+
Returns:
|
|
415
|
+
COE: The target COE.
|
|
416
|
+
"""
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Apache License 2.0
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# Apache License 2.0
|
|
2
|
+
|
|
3
|
+
# Python-only State functionality
|
|
4
|
+
import re
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
from ostk.physics.coordinate import Frame
|
|
9
|
+
from ostk.physics.time import Instant
|
|
10
|
+
|
|
11
|
+
from ostk.astrodynamics.trajectory import State, StateBuilder
|
|
12
|
+
from ostk.astrodynamics.trajectory.state import CoordinateSubset
|
|
13
|
+
from ostk.astrodynamics.converters import coerce_to_instant
|
|
14
|
+
from ostk.astrodynamics.trajectory.state.coordinate_subset import (
|
|
15
|
+
CartesianPosition,
|
|
16
|
+
CartesianVelocity,
|
|
17
|
+
AttitudeQuaternion,
|
|
18
|
+
AngularVelocity,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
POS_VEL_CANONICAL_FORMAT: str = r"(r|v)_(.*?)_(x|y|z)"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def custom_class_generator(frame: Frame, coordinate_subsets: list) -> type:
|
|
25
|
+
"""
|
|
26
|
+
Emit a custom class type for States. This is meta-programming syntactic sugar on top of the StateBuilder class.
|
|
27
|
+
|
|
28
|
+
StateType = State.template(frame, coordinate_subsets)
|
|
29
|
+
state = StateType(instant, coordinates)
|
|
30
|
+
|
|
31
|
+
is equivalent to
|
|
32
|
+
|
|
33
|
+
state_builder = StateBuilder(frame, coordinate_subsets)
|
|
34
|
+
state = state_builder.build(instant, coordinates)
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
class StateTemplateType(State):
|
|
38
|
+
state_builder: StateBuilder = StateBuilder(frame, coordinate_subsets)
|
|
39
|
+
|
|
40
|
+
def __init__(self, instant: Instant, coordinates: np.ndarray):
|
|
41
|
+
super().__init__(StateTemplateType.state_builder.build(instant, coordinates))
|
|
42
|
+
|
|
43
|
+
return StateTemplateType
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def from_dict(data: dict) -> State:
|
|
47
|
+
"""
|
|
48
|
+
Create a State from a dictionary.
|
|
49
|
+
|
|
50
|
+
Note: Implicit assumption that ECEF = ITRF, and ECI = GCRF.
|
|
51
|
+
|
|
52
|
+
The dictionary must contain the following:
|
|
53
|
+
- 'timestamp': The timestamp of the state.
|
|
54
|
+
- 'r_ITRF_x'/'rx'/'rx_eci'/'rx_ecef': The x-coordinate of the position.
|
|
55
|
+
- 'r_ITRF_y'/'ry'/'ry_eci'/'ry_ecef': The y-coordinate of the position.
|
|
56
|
+
- 'r_ITRF_z'/'rz'/'rz_eci'/'rz_ecef': The z-coordinate of the position.
|
|
57
|
+
- 'v_ITRF_x'/'vx'/'vx_eci'/'vx_ecef': The x-coordinate of the velocity.
|
|
58
|
+
- 'v_ITRF_y'/'vy'/'vy_eci'/'vy_ecef': The y-coordinate of the velocity.
|
|
59
|
+
- 'v_ITRF_z'/'vz'/'vz_eci'/'vz_ecef': The z-coordinate of the velocity.
|
|
60
|
+
- 'frame': The frame of the state. Required if 'rx', 'ry', 'rz', 'vx', 'vy', 'vz' are provided.
|
|
61
|
+
- 'q_B_ECI_x': The x-coordinate of the quaternion. Optional.
|
|
62
|
+
- 'q_B_ECI_y': The y-coordinate of the quaternion. Optional.
|
|
63
|
+
- 'q_B_ECI_z': The z-coordinate of the quaternion. Optional.
|
|
64
|
+
- 'q_B_ECI_s': The s-coordinate of the quaternion. Optional.
|
|
65
|
+
- 'w_B_ECI_in_B_x': The x-coordinate of the angular velocity. Optional.
|
|
66
|
+
- 'w_B_ECI_in_B_y': The y-coordinate of the angular velocity. Optional.
|
|
67
|
+
- 'w_B_ECI_in_B_z': The z-coordinate of the angular velocity. Optional.
|
|
68
|
+
- 'drag_coefficient'/'cd': The drag coefficient. Optional.
|
|
69
|
+
- 'cross_sectional_area'/'surface_area': The cross-sectional area. Optional.
|
|
70
|
+
- 'mass': The mass. Optional.
|
|
71
|
+
- 'ballistic_coefficient'/'bc': The ballistic coefficient. Optional.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
data (dict): The dictionary.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
State: The State.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
# Position and velocity subsets
|
|
81
|
+
|
|
82
|
+
eci_columns: list[str] = [
|
|
83
|
+
"rx_eci",
|
|
84
|
+
"ry_eci",
|
|
85
|
+
"rz_eci",
|
|
86
|
+
"vx_eci",
|
|
87
|
+
"vy_eci",
|
|
88
|
+
"vz_eci",
|
|
89
|
+
]
|
|
90
|
+
ecef_columns: list[str] = [
|
|
91
|
+
"rx_ecef",
|
|
92
|
+
"ry_ecef",
|
|
93
|
+
"rz_ecef",
|
|
94
|
+
"vx_ecef",
|
|
95
|
+
"vy_ecef",
|
|
96
|
+
"vz_ecef",
|
|
97
|
+
]
|
|
98
|
+
generic_columns: list[str] = [
|
|
99
|
+
"rx",
|
|
100
|
+
"ry",
|
|
101
|
+
"rz",
|
|
102
|
+
"vx",
|
|
103
|
+
"vy",
|
|
104
|
+
"vz",
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
# Replace non-standard position keys with canonical representation
|
|
108
|
+
if all(key in data.keys() for key in ("x_eci", "y_eci", "z_eci")):
|
|
109
|
+
data["rx_eci"] = data["x_eci"]
|
|
110
|
+
data["ry_eci"] = data["y_eci"]
|
|
111
|
+
data["rz_eci"] = data["z_eci"]
|
|
112
|
+
|
|
113
|
+
if all(key in data.keys() for key in ("x_ecef", "y_ecef", "z_ecef")):
|
|
114
|
+
data["rx_ecef"] = data["x_ecef"]
|
|
115
|
+
data["ry_ecef"] = data["y_ecef"]
|
|
116
|
+
data["rz_ecef"] = data["z_ecef"]
|
|
117
|
+
|
|
118
|
+
frame: Frame
|
|
119
|
+
coordinates: np.ndarray
|
|
120
|
+
|
|
121
|
+
coordinate_subsets: list[CoordinateSubset] = [
|
|
122
|
+
CartesianPosition.default(),
|
|
123
|
+
CartesianVelocity.default(),
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
match_groups: list[re.Match] = [
|
|
127
|
+
re.match(POS_VEL_CANONICAL_FORMAT, column) for column in data.keys()
|
|
128
|
+
]
|
|
129
|
+
|
|
130
|
+
if len(matches := [match for match in match_groups if match is not None]) == 6:
|
|
131
|
+
frame_name: str = matches[0].group(2)
|
|
132
|
+
try:
|
|
133
|
+
frame: Frame = Frame.with_name(frame_name) or getattr(Frame, frame_name)()
|
|
134
|
+
except Exception:
|
|
135
|
+
raise ValueError(f"No frame exists with name [{frame_name}].")
|
|
136
|
+
|
|
137
|
+
coordinates = np.array([data[match.group(0)] for match in matches])
|
|
138
|
+
|
|
139
|
+
elif all(column in data for column in eci_columns):
|
|
140
|
+
frame: Frame = Frame.GCRF()
|
|
141
|
+
coordinates = np.array(
|
|
142
|
+
[
|
|
143
|
+
data["rx_eci"],
|
|
144
|
+
data["ry_eci"],
|
|
145
|
+
data["rz_eci"],
|
|
146
|
+
data["vx_eci"],
|
|
147
|
+
data["vy_eci"],
|
|
148
|
+
data["vz_eci"],
|
|
149
|
+
]
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
elif all(column in data for column in ecef_columns):
|
|
153
|
+
frame = Frame.ITRF()
|
|
154
|
+
coordinates = np.array(
|
|
155
|
+
[
|
|
156
|
+
data["rx_ecef"],
|
|
157
|
+
data["ry_ecef"],
|
|
158
|
+
data["rz_ecef"],
|
|
159
|
+
data["vx_ecef"],
|
|
160
|
+
data["vy_ecef"],
|
|
161
|
+
data["vz_ecef"],
|
|
162
|
+
]
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
elif all(column in data for column in generic_columns):
|
|
166
|
+
if "frame" not in data:
|
|
167
|
+
raise ValueError("Frame must be provided for generic columns.")
|
|
168
|
+
|
|
169
|
+
if isinstance(data["frame"], str):
|
|
170
|
+
if Frame.exists(data["frame"]):
|
|
171
|
+
frame = Frame.with_name(data["frame"])
|
|
172
|
+
else:
|
|
173
|
+
raise ValueError(f"No frame exists with name [{data['frame']}].")
|
|
174
|
+
elif isinstance(data["frame"], Frame):
|
|
175
|
+
frame = data["frame"]
|
|
176
|
+
else:
|
|
177
|
+
raise ValueError(f"Invalid frame data [{data['frame']}].")
|
|
178
|
+
|
|
179
|
+
coordinates = np.array(
|
|
180
|
+
[
|
|
181
|
+
data["rx"],
|
|
182
|
+
data["ry"],
|
|
183
|
+
data["rz"],
|
|
184
|
+
data["vx"],
|
|
185
|
+
data["vy"],
|
|
186
|
+
data["vz"],
|
|
187
|
+
]
|
|
188
|
+
)
|
|
189
|
+
else:
|
|
190
|
+
raise ValueError("Invalid state data.")
|
|
191
|
+
|
|
192
|
+
# Attitude and angular velocity subsets
|
|
193
|
+
|
|
194
|
+
if all(
|
|
195
|
+
column in data for column in ["q_B_ECI_x", "q_B_ECI_y", "q_B_ECI_z", "q_B_ECI_s"]
|
|
196
|
+
):
|
|
197
|
+
coordinate_subsets.append(AttitudeQuaternion.default())
|
|
198
|
+
coordinates = np.append(
|
|
199
|
+
coordinates,
|
|
200
|
+
[
|
|
201
|
+
data["q_B_ECI_x"],
|
|
202
|
+
data["q_B_ECI_y"],
|
|
203
|
+
data["q_B_ECI_z"],
|
|
204
|
+
data["q_B_ECI_s"],
|
|
205
|
+
],
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
if all(
|
|
209
|
+
column in data
|
|
210
|
+
for column in ["w_B_ECI_in_B_x", "w_B_ECI_in_B_y", "w_B_ECI_in_B_z"]
|
|
211
|
+
):
|
|
212
|
+
coordinate_subsets.append(AngularVelocity.default())
|
|
213
|
+
coordinates = np.append(
|
|
214
|
+
coordinates,
|
|
215
|
+
[
|
|
216
|
+
data["w_B_ECI_in_B_x"],
|
|
217
|
+
data["w_B_ECI_in_B_y"],
|
|
218
|
+
data["w_B_ECI_in_B_z"],
|
|
219
|
+
],
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
# Extra subsets
|
|
223
|
+
|
|
224
|
+
if (data.get("drag_coefficient") is not None) or (data.get("cd") is not None):
|
|
225
|
+
coordinate_subsets.append(CoordinateSubset.drag_coefficient())
|
|
226
|
+
coordinates = np.append(
|
|
227
|
+
coordinates,
|
|
228
|
+
data.get("drag_coefficient", data.get("cd")),
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
if (data.get("cross_sectional_area") is not None) or (
|
|
232
|
+
data.get("surface_area") is not None
|
|
233
|
+
):
|
|
234
|
+
coordinate_subsets.append(CoordinateSubset.surface_area())
|
|
235
|
+
coordinates = np.append(
|
|
236
|
+
coordinates,
|
|
237
|
+
data.get("cross_sectional_area", data.get("surface_area")),
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
if data.get("mass") is not None:
|
|
241
|
+
coordinate_subsets.append(CoordinateSubset.mass())
|
|
242
|
+
coordinates = np.append(
|
|
243
|
+
coordinates,
|
|
244
|
+
data["mass"],
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
if (data.get("ballistic_coefficient") is not None) or (data.get("bc") is not None):
|
|
248
|
+
coordinate_subsets.append(CoordinateSubset.ballistic_coefficient())
|
|
249
|
+
coordinates = np.append(
|
|
250
|
+
coordinates,
|
|
251
|
+
data.get("ballistic_coefficient", data.get("bc")),
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
return State(
|
|
255
|
+
instant=coerce_to_instant(data["timestamp"]),
|
|
256
|
+
coordinates=coordinates,
|
|
257
|
+
frame=frame,
|
|
258
|
+
coordinate_subsets=coordinate_subsets,
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
State.from_dict = staticmethod(from_dict)
|
|
263
|
+
State.template = staticmethod(custom_class_generator)
|