pntos-api 2.1.0.post0.dev0__py3-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.
- pntos/__init__.py +3 -0
- pntos/api/__init__.py +79 -0
- pntos/api/plugins/__init__.py +1 -0
- pntos/api/plugins/common.py +1046 -0
- pntos/api/plugins/controller.py +99 -0
- pntos/api/plugins/fusion.py +572 -0
- pntos/api/plugins/fusion_strategy.py +306 -0
- pntos/api/plugins/inertial.py +414 -0
- pntos/api/plugins/initialization.py +278 -0
- pntos/api/plugins/logging.py +68 -0
- pntos/api/plugins/orchestration.py +253 -0
- pntos/api/plugins/platform_integration.py +81 -0
- pntos/api/plugins/preprocessor.py +88 -0
- pntos/api/plugins/registry.py +46 -0
- pntos/api/plugins/state_modeling.py +581 -0
- pntos/api/plugins/transport.py +50 -0
- pntos/api/plugins/ui.py +43 -0
- pntos/api/plugins/utility.py +17 -0
- pntos/py.typed +0 -0
- pntos_api-2.1.0.post0.dev0.dist-info/METADATA +21 -0
- pntos_api-2.1.0.post0.dev0.dist-info/RECORD +24 -0
- pntos_api-2.1.0.post0.dev0.dist-info/WHEEL +5 -0
- pntos_api-2.1.0.post0.dev0.dist-info/licenses/LICENSE +177 -0
- pntos_api-2.1.0.post0.dev0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""Python API of pntOS."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
|
|
5
|
+
from pntos.api import CommonPlugin
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ControllerPlugin(CommonPlugin, ABC):
|
|
9
|
+
"""
|
|
10
|
+
Controller plugin.
|
|
11
|
+
|
|
12
|
+
An implementation of a primary controller in charge of defining the usage of all other pntOS
|
|
13
|
+
plugins.
|
|
14
|
+
|
|
15
|
+
In ordinary operation, an app will import plugins, initialize a controller plugin, and then
|
|
16
|
+
call :meth:`pntos.api.ControllerPlugin.take_control` on the controller plugin, passing in a list of
|
|
17
|
+
``plugins`` that it imported.
|
|
18
|
+
|
|
19
|
+
From that point forward, the controller is responsible for all activity. It may
|
|
20
|
+
use any or none of the plugins in the ``plugins`` list as desired. In general, it may do
|
|
21
|
+
anything it wants, within the following guidelines:
|
|
22
|
+
|
|
23
|
+
- The controller should not load new plugins - it should work with the ``plugins`` passed to it
|
|
24
|
+
in the :meth:`take_control` parameters.
|
|
25
|
+
|
|
26
|
+
- The controller must call :meth:`pntos.api.CommonPlugin.init_plugin` on any plugin it wishes to use prior
|
|
27
|
+
to using any other functionality on that plugin. The controller must pass a :class:`pntos.api.Mediator`
|
|
28
|
+
that the plugin may use to communicate back to the controller. This callback design allows the
|
|
29
|
+
controller to abstract away the concurrency model - in particular, a callback function may be
|
|
30
|
+
anything from a direct invocation of a Python function to a shim that utilizes IPC channels to
|
|
31
|
+
communicate to process-separated or machine-separated plugins.
|
|
32
|
+
|
|
33
|
+
Outside of these requirements, the controller defines any and all I/O it supports, which pntOS
|
|
34
|
+
plugins are loaded / used, and the type of fusion being done. The controller can be hard-coded
|
|
35
|
+
to support only a specific sensor configuration or written generically to support arbitrary
|
|
36
|
+
run-time environment sensing. Outside of some initialization in the app, the controller is the
|
|
37
|
+
conceptual "main" function.
|
|
38
|
+
|
|
39
|
+
When the controller is provided a :class:`pntos.api.PlatformIntegrationPlugin` as one of the plugins in
|
|
40
|
+
the ``plugins`` list passed to :meth:`take_control`, that indicates to the controller that
|
|
41
|
+
platform-specific control logic exists and must be used. In this case, the controller's primary
|
|
42
|
+
objective's are to:
|
|
43
|
+
|
|
44
|
+
- Pick the concurrency model being used (multiprocessed, multithreaded, coroutines,
|
|
45
|
+
single-threaded, etc.).
|
|
46
|
+
- Spin up the concurrency primitives to implement the chosen concurrency type.
|
|
47
|
+
- Provide a :class:`pntos.api.Mediator` to all plugins in their :meth:`pntos.api.CommonPlugin.init_plugin` call that
|
|
48
|
+
enables inter-plugin communication.
|
|
49
|
+
|
|
50
|
+
After that task is accomplished, the controller should call the
|
|
51
|
+
:meth:`pntos.api.PlatformIntegrationPlugin.take_control` function and allow the
|
|
52
|
+
:class:`pntos.api.PlatformIntegrationPlugin` (PIP) to actively call functions on the ``plugins`` list.
|
|
53
|
+
Once the :meth:`pntos.api.PlatformIntegrationPlugin.take_control` has been called, the controller must
|
|
54
|
+
lock/synchronize the controller's and the PIP's access to function calls in the ``plugins``
|
|
55
|
+
list, such that any action the PIP might take will not interfere with the controller's actions
|
|
56
|
+
(or, equivalently, actions that the mediator provided by the controller is taking). One simple
|
|
57
|
+
approach to synchronizing access to the plugins list across the controller and PIP is for the
|
|
58
|
+
plugins list provided to the PIP to be a facade that actually routes messages through to the
|
|
59
|
+
mediator, such that the mediator handles all requests and can synchronously dispatch them. More
|
|
60
|
+
efficient approaches exist, however, it is the responsibility of the controller to make sure
|
|
61
|
+
that all accesses the PIP makes to resources passed to it are synchronized with respect to the
|
|
62
|
+
controller's chosen concurrency primitive.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
@abstractmethod
|
|
66
|
+
def take_control(
|
|
67
|
+
self,
|
|
68
|
+
plugins: list[CommonPlugin],
|
|
69
|
+
plugin_resources_locations: list[str | None] | None = None,
|
|
70
|
+
initial_config: str | None = None,
|
|
71
|
+
) -> None:
|
|
72
|
+
"""
|
|
73
|
+
Takes over primary control of the program from the app.
|
|
74
|
+
|
|
75
|
+
Takes over primary control of the program from the app, using the ``plugins`` to process
|
|
76
|
+
data, generate fused estimates, and ultimately produce and output PNT solutions.
|
|
77
|
+
:meth:`take_control` must use the plugins passed to it and construct a full pntOS system.
|
|
78
|
+
Please see the description of the :class:`pntos.api.PlatformIntegrationPlugin` (PIP) for a description
|
|
79
|
+
of duties of this function compared to the duties of the
|
|
80
|
+
:meth:`pntos.api.PlatformIntegrationPlugin.take_control` method (if a PIP is in the ``plugins`` list).
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
plugins (list[CommonPlugin]): An array of plugins available to the controller.
|
|
84
|
+
plugin_resources_locations (list[str | None] | None, optional): A list of strings
|
|
85
|
+
which represent a list of locations, one for each plugin in ``plugins``, where those
|
|
86
|
+
plugins may find auxiliary data if needed. The array can be ``None``,
|
|
87
|
+
otherwise the array is of the same length as ``plugins``. Each string may be
|
|
88
|
+
``None``, filesystem paths, or adhere to some scheme, such as the URI scheme, for
|
|
89
|
+
defining the resource's location.
|
|
90
|
+
initial_config (str | None, optional): Represents a source of values to initialize the
|
|
91
|
+
primary pntOS configuration. This could be ``None`` or a ``str``. Examples of
|
|
92
|
+
possible values for the latter are:
|
|
93
|
+
|
|
94
|
+
1. The entire config.
|
|
95
|
+
2. A local file path on systems which support them.
|
|
96
|
+
3. A string adhering to the URI scheme.
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
pass
|
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
"""Python API of pntOS."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Any, TypeVar
|
|
6
|
+
|
|
7
|
+
from aspn23 import TypeTimestamp
|
|
8
|
+
from numpy import float64
|
|
9
|
+
from numpy.typing import NDArray
|
|
10
|
+
|
|
11
|
+
from .common import CommonPlugin, EstimateWithCovariance, Message
|
|
12
|
+
from .fusion_strategy import (
|
|
13
|
+
StandardFusionStrategy,
|
|
14
|
+
)
|
|
15
|
+
from .state_modeling import (
|
|
16
|
+
StandardMeasurementProcessor,
|
|
17
|
+
StandardStateBlock,
|
|
18
|
+
VirtualStateBlock,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class CrossCovariances:
|
|
24
|
+
"""
|
|
25
|
+
A container for a set of covariances relating a StateBlock to one or more other StateBlocks.
|
|
26
|
+
|
|
27
|
+
For example, suppose that some StateBlock named ``A`` existed containing ``a`` states. Then this
|
|
28
|
+
structure could define the cross covariance of ``A`` with respect to other StateBlocks named
|
|
29
|
+
``B`` (with ``b`` states) and ``C`` (with ``c`` states). In that case, :attr:`block_labels`
|
|
30
|
+
would be an array of 2 strings ``B`` and ``C``, and :attr:`cross_covariances` would be an array
|
|
31
|
+
of two matrices: the cross-covariance matrix of ``B`` and ``A``, with shape ``[b, a]`` and the
|
|
32
|
+
cross-covariance matrix of ``C`` and ``A`` with shape ``[c, a]``.
|
|
33
|
+
|
|
34
|
+
Attributes:
|
|
35
|
+
block_labels (list[str]): A list of labels of the :class:`pntos.api.StandardStateBlock` this
|
|
36
|
+
structure contains the cross-covariances for.
|
|
37
|
+
cross_covariances (list[NDArray[float64]]): A list of cross-covariance matrices between a single
|
|
38
|
+
StateBlock and the set of StateBlocks listed in :attr:`block_labels`.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
block_labels: list[str]
|
|
42
|
+
"""The labels of the state blocks that the entries in ``cross_covariances`` relate to.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
cross_covariances: list[NDArray[float64]]
|
|
46
|
+
"""The covariances between the state blocks.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class StandardFusionEngine(ABC):
|
|
51
|
+
"""
|
|
52
|
+
An implementation of a fusion engine that supports the standard fusion model.
|
|
53
|
+
|
|
54
|
+
Assumes the system is described by discrete-time matrices and noise inputs are zero-mean white
|
|
55
|
+
Gaussian. In addition, all covariance matrices / mean vectors are descriptions of
|
|
56
|
+
jointly-Gaussian multivariate distributions. All noise sources are jointly-Gaussian distributed.
|
|
57
|
+
|
|
58
|
+
This object requires a :class:`pntos.api.StandardFusionStrategy` to work. Some implementations may be able
|
|
59
|
+
to provide their own. Others will require a strategy to be provided by setting the
|
|
60
|
+
:attr:`StandardFusionEngine.strategy` field. It is possible to check whether a fusion
|
|
61
|
+
engine needs to be provided a fusion strategy by checking the
|
|
62
|
+
:attr:`StandardFusionEngine.strategy` field (if it is ``None`` then this fusion engine
|
|
63
|
+
needs to be provided a strategy). While :attr:`StandardFusionEngine.strategy` is ``None``,
|
|
64
|
+
all other methods are unsafe to be called.
|
|
65
|
+
|
|
66
|
+
Note:
|
|
67
|
+
This class must have an operational ``__deepcopy__`` method. For most classes, the default
|
|
68
|
+
``__deepcopy__`` method provided by Python will be sufficient. However, if the class has a
|
|
69
|
+
field which does not properly implement its own ``__deepcopy__`` (such as a C object wrapped
|
|
70
|
+
to Python), then the class will need to implement a custom ``__deepcopy__`` which properly
|
|
71
|
+
copies all fields.
|
|
72
|
+
|
|
73
|
+
Caution:
|
|
74
|
+
**Unstable**: This feature is unstable and is not yet considered part of the stable pntOS
|
|
75
|
+
API. Usage of this feature is highly discouraged in non-experimental code, and its
|
|
76
|
+
definition may change at any time.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
@abstractmethod
|
|
81
|
+
def time(self) -> TypeTimestamp:
|
|
82
|
+
"""
|
|
83
|
+
Get the current time of the filter.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
TypeTimestamp
|
|
87
|
+
"""
|
|
88
|
+
pass
|
|
89
|
+
|
|
90
|
+
@time.setter
|
|
91
|
+
@abstractmethod
|
|
92
|
+
def time(self, time: TypeTimestamp) -> None:
|
|
93
|
+
"""Setter for the :meth:`pntos.api.StandardFusionEngine.time` property."""
|
|
94
|
+
pass
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
@abstractmethod
|
|
98
|
+
def strategy(self) -> StandardFusionStrategy | None:
|
|
99
|
+
"""
|
|
100
|
+
The underlying algorithm used for Bayesian inference.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
StandardFusionStrategy | None: The fusion strategy is the type of filter (EKF, UKF,
|
|
104
|
+
etc.).
|
|
105
|
+
"""
|
|
106
|
+
pass
|
|
107
|
+
|
|
108
|
+
@strategy.setter
|
|
109
|
+
@abstractmethod
|
|
110
|
+
def strategy(self, strategy: StandardFusionStrategy) -> None:
|
|
111
|
+
"""The setter for the :meth:`strategy` property on :class:`pntos.api.StandardFusionEngine`."""
|
|
112
|
+
pass
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
@abstractmethod
|
|
116
|
+
def num_states(self) -> int:
|
|
117
|
+
"""
|
|
118
|
+
Get the total number of states currently in the fusion engine.
|
|
119
|
+
|
|
120
|
+
Virtual state blocks do not affect this result.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
int: The total number of states currently in the fusion engine.
|
|
124
|
+
"""
|
|
125
|
+
pass
|
|
126
|
+
|
|
127
|
+
@property
|
|
128
|
+
@abstractmethod
|
|
129
|
+
def state_block_labels(self) -> list[str] | None:
|
|
130
|
+
"""
|
|
131
|
+
Get a list of :class:`pntos.api.StandardStateBlock` labels that have been added to this fusion engine.
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
list[str] | None: A list of the :class:`pntos.api.StandardStateBlock` labels that have been added
|
|
135
|
+
to this fusion engine. Returns ``None`` if no state blocks have been added. Guaranteed
|
|
136
|
+
to not return ``None`` if :attr:`num_states` is a value other than 0.
|
|
137
|
+
"""
|
|
138
|
+
pass
|
|
139
|
+
|
|
140
|
+
@abstractmethod
|
|
141
|
+
def add_state_block(
|
|
142
|
+
self,
|
|
143
|
+
block: StandardStateBlock,
|
|
144
|
+
initial_estimate_covariance: EstimateWithCovariance,
|
|
145
|
+
cross_covariances: CrossCovariances | None = None,
|
|
146
|
+
) -> None:
|
|
147
|
+
"""
|
|
148
|
+
Add the given :class:`pntos.api.StandardStateBlock` to the fusion engine.
|
|
149
|
+
|
|
150
|
+
This will expand the state vector being estimated by the value of :attr:`num_states`.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
block (StandardStateBlock): The :class:`pntos.api.StandardStateBlock` to be added to the fusion
|
|
154
|
+
engine.
|
|
155
|
+
initial_estimate_covariance (EstimateWithCovariance): Contains the initial conditions of
|
|
156
|
+
the states, with ``initial_estimate_covariance.estimate`` being an Nx1 matrix and
|
|
157
|
+
``initial_estimate_covariance.covariance`` being an NxN matrix, where N is
|
|
158
|
+
``block.num_states``.
|
|
159
|
+
cross_covariances (CrossCovariances | None, optional): An optional parameter which, if
|
|
160
|
+
non-``None``, contains a description of the newly added StateBlock's cross
|
|
161
|
+
covariances with respect to a set of StateBlocks which already exist inside the
|
|
162
|
+
filter (specified by ``cross_covariances.block_labels``). If the
|
|
163
|
+
``cross_covariance`` parameter is ``None``, cross covariance between the existing
|
|
164
|
+
states and the added states will be set to zeroes.
|
|
165
|
+
"""
|
|
166
|
+
pass
|
|
167
|
+
|
|
168
|
+
@abstractmethod
|
|
169
|
+
def get_state_block_estimate(self, block_label: str) -> NDArray[float64] | None:
|
|
170
|
+
"""
|
|
171
|
+
Get the estimate associated with a state block.
|
|
172
|
+
|
|
173
|
+
Find a :class:`pntos.api.StandardStateBlock` or :class:`pntos.api.VirtualStateBlock` within the fusion engine
|
|
174
|
+
matching ``block_label``, and return a copy of its current estimate vector.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
block_label (str)
|
|
178
|
+
|
|
179
|
+
Returns:
|
|
180
|
+
NDArray[float64] | None: A copy of its current estimate vector. If ``block_label`` references a
|
|
181
|
+
virtual state block (VSB) this will return a converted estimate, converted into the VSBs
|
|
182
|
+
coordinate frame. Returns ``None`` if ``block_label`` does not correspond to a block
|
|
183
|
+
that has been added to the fusion engine. Guaranteed to not return ``None`` when
|
|
184
|
+
``block_label`` is in the list returned by :attr:`state_block_labels` and
|
|
185
|
+
:attr:`strategy` is not ``None``.
|
|
186
|
+
"""
|
|
187
|
+
pass
|
|
188
|
+
|
|
189
|
+
@abstractmethod
|
|
190
|
+
def get_state_block_covariance(self, block_label: str) -> NDArray[float64] | None:
|
|
191
|
+
"""
|
|
192
|
+
Get the covariance associated with a state block.
|
|
193
|
+
|
|
194
|
+
Find a :class:`pntos.api.StandardStateBlock` or :class:`pntos.api.VirtualStateBlock` within the fusion engine
|
|
195
|
+
matching ``block_label``, and return a copy of its current covariance matrix.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
block_label (str)
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
NDArray[float64] | None: A copy of its current covariance matrix. If ``block_label`` references a
|
|
202
|
+
virtual state block (VSB) this will return a converted covariance, converted into the
|
|
203
|
+
VSBs coordinate frame. Returns ``None`` if ``block_label`` does not correspond to a
|
|
204
|
+
block that has been added to the fusion engine. Guaranteed to not return ``None`` when
|
|
205
|
+
``block_label`` is in the list returned by :attr:`state_block_labels` and
|
|
206
|
+
:attr:`strategy` is not ``None``.
|
|
207
|
+
"""
|
|
208
|
+
pass
|
|
209
|
+
|
|
210
|
+
@abstractmethod
|
|
211
|
+
def get_state_block_cross_covariance(
|
|
212
|
+
self, block_label1: str, block_label2: str
|
|
213
|
+
) -> NDArray[float64] | None:
|
|
214
|
+
"""
|
|
215
|
+
Get the cross covariance between the states associated with two state blocks.
|
|
216
|
+
|
|
217
|
+
Find the :class:`pntos.api.StandardStateBlock` s within the fusion engine matching ``block_label1``
|
|
218
|
+
and ``block_label2``, and return the cross-covariance matrix between them.
|
|
219
|
+
|
|
220
|
+
Args:
|
|
221
|
+
block_label1 (str)
|
|
222
|
+
block_label2 (str)
|
|
223
|
+
|
|
224
|
+
Returns:
|
|
225
|
+
NDArray[float64] | None: The cross-covariance matrix between ``block_label1`` and
|
|
226
|
+
``block_label2``. Returns ``None`` if ``block_label1`` or ``block_label2`` do not
|
|
227
|
+
correspond to blocks that have been added to the fusion engine. Guaranteed to not return
|
|
228
|
+
``None`` when both ``block_label1`` and ``block_label2`` are in the list returned by
|
|
229
|
+
:attr:`state_block_labels` and :attr:`strategy` is not ``None``.
|
|
230
|
+
"""
|
|
231
|
+
pass
|
|
232
|
+
|
|
233
|
+
@abstractmethod
|
|
234
|
+
def set_state_block_estimate(
|
|
235
|
+
self, block_label: str, estimate: NDArray[float64]
|
|
236
|
+
) -> None:
|
|
237
|
+
"""
|
|
238
|
+
Update the estimate associated with a given state block.
|
|
239
|
+
|
|
240
|
+
Find a :class:`pntos.api.StandardStateBlock` within the fusion engine matching ``block_label``, and
|
|
241
|
+
change its current estimate vector.
|
|
242
|
+
|
|
243
|
+
Note:
|
|
244
|
+
This function may lead to performance degradation with some implementations and thus its
|
|
245
|
+
use is discouraged if other options are available.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
block_label (str)
|
|
249
|
+
estimate (NDArray[float64])
|
|
250
|
+
"""
|
|
251
|
+
pass
|
|
252
|
+
|
|
253
|
+
@abstractmethod
|
|
254
|
+
def set_state_block_covariance(
|
|
255
|
+
self, block_label: str, covariance: NDArray[float64]
|
|
256
|
+
) -> None:
|
|
257
|
+
"""
|
|
258
|
+
Update the covariance associated with a given state block.
|
|
259
|
+
|
|
260
|
+
Find a :class:`pntos.api.StandardStateBlock` within the fusion engine matching ``block_label``, and
|
|
261
|
+
change its current covariance matrix.
|
|
262
|
+
|
|
263
|
+
Note:
|
|
264
|
+
This function may lead to performance degradation with some implementations and thus its
|
|
265
|
+
use is discouraged if other options are available.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
block_label (str)
|
|
269
|
+
covariance (NDArray[float64])
|
|
270
|
+
"""
|
|
271
|
+
pass
|
|
272
|
+
|
|
273
|
+
@abstractmethod
|
|
274
|
+
def set_state_block_cross_covariance(
|
|
275
|
+
self, block_label1: str, block_label2: str, covariance: NDArray[float64]
|
|
276
|
+
) -> None:
|
|
277
|
+
"""
|
|
278
|
+
Update the covariance between two state blocks.
|
|
279
|
+
|
|
280
|
+
Find the :class:`pntos.api.StandardStateBlock` s within the fusion engine matching ``block_label1``
|
|
281
|
+
and ``block_label2``, and change the current covariance matrix between them.
|
|
282
|
+
|
|
283
|
+
Note:
|
|
284
|
+
This function may lead to performance degradation with some implementations and thus its
|
|
285
|
+
use is discouraged if other options are available.
|
|
286
|
+
|
|
287
|
+
Args:
|
|
288
|
+
block_label1 (str)
|
|
289
|
+
block_label2 (str)
|
|
290
|
+
covariance (NDArray[float64])
|
|
291
|
+
"""
|
|
292
|
+
pass
|
|
293
|
+
|
|
294
|
+
@abstractmethod
|
|
295
|
+
def remove_state_block(self, block_label: str) -> None:
|
|
296
|
+
"""
|
|
297
|
+
Remove the :class:`pntos.api.StandardStateBlock` matching ``block_label``.
|
|
298
|
+
|
|
299
|
+
This will reduce the state vector being estimated by the number of states that the block
|
|
300
|
+
represents.
|
|
301
|
+
|
|
302
|
+
Args:
|
|
303
|
+
block_label (str)
|
|
304
|
+
"""
|
|
305
|
+
pass
|
|
306
|
+
|
|
307
|
+
@property
|
|
308
|
+
@abstractmethod
|
|
309
|
+
def virtual_state_block_target_labels(self) -> list[str] | None:
|
|
310
|
+
"""
|
|
311
|
+
Gets a list of the target labels of virtual state blocks that have been added.
|
|
312
|
+
|
|
313
|
+
A label being returned by this list is not a guarantee that the virtual state block has a
|
|
314
|
+
valid source. For that, call :meth:`has_virtual_state_block`.
|
|
315
|
+
|
|
316
|
+
Returns:
|
|
317
|
+
list[str] | None: A list of the target labels of virtual state blocks that have been
|
|
318
|
+
added. Returns ``None`` if no virtual state blocks have been added to this fusion
|
|
319
|
+
engine.
|
|
320
|
+
"""
|
|
321
|
+
pass
|
|
322
|
+
|
|
323
|
+
@abstractmethod
|
|
324
|
+
def has_virtual_state_block(self, vsb_target_label: str) -> bool:
|
|
325
|
+
"""
|
|
326
|
+
Checks if the fusion engine has a :class:`pntos.api.VirtualStateBlock` with a matching target label.
|
|
327
|
+
|
|
328
|
+
Args:
|
|
329
|
+
vsb_target_label (str)
|
|
330
|
+
|
|
331
|
+
Returns:
|
|
332
|
+
bool: ``True`` if the fusion engine has a :class:`pntos.api.VirtualStateBlock` with a matching
|
|
333
|
+
target label, ``False`` if no virtual state block with matching target label exists or
|
|
334
|
+
if one exists but is not capable of generating an estimate. That is, the VSB's source
|
|
335
|
+
must exist and be in a continuous chain to a concrete state block which also exists in
|
|
336
|
+
the fusion engine in order to return ``True``.
|
|
337
|
+
"""
|
|
338
|
+
pass
|
|
339
|
+
|
|
340
|
+
@abstractmethod
|
|
341
|
+
def add_virtual_state_block(self, virtual_state_block: VirtualStateBlock) -> None:
|
|
342
|
+
"""
|
|
343
|
+
Add the given :class:`pntos.api.VirtualStateBlock` to the fusion engine.
|
|
344
|
+
|
|
345
|
+
A virtual state block (VSB) convert from an underlying block coordinate frame into the VSB
|
|
346
|
+
coordinate frame.
|
|
347
|
+
|
|
348
|
+
Args:
|
|
349
|
+
virtual_state_block (VirtualStateBlock)
|
|
350
|
+
"""
|
|
351
|
+
pass
|
|
352
|
+
|
|
353
|
+
@abstractmethod
|
|
354
|
+
def remove_virtual_state_block(self, vsb_target_label: str) -> None:
|
|
355
|
+
"""
|
|
356
|
+
Remove the :class:`pntos.api.VirtualStateBlock` matching ``vsb_target_label``.
|
|
357
|
+
|
|
358
|
+
Args:
|
|
359
|
+
vsb_target_label (str)
|
|
360
|
+
"""
|
|
361
|
+
pass
|
|
362
|
+
|
|
363
|
+
@property
|
|
364
|
+
@abstractmethod
|
|
365
|
+
def measurement_processor_labels(self) -> list[str] | None:
|
|
366
|
+
"""
|
|
367
|
+
Get a list of the labels of measurement processors that have been added.
|
|
368
|
+
|
|
369
|
+
Returns:
|
|
370
|
+
list[str] | None: list of labels of measurement processors that have been added. Returns
|
|
371
|
+
``None`` if no measurement processors have been added to this fusion engine.
|
|
372
|
+
"""
|
|
373
|
+
pass
|
|
374
|
+
|
|
375
|
+
@abstractmethod
|
|
376
|
+
def add_measurement_processor(
|
|
377
|
+
self, processor: StandardMeasurementProcessor
|
|
378
|
+
) -> None:
|
|
379
|
+
"""
|
|
380
|
+
Add a :class:`pntos.api.StandardMeasurementProcessor`.
|
|
381
|
+
|
|
382
|
+
This can be used to process future measurements that correspond to ``processor.label``.
|
|
383
|
+
|
|
384
|
+
Args:
|
|
385
|
+
processor (StandardMeasurementProcessor)
|
|
386
|
+
"""
|
|
387
|
+
pass
|
|
388
|
+
|
|
389
|
+
@abstractmethod
|
|
390
|
+
def remove_measurement_processor(self, processor_label: str) -> None:
|
|
391
|
+
"""
|
|
392
|
+
Remove a :class:`pntos.api.StandardMeasurementProcessor` previously added to the fusion engine.
|
|
393
|
+
|
|
394
|
+
Assumes a measurement processor was previously added via :meth:`add_measurement_processor`
|
|
395
|
+
with the label ``processor_label``.
|
|
396
|
+
|
|
397
|
+
Args:
|
|
398
|
+
processor_label (str)
|
|
399
|
+
"""
|
|
400
|
+
pass
|
|
401
|
+
|
|
402
|
+
@abstractmethod
|
|
403
|
+
def propagate(self, time: TypeTimestamp) -> None:
|
|
404
|
+
"""
|
|
405
|
+
Propagate the filter estimate forward in time.
|
|
406
|
+
|
|
407
|
+
May be evaluated lazily (when results are requested).
|
|
408
|
+
|
|
409
|
+
Args:
|
|
410
|
+
time (TypeTimestamp)
|
|
411
|
+
"""
|
|
412
|
+
pass
|
|
413
|
+
|
|
414
|
+
@abstractmethod
|
|
415
|
+
def update(self, processor_label: str, message: Message) -> None:
|
|
416
|
+
"""
|
|
417
|
+
Update the filter with the given measurement.
|
|
418
|
+
|
|
419
|
+
Will propagate first if needed to reach the time encoded inside the measurement.
|
|
420
|
+
|
|
421
|
+
Args:
|
|
422
|
+
processor_label (str)
|
|
423
|
+
message (Message)
|
|
424
|
+
"""
|
|
425
|
+
pass
|
|
426
|
+
|
|
427
|
+
@abstractmethod
|
|
428
|
+
def peek_ahead(
|
|
429
|
+
self, time: TypeTimestamp, block_labels: list[str]
|
|
430
|
+
) -> EstimateWithCovariance | None:
|
|
431
|
+
"""
|
|
432
|
+
Calculates the estimate and covariance at a requested time.
|
|
433
|
+
|
|
434
|
+
Uses the state blocks listed in ``block_labels``, without changing the state of the fusion
|
|
435
|
+
engine or its underlying filter. Blocks are assembled in the order that the labels are
|
|
436
|
+
passed in.
|
|
437
|
+
|
|
438
|
+
If all of the following are true:
|
|
439
|
+
|
|
440
|
+
- ``time`` is equal to or after the filter time (which can be checked with :attr:`time`).
|
|
441
|
+
- All labels in ``block_labels`` correspond to a block that has been added to the fusion
|
|
442
|
+
engine (which can be checked with :attr:`state_block_labels`).
|
|
443
|
+
- ``block_labels`` has at least one element.
|
|
444
|
+
|
|
445
|
+
Then the result returned is guaranteed to not be ``None``. Otherwise, if any of the above
|
|
446
|
+
are false then the result will be ``None``.
|
|
447
|
+
|
|
448
|
+
Args:
|
|
449
|
+
time (TypeTimestamp)
|
|
450
|
+
block_labels (list[str]): An array of strings.
|
|
451
|
+
|
|
452
|
+
Returns:
|
|
453
|
+
EstimateWithCovariance | None
|
|
454
|
+
"""
|
|
455
|
+
pass
|
|
456
|
+
|
|
457
|
+
@abstractmethod
|
|
458
|
+
def generate_x_and_p(
|
|
459
|
+
self, block_labels: list[str]
|
|
460
|
+
) -> EstimateWithCovariance | None:
|
|
461
|
+
"""
|
|
462
|
+
Generates the current estimate and covariance.
|
|
463
|
+
|
|
464
|
+
Estimate and covariance are built corresponding to a list of StateBlock labels. Blocks are
|
|
465
|
+
assembled in the order that the labels are passed in.
|
|
466
|
+
|
|
467
|
+
If all of the following are true:
|
|
468
|
+
|
|
469
|
+
- All labels in ``block_labels`` correspond to a block that has been added to the fusion
|
|
470
|
+
engine (which can be checked with :attr:`state_block_labels`).
|
|
471
|
+
- ``block_labels`` has at least one element.
|
|
472
|
+
|
|
473
|
+
Then the result returned is guaranteed to not be ``None``. Otherwise, if any of the above
|
|
474
|
+
are false then the result will be ``None``.
|
|
475
|
+
|
|
476
|
+
Args:
|
|
477
|
+
block_labels (list[str]): An array of strings.
|
|
478
|
+
|
|
479
|
+
Returns:
|
|
480
|
+
EstimateWithCovariance | None
|
|
481
|
+
"""
|
|
482
|
+
pass
|
|
483
|
+
|
|
484
|
+
@abstractmethod
|
|
485
|
+
def give_state_block_aux_data(
|
|
486
|
+
self, block_label: str, aux: list[Message | None]
|
|
487
|
+
) -> None:
|
|
488
|
+
"""
|
|
489
|
+
Route a list of messages of aux data to a :class:`pntos.api.StandardStateBlock`.
|
|
490
|
+
|
|
491
|
+
Args:
|
|
492
|
+
block_label (str)
|
|
493
|
+
aux (list[Message | None])
|
|
494
|
+
"""
|
|
495
|
+
pass
|
|
496
|
+
|
|
497
|
+
@abstractmethod
|
|
498
|
+
def give_measurement_processor_aux_data(
|
|
499
|
+
self, processor_label: str, aux: list[Message | None]
|
|
500
|
+
) -> None:
|
|
501
|
+
"""
|
|
502
|
+
Route a list of messages of aux data to a :class:`pntos.api.StandardMeasurementProcessor`.
|
|
503
|
+
|
|
504
|
+
Args:
|
|
505
|
+
processor_label (str)
|
|
506
|
+
aux (list[Message | None])
|
|
507
|
+
"""
|
|
508
|
+
pass
|
|
509
|
+
|
|
510
|
+
@abstractmethod
|
|
511
|
+
def give_virtual_state_block_aux_data(
|
|
512
|
+
self, target_label: str, aux: list[Message | None]
|
|
513
|
+
) -> None:
|
|
514
|
+
"""
|
|
515
|
+
Route a list of messages of aux data to a :class:`pntos.api.VirtualStateBlock`.
|
|
516
|
+
|
|
517
|
+
Args:
|
|
518
|
+
target_label (str)
|
|
519
|
+
aux (list[Message | None])
|
|
520
|
+
"""
|
|
521
|
+
pass
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
FusionEngineType = TypeVar('FusionEngineType', StandardFusionEngine, Any)
|
|
525
|
+
"""Enumerates the types of fusion engines.
|
|
526
|
+
|
|
527
|
+
Currently only StandardFusionEngine is defined, but this TypeVar also includes "Any" in the type
|
|
528
|
+
list for future compatibility.
|
|
529
|
+
"""
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
class FusionPlugin(CommonPlugin, ABC):
|
|
533
|
+
"""
|
|
534
|
+
Plugin that provides a fusion engine.
|
|
535
|
+
|
|
536
|
+
A fusion engine allows data from multiple sensors to be integrated into a unified state
|
|
537
|
+
estimate.
|
|
538
|
+
"""
|
|
539
|
+
|
|
540
|
+
@abstractmethod
|
|
541
|
+
def is_fusion_type_supported(self, fusion_type: type[FusionEngineType]) -> bool:
|
|
542
|
+
"""
|
|
543
|
+
Check if the plugin supports a given type of fusion.
|
|
544
|
+
|
|
545
|
+
Args:
|
|
546
|
+
fusion_type (type[FusionEngineType])
|
|
547
|
+
|
|
548
|
+
Returns:
|
|
549
|
+
bool
|
|
550
|
+
"""
|
|
551
|
+
pass
|
|
552
|
+
|
|
553
|
+
@abstractmethod
|
|
554
|
+
def new_fusion_engine(
|
|
555
|
+
self, fusion_type: type[FusionEngineType]
|
|
556
|
+
) -> FusionEngineType | None:
|
|
557
|
+
"""
|
|
558
|
+
Create a fusion engine.
|
|
559
|
+
|
|
560
|
+
Args:
|
|
561
|
+
fusion_type (type[FusionEngineType]): This parameter specifies the type of fusion engine that
|
|
562
|
+
will be returned.
|
|
563
|
+
|
|
564
|
+
Returns:
|
|
565
|
+
FusionEngineType | None: The ``fusion_type`` parameter specifies the type of fusion engine
|
|
566
|
+
that will be returned. For example, if the user passes in :class:`pntos.api.StandardFusionEngine`,
|
|
567
|
+
then an implementation of :class:`pntos.api.StandardFusionEngine` will be returned. Returns
|
|
568
|
+
``None`` if ``fusion_type`` is not supported by this fusion plugin
|
|
569
|
+
(:meth:`is_fusion_type_supported` can be used to check the type before calling this
|
|
570
|
+
method). Otherwise the return is guaranteed to not be ``None``.
|
|
571
|
+
"""
|
|
572
|
+
pass
|