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.
Files changed (151) hide show
  1. open_space_toolkit_astrodynamics-17.2.0.dist-info/METADATA +30 -0
  2. open_space_toolkit_astrodynamics-17.2.0.dist-info/RECORD +151 -0
  3. open_space_toolkit_astrodynamics-17.2.0.dist-info/WHEEL +5 -0
  4. open_space_toolkit_astrodynamics-17.2.0.dist-info/top_level.txt +1 -0
  5. open_space_toolkit_astrodynamics-17.2.0.dist-info/zip-safe +1 -0
  6. ostk/__init__.py +1 -0
  7. ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-312-x86_64-linux-gnu.so +0 -0
  8. ostk/astrodynamics/__init__.py +11 -0
  9. ostk/astrodynamics/__init__.pyi +720 -0
  10. ostk/astrodynamics/access.pyi +577 -0
  11. ostk/astrodynamics/conjunction/__init__.pyi +121 -0
  12. ostk/astrodynamics/conjunction/close_approach.pyi +89 -0
  13. ostk/astrodynamics/conjunction/message/__init__.pyi +3 -0
  14. ostk/astrodynamics/conjunction/message/ccsds.pyi +705 -0
  15. ostk/astrodynamics/converters.py +130 -0
  16. ostk/astrodynamics/converters.pyi +58 -0
  17. ostk/astrodynamics/data/__init__.pyi +3 -0
  18. ostk/astrodynamics/data/provider.pyi +22 -0
  19. ostk/astrodynamics/dataframe.py +597 -0
  20. ostk/astrodynamics/display.py +281 -0
  21. ostk/astrodynamics/dynamics.pyi +311 -0
  22. ostk/astrodynamics/eclipse.pyi +70 -0
  23. ostk/astrodynamics/estimator.pyi +268 -0
  24. ostk/astrodynamics/event_condition.pyi +910 -0
  25. ostk/astrodynamics/flight/__init__.pyi +626 -0
  26. ostk/astrodynamics/flight/profile/__init__.pyi +99 -0
  27. ostk/astrodynamics/flight/profile/model.pyi +179 -0
  28. ostk/astrodynamics/flight/system.pyi +268 -0
  29. ostk/astrodynamics/guidance_law.pyi +416 -0
  30. ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.17 +0 -0
  31. ostk/astrodynamics/pytrajectory/__init__.py +1 -0
  32. ostk/astrodynamics/pytrajectory/__init__.pyi +3 -0
  33. ostk/astrodynamics/pytrajectory/pystate.py +263 -0
  34. ostk/astrodynamics/pytrajectory/pystate.pyi +66 -0
  35. ostk/astrodynamics/solver.pyi +432 -0
  36. ostk/astrodynamics/test/__init__.py +1 -0
  37. ostk/astrodynamics/test/access/__init__.py +1 -0
  38. ostk/astrodynamics/test/access/test_generator.py +319 -0
  39. ostk/astrodynamics/test/access/test_visibility_criterion.py +201 -0
  40. ostk/astrodynamics/test/conftest.py +119 -0
  41. ostk/astrodynamics/test/conjunction/close_approach/__init__.py +0 -0
  42. ostk/astrodynamics/test/conjunction/close_approach/test_generator.py +228 -0
  43. ostk/astrodynamics/test/conjunction/message/ccsds/__init__.py +1 -0
  44. ostk/astrodynamics/test/conjunction/message/ccsds/conftest.py +325 -0
  45. ostk/astrodynamics/test/conjunction/message/ccsds/data/cdm.json +303 -0
  46. ostk/astrodynamics/test/conjunction/message/ccsds/test_cdm.py +416 -0
  47. ostk/astrodynamics/test/conjunction/test_close_approach.py +244 -0
  48. ostk/astrodynamics/test/data/provider/test_off_nadir.py +58 -0
  49. ostk/astrodynamics/test/dynamics/__init__.py +1 -0
  50. ostk/astrodynamics/test/dynamics/data/Tabulated_Earth_Gravity.csv +565 -0
  51. ostk/astrodynamics/test/dynamics/data/Tabulated_Earth_Gravity_Truth.csv +100 -0
  52. ostk/astrodynamics/test/dynamics/test_atmospheric_drag.py +128 -0
  53. ostk/astrodynamics/test/dynamics/test_central_body_gravity.py +58 -0
  54. ostk/astrodynamics/test/dynamics/test_dynamics.py +50 -0
  55. ostk/astrodynamics/test/dynamics/test_position_derivative.py +51 -0
  56. ostk/astrodynamics/test/dynamics/test_tabulated.py +138 -0
  57. ostk/astrodynamics/test/dynamics/test_third_body_gravity.py +67 -0
  58. ostk/astrodynamics/test/dynamics/test_thruster.py +157 -0
  59. ostk/astrodynamics/test/eclipse/__init__.py +1 -0
  60. ostk/astrodynamics/test/eclipse/test_generator.py +138 -0
  61. ostk/astrodynamics/test/estimator/test_orbit_determination_solver.py +261 -0
  62. ostk/astrodynamics/test/estimator/test_tle_solver.py +216 -0
  63. ostk/astrodynamics/test/event_condition/test_angular_condition.py +113 -0
  64. ostk/astrodynamics/test/event_condition/test_boolean_condition.py +55 -0
  65. ostk/astrodynamics/test/event_condition/test_brouwer_lyddane_mean_long_condition.py +135 -0
  66. ostk/astrodynamics/test/event_condition/test_coe_condition.py +135 -0
  67. ostk/astrodynamics/test/event_condition/test_instant_condition.py +48 -0
  68. ostk/astrodynamics/test/event_condition/test_logical_condition.py +120 -0
  69. ostk/astrodynamics/test/event_condition/test_real_condition.py +50 -0
  70. ostk/astrodynamics/test/flight/__init__.py +1 -0
  71. ostk/astrodynamics/test/flight/profile/model/test_tabulated_profile.py +115 -0
  72. ostk/astrodynamics/test/flight/system/__init__.py +1 -0
  73. ostk/astrodynamics/test/flight/system/test_propulsion_system.py +64 -0
  74. ostk/astrodynamics/test/flight/system/test_satellite_system.py +83 -0
  75. ostk/astrodynamics/test/flight/system/test_satellite_system_builder.py +71 -0
  76. ostk/astrodynamics/test/flight/test_maneuver.py +231 -0
  77. ostk/astrodynamics/test/flight/test_profile.py +293 -0
  78. ostk/astrodynamics/test/flight/test_system.py +45 -0
  79. ostk/astrodynamics/test/guidance_law/test_constant_thrust.py +177 -0
  80. ostk/astrodynamics/test/guidance_law/test_guidance_law.py +60 -0
  81. ostk/astrodynamics/test/guidance_law/test_heterogeneous_guidance_law.py +164 -0
  82. ostk/astrodynamics/test/guidance_law/test_qlaw.py +209 -0
  83. ostk/astrodynamics/test/solvers/__init__.py +1 -0
  84. ostk/astrodynamics/test/solvers/test_finite_difference_solver.py +196 -0
  85. ostk/astrodynamics/test/solvers/test_least_squares_solver.py +334 -0
  86. ostk/astrodynamics/test/solvers/test_temporal_condition_solver.py +161 -0
  87. ostk/astrodynamics/test/test_access.py +128 -0
  88. ostk/astrodynamics/test/test_converters.py +290 -0
  89. ostk/astrodynamics/test/test_dataframe.py +1355 -0
  90. ostk/astrodynamics/test/test_display.py +184 -0
  91. ostk/astrodynamics/test/test_event_condition.py +80 -0
  92. ostk/astrodynamics/test/test_import.py +26 -0
  93. ostk/astrodynamics/test/test_root_solver.py +70 -0
  94. ostk/astrodynamics/test/test_trajectory.py +126 -0
  95. ostk/astrodynamics/test/test_utilities.py +338 -0
  96. ostk/astrodynamics/test/test_viewer.py +318 -0
  97. ostk/astrodynamics/test/trajectory/__init__.py +1 -0
  98. ostk/astrodynamics/test/trajectory/model/test_nadir_trajectory.py +87 -0
  99. ostk/astrodynamics/test/trajectory/model/test_tabulated_trajectory.py +303 -0
  100. ostk/astrodynamics/test/trajectory/model/test_target_scan_trajectory.py +126 -0
  101. ostk/astrodynamics/test/trajectory/orbit/__init__.py +1 -0
  102. ostk/astrodynamics/test/trajectory/orbit/message/__init__.py +1 -0
  103. ostk/astrodynamics/test/trajectory/orbit/message/spacex/__init__.py +1 -0
  104. ostk/astrodynamics/test/trajectory/orbit/message/spacex/conftest.py +18 -0
  105. ostk/astrodynamics/test/trajectory/orbit/message/spacex/data/opm_1.yaml +44 -0
  106. ostk/astrodynamics/test/trajectory/orbit/message/spacex/test_opm.py +108 -0
  107. ostk/astrodynamics/test/trajectory/orbit/models/__init__.py +1 -0
  108. ostk/astrodynamics/test/trajectory/orbit/models/kepler/__init__.py +1 -0
  109. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean.py +65 -0
  110. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean_long.py +102 -0
  111. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean_short.py +102 -0
  112. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_coe.py +305 -0
  113. ostk/astrodynamics/test/trajectory/orbit/models/sgp4/__init__.py +1 -0
  114. ostk/astrodynamics/test/trajectory/orbit/models/sgp4/test_tle.py +337 -0
  115. ostk/astrodynamics/test/trajectory/orbit/models/test_kepler.py +130 -0
  116. ostk/astrodynamics/test/trajectory/orbit/models/test_modified_equinoctial.py +142 -0
  117. ostk/astrodynamics/test/trajectory/orbit/models/test_propagated.py +234 -0
  118. ostk/astrodynamics/test/trajectory/orbit/models/test_sgp4.py +1 -0
  119. ostk/astrodynamics/test/trajectory/orbit/models/test_tabulated.py +380 -0
  120. ostk/astrodynamics/test/trajectory/orbit/test_model.py +1 -0
  121. ostk/astrodynamics/test/trajectory/orbit/test_pass.py +75 -0
  122. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_angular_velocity.py +30 -0
  123. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_attitude_quaternion.py +18 -0
  124. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_acceleration.py +136 -0
  125. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_position.py +107 -0
  126. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_velocity.py +115 -0
  127. ostk/astrodynamics/test/trajectory/state/test_coordinate_broker.py +84 -0
  128. ostk/astrodynamics/test/trajectory/state/test_coordinate_subset.py +58 -0
  129. ostk/astrodynamics/test/trajectory/state/test_numerical_solver.py +316 -0
  130. ostk/astrodynamics/test/trajectory/test_local_orbital_frame_direction.py +81 -0
  131. ostk/astrodynamics/test/trajectory/test_local_orbital_frame_factory.py +119 -0
  132. ostk/astrodynamics/test/trajectory/test_model.py +1 -0
  133. ostk/astrodynamics/test/trajectory/test_orbit.py +212 -0
  134. ostk/astrodynamics/test/trajectory/test_propagator.py +452 -0
  135. ostk/astrodynamics/test/trajectory/test_segment.py +694 -0
  136. ostk/astrodynamics/test/trajectory/test_sequence.py +550 -0
  137. ostk/astrodynamics/test/trajectory/test_state.py +629 -0
  138. ostk/astrodynamics/test/trajectory/test_state_builder.py +172 -0
  139. ostk/astrodynamics/trajectory/__init__.pyi +1982 -0
  140. ostk/astrodynamics/trajectory/model.pyi +259 -0
  141. ostk/astrodynamics/trajectory/orbit/__init__.pyi +349 -0
  142. ostk/astrodynamics/trajectory/orbit/message/__init__.pyi +3 -0
  143. ostk/astrodynamics/trajectory/orbit/message/spacex.pyi +264 -0
  144. ostk/astrodynamics/trajectory/orbit/model/__init__.pyi +648 -0
  145. ostk/astrodynamics/trajectory/orbit/model/brouwerLyddaneMean.pyi +121 -0
  146. ostk/astrodynamics/trajectory/orbit/model/kepler.pyi +709 -0
  147. ostk/astrodynamics/trajectory/orbit/model/sgp4.pyi +330 -0
  148. ostk/astrodynamics/trajectory/state/__init__.pyi +402 -0
  149. ostk/astrodynamics/trajectory/state/coordinate_subset.pyi +208 -0
  150. ostk/astrodynamics/utilities.py +396 -0
  151. ostk/astrodynamics/viewer.py +851 -0
@@ -0,0 +1,396 @@
1
+ # Apache License 2.0
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from datetime import datetime
7
+ from datetime import timezone
8
+
9
+ import numpy as np
10
+
11
+ from ostk.physics import Environment
12
+ from ostk.physics.time import Scale
13
+ from ostk.physics.time import Instant
14
+ from ostk.physics.time import Duration
15
+ from ostk.physics.time import Interval
16
+ from ostk.physics.unit import Length
17
+ from ostk.physics.coordinate.spherical import LLA
18
+ from ostk.physics.coordinate.spherical import AER
19
+ from ostk.physics.coordinate import Position
20
+ from ostk.physics.coordinate import Frame
21
+ from ostk.physics.environment.object.celestial import Earth
22
+ from ostk.physics.environment.gravitational import Earth as EarthGravitationalModel
23
+
24
+ from ostk.astrodynamics import Trajectory
25
+ from ostk.astrodynamics.converters import coerce_to_datetime
26
+ from ostk.astrodynamics.trajectory import State
27
+ from ostk.astrodynamics.trajectory import StateBuilder
28
+ from ostk.astrodynamics.trajectory import Orbit
29
+ from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianPosition
30
+ from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianVelocity
31
+ from ostk.astrodynamics.trajectory import LocalOrbitalFrameFactory
32
+
33
+
34
+ POSITION_VELOCITY_STATE_BUILDER: StateBuilder = StateBuilder(
35
+ frame=Frame.GCRF(),
36
+ coordinate_subsets=[
37
+ CartesianPosition.default(),
38
+ CartesianVelocity.default(),
39
+ ],
40
+ )
41
+
42
+ DEFAULT_INERTIAL_FRAME: Frame = Frame.GCRF()
43
+
44
+
45
+ @dataclass
46
+ class Residual:
47
+ timestamp: datetime
48
+ frame: Frame
49
+ dr: float
50
+ dr_x: float
51
+ dr_y: float
52
+ dr_z: float
53
+ dv: float
54
+ dv_x: float
55
+ dv_y: float
56
+ dv_z: float
57
+
58
+
59
+ def compute_residuals(
60
+ candidate_states: list[State],
61
+ reference_states: list[State],
62
+ local_orbital_frame_factory_or_frame: (
63
+ LocalOrbitalFrameFactory | Frame
64
+ ) = DEFAULT_INERTIAL_FRAME,
65
+ ) -> list[Residual]:
66
+ """
67
+ Compute position and velocity residuals by comparing candidate states against reference states.
68
+
69
+ Args:
70
+ candidate_states (list[State]): Candidate list of States.
71
+ reference_states (list[State]): List of reference States to compare against.
72
+ local_orbital_frame_factory_or_frame (LocalOrbitalFrameFactory | Frame, optional): The local orbital frame factory to use. Defaults to Frame.GCRF().
73
+
74
+ Returns:
75
+ list[Residual]: List of Residuals.
76
+ """
77
+ residuals: list[Residual] = []
78
+
79
+ for candidate_state, reference_state in zip(candidate_states, reference_states):
80
+ frame: Frame
81
+ if isinstance(local_orbital_frame_factory_or_frame, LocalOrbitalFrameFactory):
82
+ frame = local_orbital_frame_factory_or_frame.generate_frame(candidate_state)
83
+ else:
84
+ frame = local_orbital_frame_factory_or_frame
85
+
86
+ relative_state: State = POSITION_VELOCITY_STATE_BUILDER.reduce(
87
+ candidate_state
88
+ ).in_frame(frame) - POSITION_VELOCITY_STATE_BUILDER.reduce(
89
+ reference_state
90
+ ).in_frame(
91
+ frame
92
+ )
93
+
94
+ dr: np.ndarray = relative_state.get_position().get_coordinates()
95
+ dv: np.ndarray = relative_state.get_velocity().get_coordinates()
96
+
97
+ residuals.append(
98
+ Residual(
99
+ timestamp=coerce_to_datetime(reference_state.get_instant()),
100
+ frame=frame,
101
+ dr=float(np.linalg.norm(dr)),
102
+ dr_x=float(dr[0]),
103
+ dr_y=float(dr[1]),
104
+ dr_z=float(dr[2]),
105
+ dv=float(np.linalg.norm(dv)),
106
+ dv_x=float(dv[0]),
107
+ dv_y=float(dv[1]),
108
+ dv_z=float(dv[2]),
109
+ )
110
+ )
111
+
112
+ return residuals
113
+
114
+
115
+ def compute_residuals_for_orbit(
116
+ candidate_orbit: Orbit,
117
+ reference_states: list[State],
118
+ local_orbital_frame_factory_or_frame: (
119
+ LocalOrbitalFrameFactory | Frame
120
+ ) = DEFAULT_INERTIAL_FRAME,
121
+ ) -> list[Residual]:
122
+ """
123
+ Compute position and velocity residuals for an orbit against a list of reference states.
124
+
125
+ Args:
126
+ candidate_orbit (Orbit): Candidate Orbit used to generate states at the instants of the reference states.
127
+ reference_states (list[State]): List of reference States to compare against.
128
+ local_orbital_frame_factory_or_frame (LocalOrbitalFrameFactory | Frame, optional): The local orbital frame factory to use. Defaults to Frame.GCRF().
129
+
130
+ Returns:
131
+ list[Residual]: List of Residuals.
132
+ """
133
+ instants: list[Instant] = [state.get_instant() for state in reference_states]
134
+ candidate_states: list[State] = candidate_orbit.get_states_at(instants)
135
+
136
+ return compute_residuals(
137
+ candidate_states=candidate_states,
138
+ reference_states=reference_states,
139
+ local_orbital_frame_factory_or_frame=local_orbital_frame_factory_or_frame,
140
+ )
141
+
142
+
143
+ def compute_residuals_for_orbits(
144
+ candidate_orbit: Orbit,
145
+ reference_orbit: Orbit,
146
+ instants: list[Instant],
147
+ local_orbital_frame_factory_or_frame: (
148
+ LocalOrbitalFrameFactory | Frame
149
+ ) = DEFAULT_INERTIAL_FRAME,
150
+ ) -> list[Residual]:
151
+ """
152
+ Compare two orbits at the provided instants and compute position and velocity residuals.
153
+
154
+ Args:
155
+ candidate_orbit (Orbit): Candidate Orbit.
156
+ reference_orbit (Orbit): Reference Orbit.
157
+ instants (list[Instant]): List of instants to generate states at.
158
+ local_orbital_frame_factory_or_frame (LocalOrbitalFrameFactory | Frame, optional): The local orbital frame factory to use. Defaults to Frame.GCRF().
159
+
160
+ Returns:
161
+ list[Residual]: List of Residuals.
162
+ """
163
+ candidate_states: list[State] = candidate_orbit.get_states_at(instants)
164
+ reference_states: list[State] = reference_orbit.get_states_at(instants)
165
+
166
+ return compute_residuals(
167
+ candidate_states=candidate_states,
168
+ reference_states=reference_states,
169
+ local_orbital_frame_factory_or_frame=local_orbital_frame_factory_or_frame,
170
+ )
171
+
172
+
173
+ def lla_from_state(state: State) -> LLA:
174
+ """
175
+ Return latitude (degrees), longitude (degrees), altitude (meters) float list from a state.
176
+
177
+ Args:
178
+ state (State): A state.
179
+
180
+ Returns:
181
+ LLA: The LLA.
182
+ """
183
+
184
+ return lla_from_position(state.get_position(), state.get_instant())
185
+
186
+
187
+ def lla_from_position(
188
+ position: Position,
189
+ instant: Instant | None = None,
190
+ ) -> LLA:
191
+ """
192
+ Return LLA from position and instant.
193
+
194
+ Args:
195
+ position (Position): A position.
196
+ instant (Instant): An instant.
197
+
198
+ Returns:
199
+ LLA: The LLA.
200
+ """
201
+
202
+ if position.access_frame() != Frame.ITRF():
203
+ if instant is None:
204
+ raise ValueError(
205
+ "Instant must be provided if position is not expressed in ECEF."
206
+ )
207
+ position: Position = position.in_frame(Frame.ITRF(), instant)
208
+
209
+ return LLA.cartesian(
210
+ position.get_coordinates(),
211
+ EarthGravitationalModel.EGM2008.equatorial_radius,
212
+ EarthGravitationalModel.EGM2008.flattening,
213
+ )
214
+
215
+
216
+ def position_from_lla(lla: LLA) -> Position:
217
+ """
218
+ Return position from lla.
219
+
220
+ Args:
221
+ lla (LLA): A LLA.
222
+
223
+ Returns:
224
+ Position: The position.
225
+ """
226
+
227
+ return Position.meters(
228
+ lla.to_cartesian(
229
+ EarthGravitationalModel.EGM2008.equatorial_radius,
230
+ EarthGravitationalModel.EGM2008.flattening,
231
+ ),
232
+ Frame.ITRF(),
233
+ )
234
+
235
+
236
+ def compute_aer(
237
+ instant: Instant,
238
+ from_position: Position,
239
+ to_position: Position,
240
+ environment: Environment,
241
+ ) -> AER:
242
+ """
243
+ Return AER from Instant and Positions (observer, target).
244
+
245
+ Args:
246
+ instant (Instant): An instant.
247
+ from_position (Position): An observer position.
248
+ to_position (Position): A target position.
249
+ environment (Environment): An environment.
250
+
251
+ Returns:
252
+ AER: The AER.
253
+ """
254
+
255
+ from_lla: LLA = lla_from_position(from_position, instant)
256
+
257
+ earth: Earth = environment.access_celestial_object_with_name("Earth")
258
+ ned_frame: Frame = earth.get_frame_at(from_lla, Earth.FrameType.NED)
259
+
260
+ from_position_NED: Position = from_position.in_frame(ned_frame, instant)
261
+ to_position_NED: Position = to_position.in_frame(ned_frame, instant)
262
+
263
+ return AER.from_position_to_position(from_position_NED, to_position_NED, True)
264
+
265
+
266
+ def compute_time_lla_aer_coordinates(
267
+ state: State,
268
+ from_position: Position,
269
+ environment: Environment,
270
+ ) -> tuple[datetime, float, float, float, float, float, float]:
271
+ """
272
+ Return [datetime, latitude, longitude, altitude, azimuth, elevation, range] from State and observer Position.
273
+
274
+ Args:
275
+ state (State): A state.
276
+ from_position (Position): An observer position.
277
+ environment (Environment): An environment.
278
+
279
+ Returns:
280
+ tuple[datetime, float, float, float, float, float, float]: The [datetime, latitude, longitude, altitude, azimuth, elevation, range].
281
+ """
282
+
283
+ instant: Instant = state.get_instant()
284
+
285
+ lla: LLA = lla_from_state(state)
286
+
287
+ aer: AER = compute_aer(
288
+ instant,
289
+ from_position,
290
+ state.get_position().in_frame(Frame.ITRF(), state.get_instant()),
291
+ environment,
292
+ )
293
+
294
+ return (
295
+ instant.get_date_time(Scale.UTC).replace(tzinfo=timezone.utc),
296
+ float(lla.get_latitude().in_degrees()),
297
+ float(lla.get_longitude().in_degrees()),
298
+ float(lla.get_altitude().in_meters()),
299
+ float(aer.get_azimuth().in_degrees()),
300
+ float(aer.get_elevation().in_degrees()),
301
+ float(aer.get_range().in_meters()),
302
+ )
303
+
304
+
305
+ def compute_trajectory_geometry(
306
+ trajectory: Trajectory,
307
+ interval: Interval,
308
+ step: Duration = Duration.minutes(1.0),
309
+ ) -> list[LLA]:
310
+ """
311
+ Return list of LLA along a Trajectory during the Interval at the provided step.
312
+
313
+ Args:
314
+ trajectory (Trajectory): A trajectory.
315
+ interval (Interval): An interval.
316
+ step (Duration): A step. Defaults to 1.0 minutes.
317
+
318
+ Returns:
319
+ list[LLA]: The list of LLA.
320
+ """
321
+
322
+ return [
323
+ lla_from_state(state)
324
+ for state in trajectory.get_states_at(interval.generate_grid(step))
325
+ ]
326
+
327
+
328
+ def compute_ground_track(
329
+ trajectory: Trajectory,
330
+ interval: Interval,
331
+ step: Duration = Duration.minutes(1.0),
332
+ ) -> list[LLA]:
333
+ """
334
+ Return list of LLA along a Trajectory ground track (altitude set to 10.0 meters) during the Interval at the provided step.
335
+
336
+ Args:
337
+ trajectory (Trajectory): A trajectory.
338
+ interval (Interval): An interval.
339
+ step (Duration): A step. Defaults to 1.0 minutes.
340
+
341
+ Returns:
342
+ list[LLA]: The list of LLA.
343
+ """
344
+
345
+ ground_llas: list[LLA] = []
346
+ for state in trajectory.get_states_at(interval.generate_grid(step)):
347
+ lla: LLA = lla_from_state(state)
348
+
349
+ ground_lla: LLA = LLA(
350
+ lla.get_latitude(),
351
+ lla.get_longitude(),
352
+ Length.meters(10.0),
353
+ )
354
+
355
+ ground_llas.append(ground_lla)
356
+
357
+ return ground_llas
358
+
359
+
360
+ def convert_state(
361
+ state: State,
362
+ ) -> tuple[str, float, float, float, float, float, float, float, float, float]:
363
+ """
364
+ Convert a State into dataframe-ready values.
365
+ - Instant (str)
366
+ - Modified Julian Date (float)
367
+ - Position X [meters] (float)
368
+ - Position Y [meters] (float)
369
+ - Position Z [meters] (float)
370
+ - Velocity X [meters/second] (float)
371
+ - Velocity Y [meters/second] (float)
372
+ - Velocity Z [meters/second] (float)
373
+ - Latitude [degrees] (float)
374
+ - Longitude [degrees] (float)
375
+ - Altitude [meters] (float)
376
+
377
+ Args:
378
+ state (State): A state.
379
+
380
+ Returns:
381
+ tuple[str, float, float, float, float, float, float, float, float, float]: The dataframe-ready values.
382
+ """
383
+
384
+ lla: LLA = lla_from_state(state)
385
+
386
+ instant: Instant = state.get_instant()
387
+
388
+ return (
389
+ str(instant.to_string()),
390
+ float(instant.get_modified_julian_date(Scale.UTC)),
391
+ *state.get_position().get_coordinates().transpose().tolist(),
392
+ *state.get_velocity().get_coordinates().transpose().tolist(),
393
+ float(lla.get_latitude().in_degrees()),
394
+ float(lla.get_longitude().in_degrees()),
395
+ float(lla.get_altitude().in_meters()),
396
+ )