open-space-toolkit-astrodynamics 15.1.0__py312-none-manylinux2014_x86_64.whl → 15.2.1__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.
- {open_space_toolkit_astrodynamics-15.1.0.dist-info → open_space_toolkit_astrodynamics-15.2.1.dist-info}/METADATA +1 -1
- {open_space_toolkit_astrodynamics-15.1.0.dist-info → open_space_toolkit_astrodynamics-15.2.1.dist-info}/RECORD +16 -12
- ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-312-x86_64-linux-gnu.so +0 -0
- ostk/astrodynamics/__init__.pyi +6 -5
- ostk/astrodynamics/access.pyi +13 -0
- ostk/astrodynamics/estimator.pyi +280 -0
- ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.15 +0 -0
- ostk/astrodynamics/solver.pyi +209 -1
- ostk/astrodynamics/test/access/test_visibility_criterion.py +3 -0
- ostk/astrodynamics/test/estimator/test_orbit_determination_solver.py +261 -0
- ostk/astrodynamics/test/estimator/test_tle_solver.py +215 -0
- ostk/astrodynamics/test/solvers/test_least_squares_solver.py +334 -0
- ostk/astrodynamics/utilities.py +9 -8
- {open_space_toolkit_astrodynamics-15.1.0.dist-info → open_space_toolkit_astrodynamics-15.2.1.dist-info}/WHEEL +0 -0
- {open_space_toolkit_astrodynamics-15.1.0.dist-info → open_space_toolkit_astrodynamics-15.2.1.dist-info}/top_level.txt +0 -0
- {open_space_toolkit_astrodynamics-15.1.0.dist-info → open_space_toolkit_astrodynamics-15.2.1.dist-info}/zip-safe +0 -0
ostk/astrodynamics/solver.pyi
CHANGED
@@ -3,7 +3,7 @@ import numpy
|
|
3
3
|
import ostk.core.type
|
4
4
|
import ostk.physics.time
|
5
5
|
import typing
|
6
|
-
__all__ = ['FiniteDifferenceSolver', 'TemporalConditionSolver']
|
6
|
+
__all__ = ['FiniteDifferenceSolver', 'LeastSquaresSolver', 'TemporalConditionSolver']
|
7
7
|
class FiniteDifferenceSolver:
|
8
8
|
"""
|
9
9
|
|
@@ -166,6 +166,214 @@ class FiniteDifferenceSolver:
|
|
166
166
|
Returns:
|
167
167
|
FiniteDifferenceSolver.Type: The type.
|
168
168
|
"""
|
169
|
+
class LeastSquaresSolver:
|
170
|
+
"""
|
171
|
+
|
172
|
+
Class to solve non-linear least squares problems.
|
173
|
+
|
174
|
+
"""
|
175
|
+
class Analysis:
|
176
|
+
"""
|
177
|
+
|
178
|
+
Class representing the analysis of the least squares solver.
|
179
|
+
|
180
|
+
"""
|
181
|
+
@staticmethod
|
182
|
+
def _pybind11_conduit_v1_(*args, **kwargs):
|
183
|
+
...
|
184
|
+
def __init__(self, termination_criteria: ostk.core.type.String, estimated_state: typing.Any, estimated_covariance: numpy.ndarray[numpy.float64[m, n]], estimated_frisbee_covariance: numpy.ndarray[numpy.float64[m, n]], computed_observations: list[...], steps: list[LeastSquaresSolver.Step]) -> None:
|
185
|
+
"""
|
186
|
+
Constructor.
|
187
|
+
|
188
|
+
Args:
|
189
|
+
termination_criteria (str): The termination criteria.
|
190
|
+
estimated_state (State): The estimated state.
|
191
|
+
estimated_covariance (np.ndarray): The estimated covariance matrix.
|
192
|
+
estimated_frisbee_covariance (np.ndarray): The estimated Frisbee covariance matrix.
|
193
|
+
computed_observations (list[State]): The computed observations of the final iteration.
|
194
|
+
steps (list[LeastSquaresSolver.Step]): The steps.
|
195
|
+
"""
|
196
|
+
def __repr__(self) -> str:
|
197
|
+
...
|
198
|
+
def __str__(self) -> str:
|
199
|
+
...
|
200
|
+
def compute_residual_states(self, observations: list[...]) -> list[...]:
|
201
|
+
"""
|
202
|
+
Compute the residual states.
|
203
|
+
|
204
|
+
Args:
|
205
|
+
observations (list[State]): The observations.
|
206
|
+
|
207
|
+
Returns:
|
208
|
+
list[State]: The residuals.
|
209
|
+
"""
|
210
|
+
@property
|
211
|
+
def computed_observations(self) -> list[...]:
|
212
|
+
"""
|
213
|
+
The computed observations of the final iteration.
|
214
|
+
|
215
|
+
:type: np.ndarray
|
216
|
+
"""
|
217
|
+
@property
|
218
|
+
def estimated_covariance(self) -> numpy.ndarray[numpy.float64[m, n]]:
|
219
|
+
"""
|
220
|
+
The estimated covariance matrix.
|
221
|
+
|
222
|
+
:type: np.ndarray
|
223
|
+
"""
|
224
|
+
@property
|
225
|
+
def estimated_frisbee_covariance(self) -> numpy.ndarray[numpy.float64[m, n]]:
|
226
|
+
"""
|
227
|
+
The estimated Frisbee covariance matrix.
|
228
|
+
|
229
|
+
:type: np.ndarray
|
230
|
+
"""
|
231
|
+
@property
|
232
|
+
def estimated_state(self) -> ...:
|
233
|
+
"""
|
234
|
+
The estimated state.
|
235
|
+
|
236
|
+
:type: State
|
237
|
+
"""
|
238
|
+
@property
|
239
|
+
def iteration_count(self) -> int:
|
240
|
+
"""
|
241
|
+
The iteration count.
|
242
|
+
|
243
|
+
:type: int
|
244
|
+
"""
|
245
|
+
@property
|
246
|
+
def observation_count(self) -> int:
|
247
|
+
"""
|
248
|
+
The observation count.
|
249
|
+
|
250
|
+
:type: int
|
251
|
+
"""
|
252
|
+
@property
|
253
|
+
def rms_error(self) -> ostk.core.type.Real:
|
254
|
+
"""
|
255
|
+
The RMS error.
|
256
|
+
|
257
|
+
:type: float
|
258
|
+
"""
|
259
|
+
@property
|
260
|
+
def steps(self) -> list[LeastSquaresSolver.Step]:
|
261
|
+
"""
|
262
|
+
The steps.
|
263
|
+
|
264
|
+
:type: list[LeastSquaresSolver.Step]
|
265
|
+
"""
|
266
|
+
@property
|
267
|
+
def termination_criteria(self) -> ostk.core.type.String:
|
268
|
+
"""
|
269
|
+
The termination criteria.
|
270
|
+
|
271
|
+
:type: str
|
272
|
+
"""
|
273
|
+
class Step:
|
274
|
+
"""
|
275
|
+
|
276
|
+
Class representing a step in the least squares solver.
|
277
|
+
|
278
|
+
"""
|
279
|
+
@staticmethod
|
280
|
+
def _pybind11_conduit_v1_(*args, **kwargs):
|
281
|
+
...
|
282
|
+
def __init__(self, rms_error: ostk.core.type.Real, x_hat: numpy.ndarray[numpy.float64[m, 1]]) -> None:
|
283
|
+
"""
|
284
|
+
Constructor.
|
285
|
+
|
286
|
+
Args:
|
287
|
+
rms_error (float): The RMS error.
|
288
|
+
x_hat (np.ndarray): The X hat vector.
|
289
|
+
"""
|
290
|
+
def __repr__(self) -> str:
|
291
|
+
...
|
292
|
+
def __str__(self) -> str:
|
293
|
+
...
|
294
|
+
@property
|
295
|
+
def rms_error(self) -> ostk.core.type.Real:
|
296
|
+
"""
|
297
|
+
The RMS error.
|
298
|
+
|
299
|
+
:type: float
|
300
|
+
"""
|
301
|
+
@property
|
302
|
+
def x_hat(self) -> numpy.ndarray[numpy.float64[m, 1]]:
|
303
|
+
"""
|
304
|
+
The X hat vector.
|
305
|
+
|
306
|
+
:type: np.ndarray
|
307
|
+
"""
|
308
|
+
@staticmethod
|
309
|
+
def _pybind11_conduit_v1_(*args, **kwargs):
|
310
|
+
...
|
311
|
+
@staticmethod
|
312
|
+
def calculate_empirical_covariance(residuals: list[...]) -> numpy.ndarray[numpy.float64[m, n]]:
|
313
|
+
"""
|
314
|
+
Calculate the empirical covariance matrix from an array of state residuals.
|
315
|
+
|
316
|
+
Args:
|
317
|
+
residuals (list[State]): A list of state residuals.
|
318
|
+
|
319
|
+
Returns:
|
320
|
+
np.ndarray: The empirical covariance matrix.
|
321
|
+
|
322
|
+
Throws:
|
323
|
+
ostk::core::error::runtime::Undefined: If the residual array is empty.
|
324
|
+
"""
|
325
|
+
@staticmethod
|
326
|
+
def default() -> LeastSquaresSolver:
|
327
|
+
"""
|
328
|
+
Create a default instance of LeastSquaresSolver.
|
329
|
+
|
330
|
+
Returns:
|
331
|
+
LeastSquaresSolver: A default instance of LeastSquaresSolver.
|
332
|
+
"""
|
333
|
+
def __init__(self, maximum_iteration_count: int, rms_update_threshold: ostk.core.type.Real, finite_difference_solver: FiniteDifferenceSolver = ...) -> None:
|
334
|
+
"""
|
335
|
+
Constructor.
|
336
|
+
|
337
|
+
Args:
|
338
|
+
maximum_iteration_count (int): Maximum number of iterations.
|
339
|
+
rms_update_threshold (float): Minimum RMS threshold.
|
340
|
+
finite_difference_solver (FiniteDifferenceSolver): Finite difference solver. Defaults to FiniteDifferenceSolver.Default().
|
341
|
+
"""
|
342
|
+
def get_finite_difference_solver(self) -> FiniteDifferenceSolver:
|
343
|
+
"""
|
344
|
+
Get the finite difference solver.
|
345
|
+
|
346
|
+
Returns:
|
347
|
+
FiniteDifferenceSolver: The finite difference solver.
|
348
|
+
"""
|
349
|
+
def get_max_iteration_count(self) -> int:
|
350
|
+
"""
|
351
|
+
Get the maximum iteration count.
|
352
|
+
|
353
|
+
Returns:
|
354
|
+
int: The maximum iteration count.
|
355
|
+
"""
|
356
|
+
def get_rms_update_threshold(self) -> ostk.core.type.Real:
|
357
|
+
"""
|
358
|
+
Get the RMS update threshold.
|
359
|
+
|
360
|
+
Returns:
|
361
|
+
float: The RMS update threshold.
|
362
|
+
"""
|
363
|
+
def solve(self, initial_guess: typing.Any, observations: list[...], state_generator: typing.Callable[[..., list[ostk.physics.time.Instant]], list[...]], initial_guess_sigmas: dict[..., numpy.ndarray[numpy.float64[m, 1]]] = {}, observation_sigmas: dict[..., numpy.ndarray[numpy.float64[m, 1]]] = {}) -> LeastSquaresSolver.Analysis:
|
364
|
+
"""
|
365
|
+
Solve the non-linear least squares problem.
|
366
|
+
|
367
|
+
Args:
|
368
|
+
initial_guess (State): Initial guess state (the Estimated State is of the same domain as this state).
|
369
|
+
observations (list[State]): List of observations.
|
370
|
+
state_generator (callable[list[State],[State, list[Instant]]]): Function to generate states.
|
371
|
+
initial_guess_sigmas (dict[CoordinateSubset, np.ndarray], optional): Dictionary of sigmas for initial guess.
|
372
|
+
observation_sigmas (dict[CoordinateSubset, np.ndarray], optional): Dictionary of sigmas for observations.
|
373
|
+
|
374
|
+
Returns:
|
375
|
+
LeastSquaresSolver::Analysis: The analysis of the estimate.
|
376
|
+
"""
|
169
377
|
class TemporalConditionSolver:
|
170
378
|
"""
|
171
379
|
|
@@ -9,6 +9,7 @@ from ostk.physics import Environment
|
|
9
9
|
from ostk.physics.time import Instant
|
10
10
|
from ostk.physics.time import DateTime
|
11
11
|
from ostk.physics.time import Scale
|
12
|
+
from ostk.physics.unit import Angle
|
12
13
|
|
13
14
|
from ostk.astrodynamics.access import VisibilityCriterion
|
14
15
|
|
@@ -152,9 +153,11 @@ class TestVisibilityCriterion:
|
|
152
153
|
elevation_criterion = VisibilityCriterion.ElevationInterval(elevation_interval)
|
153
154
|
elevation_valid = np.pi / 8 # 22.5 degrees
|
154
155
|
assert elevation_criterion.is_satisfied(elevation_valid) is True
|
156
|
+
assert elevation_criterion.is_satisfied(Angle.radians(elevation_valid)) is True
|
155
157
|
|
156
158
|
elevation_invalid = np.pi / 2 # 90 degrees
|
157
159
|
assert elevation_criterion.is_satisfied(elevation_invalid) is False
|
160
|
+
assert elevation_criterion.is_satisfied(Angle.radians(elevation_invalid)) is False
|
158
161
|
|
159
162
|
def test_line_of_sight_is_satisfied(
|
160
163
|
self,
|
@@ -0,0 +1,261 @@
|
|
1
|
+
# Apache License 2.0
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
import pandas as pd
|
6
|
+
|
7
|
+
import numpy as np
|
8
|
+
|
9
|
+
from ostk.physics import Environment
|
10
|
+
from ostk.physics.time import Instant
|
11
|
+
from ostk.physics.coordinate import Frame
|
12
|
+
from ostk.physics.environment.object.celestial import Earth
|
13
|
+
|
14
|
+
from ostk.astrodynamics.solver import LeastSquaresSolver
|
15
|
+
from ostk.astrodynamics.trajectory import State
|
16
|
+
from ostk.astrodynamics.trajectory import Orbit
|
17
|
+
from ostk.astrodynamics.trajectory import Propagator
|
18
|
+
from ostk.astrodynamics.trajectory.state import NumericalSolver
|
19
|
+
from ostk.astrodynamics.trajectory.state import CoordinateSubset
|
20
|
+
from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianPosition
|
21
|
+
from ostk.astrodynamics.trajectory.state.coordinate_subset import CartesianVelocity
|
22
|
+
from ostk.astrodynamics.estimator import OrbitDeterminationSolver
|
23
|
+
from ostk.astrodynamics.dataframe import generate_states_from_dataframe
|
24
|
+
|
25
|
+
|
26
|
+
@pytest.fixture
|
27
|
+
def environment() -> Environment:
|
28
|
+
return Environment(central_celestial_object=Earth.EGM96(10, 10), objects=[])
|
29
|
+
|
30
|
+
|
31
|
+
@pytest.fixture
|
32
|
+
def numerical_solver() -> NumericalSolver:
|
33
|
+
return NumericalSolver.default()
|
34
|
+
|
35
|
+
|
36
|
+
@pytest.fixture
|
37
|
+
def least_squares_solver() -> LeastSquaresSolver:
|
38
|
+
return LeastSquaresSolver.default()
|
39
|
+
|
40
|
+
|
41
|
+
@pytest.fixture
|
42
|
+
def orbit_determination_solver(
|
43
|
+
environment: Environment,
|
44
|
+
numerical_solver: NumericalSolver,
|
45
|
+
least_squares_solver: LeastSquaresSolver,
|
46
|
+
) -> OrbitDeterminationSolver:
|
47
|
+
return OrbitDeterminationSolver(
|
48
|
+
environment=environment,
|
49
|
+
numerical_solver=numerical_solver,
|
50
|
+
solver=least_squares_solver,
|
51
|
+
)
|
52
|
+
|
53
|
+
|
54
|
+
@pytest.fixture
|
55
|
+
def coordinate_subsets() -> list[CoordinateSubset]:
|
56
|
+
return [
|
57
|
+
CartesianPosition.default(),
|
58
|
+
CartesianVelocity.default(),
|
59
|
+
]
|
60
|
+
|
61
|
+
|
62
|
+
@pytest.fixture
|
63
|
+
def initial_guess(
|
64
|
+
observations: list[State],
|
65
|
+
) -> State:
|
66
|
+
return observations[0]
|
67
|
+
|
68
|
+
|
69
|
+
@pytest.fixture
|
70
|
+
def observations() -> list[State]:
|
71
|
+
return generate_states_from_dataframe(
|
72
|
+
pd.read_csv(
|
73
|
+
"/app/test/OpenSpaceToolkit/Astrodynamics/Estimator/OrbitDeterminationSolverData/gnss_data.csv"
|
74
|
+
),
|
75
|
+
reference_frame=Frame.ITRF(),
|
76
|
+
)
|
77
|
+
|
78
|
+
|
79
|
+
@pytest.fixture
|
80
|
+
def initial_guess_sigmas(
|
81
|
+
coordinate_subsets: list[CoordinateSubset],
|
82
|
+
) -> dict[CoordinateSubset, list[float]]:
|
83
|
+
return {
|
84
|
+
coordinate_subsets[0]: [1e-1, 1e-1, 1e-1],
|
85
|
+
coordinate_subsets[1]: [1e-2, 1e-2, 1e-2],
|
86
|
+
}
|
87
|
+
|
88
|
+
|
89
|
+
@pytest.fixture
|
90
|
+
def observation_sigmas(
|
91
|
+
coordinate_subsets: list[CoordinateSubset],
|
92
|
+
) -> dict[CoordinateSubset, list[float]]:
|
93
|
+
return {
|
94
|
+
coordinate_subsets[0]: [1e-1, 1e-1, 1e-1],
|
95
|
+
coordinate_subsets[1]: [1e-2, 1e-2, 1e-2],
|
96
|
+
}
|
97
|
+
|
98
|
+
|
99
|
+
@pytest.fixture
|
100
|
+
def rms_error() -> float:
|
101
|
+
return 1.0
|
102
|
+
|
103
|
+
|
104
|
+
@pytest.fixture
|
105
|
+
def x_hat() -> np.ndarray:
|
106
|
+
return np.array([1.0, 0.0])
|
107
|
+
|
108
|
+
|
109
|
+
@pytest.fixture
|
110
|
+
def step(
|
111
|
+
rms_error: float,
|
112
|
+
x_hat: np.ndarray,
|
113
|
+
) -> LeastSquaresSolver.Step:
|
114
|
+
return LeastSquaresSolver.Step(
|
115
|
+
rms_error=rms_error,
|
116
|
+
x_hat=x_hat,
|
117
|
+
)
|
118
|
+
|
119
|
+
|
120
|
+
@pytest.fixture
|
121
|
+
def observation_count() -> int:
|
122
|
+
return 5
|
123
|
+
|
124
|
+
|
125
|
+
@pytest.fixture
|
126
|
+
def termination_criteria() -> str:
|
127
|
+
return "RMS Update Threshold"
|
128
|
+
|
129
|
+
|
130
|
+
@pytest.fixture
|
131
|
+
def estimated_state() -> State:
|
132
|
+
return State(
|
133
|
+
Instant.J2000(),
|
134
|
+
[1.0, 0.0],
|
135
|
+
Frame.GCRF(),
|
136
|
+
[CoordinateSubset("Position", 1), CoordinateSubset("Velocity", 1)],
|
137
|
+
)
|
138
|
+
|
139
|
+
|
140
|
+
@pytest.fixture
|
141
|
+
def estimated_covariance() -> np.ndarray:
|
142
|
+
return np.array([[1.0, 0.0], [0.0, 1.0]])
|
143
|
+
|
144
|
+
|
145
|
+
@pytest.fixture
|
146
|
+
def estimated_frisbee_covariance() -> np.ndarray:
|
147
|
+
return np.array([[1.0, 0.0], [0.0, 1.0]])
|
148
|
+
|
149
|
+
|
150
|
+
@pytest.fixture
|
151
|
+
def computed_observations(
|
152
|
+
observations: list[State],
|
153
|
+
) -> list[State]:
|
154
|
+
return observations
|
155
|
+
|
156
|
+
|
157
|
+
@pytest.fixture
|
158
|
+
def steps(step: LeastSquaresSolver.Step) -> list[LeastSquaresSolver.Step]:
|
159
|
+
return [step]
|
160
|
+
|
161
|
+
|
162
|
+
@pytest.fixture
|
163
|
+
def solver_analysis(
|
164
|
+
termination_criteria: str,
|
165
|
+
estimated_state: State,
|
166
|
+
estimated_covariance: np.ndarray,
|
167
|
+
estimated_frisbee_covariance: np.ndarray,
|
168
|
+
computed_observations: list[State],
|
169
|
+
steps: list[LeastSquaresSolver.Step],
|
170
|
+
) -> LeastSquaresSolver.Analysis:
|
171
|
+
return LeastSquaresSolver.Analysis(
|
172
|
+
termination_criteria=termination_criteria,
|
173
|
+
estimated_state=estimated_state,
|
174
|
+
estimated_covariance=estimated_covariance,
|
175
|
+
estimated_frisbee_covariance=estimated_frisbee_covariance,
|
176
|
+
computed_observations=computed_observations,
|
177
|
+
steps=steps,
|
178
|
+
)
|
179
|
+
|
180
|
+
|
181
|
+
@pytest.fixture
|
182
|
+
def analysis(
|
183
|
+
initial_guess: State,
|
184
|
+
solver_analysis: LeastSquaresSolver.Analysis,
|
185
|
+
) -> OrbitDeterminationSolver.Analysis:
|
186
|
+
return OrbitDeterminationSolver.Analysis(
|
187
|
+
estimated_state=initial_guess,
|
188
|
+
solver_analysis=solver_analysis,
|
189
|
+
)
|
190
|
+
|
191
|
+
|
192
|
+
class TestOrbitDeterminationSolverAnalysis:
|
193
|
+
def test_constructor(
|
194
|
+
self,
|
195
|
+
analysis: OrbitDeterminationSolver.Analysis,
|
196
|
+
):
|
197
|
+
assert isinstance(analysis, OrbitDeterminationSolver.Analysis)
|
198
|
+
|
199
|
+
def test_properties(
|
200
|
+
self,
|
201
|
+
analysis: OrbitDeterminationSolver.Analysis,
|
202
|
+
):
|
203
|
+
assert isinstance(analysis.estimated_state, State)
|
204
|
+
assert isinstance(analysis.solver_analysis, LeastSquaresSolver.Analysis)
|
205
|
+
|
206
|
+
|
207
|
+
class TestOrbitDeterminationSolver:
|
208
|
+
def test_constructor(
|
209
|
+
self,
|
210
|
+
orbit_determination_solver: OrbitDeterminationSolver,
|
211
|
+
):
|
212
|
+
assert isinstance(orbit_determination_solver, OrbitDeterminationSolver)
|
213
|
+
|
214
|
+
def test_access_methods(
|
215
|
+
self,
|
216
|
+
orbit_determination_solver: OrbitDeterminationSolver,
|
217
|
+
):
|
218
|
+
assert isinstance(orbit_determination_solver.access_environment(), Environment)
|
219
|
+
assert isinstance(orbit_determination_solver.access_propagator(), Propagator)
|
220
|
+
assert isinstance(orbit_determination_solver.access_solver(), LeastSquaresSolver)
|
221
|
+
assert isinstance(orbit_determination_solver.access_estimation_frame(), Frame)
|
222
|
+
|
223
|
+
def test_estimate(
|
224
|
+
self,
|
225
|
+
orbit_determination_solver: OrbitDeterminationSolver,
|
226
|
+
initial_guess: State,
|
227
|
+
observations: list[State],
|
228
|
+
coordinate_subsets: list[CoordinateSubset],
|
229
|
+
initial_guess_sigmas: dict[CoordinateSubset, list[float]],
|
230
|
+
observation_sigmas: dict[CoordinateSubset, list[float]],
|
231
|
+
):
|
232
|
+
analysis: OrbitDeterminationSolver.Analysis = orbit_determination_solver.estimate(
|
233
|
+
initial_guess=initial_guess,
|
234
|
+
observations=observations,
|
235
|
+
estimation_coordinate_subsets=coordinate_subsets,
|
236
|
+
initial_guess_sigmas=initial_guess_sigmas,
|
237
|
+
observation_sigmas=observation_sigmas,
|
238
|
+
)
|
239
|
+
|
240
|
+
assert isinstance(analysis, OrbitDeterminationSolver.Analysis)
|
241
|
+
assert isinstance(analysis.estimated_state, State)
|
242
|
+
assert isinstance(analysis.solver_analysis, LeastSquaresSolver.Analysis)
|
243
|
+
|
244
|
+
def test_estimate_orbit(
|
245
|
+
self,
|
246
|
+
orbit_determination_solver: OrbitDeterminationSolver,
|
247
|
+
initial_guess: State,
|
248
|
+
observations: list[State],
|
249
|
+
coordinate_subsets: list[CoordinateSubset],
|
250
|
+
initial_guess_sigmas: dict[CoordinateSubset, list[float]],
|
251
|
+
observation_sigmas: dict[CoordinateSubset, list[float]],
|
252
|
+
):
|
253
|
+
orbit: Orbit = orbit_determination_solver.estimate_orbit(
|
254
|
+
initial_guess=initial_guess,
|
255
|
+
observations=observations,
|
256
|
+
estimation_coordinate_subsets=coordinate_subsets,
|
257
|
+
initial_guess_sigmas=initial_guess_sigmas,
|
258
|
+
observation_sigmas=observation_sigmas,
|
259
|
+
)
|
260
|
+
|
261
|
+
assert isinstance(orbit, Orbit)
|