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,416 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ from datetime import datetime
6
+
7
+ from ostk.core.container import Dictionary
8
+ from ostk.core.filesystem import File
9
+
10
+ from ostk.physics.unit import Length
11
+ from ostk.physics.unit import Mass
12
+ from ostk.physics.time import Instant
13
+ from ostk.physics.time import Scale
14
+ from ostk.physics.time import Duration
15
+ from ostk.physics.coordinate import Frame
16
+ from ostk.physics.coordinate import Position
17
+ from ostk.physics.coordinate import Velocity
18
+
19
+ from ostk.astrodynamics.trajectory import State
20
+ from ostk.astrodynamics.conjunction.message.ccsds import CDM
21
+
22
+
23
+ @pytest.fixture
24
+ def cdm() -> CDM:
25
+ return CDM(
26
+ header=CDM.Header(
27
+ ccsds_cdm_version="1.0",
28
+ creation_date=Instant.date_time(datetime(2010, 3, 12, 22, 31, 12), Scale.UTC),
29
+ originator="JSPOC",
30
+ message_for="SATELLITE A",
31
+ message_id="201113719185",
32
+ ),
33
+ relative_metadata=CDM.RelativeMetadata(
34
+ comment="",
35
+ time_of_closest_approach=Instant.date_time(
36
+ datetime(2010, 3, 13, 22, 37, 52, 618), Scale.UTC
37
+ ),
38
+ miss_distance=Length.meters(715.0),
39
+ start_screen_period=Instant.date_time(
40
+ datetime(2010, 3, 12, 18, 29, 32, 212), Scale.UTC
41
+ ),
42
+ end_screen_period=Instant.date_time(
43
+ datetime(2010, 3, 15, 18, 29, 32, 212), Scale.UTC
44
+ ),
45
+ screen_volume_frame="RTN",
46
+ screen_volume_shape="ELLIPSOID",
47
+ screen_volume_x=200.0,
48
+ screen_volume_y=1000.0,
49
+ screen_volume_z=1000.0,
50
+ screen_entry_time=Instant.date_time(
51
+ datetime(2010, 3, 13, 22, 37, 52, 222), Scale.UTC
52
+ ),
53
+ screen_exit_time=Instant.date_time(
54
+ datetime(2010, 3, 13, 22, 37, 52, 824), Scale.UTC
55
+ ),
56
+ collision_probability=0.0000435,
57
+ collision_probability_method="FOSTER-1992",
58
+ ),
59
+ objects_metadata_array=[
60
+ CDM.Metadata(
61
+ comment="",
62
+ object="OBJECT1",
63
+ object_designator=12345,
64
+ catalog_name="SATCAT",
65
+ object_name="SATELLITE A",
66
+ international_designator="1997−030E",
67
+ object_type=CDM.ObjectType.Payload,
68
+ operator_contact_position="OSA",
69
+ operator_organization="EUTMETSAT",
70
+ operator_phone="+49615130312",
71
+ operator_email="JOHN.DOE@SOMEWHERE.NET",
72
+ ephemeris_name="EPHEMERIS SATELLITE A",
73
+ covariance_method="CALCULATED",
74
+ maneuverable="YES",
75
+ orbit_center="",
76
+ reference_frame="EME2000",
77
+ gravity_model="EGM-96: 36D 36O",
78
+ atmospheric_model="JACCHIA 70 DCA",
79
+ n_body_perturbations="MOON, SUN",
80
+ solar_radiation_pressure=False,
81
+ earth_tides=False,
82
+ in_track_thrust=False,
83
+ ),
84
+ CDM.Metadata(
85
+ object="OBJECT2",
86
+ object_designator=12346,
87
+ catalog_name="SATCAT",
88
+ object_name="SATELLITE B",
89
+ international_designator="1997−030F",
90
+ object_type=CDM.ObjectType.Payload,
91
+ ephemeris_name="EPHEMERIS SATELLITE B",
92
+ covariance_method="CALCULATED",
93
+ maneuverable="YES",
94
+ reference_frame="EME2000",
95
+ ),
96
+ ],
97
+ objects_data_array=[
98
+ CDM.Data(
99
+ time_last_observation_start=Instant.date_time(
100
+ datetime(2010, 3, 12, 2, 14, 12, 746), Scale.UTC
101
+ ),
102
+ time_last_observation_end=Instant.date_time(
103
+ datetime(2010, 3, 12, 2, 14, 12, 746), Scale.UTC
104
+ ),
105
+ recommended_od_span=Duration.days(7.88),
106
+ actual_od_span=Duration.days(5.50),
107
+ observations_available=592,
108
+ observations_used=579,
109
+ tracks_available=123,
110
+ tracks_used=119,
111
+ residuals_accepted=97.8,
112
+ weighted_rms=0.864,
113
+ area_pc=5.2,
114
+ area_drag=0.0,
115
+ area_srp=0.0,
116
+ mass=Mass.kilograms(251.6),
117
+ cd_area_over_mass=0.0,
118
+ cr_area_over_mass=0.0,
119
+ thrust_acceleration=0.0,
120
+ sedr=0.0,
121
+ ),
122
+ CDM.Data(
123
+ time_last_observation_start=Instant.date_time(
124
+ datetime(2010, 3, 12, 2, 14, 12, 746), Scale.UTC
125
+ ),
126
+ time_last_observation_end=Instant.date_time(
127
+ datetime(2010, 3, 12, 2, 14, 12, 746), Scale.UTC
128
+ ),
129
+ recommended_od_span=Duration.days(7.88),
130
+ actual_od_span=Duration.days(5.50),
131
+ observations_available=592,
132
+ observations_used=579,
133
+ tracks_available=123,
134
+ tracks_used=119,
135
+ residuals_accepted=97.8,
136
+ weighted_rms=0.864,
137
+ area_pc=5.2,
138
+ area_drag=0.0,
139
+ area_srp=0.0,
140
+ mass=Mass.kilograms(251.6),
141
+ cd_area_over_mass=0.0,
142
+ cr_area_over_mass=0.0,
143
+ thrust_acceleration=0.0,
144
+ sedr=0.0,
145
+ ),
146
+ ],
147
+ )
148
+
149
+
150
+ class TestCDM:
151
+ def test_constructor(self, cdm: CDM):
152
+ assert cdm is not None
153
+
154
+ def test_get_header(self, cdm: CDM):
155
+ cdm_header: CDM.Header = cdm.get_header()
156
+
157
+ assert cdm_header is not None
158
+ assert cdm_header.ccsds_cdm_version == "1.0"
159
+ assert cdm_header.creation_date == Instant.date_time(
160
+ datetime(2010, 3, 12, 22, 31, 12), Scale.UTC
161
+ )
162
+ assert cdm_header.originator == "JSPOC"
163
+ assert cdm_header.message_for == "SATELLITE A"
164
+ assert cdm_header.message_id == "201113719185"
165
+
166
+ def test_get_relative_metadata(self, cdm: CDM):
167
+ cdm_relative_metadata: CDM.RelativeMetadata = cdm.get_relative_metadata()
168
+
169
+ assert cdm_relative_metadata is not None
170
+ assert cdm_relative_metadata.comment == ""
171
+ assert cdm_relative_metadata.time_of_closest_approach == Instant.date_time(
172
+ datetime(2010, 3, 13, 22, 37, 52, 618), Scale.UTC
173
+ )
174
+ assert cdm_relative_metadata.miss_distance == Length.meters(715.0)
175
+ assert cdm_relative_metadata.start_screen_period == Instant.date_time(
176
+ datetime(2010, 3, 12, 18, 29, 32, 212), Scale.UTC
177
+ )
178
+ assert cdm_relative_metadata.end_screen_period == Instant.date_time(
179
+ datetime(2010, 3, 15, 18, 29, 32, 212), Scale.UTC
180
+ )
181
+ assert cdm_relative_metadata.screen_volume_frame == "RTN"
182
+ assert cdm_relative_metadata.screen_volume_shape == "ELLIPSOID"
183
+ assert cdm_relative_metadata.screen_volume_x == 200.0
184
+ assert cdm_relative_metadata.screen_volume_y == 1000.0
185
+ assert cdm_relative_metadata.screen_volume_z == 1000.0
186
+ assert cdm_relative_metadata.screen_entry_time == Instant.date_time(
187
+ datetime(2010, 3, 13, 22, 37, 52, 222), Scale.UTC
188
+ )
189
+ assert cdm_relative_metadata.screen_exit_time == Instant.date_time(
190
+ datetime(2010, 3, 13, 22, 37, 52, 824), Scale.UTC
191
+ )
192
+ assert cdm_relative_metadata.collision_probability == 0.0000435
193
+ assert cdm_relative_metadata.collision_probability_method == "FOSTER-1992"
194
+
195
+ def test_get_metadata_array(self, cdm: CDM):
196
+ assert cdm.get_metadata_array() is not None
197
+ assert len(cdm.get_metadata_array()) == 2
198
+
199
+ def test_get_data_array(self, cdm: CDM):
200
+ assert cdm.get_data_array() is not None
201
+ assert len(cdm.get_data_array()) == 2
202
+
203
+ def test_get_object_metadata_at(self, cdm: CDM):
204
+ assert cdm.get_object_metadata_at(0) is not None
205
+ assert cdm.get_object_metadata_at(1) is not None
206
+
207
+ cdm_object_1_metadata: CDM.Metadata = cdm.get_object_metadata_at(0)
208
+
209
+ assert cdm_object_1_metadata.comment == ""
210
+ assert cdm_object_1_metadata.object == "OBJECT1"
211
+ assert cdm_object_1_metadata.object_designator == 12345
212
+ assert cdm_object_1_metadata.catalog_name == "SATCAT"
213
+ assert cdm_object_1_metadata.object_name == "SATELLITE A"
214
+ assert cdm_object_1_metadata.international_designator == "1997−030E"
215
+ assert cdm_object_1_metadata.object_type == CDM.ObjectType.Payload
216
+ assert cdm_object_1_metadata.operator_contact_position == "OSA"
217
+ assert cdm_object_1_metadata.operator_organization == "EUTMETSAT"
218
+ assert cdm_object_1_metadata.operator_phone == "+49615130312"
219
+ assert cdm_object_1_metadata.operator_email == "JOHN.DOE@SOMEWHERE.NET"
220
+ assert cdm_object_1_metadata.ephemeris_name == "EPHEMERIS SATELLITE A"
221
+ assert cdm_object_1_metadata.covariance_method == "CALCULATED"
222
+ assert cdm_object_1_metadata.maneuverable == "YES"
223
+ assert cdm_object_1_metadata.orbit_center == ""
224
+ assert cdm_object_1_metadata.reference_frame == "EME2000"
225
+ assert cdm_object_1_metadata.gravity_model == "EGM-96: 36D 36O"
226
+ assert cdm_object_1_metadata.atmospheric_model == "JACCHIA 70 DCA"
227
+ assert cdm_object_1_metadata.n_body_perturbations == "MOON, SUN"
228
+ assert cdm_object_1_metadata.solar_radiation_pressure == False
229
+ assert cdm_object_1_metadata.earth_tides == False
230
+ assert cdm_object_1_metadata.in_track_thrust == False
231
+
232
+ cdm_object_2_metadata: CDM.Metadata = cdm.get_object_metadata_at(1)
233
+
234
+ assert cdm_object_2_metadata.comment == ""
235
+ assert cdm_object_2_metadata.object == "OBJECT2"
236
+ assert cdm_object_2_metadata.object_designator == 12346
237
+ assert cdm_object_2_metadata.catalog_name == "SATCAT"
238
+ assert cdm_object_2_metadata.object_name == "SATELLITE B"
239
+ assert cdm_object_2_metadata.international_designator == "1997−030F"
240
+ assert cdm_object_2_metadata.object_type == CDM.ObjectType.Payload
241
+ assert cdm_object_2_metadata.operator_contact_position == ""
242
+ assert cdm_object_2_metadata.operator_organization == ""
243
+ assert cdm_object_2_metadata.operator_phone == ""
244
+ assert cdm_object_2_metadata.operator_email == ""
245
+ assert cdm_object_2_metadata.ephemeris_name == "EPHEMERIS SATELLITE B"
246
+ assert cdm_object_2_metadata.covariance_method == "CALCULATED"
247
+ assert cdm_object_2_metadata.maneuverable == "YES"
248
+ assert cdm_object_2_metadata.orbit_center == ""
249
+ assert cdm_object_2_metadata.reference_frame == "EME2000"
250
+ assert cdm_object_2_metadata.gravity_model == ""
251
+ assert cdm_object_2_metadata.atmospheric_model == ""
252
+ assert cdm_object_2_metadata.n_body_perturbations == ""
253
+ assert cdm_object_2_metadata.solar_radiation_pressure == False
254
+ assert cdm_object_2_metadata.earth_tides == False
255
+ assert cdm_object_2_metadata.in_track_thrust == False
256
+
257
+ with pytest.raises(Exception) as e:
258
+ cdm.get_object_metadata_at(2)
259
+
260
+ def test_get_object_data_at(self, cdm: CDM):
261
+ assert cdm.get_object_data_at(0) is not None
262
+ assert cdm.get_object_data_at(1) is not None
263
+
264
+ cdm_object_1_data: CDM.Data = cdm.get_object_data_at(0)
265
+
266
+ assert cdm_object_1_data.time_last_observation_start == Instant.date_time(
267
+ datetime(2010, 3, 12, 2, 14, 12, 746), Scale.UTC
268
+ )
269
+ assert cdm_object_1_data.time_last_observation_end == Instant.date_time(
270
+ datetime(2010, 3, 12, 2, 14, 12, 746), Scale.UTC
271
+ )
272
+ assert cdm_object_1_data.recommended_od_span == Duration.days(7.88)
273
+ assert cdm_object_1_data.actual_od_span == Duration.days(5.50)
274
+ assert cdm_object_1_data.observations_available == 592
275
+ assert cdm_object_1_data.observations_used == 579
276
+ assert cdm_object_1_data.tracks_available == 123
277
+ assert cdm_object_1_data.tracks_used == 119
278
+ assert cdm_object_1_data.residuals_accepted == 97.8
279
+ assert cdm_object_1_data.weighted_rms == 0.864
280
+ assert cdm_object_1_data.area_pc == 5.2
281
+ assert cdm_object_1_data.area_drag == 0.0
282
+ assert cdm_object_1_data.area_srp == 0.0
283
+ assert cdm_object_1_data.mass == Mass.kilograms(251.6)
284
+ assert cdm_object_1_data.cd_area_over_mass == 0.0
285
+ assert cdm_object_1_data.cr_area_over_mass == 0.0
286
+ assert cdm_object_1_data.thrust_acceleration == 0.0
287
+ assert cdm_object_1_data.sedr == 0.0
288
+
289
+ cdm_object_2_data: CDM.Data = cdm.get_object_data_at(1)
290
+
291
+ assert cdm_object_2_data.time_last_observation_start == Instant.date_time(
292
+ datetime(2010, 3, 12, 2, 14, 12, 746), Scale.UTC
293
+ )
294
+ assert cdm_object_2_data.time_last_observation_end == Instant.date_time(
295
+ datetime(2010, 3, 12, 2, 14, 12, 746), Scale.UTC
296
+ )
297
+ assert cdm_object_2_data.recommended_od_span == Duration.days(7.88)
298
+ assert cdm_object_2_data.actual_od_span == Duration.days(5.50)
299
+ assert cdm_object_2_data.observations_available == 592
300
+ assert cdm_object_2_data.observations_used == 579
301
+ assert cdm_object_2_data.tracks_available == 123
302
+ assert cdm_object_2_data.tracks_used == 119
303
+ assert cdm_object_2_data.residuals_accepted == 97.8
304
+ assert cdm_object_2_data.weighted_rms == 0.864
305
+ assert cdm_object_2_data.area_pc == 5.2
306
+ assert cdm_object_2_data.area_drag == 0.0
307
+ assert cdm_object_2_data.area_srp == 0.0
308
+ assert cdm_object_2_data.mass == Mass.kilograms(251.6)
309
+ assert cdm_object_2_data.cd_area_over_mass == 0.0
310
+ assert cdm_object_2_data.cr_area_over_mass == 0.0
311
+ assert cdm_object_2_data.thrust_acceleration == 0.0
312
+ assert cdm_object_2_data.sedr == 0.0
313
+
314
+ with pytest.raises(Exception) as e:
315
+ cdm.get_object_data_at(2)
316
+
317
+ def test_get_ccsds_cdm_version(self, cdm: CDM):
318
+ assert cdm.get_ccsds_cdm_version() == "1.0"
319
+
320
+ def test_get_creation_instant(self, cdm: CDM):
321
+ assert cdm.get_creation_instant() == Instant.date_time(
322
+ datetime(2010, 3, 12, 22, 31, 12), Scale.UTC
323
+ )
324
+
325
+ def test_get_originator(self, cdm: CDM):
326
+ assert cdm.get_originator() == "JSPOC"
327
+
328
+ def test_get_message_for(self, cdm: CDM):
329
+ assert cdm.get_message_for() == "SATELLITE A"
330
+
331
+ def test_get_message_id(self, cdm: CDM):
332
+ assert cdm.get_message_id() == "201113719185"
333
+
334
+ def test_get_time_of_closest_approach(self, cdm: CDM):
335
+ assert cdm.get_time_of_closest_approach() == Instant.date_time(
336
+ datetime(2010, 3, 13, 22, 37, 52, 618), Scale.UTC
337
+ )
338
+
339
+ def test_get_miss_distance(self, cdm: CDM):
340
+ assert cdm.get_miss_distance() == Length.meters(715.0)
341
+
342
+ def test_get_relative_position(self, cdm: CDM):
343
+ assert cdm.get_relative_position().is_defined() is False
344
+
345
+ def test_get_relative_velocity(self, cdm: CDM):
346
+ assert cdm.get_relative_velocity().is_defined() is False
347
+
348
+ def test_get_collision_probability(self, cdm: CDM):
349
+ assert cdm.get_collision_probability() == 0.0000435
350
+
351
+ def test_get_collision_probability_method(self, cdm: CDM):
352
+ assert cdm.get_collision_probability_method() == "FOSTER-1992"
353
+
354
+ def test_undefined(self):
355
+ assert CDM.undefined().is_defined() is False
356
+
357
+ def test_dictionary(self, cdm_spacetrack_dictionary: dict):
358
+ dictionary = Dictionary(cdm_spacetrack_dictionary)
359
+
360
+ cdm: CDM = CDM.dictionary(dictionary)
361
+
362
+ assert cdm is not None
363
+ assert cdm.get_header() is not None
364
+ assert cdm.get_ccsds_cdm_version() == "1.0"
365
+ assert cdm.get_creation_instant() == Instant.date_time(
366
+ datetime(2022, 12, 25, 0, 33, 16), Scale.UTC
367
+ )
368
+ assert cdm.get_originator() == "CSpOC"
369
+ assert cdm.get_message_for() == "YAM-2"
370
+ assert cdm.get_message_id() == "406320986"
371
+ assert cdm.get_time_of_closest_approach() == Instant.date_time(
372
+ datetime(2022, 12, 27, 13, 28, 59, 516000), Scale.UTC
373
+ )
374
+ assert cdm.get_miss_distance() == Length.meters(974.0)
375
+ assert cdm.get_relative_position().is_defined() is False
376
+ assert cdm.get_relative_velocity().is_defined() is False
377
+ assert cdm.get_collision_probability() == 5.162516e-16
378
+ assert cdm.get_collision_probability_method() == "FOSTER-1992"
379
+
380
+ object_1_metadata: CDM.Metadata = cdm.get_object_metadata_at(0)
381
+
382
+ assert object_1_metadata.object == "OBJECT1"
383
+ assert object_1_metadata.object_designator == 48911
384
+ assert object_1_metadata.catalog_name == "SATCAT"
385
+ assert object_1_metadata.object_name == "YAM-2"
386
+ assert object_1_metadata.international_designator == "2021-059AJ"
387
+ assert object_1_metadata.object_type == CDM.ObjectType.Payload
388
+ assert object_1_metadata.ephemeris_name == "NONE"
389
+ assert object_1_metadata.covariance_method == "CALCULATED"
390
+ assert object_1_metadata.maneuverable == "N/A"
391
+ assert object_1_metadata.reference_frame == "ITRF"
392
+
393
+ # object_1_data: CDM.Data = cdm.get_object_data_at(0)
394
+
395
+ # assert object_1_data.state == State(
396
+ # Instant.date_time(datetime(2022, 12, 27, 13, 28, 59, 516000), Scale.UTC),
397
+ # Position.meters([-4988150.231999999844, -1691825.955000000075, -4469421.481999999844], Frame.ITRF()),
398
+ # Velocity.meters_per_second([-5122.248844000000, 54.300816000000, 5699.434412000000], Frame.ITRF())
399
+ # )
400
+
401
+ def test_parse(self, cdm_file: File):
402
+ with open(str(cdm_file.get_path().to_string()), "r") as stream:
403
+ assert CDM.parse(string=stream.read()) is not None
404
+
405
+ def test_load(self, cdm_file: File):
406
+ assert CDM.load(file=cdm_file) is not None
407
+
408
+ def test_object_type_from_string(self):
409
+ assert CDM.object_type_from_string("PAYLOAD") == CDM.ObjectType.Payload
410
+ assert CDM.object_type_from_string("ROCKET BODY") == CDM.ObjectType.RocketBody
411
+ assert CDM.object_type_from_string("DEBRIS") == CDM.ObjectType.Debris
412
+ assert CDM.object_type_from_string("UNKNOWN") == CDM.ObjectType.Unknown
413
+ assert CDM.object_type_from_string("OTHER") == CDM.ObjectType.Other
414
+
415
+ with pytest.raises(Exception) as e:
416
+ CDM.object_type_from_string("ANOTHERSUPPORTEDTYPE")
@@ -0,0 +1,244 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ from ostk.physics.unit import Length
6
+ from ostk.physics.unit import Angle
7
+ from ostk.physics.time import DateTime
8
+ from ostk.physics.time import Scale
9
+ from ostk.physics.time import Instant
10
+ from ostk.physics.coordinate import Frame
11
+ from ostk.physics import Environment
12
+ from ostk.physics.environment.object import Celestial
13
+
14
+ from ostk.astrodynamics.trajectory import Orbit
15
+ from ostk.astrodynamics.trajectory import State
16
+ from ostk.astrodynamics.trajectory import LocalOrbitalFrameFactory
17
+ from ostk.astrodynamics.trajectory.orbit.model import Kepler
18
+ from ostk.astrodynamics.trajectory.orbit.model.kepler import COE
19
+ from ostk.astrodynamics.conjunction import CloseApproach
20
+
21
+
22
+ @pytest.fixture
23
+ def environment() -> Environment:
24
+ return Environment.default()
25
+
26
+
27
+ @pytest.fixture
28
+ def earth(environment: Environment) -> Celestial:
29
+ return environment.access_celestial_object_with_name("Earth")
30
+
31
+
32
+ @pytest.fixture
33
+ def instant() -> Instant:
34
+ return Instant.date_time(DateTime(2024, 1, 1, 0, 0, 0), Scale.UTC)
35
+
36
+
37
+ @pytest.fixture
38
+ def gcrf_frame() -> Frame:
39
+ return Frame.GCRF()
40
+
41
+
42
+ @pytest.fixture
43
+ def object_1_state(
44
+ instant: Instant,
45
+ earth: Celestial,
46
+ ) -> State:
47
+ orbit = Orbit(
48
+ model=Kepler(
49
+ coe=COE(
50
+ semi_major_axis=Length.kilometers(7000.0),
51
+ eccentricity=0.0,
52
+ inclination=Angle.degrees(0.0),
53
+ raan=Angle.degrees(0.0),
54
+ aop=Angle.degrees(0.0),
55
+ true_anomaly=Angle.degrees(0.0),
56
+ ),
57
+ epoch=instant,
58
+ celestial_object=earth,
59
+ perturbation_type=Kepler.PerturbationType.No,
60
+ ),
61
+ celestial_object=earth,
62
+ )
63
+ return orbit.get_state_at(instant)
64
+
65
+
66
+ @pytest.fixture
67
+ def object_2_state(
68
+ instant: Instant,
69
+ earth: Celestial,
70
+ ) -> State:
71
+ orbit = Orbit(
72
+ model=Kepler(
73
+ coe=COE(
74
+ semi_major_axis=Length.kilometers(7000.0),
75
+ eccentricity=0.0,
76
+ inclination=Angle.degrees(90.0),
77
+ raan=Angle.degrees(0.0),
78
+ aop=Angle.degrees(0.0),
79
+ true_anomaly=Angle.degrees(1.0),
80
+ ),
81
+ epoch=instant,
82
+ celestial_object=earth,
83
+ perturbation_type=Kepler.PerturbationType.No,
84
+ ),
85
+ celestial_object=earth,
86
+ )
87
+ return orbit.get_state_at(instant)
88
+
89
+
90
+ @pytest.fixture
91
+ def close_approach(
92
+ object_1_state: State,
93
+ object_2_state: State,
94
+ ) -> CloseApproach:
95
+ return CloseApproach(
96
+ object_1_state=object_1_state,
97
+ object_2_state=object_2_state,
98
+ )
99
+
100
+
101
+ class TestCloseApproach:
102
+ def test_constructor_success(
103
+ self,
104
+ object_1_state: State,
105
+ object_2_state: State,
106
+ ):
107
+ close_approach = CloseApproach(
108
+ object_1_state=object_1_state,
109
+ object_2_state=object_2_state,
110
+ )
111
+
112
+ assert close_approach is not None
113
+ assert isinstance(close_approach, CloseApproach)
114
+
115
+ def test_is_defined_success(
116
+ self,
117
+ close_approach: CloseApproach,
118
+ ):
119
+ assert close_approach.is_defined() is True
120
+
121
+ def test_undefined_success(self):
122
+ close_approach = CloseApproach.undefined()
123
+
124
+ assert close_approach is not None
125
+ assert isinstance(close_approach, CloseApproach)
126
+ assert close_approach.is_defined() is False
127
+
128
+ def test_get_object_1_state_success(
129
+ self,
130
+ close_approach: CloseApproach,
131
+ object_1_state: State,
132
+ ):
133
+ state = close_approach.get_object_1_state()
134
+
135
+ assert state is not None
136
+ assert isinstance(state, State)
137
+ assert state.get_instant() == object_1_state.get_instant()
138
+
139
+ def test_get_object_2_state_success(
140
+ self,
141
+ close_approach: CloseApproach,
142
+ object_2_state: State,
143
+ ):
144
+ state = close_approach.get_object_2_state()
145
+
146
+ assert state is not None
147
+ assert isinstance(state, State)
148
+ assert state.get_instant() == object_2_state.get_instant()
149
+
150
+ def test_get_instant_success(
151
+ self,
152
+ close_approach: CloseApproach,
153
+ instant: Instant,
154
+ ):
155
+ ca_instant = close_approach.get_instant()
156
+
157
+ assert ca_instant is not None
158
+ assert isinstance(ca_instant, Instant)
159
+ assert ca_instant == instant
160
+
161
+ def test_get_miss_distance_success(
162
+ self,
163
+ close_approach: CloseApproach,
164
+ ):
165
+ miss_distance = close_approach.get_miss_distance()
166
+
167
+ assert miss_distance is not None
168
+ assert isinstance(miss_distance, Length)
169
+ assert miss_distance.in_meters() > 0.0
170
+
171
+ def test_get_relative_state_success(
172
+ self,
173
+ close_approach: CloseApproach,
174
+ ):
175
+ relative_state = close_approach.get_relative_state()
176
+
177
+ assert relative_state is not None
178
+ assert isinstance(relative_state, State)
179
+
180
+ def test_compute_miss_distance_components_in_frame_success(
181
+ self,
182
+ close_approach: CloseApproach,
183
+ gcrf_frame: Frame,
184
+ ):
185
+ components = close_approach.compute_miss_distance_components_in_frame(
186
+ frame=gcrf_frame
187
+ )
188
+
189
+ assert components is not None
190
+ assert isinstance(components, tuple)
191
+ assert len(components) == 3
192
+
193
+ # Check each component is a Length
194
+ for component in components:
195
+ assert isinstance(component, Length)
196
+
197
+ def test_compute_miss_distance_components_in_local_orbital_frame_success(
198
+ self,
199
+ close_approach: CloseApproach,
200
+ gcrf_frame: Frame,
201
+ ):
202
+ qsw_factory = LocalOrbitalFrameFactory.QSW(gcrf_frame)
203
+
204
+ components = (
205
+ close_approach.compute_miss_distance_components_in_local_orbital_frame(
206
+ local_orbital_frame_factory=qsw_factory
207
+ )
208
+ )
209
+
210
+ assert components is not None
211
+ assert isinstance(components, tuple)
212
+ assert len(components) == 3
213
+
214
+ # Check each component is a Length
215
+ for component in components:
216
+ assert isinstance(component, Length)
217
+
218
+ def test_equality_operators_success(
219
+ self,
220
+ object_1_state: State,
221
+ object_2_state: State,
222
+ ):
223
+ close_approach_1 = CloseApproach(
224
+ object_1_state=object_1_state,
225
+ object_2_state=object_2_state,
226
+ )
227
+
228
+ close_approach_2 = CloseApproach(
229
+ object_1_state=object_1_state,
230
+ object_2_state=object_2_state,
231
+ )
232
+
233
+ assert close_approach_1 == close_approach_2
234
+ assert not (close_approach_1 != close_approach_2)
235
+
236
+ def test_string_representation_success(
237
+ self,
238
+ close_approach: CloseApproach,
239
+ ):
240
+ string_repr = str(close_approach)
241
+
242
+ assert string_repr is not None
243
+ assert isinstance(string_repr, str)
244
+ assert len(string_repr) > 0