c4dynamics 2.0.3__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.
Files changed (50) hide show
  1. c4dynamics/__init__.py +240 -0
  2. c4dynamics/datasets/__init__.py +95 -0
  3. c4dynamics/datasets/_manager.py +596 -0
  4. c4dynamics/datasets/_registry.py +80 -0
  5. c4dynamics/detectors/__init__.py +37 -0
  6. c4dynamics/detectors/yolo3_opencv.py +686 -0
  7. c4dynamics/detectors/yolo3_tf.py +124 -0
  8. c4dynamics/eqm/__init__.py +324 -0
  9. c4dynamics/eqm/derivs.py +212 -0
  10. c4dynamics/eqm/integrate.py +359 -0
  11. c4dynamics/filters/__init__.py +1373 -0
  12. c4dynamics/filters/a.py +48 -0
  13. c4dynamics/filters/ekf.py +320 -0
  14. c4dynamics/filters/kalman.py +725 -0
  15. c4dynamics/filters/kalman_v0.py +1071 -0
  16. c4dynamics/filters/kalman_v1.py +821 -0
  17. c4dynamics/filters/lowpass.py +123 -0
  18. c4dynamics/filters/luenberger.py +97 -0
  19. c4dynamics/rotmat/__init__.py +141 -0
  20. c4dynamics/rotmat/animate.py +465 -0
  21. c4dynamics/rotmat/rotmat.py +351 -0
  22. c4dynamics/sensors/__init__.py +72 -0
  23. c4dynamics/sensors/lineofsight.py +78 -0
  24. c4dynamics/sensors/radar.py +740 -0
  25. c4dynamics/sensors/seeker.py +1030 -0
  26. c4dynamics/states/__init__.py +327 -0
  27. c4dynamics/states/lib/__init__.py +320 -0
  28. c4dynamics/states/lib/datapoint.py +660 -0
  29. c4dynamics/states/lib/pixelpoint.py +776 -0
  30. c4dynamics/states/lib/rigidbody.py +677 -0
  31. c4dynamics/states/state.py +1486 -0
  32. c4dynamics/utils/__init__.py +44 -0
  33. c4dynamics/utils/_struct.py +6 -0
  34. c4dynamics/utils/const.py +130 -0
  35. c4dynamics/utils/cprint.py +80 -0
  36. c4dynamics/utils/gen_gif.py +142 -0
  37. c4dynamics/utils/idx2keys.py +4 -0
  38. c4dynamics/utils/images_loader.py +63 -0
  39. c4dynamics/utils/math.py +136 -0
  40. c4dynamics/utils/plottools.py +140 -0
  41. c4dynamics/utils/plottracks.py +304 -0
  42. c4dynamics/utils/printpts.py +36 -0
  43. c4dynamics/utils/slides_gen.py +64 -0
  44. c4dynamics/utils/tictoc.py +167 -0
  45. c4dynamics/utils/video_gen.py +300 -0
  46. c4dynamics/utils/vidgen.py +182 -0
  47. c4dynamics-2.0.3.dist-info/METADATA +242 -0
  48. c4dynamics-2.0.3.dist-info/RECORD +50 -0
  49. c4dynamics-2.0.3.dist-info/WHEEL +5 -0
  50. c4dynamics-2.0.3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,48 @@
1
+ def add(a, b):
2
+ """
3
+ Adds two numbers together.
4
+
5
+ Example:
6
+ >>> add(2, 3)
7
+ 5
8
+ >>> add(0, 0)
9
+ 0
10
+ >>> add(-1, 1)
11
+ 0
12
+ """
13
+ return a + b
14
+
15
+
16
+ class Calculator:
17
+ """
18
+ A simple calculator class.
19
+
20
+ Example:
21
+ >>> calc = Calculator()
22
+ >>> calc.add(2, 3)
23
+ 5
24
+ >>> calc.subtract(5, 3)
25
+ 2
26
+ """
27
+
28
+ def add(self, a, b):
29
+ return a + b
30
+
31
+ def subtract(self, a, b):
32
+ return a - b
33
+
34
+ if __name__ == "__main__":
35
+ # import doctest
36
+ # doctest.testmod()
37
+
38
+ import sys
39
+ sys.path.append('.')
40
+ from c4dynamics.datasets._manager import sha256
41
+ print(sha256(r'C:\Users\odely\Downloads\drifting_car.mp4'))
42
+
43
+
44
+
45
+
46
+
47
+
48
+
@@ -0,0 +1,320 @@
1
+ import numpy as np
2
+ import sys
3
+ sys.path.append('.')
4
+ # import c4dynamics as c4d
5
+ from c4dynamics.filters import kalman
6
+ from typing import Optional
7
+
8
+ class ekf(kalman):
9
+ '''
10
+ Extended Kalman Filter class for handling nonlinear dynamics by
11
+ incorporating functions for nonlinear state transitions and measurements.
12
+
13
+ This subclass extends the base
14
+ :class:`kalman <c4dynamics.filters.kalman.kalman>`
15
+ class to handle cases where
16
+ system dynamics or measurements are nonlinear. The Jacobian matrices
17
+ `F` and `H` can be dynamically updated as linearizations of the
18
+ nonlinear functions.
19
+
20
+
21
+ Parameters
22
+ ----------
23
+ X : dict
24
+ Initial state estimate dictionary, where key-value pairs
25
+ represent state variables and their initial values.
26
+ P0 : np.ndarray
27
+ Initial error covariance matrix, defining the initial
28
+ uncertainty for each state variable.
29
+ F : np.ndarray, optional
30
+ State transition Jacobian matrix; defaults to an identity matrix
31
+ if not provided, assuming a linear system model.
32
+ H : np.ndarray, optional
33
+ Measurement Jacobian matrix; defaults to a zero matrix if not
34
+ provided.
35
+ G : np.ndarray, optional
36
+ Control input matrix, mapping control inputs to the state.
37
+ Q : np.ndarray, optional
38
+ Process noise covariance matrix.
39
+ R : np.ndarray, optional
40
+ Measurement noise covariance matrix.
41
+
42
+
43
+ Example
44
+ -------
45
+ A detailed example can be found in the introduction
46
+ to the c4dynamics.filters module.
47
+ The mechanism of this class is similar to
48
+ the :class:`kalman <c4dynamics.filters.kalman.kalman>`,
49
+ so the examples provided there may serve as
50
+ inspiration for using `ekf`.
51
+
52
+ '''
53
+
54
+ def __init__(self, X: dict, P0: np.ndarray
55
+ , F: Optional[np.ndarray] = None
56
+ , H: Optional[np.ndarray] = None
57
+ , G: Optional[np.ndarray] = None
58
+ , Q: Optional[np.ndarray] = None
59
+ , R: Optional[np.ndarray] = None):
60
+ # F and H are necessary also for ekf because they are required to the ricatti.
61
+ # yes but the can be delivered at each call in the immediate linearized form.
62
+
63
+ if F is None:
64
+ F = np.eye(P0.shape[0])
65
+
66
+ if H is None:
67
+ H = np.zeros(P0.shape[0])
68
+
69
+
70
+ super().__init__(X, F, H, P0 = P0, G = G, Q = Q, R = R)
71
+ self._ekf = True
72
+
73
+
74
+
75
+
76
+
77
+
78
+ def predict(self, F: Optional[np.ndarray] = None, fx: Optional[np.ndarray] = None, dt = None # type: ignore
79
+ , u: Optional[np.ndarray] = None
80
+ , Q: Optional[np.ndarray] = None):
81
+ '''
82
+ Predicts the next state of the system based on the current state
83
+ and an optional nonlinear state transition function.
84
+
85
+ Parameters
86
+ ----------
87
+ F : np.ndarray, optional
88
+ The state transition Jacobian matrix. If not provided, the
89
+ previously set `F` matrix is used.
90
+ fx : np.ndarray, optional
91
+ Nonlinear state transition function derivative. If specified,
92
+ this value is used for updating the state with nonlinear dynamics.
93
+ dt : float, optional
94
+ Time step duration. Must be provided if `fx` is specified.
95
+ u : np.ndarray, optional
96
+ Control input vector, affecting the state based on the `G` matrix.
97
+ Q : np.ndarray, optional
98
+ Process noise covariance matrix, representing uncertainty in
99
+ the model during prediction.
100
+
101
+ Raises
102
+ ------
103
+ TypeError
104
+ If `fx` is provided without a corresponding `dt` value.
105
+
106
+ Examples
107
+ --------
108
+ The examples in this section are intended to
109
+ demonstrate the usage of the `ekf` class and specifically the `predict` method.
110
+ However, they are not limited to nonlinear dynamics.
111
+ For detailed usage that highlights the properties of nonlinear dynamics,
112
+ refer to the :mod:`filters <c4dynamics.filters>` module introduction.
113
+
114
+
115
+
116
+ Import required packages:
117
+
118
+ .. code::
119
+
120
+ >>> from c4dynamics.filters import ekf
121
+
122
+
123
+
124
+ Plain `predict` step
125
+ (predict in steady-state mode where the process variance matrix
126
+ remains constant
127
+ and is provided once to initialize the filter):
128
+
129
+ .. code::
130
+
131
+ >>> _ekf = ekf({'x': 0}, P0 = 0.5**2, F = 1, H = 1, Q = 0.05, R = 200)
132
+ >>> print(_ekf)
133
+ [ x ]
134
+ >>> _ekf.X # doctest: +NUMPY_FORMAT
135
+ [0]
136
+ >>> _ekf.P # doctest: +NUMPY_FORMAT
137
+ [[0.25]]
138
+ >>> _ekf.predict()
139
+ >>> _ekf.X # doctest: +NUMPY_FORMAT
140
+ [0]
141
+ >>> _ekf.P # doctest: +NUMPY_FORMAT
142
+ [[0.3]]
143
+
144
+
145
+ Predict with control input:
146
+
147
+ .. code::
148
+
149
+ >>> _ekf = ekf({'x': 0}, P0 = 0.5**2, F = 1, G = 150, H = 1, R = 200, Q = 0.05)
150
+ >>> _ekf.X # doctest: +NUMPY_FORMAT
151
+ [0]
152
+ >>> _ekf.P # doctest: +NUMPY_FORMAT
153
+ [[0.25]]
154
+ >>> _ekf.predict(u = 1)
155
+ >>> _ekf.X # doctest: +NUMPY_FORMAT
156
+ [150]
157
+ >>> _ekf.P # doctest: +NUMPY_FORMAT
158
+ [[0.3]]
159
+
160
+
161
+
162
+ Predict with updated process noise covariance matrix:
163
+
164
+ .. code::
165
+
166
+ >>> _ekf = ekf({'x': 0}, P0 = 0.5**2, F = 1, G = 150, H = 1, R = 200, Q = 0.05)
167
+ >>> _ekf.X # doctest: +NUMPY_FORMAT
168
+ [0]
169
+ >>> _ekf.P # doctest: +NUMPY_FORMAT
170
+ [[0.25]]
171
+ >>> _ekf.predict(u = 1, Q = 0.01)
172
+ >>> _ekf.X # doctest: +NUMPY_FORMAT
173
+ [150]
174
+ >>> _ekf.P # doctest: +NUMPY_FORMAT
175
+ [[0.26]]
176
+
177
+
178
+
179
+
180
+ '''
181
+
182
+ if fx is not None:
183
+ if dt is None:
184
+ raise TypeError('For nonlinear derivatives inpout (fx), dt must be provided.')
185
+ self.X += np.atleast_1d(fx).ravel() * dt
186
+ self._nonlinearF = True
187
+
188
+
189
+ if F is not None:
190
+ # "if F" is not enough because F is an array and
191
+ # the truth value of an array with more than one
192
+ # element is ambiguous.
193
+ self.F = np.atleast_2d(F)
194
+
195
+ super().predict(u = u, Q = Q)
196
+
197
+ self._nonlinearF = True
198
+
199
+
200
+
201
+ def update(self, z: np.ndarray # type: ignore
202
+ , H: Optional[np.ndarray] = None
203
+ , hx: Optional[np.ndarray] = None
204
+ , R: Optional[np.ndarray] = None
205
+ ):
206
+
207
+ '''
208
+ Updates the state estimate based on the latest measurement, using an
209
+ optional nonlinear measurement function.
210
+
211
+ Parameters
212
+ ----------
213
+ z : np.ndarray
214
+ Measurement vector, representing observed values from the system.
215
+ H : np.ndarray, optional
216
+ Measurement Jacobian matrix. If provided, it overrides the
217
+ previously set `H` matrix for this update step.
218
+ hx : np.ndarray, optional
219
+ Nonlinear measurement function output. If provided, it is used
220
+ as the current estimate of the state based on measurement data.
221
+ R : np.ndarray, optional
222
+ Measurement noise covariance matrix, representing the uncertainty
223
+ in the measurements.
224
+
225
+
226
+ Examples
227
+ --------
228
+ The examples in this section are intended to
229
+ demonstrate the usage of the `ekf` class and specifically the `update` method.
230
+ However, they are not limited to nonlinear dynamics.
231
+ For detailed usage that highlights the properties of nonlinear dynamics,
232
+ refer to the :mod:`filters <c4dynamics.filters>` module introduction.
233
+
234
+
235
+ Import required packages:
236
+
237
+ .. code::
238
+
239
+ >>> from c4dynamics.filters import ekf
240
+
241
+
242
+
243
+ Plain update step:
244
+
245
+ .. code::
246
+
247
+ >>> _ekf = ekf({'x': 0}, P0 = 0.5**2, F = 1, H = 1, Q = 0.05, R = 200)
248
+ >>> print(_ekf)
249
+ [ x ]
250
+ >>> _ekf.X # doctest: +NUMPY_FORMAT
251
+ [0]
252
+ >>> _ekf.P # doctest: +NUMPY_FORMAT
253
+ [[0.25]]
254
+ >>> _ekf.update(z = 100) # returns Kalman gain # doctest: +NUMPY_FORMAT
255
+ [[0.001...]]
256
+ >>> _ekf.X # doctest: +NUMPY_FORMAT
257
+ [0.124...]
258
+ >>> _ekf.P # doctest: +NUMPY_FORMAT
259
+ [[0.249...]]
260
+
261
+
262
+
263
+ Update with modified measurement noise covariance matrix:
264
+
265
+ .. code::
266
+
267
+ >>> _ekf = ekf({'x': 0}, P0 = 0.5**2, F = 1, G = 150, H = 1, R = 200, Q = 0.05)
268
+ >>> _ekf.X # doctest: +NUMPY_FORMAT
269
+ [0]
270
+ >>> _ekf.P # doctest: +NUMPY_FORMAT
271
+ [[0.25]]
272
+ >>> K = _ekf.update(z = 150, R = 0)
273
+ >>> K # doctest: +NUMPY_FORMAT
274
+ [[1]]
275
+ >>> _ekf.X # doctest: +NUMPY_FORMAT
276
+ [150]
277
+ >>> _ekf.P # doctest: +NUMPY_FORMAT
278
+ [[0]]
279
+
280
+ '''
281
+ if hx is not None:
282
+ self.X = hx
283
+ self._nonlinearH = True
284
+
285
+ if H is not None:
286
+ self.H = np.atleast_2d(H)
287
+
288
+ K = super().update(z = z, R = R)
289
+ self._nonlinearH = False
290
+ return K
291
+
292
+
293
+
294
+ if __name__ == "__main__":
295
+
296
+ import doctest, contextlib, os
297
+ from c4dynamics import IgnoreOutputChecker, cprint
298
+
299
+ # Register the custom OutputChecker
300
+ doctest.OutputChecker = IgnoreOutputChecker
301
+
302
+ tofile = False
303
+ optionflags = doctest.FAIL_FAST
304
+
305
+ if tofile:
306
+ with open(os.path.join('tests', '_out', 'output.txt'), 'w') as f:
307
+ with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f):
308
+ result = doctest.testmod(optionflags = optionflags)
309
+ else:
310
+ result = doctest.testmod(optionflags = optionflags)
311
+
312
+ if result.failed == 0:
313
+ cprint(os.path.basename(__file__) + ": all tests passed!", 'g')
314
+ else:
315
+ print(f"{result.failed}")
316
+
317
+
318
+
319
+
320
+