open-space-toolkit-astrodynamics 1.3.0__py38-none-any.whl → 2.1.0__py38-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.
- {open_space_toolkit_astrodynamics-1.3.0.dist-info → open_space_toolkit_astrodynamics-2.1.0.dist-info}/METADATA +2 -2
- {open_space_toolkit_astrodynamics-1.3.0.dist-info → open_space_toolkit_astrodynamics-2.1.0.dist-info}/RECORD +24 -17
- ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-38-x86_64-linux-gnu.so +0 -0
- ostk/astrodynamics/{libopen-space-toolkit-astrodynamics.so.1 → libopen-space-toolkit-astrodynamics.so.2} +0 -0
- ostk/astrodynamics/test/event_condition/test_boolean_event_condition.py +44 -0
- ostk/astrodynamics/test/event_condition/test_coe_condition.py +40 -11
- ostk/astrodynamics/test/event_condition/test_conjunctive.py +19 -18
- ostk/astrodynamics/test/event_condition/test_disjunctive.py +19 -18
- ostk/astrodynamics/test/event_condition/test_logical_connective.py +4 -2
- ostk/astrodynamics/test/event_condition/test_real_event_condition.py +41 -0
- ostk/astrodynamics/test/flight/system/dynamics/test_dynamics.py +37 -0
- ostk/astrodynamics/test/test_event_condition.py +9 -28
- ostk/astrodynamics/test/test_numerical_solver.py +23 -15
- ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_coe.py +5 -0
- ostk/astrodynamics/test/trajectory/state/coordinates_subset/test_cartesian_position.py +103 -0
- ostk/astrodynamics/test/trajectory/state/coordinates_subset/test_cartesian_velocity.py +113 -0
- ostk/astrodynamics/test/trajectory/state/test_coordinates_broker.py +71 -0
- ostk/astrodynamics/test/trajectory/state/test_coordinates_subset.py +43 -0
- ostk/astrodynamics/test/trajectory/test_propagator.py +12 -8
- ostk/astrodynamics/test/trajectory/test_state.py +66 -15
- ostk/astrodynamics/viewer.py +1 -1
- {open_space_toolkit_astrodynamics-1.3.0.dist-info → open_space_toolkit_astrodynamics-2.1.0.dist-info}/WHEEL +0 -0
- {open_space_toolkit_astrodynamics-1.3.0.dist-info → open_space_toolkit_astrodynamics-2.1.0.dist-info}/top_level.txt +0 -0
- {open_space_toolkit_astrodynamics-1.3.0.dist-info → open_space_toolkit_astrodynamics-2.1.0.dist-info}/zip-safe +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: open-space-toolkit-astrodynamics
|
3
|
-
Version: 1.
|
3
|
+
Version: 2.1.0
|
4
4
|
Summary: Orbit, attitude, access.
|
5
5
|
Author: Open Space Collective
|
6
6
|
Author-email: contact@open-space-collective.org
|
@@ -11,7 +11,7 @@ Classifier: Programming Language :: Python :: 3
|
|
11
11
|
Classifier: License :: OSI Approved :: Apache Software License
|
12
12
|
Classifier: Operating System :: POSIX :: Linux
|
13
13
|
Description-Content-Type: text/markdown
|
14
|
-
Requires-Dist: open-space-toolkit-physics (~=
|
14
|
+
Requires-Dist: open-space-toolkit-physics (~=2.0.0)
|
15
15
|
|
16
16
|
# Open Space Toolkit ▸ Astrodynamics
|
17
17
|
|
@@ -1,19 +1,19 @@
|
|
1
1
|
ostk/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
|
2
|
-
ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-38-x86_64-linux-gnu.so,sha256
|
2
|
+
ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-38-x86_64-linux-gnu.so,sha256=BtJCIbcnMBY4AKqmSFiCt9iRkTPiVNEqCdZDCE2hWvI,1332600
|
3
3
|
ostk/astrodynamics/__init__.py,sha256=BE7yyrOnPqFCTPT3GhYEI4IWR5nzs96VSjKphhQ09ew,97
|
4
4
|
ostk/astrodynamics/converters.py,sha256=sBZ3_JMjowWbQ9gBPA2cSEkbBfAwXmt1IBbLks76-Vk,3502
|
5
5
|
ostk/astrodynamics/display.py,sha256=y9FnoQbPFGM6LzkUdgXgeqtuVGhv57GuTKbeDdcFPgw,6306
|
6
|
-
ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.
|
6
|
+
ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.2,sha256=3xgJFd7EtUQR97QzanL9AnZbbrxA6IxRInCFSKd6X-A,67701896
|
7
7
|
ostk/astrodynamics/utilities.py,sha256=NbeKN_CtcCRHIinhoNWTEosBMR7xc924S-ZFD97mduw,4478
|
8
|
-
ostk/astrodynamics/viewer.py,sha256=
|
8
|
+
ostk/astrodynamics/viewer.py,sha256=_4uucNtZrIADtKtEYHbiu91RVVvKRG3vPULUAshPLJU,8912
|
9
9
|
ostk/astrodynamics/test/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
|
10
10
|
ostk/astrodynamics/test/conftest.py,sha256=J3SbQibnMVaPktAF6Z6cwVCa7xhW3uXpkOJRom6YtCo,2719
|
11
11
|
ostk/astrodynamics/test/test_access.py,sha256=4I5r4Hukv0fkByHVARhaYpcDu5EOQ7dtbs-ZK7siTqg,3961
|
12
12
|
ostk/astrodynamics/test/test_converters.py,sha256=ktkLH0xpeRdQ7kN6i5a_agmGqovUxVtCwlwcCdCUaa0,5847
|
13
13
|
ostk/astrodynamics/test/test_display.py,sha256=8YeiYRYMpokzqprbRoDBI_xhHI5B8uxcdSzmqmF3AIc,3738
|
14
|
-
ostk/astrodynamics/test/test_event_condition.py,sha256=
|
14
|
+
ostk/astrodynamics/test/test_event_condition.py,sha256=a503h3sHj-Q8c6jo1z_CcgW1kplZqtugPH-jhf3Huvk,1413
|
15
15
|
ostk/astrodynamics/test/test_import.py,sha256=y62-SI3pmSkIgyOIrDDXeWqWI3DhnjnUl7SgWAp99kA,1212
|
16
|
-
ostk/astrodynamics/test/test_numerical_solver.py,sha256=
|
16
|
+
ostk/astrodynamics/test/test_numerical_solver.py,sha256=kM1zx_D1Tot1hmnVOUK1Zw5CnwUlq5BvB9ugrzOOlY4,8366
|
17
17
|
ostk/astrodynamics/test/test_root_solver.py,sha256=hQ8O6g-WP49gZH_H3Rdufv0F0gQorpzJyIcjBGGUQ34,1831
|
18
18
|
ostk/astrodynamics/test/test_trajectory.py,sha256=4AhlAaIrCrP17ZycJqYlYskj8SC2MH7fp3_4eqWdF9s,1366
|
19
19
|
ostk/astrodynamics/test/test_utilities.py,sha256=edAPLXNMflCPa0gzhU4e05pa6HbAq7UV0JzMMRx3VlQ,3252
|
@@ -24,11 +24,13 @@ ostk/astrodynamics/test/conjunction/messages/ccsds/__init__.py,sha256=epnVn2PwdQ
|
|
24
24
|
ostk/astrodynamics/test/conjunction/messages/ccsds/conftest.py,sha256=xyTd24828Ue2HgOWY8UhizIc5mzgRgoH2VSOfVfKCdw,14632
|
25
25
|
ostk/astrodynamics/test/conjunction/messages/ccsds/test_cdm.py,sha256=SqtYXB8qhKzbQEWmCzz13xi0Uu64-VSKXuMObcFV7EI,18518
|
26
26
|
ostk/astrodynamics/test/conjunction/messages/ccsds/data/cdm.json,sha256=-CL8Bu-ivigzkrqHs9Q5snSubHJ_D0YMroatEInkidc,12965
|
27
|
-
ostk/astrodynamics/test/event_condition/
|
28
|
-
ostk/astrodynamics/test/event_condition/
|
29
|
-
ostk/astrodynamics/test/event_condition/
|
27
|
+
ostk/astrodynamics/test/event_condition/test_boolean_event_condition.py,sha256=2QOgkLM5ROhOx2uNNQQfn0XDC34sx4k0ZXn9Zm6SD_0,1184
|
28
|
+
ostk/astrodynamics/test/event_condition/test_coe_condition.py,sha256=aUQrgLUYvz5yzmlhic5-ti6Gn8kdo4G6wU1MRrF6pRk,3289
|
29
|
+
ostk/astrodynamics/test/event_condition/test_conjunctive.py,sha256=LGzxK6_qTcE8FMLap0WZ-4maJuXNU1DtXeJjodoWy9w,1916
|
30
|
+
ostk/astrodynamics/test/event_condition/test_disjunctive.py,sha256=dVmEILtS_Cj0BYNWSMA5z6T7B-mmYexQB8gXatJqrz4,1902
|
30
31
|
ostk/astrodynamics/test/event_condition/test_duration_condition.py,sha256=wyDBde1vc06-cUjOwmJP6Po8cHbQTGHIDWB3e6eoO_o,973
|
31
|
-
ostk/astrodynamics/test/event_condition/test_logical_connective.py,sha256=
|
32
|
+
ostk/astrodynamics/test/event_condition/test_logical_connective.py,sha256=DjBFecD9hNjF379if3mWUAeCnDF_vhUhJbnRZEhvb-8,1197
|
33
|
+
ostk/astrodynamics/test/event_condition/test_real_event_condition.py,sha256=HQu545o1ViLIRsNkx-3Ivmn84IUOssnLIFIcD1JxU7I,1103
|
32
34
|
ostk/astrodynamics/test/flight/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
|
33
35
|
ostk/astrodynamics/test/flight/test_profile.py,sha256=27g5Atvr2RGslvFujdP90cA9qldkNb7C0U1RgbOAws0,5197
|
34
36
|
ostk/astrodynamics/test/flight/test_system.py,sha256=YPrjoV3o67_1zCXCZqohlSAR7zkU0LXP2fF20M2s0C8,1326
|
@@ -39,6 +41,7 @@ ostk/astrodynamics/test/flight/system/test_satellite_system.py,sha256=-5KOGVTWRI
|
|
39
41
|
ostk/astrodynamics/test/flight/system/dynamics/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
|
40
42
|
ostk/astrodynamics/test/flight/system/dynamics/test_atmospheric_drag.py,sha256=nZ2lBGq5Ni3ypuqGbTfluxTXYERpwol49d0DrgnYsIo,3115
|
41
43
|
ostk/astrodynamics/test/flight/system/dynamics/test_central_body_gravity.py,sha256=r3JIIX7cD63BhrgvLtjFaK7ew1BqHdKP5_VxwGmuv1Q,1818
|
44
|
+
ostk/astrodynamics/test/flight/system/dynamics/test_dynamics.py,sha256=arNkAOj2y4CDmc9CXxItbFtC4QYjaByuJefdi5S6alw,914
|
42
45
|
ostk/astrodynamics/test/flight/system/dynamics/test_position_derivative.py,sha256=ZVVewpqZwqiBLDqoNQDHDgDodtj6_M0J6ZmgHe_1gz8,1646
|
43
46
|
ostk/astrodynamics/test/flight/system/dynamics/test_third_body_gravity.py,sha256=Z8OkM-EFafFpWziu3bfatlSlZA4Tic2fsVLU35rDp5E,1915
|
44
47
|
ostk/astrodynamics/test/solvers/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
|
@@ -46,8 +49,8 @@ ostk/astrodynamics/test/solvers/test_temporal_condition_solver.py,sha256=s7r7Vel
|
|
46
49
|
ostk/astrodynamics/test/trajectory/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
|
47
50
|
ostk/astrodynamics/test/trajectory/test_model.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
|
48
51
|
ostk/astrodynamics/test/trajectory/test_orbit.py,sha256=SlCBZ_broPaJ6L8khMuvbdPem9-zmqG6IZwxr9cECB4,3155
|
49
|
-
ostk/astrodynamics/test/trajectory/test_propagator.py,sha256=
|
50
|
-
ostk/astrodynamics/test/trajectory/test_state.py,sha256=
|
52
|
+
ostk/astrodynamics/test/trajectory/test_propagator.py,sha256=PHeZgFO8-xaH1ItFMZdjXxyQ792z8yROYMx0HnsfSSo,7570
|
53
|
+
ostk/astrodynamics/test/trajectory/test_state.py,sha256=okpjRPixi7AUSV1YG8hNFFEo0AayfIK50X2vor9yOB0,3199
|
51
54
|
ostk/astrodynamics/test/trajectory/orbit/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
|
52
55
|
ostk/astrodynamics/test/trajectory/orbit/test_model.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
|
53
56
|
ostk/astrodynamics/test/trajectory/orbit/test_pass.py,sha256=MtPRKhVz4hCzfFuE0p1x89Ps68M9s7miT7VtPIDVeOo,1898
|
@@ -62,11 +65,15 @@ ostk/astrodynamics/test/trajectory/orbit/models/test_propagated.py,sha256=MpGL1F
|
|
62
65
|
ostk/astrodynamics/test/trajectory/orbit/models/test_sgp4.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
|
63
66
|
ostk/astrodynamics/test/trajectory/orbit/models/test_tabulated.py,sha256=tL3gGDitdEYCCRwGtu2RP-9d4JWsujV53ck9DRkyeG4,11183
|
64
67
|
ostk/astrodynamics/test/trajectory/orbit/models/kepler/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
|
65
|
-
ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_coe.py,sha256=
|
68
|
+
ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_coe.py,sha256=uWgUO9zHrcqEKGJ-SWUiHfEbWDm8YcgptnS2I2y_V1U,2728
|
66
69
|
ostk/astrodynamics/test/trajectory/orbit/models/sgp4/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
|
67
70
|
ostk/astrodynamics/test/trajectory/orbit/models/sgp4/test_tle.py,sha256=lbPqHd87ExTNbBFcFSTMWRnWbpe_4BDJ2g2APlQLJkY,11486
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
open_space_toolkit_astrodynamics-1.
|
71
|
+
ostk/astrodynamics/test/trajectory/state/test_coordinates_broker.py,sha256=kB_gsJHxvCDY9kfuqVkwHt5ZmMuaAoRk_3YZGxoXOwg,2515
|
72
|
+
ostk/astrodynamics/test/trajectory/state/test_coordinates_subset.py,sha256=eMmifR5rJMk2yFN7pfAHq2Ub3FPvknb6gvS-nBDidro,1201
|
73
|
+
ostk/astrodynamics/test/trajectory/state/coordinates_subset/test_cartesian_position.py,sha256=V5d7UnV6KIJjJvh5R0i3imRfyN04JCDvCUsKdvfKmhE,2708
|
74
|
+
ostk/astrodynamics/test/trajectory/state/coordinates_subset/test_cartesian_velocity.py,sha256=5a7yeOVt7gY4oQdINSElb_U2jznJmuWPrT_YJrI6KaM,3070
|
75
|
+
open_space_toolkit_astrodynamics-2.1.0.dist-info/METADATA,sha256=f4RCJAapR8IVLJRap7NK1HBhX_FX9RB8Dr0q-PsZl7E,1779
|
76
|
+
open_space_toolkit_astrodynamics-2.1.0.dist-info/WHEEL,sha256=pruk-ncpSL7wyHyfRUEyLDsvov8r7FCaWTBJ2klfed4,93
|
77
|
+
open_space_toolkit_astrodynamics-2.1.0.dist-info/top_level.txt,sha256=zOR18699uDYnafgarhL8WU_LmTZY_5NVqutv-flp_x4,5
|
78
|
+
open_space_toolkit_astrodynamics-2.1.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
79
|
+
open_space_toolkit_astrodynamics-2.1.0.dist-info/RECORD,,
|
Binary file
|
Binary file
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Apache License 2.0
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
from ostk.astrodynamics.event_condition import BooleanEventCondition
|
6
|
+
|
7
|
+
|
8
|
+
@pytest.fixture
|
9
|
+
def evaluator():
|
10
|
+
return lambda state_vector, time: time > 0.0
|
11
|
+
|
12
|
+
|
13
|
+
@pytest.fixture
|
14
|
+
def is_inversed() -> bool:
|
15
|
+
return False
|
16
|
+
|
17
|
+
|
18
|
+
@pytest.fixture
|
19
|
+
def event_condition(evaluator, is_inversed: bool) -> BooleanEventCondition:
|
20
|
+
return BooleanEventCondition(
|
21
|
+
"My Condition",
|
22
|
+
BooleanEventCondition.Criteria.StrictlyPositive,
|
23
|
+
evaluator,
|
24
|
+
is_inversed,
|
25
|
+
)
|
26
|
+
|
27
|
+
|
28
|
+
class TestBooleanEventCondition:
|
29
|
+
def test_is_inversed(self, event_condition: BooleanEventCondition, is_inversed: bool):
|
30
|
+
assert event_condition.is_inversed() == is_inversed
|
31
|
+
|
32
|
+
def test_evaluate(self, event_condition: BooleanEventCondition):
|
33
|
+
assert event_condition.evaluate(state_vector=[0.0], time=10.0) is not None
|
34
|
+
|
35
|
+
def test_is_satisfied(self, event_condition: BooleanEventCondition):
|
36
|
+
assert (
|
37
|
+
event_condition.is_satisfied(
|
38
|
+
previous_state_vector=[-1.0],
|
39
|
+
previous_time=-1.0,
|
40
|
+
current_state_vector=[1.0],
|
41
|
+
current_time=10.0,
|
42
|
+
)
|
43
|
+
== True
|
44
|
+
)
|
@@ -4,11 +4,17 @@ import pytest
|
|
4
4
|
|
5
5
|
from ostk.physics.environment.gravitational import Earth
|
6
6
|
from ostk.physics.units import Derived, Length, Angle
|
7
|
+
from ostk.physics.coordinate import Frame
|
7
8
|
|
8
9
|
from ostk.astrodynamics.event_condition import COECondition
|
9
10
|
from ostk.astrodynamics.trajectory.orbit.models.kepler import COE
|
10
11
|
|
11
12
|
|
13
|
+
@pytest.fixture
|
14
|
+
def frame() -> Frame:
|
15
|
+
return Frame.GCRF()
|
16
|
+
|
17
|
+
|
12
18
|
@pytest.fixture
|
13
19
|
def criteria() -> COECondition.Criteria:
|
14
20
|
return COECondition.Criteria.AnyCrossing
|
@@ -34,10 +40,11 @@ def condition(
|
|
34
40
|
criteria: COECondition.Criteria,
|
35
41
|
element: COE.Element,
|
36
42
|
target: float,
|
43
|
+
frame: Frame,
|
37
44
|
gravitational_parameter: Derived,
|
38
45
|
) -> COECondition:
|
39
46
|
return COECondition(
|
40
|
-
"Test COECondition", criteria, element, target, gravitational_parameter
|
47
|
+
"Test COECondition", criteria, element, target, frame, gravitational_parameter
|
41
48
|
)
|
42
49
|
|
43
50
|
|
@@ -54,13 +61,28 @@ def state_vector() -> list[float]:
|
|
54
61
|
|
55
62
|
|
56
63
|
class TestCOECondition:
|
57
|
-
def test_constructor(
|
64
|
+
def test_constructor(
|
65
|
+
self,
|
66
|
+
criteria: COECondition.Criteria,
|
67
|
+
element: COE.Element,
|
68
|
+
target: float,
|
69
|
+
frame: Frame,
|
70
|
+
gravitational_parameter: Derived,
|
71
|
+
):
|
58
72
|
name = "Test COECondition"
|
59
|
-
condition = COECondition(
|
73
|
+
condition = COECondition(
|
74
|
+
name, criteria, element, target, frame, gravitational_parameter
|
75
|
+
)
|
60
76
|
|
61
77
|
assert condition is not None
|
62
78
|
|
63
|
-
def test_getters(
|
79
|
+
def test_getters(
|
80
|
+
self,
|
81
|
+
condition: COECondition,
|
82
|
+
element: COE.Element,
|
83
|
+
target: float,
|
84
|
+
gravitational_parameter: Derived,
|
85
|
+
):
|
64
86
|
assert condition.get_element() == element
|
65
87
|
assert condition.get_target() == target
|
66
88
|
assert condition.get_gravitational_parameter() == gravitational_parameter
|
@@ -79,15 +101,22 @@ class TestCOECondition:
|
|
79
101
|
),
|
80
102
|
)
|
81
103
|
def test_static_constructors(
|
82
|
-
self,
|
104
|
+
self,
|
105
|
+
static_constructor,
|
106
|
+
target: float,
|
107
|
+
criteria: COECondition.Criteria,
|
108
|
+
frame: Frame,
|
109
|
+
gravitational_parameter: Derived,
|
110
|
+
state_vector: list[float],
|
83
111
|
):
|
84
|
-
|
112
|
+
condition = static_constructor(criteria, target, frame, gravitational_parameter)
|
113
|
+
assert condition is not None
|
114
|
+
|
115
|
+
assert condition.evaluate(state_vector, 0.0) is not None
|
85
116
|
|
86
|
-
def test_evaluate(
|
117
|
+
def test_evaluate(
|
118
|
+
self, condition: COECondition, state_vector: list[float], target: float
|
119
|
+
):
|
87
120
|
assert condition.evaluate(state_vector, 0.0) == pytest.approx(
|
88
121
|
6904757.8910061345 - target, abs=1e-9
|
89
122
|
)
|
90
|
-
|
91
|
-
def test_string_from_element(self):
|
92
|
-
element_str = COECondition.string_from_element(COE.Element.SemiMajorAxis)
|
93
|
-
assert element_str == "Semi-major axis"
|
@@ -2,42 +2,43 @@
|
|
2
2
|
|
3
3
|
import pytest
|
4
4
|
|
5
|
-
from ostk.astrodynamics import
|
6
|
-
from ostk.astrodynamics.event_condition import Conjunctive
|
5
|
+
from ostk.astrodynamics.event_condition import Conjunctive, RealEventCondition
|
7
6
|
|
8
7
|
|
9
8
|
@pytest.fixture
|
10
|
-
def first_condition() ->
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
def first_condition() -> RealEventCondition:
|
10
|
+
return RealEventCondition(
|
11
|
+
"First Condition",
|
12
|
+
RealEventCondition.Criteria.PositiveCrossing,
|
13
|
+
lambda state_vector, time: state_vector[0],
|
14
|
+
0.0,
|
15
|
+
)
|
16
16
|
|
17
17
|
|
18
18
|
@pytest.fixture
|
19
|
-
def second_condition() ->
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
def second_condition() -> RealEventCondition:
|
20
|
+
return RealEventCondition(
|
21
|
+
"Second condition",
|
22
|
+
RealEventCondition.Criteria.StrictlyNegative,
|
23
|
+
lambda state_vector, time: state_vector[1],
|
24
|
+
0.1,
|
25
|
+
)
|
25
26
|
|
26
27
|
|
27
28
|
@pytest.fixture
|
28
29
|
def event_conditions(
|
29
|
-
first_condition:
|
30
|
-
) -> list[
|
30
|
+
first_condition: RealEventCondition, second_condition: RealEventCondition
|
31
|
+
) -> list[RealEventCondition]:
|
31
32
|
return [first_condition, second_condition]
|
32
33
|
|
33
34
|
|
34
35
|
@pytest.fixture
|
35
|
-
def conjunction_condition(event_conditions: list[
|
36
|
+
def conjunction_condition(event_conditions: list[RealEventCondition]) -> Conjunctive:
|
36
37
|
return Conjunctive(event_conditions)
|
37
38
|
|
38
39
|
|
39
40
|
class TestConjunctiveCondition:
|
40
|
-
def test_constructor(self, event_conditions: list[
|
41
|
+
def test_constructor(self, event_conditions: list[RealEventCondition]):
|
41
42
|
assert Conjunctive(event_conditions) is not None
|
42
43
|
|
43
44
|
def test_is_satisfied(self, conjunction_condition: Conjunctive):
|
@@ -2,42 +2,43 @@
|
|
2
2
|
|
3
3
|
import pytest
|
4
4
|
|
5
|
-
from ostk.astrodynamics import
|
6
|
-
from ostk.astrodynamics.event_condition import Disjunctive
|
5
|
+
from ostk.astrodynamics.event_condition import Disjunctive, RealEventCondition
|
7
6
|
|
8
7
|
|
9
8
|
@pytest.fixture
|
10
|
-
def first_condition() ->
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
def first_condition() -> RealEventCondition:
|
10
|
+
return RealEventCondition(
|
11
|
+
"First Condition",
|
12
|
+
RealEventCondition.Criteria.PositiveCrossing,
|
13
|
+
lambda state_vector, time: state_vector[0],
|
14
|
+
0.0,
|
15
|
+
)
|
16
16
|
|
17
17
|
|
18
18
|
@pytest.fixture
|
19
|
-
def second_condition() ->
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
def second_condition() -> RealEventCondition:
|
20
|
+
return RealEventCondition(
|
21
|
+
"Second condition",
|
22
|
+
RealEventCondition.Criteria.StrictlyNegative,
|
23
|
+
lambda state_vector, time: state_vector[1],
|
24
|
+
0.1,
|
25
|
+
)
|
25
26
|
|
26
27
|
|
27
28
|
@pytest.fixture
|
28
29
|
def event_conditions(
|
29
|
-
first_condition:
|
30
|
-
) -> list[
|
30
|
+
first_condition: RealEventCondition, second_condition: RealEventCondition
|
31
|
+
) -> list[RealEventCondition]:
|
31
32
|
return [first_condition, second_condition]
|
32
33
|
|
33
34
|
|
34
35
|
@pytest.fixture
|
35
|
-
def disjunction_condition(event_conditions: list[
|
36
|
+
def disjunction_condition(event_conditions: list[RealEventCondition]) -> Disjunctive:
|
36
37
|
return Disjunctive(event_conditions)
|
37
38
|
|
38
39
|
|
39
40
|
class TestDisjunctiveCondition:
|
40
|
-
def test_constructor(self, event_conditions: list[
|
41
|
+
def test_constructor(self, event_conditions: list[RealEventCondition]):
|
41
42
|
assert Disjunctive(event_conditions) is not None
|
42
43
|
|
43
44
|
def test_is_satisfied(self, disjunction_condition: Disjunctive):
|
@@ -9,8 +9,10 @@ from ostk.astrodynamics.event_condition import LogicalConnective
|
|
9
9
|
@pytest.fixture
|
10
10
|
def event_condition() -> EventCondition:
|
11
11
|
class MyCondition(EventCondition):
|
12
|
-
def
|
13
|
-
|
12
|
+
def is_satisfied(
|
13
|
+
self, current_state_vector, current_time, previous_state_vector, previous_time
|
14
|
+
):
|
15
|
+
return True
|
14
16
|
|
15
17
|
return MyCondition("My Condition", EventCondition.Criteria.StrictlyNegative)
|
16
18
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Apache License 2.0
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
from ostk.astrodynamics.event_condition import RealEventCondition
|
6
|
+
|
7
|
+
|
8
|
+
@pytest.fixture
|
9
|
+
def evaluator():
|
10
|
+
return lambda state_vector, time: time
|
11
|
+
|
12
|
+
|
13
|
+
@pytest.fixture
|
14
|
+
def target() -> float:
|
15
|
+
return 10.0
|
16
|
+
|
17
|
+
|
18
|
+
@pytest.fixture
|
19
|
+
def event_condition(evaluator, target: float) -> RealEventCondition:
|
20
|
+
return RealEventCondition(
|
21
|
+
"My Condition", RealEventCondition.Criteria.PositiveCrossing, evaluator, target
|
22
|
+
)
|
23
|
+
|
24
|
+
|
25
|
+
class TestRealEventCondition:
|
26
|
+
def test_get_target(self, event_condition: RealEventCondition, target: float):
|
27
|
+
assert event_condition.get_target() == target
|
28
|
+
|
29
|
+
def test_evaluate(self, event_condition: RealEventCondition):
|
30
|
+
assert event_condition.evaluate(state_vector=[0.0], time=10.0) is not None
|
31
|
+
|
32
|
+
def test_is_satisfied(self, event_condition: RealEventCondition):
|
33
|
+
assert (
|
34
|
+
event_condition.is_satisfied(
|
35
|
+
previous_state_vector=[-1.0],
|
36
|
+
previous_time=5.0,
|
37
|
+
current_state_vector=[1.0],
|
38
|
+
current_time=15.0,
|
39
|
+
)
|
40
|
+
== True
|
41
|
+
)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Apache License 2.0
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
from ostk.astrodynamics.flight.system import Dynamics
|
6
|
+
from ostk.astrodynamics.trajectory.state.coordinates_subset import CartesianPosition
|
7
|
+
|
8
|
+
|
9
|
+
@pytest.fixture
|
10
|
+
def name() -> str:
|
11
|
+
return "MyDynamics"
|
12
|
+
|
13
|
+
|
14
|
+
@pytest.fixture
|
15
|
+
def dynamics(name: str) -> Dynamics:
|
16
|
+
class MyDynamics(Dynamics):
|
17
|
+
def is_defined():
|
18
|
+
return True
|
19
|
+
|
20
|
+
def get_read_coordinates_subsets(self):
|
21
|
+
return [CartesianPosition.default()]
|
22
|
+
|
23
|
+
def get_write_coordinates_subsets(self):
|
24
|
+
return [CartesianPosition.default()]
|
25
|
+
|
26
|
+
def compute_contribution(self, instant, state_vector, frame):
|
27
|
+
return state_vector
|
28
|
+
|
29
|
+
return MyDynamics(name)
|
30
|
+
|
31
|
+
|
32
|
+
class TestDynamics:
|
33
|
+
def test_subclass(self, dynamics: Dynamics):
|
34
|
+
assert dynamics is not None
|
35
|
+
|
36
|
+
def test_get_name(self, dynamics: Dynamics, name: str):
|
37
|
+
assert dynamics.get_name() == name
|
@@ -18,26 +18,14 @@ def criteria() -> EventCondition.Criteria:
|
|
18
18
|
@pytest.fixture
|
19
19
|
def event_condition(name: str, criteria: EventCondition.Criteria) -> EventCondition:
|
20
20
|
class MyEventCondition(EventCondition):
|
21
|
-
def
|
22
|
-
|
21
|
+
def is_satisfied(
|
22
|
+
self, current_state_vector, current_time, previous_state_vector, previous_time
|
23
|
+
):
|
24
|
+
return current_state_vector[0] > 0.0 and previous_state_vector[0] < 0.0
|
23
25
|
|
24
26
|
return MyEventCondition(name, criteria)
|
25
27
|
|
26
28
|
|
27
|
-
@pytest.fixture
|
28
|
-
def event_condition_overloaded() -> EventCondition:
|
29
|
-
class OverloadedEventCondition(EventCondition):
|
30
|
-
def is_satisfied(self, current_value, previous_value):
|
31
|
-
return (current_value > 0.0) and (previous_value < 0.0)
|
32
|
-
|
33
|
-
def evaluate(self, aStateVector, aTime):
|
34
|
-
return aStateVector[0]
|
35
|
-
|
36
|
-
return OverloadedEventCondition(
|
37
|
-
"OverloadedEventCondition", EventCondition.Criteria.Undefined
|
38
|
-
)
|
39
|
-
|
40
|
-
|
41
29
|
class TestEventCondition:
|
42
30
|
def test_subclass(self, event_condition: EventCondition):
|
43
31
|
assert event_condition is not None
|
@@ -52,18 +40,11 @@ class TestEventCondition:
|
|
52
40
|
|
53
41
|
def test_is_satisfied(self, event_condition: EventCondition):
|
54
42
|
assert (
|
55
|
-
event_condition.is_satisfied(
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
assert (
|
61
|
-
event_condition_overloaded.is_satisfied(
|
62
|
-
current_value=1.0, previous_value=-1.0
|
43
|
+
event_condition.is_satisfied(
|
44
|
+
previous_state_vector=[-1.0],
|
45
|
+
previous_time=0.0,
|
46
|
+
current_state_vector=[1.0],
|
47
|
+
current_time=1.0,
|
63
48
|
)
|
64
49
|
== True
|
65
50
|
)
|
66
|
-
assert (
|
67
|
-
event_condition_overloaded.is_satisfied(current_value=1.0, previous_value=1.0)
|
68
|
-
== False
|
69
|
-
)
|
@@ -5,7 +5,8 @@ import pytest
|
|
5
5
|
import numpy as np
|
6
6
|
import math
|
7
7
|
|
8
|
-
from ostk.astrodynamics import NumericalSolver
|
8
|
+
from ostk.astrodynamics import NumericalSolver
|
9
|
+
from ostk.astrodynamics.event_condition import RealEventCondition
|
9
10
|
|
10
11
|
|
11
12
|
def oscillator(x, dxdt, _):
|
@@ -24,16 +25,13 @@ def initial_state_vec() -> np.ndarray:
|
|
24
25
|
|
25
26
|
|
26
27
|
@pytest.fixture
|
27
|
-
def custom_condition() ->
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
return time - self._target
|
35
|
-
|
36
|
-
return CustomCondition(5.0, EventCondition.Criteria.StrictlyPositive)
|
28
|
+
def custom_condition() -> RealEventCondition:
|
29
|
+
return RealEventCondition(
|
30
|
+
"Custom",
|
31
|
+
RealEventCondition.Criteria.StrictlyPositive,
|
32
|
+
lambda state_vector, time: time,
|
33
|
+
5.0,
|
34
|
+
)
|
37
35
|
|
38
36
|
|
39
37
|
@pytest.fixture
|
@@ -87,6 +85,12 @@ class TestNumericalSolver:
|
|
87
85
|
assert numerical_solver == numerical_solver
|
88
86
|
assert (numerical_solver != numerical_solver) is False
|
89
87
|
|
88
|
+
def test_accessors(
|
89
|
+
self,
|
90
|
+
numerical_solver: NumericalSolver,
|
91
|
+
):
|
92
|
+
assert numerical_solver.access_observed_states() is not None
|
93
|
+
|
90
94
|
def test_get_types(
|
91
95
|
self,
|
92
96
|
numerical_solver_default_inputs: tuple[
|
@@ -108,6 +112,7 @@ class TestNumericalSolver:
|
|
108
112
|
assert numerical_solver.get_relative_tolerance() == relative_tolerance
|
109
113
|
assert numerical_solver.get_absolute_tolerance() == absolute_tolerance
|
110
114
|
assert numerical_solver.get_root_solver() is not None
|
115
|
+
assert numerical_solver.get_observed_states() is not None
|
111
116
|
|
112
117
|
def test_get_string_from_types(self):
|
113
118
|
assert (
|
@@ -191,7 +196,7 @@ class TestNumericalSolver:
|
|
191
196
|
self,
|
192
197
|
numerical_solver_conditional: NumericalSolver,
|
193
198
|
initial_state_vec: np.ndarray,
|
194
|
-
custom_condition:
|
199
|
+
custom_condition: RealEventCondition,
|
195
200
|
):
|
196
201
|
integration_duration: float = 100.0
|
197
202
|
|
@@ -207,7 +212,7 @@ class TestNumericalSolver:
|
|
207
212
|
|
208
213
|
state_vector, time = condition_solution.solution
|
209
214
|
|
210
|
-
assert abs(time - custom_condition.
|
215
|
+
assert abs(float(time - custom_condition.get_target())) < 1e-6
|
211
216
|
|
212
217
|
assert 5e-9 >= abs(state_vector[0] - math.sin(time))
|
213
218
|
assert 5e-9 >= abs(state_vector[1] - math.cos(time))
|
@@ -215,7 +220,7 @@ class TestNumericalSolver:
|
|
215
220
|
def test_integrate_time_with_condition(
|
216
221
|
self,
|
217
222
|
numerical_solver_conditional: NumericalSolver,
|
218
|
-
custom_condition:
|
223
|
+
custom_condition: RealEventCondition,
|
219
224
|
):
|
220
225
|
start_time: float = 500.0
|
221
226
|
end_time: float = start_time + 100.0
|
@@ -234,7 +239,7 @@ class TestNumericalSolver:
|
|
234
239
|
|
235
240
|
state_vector, time = condition_solution.solution
|
236
241
|
|
237
|
-
assert abs(time - start_time - custom_condition.
|
242
|
+
assert abs(float(time - start_time - custom_condition.get_target())) < 1e-6
|
238
243
|
|
239
244
|
assert 5e-9 >= abs(state_vector[0] - math.sin(time))
|
240
245
|
assert 5e-9 >= abs(state_vector[1] - math.cos(time))
|
@@ -242,6 +247,9 @@ class TestNumericalSolver:
|
|
242
247
|
def test_default(self):
|
243
248
|
assert NumericalSolver.default() is not None
|
244
249
|
|
250
|
+
def test_default_conditional(self):
|
251
|
+
assert NumericalSolver.default_conditional() is not None
|
252
|
+
|
245
253
|
def test_undefined(self):
|
246
254
|
assert NumericalSolver.undefined() is not None
|
247
255
|
assert NumericalSolver.undefined().is_defined() is False
|
@@ -105,3 +105,8 @@ def test_trajectory_orbit_models_kepler_coe_static_methods():
|
|
105
105
|
assert (
|
106
106
|
COE.eccentric_anomaly_from_mean_anomaly(Angle.degrees(0.0), 0.0, 0.0) is not None
|
107
107
|
)
|
108
|
+
|
109
|
+
|
110
|
+
def test_string_from_element():
|
111
|
+
element_str = COE.string_from_element(COE.Element.SemiMajorAxis)
|
112
|
+
assert element_str == "SemiMajorAxis"
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# Apache License 2.0
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
from ostk.physics.time import Instant
|
6
|
+
from ostk.physics.coordinate import Frame
|
7
|
+
|
8
|
+
from ostk.astrodynamics.trajectory.state import CoordinatesBroker, CoordinatesSubset
|
9
|
+
from ostk.astrodynamics.trajectory.state.coordinates_subset import CartesianPosition
|
10
|
+
|
11
|
+
|
12
|
+
@pytest.fixture
|
13
|
+
def name() -> str:
|
14
|
+
return "Position"
|
15
|
+
|
16
|
+
|
17
|
+
@pytest.fixture
|
18
|
+
def cartesian_position() -> CartesianPosition:
|
19
|
+
return CartesianPosition.default()
|
20
|
+
|
21
|
+
|
22
|
+
@pytest.fixture
|
23
|
+
def coordinates_subsets(cartesian_position: CartesianPosition) -> list[CoordinatesSubset]:
|
24
|
+
return [cartesian_position]
|
25
|
+
|
26
|
+
|
27
|
+
@pytest.fixture
|
28
|
+
def instant() -> Instant:
|
29
|
+
return Instant.J2000()
|
30
|
+
|
31
|
+
|
32
|
+
@pytest.fixture
|
33
|
+
def frame() -> Frame:
|
34
|
+
return Frame.GCRF()
|
35
|
+
|
36
|
+
|
37
|
+
@pytest.fixture
|
38
|
+
def coordinates_broker(coordinates_subsets: list[CoordinatesSubset]) -> CoordinatesBroker:
|
39
|
+
return CoordinatesBroker(coordinates_subsets)
|
40
|
+
|
41
|
+
|
42
|
+
@pytest.fixture
|
43
|
+
def coordinates() -> list[float]:
|
44
|
+
return [7000000.0, 0.0, 0.0]
|
45
|
+
|
46
|
+
|
47
|
+
@pytest.fixture
|
48
|
+
def another_coordinates() -> list[float]:
|
49
|
+
return [0.0, 7000000.0, 0.0]
|
50
|
+
|
51
|
+
|
52
|
+
class TestCoordinatesSubset:
|
53
|
+
def test_constructor(self, name: str):
|
54
|
+
assert CartesianPosition(name) is not None
|
55
|
+
|
56
|
+
def test_add(
|
57
|
+
self,
|
58
|
+
cartesian_position: CartesianPosition,
|
59
|
+
instant: Instant,
|
60
|
+
frame: Frame,
|
61
|
+
coordinates: list[float],
|
62
|
+
another_coordinates: list[float],
|
63
|
+
coordinates_broker: CoordinatesBroker,
|
64
|
+
):
|
65
|
+
assert all(
|
66
|
+
cartesian_position.add(
|
67
|
+
instant, coordinates, another_coordinates, frame, coordinates_broker
|
68
|
+
)
|
69
|
+
== [7000000.0, 7000000.0, 0.0]
|
70
|
+
)
|
71
|
+
|
72
|
+
def test_subtract(
|
73
|
+
self,
|
74
|
+
cartesian_position: CartesianPosition,
|
75
|
+
instant: Instant,
|
76
|
+
frame: Frame,
|
77
|
+
coordinates: list[float],
|
78
|
+
another_coordinates: list[float],
|
79
|
+
coordinates_broker: CoordinatesBroker,
|
80
|
+
):
|
81
|
+
assert all(
|
82
|
+
cartesian_position.subtract(
|
83
|
+
instant, coordinates, another_coordinates, frame, coordinates_broker
|
84
|
+
)
|
85
|
+
== [7000000.0, -7000000.0, 0.0]
|
86
|
+
)
|
87
|
+
|
88
|
+
def test_in_frame(
|
89
|
+
self,
|
90
|
+
cartesian_position: CartesianPosition,
|
91
|
+
instant: Instant,
|
92
|
+
frame: Frame,
|
93
|
+
coordinates: list[float],
|
94
|
+
another_coordinates: list[float],
|
95
|
+
coordinates_broker: CoordinatesBroker,
|
96
|
+
):
|
97
|
+
for value, expected in zip(
|
98
|
+
cartesian_position.in_frame(
|
99
|
+
instant, coordinates, frame, Frame.ITRF(), coordinates_broker
|
100
|
+
),
|
101
|
+
[1238864.12746338, 6889500.39136482, -176.262107699686],
|
102
|
+
):
|
103
|
+
assert value == pytest.approx(expected, rel=1e-14)
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# Apache License 2.0
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
from ostk.physics.time import Instant
|
6
|
+
from ostk.physics.coordinate import Frame
|
7
|
+
|
8
|
+
from ostk.astrodynamics.trajectory.state import CoordinatesBroker, CoordinatesSubset
|
9
|
+
from ostk.astrodynamics.trajectory.state.coordinates_subset import (
|
10
|
+
CartesianVelocity,
|
11
|
+
CartesianPosition,
|
12
|
+
)
|
13
|
+
|
14
|
+
|
15
|
+
@pytest.fixture
|
16
|
+
def name() -> str:
|
17
|
+
return "Position"
|
18
|
+
|
19
|
+
|
20
|
+
@pytest.fixture
|
21
|
+
def cartesian_position() -> CartesianPosition:
|
22
|
+
return CartesianPosition.default()
|
23
|
+
|
24
|
+
|
25
|
+
@pytest.fixture
|
26
|
+
def cartesian_velocity() -> CartesianVelocity:
|
27
|
+
return CartesianVelocity.default()
|
28
|
+
|
29
|
+
|
30
|
+
@pytest.fixture
|
31
|
+
def coordinates_subsets(
|
32
|
+
cartesian_position: CartesianPosition, cartesian_velocity: CartesianVelocity
|
33
|
+
) -> list[CoordinatesSubset]:
|
34
|
+
return [cartesian_position, cartesian_velocity]
|
35
|
+
|
36
|
+
|
37
|
+
@pytest.fixture
|
38
|
+
def instant() -> Instant:
|
39
|
+
return Instant.J2000()
|
40
|
+
|
41
|
+
|
42
|
+
@pytest.fixture
|
43
|
+
def frame() -> Frame:
|
44
|
+
return Frame.GCRF()
|
45
|
+
|
46
|
+
|
47
|
+
@pytest.fixture
|
48
|
+
def coordinates_broker(coordinates_subsets: list[CoordinatesSubset]) -> CoordinatesBroker:
|
49
|
+
return CoordinatesBroker(coordinates_subsets)
|
50
|
+
|
51
|
+
|
52
|
+
@pytest.fixture
|
53
|
+
def coordinates() -> list[float]:
|
54
|
+
return [7000000.0, 0.0, 0.0, 0.0, 5335.865450622126, 5335.865450622126]
|
55
|
+
|
56
|
+
|
57
|
+
@pytest.fixture
|
58
|
+
def another_coordinates() -> list[float]:
|
59
|
+
return [0.0, 7000000.0, 0.0, 5335.865450622126, 0.0, 0.0]
|
60
|
+
|
61
|
+
|
62
|
+
class TestCoordinatesSubset:
|
63
|
+
def test_constructor(self, name: str):
|
64
|
+
assert CartesianVelocity(CartesianPosition.default(), name) is not None
|
65
|
+
|
66
|
+
def test_add(
|
67
|
+
self,
|
68
|
+
cartesian_velocity: CartesianVelocity,
|
69
|
+
instant: Instant,
|
70
|
+
frame: Frame,
|
71
|
+
coordinates: list[float],
|
72
|
+
another_coordinates: list[float],
|
73
|
+
coordinates_broker: CoordinatesBroker,
|
74
|
+
):
|
75
|
+
assert all(
|
76
|
+
cartesian_velocity.add(
|
77
|
+
instant, coordinates, another_coordinates, frame, coordinates_broker
|
78
|
+
)
|
79
|
+
== [5335.865450622126, 5335.865450622126, 5335.865450622126]
|
80
|
+
)
|
81
|
+
|
82
|
+
def test_subtract(
|
83
|
+
self,
|
84
|
+
cartesian_velocity: CartesianVelocity,
|
85
|
+
instant: Instant,
|
86
|
+
frame: Frame,
|
87
|
+
coordinates: list[float],
|
88
|
+
another_coordinates: list[float],
|
89
|
+
coordinates_broker: CoordinatesBroker,
|
90
|
+
):
|
91
|
+
assert all(
|
92
|
+
cartesian_velocity.subtract(
|
93
|
+
instant, coordinates, another_coordinates, frame, coordinates_broker
|
94
|
+
)
|
95
|
+
== [-5335.865450622126, 5335.865450622126, 5335.865450622126]
|
96
|
+
)
|
97
|
+
|
98
|
+
def test_in_frame(
|
99
|
+
self,
|
100
|
+
cartesian_velocity: CartesianVelocity,
|
101
|
+
instant: Instant,
|
102
|
+
frame: Frame,
|
103
|
+
coordinates: list[float],
|
104
|
+
another_coordinates: list[float],
|
105
|
+
coordinates_broker: CoordinatesBroker,
|
106
|
+
):
|
107
|
+
for value, expected in zip(
|
108
|
+
cartesian_velocity.in_frame(
|
109
|
+
instant, coordinates, frame, Frame.ITRF(), coordinates_broker
|
110
|
+
),
|
111
|
+
[-4749.36551256577, 854.163395375881, 5335.71857543495],
|
112
|
+
):
|
113
|
+
assert value == pytest.approx(expected, rel=1e-14)
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# Apache License 2.0
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
from ostk.astrodynamics.trajectory.state import CoordinatesBroker, CoordinatesSubset
|
6
|
+
|
7
|
+
|
8
|
+
@pytest.fixture
|
9
|
+
def coordinates_subsets() -> list:
|
10
|
+
return [CoordinatesSubset("Subset1", 2), CoordinatesSubset("Subset2", 3)]
|
11
|
+
|
12
|
+
|
13
|
+
@pytest.fixture
|
14
|
+
def coordinates_broker(coordinates_subsets) -> CoordinatesBroker:
|
15
|
+
return CoordinatesBroker(coordinates_subsets)
|
16
|
+
|
17
|
+
|
18
|
+
@pytest.fixture
|
19
|
+
def coordinates() -> list[float]:
|
20
|
+
return [1.0, 2.0, 3.0, 4.0, 5.0]
|
21
|
+
|
22
|
+
|
23
|
+
class TestCoordinatesBroker:
|
24
|
+
def test_constructor(self, coordinates_broker: CoordinatesBroker):
|
25
|
+
assert coordinates_broker is not None
|
26
|
+
|
27
|
+
def test_eq(self, coordinates_broker: CoordinatesBroker):
|
28
|
+
assert coordinates_broker == coordinates_broker
|
29
|
+
|
30
|
+
def test_ne(self, coordinates_broker: CoordinatesBroker):
|
31
|
+
assert (coordinates_broker != coordinates_broker) == False
|
32
|
+
|
33
|
+
def test_access_subsets(
|
34
|
+
self, coordinates_broker: CoordinatesBroker, coordinates_subsets: list
|
35
|
+
):
|
36
|
+
assert coordinates_broker.access_subsets() == coordinates_subsets
|
37
|
+
|
38
|
+
def test_get_number_of_coordinates(self, coordinates_broker: CoordinatesBroker):
|
39
|
+
assert coordinates_broker.get_number_of_coordinates() == 5
|
40
|
+
|
41
|
+
def test_get_number_of_subsets(self, coordinates_broker: CoordinatesBroker):
|
42
|
+
assert coordinates_broker.get_number_of_subsets() == 2
|
43
|
+
|
44
|
+
def test_get_subsets(
|
45
|
+
self, coordinates_broker: CoordinatesBroker, coordinates_subsets: list
|
46
|
+
):
|
47
|
+
assert coordinates_broker.get_subsets() == coordinates_subsets
|
48
|
+
|
49
|
+
def test_add_subset(self, coordinates_broker: CoordinatesBroker):
|
50
|
+
new_subset = CoordinatesSubset("NewSubset", 4)
|
51
|
+
number_of_coordinates = coordinates_broker.get_number_of_coordinates()
|
52
|
+
assert coordinates_broker.add_subset(new_subset) == number_of_coordinates
|
53
|
+
assert coordinates_broker.has_subset(new_subset)
|
54
|
+
|
55
|
+
def test_has_subset(
|
56
|
+
self, coordinates_broker: CoordinatesBroker, coordinates_subsets: list
|
57
|
+
):
|
58
|
+
assert coordinates_broker.has_subset(coordinates_subsets[0])
|
59
|
+
|
60
|
+
def extract_coordinates(
|
61
|
+
self,
|
62
|
+
coordinates_broker: CoordinatesBroker,
|
63
|
+
coordinates: list[float],
|
64
|
+
coordinates_subsets: list[CoordinatesSubset],
|
65
|
+
):
|
66
|
+
assert coordinates_broker.extract_coordinates(
|
67
|
+
coordinates, coordinates_subsets[0]
|
68
|
+
) == [1.0, 2.0]
|
69
|
+
assert coordinates_broker.extract_coordinates(
|
70
|
+
coordinates, coordinates_subsets[1]
|
71
|
+
) == [3.0, 4.0, 5.0]
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Apache License 2.0
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
from ostk.astrodynamics.trajectory.state import CoordinatesSubset
|
6
|
+
|
7
|
+
|
8
|
+
@pytest.fixture
|
9
|
+
def name() -> str:
|
10
|
+
return "MySubset"
|
11
|
+
|
12
|
+
|
13
|
+
@pytest.fixture
|
14
|
+
def size() -> int:
|
15
|
+
return 3
|
16
|
+
|
17
|
+
|
18
|
+
@pytest.fixture
|
19
|
+
def coordinates_subset(name: str, size: int) -> CoordinatesSubset:
|
20
|
+
return CoordinatesSubset(name, size)
|
21
|
+
|
22
|
+
|
23
|
+
class TestCoordinatesSubset:
|
24
|
+
def test_constructor(self, coordinates_subset: CoordinatesSubset):
|
25
|
+
assert coordinates_subset is not None
|
26
|
+
|
27
|
+
def test_eq(self, coordinates_subset: CoordinatesSubset):
|
28
|
+
assert coordinates_subset == coordinates_subset
|
29
|
+
|
30
|
+
def test_ne(self, coordinates_subset: CoordinatesSubset):
|
31
|
+
assert (coordinates_subset != coordinates_subset) == False
|
32
|
+
|
33
|
+
def test_get_id(self, coordinates_subset: CoordinatesSubset):
|
34
|
+
assert coordinates_subset.get_id() is not None
|
35
|
+
|
36
|
+
def test_get_name(self, coordinates_subset: CoordinatesSubset, name: str):
|
37
|
+
assert coordinates_subset.get_name() == name
|
38
|
+
|
39
|
+
def test_get_size(self, coordinates_subset: CoordinatesSubset, size: int):
|
40
|
+
assert coordinates_subset.get_size() == size
|
41
|
+
|
42
|
+
def test_mass(self):
|
43
|
+
assert CoordinatesSubset.mass() is not None
|
@@ -13,6 +13,7 @@ from ostk.physics.units import Mass
|
|
13
13
|
from ostk.physics.time import Instant
|
14
14
|
from ostk.physics.time import DateTime
|
15
15
|
from ostk.physics.time import Scale
|
16
|
+
from ostk.physics.time import Duration
|
16
17
|
from ostk.physics.coordinate import Position
|
17
18
|
from ostk.physics.coordinate import Velocity
|
18
19
|
from ostk.physics.coordinate import Frame
|
@@ -25,7 +26,7 @@ from ostk.astrodynamics.flight.system.dynamics import CentralBodyGravity
|
|
25
26
|
from ostk.astrodynamics.flight.system.dynamics import PositionDerivative
|
26
27
|
from ostk.astrodynamics.trajectory import State
|
27
28
|
from ostk.astrodynamics.trajectory import Propagator
|
28
|
-
from ostk.astrodynamics import
|
29
|
+
from ostk.astrodynamics.event_condition import DurationCondition
|
29
30
|
|
30
31
|
|
31
32
|
@pytest.fixture
|
@@ -104,12 +105,10 @@ def conditional_numerical_solver() -> NumericalSolver:
|
|
104
105
|
|
105
106
|
|
106
107
|
@pytest.fixture
|
107
|
-
def event_condition() ->
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
return MyEventCondition("42 Seconds", EventCondition.Criteria.StrictlyPositive)
|
108
|
+
def event_condition() -> DurationCondition:
|
109
|
+
return DurationCondition(
|
110
|
+
DurationCondition.Criteria.StrictlyPositive, Duration.seconds(42.0)
|
111
|
+
)
|
113
112
|
|
114
113
|
|
115
114
|
@pytest.fixture
|
@@ -123,6 +122,11 @@ class TestPropagator:
|
|
123
122
|
assert isinstance(propagator, Propagator)
|
124
123
|
assert propagator.is_defined()
|
125
124
|
|
125
|
+
def test_access_numerical_solver(
|
126
|
+
self, propagator: Propagator, numerical_solver: NumericalSolver
|
127
|
+
):
|
128
|
+
assert propagator.access_numerical_solver() == numerical_solver
|
129
|
+
|
126
130
|
def test_get_dynamics(self, propagator: Propagator, dynamics: list):
|
127
131
|
assert propagator.get_dynamics() == dynamics
|
128
132
|
|
@@ -186,7 +190,7 @@ class TestPropagator:
|
|
186
190
|
conditional_numerical_solver: NumericalSolver,
|
187
191
|
dynamics: list[Dynamics],
|
188
192
|
state: State,
|
189
|
-
event_condition:
|
193
|
+
event_condition: DurationCondition,
|
190
194
|
):
|
191
195
|
propagator: Propagator = Propagator(conditional_numerical_solver, dynamics)
|
192
196
|
|
@@ -12,26 +12,77 @@ from ostk.physics.coordinate import Velocity
|
|
12
12
|
from ostk.physics.coordinate import Frame
|
13
13
|
|
14
14
|
from ostk.astrodynamics.trajectory import State
|
15
|
+
from ostk.astrodynamics.trajectory.state import CoordinatesBroker
|
16
|
+
from ostk.astrodynamics.trajectory.state.coordinates_subset import (
|
17
|
+
CartesianPosition,
|
18
|
+
CartesianVelocity,
|
19
|
+
)
|
20
|
+
|
21
|
+
|
22
|
+
@pytest.fixture()
|
23
|
+
def instant() -> Instant:
|
24
|
+
return Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC)
|
15
25
|
|
16
26
|
|
17
27
|
@pytest.fixture
|
18
|
-
def
|
19
|
-
|
20
|
-
|
21
|
-
velocity: Velocity = Velocity.meters_per_second([7600.0, 0.0, 0.0], frame)
|
28
|
+
def frame() -> Frame:
|
29
|
+
return Frame.GCRF()
|
30
|
+
|
22
31
|
|
23
|
-
|
32
|
+
@pytest.fixture()
|
33
|
+
def position(frame: Frame) -> Position:
|
34
|
+
return Position.meters([6371000.0, 0.0, 0.0], frame)
|
24
35
|
|
25
|
-
|
36
|
+
|
37
|
+
@pytest.fixture()
|
38
|
+
def velocity(frame: Frame) -> Velocity:
|
39
|
+
return Velocity.meters_per_second([7600.0, 0.0, 0.0], frame)
|
26
40
|
|
27
41
|
|
28
42
|
@pytest.fixture
|
29
|
-
def state(
|
30
|
-
|
43
|
+
def state(
|
44
|
+
instant: Instant, position: Position, velocity: Velocity, frame: Frame
|
45
|
+
) -> State:
|
46
|
+
return State(instant, position, velocity)
|
47
|
+
|
48
|
+
|
49
|
+
@pytest.fixture
|
50
|
+
def coordinates_broker() -> CoordinatesBroker:
|
51
|
+
return CoordinatesBroker([CartesianPosition.default(), CartesianVelocity.default()])
|
31
52
|
|
32
53
|
|
33
54
|
class TestState:
|
34
|
-
def test_constructor(
|
55
|
+
def test_constructor(
|
56
|
+
self,
|
57
|
+
instant: Instant,
|
58
|
+
position: Position,
|
59
|
+
velocity: Velocity,
|
60
|
+
):
|
61
|
+
state = State(instant, position, velocity)
|
62
|
+
assert state is not None
|
63
|
+
assert isinstance(state, State)
|
64
|
+
assert state.is_defined()
|
65
|
+
|
66
|
+
def test_explicit_constructor(
|
67
|
+
self,
|
68
|
+
instant: Instant,
|
69
|
+
position: Position,
|
70
|
+
velocity: Velocity,
|
71
|
+
frame: Frame,
|
72
|
+
coordinates_broker: CoordinatesBroker,
|
73
|
+
):
|
74
|
+
state = State(instant, position, velocity)
|
75
|
+
assert state is not None
|
76
|
+
assert isinstance(state, State)
|
77
|
+
assert state.is_defined()
|
78
|
+
|
79
|
+
state = State(
|
80
|
+
instant,
|
81
|
+
np.append(position.get_coordinates(), velocity.get_coordinates()),
|
82
|
+
frame,
|
83
|
+
coordinates_broker,
|
84
|
+
)
|
85
|
+
|
35
86
|
assert state is not None
|
36
87
|
assert isinstance(state, State)
|
37
88
|
assert state.is_defined()
|
@@ -47,13 +98,15 @@ class TestState:
|
|
47
98
|
def test_getters(
|
48
99
|
self,
|
49
100
|
state: State,
|
50
|
-
|
101
|
+
instant: Instant,
|
102
|
+
position: Position,
|
103
|
+
velocity: Velocity,
|
104
|
+
frame: Frame,
|
51
105
|
):
|
52
|
-
(instant, position, velocity, _) = state_default_inputs
|
53
|
-
|
54
106
|
assert state.get_instant() == instant
|
55
107
|
assert state.get_position() == position
|
56
108
|
assert state.get_velocity() == velocity
|
109
|
+
assert state.get_frame() == frame
|
57
110
|
assert (
|
58
111
|
state.get_coordinates()
|
59
112
|
== np.append(position.get_coordinates(), velocity.get_coordinates())
|
@@ -62,9 +115,7 @@ class TestState:
|
|
62
115
|
def test_in_frame(
|
63
116
|
self,
|
64
117
|
state: State,
|
65
|
-
|
118
|
+
frame: Frame,
|
66
119
|
):
|
67
|
-
(_, _, _, frame) = state_default_inputs
|
68
|
-
|
69
120
|
assert state.in_frame(frame) == state
|
70
121
|
assert state.in_frame(Frame.ITRF()) != state
|
ostk/astrodynamics/viewer.py
CHANGED
@@ -303,7 +303,7 @@ def _cesium_from_ostk_sensor(sensor: Sensor) -> cesiumpy.ConicSensor:
|
|
303
303
|
return cesiumpy.ConicSensor(
|
304
304
|
name=sensor.name,
|
305
305
|
direction=cesiumpy.Cartesian3(*sensor.direction),
|
306
|
-
half_angle=
|
306
|
+
half_angle=float(sensor.half_angle.in_radians()),
|
307
307
|
length=float(sensor.length.in_meters()),
|
308
308
|
material=sensor.color or cesiumpy.color.RED,
|
309
309
|
)
|
File without changes
|
File without changes
|
File without changes
|