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,351 @@
1
+ import numpy as np
2
+ import sys
3
+ sys.path.append('.')
4
+ # import c4dynamics as c4d
5
+ from c4dynamics.utils.const import *
6
+ from c4dynamics.utils.math import *
7
+
8
+
9
+ def rotx(phi):
10
+ '''
11
+ Generate a 3x3 Direction Cosine Matrix for
12
+ a positive rotation about the x-axis by an angle :math:`\\phi` in radians.
13
+
14
+ A right-hand rotation matrix about `x` is given by:
15
+
16
+ .. math::
17
+
18
+ R = \\begin{bmatrix}
19
+ 1 & 0 & 0 \\\\
20
+ 0 & cos(\\varphi) & sin(\\varphi) \\\\
21
+ 0 & -sin(\\varphi) & cos(\\varphi)
22
+ \\end{bmatrix}
23
+
24
+
25
+
26
+ Parameters
27
+ ----------
28
+ phi : float or int
29
+ The angle of rotation in radians.
30
+
31
+ Returns
32
+ -------
33
+ out : numpy.array
34
+ A 3x3 rotation matrix representing the rotation about the x-axis.
35
+
36
+
37
+ Examples
38
+ --------
39
+
40
+ >>> rotx(0) # doctest: +NUMPY_FORMAT
41
+ [[1 0 0]
42
+ [0 1 0]
43
+ [0 0 1]]
44
+
45
+
46
+ >>> rotx(c4d.pi / 2) # doctest: +NUMPY_FORMAT
47
+ [[1 0 0]
48
+ [0 0 1]
49
+ [0 -1 0]]
50
+
51
+
52
+ >>> v1 = [0, 0, 1]
53
+ >>> phi = 90 * c4d.d2r
54
+ >>> rotx(phi) @ v1 # doctest: +NUMPY_FORMAT
55
+ [0 1 0]
56
+
57
+
58
+ >>> phi = 45 * c4d.d2r
59
+ >>> rotx(phi) @ v1 # doctest: +NUMPY_FORMAT
60
+ [0 0.707 0.707]
61
+
62
+ '''
63
+ return np.array([[1, 0, 0], [0, cos(phi), sin(phi)], [0, -sin(phi), cos(phi)]])
64
+
65
+
66
+ def roty(theta):
67
+ '''
68
+ Generate a 3x3 Direction Cosine Matrix for
69
+ a positive rotation about the y-axis by an angle :math:`\\theta` in radians.
70
+
71
+
72
+
73
+ A right-hand rotation matrix about `y` is given by:
74
+
75
+ .. math::
76
+
77
+ R = \\begin{bmatrix}
78
+ cos(\\theta) & 0& -sin(\\theta) \\\\
79
+ 0 & 1 & 0 \\\\
80
+ sin(\\theta) & 0 & cos(\\theta)
81
+ \\end{bmatrix}
82
+
83
+
84
+ Parameters
85
+ ----------
86
+ theta : float or int
87
+ The angle of rotation in radians.
88
+
89
+ Returns
90
+ -------
91
+ out : numpy.array
92
+ A 3x3 rotation matrix representing the rotation about the y-axis.
93
+
94
+ Examples
95
+ --------
96
+
97
+ >>> roty(0) # doctest: +NUMPY_FORMAT
98
+ [[1 0 0]
99
+ [0 1 0]
100
+ [0 0 1]]
101
+
102
+
103
+ >>> roty(c4d.pi / 2) # doctest: +NUMPY_FORMAT
104
+ [[0 0 -1]
105
+ [0 1 0]
106
+ [1 0 0]]
107
+
108
+
109
+ >>> v1 = [0, 0, 1]
110
+ >>> phi = 90 * c4d.d2r
111
+ >>> roty(phi) @ v1 # doctest: +NUMPY_FORMAT
112
+ [-1 0 0]
113
+
114
+
115
+ >>> phi = 45 * c4d.d2r
116
+ >>> roty(phi) @ v1 # doctest: +NUMPY_FORMAT
117
+ [-0.707 0 0.707]
118
+
119
+ '''
120
+ return np.array([[cos(theta), 0, -sin(theta)], [0, 1, 0], [sin(theta), 0, cos(theta)]])
121
+
122
+
123
+ def rotz(psi):
124
+ '''
125
+ Generate a 3x3 Direction Cosine Matrix for
126
+ a positive rotation about the z-axis by an angle :math:`\\psi` in radians.
127
+
128
+ A right-hand rotation matrix about `y` is given by:
129
+
130
+
131
+ .. math::
132
+
133
+ R = \\begin{bmatrix}
134
+ cos(\\psi) & sin(\\psi) & 0 \\\\
135
+ -sin(\\psi) & cos(\\psi) & 0 \\\\
136
+ 0 & 0 & 1
137
+ \\end{bmatrix}
138
+
139
+
140
+
141
+ Parameters
142
+ ----------
143
+ psi : float or int
144
+ The angle of rotation in radians.
145
+
146
+ Returns
147
+ -------
148
+ out : numpy.array
149
+ A 3x3 rotation matrix representing the rotation about the z-axis.
150
+
151
+ Examples
152
+ --------
153
+
154
+ >>> rotz(0) # doctest: +NUMPY_FORMAT
155
+ [[1 0 0]
156
+ [0 1 0]
157
+ [0 0 1]]
158
+
159
+
160
+ >>> rotz(c4d.pi / 2) # doctest: +NUMPY_FORMAT
161
+ [[0 1 0]
162
+ [-1 0 0]
163
+ [0 0 1]]
164
+
165
+
166
+ >>> v1 = [0.707, 0.707, 0]
167
+ >>> phi = 90 * c4d.d2r
168
+ >>> rotz(phi) @ v1 # doctest: +NUMPY_FORMAT
169
+ [0.707 -0.707 0]
170
+
171
+ >>> phi = 45 * c4d.d2r
172
+ >>> rotz(phi) @ v1 # doctest: +NUMPY_FORMAT
173
+ [1 0 0]
174
+
175
+ '''
176
+ return np.array([[cos(psi), sin(psi), 0], [-sin(psi), cos(psi), 0], [0, 0, 1]])
177
+
178
+
179
+ def dcm321(phi = 0.0, theta = 0.0, psi = 0.0):
180
+ '''
181
+ Generate a 3x3 Direction Cosine Matrix (DCM) for a sequence of
182
+ positive rotations around the axes in the following order:
183
+ :math:`z`, then :math:`y`, then :math:`x`.
184
+
185
+ The final form of the matrix is given by:
186
+
187
+ .. math::
188
+
189
+ R = \\begin{bmatrix}
190
+ c\\theta \\cdot c\\psi
191
+ & c\\theta \\cdot s\\psi
192
+ & -s\\theta \\\\
193
+ s\\varphi \\cdot s\\theta \\cdot c\\psi - c\\varphi \\cdot s\\psi
194
+ & s\\varphi \\cdot s\\theta \\cdot s\\psi + c\\varphi \\cdot c\\psi
195
+ & s\\varphi \\cdot c\\theta \\\\
196
+ c\\varphi \\cdot s\\theta \\cdot c\\psi + s\\varphi \\cdot s\\psi
197
+ & c\\varphi \\cdot s\\theta \\cdot s\\psi - s\\varphi \\cdot c\\psi
198
+ & c\\varphi \\cdot c\\theta
199
+ \\end{bmatrix}
200
+
201
+ where
202
+
203
+ - :math:`c\\varphi \\equiv cos(\\varphi)`
204
+ - :math:`s\\varphi \\equiv sin(\\varphi)`
205
+ - :math:`c\\theta \\equiv cos(\\theta)`
206
+ - :math:`s\\theta \\equiv sin(\\theta)`
207
+ - :math:`c\\psi \\equiv cos(\\psi)`
208
+ - :math:`s\\psi \\equiv sin(\\psi)`
209
+
210
+
211
+
212
+ Parameters
213
+ ----------
214
+ phi : float or int
215
+ The angle in radian of rotation about `x`, default :math:`\\phi = 0`.
216
+ theta : float or int
217
+ The angle in radian of rotation about `y`, default :math:`\\theta = 0`.
218
+ psi : float or int
219
+ The angle in radian of rotation about `z`, default :math:`\\psi = 0`.
220
+
221
+ Returns
222
+ -------
223
+ out : numpy.array
224
+ 3x3 Direction Cosine Matrix representing the combined rotation.
225
+
226
+
227
+ Examples
228
+ --------
229
+
230
+ The inertial velocity vector of an aircraft expressed in an inertial earth frame is given by:
231
+
232
+ >>> v = [150, 0, 0]
233
+
234
+ The attitude of the aircraft with respect to the inertial earth frame is
235
+ given by the 3 Euler angles:
236
+
237
+ .. math::
238
+
239
+ \\phi = 0
240
+
241
+ \\theta = 30 \\cdot {\\pi \\over 180}
242
+
243
+ \\psi = 0
244
+
245
+ The velcoty expressed in body frame:
246
+
247
+ >>> dcm321(phi = 0, theta = 30 * c4d.d2r, psi = 0) @ v # doctest: +NUMPY_FORMAT
248
+ [129.9 0 75]
249
+
250
+ '''
251
+ return rotx(phi) @ roty(theta) @ rotz(psi)
252
+
253
+
254
+ def dcm321euler(dcm):
255
+ '''
256
+ Extract Euler angles (roll, pitch, yaw) from a Direction Cosine Matrix (DCM) of 3-2-1 order.
257
+
258
+ The form of a 3-2-1 rotation matrix:
259
+
260
+ .. math::
261
+
262
+ R = \\begin{bmatrix}
263
+ c\\theta \\cdot c\\psi
264
+ & c\\theta \\cdot s\\psi
265
+ & -s\\theta \\\\
266
+ s\\varphi \\cdot s\\theta \\cdot c\\psi - c\\varphi \\cdot s\\psi
267
+ & s\\varphi \\cdot s\\theta \\cdot s\\psi - c\\varphi \\cdot c\\psi
268
+ & s\\varphi \\cdot c\\theta \\\\
269
+ s\\varphi \\cdot s\\theta \\cdot s\\psi + s\\varphi \\cdot s\\psi
270
+ & s\\varphi \\cdot s\\theta \\cdot s\\psi - s\\varphi \\cdot c\\psi
271
+ & c\\varphi \\cdot c\\theta
272
+ \\end{bmatrix}
273
+
274
+ where
275
+
276
+ - :math:`c\\varphi \\equiv cos(\\varphi)`
277
+ - :math:`s\\varphi \\equiv sin(\\varphi)`
278
+ - :math:`c\\theta \\equiv cos(\\theta)`
279
+ - :math:`s\\theta \\equiv sin(\\theta)`
280
+ - :math:`c\\psi \\equiv cos(\\psi)`
281
+ - :math:`s\\psi \\equiv sin(\\psi)`
282
+
283
+
284
+ Parameters
285
+ ----------
286
+ dcm : numpy.array
287
+ 3x3 Direction Cosine Matrix representing a rotation.
288
+
289
+ Returns
290
+ -------
291
+ out : tuple
292
+ A tuple containing Euler angles (yaw, pitch, roll) in degrees.
293
+
294
+ Notes
295
+ -----
296
+ Each set of Euler angles has a geometric singularity where
297
+ two angles are not uniquely defined.
298
+ It is always the second angle which defines this singular orientation:
299
+
300
+ - Symmetric Set: 2nd angle is 0 or 180 degrees. For example the 3-1-3 orbit angles with zero inclination.
301
+ - Asymmetric Set: 2nd angle is ±90 degrees. For example, the 3-2-1 angle of an aircraft with 90 degrees pitch.
302
+
303
+ Examples
304
+ --------
305
+
306
+ >>> dcm321euler(np.eye(3)) # doctest: +NUMPY_FORMAT
307
+ (0, 0, 0)
308
+
309
+ A rotation matrix that represents the attitude of an aircraft with respect to
310
+ an inertial earth frame is given by:
311
+
312
+ >>> BI = np.array([[ 0.866, 0, -0.5 ]
313
+ ... , [ 0, 1, 0 ]
314
+ ... , [ 0.5, 0, 0.866 ]])
315
+ >>> dcm321euler(BI) # doctest: +NUMPY_FORMAT
316
+ (0, 30, 0)
317
+
318
+ '''
319
+
320
+ psi = atan2(dcm[0, 1], dcm[0, 0]) * r2d
321
+ theta = -asin(dcm[0, 2]) * r2d
322
+ phi = atan2(dcm[1, 2], dcm[2, 2]) * r2d
323
+
324
+ return phi, theta, psi
325
+
326
+
327
+
328
+ if __name__ == "__main__":
329
+
330
+ import doctest, contextlib, os
331
+ from c4dynamics import IgnoreOutputChecker, cprint
332
+
333
+ # Register the custom OutputChecker
334
+ doctest.OutputChecker = IgnoreOutputChecker
335
+
336
+ tofile = False
337
+ optionflags = doctest.FAIL_FAST
338
+
339
+ if tofile:
340
+ with open(os.path.join('tests', '_out', 'output.txt'), 'w') as f:
341
+ with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f):
342
+ result = doctest.testmod(optionflags = optionflags)
343
+ else:
344
+ result = doctest.testmod(optionflags = optionflags)
345
+
346
+ if result.failed == 0:
347
+ cprint(os.path.basename(__file__) + ": all tests passed!", 'g')
348
+ else:
349
+ print(f"{result.failed}")
350
+
351
+
@@ -0,0 +1,72 @@
1
+ '''
2
+
3
+ `c4dynamics` provides sensor models to simulate real world applications.
4
+ The models include the functionality and the errors model
5
+ of electro-optic, lasers, and electro-magnetic devices.
6
+
7
+ '''
8
+ #
9
+ # i think maybe to include also detectors in this module
10
+ # and rename it to something like perception \ source \ input
11
+ # measures \
12
+ #
13
+
14
+ import sys
15
+ sys.path.append('.')
16
+
17
+ from c4dynamics.sensors.radar import radar
18
+ from c4dynamics.sensors.lineofsight import lineofsight
19
+ from c4dynamics.sensors.seeker import seeker
20
+
21
+
22
+ # Background Material
23
+ # -------------------
24
+
25
+ # Introduction
26
+ # ^^^^^^^^^^^^
27
+ # '''
28
+
29
+ # seekers:
30
+ # matter:
31
+ # radar
32
+ # laser
33
+ # optic
34
+ # functionallity:
35
+ # altitude radar
36
+ # lineofsight seeker
37
+
38
+ # sensors:
39
+ # imu
40
+ # accelerometers
41
+ # roll gyro
42
+ # rate gyro
43
+ # gps
44
+ # lidar
45
+
46
+
47
+
48
+ if __name__ == "__main__":
49
+
50
+ import doctest, contextlib, os
51
+ from c4dynamics import IgnoreOutputChecker, cprint
52
+
53
+ # Register the custom OutputChecker
54
+ doctest.OutputChecker = IgnoreOutputChecker
55
+
56
+ tofile = False
57
+ optionflags = doctest.FAIL_FAST
58
+
59
+ if tofile:
60
+ with open(os.path.join('tests', '_out', 'output.txt'), 'w') as f:
61
+ with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f):
62
+ result = doctest.testmod(optionflags = optionflags)
63
+ else:
64
+ result = doctest.testmod(optionflags = optionflags)
65
+
66
+ if result.failed == 0:
67
+ cprint(os.path.basename(__file__) + ": all tests passed!", 'g')
68
+ else:
69
+ print(f"{result.failed}")
70
+
71
+
72
+
@@ -0,0 +1,78 @@
1
+ import numpy as np
2
+
3
+ import c4dynamics as c4d
4
+
5
+ # np.warnings.filterwarnings('ignore', category=np.VisibleDeprecationWarning)
6
+
7
+ class lineofsight:
8
+ '''
9
+ Line of Sight seeker.
10
+
11
+ the lineofsight is measure line of sight vector rate
12
+ the seeker head lags the true angular rate.
13
+ this lag is represented by a first order transfer function with time constant tau1
14
+ there are assumed to be delays involved in processing the seeker head angular rate singal.
15
+ the filter delays are represented by a first order transfer function with time constant tau2
16
+
17
+ Parameters
18
+ ==========
19
+ TODO complete
20
+
21
+ Example
22
+ =======
23
+ TODO complete
24
+
25
+ '''
26
+
27
+ tau1 = 0
28
+ tau2 = 0
29
+ dt = 0
30
+
31
+ isideal = False
32
+
33
+
34
+ omega = np.array([0, 0, 0]) # truth los rate
35
+ omega_ach = np.array([0, 0, 0]) # achieved los rate after first order filter
36
+ omega_f = np.array([0, 0, 0]) # filtered los rate after first order filter
37
+
38
+ _data = np.zeros((1, 7))
39
+
40
+ def __init__(obj, dt, tau1 = 0.05, tau2 = 0.05, isideal = False): #**kwargs):
41
+ # obj.__dict__.update(kwargs)
42
+ obj.dt = dt
43
+ obj.tau1 = tau1 # tracking loop time constant
44
+ obj.tau2 = tau2 # seeker signal processing time constant
45
+ obj.isideal = isideal
46
+
47
+
48
+ def measure(obj, r, v):
49
+ # r: range to target (line of sight vector)
50
+ # v: relative velocity with target
51
+
52
+ #
53
+ # true angular rate of the los vector
54
+ ##
55
+ obj.omega = np.cross(r, v) / np.linalg.norm(r)**2
56
+
57
+ #
58
+ # achieved seeker-head angular rate vector
59
+ ##
60
+ obj.omega_ach = obj.omega_ach * np.exp(-obj.dt / obj.tau1) + obj.omega * (1 - np.exp(-obj.dt / obj.tau1)) # lag
61
+
62
+ #
63
+ # final processed tracking rate signal vector
64
+ ##
65
+ obj.omega_f = obj.omega_f * np.exp(-obj.dt / obj.tau2) + obj.omega_ach * (1 - np.exp(-obj.dt / obj.tau2)) # filter
66
+
67
+ if obj.isideal:
68
+ obj.omega_f = obj.omega_ach = obj.omega
69
+
70
+
71
+ return obj.omega_f
72
+
73
+
74
+ def store(obj, t = -1):
75
+ obj._data = np.vstack((obj._data
76
+ , np.concatenate(([t], obj.omega, obj.omega_f)))).copy()
77
+
78
+