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,414 @@
|
|
|
1
|
+
"""Python API of pntOS."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from enum import IntEnum
|
|
6
|
+
from typing import Any, TypeVar
|
|
7
|
+
|
|
8
|
+
from aspn23 import AspnBase, MeasurementImu, TypeTimestamp
|
|
9
|
+
from numpy import float64
|
|
10
|
+
from numpy.typing import NDArray
|
|
11
|
+
|
|
12
|
+
from .common import CommonPlugin, Message
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class InertialFrame(IntEnum):
|
|
16
|
+
"""
|
|
17
|
+
An enumeration that specifies frame.
|
|
18
|
+
|
|
19
|
+
Caution:
|
|
20
|
+
**Unstable**: This feature is unstable and is not yet considered part of the stable pntOS
|
|
21
|
+
API. Usage of this feature is highly discouraged in non-experimental code, and its
|
|
22
|
+
definition may change at any time.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
INERTIAL_FRAME_NED = 0
|
|
26
|
+
"""
|
|
27
|
+
Force vectors in this frame are north-east-down in :math:`m/s^2`.
|
|
28
|
+
|
|
29
|
+
Rotation rate vectors in this frame are of an inertial sensor with respect to inertial frame, in
|
|
30
|
+
the inertial sensor frame (:math:`rad/s`). Sometimes represented as
|
|
31
|
+
:math:`w^\\text{s}_\\text{is}` (or :math:`w^\\text{b}_\\text{ib}` if the body frame is aligned
|
|
32
|
+
with the inertial sensor frame.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass
|
|
37
|
+
class InertialForcesRates:
|
|
38
|
+
"""
|
|
39
|
+
A struct containing specific forces and rotation rates from the inertial.
|
|
40
|
+
|
|
41
|
+
Caution:
|
|
42
|
+
**Unstable**: This feature is unstable and is not yet considered part of the stable pntOS
|
|
43
|
+
API. Usage of this feature is highly discouraged in non-experimental code, and its
|
|
44
|
+
definition may change at any time.
|
|
45
|
+
|
|
46
|
+
Attributes:
|
|
47
|
+
forces_and_rates (MeasurementImu): An ASPN IMU message which has been repurposed to hold
|
|
48
|
+
specific forces (the ``meas_accel`` field) and rotation rates (the ``meas_gyro`` field)
|
|
49
|
+
in a different frame (see :attr:`frame` below).
|
|
50
|
+
frame (InertialFrame): Specifies the frame of the above forces and rates.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
forces_and_rates: MeasurementImu
|
|
54
|
+
frame: InertialFrame
|
|
55
|
+
"""The frame at which the forces and rates are valid.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass
|
|
60
|
+
class StandardInertialErrors:
|
|
61
|
+
"""
|
|
62
|
+
A structure representing the biases on a set of 3-axis gyros and 3-axis accelerometers.
|
|
63
|
+
|
|
64
|
+
Caution:
|
|
65
|
+
**Unstable**: This feature is unstable and is not yet considered part of the stable pntOS
|
|
66
|
+
API. Usage of this feature is highly discouraged in non-experimental code, and its
|
|
67
|
+
definition may change at any time.
|
|
68
|
+
|
|
69
|
+
Attributes:
|
|
70
|
+
accel_biases (NDArray[float64]): A 1D vector of length 3 containing biases for a 3-axis accelerometer
|
|
71
|
+
in the sensor's (X-Y-Z) frame, expressed in :math:`m/s^2`.
|
|
72
|
+
gyro_biases (NDArray[float64]): A 1D vector of length 3 containing biases for a 3-axis gyro in the
|
|
73
|
+
sensor's (X-Y-Z) frame, expressed in :math:`rad/s`.
|
|
74
|
+
accel_scale_factors (NDArray[float64]): A 1D vector of length 3 containing scale factor errors for a
|
|
75
|
+
3-axis accelerometer in the sensor's (X-Y-Z) frame, unitless.
|
|
76
|
+
gyro_scale_factors (NDArray[float64]): A 1D vector of length 3 containing scale factor errors for a
|
|
77
|
+
3-axis gyroscope in the sensor's (X-Y-Z) frame, unitless.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
accel_biases: NDArray[float64]
|
|
81
|
+
gyro_biases: NDArray[float64]
|
|
82
|
+
accel_scale_factors: NDArray[float64]
|
|
83
|
+
gyro_scale_factors: NDArray[float64]
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class InertialSolutionRangeType(IntEnum):
|
|
87
|
+
"""
|
|
88
|
+
Solution type to request from an inertial.
|
|
89
|
+
|
|
90
|
+
An enumeration that allows the user to decide if the solution they request is the best available
|
|
91
|
+
solution or one that has no discontinuities in it due to resets.
|
|
92
|
+
|
|
93
|
+
Caution:
|
|
94
|
+
**Unstable**: This feature is unstable and is not yet considered part of the stable pntOS
|
|
95
|
+
API. Usage of this feature is highly discouraged in non-experimental code, and its
|
|
96
|
+
definition may change at any time.
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
INERTIAL_BEST_KNOWN_SOLUTION = 0
|
|
100
|
+
INERTIAL_NO_UPDATES_WITHIN_RANGE = 1
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class CommonInertial(ABC):
|
|
104
|
+
"""
|
|
105
|
+
A common base type for an inertial.
|
|
106
|
+
|
|
107
|
+
Caution:
|
|
108
|
+
**Unstable**: This feature is unstable and is not yet considered part of the stable pntOS
|
|
109
|
+
API. Usage of this feature is highly discouraged in non-experimental code, and its
|
|
110
|
+
definition may change at any time.
|
|
111
|
+
"""
|
|
112
|
+
|
|
113
|
+
@abstractmethod
|
|
114
|
+
def request_solution_message_type(self) -> type[AspnBase]:
|
|
115
|
+
"""
|
|
116
|
+
Get the solution type.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
type[AspnBase]: The message type that will be returned by
|
|
120
|
+
:meth:`request_current_solution`, :meth:`request_solution`, and
|
|
121
|
+
:meth:`request_solutions`.
|
|
122
|
+
"""
|
|
123
|
+
pass
|
|
124
|
+
|
|
125
|
+
@abstractmethod
|
|
126
|
+
def request_current_solution(self) -> Message:
|
|
127
|
+
"""
|
|
128
|
+
Get the current inertial solution.
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
Message: The current inertial solution.
|
|
132
|
+
"""
|
|
133
|
+
pass
|
|
134
|
+
|
|
135
|
+
@abstractmethod
|
|
136
|
+
def request_solution(self, time: TypeTimestamp) -> Message | None:
|
|
137
|
+
"""
|
|
138
|
+
Request solution at a specific time.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
time (TypeTimestamp): The time at which the returned solution should be valid.
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
Message | None: The solution computed by this inertial at ``time`` if ``time`` is in the
|
|
145
|
+
valid range, ``None`` otherwise (:meth:`is_time_in_range` can be used to check ``time``
|
|
146
|
+
before calling this method).
|
|
147
|
+
"""
|
|
148
|
+
pass
|
|
149
|
+
|
|
150
|
+
@abstractmethod
|
|
151
|
+
def request_solutions(
|
|
152
|
+
self, times: list[TypeTimestamp], solution_type: InertialSolutionRangeType
|
|
153
|
+
) -> list[Message | None] | None:
|
|
154
|
+
"""
|
|
155
|
+
Request solutions at multiple specific times.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
times (list[TypeTimestamp]): An array of times at which solutions are requested.
|
|
159
|
+
solution_type (InertialSolutionRangeType): The type of solution requested.
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
list[Message | None] | None: An array of solutions. Returns ``None`` if ``solution_type`` is unsupported
|
|
163
|
+
by this inertial or every instance of ``times`` is outside the valid range. Otherwise
|
|
164
|
+
guaranteed to not be ``None``.
|
|
165
|
+
"""
|
|
166
|
+
pass
|
|
167
|
+
|
|
168
|
+
@abstractmethod
|
|
169
|
+
def is_time_in_range(self, time: TypeTimestamp) -> bool:
|
|
170
|
+
"""
|
|
171
|
+
Check if a solution exists at a given time.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
time (TypeTimestamp): The query time.
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
bool: ``True`` if a solution exists at ``time``, ``False`` otherwise. This result is
|
|
178
|
+
only valid until another method (for example, :meth:`process_pntos_message`) is called.
|
|
179
|
+
"""
|
|
180
|
+
pass
|
|
181
|
+
|
|
182
|
+
@abstractmethod
|
|
183
|
+
def request_earliest_time(self) -> TypeTimestamp:
|
|
184
|
+
"""
|
|
185
|
+
Get the earliest available time at which a solution or forces and rates can be requested.
|
|
186
|
+
|
|
187
|
+
This result is only valid until another method (for example, :meth:`process_pntos_message`)
|
|
188
|
+
is called.
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
TypeTimestamp: The earliest available time at which a solution or forces and rates can
|
|
192
|
+
be requested.
|
|
193
|
+
"""
|
|
194
|
+
pass
|
|
195
|
+
|
|
196
|
+
@abstractmethod
|
|
197
|
+
def request_latest_time(self) -> TypeTimestamp:
|
|
198
|
+
"""
|
|
199
|
+
Get the latest available time at which a solution or forces and rates can be requested.
|
|
200
|
+
|
|
201
|
+
This result is only valid until another method (for example, :meth:`process_pntos_message`)
|
|
202
|
+
is called.
|
|
203
|
+
|
|
204
|
+
Returns:
|
|
205
|
+
TypeTimestamp: The latest available time at which a solution or forces and rates can
|
|
206
|
+
be requested.
|
|
207
|
+
"""
|
|
208
|
+
pass
|
|
209
|
+
|
|
210
|
+
@abstractmethod
|
|
211
|
+
def request_process_pntos_message_types(self) -> list[type[AspnBase]]:
|
|
212
|
+
"""
|
|
213
|
+
Returns an array of message types that are supported by this plugin.
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
list[type[AspnBase]]: An array of message types that are supported by this plugin as
|
|
217
|
+
inputs to :meth:`process_pntos_message`.
|
|
218
|
+
"""
|
|
219
|
+
pass
|
|
220
|
+
|
|
221
|
+
@abstractmethod
|
|
222
|
+
def process_pntos_message(self, message: Message) -> None:
|
|
223
|
+
"""
|
|
224
|
+
A new message to be incorporated into the computed inertial solution.
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
message (Message)
|
|
228
|
+
"""
|
|
229
|
+
pass
|
|
230
|
+
|
|
231
|
+
@abstractmethod
|
|
232
|
+
def request_forces_and_rates(
|
|
233
|
+
self, time: TypeTimestamp
|
|
234
|
+
) -> InertialForcesRates | None:
|
|
235
|
+
"""
|
|
236
|
+
Request forces and rates for a given time.
|
|
237
|
+
|
|
238
|
+
Args:
|
|
239
|
+
time (TypeTimestamp): The time at which the forces and rates should be valid.
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
InertialForcesRates | None: The instantaneous forces and rates at ``time`` if ``time``
|
|
243
|
+
is in the valid range, ``None`` otherwise (:meth:`is_time_in_range` can be used to check
|
|
244
|
+
``time`` before calling this method).
|
|
245
|
+
"""
|
|
246
|
+
pass
|
|
247
|
+
|
|
248
|
+
@abstractmethod
|
|
249
|
+
def request_average_forces_and_rates(
|
|
250
|
+
self, time1: TypeTimestamp, time2: TypeTimestamp
|
|
251
|
+
) -> InertialForcesRates | None:
|
|
252
|
+
"""
|
|
253
|
+
Request average forces and rates over a time period.
|
|
254
|
+
|
|
255
|
+
Args:
|
|
256
|
+
time1 (TypeTimestamp): The start of the time range over which the forces and rates
|
|
257
|
+
should be valid.
|
|
258
|
+
time2 (TypeTimestamp): The end of the time range over which the forces
|
|
259
|
+
and rates should be valid.
|
|
260
|
+
|
|
261
|
+
Returns:
|
|
262
|
+
InertialForcesRates | None: The average forces and rates over the period of time defined
|
|
263
|
+
by ``time1`` and ``time2`` if at least one of them is in the valid range, ``None``
|
|
264
|
+
otherwise (:meth:`is_time_in_range` can be used to check both times before calling this
|
|
265
|
+
method).
|
|
266
|
+
"""
|
|
267
|
+
pass
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
# The external inertial case does not need any extra functionality, so just alias the base class
|
|
271
|
+
# rather than inheriting from it and adding nothing.
|
|
272
|
+
ExternalInertial = CommonInertial
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
class StandardInertialMechanization(CommonInertial, ABC):
|
|
276
|
+
"""
|
|
277
|
+
A struct produced by a :class:`pntos.api.InertialPlugin`. It generates solutions from raw IMU data.
|
|
278
|
+
|
|
279
|
+
Caution:
|
|
280
|
+
**Unstable**: This feature is unstable and is not yet considered part of the stable pntOS
|
|
281
|
+
API. Usage of this feature is highly discouraged in non-experimental code, and its
|
|
282
|
+
definition may change at any time.
|
|
283
|
+
"""
|
|
284
|
+
|
|
285
|
+
@abstractmethod
|
|
286
|
+
def request_reset_message_types(self) -> list[type[AspnBase]] | None:
|
|
287
|
+
"""
|
|
288
|
+
Get valid types of reset messages.
|
|
289
|
+
|
|
290
|
+
Returns:
|
|
291
|
+
list[type[AspnBase]] | None: An array of message types that are supported by this plugin
|
|
292
|
+
for resetting the inertial solution, or ``None`` if resetting the inertial solution is
|
|
293
|
+
an unsupported operation by the inertial plugin.
|
|
294
|
+
"""
|
|
295
|
+
pass
|
|
296
|
+
|
|
297
|
+
@abstractmethod
|
|
298
|
+
def reset_solution(self, message: Message) -> None:
|
|
299
|
+
"""
|
|
300
|
+
Set the solution to the values in ``message``.
|
|
301
|
+
|
|
302
|
+
For example, if ``message`` is PVA then the inertial solution will be set to that PVA. If
|
|
303
|
+
``message`` is just position, then only the position portion of the inertial solution will
|
|
304
|
+
be set using ``message``.
|
|
305
|
+
|
|
306
|
+
Args:
|
|
307
|
+
message (Message): A message containing the information necessary to reset the solution.
|
|
308
|
+
To see the types supported by the implementation, call
|
|
309
|
+
:meth:`request_reset_message_types`.
|
|
310
|
+
"""
|
|
311
|
+
pass
|
|
312
|
+
|
|
313
|
+
@abstractmethod
|
|
314
|
+
def correct_sensor_errors(
|
|
315
|
+
self, time: TypeTimestamp, errors: StandardInertialErrors
|
|
316
|
+
) -> None:
|
|
317
|
+
"""
|
|
318
|
+
Reset the current inertial internal bias values.
|
|
319
|
+
|
|
320
|
+
Reset the current inertial internal bias values with corrections from an external source,
|
|
321
|
+
such as a filter or error estimator. The errors passed in here will be adjusted for
|
|
322
|
+
internally by the inertial when processing incoming data. Thus, if errors are passed into the
|
|
323
|
+
inertial here they should not be corrected for in an external filter processing the inertial
|
|
324
|
+
output (which would lead to a double correction).
|
|
325
|
+
|
|
326
|
+
Args:
|
|
327
|
+
time (TypeTimestamp): The time at which ``errors`` should be valid.
|
|
328
|
+
errors (StandardInertialErrors): An estimate of the inertial sensor's errors.
|
|
329
|
+
"""
|
|
330
|
+
pass
|
|
331
|
+
|
|
332
|
+
@abstractmethod
|
|
333
|
+
def request_sensor_errors(
|
|
334
|
+
self, time: TypeTimestamp
|
|
335
|
+
) -> StandardInertialErrors | None:
|
|
336
|
+
"""
|
|
337
|
+
Request inertial errors for a given time.
|
|
338
|
+
|
|
339
|
+
Args:
|
|
340
|
+
time (TypeTimestamp): Time at which inertial errors should be valid.
|
|
341
|
+
|
|
342
|
+
Returns:
|
|
343
|
+
StandardInertialErrors | None: Inertial errors at ``time`` if ``time`` is in the valid
|
|
344
|
+
range (:meth:`pntos.api.CommonInertial.is_time_in_range` can be used to check ``time`` before
|
|
345
|
+
calling this method), ``None`` otherwise.
|
|
346
|
+
"""
|
|
347
|
+
pass
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
InertialType = TypeVar(
|
|
351
|
+
'InertialType', StandardInertialMechanization, ExternalInertial, Any
|
|
352
|
+
)
|
|
353
|
+
"""
|
|
354
|
+
An enumeration of the types of inertials an inertial plugin could provide.
|
|
355
|
+
|
|
356
|
+
"Any" is included for future compatibility.
|
|
357
|
+
"""
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
class InertialPlugin(CommonPlugin, ABC):
|
|
361
|
+
"""
|
|
362
|
+
An implementation of an inertial plugin.
|
|
363
|
+
|
|
364
|
+
This plugin generates :class:`pntos.api.CommonInertial` instances which may be used to generate INS
|
|
365
|
+
solutions from raw IMU data.
|
|
366
|
+
|
|
367
|
+
Caution:
|
|
368
|
+
**Unstable**: This feature is unstable and is not yet considered part of the stable pntOS
|
|
369
|
+
API. Usage of this feature is highly discouraged in non-experimental code, and its
|
|
370
|
+
definition may change at any time.
|
|
371
|
+
"""
|
|
372
|
+
|
|
373
|
+
@abstractmethod
|
|
374
|
+
def is_inertial_type_supported(self, inertial_type: type[InertialType]) -> bool:
|
|
375
|
+
"""
|
|
376
|
+
Check if the plugin supports a given type of inertial.
|
|
377
|
+
|
|
378
|
+
Args:
|
|
379
|
+
inertial_type (type[InertialType])
|
|
380
|
+
|
|
381
|
+
Returns:
|
|
382
|
+
bool: ``True`` if inertial type is supported, ``False`` otherwise.
|
|
383
|
+
"""
|
|
384
|
+
pass
|
|
385
|
+
|
|
386
|
+
@abstractmethod
|
|
387
|
+
def new_inertial(
|
|
388
|
+
self,
|
|
389
|
+
inertial_type: type[InertialType],
|
|
390
|
+
solution: Message,
|
|
391
|
+
config_group: str | None = None,
|
|
392
|
+
) -> InertialType | None:
|
|
393
|
+
"""
|
|
394
|
+
Create an instance of an implementation of :class:`pntos.api.CommonInertial`.
|
|
395
|
+
|
|
396
|
+
Args:
|
|
397
|
+
inertial_type (type[InertialType]): Specifies the type of inertial that the returned value will
|
|
398
|
+
support. For example, if the user passes in ``STANDARD_INERTIAL_MECHANIZATION``,
|
|
399
|
+
then the returned value will be an implementation of
|
|
400
|
+
:class:`pntos.api.StandardInertialMechanization`. If ``inertial_type`` is unsupported by the plugin,
|
|
401
|
+
then ``None`` will be returned. Please use :meth:`is_inertial_type_supported` to
|
|
402
|
+
check if the type is supported by the plugin.
|
|
403
|
+
solution (Message): The initial solution (i.e. the alignment) to mechanize from.
|
|
404
|
+
config_group (str | None, optional): An optional parameter which can be used to specify
|
|
405
|
+
which group in the config should be used to initialize the new inertial. This allows
|
|
406
|
+
for multiple inertial instances to exist with unique settings.
|
|
407
|
+
|
|
408
|
+
Returns:
|
|
409
|
+
InertialType | None: A new inertial object. Returns ``None`` if ``inertial_type`` is
|
|
410
|
+
unsupported, ``solution`` is invalid, or ``config_group`` is invalid.
|
|
411
|
+
:meth:`is_inertial_type_supported` can be called to verify ``inertial_type`` before calling this
|
|
412
|
+
method.
|
|
413
|
+
"""
|
|
414
|
+
pass
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
"""Python API of pntOS."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from enum import IntEnum
|
|
6
|
+
from typing import Any, TypeVar
|
|
7
|
+
|
|
8
|
+
from aspn23 import TypeTimestamp
|
|
9
|
+
from numpy import float64
|
|
10
|
+
from numpy.typing import NDArray
|
|
11
|
+
|
|
12
|
+
from .common import CommonPlugin, EstimateWithCovariance, Message
|
|
13
|
+
from .inertial import StandardInertialErrors
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class InitializationStatus(IntEnum):
|
|
17
|
+
"""
|
|
18
|
+
An enumeration that allows the user to know the initialization status.
|
|
19
|
+
|
|
20
|
+
Caution:
|
|
21
|
+
**Unstable**: This feature is unstable and is not yet considered part of the stable pntOS
|
|
22
|
+
API. Usage of this feature is highly discouraged in non-experimental code, and its
|
|
23
|
+
definition may change at any time.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
WAITING = 0
|
|
27
|
+
"""Waiting to start initialization process."""
|
|
28
|
+
|
|
29
|
+
INITIALIZING_COARSE = 1
|
|
30
|
+
"""Attempting to initialize and produce a navigation solution."""
|
|
31
|
+
|
|
32
|
+
INITIALIZING_FINE = 2
|
|
33
|
+
"""
|
|
34
|
+
A coarse initialization has been calculated by the algorithm, and the initialization is being
|
|
35
|
+
tested or adjusted before producing a navigation solution.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
INITIALIZED_GOOD = 3
|
|
39
|
+
"""
|
|
40
|
+
We have a good initialization.
|
|
41
|
+
|
|
42
|
+
The provided solution can be used to kickoff inertial and fusion.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
INITIALIZATION_FAILED = 4
|
|
46
|
+
"""The initialization process failed in some way, and may attempt to restart."""
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class InitializationMotionNeeded(IntEnum):
|
|
50
|
+
"""
|
|
51
|
+
An enumeration that specifies what type of motion is required by the initialization strategy.
|
|
52
|
+
|
|
53
|
+
Caution:
|
|
54
|
+
**Unstable**: This feature is unstable and is not yet considered part of the stable pntOS
|
|
55
|
+
API. Usage of this feature is highly discouraged in non-experimental code, and its
|
|
56
|
+
definition may change at any time.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
NO_MOTION = 0
|
|
60
|
+
"""Stationary data is needed."""
|
|
61
|
+
|
|
62
|
+
MOTION_NEEDED = 1
|
|
63
|
+
"""Dynamic data is needed."""
|
|
64
|
+
|
|
65
|
+
ANY_MOTION = 2
|
|
66
|
+
"""No particular type of motion is required."""
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class CommonInitializationStrategy(ABC):
|
|
70
|
+
"""
|
|
71
|
+
A common base type for initialization algorithms.
|
|
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
|
+
@abstractmethod
|
|
80
|
+
def request_motion_needed(self) -> InitializationMotionNeeded:
|
|
81
|
+
"""
|
|
82
|
+
Check the type of motion (if any) needed.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
InitializationMotionNeeded
|
|
86
|
+
"""
|
|
87
|
+
pass
|
|
88
|
+
|
|
89
|
+
@abstractmethod
|
|
90
|
+
def request_current_status(self) -> InitializationStatus:
|
|
91
|
+
"""
|
|
92
|
+
Check the current initialization status.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
InitializationStatus
|
|
96
|
+
"""
|
|
97
|
+
pass
|
|
98
|
+
|
|
99
|
+
@abstractmethod
|
|
100
|
+
def process_pntos_message(self, message: Message) -> None:
|
|
101
|
+
"""
|
|
102
|
+
Incorporate a new message into the initialization algorithm.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
message (Message)
|
|
106
|
+
"""
|
|
107
|
+
pass
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@dataclass
|
|
111
|
+
class InitialInertialSolution:
|
|
112
|
+
"""
|
|
113
|
+
Holds both the current solution, inertial errors (and their covariance), and the current status.
|
|
114
|
+
|
|
115
|
+
Coupling these avoids time-of-check to time-of-use (TOCTOU) issues.
|
|
116
|
+
|
|
117
|
+
Attributes:
|
|
118
|
+
solution (Message | None): The initial solution.
|
|
119
|
+
inertial_errors (StandardInertialErrors | None): The inertial errors.
|
|
120
|
+
inertial_error_covariance (NDArray[float64] | None): The covariance matrix associated with the terms
|
|
121
|
+
in ``inertial_errors``.
|
|
122
|
+
status (InitializationStatus): Indicates the current initialization status. Should be
|
|
123
|
+
checked before using any of the other fields.
|
|
124
|
+
|
|
125
|
+
Caution:
|
|
126
|
+
**Unstable**: This feature is unstable and is not yet considered part of the stable pntOS
|
|
127
|
+
API. Usage of this feature is highly discouraged in non-experimental code, and its
|
|
128
|
+
definition may change at any time.
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
solution: Message | None
|
|
132
|
+
inertial_errors: StandardInertialErrors | None
|
|
133
|
+
inertial_error_covariance: NDArray[float64] | None
|
|
134
|
+
status: InitializationStatus
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class InertialInitializationStrategy(CommonInitializationStrategy, ABC):
|
|
138
|
+
"""
|
|
139
|
+
Generates an initial ASPN solution from sensor data.
|
|
140
|
+
|
|
141
|
+
Caution:
|
|
142
|
+
**Unstable**: This feature is unstable and is not yet considered part of the stable pntOS
|
|
143
|
+
API. Usage of this feature is highly discouraged in non-experimental code, and its
|
|
144
|
+
definition may change at any time.
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
@abstractmethod
|
|
148
|
+
def request_solution(self) -> InitialInertialSolution:
|
|
149
|
+
"""
|
|
150
|
+
Get the current initial solution.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
InitialInertialSolution
|
|
154
|
+
"""
|
|
155
|
+
pass
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@dataclass
|
|
159
|
+
class InitialEstimateWithCovariance:
|
|
160
|
+
"""
|
|
161
|
+
Holds both the current estimate and its associated covariance as well as the current status.
|
|
162
|
+
|
|
163
|
+
Coupling these avoids time-of-check to time-of-use (TOCTOU) issues.
|
|
164
|
+
|
|
165
|
+
Attributes:
|
|
166
|
+
time (TypeTimestamp): The time at which ``estimate_with_covariance`` is valid.
|
|
167
|
+
estimate_with_covariance (EstimateWithCovariance | None): The current estimate of the
|
|
168
|
+
initial solution. Check ``status`` for its validity (can be ``None`` if ``status`` is
|
|
169
|
+
anything other than ``INITIALIZED_GOOD``).
|
|
170
|
+
status (InitializationStatus): Indicates the current initialization status. Should be
|
|
171
|
+
checked before using ``estimate_with_covariance``.
|
|
172
|
+
|
|
173
|
+
Caution:
|
|
174
|
+
**Unstable**: This feature is unstable and is not yet considered part of the stable pntOS
|
|
175
|
+
API. Usage of this feature is highly discouraged in non-experimental code, and its
|
|
176
|
+
definition may change at any time.
|
|
177
|
+
"""
|
|
178
|
+
|
|
179
|
+
time: TypeTimestamp
|
|
180
|
+
estimate_with_covariance: EstimateWithCovariance | None
|
|
181
|
+
status: InitializationStatus
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class EwcInitializationStrategy(CommonInitializationStrategy):
|
|
185
|
+
"""
|
|
186
|
+
Generates an initial estimate-with-covariance (EWC) solution from sensor data.
|
|
187
|
+
|
|
188
|
+
Caution:
|
|
189
|
+
**Unstable**: This feature is unstable and is not yet considered part of the stable pntOS
|
|
190
|
+
API. Usage of this feature is highly discouraged in non-experimental code, and its
|
|
191
|
+
definition may change at any time.
|
|
192
|
+
"""
|
|
193
|
+
|
|
194
|
+
@abstractmethod
|
|
195
|
+
def request_solution(self) -> InitialEstimateWithCovariance | None:
|
|
196
|
+
"""
|
|
197
|
+
Get the current initial solution.
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
InitialEstimateWithCovariance | None: The current initial solution. Will be ``None`` if
|
|
201
|
+
the initialization strategy has not yet finished. Use
|
|
202
|
+
:meth:`pntos.api.CommonInitializationStrategy.request_current_status` to check current status of
|
|
203
|
+
the strategy. If the status is ``INITIALIZING_FINE`` or ``INITIALIZED_GOOD``, then the
|
|
204
|
+
result is guaranteed to not be ``None``.
|
|
205
|
+
"""
|
|
206
|
+
pass
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
InitializationType = TypeVar(
|
|
210
|
+
'InitializationType',
|
|
211
|
+
InertialInitializationStrategy,
|
|
212
|
+
EwcInitializationStrategy,
|
|
213
|
+
Any,
|
|
214
|
+
)
|
|
215
|
+
"""
|
|
216
|
+
An enumeration of the types of initializers an initializer plugin could provide.
|
|
217
|
+
|
|
218
|
+
"Any" is included for future compatibility.
|
|
219
|
+
"""
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class InitializationPlugin(CommonPlugin, ABC):
|
|
223
|
+
"""
|
|
224
|
+
An implementation of an initialization plugin.
|
|
225
|
+
|
|
226
|
+
This plugin generates :class:`pntos.api.CommonInitializationStrategy` instances which may be used to
|
|
227
|
+
generate an initial solution from additional external sensor data, such as IMU data.
|
|
228
|
+
|
|
229
|
+
Caution:
|
|
230
|
+
**Unstable**: This feature is unstable and is not yet considered part of the stable pntOS
|
|
231
|
+
API. Usage of this feature is highly discouraged in non-experimental code, and its
|
|
232
|
+
definition may change at any time.
|
|
233
|
+
"""
|
|
234
|
+
|
|
235
|
+
@abstractmethod
|
|
236
|
+
def is_initialization_type_supported(
|
|
237
|
+
self, initialization_type: type[InitializationType]
|
|
238
|
+
) -> bool:
|
|
239
|
+
"""
|
|
240
|
+
Check if given ``InitializationType`` is supported.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
initialization_type (type[InitializationType])
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
bool: ``True`` if the plugin supports a given type of mechanization, ``False``
|
|
247
|
+
otherwise.
|
|
248
|
+
"""
|
|
249
|
+
pass
|
|
250
|
+
|
|
251
|
+
@abstractmethod
|
|
252
|
+
def new_initialization_strategy(
|
|
253
|
+
self,
|
|
254
|
+
initialization_type: type[InitializationType],
|
|
255
|
+
config_group: str | None = None,
|
|
256
|
+
) -> InitializationType | None:
|
|
257
|
+
"""
|
|
258
|
+
Create an instance of :class:`pntos.api.CommonInitializationStrategy`.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
initialization_type (type[InitializationType]): Specifies the type of initializer that the returned
|
|
262
|
+
value will support. For example, if the user passes in
|
|
263
|
+
``INERTIAL_INITIALIZATION_STRATEGY``, then the returned value will be an
|
|
264
|
+
implementation of :class:`pntos.api.InertialInitializationStrategy`. If ``initialization_type`` is
|
|
265
|
+
unsupported by the plugin, then ``None`` will be returned. Please use
|
|
266
|
+
:meth:`is_initialization_type_supported` to check if the type is supported by the
|
|
267
|
+
plugin.
|
|
268
|
+
config_group (str | None, optional): An optional parameter which can be used to specify
|
|
269
|
+
which group in the config should be used to set up the new initialization strategy.
|
|
270
|
+
This allows for multiple initialization strategy instances to exist with unique
|
|
271
|
+
settings.
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
InitializationType | None: The new initialization strategy object. Returns ``None``
|
|
275
|
+
if ``initialization_type`` is unsupported by this plugin (this can be checked using
|
|
276
|
+
:meth:`is_initialization_type_supported`) or if ``config_group`` is invalid.
|
|
277
|
+
"""
|
|
278
|
+
pass
|