open-space-toolkit-astrodynamics 9.1.6__py39-none-manylinux2014_aarch64.whl → 13.0.2__py39-none-manylinux2014_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. {open_space_toolkit_astrodynamics-9.1.6.dist-info → open_space_toolkit_astrodynamics-13.0.2.dist-info}/METADATA +5 -5
  2. {open_space_toolkit_astrodynamics-9.1.6.dist-info → open_space_toolkit_astrodynamics-13.0.2.dist-info}/RECORD +29 -27
  3. {open_space_toolkit_astrodynamics-9.1.6.dist-info → open_space_toolkit_astrodynamics-13.0.2.dist-info}/WHEEL +1 -1
  4. ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-39-aarch64-linux-gnu.so +0 -0
  5. ostk/astrodynamics/converters.py +35 -90
  6. ostk/astrodynamics/dataframe.py +479 -0
  7. ostk/astrodynamics/display.py +2 -0
  8. ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.13 +0 -0
  9. ostk/astrodynamics/pytrajectory/pystate.py +216 -1
  10. ostk/astrodynamics/test/conftest.py +2 -2
  11. ostk/astrodynamics/test/flight/test_profile.py +155 -55
  12. ostk/astrodynamics/test/test_converters.py +43 -140
  13. ostk/astrodynamics/test/test_dataframe.py +875 -0
  14. ostk/astrodynamics/test/test_display.py +2 -3
  15. ostk/astrodynamics/test/test_event_condition.py +27 -7
  16. ostk/astrodynamics/test/test_trajectory.py +116 -38
  17. ostk/astrodynamics/test/test_utilities.py +31 -46
  18. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_coe.py +13 -0
  19. ostk/astrodynamics/test/trajectory/orbit/test_pass.py +9 -0
  20. ostk/astrodynamics/test/trajectory/state/test_coordinate_subset.py +3 -0
  21. ostk/astrodynamics/test/trajectory/state/test_numerical_solver.py +2 -2
  22. ostk/astrodynamics/test/trajectory/test_local_orbital_frame_factory.py +34 -2
  23. ostk/astrodynamics/test/trajectory/test_orbit.py +26 -2
  24. ostk/astrodynamics/test/trajectory/test_segment.py +99 -1
  25. ostk/astrodynamics/test/trajectory/test_sequence.py +53 -0
  26. ostk/astrodynamics/test/trajectory/test_state.py +306 -0
  27. ostk/astrodynamics/utilities.py +125 -36
  28. ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.9 +0 -0
  29. {open_space_toolkit_astrodynamics-9.1.6.dist-info → open_space_toolkit_astrodynamics-13.0.2.dist-info}/top_level.txt +0 -0
  30. {open_space_toolkit_astrodynamics-9.1.6.dist-info → open_space_toolkit_astrodynamics-13.0.2.dist-info}/zip-safe +0 -0
@@ -339,6 +339,59 @@ def instants(state: State) -> list[Instant]:
339
339
  return [state.get_instant(), state.get_instant() + Duration.minutes(1.0)]
340
340
 
341
341
 
342
+ @pytest.fixture
343
+ def sequence_solution(
344
+ segment_solution: Segment.Solution,
345
+ ):
346
+ return Sequence.Solution(
347
+ segment_solutions=[
348
+ segment_solution,
349
+ ],
350
+ execution_is_complete=True,
351
+ )
352
+
353
+
354
+ class TestSequenceSolution:
355
+ def test_properties(
356
+ self,
357
+ sequence_solution: Sequence.Solution,
358
+ ):
359
+ assert sequence_solution is not None
360
+ assert len(sequence_solution.segment_solutions) == 1
361
+ assert sequence_solution.execution_is_complete
362
+
363
+ def test_getters_and_accessors(
364
+ self,
365
+ sequence_solution: Sequence.Solution,
366
+ ):
367
+ assert sequence_solution.access_start_instant() is not None
368
+ assert sequence_solution.access_end_instant() is not None
369
+
370
+ assert sequence_solution.get_states() is not None
371
+ assert sequence_solution.get_initial_mass() is not None
372
+ assert sequence_solution.get_final_mass() is not None
373
+ assert sequence_solution.get_propagation_duration() is not None
374
+
375
+ assert sequence_solution.compute_delta_mass() is not None
376
+ assert sequence_solution.compute_delta_v(1500.0) is not None
377
+
378
+ def test_calculate_states_at(
379
+ self,
380
+ sequence_solution: Sequence.Solution,
381
+ numerical_solver: NumericalSolver,
382
+ ):
383
+ instants: list[Instant] = sequence_solution.get_interval().generate_grid(
384
+ Duration.seconds(10.0)
385
+ )
386
+ states: list[State] = sequence_solution.calculate_states_at(
387
+ instants,
388
+ numerical_solver,
389
+ )
390
+
391
+ assert states is not None
392
+ assert len(states) == len(instants)
393
+
394
+
342
395
  class TestSequence:
343
396
  def test_get_segments(
344
397
  self,
@@ -2,6 +2,8 @@
2
2
 
3
3
  import pytest
4
4
 
5
+ from datetime import datetime, timezone
6
+
5
7
  import numpy as np
6
8
 
7
9
  from ostk.mathematics.geometry.d3.transformation.rotation import Quaternion
@@ -177,6 +179,310 @@ class TestState:
177
179
  assert custom_state == state
178
180
  assert custom_state is not state
179
181
 
182
+ def test_from_dict_with_eci_coordinates(self):
183
+ data = {
184
+ "timestamp": datetime.now(timezone.utc),
185
+ "rx_eci": 7000.0,
186
+ "ry_eci": 0.0,
187
+ "rz_eci": 0.0,
188
+ "vx_eci": 0.0,
189
+ "vy_eci": 7.5,
190
+ "vz_eci": 0.0,
191
+ }
192
+
193
+ state: State = State.from_dict(data)
194
+
195
+ assert state is not None
196
+ assert isinstance(state, State)
197
+ assert state.get_frame() == Frame.GCRF()
198
+ assert state.get_size() == 6
199
+
200
+ def test_from_dict_with_ecef_coordinates(self):
201
+ data = {
202
+ "timestamp": datetime.now(timezone.utc).isoformat(),
203
+ "rx_ecef": 7000.0,
204
+ "ry_ecef": 0.0,
205
+ "rz_ecef": 0.0,
206
+ "vx_ecef": 0.0,
207
+ "vy_ecef": 7.5,
208
+ "vz_ecef": 0.0,
209
+ }
210
+
211
+ state: State = State.from_dict(data)
212
+
213
+ assert state is not None
214
+ assert isinstance(state, State)
215
+ assert state.get_frame() == Frame.ITRF()
216
+ assert state.get_size() == 6
217
+
218
+ def test_from_dict_with_generic_coordinates(self):
219
+ data = {
220
+ "timestamp": datetime.now(timezone.utc).isoformat(),
221
+ "rx": 7000.0,
222
+ "ry": 0.0,
223
+ "rz": 0.0,
224
+ "vx": 0.0,
225
+ "vy": 7.5,
226
+ "vz": 0.0,
227
+ "frame": "GCRF",
228
+ }
229
+
230
+ state: State = State.from_dict(data)
231
+
232
+ assert state is not None
233
+ assert isinstance(state, State)
234
+ assert state.get_frame() == Frame.GCRF()
235
+ assert state.get_size() == 6
236
+
237
+ with pytest.raises(
238
+ ValueError, match="Frame must be provided for generic columns."
239
+ ):
240
+ data = {
241
+ "timestamp": datetime.now(timezone.utc).isoformat(),
242
+ "rx": 7000.0,
243
+ "ry": 0.0,
244
+ "rz": 0.0,
245
+ "vx": 0.0,
246
+ "vy": 7.5,
247
+ "vz": 0.0,
248
+ }
249
+
250
+ State.from_dict(data)
251
+
252
+ with pytest.raises(ValueError, match="No frame exists with name \\[RANDOM\\]."):
253
+ data = {
254
+ "timestamp": datetime.now(timezone.utc).isoformat(),
255
+ "rx": 7000.0,
256
+ "ry": 0.0,
257
+ "rz": 0.0,
258
+ "vx": 0.0,
259
+ "vy": 7.5,
260
+ "vz": 0.0,
261
+ "frame": "RANDOM",
262
+ }
263
+
264
+ State.from_dict(data)
265
+
266
+ with pytest.raises(ValueError, match="Invalid frame data \\[123\\]"):
267
+ data = {
268
+ "timestamp": datetime.now(timezone.utc).isoformat(),
269
+ "rx": 7000.0,
270
+ "ry": 0.0,
271
+ "rz": 0.0,
272
+ "vx": 0.0,
273
+ "vy": 7.5,
274
+ "vz": 0.0,
275
+ "frame": 123,
276
+ }
277
+
278
+ State.from_dict(data)
279
+
280
+ def test_from_dict_with_attitude_quaternion(self):
281
+ data = {
282
+ "timestamp": datetime.now(timezone.utc).isoformat(),
283
+ "rx_eci": 7000.0,
284
+ "ry_eci": 0.0,
285
+ "rz_eci": 0.0,
286
+ "vx_eci": 0.0,
287
+ "vy_eci": 7.5,
288
+ "vz_eci": 0.0,
289
+ "q_B_ECI_x": 0.0,
290
+ "q_B_ECI_y": 0.0,
291
+ "q_B_ECI_z": 0.0,
292
+ "q_B_ECI_s": 1.0,
293
+ }
294
+
295
+ state: State = State.from_dict(data)
296
+
297
+ assert state is not None
298
+ assert isinstance(state, State)
299
+ assert state.get_frame() == Frame.GCRF()
300
+ assert state.get_size() == 10
301
+
302
+ def test_from_dict_with_angular_velocity(self):
303
+ data = {
304
+ "timestamp": datetime.now(timezone.utc).isoformat(),
305
+ "rx_eci": 7000.0,
306
+ "ry_eci": 0.0,
307
+ "rz_eci": 0.0,
308
+ "vx_eci": 0.0,
309
+ "vy_eci": 7.5,
310
+ "vz_eci": 0.0,
311
+ "w_B_ECI_in_B_x": 0.1,
312
+ "w_B_ECI_in_B_y": 0.2,
313
+ "w_B_ECI_in_B_z": 0.3,
314
+ }
315
+
316
+ state: State = State.from_dict(data)
317
+
318
+ assert state is not None
319
+ assert isinstance(state, State)
320
+ assert state.get_size() == 9
321
+
322
+ def test_from_dict_with_drag_coefficient(self):
323
+ data = {
324
+ "timestamp": datetime.now(timezone.utc).isoformat(),
325
+ "rx_eci": 7000.0,
326
+ "ry_eci": 0.0,
327
+ "rz_eci": 0.0,
328
+ "vx_eci": 0.0,
329
+ "vy_eci": 7.5,
330
+ "vz_eci": 0.0,
331
+ "drag_coefficient": 2.2,
332
+ }
333
+
334
+ state: State = State.from_dict(data)
335
+
336
+ assert state is not None
337
+ assert isinstance(state, State)
338
+ assert state.get_size() == 7
339
+
340
+ data = {
341
+ "timestamp": datetime.now(timezone.utc).isoformat(),
342
+ "rx_eci": 7000.0,
343
+ "ry_eci": 0.0,
344
+ "rz_eci": 0.0,
345
+ "vx_eci": 0.0,
346
+ "vy_eci": 7.5,
347
+ "vz_eci": 0.0,
348
+ "cd": 2.2,
349
+ }
350
+
351
+ state: State = State.from_dict(data)
352
+
353
+ assert state is not None
354
+ assert isinstance(state, State)
355
+ assert state.get_size() == 7
356
+
357
+ def test_from_dict_with_surface_area(self):
358
+ data = {
359
+ "timestamp": datetime.now(timezone.utc).isoformat(),
360
+ "rx_eci": 7000.0,
361
+ "ry_eci": 0.0,
362
+ "rz_eci": 0.0,
363
+ "vx_eci": 0.0,
364
+ "vy_eci": 7.5,
365
+ "vz_eci": 0.0,
366
+ "surface_area": 2.2,
367
+ }
368
+
369
+ state: State = State.from_dict(data)
370
+
371
+ assert state is not None
372
+ assert isinstance(state, State)
373
+ assert state.get_size() == 7
374
+
375
+ data = {
376
+ "timestamp": datetime.now(timezone.utc).isoformat(),
377
+ "rx_eci": 7000.0,
378
+ "ry_eci": 0.0,
379
+ "rz_eci": 0.0,
380
+ "vx_eci": 0.0,
381
+ "vy_eci": 7.5,
382
+ "vz_eci": 0.0,
383
+ "cross_sectional_area": 2.2,
384
+ }
385
+
386
+ state: State = State.from_dict(data)
387
+
388
+ assert state is not None
389
+ assert isinstance(state, State)
390
+ assert state.get_size() == 7
391
+
392
+ def test_from_dict_with_mass(self):
393
+ data = {
394
+ "timestamp": datetime.now(timezone.utc).isoformat(),
395
+ "rx_eci": 7000.0,
396
+ "ry_eci": 0.0,
397
+ "rz_eci": 0.0,
398
+ "vx_eci": 0.0,
399
+ "vy_eci": 7.5,
400
+ "vz_eci": 0.0,
401
+ "mass": 2.2,
402
+ }
403
+
404
+ state: State = State.from_dict(data)
405
+
406
+ assert state is not None
407
+ assert isinstance(state, State)
408
+ assert state.get_size() == 7
409
+
410
+ @pytest.mark.parametrize(
411
+ ("data", "expected_length", "expected_frame"),
412
+ [
413
+ (
414
+ {
415
+ "timestamp": datetime.now(timezone.utc).isoformat(),
416
+ "r_GCRF_x": 1.0,
417
+ "r_GCRF_y": 2.0,
418
+ "r_GCRF_z": 3.0,
419
+ "v_GCRF_x": 4.0,
420
+ "v_GCRF_y": 5.0,
421
+ "v_GCRF_z": 6.0,
422
+ },
423
+ 6,
424
+ Frame.GCRF(),
425
+ ),
426
+ (
427
+ {
428
+ "timestamp": datetime.now(timezone.utc).isoformat(),
429
+ "r_ITRF_x": 1.0,
430
+ "r_ITRF_y": 2.0,
431
+ "r_ITRF_z": 3.0,
432
+ "v_ITRF_x": 4.0,
433
+ "v_ITRF_y": 5.0,
434
+ "v_ITRF_z": 6.0,
435
+ },
436
+ 6,
437
+ Frame.ITRF(),
438
+ ),
439
+ ],
440
+ )
441
+ def test_from_dict_cannonical_success(
442
+ self, data: dict, expected_length: int, expected_frame: Frame
443
+ ):
444
+ state: State = State.from_dict(data)
445
+
446
+ assert state is not None
447
+ assert isinstance(state, State)
448
+
449
+ assert state.get_size() == expected_length
450
+ assert state.get_frame() == expected_frame
451
+
452
+ @pytest.mark.parametrize(
453
+ ("data", "expected_failure_message"),
454
+ [
455
+ (
456
+ {
457
+ "timestamp": datetime.now(timezone.utc).isoformat(),
458
+ "r_GCRF_x": 1.0,
459
+ "r_GCRF_y": 2.0,
460
+ "r_GCRF_z": 3.0,
461
+ "v_GCRF_x": 4.0,
462
+ "v_GCRF_y": 5.0,
463
+ },
464
+ "Invalid state data.",
465
+ ),
466
+ (
467
+ {
468
+ "timestamp": datetime.now(timezone.utc).isoformat(),
469
+ "r_TEST_x": 1.0,
470
+ "r_TEST_y": 2.0,
471
+ "r_TEST_z": 3.0,
472
+ "v_TEST_x": 4.0,
473
+ "v_TEST_y": 5.0,
474
+ "v_TEST_z": 6.0,
475
+ },
476
+ "No frame exists with name \\[TEST\\].",
477
+ ),
478
+ ],
479
+ )
480
+ def test_from_dict_cannonical_failure(
481
+ self, data: dict, expected_failure_message: str
482
+ ):
483
+ with pytest.raises(ValueError, match=expected_failure_message):
484
+ State.from_dict(data)
485
+
180
486
  def test_comparators(self, state: State):
181
487
  assert (state == state) is True
182
488
  assert (state != state) is False
@@ -1,5 +1,10 @@
1
1
  # Apache License 2.0
2
2
 
3
+ from __future__ import annotations
4
+
5
+ from datetime import datetime
6
+ from datetime import timezone
7
+
3
8
  from .OpenSpaceToolkitAstrodynamicsPy import *
4
9
 
5
10
  from ostk.physics import Environment
@@ -7,6 +12,7 @@ from ostk.physics.time import Scale
7
12
  from ostk.physics.time import Instant
8
13
  from ostk.physics.time import Duration
9
14
  from ostk.physics.time import Interval
15
+ from ostk.physics.unit import Length
10
16
  from ostk.physics.coordinate.spherical import LLA
11
17
  from ostk.physics.coordinate.spherical import AER
12
18
  from ostk.physics.coordinate import Position
@@ -15,18 +21,18 @@ from ostk.physics.environment.object.celestial import Earth
15
21
  from ostk.physics.environment.gravitational import Earth as EarthGravitationalModel
16
22
 
17
23
 
18
- def lla_from_state(state: trajectory.State) -> tuple[float, float, float]:
24
+ def lla_from_state(state: trajectory.State) -> LLA:
19
25
  """
20
26
  Return latitude (degrees), longitude (degrees), altitude (meters) float list from a state.
21
- """
22
27
 
23
- lla: LLA = lla_from_position(state.get_position(), state.get_instant())
28
+ Args:
29
+ state (trajectory.State): A state.
24
30
 
25
- return (
26
- float(lla.get_latitude().in_degrees()),
27
- float(lla.get_longitude().in_degrees()),
28
- float(lla.get_altitude().in_meters()),
29
- )
31
+ Returns:
32
+ LLA: The LLA.
33
+ """
34
+
35
+ return lla_from_position(state.get_position(), state.get_instant())
30
36
 
31
37
 
32
38
  def lla_from_position(
@@ -35,6 +41,13 @@ def lla_from_position(
35
41
  ) -> LLA:
36
42
  """
37
43
  Return LLA from position and instant.
44
+
45
+ Args:
46
+ position (Position): A position.
47
+ instant (Instant): An instant.
48
+
49
+ Returns:
50
+ LLA: The LLA.
38
51
  """
39
52
 
40
53
  if position.access_frame() != Frame.ITRF():
@@ -54,6 +67,12 @@ def lla_from_position(
54
67
  def position_from_lla(lla: LLA) -> Position:
55
68
  """
56
69
  Return position from lla.
70
+
71
+ Args:
72
+ lla (LLA): A LLA.
73
+
74
+ Returns:
75
+ Position: The position.
57
76
  """
58
77
 
59
78
  return Position.meters(
@@ -70,9 +89,18 @@ def compute_aer(
70
89
  from_position: Position,
71
90
  to_position: Position,
72
91
  environment: Environment,
73
- ) -> tuple[float, float, float]:
92
+ ) -> AER:
74
93
  """
75
- Return [azimuth (degrees), elevation (degrees), range (meters)] from Instant and Positions (observer, target).
94
+ Return AER from Instant and Positions (observer, target).
95
+
96
+ Args:
97
+ instant (Instant): An instant.
98
+ from_position (Position): An observer position.
99
+ to_position (Position): A target position.
100
+ environment (Environment): An environment.
101
+
102
+ Returns:
103
+ AER: The AER.
76
104
  """
77
105
 
78
106
  from_lla: LLA = lla_from_position(from_position, instant)
@@ -83,27 +111,30 @@ def compute_aer(
83
111
  from_position_NED: Position = from_position.in_frame(ned_frame, instant)
84
112
  to_position_NED: Position = to_position.in_frame(ned_frame, instant)
85
113
 
86
- aer: AER = AER.from_position_to_position(from_position_NED, to_position_NED, True)
87
-
88
- return (
89
- float(aer.get_azimuth().in_degrees()),
90
- float(aer.get_elevation().in_degrees()),
91
- float(aer.get_range().in_meters()),
92
- )
114
+ return AER.from_position_to_position(from_position_NED, to_position_NED, True)
93
115
 
94
116
 
95
- def compute_time_lla_aer_state(
117
+ def compute_time_lla_aer_coordinates(
96
118
  state: trajectory.State,
97
119
  from_position: Position,
98
120
  environment: Environment,
99
- ) -> tuple[Instant, float, float, float, float, float, float]:
121
+ ) -> tuple[datetime, float, float, float, float, float, float]:
100
122
  """
101
- Return [instant, latitude, longitude, altitude, azimuth, elevation, range] from State and observer Position.
123
+ Return [datetime, latitude, longitude, altitude, azimuth, elevation, range] from State and observer Position.
124
+
125
+ Args:
126
+ state (trajectory.State): A state.
127
+ from_position (Position): An observer position.
128
+ environment (Environment): An environment.
129
+
130
+ Returns:
131
+ tuple[datetime, float, float, float, float, float, float]: The [datetime, latitude, longitude, altitude, azimuth, elevation, range].
102
132
  """
103
133
 
104
134
  instant: Instant = state.get_instant()
105
135
 
106
- lla: tuple[float, float, float] = lla_from_state(state)
136
+ lla: LLA = lla_from_state(state)
137
+
107
138
  aer: AER = compute_aer(
108
139
  instant,
109
140
  from_position,
@@ -111,44 +142,102 @@ def compute_time_lla_aer_state(
111
142
  environment,
112
143
  )
113
144
 
114
- return (instant, lla[0], lla[1], lla[2], aer[0], aer[1], aer[2])
145
+ return (
146
+ instant.get_date_time(Scale.UTC).replace(tzinfo=timezone.utc),
147
+ float(lla.get_latitude().in_degrees()),
148
+ float(lla.get_longitude().in_degrees()),
149
+ float(lla.get_altitude().in_meters()),
150
+ float(aer.get_azimuth().in_degrees()),
151
+ float(aer.get_elevation().in_degrees()),
152
+ float(aer.get_range().in_meters()),
153
+ )
115
154
 
116
155
 
117
156
  def compute_trajectory_geometry(
118
157
  trajectory: Trajectory,
119
158
  interval: Interval,
120
- ) -> list[tuple[float, float, float]]:
159
+ step: Duration = Duration.minutes(1.0),
160
+ ) -> list[LLA]:
121
161
  """
122
- Return [latitude (degrees), longitude (degrees), altitude (meters)] values along a Trajectory during Interval.
162
+ Return list of LLA along a Trajectory during the Interval at the provided step.
163
+
164
+ Args:
165
+ trajectory (Trajectory): A trajectory.
166
+ interval (Interval): An interval.
167
+ step (Duration): A step. Defaults to 1.0 minutes.
168
+
169
+ Returns:
170
+ list[LLA]: The list of LLA.
123
171
  """
124
172
 
125
173
  return [
126
174
  lla_from_state(state)
127
- for state in trajectory.get_states_at(
128
- interval.generate_grid(Duration.minutes(1.0))
129
- )
175
+ for state in trajectory.get_states_at(interval.generate_grid(step))
130
176
  ]
131
177
 
132
178
 
179
+ def compute_ground_track(
180
+ trajectory: Trajectory,
181
+ interval: Interval,
182
+ step: Duration = Duration.minutes(1.0),
183
+ ) -> list[LLA]:
184
+ """
185
+ Return list of LLA along a Trajectory ground track (altitude set to 10.0 meters) during the Interval at the provided step.
186
+
187
+ Args:
188
+ trajectory (Trajectory): A trajectory.
189
+ interval (Interval): An interval.
190
+ step (Duration): A step. Defaults to 1.0 minutes.
191
+
192
+ Returns:
193
+ list[LLA]: The list of LLA.
194
+ """
195
+
196
+ ground_llas: list[LLA] = []
197
+ for state in trajectory.get_states_at(interval.generate_grid(step)):
198
+ lla: LLA = lla_from_state(state)
199
+
200
+ ground_lla: LLA = LLA(
201
+ lla.get_latitude(),
202
+ lla.get_longitude(),
203
+ Length.meters(10.0),
204
+ )
205
+
206
+ ground_llas.append(ground_lla)
207
+
208
+ return ground_llas
209
+
210
+
133
211
  def convert_state(
134
212
  state: trajectory.State,
135
213
  ) -> tuple[str, float, float, float, float, float, float, float, float, float]:
136
214
  """
137
- Convert an input (Instant, State) into dataframe-ready values.
215
+ Convert a State into dataframe-ready values.
216
+ - Instant (str)
217
+ - Modified Julian Date (float)
218
+ - Position X [meters] (float)
219
+ - Position Y [meters] (float)
220
+ - Position Z [meters] (float)
221
+ - Velocity X [meters/second] (float)
222
+ - Velocity Y [meters/second] (float)
223
+ - Velocity Z [meters/second] (float)
224
+ - Latitude [degrees] (float)
225
+ - Longitude [degrees] (float)
226
+ - Altitude [meters] (float)
227
+
228
+ Args:
229
+ state (trajectory.State): A state.
230
+
231
+ Returns:
232
+ tuple[str, float, float, float, float, float, float, float, float, float]: The dataframe-ready values.
138
233
  """
139
234
 
140
- lla: LLA = LLA.cartesian(
141
- state.get_position()
142
- .in_frame(Frame.ITRF(), state.get_instant())
143
- .get_coordinates(),
144
- EarthGravitationalModel.EGM2008.equatorial_radius,
145
- EarthGravitationalModel.EGM2008.flattening,
146
- )
235
+ lla: LLA = lla_from_state(state)
147
236
 
148
237
  instant: Instant = state.get_instant()
149
238
 
150
239
  return (
151
- repr(instant),
240
+ str(instant.to_string()),
152
241
  float(instant.get_modified_julian_date(Scale.UTC)),
153
242
  *state.get_position().get_coordinates().transpose().tolist(),
154
243
  *state.get_velocity().get_coordinates().transpose().tolist(),