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.
@@ -0,0 +1,581 @@
1
+ """Python API of pntOS."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from abc import ABC, abstractmethod
6
+ from collections.abc import Callable
7
+ from dataclasses import dataclass
8
+ from typing import TYPE_CHECKING, Any, TypeVar
9
+
10
+ from aspn23 import TypeTimestamp
11
+ from numpy import float64
12
+ from numpy.typing import NDArray
13
+
14
+ from .common import CommonPlugin, EstimateWithCovariance, Message
15
+
16
+ if TYPE_CHECKING:
17
+ from .fusion import StandardFusionEngine
18
+
19
+
20
+ @dataclass
21
+ class StandardDynamicsModel:
22
+ """
23
+ A description of the propagation dynamics for a set of states.
24
+
25
+ This model assumes that the state space :math:`x` can be propagated forward in time by the
26
+ equation:
27
+
28
+ .. math::
29
+ x_k = g(x_{k-1}) + w_k
30
+
31
+ where :math:`x_k` is the set of states at time :math:`k`, :math:`g` is an arbitrary function,
32
+ and :math:`w_k` is additive white Gaussian noise.
33
+
34
+ Attributes:
35
+ g (Callable[[NDArray[float64]], NDArray[float64]]): A function that propagates forward in time a set of
36
+ states.
37
+ Phi (NDArray[float64]): The first-order Taylor series expansion (Jacobian) of the function :math:`g`.
38
+ Qd (NDArray[float64]): The covariance matrix of :math:`w_k`.
39
+ """
40
+
41
+ g: Callable[[NDArray[float64]], NDArray[float64]]
42
+ Phi: NDArray[float64]
43
+ Qd: NDArray[float64]
44
+
45
+
46
+ @dataclass
47
+ class StandardMeasurementModel:
48
+ """
49
+ A description of how a measurement relates to a state space.
50
+
51
+ This model assumes that the relationship between the measurement and state vector is well
52
+ modeled by the equation:
53
+
54
+ .. math::
55
+ z=h(x) + v
56
+
57
+ where :math:`z` is the measurement itself, :math:`x` is the set of states being estimated,
58
+ :math:`h` is an arbitrary function, and :math:`v` is additive white Gaussian noise.
59
+
60
+ Attributes:
61
+ z (NDArray[float64]): A column vector containing the measurement itself.
62
+ h (Callable[[NDArray[float64]], NDArray[float64]]): A function that maps the state space to measurement space.
63
+ H (NDArray[float64]): The first-order Taylor series expansion (i.e. Jacobian) of the function h.
64
+ R (NDArray[float64]): The covariance matrix of :math:`v`.
65
+ """
66
+
67
+ z: NDArray[float64]
68
+ h: Callable[[NDArray[float64]], NDArray[float64]]
69
+ H: NDArray[float64]
70
+ R: NDArray[float64]
71
+
72
+
73
+ GenXandP = Callable[[list[str]], EstimateWithCovariance | None]
74
+ """
75
+ Returns the estimate and covariance associated with the states of ``block_labels`` within a
76
+ particular measurement processor or state block. This is used to lazily evaluate estimate and
77
+ covariance.
78
+
79
+ Args:
80
+ block_labels (list[str]): Labels for state blocks to generate estimate and
81
+ covariance for.
82
+
83
+ Returns:
84
+ Estimate and covariance of the provided block_labels. Returns ``None`` if any label in
85
+ ``block_labels`` does not correspond to a valid block.
86
+ """
87
+
88
+
89
+ class StandardStateBlock(ABC):
90
+ """
91
+ A description of a set of states and their dynamics.
92
+
93
+ Attributes:
94
+ label (str): The unique name for this state block.
95
+ num_states (int): The number of states represented by this state block.
96
+
97
+ Note:
98
+ This class must have an operational ``__deepcopy__`` method. For most classes, the default
99
+ ``__deepcopy__`` method provided by Python will be sufficient. However, if the class has a
100
+ field which does not properly implement its own ``__deepcopy__`` (such as a C object wrapped
101
+ to Python), then the class will need to implement a custom ``__deepcopy__`` which properly
102
+ copies all fields.
103
+ """
104
+
105
+ label: str
106
+ """The unique name for this state block."""
107
+ num_states: int
108
+ """The number of states represented by this state block."""
109
+
110
+ @abstractmethod
111
+ def receive_aux_data(self, aux: list[Message | None]) -> None:
112
+ """
113
+ Receive and use an arbitrary collection of aux data.
114
+
115
+ This method will be called by the fusion engine when its
116
+ :meth:`pntos.api.StandardFusionEngine.give_state_block_aux_data` is called with a label
117
+ corresponding to this state block's ``label``.
118
+
119
+ Args:
120
+ aux (list[Message | None])
121
+ """
122
+ pass
123
+
124
+ @abstractmethod
125
+ def generate_dynamics(
126
+ self,
127
+ gen_x_and_p_func: GenXandP,
128
+ time_from: TypeTimestamp,
129
+ time_to: TypeTimestamp,
130
+ ) -> StandardDynamicsModel | None:
131
+ """
132
+ Generate a :class:`pntos.api.StandardDynamicsModel`.
133
+
134
+ The generated model contains a complete description of how to propagate
135
+ this state block forward in time. For simple models, this can simply
136
+ return a set of static matrices that are pre-defined.
137
+
138
+ Args:
139
+ gen_x_and_p_func (GenXandP): A callback function that the state block can
140
+ use to get the current estimate and covariance.
141
+ time_from (TypeTimestamp): The time to propagate from.
142
+ time_to (TypeTimestamp): The time to propagate to.
143
+
144
+ Returns:
145
+ StandardDynamicsModel | None: The description of how to propagate this state block over
146
+ the given time interval, or ``None`` if ``time_from`` is later than ``time_to``.
147
+ Otherwise guaranteed to not return ``None``.
148
+ """
149
+ pass
150
+
151
+
152
+ class VirtualStateBlock(ABC):
153
+ """
154
+ A class used to convert a set of states from one representation to another.
155
+
156
+ States are converted using a mapping function :math:`f` to convert estimates,
157
+ and the Jacobian of :math:`f()` to map covariances (note that this implies that
158
+ the order/units of terms in the estimate vector and covariance matrix are
159
+ the same). Each instance is associated with two labels, ``source`` and
160
+ ``target``, where ``source`` is the label attached to the quantity to be
161
+ transformed, and ``target`` is the label attached to the result. Typically used
162
+ with a :class:`pntos.api.StandardFusionEngine` where ``source`` refers to a *real*
163
+ :class:`pntos.api.StandardStateBlock` and ``target`` refers to some representation that is
164
+ advantageous for some other element, such as a :class:`pntos.api.StandardMeasurementProcessor`, to use.
165
+
166
+ Attributes:
167
+ source (str): The label associated with the representation this instance can transform
168
+ *from*.
169
+ target (str): The label associated with the representation this instance can transform *to*.
170
+
171
+ Note:
172
+ This class must have an operational ``__deepcopy__`` method. For most classes, the default
173
+ ``__deepcopy__`` method provided by Python will be sufficient. However, if the class has a
174
+ field which does not properly implement its own ``__deepcopy__`` (such as a C object wrapped
175
+ to Python), then the class will need to implement a custom ``__deepcopy__`` which properly
176
+ copies all fields.
177
+ """
178
+
179
+ source: str
180
+ target: str
181
+
182
+ @abstractmethod
183
+ def receive_aux_data(self, aux: list[Message | None]) -> None:
184
+ """
185
+ Receive and use an arbitrary collection of aux data.
186
+
187
+ This method will be called by the fusion engine when its
188
+ :meth:`pntos.api.StandardFusionEngine.give_virtual_state_block_aux_data` is called with a
189
+ label corresponding to this :class:`pntos.api.VirtualStateBlock` 's ``target``.
190
+
191
+ Args:
192
+ aux (list[Message | None])
193
+ """
194
+ pass
195
+
196
+ @abstractmethod
197
+ def convert(
198
+ self,
199
+ estimate_with_covariance: EstimateWithCovariance,
200
+ time: TypeTimestamp,
201
+ ) -> EstimateWithCovariance:
202
+ """
203
+ Convert a full estimate/covariance pair.
204
+
205
+ Args:
206
+ estimate_with_covariance (EstimateWithCovariance): Estimate and covariance to convert.
207
+ time (TypeTimestamp): Time that ``estimate_with_covariance`` is valid at.
208
+
209
+ Returns:
210
+ EstimateWithCovariance: The converted value.
211
+ """
212
+ pass
213
+
214
+ @abstractmethod
215
+ def convert_estimate(
216
+ self, estimate: NDArray[float64], time: TypeTimestamp
217
+ ) -> NDArray[float64]:
218
+ """
219
+ Convert just an estimate vector.
220
+
221
+ Args:
222
+ estimate (NDArray[float64]): Estimate vector to convert, Nx1.
223
+ time (TypeTimestamp): Time that ``estimate`` is valid at.
224
+
225
+ Returns:
226
+ NDArray[float64]: The converted vector, Mx1.
227
+ """
228
+ pass
229
+
230
+ @abstractmethod
231
+ def jacobian(
232
+ self, estimate: NDArray[float64], time: TypeTimestamp
233
+ ) -> NDArray[float64]:
234
+ """
235
+ Obtain the Jacobian of the transform performed by this instance.
236
+
237
+ The Jacobian is calculated at an instance in time, given an estimate to
238
+ differentiate with respect to.
239
+
240
+ Args:
241
+ estimate (NDArray[float64]): Estimate vector associated with the return value of ``source``, Nx1.
242
+ time (TypeTimestamp): Time that ``estimate`` is valid at.
243
+
244
+ Returns:
245
+ NDArray[float64]: An MxN matrix that may be used to pre-multiply ``estimate`` to obtain an M
246
+ length vector in ``target`` representation (to first order).
247
+ """
248
+ pass
249
+
250
+
251
+ class StandardMeasurementProcessor(ABC):
252
+ """
253
+ A class that processes raw measurements/observations.
254
+
255
+ The measurements are used to calculate estimated states suitable for a linear or linearized
256
+ filter to use. Each type of measurement should correspond to a
257
+ :class:`pntos.api.StandardMeasurementProcessor` that is supplied to the fusion engine. Incoming
258
+ measurements received by the fusion engine will be routed to the corresponding measurement
259
+ processor (by label) and call :meth:`generate_model` to process the measurement. The resulting
260
+ :class:`pntos.api.StandardMeasurementModel` will be used by the fusion engine to call the underlying
261
+ :meth:`pntos.api.StandardFusionStrategy.update` method to update the filter estimate/error covariance.
262
+
263
+ Attributes:
264
+ label (str): A unique name for this measurement processor. This value will be used to
265
+ select a measurement processor to handle new measurements that the strategy
266
+ receives.
267
+ state_block_labels (list[str]): A list of unique state block labels associated with
268
+ measurements received by this processor. The estimate and covariance matrices passed
269
+ into :meth:`generate_model` will be composed of the states associated with these state
270
+ blocks, and the returned StandardMeasurementModel.h and StandardMeasurementModel.H must
271
+ respect these states. Note: ``state_block_labels[i]`` is the identifier for the ``i`` th
272
+ state block this processor relates to.
273
+
274
+ Note:
275
+ This class must have an operational ``__deepcopy__`` method. For most classes, the default
276
+ ``__deepcopy__`` method provided by Python will be sufficient. However, if the class has a
277
+ field which does not properly implement its own ``__deepcopy__`` (such as a C object wrapped
278
+ to Python), then the class will need to implement a custom ``__deepcopy__`` which properly
279
+ copies all fields.
280
+ """
281
+
282
+ label: str
283
+ """A unique name for this measurement processor. This value will be used to
284
+ select a measurement processor to handle new measurements that the strategy
285
+ receives"""
286
+ state_block_labels: list[str]
287
+ """A list of unique state block labels associated with
288
+ measurements received by this processor. The estimate and covariance matrices passed
289
+ into :meth:`generate_model` will be composed of the states associated with these state
290
+ blocks, and the returned StandardMeasurementModel.h and StandardMeasurementModel.H must
291
+ respect these states. Note: ``state_block_labels[i]`` is the identifier for the ``i`` th
292
+ state block this processor relates to"""
293
+
294
+ @abstractmethod
295
+ def receive_aux_data(self, aux: list[Message | None]) -> None:
296
+ """
297
+ Receive and use an arbitrary collection of aux data.
298
+
299
+ This method will be called by the fusion engine when its
300
+ :meth:`pntos.api.StandardFusionEngine.give_measurement_processor_aux_data` is called with
301
+ a label corresponding to this measurement processor's ``label``.
302
+
303
+ Args:
304
+ aux (list[Message | None])
305
+ """
306
+ pass
307
+
308
+ @abstractmethod
309
+ def generate_model(
310
+ self, message: Message, gen_x_and_p_func: GenXandP
311
+ ) -> StandardMeasurementModel | None:
312
+ """
313
+ Generate a :class:`pntos.api.StandardMeasurementModel`.
314
+
315
+ Args:
316
+ message (Message): The measurement/observation to process.
317
+ gen_x_and_p_func (GenXandP): A callback function that can be used to
318
+ retrieve the current estimate and covariance for the state blocks this
319
+ measurement processor targets.
320
+
321
+ Returns:
322
+ StandardMeasurementModel | None: A generated model containing the
323
+ parameters required for a filter update. Will be ``None`` when a
324
+ measurement cannot be produced from ``message`` (for example, this
325
+ could happen if the measurement type is unsupported by the
326
+ measurement processor or if it is rejected due to residual
327
+ monitoring).
328
+ """
329
+ pass
330
+
331
+
332
+ class StandardStateModelProvider(ABC):
333
+ """
334
+ A collection of tools for modeling states and measurements.
335
+
336
+ These tools are used to model the propagation and innovation of state
337
+ spaces using pntOS's standard fusion model. Specifically, a
338
+ :class:`pntos.api.StandardStateModelProvider` provides three types of tools:
339
+
340
+ 1. State Blocks - Define a set of states and a model for propagating those states.
341
+ 2. Virtual State Blocks - Relate two statespaces to each other.
342
+ 3. Measurement Processors - Relate measurements to a statespace.
343
+
344
+ A :class:`pntos.api.StandardStateModelProvider` conceptually models a set of zero or more
345
+ :class:`pntos.api.StandardStateBlock` s and a set of zero or more
346
+ :class:`pntos.api.StandardMeasurementProcessor` s which together model the phenomenology of
347
+ sensor data that is being brought into a fusion engine. The first type,
348
+ state blocks, describe how a set of states propagates forward through time.
349
+ The second type, measurement processors, describe how a measurement relates
350
+ to a set of state blocks.
351
+
352
+ Each :class:`pntos.api.StandardStateModelProvider` consists of factory methods which generate
353
+ instances of the state blocks and measurement processors it provides. The
354
+ :meth:`pntos.api.StandardStateModelProvider.new_block` method is a factory method that
355
+ returns a newly created state block on each invocation. Because the
356
+ :class:`pntos.api.StandardStateModelProvider` can provide more than one kind of state block,
357
+ the :meth:`pntos.api.StandardStateModelProvider.new_block` method takes a ``block_index``
358
+ parameter which allows the user to request which kind of state block is
359
+ created by the factory. ``block_identifiers[i]`` gives a description of the
360
+ ``i`` th kind of state block returned when ``block_index=i``.
361
+
362
+ Similarly, :meth:`pntos.api.StandardStateModelProvider.new_processor` is a factory method for
363
+ returning new measurement processors and ``processor_identifiers`` is a set
364
+ of identifiers for each available kind of measurement processor that can be
365
+ returned by the factory.
366
+
367
+ Attributes:
368
+ processor_identifiers (list[str] | None): A list of identifying strings for each kind of
369
+ measurement processor that this :class:`pntos.api.StandardStateModelProvider` can create instances
370
+ of. The ``processor_index`` parameter of :meth:`new_processor` is an index into this
371
+ array. This field will be ``None`` when this state model provider does not provide
372
+ any measurement processors.
373
+ block_identifiers (list[str] | None): A list of identifying strings for each kind of state block
374
+ that this :class:`pntos.api.StandardStateModelProvider` can create instances of.
375
+ The ``block_index`` parameter of :meth:`new_block` is an index into this array.
376
+ This field will be ``None`` when this state model provider does not
377
+ provide any state blocks.
378
+ virtual_block_identifiers (list[str] | None): A list of identifying strings for each kind of
379
+ virtual state block that this :class:`pntos.api.StandardStateModelProvider` can create instances
380
+ of. The ``virtual_block_index`` parameter of :meth:`new_virtual_block` is an index into
381
+ this array. This field will be ``None`` when this state model provider does not
382
+ provide any virtual state blocks.
383
+ """
384
+
385
+ processor_identifiers: list[str] | None
386
+ """Strings describing the measurement processors the provider can create.
387
+ """
388
+ block_identifiers: list[str] | None
389
+ """Strings describing the state blocks the provider can create.
390
+ """
391
+ virtual_block_identifiers: list[str] | None
392
+ """Strings describing the virtual state blocks the provider can create.
393
+ """
394
+
395
+ @abstractmethod
396
+ def new_processor(
397
+ self,
398
+ processor_index: int,
399
+ engine: StandardFusionEngine | None,
400
+ label: str,
401
+ state_block_labels: list[str],
402
+ config_group: str | None,
403
+ ) -> StandardMeasurementProcessor | None:
404
+ """
405
+ Generate a newly created :class:`pntos.api.StandardMeasurementProcessor`.
406
+
407
+ This measurement processor describes the relationship between a
408
+ measurement and a set of state blocks.
409
+
410
+ Args:
411
+ processor_index (int): Since the :class:`pntos.api.StandardStateModelProvider` can create
412
+ different kinds of measurement processors, the ``processor_index``
413
+ parameter is used to select which kind of measurement processor
414
+ to create a new instance of. The :attr:`processor_identifiers` field
415
+ contains identifying strings for the kinds of processors. For
416
+ example, if the model can create 45 different processors, the
417
+ identifier of the last processor that can be created is found in
418
+ ``processor_identifiers[44]``. An instance of this processor can be
419
+ created by calling ``new_processor(self, 44, ...)``. Note that ``0
420
+ <= processor_index < len(processor_identifiers)``.
421
+ engine (StandardFusionEngine | None): An optional parameter that may be provided to the
422
+ new processor, such that the processor may interact with the fusion engine it
423
+ is being used in (for example, to add/remove states). Set it to
424
+ ``None`` when no engine is available for the processor to use.
425
+ label (str): A string which will be used to populate the ``label`` field of
426
+ the newly created processor. This ``label`` will be the unique name
427
+ for the returned instance of a processor, and used to track the
428
+ processor throughout its lifecycle. Note that it differs from
429
+ :attr:`processor_identifiers` which is the model's mechanism for
430
+ selecting the *kind* of processor to create.
431
+ state_block_labels (list[str]): A list of strings which will be used to
432
+ populate the ``state_block_labels`` field of the newly created
433
+ processor.
434
+ config_group (str | None): Indicates which (if any) parameter group in the
435
+ registry may be used to obtain additional configuration values to
436
+ generate the new processor. If the processor requires no outside
437
+ configuration, ``config_group`` may be ``None``.
438
+
439
+ Returns:
440
+ StandardMeasurementProcessor | None: The newly created
441
+ :class:`pntos.api.StandardMeasurementProcessor` or ``None`` when no measurement processor can be
442
+ produced with the given ``processor_index``, ``engine``, and ``config_group``.
443
+ """
444
+ pass
445
+
446
+ @abstractmethod
447
+ def new_block(
448
+ self,
449
+ block_index: int,
450
+ engine: StandardFusionEngine | None,
451
+ label: str,
452
+ config_group: str | None,
453
+ ) -> StandardStateBlock | None:
454
+ """
455
+ Generate a newly created :class:`pntos.api.StandardStateBlock`.
456
+
457
+ This state block describes a set of states and how they propagate over
458
+ time.
459
+
460
+ Args:
461
+ block_index (int): Since the :class:`pntos.api.StandardStateModelProvider` can create
462
+ different kinds of state blocks, the ``block_index`` parameter is
463
+ used to select which kind of state block to create a new instance
464
+ of. The :attr:`block_identifiers` field contains identifying strings for
465
+ the kinds of state blocks. For example, if the model can create
466
+ 45 different state blocks, the identifier of the last state block
467
+ that can be created is found in ``block_identifiers[44]``. An
468
+ instance of this state block can be created by calling
469
+ ``new_block(self, 44, ...)``. Note that ``0 <= block_index <
470
+ len(block_identifiers)``.
471
+ engine (StandardFusionEngine | None): An optional parameter that may be provided to the
472
+ new block, such that the block may interact with the fusion engine it
473
+ is being used in (for example, to add/remove states). Set it to
474
+ ``None`` when no engine is available for the block to use.
475
+ label (str): A string which will be used to populate the ``label`` field
476
+ of the newly created state block. This ``label`` will be the unique
477
+ name for the returned instance of a state block, and used to
478
+ track the state block throughout its lifecycle. Note that it
479
+ differs from :attr:`block_identifiers` which is the model's mechanism
480
+ for selecting the *kind* of state block to create.
481
+ config_group (str | None): Indicates which (if any) parameter group in the
482
+ registry may be used to obtain additional configuration values to
483
+ generate the new state block. If the state block requires no
484
+ outside configuration, ``config_group`` may be ``None``.
485
+
486
+ Returns:
487
+ StandardStateBlock | None: The newly created
488
+ :class:`pntos.api.StandardStateBlock` or ``None`` when no state block can be produced
489
+ with the given ``block_index``, ``engine``, and ``config_group``.
490
+ """
491
+ pass
492
+
493
+ @abstractmethod
494
+ def new_virtual_block(
495
+ self,
496
+ virtual_block_index: int,
497
+ source_label: str,
498
+ target_label: str,
499
+ config_group: str | None,
500
+ ) -> VirtualStateBlock | None:
501
+ """
502
+ Generate a newly created :class:`pntos.api.VirtualStateBlock`.
503
+
504
+ This virtual state block is used to convert a set of states from one
505
+ representation to another.
506
+
507
+ Args:
508
+ virtual_block_index (int): Since the :class:`pntos.api.StandardStateModelProvider` can
509
+ create different kinds of virtual state blocks, the
510
+ ``virtual_block_index parameter`` is used to select which kind of
511
+ virtual state block to create a new instance of. The
512
+ :attr:`pntos.api.StandardStateModelProvider.virtual_block_identifiers` field contains identifying strings for
513
+ the kinds of virtual state blocks. For example, if the model can
514
+ create 45 different virtual state blocks, the identifier of the
515
+ last virtual state block that can be created is found in
516
+ ``virtual_block_identifiers[44]``. An instance of this virtual
517
+ state block can be created by calling ``new_virtual_block(self,
518
+ 44, ...)``. Note that ``0 <= virtual_block_index <
519
+ len(virtual_block_identifiers)``.
520
+ source_label (str): The label of the state block or virtual state block
521
+ whose states this virtual state block transforms.
522
+ target_label (str): A unique identifier for this virtual state block.
523
+ config_group (str | None): Indicates which (if any) parameter group in the
524
+ registry may be used to obtain additional configuration values to
525
+ generate the new virtual state block. If the virtual state block
526
+ requires no outside configuration, ``config_group`` may be ``None``.
527
+
528
+ Returns:
529
+ VirtualStateBlock | None: The newly created :class:`pntos.api.VirtualStateBlock` or ``None`` when
530
+ no virtual state block can be produced with the given ``virtual_block_index`` and
531
+ ``config_group``.
532
+ """
533
+ pass
534
+
535
+
536
+ StateModelProviderType = TypeVar(
537
+ 'StateModelProviderType', StandardStateModelProvider, Any
538
+ )
539
+ """
540
+ An enumeration of the types of state model providers a state modeling plugin could provide.
541
+
542
+ "Any" is included for future compatibility.
543
+ """
544
+
545
+
546
+ class StateModelingPlugin(CommonPlugin, ABC):
547
+ """A :class:`pntos.api.CommonPlugin` subclass that generates state model providers."""
548
+
549
+ @abstractmethod
550
+ def is_fusion_type_supported(
551
+ self, fusion_type: type[StateModelProviderType]
552
+ ) -> bool:
553
+ """
554
+ Check if the plugin supports a given type of fusion. See ``StateModelProviderType``.
555
+
556
+ Args:
557
+ fusion_type (StateModelProviderType)
558
+
559
+ Returns:
560
+ bool
561
+ """
562
+ pass
563
+
564
+ @abstractmethod
565
+ def new_state_model_provider(
566
+ self, fusion_type: type[StateModelProviderType]
567
+ ) -> StateModelProviderType | None:
568
+ """
569
+ Generate a state model provider.
570
+
571
+ Args:
572
+ fusion_type (StateModelProviderType): Specifies the type of fusion that the returned value will
573
+ support. For example, if the user passes in ``STANDARD_MODEL``, then the returned
574
+ value will be an implementation of :class:`pntos.api.StandardStateModelProvider`.
575
+
576
+ Returns:
577
+ StateModelProviderType | None: A state model provider which implements the specified
578
+ type or None if ``fusion_type`` is not supported (:meth:`is_fusion_type_supported` can be used
579
+ to check ``fusion_type``).
580
+ """
581
+ pass
@@ -0,0 +1,50 @@
1
+ """Python API of pntOS."""
2
+
3
+ from abc import ABC, abstractmethod
4
+
5
+ from pntos.api import CommonPlugin, Message
6
+
7
+
8
+ class TransportPlugin(CommonPlugin, ABC):
9
+ """
10
+ Transport plugin.
11
+
12
+ A plugin that abstracts a network transport. listening for sensor data off
13
+ the wire and sending data back to the sensors as needed.
14
+ """
15
+
16
+ @abstractmethod
17
+ def start_listening(self) -> None:
18
+ """
19
+ Start listening.
20
+
21
+ Start listening to the transport that this plugin implements, calling
22
+ the appropriate controller function as data streams in.
23
+ """
24
+ pass
25
+
26
+ @abstractmethod
27
+ def stop_listening(self) -> None:
28
+ """
29
+ Disable listening.
30
+
31
+ Disable listening to the transport that was previously started in a
32
+ call to :meth:`start_listening`.
33
+ """
34
+ pass
35
+
36
+ @abstractmethod
37
+ def broadcast_message(
38
+ self, message: Message, channel_name: str | None = None
39
+ ) -> None:
40
+ """
41
+ Send a message back out to the sensor from pntOS.
42
+
43
+ Args:
44
+ message (Message): The message to send.
45
+ channel_name (str | None, optional): The desired channel. If ``channel_name`` is
46
+ ``None`` the implementation may decide where ``message`` should be routed, if
47
+ anywhere. For example, a serial cable might send all messages to a single
48
+ destination.
49
+ """
50
+ pass
@@ -0,0 +1,43 @@
1
+ """Python API of pntOS."""
2
+
3
+ from abc import ABC, abstractmethod
4
+
5
+ from pntos.api import CommonPlugin
6
+
7
+
8
+ class UiPlugin(CommonPlugin, ABC):
9
+ """
10
+ A plugin for a UI that is integrated directly into pntOS.
11
+
12
+ While it is always possible to write a GUI that listens to pntOS outputs and interacts with it
13
+ externally, this plugin allows users to write a GUI that has direct access to pntOS via the
14
+ plugin API. This allows for low latency and high performance GUI/UIs to be generated. Note that
15
+ this plugin is designed for developer/research style UIs and not production environments. A user
16
+ display in a production environment is better modeled as a :class:`pntos.api.PlatformIntegrationPlugin`,
17
+ as that is designed to represent requests from the system and not simply status updates.
18
+ """
19
+
20
+ @abstractmethod
21
+ def requires_main_thread(self) -> bool:
22
+ """
23
+ Check if this plugin needs to run on the main thread.
24
+
25
+ Some systems require GUI applications to run on the main thread. This method can be used to
26
+ query whether or not this plugin must be run on the main thread. If this method returns
27
+ True, then :meth:`run_main_thread` must be called from the main thread in order to start
28
+ this plugin.
29
+
30
+ Returns:
31
+ bool: ``True`` if plugin needs to run on the main thread, ``False`` otherwise.
32
+ """
33
+ pass
34
+
35
+ @abstractmethod
36
+ def run_main_thread(self) -> None:
37
+ """
38
+ Start plugin on the main thread.
39
+
40
+ This method should only be called if :meth:`requires_main_thread` returns True. This method
41
+ should only be called from the main thread.
42
+ """
43
+ pass