open-space-toolkit-astrodynamics 5.1.5__py310-none-any.whl → 5.2.0__py310-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. {open_space_toolkit_astrodynamics-5.1.5.dist-info → open_space_toolkit_astrodynamics-5.2.0.dist-info}/METADATA +1 -1
  2. open_space_toolkit_astrodynamics-5.2.0.dist-info/RECORD +96 -0
  3. ostk/__init__.py +1 -0
  4. ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-310-x86_64-linux-gnu.so +0 -0
  5. ostk/astrodynamics/converters.py +44 -6
  6. ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.5 +0 -0
  7. ostk/astrodynamics/pytrajectory/pystate.py +1 -3
  8. ostk/astrodynamics/test/access/__init__.py +1 -0
  9. ostk/astrodynamics/test/access/test_generator.py +248 -0
  10. ostk/astrodynamics/test/conjunction/messages/ccsds/__init__.py +1 -0
  11. ostk/astrodynamics/test/conjunction/messages/ccsds/conftest.py +325 -0
  12. ostk/astrodynamics/test/conjunction/messages/ccsds/data/cdm.json +303 -0
  13. ostk/astrodynamics/test/conjunction/messages/ccsds/test_cdm.py +416 -0
  14. ostk/astrodynamics/test/dynamics/__init__.py +1 -0
  15. ostk/astrodynamics/test/dynamics/test_atmospheric_drag.py +128 -0
  16. ostk/astrodynamics/test/dynamics/test_central_body_gravity.py +58 -0
  17. ostk/astrodynamics/test/dynamics/test_dynamics.py +50 -0
  18. ostk/astrodynamics/test/dynamics/test_position_derivative.py +51 -0
  19. ostk/astrodynamics/test/dynamics/test_third_body_gravity.py +67 -0
  20. ostk/astrodynamics/test/dynamics/test_thruster.py +142 -0
  21. ostk/astrodynamics/test/event_condition/test_angular_condition.py +113 -0
  22. ostk/astrodynamics/test/event_condition/test_boolean_condition.py +55 -0
  23. ostk/astrodynamics/test/event_condition/test_coe_condition.py +87 -0
  24. ostk/astrodynamics/test/event_condition/test_instant_condition.py +48 -0
  25. ostk/astrodynamics/test/event_condition/test_logical_condition.py +120 -0
  26. ostk/astrodynamics/test/event_condition/test_real_condition.py +50 -0
  27. ostk/astrodynamics/test/flight/__init__.py +1 -0
  28. ostk/astrodynamics/test/flight/profile/__init__.py +1 -0
  29. ostk/astrodynamics/test/flight/profile/test_state.py +144 -0
  30. ostk/astrodynamics/test/flight/system/__init__.py +1 -0
  31. ostk/astrodynamics/test/flight/system/test_propulsion_system.py +46 -0
  32. ostk/astrodynamics/test/flight/system/test_satellite_system.py +91 -0
  33. ostk/astrodynamics/test/flight/system/test_satellite_system_builder.py +71 -0
  34. ostk/astrodynamics/test/flight/test_profile.py +153 -0
  35. ostk/astrodynamics/test/flight/test_system.py +55 -0
  36. ostk/astrodynamics/test/guidance_law/test_constant_thrust.py +91 -0
  37. ostk/astrodynamics/test/guidance_law/test_qlaw.py +139 -0
  38. ostk/astrodynamics/test/solvers/__init__.py +1 -0
  39. ostk/astrodynamics/test/solvers/test_finite_difference_solver.py +181 -0
  40. ostk/astrodynamics/test/solvers/test_temporal_condition_solver.py +153 -0
  41. ostk/astrodynamics/test/test_access.py +2 -6
  42. ostk/astrodynamics/test/test_converters.py +213 -6
  43. ostk/astrodynamics/test/test_viewer.py +1 -2
  44. ostk/astrodynamics/test/trajectory/__init__.py +1 -0
  45. ostk/astrodynamics/test/trajectory/orbit/__init__.py +1 -0
  46. ostk/astrodynamics/test/trajectory/orbit/messages/__init__.py +1 -0
  47. ostk/astrodynamics/test/trajectory/orbit/messages/spacex/__init__.py +1 -0
  48. ostk/astrodynamics/test/trajectory/orbit/messages/spacex/conftest.py +18 -0
  49. ostk/astrodynamics/test/trajectory/orbit/messages/spacex/data/opm_1.yaml +44 -0
  50. ostk/astrodynamics/test/trajectory/orbit/messages/spacex/test_opm.py +108 -0
  51. ostk/astrodynamics/test/trajectory/orbit/models/__init__.py +1 -0
  52. ostk/astrodynamics/test/trajectory/orbit/models/kepler/__init__.py +1 -0
  53. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean.py +65 -0
  54. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean_long.py +102 -0
  55. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean_short.py +102 -0
  56. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_coe.py +167 -0
  57. ostk/astrodynamics/test/trajectory/orbit/models/sgp4/__init__.py +1 -0
  58. ostk/astrodynamics/test/trajectory/orbit/models/sgp4/test_tle.py +331 -0
  59. ostk/astrodynamics/test/trajectory/orbit/models/test_kepler.py +130 -0
  60. ostk/astrodynamics/test/trajectory/orbit/models/test_propagated.py +195 -0
  61. ostk/astrodynamics/test/trajectory/orbit/models/test_sgp4.py +1 -0
  62. ostk/astrodynamics/test/trajectory/orbit/models/test_tabulated.py +380 -0
  63. ostk/astrodynamics/test/trajectory/orbit/test_model.py +1 -0
  64. ostk/astrodynamics/test/trajectory/orbit/test_pass.py +55 -0
  65. ostk/astrodynamics/test/trajectory/state/coordinates_subset/test_angular_velocity.py +30 -0
  66. ostk/astrodynamics/test/trajectory/state/coordinates_subset/test_attitude_quaternion.py +18 -0
  67. ostk/astrodynamics/test/trajectory/state/coordinates_subset/test_cartesian_position.py +107 -0
  68. ostk/astrodynamics/test/trajectory/state/coordinates_subset/test_cartesian_velocity.py +115 -0
  69. ostk/astrodynamics/test/trajectory/state/test_coordinates_broker.py +84 -0
  70. ostk/astrodynamics/test/trajectory/state/test_coordinates_subset.py +43 -0
  71. ostk/astrodynamics/test/trajectory/state/test_numerical_solver.py +314 -0
  72. ostk/astrodynamics/test/trajectory/test_local_orbital_frame_direction.py +81 -0
  73. ostk/astrodynamics/test/trajectory/test_local_orbital_frame_factory.py +64 -0
  74. ostk/astrodynamics/test/trajectory/test_model.py +1 -0
  75. ostk/astrodynamics/test/trajectory/test_orbit.py +92 -0
  76. ostk/astrodynamics/test/trajectory/test_propagator.py +402 -0
  77. ostk/astrodynamics/test/trajectory/test_segment.py +288 -0
  78. ostk/astrodynamics/test/trajectory/test_sequence.py +459 -0
  79. ostk/astrodynamics/test/trajectory/test_state.py +223 -0
  80. ostk/astrodynamics/test/trajectory/test_state_builder.py +171 -0
  81. ostk/astrodynamics/viewer.py +1 -3
  82. open_space_toolkit_astrodynamics-5.1.5.dist-info/RECORD +0 -25
  83. {open_space_toolkit_astrodynamics-5.1.5.dist-info → open_space_toolkit_astrodynamics-5.2.0.dist-info}/WHEEL +0 -0
  84. {open_space_toolkit_astrodynamics-5.1.5.dist-info → open_space_toolkit_astrodynamics-5.2.0.dist-info}/top_level.txt +0 -0
  85. {open_space_toolkit_astrodynamics-5.1.5.dist-info → open_space_toolkit_astrodynamics-5.2.0.dist-info}/zip-safe +0 -0
@@ -1,5 +1,7 @@
1
1
  # Apache License 2.0
2
2
 
3
+ import pytest
4
+
3
5
  from datetime import datetime, timedelta, timezone
4
6
 
5
7
  import numpy as np
@@ -17,6 +19,7 @@ from ostk.physics.coordinate import Frame
17
19
 
18
20
  from ostk.astrodynamics.converters import coerce_to_datetime
19
21
  from ostk.astrodynamics.converters import coerce_to_instant
22
+ from ostk.astrodynamics.converters import coerce_to_iso
20
23
  from ostk.astrodynamics.converters import coerce_to_interval
21
24
  from ostk.astrodynamics.converters import coerce_to_duration
22
25
  from ostk.astrodynamics.converters import coerce_to_position
@@ -25,27 +28,231 @@ from ostk.astrodynamics.converters import coerce_to_quaternion
25
28
 
26
29
 
27
30
  def test_coerce_to_datetime_success_instant():
28
- value = Instant.date_time(DateTime(2020, 1, 1), Scale.UTC)
29
- assert coerce_to_datetime(value) == datetime(2020, 1, 1, tzinfo=timezone.utc)
31
+ value = Instant.date_time(DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.UTC)
32
+ assert coerce_to_datetime(value) == datetime(
33
+ 2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone.utc
34
+ )
35
+
36
+ value = Instant.date_time(DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.TAI)
37
+ assert coerce_to_datetime(value) == datetime(
38
+ 2020, 1, 2, 3, 3, 28, 123456, tzinfo=timezone.utc
39
+ )
30
40
 
31
41
 
32
42
  def test_coerce_to_datetime_success_datetime():
33
- value = datetime(2020, 1, 1, tzinfo=timezone.utc)
43
+ value = datetime(2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone.utc)
34
44
  assert coerce_to_datetime(value) == value
35
45
 
46
+ value = datetime(
47
+ 2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone(timedelta(seconds=3600))
48
+ )
49
+ assert coerce_to_datetime(value) == value
50
+
51
+
52
+ def test_coerce_to_datetime_success_iso():
53
+ value = "2020-01-02T03:04:05.123456+00:00"
54
+ assert coerce_to_datetime(value) == datetime(
55
+ 2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone.utc
56
+ )
57
+
58
+ value = "2020-01-02T03:04:05+00:00"
59
+ assert coerce_to_datetime(value) == datetime(2020, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
60
+
61
+ value = "2020-01-02T03:04:05.123456+01:00"
62
+ assert coerce_to_datetime(value) == datetime(
63
+ 2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone(timedelta(seconds=3600))
64
+ )
65
+
66
+ value = "2020-01-02T03:04:05.123456Z"
67
+ assert coerce_to_datetime(value) == datetime(
68
+ 2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone.utc
69
+ )
70
+
71
+ value = "2020-01-02T03:04:05Z"
72
+ assert coerce_to_datetime(value) == datetime(2020, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
73
+
74
+
75
+ def test_coerce_to_datetime_failure():
76
+ with pytest.raises(TypeError):
77
+ coerce_to_datetime(False)
78
+
79
+ with pytest.raises(Exception):
80
+ coerce_to_datetime("some_ill_formed_iso")
81
+
36
82
 
37
83
  def test_coerce_to_instant_success_datetime():
38
- value = datetime(2020, 1, 1, tzinfo=timezone.utc)
84
+ value = datetime(2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone.utc)
85
+ assert coerce_to_instant(value) == Instant.date_time(
86
+ DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.UTC
87
+ )
88
+
89
+ value = datetime(
90
+ 2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone(timedelta(seconds=3600))
91
+ )
39
92
  assert coerce_to_instant(value) == Instant.date_time(
40
- DateTime(2020, 1, 1), Scale.UTC
93
+ DateTime(2020, 1, 2, 2, 4, 5, 123, 456), Scale.UTC
41
94
  )
42
95
 
43
96
 
44
97
  def test_coerce_to_instant_success_instant():
45
- value = Instant.date_time(DateTime(2020, 1, 1), Scale.UTC)
98
+ value = Instant.date_time(DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.UTC)
99
+ assert coerce_to_instant(value) == value
100
+
101
+ value = Instant.date_time(DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.TAI)
46
102
  assert coerce_to_instant(value) == value
47
103
 
48
104
 
105
+ def test_coerce_to_instant_success_iso():
106
+ value = "2020-01-02T03:04:05.123456+00:00"
107
+ assert coerce_to_instant(value) == Instant.date_time(
108
+ DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.UTC
109
+ )
110
+
111
+ value = "2020-01-02T03:04:05+00:00"
112
+ assert coerce_to_instant(value) == Instant.date_time(
113
+ DateTime(2020, 1, 2, 3, 4, 5), Scale.UTC
114
+ )
115
+
116
+ value = "2020-01-02T03:04:05.123456+01:00"
117
+ assert coerce_to_instant(value) == Instant.date_time(
118
+ DateTime(2020, 1, 2, 2, 4, 5, 123, 456), Scale.UTC
119
+ )
120
+
121
+ value = "2020-01-02T03:04:05.123456Z"
122
+ assert coerce_to_instant(value) == Instant.date_time(
123
+ DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.UTC
124
+ )
125
+
126
+ value = "2020-01-02T03:04:05Z"
127
+ assert coerce_to_instant(value) == Instant.date_time(
128
+ DateTime(
129
+ 2020,
130
+ 1,
131
+ 2,
132
+ 3,
133
+ 4,
134
+ 5,
135
+ ),
136
+ Scale.UTC,
137
+ )
138
+
139
+
140
+ def test_coerce_to_instant_failure():
141
+ with pytest.raises(TypeError):
142
+ coerce_to_instant(False)
143
+
144
+ with pytest.raises(Exception):
145
+ coerce_to_instant("some_ill_formed_iso")
146
+
147
+
148
+ def test_coerce_to_iso_success_datetime():
149
+ value = datetime(2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone.utc)
150
+ assert (
151
+ coerce_to_iso(value, timespec="microseconds")
152
+ == "2020-01-02T03:04:05.123456+00:00"
153
+ )
154
+
155
+ value = datetime(
156
+ 2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone(timedelta(seconds=3600))
157
+ )
158
+ assert (
159
+ coerce_to_iso(value, timespec="microseconds")
160
+ == "2020-01-02T03:04:05.123456+01:00"
161
+ )
162
+
163
+ value = datetime(2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone.utc)
164
+ assert (
165
+ coerce_to_iso(value, timespec="milliseconds") == "2020-01-02T03:04:05.123+00:00"
166
+ )
167
+
168
+ value = datetime(2020, 1, 2, 3, 4, 5, 0, tzinfo=timezone.utc)
169
+ assert (
170
+ coerce_to_iso(value, timespec="microseconds")
171
+ == "2020-01-02T03:04:05.000000+00:00"
172
+ )
173
+
174
+
175
+ def test_coerce_to_iso_success_instant():
176
+ value = Instant.date_time(DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.UTC)
177
+ assert (
178
+ coerce_to_iso(value, timespec="microseconds")
179
+ == "2020-01-02T03:04:05.123456+00:00"
180
+ )
181
+
182
+ value = Instant.date_time(DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.TAI)
183
+ assert (
184
+ coerce_to_iso(value, timespec="microseconds")
185
+ == "2020-01-02T03:03:28.123456+00:00"
186
+ )
187
+
188
+ value = Instant.date_time(DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.UTC)
189
+ assert (
190
+ coerce_to_iso(value, timespec="milliseconds") == "2020-01-02T03:04:05.123+00:00"
191
+ )
192
+
193
+ value = Instant.date_time(DateTime(2020, 1, 2, 3, 4, 5, 123), Scale.UTC)
194
+ assert (
195
+ coerce_to_iso(value, timespec="microseconds")
196
+ == "2020-01-02T03:04:05.123000+00:00"
197
+ )
198
+
199
+
200
+ def test_coerce_to_iso_success_iso():
201
+ value = "2020-01-02T03:04:05.123456+00:00"
202
+ assert coerce_to_iso(value, timespec="microseconds") == value
203
+
204
+ value = "2020-01-02T03:04:05.123456+01:00"
205
+ assert coerce_to_iso(value, timespec="microseconds") == value
206
+
207
+ value = "2020-01-02T03:04:05.123456+00:00"
208
+ assert (
209
+ coerce_to_iso(value, timespec="milliseconds") == "2020-01-02T03:04:05.123+00:00"
210
+ )
211
+
212
+ value = "2020-01-02T03:04:05.123+00:00"
213
+ assert (
214
+ coerce_to_iso(value, timespec="microseconds")
215
+ == "2020-01-02T03:04:05.123000+00:00"
216
+ )
217
+
218
+ value = "2020-01-02T03:04:05+00:00"
219
+ assert (
220
+ coerce_to_iso(value, timespec="microseconds")
221
+ == "2020-01-02T03:04:05.000000+00:00"
222
+ )
223
+
224
+ value = "2020-01-02T03:04:05.123456Z"
225
+ assert (
226
+ coerce_to_iso(value, timespec="microseconds")
227
+ == "2020-01-02T03:04:05.123456+00:00"
228
+ )
229
+
230
+ value = "2020-01-02T03:04:05.123456Z"
231
+ assert (
232
+ coerce_to_iso(value, timespec="milliseconds") == "2020-01-02T03:04:05.123+00:00"
233
+ )
234
+
235
+ value = "2020-01-02T03:04:05.123Z"
236
+ assert (
237
+ coerce_to_iso(value, timespec="microseconds")
238
+ == "2020-01-02T03:04:05.123000+00:00"
239
+ )
240
+
241
+ value = "2020-01-02T03:04:05Z"
242
+ assert (
243
+ coerce_to_iso(value, timespec="microseconds")
244
+ == "2020-01-02T03:04:05.000000+00:00"
245
+ )
246
+
247
+
248
+ def test_coerce_to_iso_failure():
249
+ with pytest.raises(TypeError):
250
+ coerce_to_iso(False)
251
+
252
+ with pytest.raises(Exception):
253
+ coerce_to_iso("some_ill_formed_iso")
254
+
255
+
49
256
  def test_coerce_to_interval_success_interval():
50
257
  value = Interval.closed(
51
258
  Instant.date_time(DateTime(2020, 1, 1), Scale.UTC),
@@ -103,8 +103,7 @@ class TestViewer:
103
103
  assert "Cesium.IonResource.fromAssetId(123)" in rendered_html
104
104
  assert "widget.entities.add({polyline:" in rendered_html
105
105
  assert (
106
- "widget.entities.add({position: widget.star_tracker_position"
107
- in rendered_html
106
+ "widget.entities.add({position: widget.star_tracker_position" in rendered_html
108
107
  )
109
108
  assert rendered_html.endswith("</script>")
110
109
 
@@ -0,0 +1 @@
1
+ # Apache License 2.0
@@ -0,0 +1 @@
1
+ # Apache License 2.0
@@ -0,0 +1 @@
1
+ # Apache License 2.0
@@ -0,0 +1 @@
1
+ # Apache License 2.0
@@ -0,0 +1,18 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ import pathlib
6
+
7
+ from ostk.core.filesystem import Path
8
+ from ostk.core.filesystem import File
9
+
10
+
11
+ @pytest.fixture
12
+ def data_directory_path() -> str:
13
+ return f"{pathlib.Path(__file__).parent.absolute()}/data"
14
+
15
+
16
+ @pytest.fixture
17
+ def opm_file(data_directory_path: str) -> File:
18
+ return File.path(Path.parse(f"{data_directory_path}/opm_1.yaml"))
@@ -0,0 +1,44 @@
1
+ # Dummy SpaceX OPM output
2
+
3
+ # Notes:
4
+ # - ECEF velocity is Earth relative
5
+ # - Apogee/Perigee altitude assumes a spherical Earth, 6378.137 km radius
6
+ # - Orbital elements are computed in an inertial frame realized by inertially
7
+ # freezing the WGS84 ECEF frame at time of current state
8
+ # - State is post-deployment, so includes separation delta-velocity
9
+
10
+
11
+ header:
12
+ generation_date: 2020-01-01T12:34:56.789Z
13
+ launch_date: 2020-01-02T12:34:56.789Z
14
+
15
+
16
+ deployments:
17
+
18
+ - name: satellite_a
19
+ sequence_number: 1
20
+ mission_time_s: 3600.0
21
+ date: 2020-01-02T13:34:56.789Z
22
+ r_ecef_m: [693289.644, 6876578.628, -133035.288]
23
+ v_ecef_m_per_s: [1305.783, 39.783, 7525.920]
24
+ mean_perigee_altitude_km: 526.768
25
+ mean_apogee_altitude_km: 568.430
26
+ mean_inclination_deg: 97.123
27
+ mean_argument_of_perigee_deg: -179.513
28
+ mean_longitude_ascending_node_deg: 85.057
29
+ mean_mean_anomaly_deg: 179.263
30
+ ballistic_coef_kg_per_m2: 47.55
31
+
32
+ - name: satellite_b
33
+ sequence_number: 2
34
+ mission_time_s: 7200.0
35
+ date: 2020-01-02T14:34:56.789Z
36
+ r_ecef_m: [699863.059, 6875647.517, -123777.595]
37
+ v_ecef_m_per_s: [1504.658, 6.705, 7538.669]
38
+ mean_perigee_altitude_km: 536.779
39
+ mean_apogee_altitude_km: 529.851
40
+ mean_inclination_deg: 97.124
41
+ mean_argument_of_perigee_deg: 136.875
42
+ mean_longitude_ascending_node_deg: 85.032
43
+ mean_mean_anomaly_deg: -127.164
44
+ ballistic_coef_kg_per_m2: 44.26
@@ -0,0 +1,108 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ from datetime import datetime
6
+
7
+ from ostk.core.containers import Dictionary
8
+ from ostk.core.filesystem import Path
9
+ from ostk.core.filesystem import File
10
+
11
+ from ostk.physics.units import Length
12
+ from ostk.physics.units import Angle
13
+ from ostk.physics.time import Instant
14
+ from ostk.physics.time import Scale
15
+ from ostk.physics.time import Duration
16
+ from ostk.physics.coordinate import Position
17
+ from ostk.physics.coordinate import Velocity
18
+ from ostk.physics.coordinate import Frame
19
+
20
+ from ostk.astrodynamics.trajectory.orbit.messages.spacex import OPM
21
+
22
+
23
+ @pytest.fixture
24
+ def opm() -> OPM:
25
+ return OPM(
26
+ header=OPM.Header(
27
+ generation_date=Instant.date_time(datetime(2020, 1, 2, 3, 4, 5), Scale.UTC),
28
+ launch_date=Instant.date_time(datetime(2020, 1, 3, 3, 4, 5), Scale.UTC),
29
+ ),
30
+ deployments=[
31
+ OPM.Deployment(
32
+ name="A",
33
+ sequence_number=1,
34
+ mission_time=Duration.hours(3600.0),
35
+ date=Instant.date_time(datetime(2020, 1, 4, 3, 4, 5), Scale.UTC),
36
+ position=Position.meters((1.0, 2.0, 3.0), Frame.ITRF()),
37
+ velocity=Velocity.meters_per_second((4.0, 5.0, 6.0), Frame.ITRF()),
38
+ mean_perigee_altitude=Length.kilometers(500.0),
39
+ mean_apogee_altitude=Length.kilometers(500.0),
40
+ mean_inclination=Angle.degrees(1.0),
41
+ mean_argument_of_perigee=Angle.degrees(2.0),
42
+ mean_longitude_ascending_node=Angle.degrees(3.0),
43
+ mean_mean_anomaly=Angle.degrees(4.0),
44
+ ballistic_coefficient=123.456,
45
+ ),
46
+ ],
47
+ )
48
+
49
+
50
+ class TestOPM:
51
+ def test_constructor(self, opm: OPM):
52
+ assert opm is not None
53
+
54
+ def test_get_header(self, opm: OPM):
55
+ assert opm.get_header() is not None
56
+
57
+ def test_get_deployments(self, opm: OPM):
58
+ assert len(opm.get_deployments()) == 1
59
+
60
+ def test_get_deployment_at(self, opm: OPM):
61
+ assert opm.get_deployment_at(index=0).name == "A"
62
+
63
+ def test_get_deployment_with_name(self, opm: OPM):
64
+ assert opm.get_deployment_with_name(name="A").name == "A"
65
+
66
+ def test_undefined(self):
67
+ assert OPM.undefined().is_defined() is False
68
+
69
+ def test_dictionary(self):
70
+ dictionary = Dictionary(
71
+ {
72
+ "header": {
73
+ "generation_date": "2020-01-01T12:34:56.789Z",
74
+ "launch_date": "2020-01-02T12:34:56.789Z",
75
+ },
76
+ "deployments": [
77
+ {
78
+ "name": "satellite_a",
79
+ "sequence_number": 1,
80
+ "mission_time_s": 3600.0,
81
+ "date": "2020-01-02T13:34:56.789Z",
82
+ "r_ecef_m": [693289.644, 6876578.628, -133035.288],
83
+ "v_ecef_m_per_s": [1305.783, 39.783, 7525.920],
84
+ "mean_perigee_altitude_km": 526.768,
85
+ "mean_apogee_altitude_km": 568.430,
86
+ "mean_inclination_deg": 97.123,
87
+ "mean_argument_of_perigee_deg": -179.513,
88
+ "mean_longitude_ascending_node_deg": 85.057,
89
+ "mean_mean_anomaly_deg": 179.263,
90
+ "ballistic_coef_kg_per_m2": 47.55,
91
+ }
92
+ ],
93
+ }
94
+ )
95
+
96
+ assert OPM.dictionary(dictionary) is not None
97
+
98
+ def test_parse(self, opm_file: File):
99
+ with open(str(opm_file.get_path().to_string()), "r") as stream:
100
+ assert OPM.parse(string=stream.read()) is not None
101
+
102
+ def test_load(self, opm_file: File):
103
+ assert OPM.load(file=opm_file) is not None
104
+
105
+
106
+ class TestOPMDeployment:
107
+ def test_to_state(self, opm: OPM):
108
+ assert opm.get_deployment_with_name(name="A").to_state() is not None
@@ -0,0 +1 @@
1
+ # Apache License 2.0
@@ -0,0 +1 @@
1
+ # Apache License 2.0
@@ -0,0 +1,65 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ from ostk.physics.units import Length
6
+ from ostk.physics.units import Angle
7
+
8
+ from ostk.astrodynamics.trajectory.orbit.models import BrouwerLyddaneMean
9
+
10
+
11
+ @pytest.fixture
12
+ def semi_major_axis() -> Length:
13
+ return Length.kilometers(7000.0)
14
+
15
+
16
+ @pytest.fixture
17
+ def eccentricity() -> float:
18
+ return 1e-3
19
+
20
+
21
+ @pytest.fixture
22
+ def inclination() -> Angle:
23
+ return Angle.degrees(35.0)
24
+
25
+
26
+ @pytest.fixture
27
+ def raan() -> Angle:
28
+ return Angle.degrees(40.0)
29
+
30
+
31
+ @pytest.fixture
32
+ def aop() -> Angle:
33
+ return Angle.degrees(50.0)
34
+
35
+
36
+ @pytest.fixture
37
+ def mean_anomaly() -> Angle:
38
+ return Angle.degrees(60.0)
39
+
40
+
41
+ @pytest.fixture
42
+ def brouwer_lyddane_mean(
43
+ semi_major_axis, eccentricity, inclination, raan, aop, mean_anomaly
44
+ ):
45
+ class BrouwerLyddaneMeanMock(BrouwerLyddaneMean):
46
+ def __init__(
47
+ self, semi_major_axis, eccentricity, inclination, raan, aop, mean_anomaly
48
+ ):
49
+ super().__init__(
50
+ semi_major_axis, eccentricity, inclination, raan, aop, mean_anomaly
51
+ )
52
+
53
+ def to_coe():
54
+ return 0.0
55
+
56
+ return BrouwerLyddaneMeanMock(
57
+ semi_major_axis, eccentricity, inclination, raan, aop, mean_anomaly
58
+ )
59
+
60
+
61
+ class TestBrouwerLyddaneMean:
62
+ def test_getters(self, brouwer_lyddane_mean: BrouwerLyddaneMean):
63
+ assert isinstance(brouwer_lyddane_mean.get_mean_anomaly(), Angle)
64
+ assert isinstance(brouwer_lyddane_mean.get_true_anomaly(), Angle)
65
+ assert isinstance(brouwer_lyddane_mean.get_eccentric_anomaly(), Angle)
@@ -0,0 +1,102 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ from ostk.physics.units import Length
6
+ from ostk.physics.units import Angle
7
+ from ostk.physics.environment.gravitational import Earth
8
+
9
+ from ostk.physics.coordinate import Frame
10
+ from ostk.physics.coordinate import Position
11
+ from ostk.physics.coordinate import Velocity
12
+
13
+ from ostk.astrodynamics.trajectory.orbit.models.kepler import COE
14
+ from ostk.astrodynamics.trajectory.orbit.models.brouwerLyddaneMean import (
15
+ BrouwerLyddaneMeanLong,
16
+ )
17
+
18
+
19
+ @pytest.fixture
20
+ def semi_major_axis() -> Length:
21
+ return Length.kilometers(7000.0)
22
+
23
+
24
+ @pytest.fixture
25
+ def eccentricity() -> float:
26
+ return 1e-3
27
+
28
+
29
+ @pytest.fixture
30
+ def inclination() -> Angle:
31
+ return Angle.degrees(35.0)
32
+
33
+
34
+ @pytest.fixture
35
+ def raan() -> Angle:
36
+ return Angle.degrees(40.0)
37
+
38
+
39
+ @pytest.fixture
40
+ def aop() -> Angle:
41
+ return Angle.degrees(50.0)
42
+
43
+
44
+ @pytest.fixture
45
+ def mean_anomaly() -> Angle:
46
+ return Angle.degrees(60.0)
47
+
48
+
49
+ @pytest.fixture
50
+ def coe(
51
+ semi_major_axis: Length,
52
+ eccentricity: float,
53
+ inclination: Angle,
54
+ raan: Angle,
55
+ aop: Angle,
56
+ mean_anomaly: Angle,
57
+ ) -> COE:
58
+ return COE(semi_major_axis, eccentricity, inclination, raan, aop, mean_anomaly)
59
+
60
+
61
+ @pytest.fixture
62
+ def cartesian_state() -> tuple[Position, Velocity]:
63
+ return (
64
+ Position.meters(
65
+ [6596407.223662058, 2281266.582975321, -10540.61521486086], Frame.GCRF()
66
+ ),
67
+ Velocity.meters_per_second(
68
+ [337.7269674273224, -969.7192552349448, 7488.702816619139], Frame.GCRF()
69
+ ),
70
+ )
71
+
72
+
73
+ @pytest.fixture
74
+ def gravitational_parameter():
75
+ return Earth.EGM2008.gravitational_parameter
76
+
77
+
78
+ @pytest.fixture
79
+ def brouwer_lyddane_mean_long(
80
+ semi_major_axis, eccentricity, inclination, raan, aop, mean_anomaly
81
+ ):
82
+ return BrouwerLyddaneMeanLong(
83
+ semi_major_axis, eccentricity, inclination, raan, aop, mean_anomaly
84
+ )
85
+
86
+
87
+ class TestBrouwerLyddaneMeanLong:
88
+ def test_to_coe(self, brouwer_lyddane_mean_long: BrouwerLyddaneMeanLong):
89
+ assert brouwer_lyddane_mean_long.to_coe().is_defined()
90
+
91
+ def test_coe(self, coe: COE):
92
+ assert BrouwerLyddaneMeanLong.COE(coe).is_defined()
93
+
94
+ def test_cartesian(
95
+ self, cartesian_state: tuple[Position, Velocity], gravitational_parameter
96
+ ):
97
+ assert BrouwerLyddaneMeanLong.cartesian(
98
+ cartesian_state, gravitational_parameter
99
+ ).is_defined()
100
+
101
+ def test_undefined(self):
102
+ assert BrouwerLyddaneMeanLong.undefined().is_defined() is False