open-space-toolkit-astrodynamics 13.1.0__py312-none-manylinux2014_aarch64.whl → 15.0.0__py312-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 (60) hide show
  1. {open_space_toolkit_astrodynamics-13.1.0.dist-info → open_space_toolkit_astrodynamics-15.0.0.dist-info}/METADATA +4 -4
  2. {open_space_toolkit_astrodynamics-13.1.0.dist-info → open_space_toolkit_astrodynamics-15.0.0.dist-info}/RECORD +59 -28
  3. {open_space_toolkit_astrodynamics-13.1.0.dist-info → open_space_toolkit_astrodynamics-15.0.0.dist-info}/WHEEL +1 -1
  4. ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-312-aarch64-linux-gnu.so +0 -0
  5. ostk/astrodynamics/__init__.pyi +785 -0
  6. ostk/astrodynamics/access.pyi +588 -0
  7. ostk/astrodynamics/conjunction/__init__.pyi +3 -0
  8. ostk/astrodynamics/conjunction/message/__init__.pyi +3 -0
  9. ostk/astrodynamics/conjunction/message/ccsds.pyi +723 -0
  10. ostk/astrodynamics/converters.pyi +58 -0
  11. ostk/astrodynamics/data/__init__.pyi +3 -0
  12. ostk/astrodynamics/data/provider.pyi +22 -0
  13. ostk/astrodynamics/dynamics.pyi +329 -0
  14. ostk/astrodynamics/event_condition.pyi +580 -0
  15. ostk/astrodynamics/flight/__init__.pyi +547 -0
  16. ostk/astrodynamics/flight/profile/__init__.pyi +102 -0
  17. ostk/astrodynamics/flight/profile/model.pyi +176 -0
  18. ostk/astrodynamics/flight/system.pyi +277 -0
  19. ostk/astrodynamics/guidance_law.pyi +282 -0
  20. ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.15 +0 -0
  21. ostk/astrodynamics/pytrajectory/__init__.pyi +3 -0
  22. ostk/astrodynamics/pytrajectory/pystate.py +2 -4
  23. ostk/astrodynamics/pytrajectory/pystate.pyi +65 -0
  24. ostk/astrodynamics/solver.pyi +232 -0
  25. ostk/astrodynamics/test/access/test_generator.py +130 -59
  26. ostk/astrodynamics/test/access/test_visibility_criterion.py +198 -0
  27. ostk/astrodynamics/test/data/provider/test_off_nadir.py +58 -0
  28. ostk/astrodynamics/test/dynamics/test_dynamics.py +1 -1
  29. ostk/astrodynamics/test/flight/system/test_propulsion_system.py +2 -11
  30. ostk/astrodynamics/test/flight/system/test_satellite_system.py +6 -14
  31. ostk/astrodynamics/test/flight/test_maneuver.py +49 -64
  32. ostk/astrodynamics/test/flight/test_profile.py +4 -2
  33. ostk/astrodynamics/test/flight/test_system.py +5 -15
  34. ostk/astrodynamics/test/solvers/test_finite_difference_solver.py +31 -16
  35. ostk/astrodynamics/test/solvers/test_temporal_condition_solver.py +9 -1
  36. ostk/astrodynamics/test/test_display.py +11 -5
  37. ostk/astrodynamics/test/test_event_condition.py +4 -2
  38. ostk/astrodynamics/test/test_utilities.py +1 -1
  39. ostk/astrodynamics/test/test_viewer.py +70 -1
  40. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_acceleration.py +136 -0
  41. ostk/astrodynamics/test/trajectory/state/test_coordinate_subset.py +9 -0
  42. ostk/astrodynamics/test/trajectory/state/test_numerical_solver.py +4 -2
  43. ostk/astrodynamics/test/trajectory/test_local_orbital_frame_factory.py +25 -15
  44. ostk/astrodynamics/test/trajectory/test_propagator.py +21 -27
  45. ostk/astrodynamics/test/trajectory/test_segment.py +0 -1
  46. ostk/astrodynamics/test/trajectory/test_state_builder.py +1 -0
  47. ostk/astrodynamics/trajectory/__init__.pyi +1802 -0
  48. ostk/astrodynamics/trajectory/orbit/__init__.pyi +361 -0
  49. ostk/astrodynamics/trajectory/orbit/message/__init__.pyi +3 -0
  50. ostk/astrodynamics/trajectory/orbit/message/spacex.pyi +273 -0
  51. ostk/astrodynamics/trajectory/orbit/model/__init__.pyi +517 -0
  52. ostk/astrodynamics/trajectory/orbit/model/brouwerLyddaneMean.pyi +127 -0
  53. ostk/astrodynamics/trajectory/orbit/model/kepler.pyi +581 -0
  54. ostk/astrodynamics/trajectory/orbit/model/sgp4.pyi +333 -0
  55. ostk/astrodynamics/trajectory/state/__init__.pyi +406 -0
  56. ostk/astrodynamics/trajectory/state/coordinate_subset.pyi +223 -0
  57. ostk/astrodynamics/viewer.py +32 -0
  58. ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.13 +0 -0
  59. {open_space_toolkit_astrodynamics-13.1.0.dist-info → open_space_toolkit_astrodynamics-15.0.0.dist-info}/top_level.txt +0 -0
  60. {open_space_toolkit_astrodynamics-13.1.0.dist-info → open_space_toolkit_astrodynamics-15.0.0.dist-info}/zip-safe +0 -0
@@ -2,6 +2,8 @@
2
2
 
3
3
  import pytest
4
4
 
5
+ import numpy as np
6
+
5
7
  from ostk.mathematics.object import RealInterval
6
8
 
7
9
  from ostk.physics.unit import Length
@@ -12,7 +14,11 @@ from ostk.physics.time import Duration
12
14
  from ostk.physics.time import Instant
13
15
  from ostk.physics.time import Interval
14
16
  from ostk.physics import Environment
17
+ from ostk.physics.coordinate import Position
18
+ from ostk.physics.coordinate import Frame
19
+ from ostk.physics.coordinate.spherical import LLA
15
20
  from ostk.physics.environment.object import Celestial
21
+ from ostk.physics.environment.object.celestial import Earth
16
22
 
17
23
  from ostk.astrodynamics import Trajectory
18
24
  from ostk.astrodynamics.trajectory import Orbit
@@ -20,6 +26,8 @@ from ostk.astrodynamics.trajectory.orbit.model import Kepler
20
26
  from ostk.astrodynamics.trajectory.orbit.model.kepler import COE
21
27
  from ostk.astrodynamics import Access
22
28
  from ostk.astrodynamics.access import Generator
29
+ from ostk.astrodynamics.access import AccessTarget
30
+ from ostk.astrodynamics.access import VisibilityCriterion
23
31
 
24
32
 
25
33
  @pytest.fixture
@@ -36,9 +44,8 @@ def earth(environment: Environment) -> Celestial:
36
44
  def generator(environment: Environment) -> Generator:
37
45
  return Generator(
38
46
  environment=environment,
39
- aer_filter=lambda aer: True,
40
47
  access_filter=lambda access: True,
41
- state_filter=lambda state_1, state_2: True,
48
+ state_filter=None,
42
49
  )
43
50
 
44
51
 
@@ -82,19 +89,106 @@ def to_trajectory(earth: Celestial) -> Trajectory:
82
89
  )
83
90
 
84
91
 
85
- class TestGenerator:
86
- def test_constructor_success_environment(self, environment: Environment):
87
- generator = Generator(
88
- environment=environment,
92
+ @pytest.fixture
93
+ def visibility_criterion(environment: Environment) -> VisibilityCriterion:
94
+ return VisibilityCriterion.from_line_of_sight(environment=environment)
95
+
96
+
97
+ @pytest.fixture
98
+ def lla() -> LLA:
99
+ return LLA.vector([0.0, 0.0, 500.0])
100
+
101
+
102
+ @pytest.fixture
103
+ def access_target(
104
+ visibility_criterion: VisibilityCriterion,
105
+ lla: LLA,
106
+ earth: Earth,
107
+ ) -> AccessTarget:
108
+ return AccessTarget.from_lla(visibility_criterion, lla, earth)
109
+
110
+
111
+ @pytest.fixture
112
+ def trajectory_target(
113
+ visibility_criterion: VisibilityCriterion,
114
+ from_trajectory: Trajectory,
115
+ ) -> AccessTarget:
116
+ return AccessTarget.from_trajectory(visibility_criterion, from_trajectory)
117
+
118
+
119
+ class TestAccessTarget:
120
+ def test_constructor_success(self, access_target: AccessTarget):
121
+ assert isinstance(access_target, AccessTarget)
122
+
123
+ def test_get_type_success(self, access_target: AccessTarget):
124
+ assert access_target.get_type() == AccessTarget.Type.Fixed
125
+
126
+ def test_get_visibility_criterion_success(self, access_target: AccessTarget):
127
+ assert access_target.get_visibility_criterion() is not None
128
+ assert isinstance(access_target.get_visibility_criterion(), VisibilityCriterion)
129
+
130
+ def test_get_trajectory_success(self, access_target: AccessTarget):
131
+ assert access_target.get_trajectory() is not None
132
+ assert isinstance(access_target.get_trajectory(), Trajectory)
133
+
134
+ def test_get_position_success(self, access_target: AccessTarget):
135
+ assert access_target.get_position() is not None
136
+ assert isinstance(access_target.get_position(), Position)
137
+
138
+ def test_get_lla_success(
139
+ self,
140
+ access_target: AccessTarget,
141
+ earth: Earth,
142
+ ):
143
+ assert access_target.get_lla(earth) is not None
144
+ assert isinstance(access_target.get_lla(earth), LLA)
145
+
146
+ def test_compute_r_sez_ecef_success(
147
+ self,
148
+ access_target: AccessTarget,
149
+ earth: Earth,
150
+ ):
151
+ assert access_target.compute_r_sez_ecef(earth) is not None
152
+ assert isinstance(access_target.compute_r_sez_ecef(earth), np.ndarray)
153
+
154
+ def test_from_lla_success(
155
+ self,
156
+ visibility_criterion: VisibilityCriterion,
157
+ lla: LLA,
158
+ earth: Earth,
159
+ ):
160
+ access_target = AccessTarget.from_lla(visibility_criterion, lla, earth)
161
+
162
+ assert access_target is not None
163
+ assert isinstance(access_target, AccessTarget)
164
+
165
+ def test_from_position_success(
166
+ self,
167
+ visibility_criterion: VisibilityCriterion,
168
+ position: Position,
169
+ ):
170
+ access_target = AccessTarget.from_position(
171
+ visibility_criterion, position.in_frame(Frame.ITRF(), Instant.J2000())
89
172
  )
90
173
 
91
- assert generator is not None
92
- assert isinstance(generator, Generator)
174
+ assert access_target is not None
175
+ assert isinstance(access_target, AccessTarget)
93
176
 
94
- def test_constructor_success_environment_aer_filter(self, environment: Environment):
177
+ def test_from_trajectory_success(
178
+ self,
179
+ visibility_criterion: VisibilityCriterion,
180
+ trajectory: Trajectory,
181
+ ):
182
+ access_target = AccessTarget.from_trajectory(visibility_criterion, trajectory)
183
+
184
+ assert access_target is not None
185
+ assert isinstance(access_target, AccessTarget)
186
+
187
+
188
+ class TestGenerator:
189
+ def test_constructor_success_environment(self, environment: Environment):
95
190
  generator = Generator(
96
191
  environment=environment,
97
- aer_filter=lambda aer: True,
98
192
  )
99
193
 
100
194
  assert generator is not None
@@ -142,18 +236,17 @@ class TestGenerator:
142
236
  def test_getters_success(self, generator: Generator):
143
237
  assert generator.get_step() == Duration.minutes(1.0)
144
238
  assert generator.get_tolerance() == Duration.microseconds(1.0)
145
- assert generator.get_aer_filter() is not None
146
239
  assert generator.get_access_filter() is not None
147
- assert generator.get_state_filter() is not None
240
+ assert generator.get_state_filter() is None
148
241
 
149
242
  def test_get_condition_function_success(
150
243
  self,
151
244
  generator: Generator,
152
- from_trajectory: Trajectory,
245
+ trajectory_target: AccessTarget,
153
246
  to_trajectory: Trajectory,
154
247
  ):
155
248
  condition_function = generator.get_condition_function(
156
- from_trajectory=from_trajectory,
249
+ access_target=trajectory_target,
157
250
  to_trajectory=to_trajectory,
158
251
  )
159
252
 
@@ -168,7 +261,7 @@ class TestGenerator:
168
261
  def test_compute_accesses_success(
169
262
  self,
170
263
  generator: Generator,
171
- from_trajectory: Trajectory,
264
+ trajectory_target: AccessTarget,
172
265
  to_trajectory: Trajectory,
173
266
  ):
174
267
  accesses = generator.compute_accesses(
@@ -176,7 +269,7 @@ class TestGenerator:
176
269
  Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC),
177
270
  Instant.date_time(DateTime(2018, 1, 1, 2, 0, 0), Scale.UTC),
178
271
  ),
179
- from_trajectory=from_trajectory,
272
+ access_target=trajectory_target,
180
273
  to_trajectory=to_trajectory,
181
274
  )
182
275
 
@@ -185,15 +278,33 @@ class TestGenerator:
185
278
  assert accesses[0] is not None
186
279
  assert isinstance(accesses[0], Access)
187
280
 
281
+ def test_compute_accesses_multiple_targets_success(
282
+ self,
283
+ generator: Generator,
284
+ trajectory_target: AccessTarget,
285
+ to_trajectory: Trajectory,
286
+ ):
287
+ accesses = generator.compute_accesses(
288
+ interval=Interval.closed(
289
+ Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC),
290
+ Instant.date_time(DateTime(2018, 1, 1, 2, 0, 0), Scale.UTC),
291
+ ),
292
+ access_targets=[trajectory_target],
293
+ to_trajectory=to_trajectory,
294
+ )
295
+
296
+ assert accesses is not None
297
+ assert isinstance(accesses, list)
298
+ assert accesses[0] is not None
299
+ assert isinstance(accesses[0], list)
300
+ assert isinstance(accesses[0][0], Access)
301
+
188
302
  def test_set_step_success(self, generator: Generator):
189
303
  generator.set_step(Duration.seconds(1.0))
190
304
 
191
305
  def test_set_tolerance_success(self, generator: Generator):
192
306
  generator.set_tolerance(Duration.seconds(1.0))
193
307
 
194
- def test_set_aer_filter_success(self, generator: Generator):
195
- generator.set_aer_filter(aer_filter=lambda aer: True)
196
-
197
308
  def test_set_access_filter_success(self, generator: Generator):
198
309
  generator.set_access_filter(access_filter=lambda access: True)
199
310
 
@@ -206,43 +317,3 @@ class TestGenerator:
206
317
  assert generator is not None
207
318
  assert isinstance(generator, Generator)
208
319
  assert generator.is_defined() is False
209
-
210
- def test_aer_ranges_success(self, environment: Environment):
211
- # Construct arbitrary AER ranges
212
- azimuth_interval = RealInterval.closed(0.0, 360.0)
213
- elevation_interval = RealInterval.closed(0.0, 90.0)
214
- range_interval = RealInterval.closed(0.0, 7000e3)
215
-
216
- generator = Generator.aer_ranges(
217
- azimuth_range=azimuth_interval,
218
- elevation_range=elevation_interval,
219
- range_range=range_interval,
220
- environment=environment,
221
- )
222
-
223
- assert generator is not None
224
- assert isinstance(generator, Generator)
225
- assert generator.is_defined()
226
-
227
- def test_aer_mask_success(self, environment: Environment):
228
- # Construct arbitrary anAzimuthElevationMask using python dict
229
- an_azimuth_elevation_mask = {
230
- 0.0: 30.0,
231
- 90.0: 60.0,
232
- 180.0: 60.0,
233
- 270.0: 30.0,
234
- 359.0: 30.0,
235
- }
236
-
237
- # Construct arbitrary aRangerange
238
- a_range_range = RealInterval(0.0, 10e4, RealInterval.Type.Closed)
239
-
240
- generator = Generator.aer_mask(
241
- azimuth_elevation_mask=an_azimuth_elevation_mask,
242
- range_range=a_range_range,
243
- environment=environment,
244
- )
245
-
246
- assert generator is not None
247
- assert isinstance(generator, Generator)
248
- assert generator.is_defined()
@@ -0,0 +1,198 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+ import numpy as np
5
+
6
+ from ostk.mathematics.object import RealInterval
7
+
8
+ from ostk.physics import Environment
9
+ from ostk.physics.time import Instant
10
+ from ostk.physics.time import DateTime
11
+ from ostk.physics.time import Scale
12
+
13
+ from ostk.astrodynamics.access import VisibilityCriterion
14
+
15
+
16
+ @pytest.fixture()
17
+ def instant() -> Instant:
18
+ return Instant.date_time(DateTime(2023, 1, 1, 0, 0, 0), Scale.UTC)
19
+
20
+
21
+ @pytest.fixture
22
+ def environment() -> Environment:
23
+ return Environment.default()
24
+
25
+
26
+ @pytest.fixture
27
+ def azimuth_interval() -> RealInterval:
28
+ return RealInterval.closed(0.0, 90.0)
29
+
30
+
31
+ @pytest.fixture
32
+ def elevation_interval() -> RealInterval:
33
+ return RealInterval.closed(0.0, 45.0)
34
+
35
+
36
+ @pytest.fixture
37
+ def range_interval() -> RealInterval:
38
+ return RealInterval.closed(0.0, 1e7)
39
+
40
+
41
+ @pytest.fixture
42
+ def aer_mask() -> dict[float, float]:
43
+ return {
44
+ 0.0: 0.0,
45
+ 90.0: 45.0,
46
+ }
47
+
48
+
49
+ class TestVisibilityCriterion:
50
+ def test_aer_interval_constructor(
51
+ self,
52
+ azimuth_interval: RealInterval,
53
+ elevation_interval: RealInterval,
54
+ range_interval: RealInterval,
55
+ ):
56
+ aer_interval = VisibilityCriterion.AERInterval(
57
+ azimuth_interval,
58
+ elevation_interval,
59
+ range_interval,
60
+ )
61
+ assert aer_interval is not None
62
+ assert isinstance(aer_interval, VisibilityCriterion.AERInterval)
63
+
64
+ def test_aer_mask_constructor(
65
+ self,
66
+ aer_mask: dict[float, float],
67
+ range_interval: RealInterval,
68
+ ):
69
+ aer_mask_criterion = VisibilityCriterion.AERMask(aer_mask, range_interval)
70
+ assert aer_mask_criterion is not None
71
+ assert isinstance(aer_mask_criterion, VisibilityCriterion.AERMask)
72
+
73
+ def test_line_of_sight_constructor(
74
+ self,
75
+ environment: Environment,
76
+ ):
77
+ line_of_sight = VisibilityCriterion.LineOfSight(environment)
78
+ assert line_of_sight is not None
79
+ assert isinstance(line_of_sight, VisibilityCriterion.LineOfSight)
80
+
81
+ def test_elevation_interval_constructor(
82
+ self,
83
+ elevation_interval: RealInterval,
84
+ ):
85
+ elevation_criterion = VisibilityCriterion.ElevationInterval(elevation_interval)
86
+ assert elevation_criterion is not None
87
+ assert isinstance(elevation_criterion, VisibilityCriterion.ElevationInterval)
88
+
89
+ def test_visibility_criterion_from_aer_interval(
90
+ self,
91
+ azimuth_interval: RealInterval,
92
+ elevation_interval: RealInterval,
93
+ range_interval: RealInterval,
94
+ ):
95
+ criterion = VisibilityCriterion.from_aer_interval(
96
+ azimuth_interval, elevation_interval, range_interval
97
+ )
98
+ assert criterion is not None
99
+ assert isinstance(criterion, VisibilityCriterion)
100
+ assert criterion.is_aer_interval()
101
+
102
+ def test_visibility_criterion_from_aer_mask(
103
+ self,
104
+ aer_mask: dict[float, float],
105
+ range_interval: RealInterval,
106
+ ):
107
+ criterion = VisibilityCriterion.from_aer_mask(aer_mask, range_interval)
108
+ assert criterion is not None
109
+ assert isinstance(criterion, VisibilityCriterion)
110
+ assert criterion.is_aer_mask()
111
+
112
+ def test_visibility_criterion_from_line_of_sight(
113
+ self,
114
+ environment: Environment,
115
+ ):
116
+ criterion = VisibilityCriterion.from_line_of_sight(environment)
117
+ assert criterion is not None
118
+ assert isinstance(criterion, VisibilityCriterion)
119
+ assert criterion.is_line_of_sight()
120
+
121
+ def test_visibility_criterion_from_elevation_interval(
122
+ self, elevation_interval: RealInterval
123
+ ):
124
+ criterion = VisibilityCriterion.from_elevation_interval(elevation_interval)
125
+ assert criterion is not None
126
+ assert isinstance(criterion, VisibilityCriterion)
127
+ assert criterion.is_elevation_interval()
128
+
129
+ def test_aer_interval_is_satisfied(
130
+ self,
131
+ azimuth_interval: RealInterval,
132
+ elevation_interval: RealInterval,
133
+ range_interval: RealInterval,
134
+ ):
135
+ aer_interval = VisibilityCriterion.AERInterval(
136
+ azimuth_interval, elevation_interval, range_interval
137
+ )
138
+ assert (
139
+ aer_interval.is_satisfied(azimuth=np.pi / 4, elevation=np.pi / 8, range=5e6)
140
+ is True
141
+ )
142
+
143
+ assert (
144
+ aer_interval.is_satisfied(azimuth=np.pi, elevation=np.pi / 2, range=1e8)
145
+ is False
146
+ )
147
+
148
+ def test_elevation_interval_is_satisfied(
149
+ self,
150
+ elevation_interval: RealInterval,
151
+ ):
152
+ elevation_criterion = VisibilityCriterion.ElevationInterval(elevation_interval)
153
+ elevation_valid = np.pi / 8 # 22.5 degrees
154
+ assert elevation_criterion.is_satisfied(elevation_valid) is True
155
+
156
+ elevation_invalid = np.pi / 2 # 90 degrees
157
+ assert elevation_criterion.is_satisfied(elevation_invalid) is False
158
+
159
+ def test_line_of_sight_is_satisfied(
160
+ self,
161
+ environment: Environment,
162
+ ):
163
+ line_of_sight = VisibilityCriterion.LineOfSight(environment)
164
+ instant = Instant.now()
165
+
166
+ from_position = np.array([7000e3, 0.0, 0.0])
167
+ to_position = np.array([7005e3, 0.0, 0.0])
168
+
169
+ assert line_of_sight.is_satisfied(instant, from_position, to_position) is True
170
+
171
+ def test_visibility_criterion_type_checks(
172
+ self,
173
+ elevation_interval: RealInterval,
174
+ environment: Environment,
175
+ ):
176
+ criterion = VisibilityCriterion.from_elevation_interval(elevation_interval)
177
+ assert criterion.is_elevation_interval() is True
178
+ assert criterion.is_aer_interval() is False
179
+ assert criterion.is_line_of_sight() is False
180
+
181
+ criterion = VisibilityCriterion.from_line_of_sight(environment)
182
+ assert criterion.is_line_of_sight() is True
183
+
184
+ def test_visibility_criterion_cast(
185
+ self,
186
+ azimuth_interval: RealInterval,
187
+ elevation_interval: RealInterval,
188
+ range_interval: RealInterval,
189
+ ):
190
+ criterion = VisibilityCriterion.from_aer_interval(
191
+ azimuth_interval, elevation_interval, range_interval
192
+ )
193
+ aer_interval = criterion.as_aer_interval()
194
+ assert aer_interval is not None
195
+ assert isinstance(aer_interval, VisibilityCriterion.AERInterval)
196
+
197
+ with pytest.raises(ValueError):
198
+ criterion.as_line_of_sight()
@@ -0,0 +1,58 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ from ostk.physics.time import DateTime
6
+ from ostk.physics.time import Instant
7
+ from ostk.physics.time import Scale
8
+ from ostk.physics.unit import Angle
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 import State
14
+ from ostk.astrodynamics.data.provider import compute_off_nadir_angles
15
+
16
+
17
+ @pytest.fixture
18
+ def target_position() -> Position:
19
+ return Position.meters([0.0, 0.0, 0.0], Frame.GCRF())
20
+
21
+
22
+ @pytest.fixture
23
+ def state() -> State:
24
+ instant = Instant.date_time(DateTime(2020, 1, 1, 0, 0, 0), Scale.UTC)
25
+ position = Position.meters([0.0, 0.0, 0.0], Frame.GCRF())
26
+ velocity = Velocity.meters_per_second([0.0, 0.0, 0.0], Frame.GCRF())
27
+
28
+ return State(instant=instant, position=position, velocity=velocity)
29
+
30
+
31
+ class TestOffNadirAngles:
32
+
33
+ def test_compute_off_nadir_angles(
34
+ self,
35
+ state: State,
36
+ target_position: Position,
37
+ ):
38
+ along_track: Angle
39
+ cross_track: Angle
40
+ off_nadir: Angle
41
+ along_track, cross_track, off_nadir = compute_off_nadir_angles(
42
+ state, target_position
43
+ )
44
+
45
+ assert along_track is not None
46
+ assert cross_track is not None
47
+ assert off_nadir is not None
48
+
49
+ def test_compute_off_nadir_angles_undefined(
50
+ self,
51
+ state: State,
52
+ target_position: Position,
53
+ ):
54
+ with pytest.raises(RuntimeError):
55
+ compute_off_nadir_angles(State.undefined(), target_position)
56
+
57
+ with pytest.raises(RuntimeError):
58
+ compute_off_nadir_angles(state, Position.undefined())
@@ -21,7 +21,7 @@ def environment() -> Environment:
21
21
  @pytest.fixture
22
22
  def dynamics(name: str) -> Dynamics:
23
23
  class MyDynamics(Dynamics):
24
- def is_defined():
24
+ def is_defined(self):
25
25
  return True
26
26
 
27
27
  def get_read_coordinate_subsets(self):
@@ -2,17 +2,8 @@
2
2
 
3
3
  import pytest
4
4
 
5
- import numpy as np
6
-
7
- import ostk.mathematics as mathematics
8
-
9
- import ostk.physics as physics
10
-
11
- import ostk.astrodynamics as astrodynamics
12
-
13
- Mass = physics.unit.Mass
14
-
15
- PropulsionSystem = astrodynamics.flight.system.PropulsionSystem
5
+ from ostk.physics.unit import Mass
6
+ from ostk.astrodynamics.flight.system import PropulsionSystem
16
7
 
17
8
 
18
9
  @pytest.fixture
@@ -4,20 +4,12 @@ import pytest
4
4
 
5
5
  import numpy as np
6
6
 
7
- import ostk.mathematics as mathematics
8
-
9
- import ostk.physics as physics
10
-
11
- import ostk.astrodynamics as astrodynamics
12
-
13
- Cuboid = mathematics.geometry.d3.object.Cuboid
14
- Composite = mathematics.geometry.d3.object.Composite
15
- Point = mathematics.geometry.d3.object.Point
16
-
17
- Mass = physics.unit.Mass
18
-
19
- SatelliteSystem = astrodynamics.flight.system.SatelliteSystem
20
- PropulsionSystem = astrodynamics.flight.system.PropulsionSystem
7
+ from ostk.mathematics.geometry.d3.object import Cuboid
8
+ from ostk.mathematics.geometry.d3.object import Composite
9
+ from ostk.mathematics.geometry.d3.object import Point
10
+ from ostk.physics.unit import Mass
11
+ from ostk.astrodynamics.flight.system import SatelliteSystem
12
+ from ostk.astrodynamics.flight.system import PropulsionSystem
21
13
 
22
14
 
23
15
  @pytest.fixture