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,337 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ import tempfile
6
+
7
+ from ostk.core.filesystem import Path
8
+ from ostk.core.filesystem import File
9
+
10
+ from ostk.physics.unit import Time
11
+ from ostk.physics.unit import Angle
12
+ from ostk.physics.unit import Derived
13
+ from ostk.physics.time import Instant
14
+ from ostk.physics.time import Scale
15
+ from ostk.physics.time import DateTime
16
+ from ostk.physics.time import Duration
17
+
18
+ from ostk.astrodynamics.trajectory.orbit.model.sgp4 import TLE
19
+
20
+ # Only 8 decimal places of numerical precision for fractional portion of day (=864 us)
21
+ TLE_EPOCH_NUMERICAL_PRECISION: Duration = Duration.days(1.0) * 1e-8
22
+
23
+
24
+ @pytest.fixture
25
+ def tle() -> TLE:
26
+ return TLE(
27
+ satellite_name="Satellite",
28
+ first_line="1 25544U 98067A 18231.17878740 .00000187 00000-0 10196-4 0 9994",
29
+ second_line="2 25544 51.6447 64.7824 0005971 73.1467 36.4366 15.53848234128316",
30
+ )
31
+
32
+
33
+ class TestTLE:
34
+ def test_constructor(self):
35
+ tle = TLE(
36
+ first_line="1 25544U 98067A 18231.17878740 .00000187 00000-0 10196-4 0 9994",
37
+ second_line="2 25544 51.6447 64.7824 0005971 73.1467 36.4366 15.53848234128316",
38
+ )
39
+
40
+ assert isinstance(tle, TLE)
41
+
42
+ def test_constructor_with_satellite_name(self):
43
+ tle = TLE(
44
+ satellite_name="Satellite",
45
+ first_line="1 25544U 98067A 18231.17878740 .00000187 00000-0 10196-4 0 9994",
46
+ second_line="2 25544 51.6447 64.7824 0005971 73.1467 36.4366 15.53848234128316",
47
+ )
48
+
49
+ assert isinstance(tle, TLE)
50
+
51
+ def test_comparators(self, tle: TLE):
52
+ assert (tle == tle) is True
53
+ assert (tle != tle) is False
54
+
55
+ def test_is_defined(self, tle: TLE):
56
+ assert tle.is_defined()
57
+
58
+ def test_get_satellite_name(self, tle: TLE):
59
+ assert tle.get_satellite_name() == "Satellite"
60
+
61
+ def test_get_first_line(self, tle: TLE):
62
+ assert (
63
+ tle.get_first_line()
64
+ == "1 25544U 98067A 18231.17878740 .00000187 00000-0 10196-4 0 9994"
65
+ )
66
+
67
+ def test_get_second_line(self, tle: TLE):
68
+ assert (
69
+ tle.get_second_line()
70
+ == "2 25544 51.6447 64.7824 0005971 73.1467 36.4366 15.53848234128316"
71
+ )
72
+
73
+ def test_get_satellite_number(self, tle: TLE):
74
+ assert tle.get_satellite_number() == 25544
75
+
76
+ def test_get_classification(self, tle: TLE):
77
+ assert tle.get_classification() == "U"
78
+
79
+ def test_get_international_designator(self, tle: TLE):
80
+ assert tle.get_international_designator() == "98067A"
81
+
82
+ def test_get_epoch(self, tle: TLE):
83
+ assert tle.get_epoch() == Instant.date_time(
84
+ DateTime(2018, 8, 19, 4, 17, 27, 231, 360, 0), Scale.UTC
85
+ )
86
+
87
+ def test_get_mean_motion_first_time_derivative_divided_by_two(self, tle: TLE):
88
+ assert (
89
+ tle.get_mean_motion_first_time_derivative_divided_by_two()
90
+ == 1.8700000000000001e-06
91
+ )
92
+
93
+ def test_get_mean_motion_second_time_derivative_divided_by_six(self, tle: TLE):
94
+ assert tle.get_mean_motion_second_time_derivative_divided_by_six() == 0.0
95
+
96
+ def test_get_b_star_drag_term(self, tle: TLE):
97
+ assert tle.get_b_star_drag_term() == 1.0196e-05
98
+
99
+ def test_get_ephemeris_type(self, tle: TLE):
100
+ assert tle.get_ephemeris_type() == 0
101
+
102
+ def test_get_element_set_number(self, tle: TLE):
103
+ assert tle.get_element_set_number() == 999
104
+
105
+ def test_get_first_line_checksum(self, tle: TLE):
106
+ assert tle.get_first_line_checksum() == 4
107
+
108
+ def test_get_inclination(self, tle: TLE):
109
+ assert tle.get_inclination().in_degrees() == 51.6447
110
+
111
+ def test_get_raan(self, tle: TLE):
112
+ assert tle.get_raan().in_degrees() == 64.782399999999996
113
+
114
+ def test_get_eccentricity(self, tle: TLE):
115
+ assert tle.get_eccentricity() == 0.00059710000000000004
116
+
117
+ def test_get_aop(self, tle: TLE):
118
+ assert tle.get_aop().in_degrees() == 73.146699999999996
119
+
120
+ def test_get_mean_anomaly(self, tle: TLE):
121
+ assert tle.get_mean_anomaly().in_degrees() == 36.436599999999999
122
+
123
+ def test_get_mean_motion(self, tle: TLE):
124
+ assert (
125
+ tle.get_mean_motion().in_unit(
126
+ Derived.Unit.angular_velocity(Angle.Unit.Revolution, Time.Unit.Day)
127
+ )
128
+ == 15.53848234
129
+ )
130
+
131
+ def test_get_revolution_number_at_epoch(self, tle: TLE):
132
+ assert tle.get_revolution_number_at_epoch() == 12831
133
+
134
+ def test_get_second_line_checksum(self, tle: TLE):
135
+ assert tle.get_second_line_checksum() == 6
136
+
137
+ def test_set_satellite_number(self, tle: TLE):
138
+ tle.set_satellite_number(99959)
139
+
140
+ assert tle.get_satellite_number() == 99959
141
+
142
+ tle.set_satellite_number(25544)
143
+
144
+ assert tle.get_satellite_number() == 25544
145
+
146
+ def test_set_epoch(self, tle: TLE):
147
+ tle.set_epoch(
148
+ Instant.date_time(DateTime(2019, 9, 20, 5, 18, 28, 232, 361, 0), Scale.UTC)
149
+ )
150
+
151
+ assert tle.get_epoch().is_near(
152
+ Instant.date_time(DateTime(2019, 9, 20, 5, 18, 28, 232, 361, 0), Scale.UTC),
153
+ TLE_EPOCH_NUMERICAL_PRECISION,
154
+ )
155
+
156
+ tle.set_epoch(
157
+ Instant.date_time(DateTime(2018, 8, 19, 4, 17, 27, 231, 360, 0), Scale.UTC)
158
+ )
159
+
160
+ assert tle.get_epoch().is_near(
161
+ Instant.date_time(DateTime(2018, 8, 19, 4, 17, 27, 231, 360, 0), Scale.UTC),
162
+ TLE_EPOCH_NUMERICAL_PRECISION,
163
+ )
164
+
165
+ def test_set_revolution_number_at_epoch(self, tle: TLE):
166
+ tle.set_revolution_number_at_epoch(2345)
167
+
168
+ assert tle.get_revolution_number_at_epoch() == 2345
169
+ assert (
170
+ tle.get_first_line()
171
+ == "1 25544U 98067A 18231.17878740 .00000187 00000-0 10196-4 0 9994"
172
+ )
173
+ assert (
174
+ tle.get_second_line()
175
+ == "2 25544 51.6447 64.7824 0005971 73.1467 36.4366 15.53848234 23455"
176
+ )
177
+
178
+ tle.set_revolution_number_at_epoch(6)
179
+
180
+ assert tle.get_revolution_number_at_epoch() == 6
181
+ assert (
182
+ tle.get_first_line()
183
+ == "1 25544U 98067A 18231.17878740 .00000187 00000-0 10196-4 0 9994"
184
+ )
185
+ assert (
186
+ tle.get_second_line()
187
+ == "2 25544 51.6447 64.7824 0005971 73.1467 36.4366 15.53848234 67"
188
+ )
189
+
190
+ other_tle = TLE(
191
+ "1 99993U 21990ZZZ 21182.62513889 .00000763 00000-0 42347-4 0 99995",
192
+ "2 99993 097.5132 311.4037 0016005 231.4378 006.3908 15.13696975009992",
193
+ )
194
+
195
+ assert other_tle.get_revolution_number_at_epoch() == 999
196
+
197
+ other_tle.set_revolution_number_at_epoch(999)
198
+
199
+ assert other_tle.get_revolution_number_at_epoch() == 999
200
+ assert (
201
+ other_tle.get_first_line()
202
+ == "1 99993U 21990ZZZ 21182.62513889 .00000763 00000-0 42347-4 0 99995"
203
+ )
204
+ assert (
205
+ other_tle.get_second_line()
206
+ == "2 99993 097.5132 311.4037 0016005 231.4378 006.3908 15.13696975 9992"
207
+ )
208
+
209
+ other_tle.set_revolution_number_at_epoch(9909)
210
+
211
+ assert other_tle.get_revolution_number_at_epoch() == 9909
212
+ assert (
213
+ other_tle.get_first_line()
214
+ == "1 99993U 21990ZZZ 21182.62513889 .00000763 00000-0 42347-4 0 99995"
215
+ )
216
+ assert (
217
+ other_tle.get_second_line()
218
+ == "2 99993 097.5132 311.4037 0016005 231.4378 006.3908 15.13696975 99092"
219
+ )
220
+
221
+ other_tle.set_revolution_number_at_epoch(99)
222
+
223
+ assert other_tle.get_revolution_number_at_epoch() == 99
224
+ assert (
225
+ other_tle.get_first_line()
226
+ == "1 99993U 21990ZZZ 21182.62513889 .00000763 00000-0 42347-4 0 99995"
227
+ )
228
+ assert (
229
+ other_tle.get_second_line()
230
+ == "2 99993 097.5132 311.4037 0016005 231.4378 006.3908 15.13696975 993"
231
+ )
232
+
233
+ def test_can_parse(self, tle: TLE):
234
+ assert TLE.can_parse(tle.get_first_line(), tle.get_second_line())
235
+
236
+ def test_parse(self, tle: TLE):
237
+ tle_lines: str = "\n".join(
238
+ [
239
+ str(tle.get_satellite_name()),
240
+ str(tle.get_first_line()),
241
+ str(tle.get_second_line()),
242
+ ]
243
+ )
244
+
245
+ assert TLE.parse(tle_lines) == tle
246
+
247
+ def test_load(self, tle: TLE):
248
+ tle_lines: str = "\n".join(
249
+ [
250
+ str(tle.get_satellite_name()),
251
+ str(tle.get_first_line()),
252
+ str(tle.get_second_line()),
253
+ ]
254
+ )
255
+
256
+ tle_file = tempfile.NamedTemporaryFile(suffix=".tle", delete=False)
257
+ tle_file.write(tle_lines.encode())
258
+ tle_file.close()
259
+
260
+ try:
261
+ assert TLE.load(File.path(Path.parse(tle_file.name))) == tle
262
+
263
+ finally:
264
+ File.path(Path.parse(tle_file.name)).remove()
265
+
266
+ def test_construct_with_satellite_name(self, tle: TLE):
267
+ constructed_tle = TLE.construct(
268
+ satellite_name="Satellite",
269
+ satellite_number=25544,
270
+ classification="U",
271
+ international_designator="98067A",
272
+ epoch=Instant.date_time(
273
+ DateTime(2018, 8, 19, 4, 17, 27, 231, 360, 0), Scale.UTC
274
+ ),
275
+ mean_motion_first_time_derivative_divided_by_two=1.8700000000000001e-06,
276
+ mean_motion_second_time_derivative_divided_by_six=0.0,
277
+ b_star_drag_term=1.0196e-05,
278
+ ephemeris_type=0,
279
+ element_set_number=999,
280
+ inclination=Angle.degrees(51.6447),
281
+ raan=Angle.degrees(64.782399999999996),
282
+ eccentricity=0.00059710000000000004,
283
+ aop=Angle.degrees(73.146699999999996),
284
+ mean_anomaly=Angle.degrees(36.436599999999999),
285
+ mean_motion=Derived(
286
+ 15.53848234,
287
+ Derived.Unit.angular_velocity(Angle.Unit.Revolution, Time.Unit.Day),
288
+ ),
289
+ revolution_number_at_epoch=12831,
290
+ )
291
+
292
+ assert constructed_tle == tle
293
+
294
+ def test_construct_without_satellite_name(self, tle: TLE):
295
+ constructed_tle = TLE.construct(
296
+ satellite_number=25544,
297
+ classification="U",
298
+ international_designator="98067A",
299
+ epoch=Instant.date_time(
300
+ DateTime(2018, 8, 19, 4, 17, 27, 231, 360, 0), Scale.UTC
301
+ ),
302
+ mean_motion_first_time_derivative_divided_by_two=1.8700000000000001e-06,
303
+ mean_motion_second_time_derivative_divided_by_six=0.0,
304
+ b_star_drag_term=1.0196e-05,
305
+ ephemeris_type=0,
306
+ element_set_number=999,
307
+ inclination=Angle.degrees(51.6447),
308
+ raan=Angle.degrees(64.782399999999996),
309
+ eccentricity=0.00059710000000000004,
310
+ aop=Angle.degrees(73.146699999999996),
311
+ mean_anomaly=Angle.degrees(36.436599999999999),
312
+ mean_motion=Derived(
313
+ 15.53848234,
314
+ Derived.Unit.angular_velocity(Angle.Unit.Revolution, Time.Unit.Day),
315
+ ),
316
+ revolution_number_at_epoch=12831,
317
+ )
318
+
319
+ assert constructed_tle.get_first_line() == tle.get_first_line()
320
+ assert constructed_tle.get_second_line() == tle.get_second_line()
321
+
322
+ def test_generate_checksum(self, tle: TLE):
323
+ assert (
324
+ TLE.generate_checksum(tle.get_first_line()) == tle.get_first_line_checksum()
325
+ )
326
+ assert (
327
+ TLE.generate_checksum(tle.get_second_line()) == tle.get_second_line_checksum()
328
+ )
329
+
330
+ assert (
331
+ TLE.generate_checksum(f"{str(tle.get_first_line())[:-1]}0")
332
+ == tle.get_first_line_checksum()
333
+ )
334
+ assert (
335
+ TLE.generate_checksum(f"{str(tle.get_second_line())[:-1]}9")
336
+ == tle.get_second_line_checksum()
337
+ )
@@ -0,0 +1,130 @@
1
+ # Apache License 2.0
2
+
3
+ import ostk.physics as physics
4
+
5
+ import ostk.astrodynamics as astrodynamics
6
+
7
+ Length = physics.unit.Length
8
+ Angle = physics.unit.Angle
9
+ Scale = physics.time.Scale
10
+ Instant = physics.time.Instant
11
+ Interval = physics.time.Interval
12
+ DateTime = physics.time.DateTime
13
+ Position = physics.coordinate.Position
14
+ Velocity = physics.coordinate.Velocity
15
+ Frame = physics.coordinate.Frame
16
+ Environment = physics.Environment
17
+
18
+ Trajectory = astrodynamics.Trajectory
19
+ Model = astrodynamics.trajectory.Model
20
+ Orbit = astrodynamics.trajectory.Orbit
21
+ Pass = astrodynamics.trajectory.orbit.Pass
22
+ Kepler = astrodynamics.trajectory.orbit.model.Kepler
23
+ COE = astrodynamics.trajectory.orbit.model.kepler.COE
24
+ SGP4 = astrodynamics.trajectory.orbit.model.SGP4
25
+ TLE = astrodynamics.trajectory.orbit.model.sgp4.TLE
26
+ State = astrodynamics.trajectory.State
27
+ Access = astrodynamics.Access
28
+
29
+ earth = Environment.default().access_celestial_object_with_name("Earth")
30
+
31
+
32
+ def construct_kepler():
33
+ a = Length.kilometers(7000.0)
34
+ e = 0.1
35
+ i = Angle.degrees(35.0)
36
+ raan = Angle.degrees(40.0)
37
+ aop = Angle.degrees(50.0)
38
+ nu = Angle.degrees(60.0)
39
+
40
+ coe = COE(a, e, i, raan, aop, nu)
41
+
42
+ assert coe is not None
43
+ assert isinstance(coe, COE)
44
+
45
+ epoch = Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC)
46
+
47
+ kepler = Kepler(coe, epoch, earth, Kepler.PerturbationType.No)
48
+
49
+ return kepler
50
+
51
+
52
+ def test_trajectory_orbit_models_kepler_constructors():
53
+ a = Length.kilometers(7000.0)
54
+ e = 0.1
55
+ i = Angle.degrees(35.0)
56
+ raan = Angle.degrees(40.0)
57
+ aop = Angle.degrees(50.0)
58
+ nu = Angle.degrees(60.0)
59
+
60
+ coe = COE(a, e, i, raan, aop, nu)
61
+
62
+ assert coe is not None
63
+ assert isinstance(coe, COE)
64
+
65
+ epoch = Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC)
66
+
67
+ kepler = Kepler(coe, epoch, earth, Kepler.PerturbationType.No)
68
+
69
+ assert kepler is not None
70
+ assert isinstance(kepler, Kepler)
71
+ assert kepler.is_defined()
72
+
73
+
74
+ def test_trajectory_orbit_models_kepler_comparators():
75
+ kepler: Kepler = construct_kepler()
76
+
77
+ assert kepler == kepler
78
+ assert (kepler != kepler) is False
79
+
80
+
81
+ def test_trajectory_orbit_models_kepler_getters():
82
+ kepler: Kepler = construct_kepler()
83
+
84
+ # get_classical_orbital_elements
85
+
86
+ assert kepler.get_classical_orbital_elements() is not None
87
+
88
+ # get_epoch
89
+
90
+ assert kepler.get_epoch() is not None
91
+
92
+ # get_revolution_number_at_epoch()
93
+
94
+ assert kepler.get_revolution_number_at_epoch() is not None
95
+
96
+ # get_gravitational_parameter()
97
+
98
+ assert kepler.get_gravitational_parameter() is not None
99
+
100
+ # get_equatorial_radius()
101
+
102
+ assert kepler.get_equatorial_radius() is not None
103
+
104
+ # get_j2()
105
+
106
+ assert kepler.get_j2() is not None
107
+
108
+ # get_j4()
109
+
110
+ assert kepler.get_j4() is not None
111
+
112
+ # get_perturbation_type()
113
+
114
+ assert kepler.get_perturbation_type() is not None
115
+
116
+
117
+ def test_trajectory_orbit_models_kepler_calculate_state_at_epoch():
118
+ kepler: Kepler = construct_kepler()
119
+
120
+ epoch: Instant = Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC)
121
+
122
+ assert kepler.calculate_state_at(epoch) is not None
123
+
124
+
125
+ def test_trajectory_orbit_models_kepler_calculate_rev_number_at_epoch():
126
+ kepler: Kepler = construct_kepler()
127
+
128
+ epoch: Instant = Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC)
129
+
130
+ assert kepler.calculate_revolution_number_at(epoch) is not None
@@ -0,0 +1,142 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ from ostk.physics.unit import Length, Angle, Derived
6
+ from ostk.physics.coordinate import Position, Velocity, Frame
7
+ from ostk.physics.environment.object.celestial import Earth
8
+
9
+ from ostk.astrodynamics.trajectory.orbit.model import ModifiedEquinoctial
10
+ from ostk.astrodynamics.trajectory.orbit.model.kepler import COE
11
+
12
+
13
+ @pytest.fixture
14
+ def earth_gravitational_parameter() -> Derived:
15
+ return Earth.default().get_gravitational_parameter()
16
+
17
+
18
+ @pytest.fixture
19
+ def gcrf() -> Frame:
20
+ return Frame.GCRF()
21
+
22
+
23
+ @pytest.fixture
24
+ def meoe_default_values():
25
+ return {
26
+ "p": Length.kilometers(7500.0),
27
+ "f": 0.01,
28
+ "g": 0.02,
29
+ "h": 0.03,
30
+ "k": 0.04,
31
+ "L": Angle.degrees(45.0),
32
+ }
33
+
34
+
35
+ @pytest.fixture
36
+ def reference_coe() -> COE:
37
+ sma_ref = Length.kilometers(7000.0)
38
+ ecc_ref = 0.0 # Circular
39
+ inc_ref = Angle.degrees(28.5)
40
+ raan_ref = Angle.degrees(10.0)
41
+ aop_ref = Angle.degrees(0.0) # Typically undefined for circular, set to 0 for COE
42
+ ta_ref = Angle.degrees(45.0) # Argument of latitude
43
+
44
+ return COE(sma_ref, ecc_ref, inc_ref, raan_ref, aop_ref, ta_ref)
45
+
46
+
47
+ @pytest.fixture
48
+ def reference_cartesian_state(
49
+ reference_coe: COE,
50
+ earth_gravitational_parameter: Derived,
51
+ gcrf: Frame,
52
+ ) -> tuple[Position, Velocity]:
53
+ return reference_coe.get_cartesian_state(
54
+ earth_gravitational_parameter,
55
+ gcrf,
56
+ )
57
+
58
+
59
+ @pytest.fixture
60
+ def modified_equinoctial(meoe_default_values: dict) -> ModifiedEquinoctial:
61
+ return ModifiedEquinoctial(
62
+ meoe_default_values["p"],
63
+ meoe_default_values["f"],
64
+ meoe_default_values["g"],
65
+ meoe_default_values["h"],
66
+ meoe_default_values["k"],
67
+ meoe_default_values["L"],
68
+ )
69
+
70
+
71
+ class TestModifiedEquinoctial:
72
+
73
+ def test_constructor_and_getters(
74
+ self,
75
+ modified_equinoctial: ModifiedEquinoctial,
76
+ meoe_default_values: dict,
77
+ ):
78
+ assert modified_equinoctial.is_defined()
79
+ assert modified_equinoctial.get_semi_latus_rectum() == meoe_default_values["p"]
80
+ assert modified_equinoctial.get_eccentricity_x() == meoe_default_values["f"]
81
+ assert modified_equinoctial.get_eccentricity_y() == meoe_default_values["g"]
82
+ assert modified_equinoctial.get_node_x() == meoe_default_values["h"]
83
+ assert modified_equinoctial.get_node_y() == meoe_default_values["k"]
84
+ assert modified_equinoctial.get_true_longitude() == meoe_default_values["L"]
85
+
86
+ def test_undefined_state(self):
87
+ meoe_undefined = ModifiedEquinoctial.undefined()
88
+ assert not meoe_undefined.is_defined()
89
+
90
+ def test_get_si_vector(
91
+ self,
92
+ modified_equinoctial: ModifiedEquinoctial,
93
+ ):
94
+ si_vector = modified_equinoctial.get_si_vector()
95
+ assert len(si_vector) == 6
96
+
97
+ def test_cartesian(
98
+ self,
99
+ reference_cartesian_state: tuple[Position, Velocity],
100
+ earth_gravitational_parameter: Derived,
101
+ ):
102
+ assert (
103
+ ModifiedEquinoctial.cartesian(
104
+ reference_cartesian_state,
105
+ earth_gravitational_parameter,
106
+ )
107
+ is not None
108
+ )
109
+
110
+ def test_get_cartesian_state(
111
+ self,
112
+ modified_equinoctial: ModifiedEquinoctial,
113
+ gcrf: Frame,
114
+ earth_gravitational_parameter: Derived,
115
+ ):
116
+ assert (
117
+ modified_equinoctial.get_cartesian_state(
118
+ earth_gravitational_parameter,
119
+ gcrf,
120
+ )
121
+ is not None
122
+ )
123
+
124
+ def test_coe_method_general_elliptical(self):
125
+ sma = Length.kilometers(24396.137)
126
+ ecc = 0.7308
127
+ inc = Angle.degrees(7.0)
128
+ raan = Angle.degrees(0.0)
129
+ aop = Angle.degrees(90.0)
130
+ ta = Angle.degrees(0.0)
131
+
132
+ coe = COE(sma, ecc, inc, raan, aop, ta)
133
+
134
+ assert ModifiedEquinoctial.coe(coe) is not None
135
+
136
+ def test_to_coe(
137
+ self,
138
+ modified_equinoctial: ModifiedEquinoctial,
139
+ earth_gravitational_parameter: Derived,
140
+ ):
141
+ coe = modified_equinoctial.to_coe(earth_gravitational_parameter)
142
+ assert coe.is_defined()