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,359 @@
1
+ from typing import Dict, Optional, Union, Tuple
2
+ from numpy.typing import NDArray
3
+ import numpy as np
4
+ import sys
5
+
6
+ sys.path.append('.')
7
+ from c4dynamics.eqm.derivs import eqm3, eqm6
8
+ from c4dynamics import datapoint, rigidbody
9
+
10
+
11
+ def int3(dp: 'datapoint', forces: Union[np.ndarray, list]
12
+ , dt: float, derivs_out: bool = False
13
+ ) -> Union[NDArray[np.float64], Tuple[NDArray[np.float64], NDArray[np.float64]]]:
14
+ '''
15
+ A step integration of the equations of translational motion.
16
+
17
+ This method makes a numerical integration using the
18
+ fourth-order Runge-Kutta method.
19
+
20
+ The integrated derivatives are of three dimensional translational motion as
21
+ given by
22
+ :func:`eqm3 <c4dynamics.eqm.derivs.eqm3>`.
23
+
24
+
25
+ The result is an integrated state in a single interval of time where the
26
+ size of the step is determined by the parameter `dt`.
27
+
28
+
29
+ Parameters
30
+ ----------
31
+ dp : :class:`datapoint <c4dynamics.states.lib.datapoint.datapoint>`
32
+ The datapoint which state vector is to be integrated.
33
+ forces : numpy.array or list
34
+ An external forces array acting on the body.
35
+ dt : float
36
+ Time step for integration.
37
+ derivs_out : bool, optional
38
+ If true, returns the last three derivatives as an estimation for
39
+ the acceleration of the datapoint.
40
+
41
+
42
+ Returns
43
+ -------
44
+ X : numpy.float64
45
+ An integrated state.
46
+ dxdt4 : numpy.float64, optional
47
+ The last three derivatives of the equations of motion.
48
+ These derivatives can use as an estimation for the acceleration of the datapoint.
49
+ Returned if `derivs_out` is set to `True`.
50
+
51
+
52
+
53
+ **Algorithm**
54
+
55
+
56
+ The integration steps follow the Runge-Kutta method:
57
+
58
+ 1. Compute k1 = f(ti, yi)
59
+
60
+ 2. Compute k2 = f(ti + dt / 2, yi + dt * k1 / 2)
61
+
62
+ 3. Compute k3 = f(ti + dt / 2, yi + dt * k2 / 2)
63
+
64
+ 4. Compute k4 = f(ti + dt, yi + dt * k3)
65
+
66
+ 5. Update yi = yi + dt / 6 * (k1 + 2 * k2 + 2 * k3 + k4)
67
+
68
+
69
+
70
+ Examples
71
+ --------
72
+
73
+ Runge-Kutta integration of the equations of motion on a mass in a free fall
74
+ (compare to the same example in :func:`eqm3 <c4dynamics.eqm.derivs.eqm3>` with Euler integration):
75
+
76
+ Import required packages
77
+
78
+
79
+ .. code::
80
+
81
+ >>> import c4dynamics as c4d
82
+
83
+ .. code::
84
+
85
+ >>> pt = c4d.datapoint(z = 10000)
86
+ >>> while pt.z > 0:
87
+ ... pt.store()
88
+ ... pt.X = c4d.eqm.int3(pt, [0, 0, -c4d.g_ms2], dt = 1)
89
+
90
+ .. figure:: /_examples/eqm/int3.png
91
+
92
+ '''
93
+
94
+
95
+ x0 = dp.X
96
+ X = dp.X
97
+
98
+
99
+ # step 1
100
+ dxdt1 = eqm3(dp, forces)
101
+ # dp.update(x0 + dt / 2 * dxdt1)
102
+ X = x0 + dt / 2 * dxdt1
103
+
104
+ # step 2
105
+ dxdt2 = eqm3(dp, forces)
106
+ # dp.update(x0 + dt / 2 * dxdt2)
107
+ X = x0 + dt / 2 * dxdt2
108
+
109
+ # step 3
110
+ dxdt3 = eqm3(dp, forces)
111
+ # dp.update(x0 + dt * dxdt3)
112
+ X = x0 + dt * dxdt3
113
+ dxdt3 += dxdt2
114
+
115
+ # step 4
116
+ dxdt4 = eqm3(dp, forces)
117
+
118
+ #
119
+ # dp.update(np.concatenate((x0 + dt / 6 * (dxdt1 + dxdt4 + 2 * dxdt3), dxdt4[-3:]), axis = 0))
120
+ X = x0 + dt / 6 * (dxdt1 + dxdt4 + 2 * dxdt3)
121
+ # dp.ax, dp.ay, dp.az = dxdt4[-3:]
122
+
123
+
124
+ if not derivs_out:
125
+ return X
126
+
127
+ # return also the derivatives.
128
+ return X, dxdt4[-3:]
129
+
130
+ ##
131
+
132
+
133
+ def int6(rb: 'rigidbody', forces: Union[np.ndarray, list], moments: Union[np.ndarray, list]
134
+ , dt: float, derivs_out: bool = False
135
+ ) -> Union[NDArray[np.float64], Tuple[NDArray[np.float64], NDArray[np.float64]]]:
136
+
137
+ '''
138
+ A step integration of the equations of motion.
139
+
140
+ This method makes a numerical integration using the
141
+ fourth-order Runge-Kutta method.
142
+
143
+ The integrated derivatives are of three dimensional translational motion as
144
+ given by
145
+ :func:`eqm6 <c4dynamics.eqm.derivs.eqm6>`.
146
+
147
+
148
+ The result is an integrated state in a single interval of time where the
149
+ size of the step is determined by the parameter `dt`.
150
+
151
+
152
+ Parameters
153
+ ----------
154
+ dp : :class:`datapoint <c4dynamics.states.lib.datapoint.datapoint>`
155
+ The datapoint which state vector is to be integrated.
156
+ forces : numpy.array or list
157
+ An external forces array acting on the body.
158
+ dt : float
159
+ Time step for integration.
160
+ derivs_out : bool, optional
161
+ If true, returns the last three derivatives as an estimation for
162
+ the acceleration of the datapoint.
163
+
164
+
165
+ Returns
166
+ -------
167
+ X : numpy.float64
168
+ An integrated state.
169
+ dxdt4 : numpy.float64, optional
170
+ The last six derivatives of the equations of motion.
171
+ These derivatives can use as an estimation for the
172
+ translational and angular acceleration of the datapoint.
173
+ Returned if `derivs_out` is set to `True`.
174
+
175
+
176
+ **Algorithm**
177
+
178
+
179
+ The integration steps follow the Runge-Kutta method:
180
+
181
+ 1. Compute k1 = f(ti, yi)
182
+
183
+ 2. Compute k2 = f(ti + dt / 2, yi + dt * k1 / 2)
184
+
185
+ 3. Compute k3 = f(ti + dt / 2, yi + dt * k2 / 2)
186
+
187
+ 4. Compute k4 = f(ti + dt, yi + dt * k3)
188
+
189
+ 5. Update yi = yi + dt / 6 * (k1 + 2 * k2 + 2 * k3 + k4)
190
+
191
+
192
+ Examples
193
+ --------
194
+
195
+ In the following example, the equations of motion of a
196
+ cylinderical body are integrated by using the
197
+ :func:`int6 <c4dynamics.eqm.integrate.int6>`.
198
+
199
+ The results are compared to the results of the same equations
200
+ integrated by using `scipy.odeint`.
201
+
202
+
203
+ 1. `int6`
204
+
205
+
206
+ Import required packages
207
+
208
+ .. code::
209
+
210
+ >>> import c4dynamics as c4d
211
+ >>> from matplotlib import pyplot as plt
212
+ >>> from scipy.integrate import odeint
213
+ >>> import numpy as np
214
+
215
+
216
+ Settings and initial conditions
217
+
218
+ .. code::
219
+
220
+ >>> dt = 0.5e-3
221
+ >>> t = np.arange(0, 10, dt)
222
+ >>> theta0 = 80 * c4d.d2r # deg
223
+ >>> q0 = 0 * c4d.d2r # deg to sec
224
+ >>> Iyy = .4 # kg * m^2
225
+ >>> length = 1 # meter
226
+ >>> mass = 0.5 # kg
227
+
228
+
229
+ Define the cylinderical-rigidbody object
230
+
231
+ .. code::
232
+
233
+ >>> rb = c4d.rigidbody(theta = theta0, q = q0)
234
+ >>> rb.I = [0, Iyy, 0]
235
+ >>> rb.mass = mass
236
+
237
+
238
+ Main loop:
239
+
240
+ .. code::
241
+
242
+ >>> for ti in t:
243
+ ... rb.store(ti)
244
+ ... tau_g = -rb.mass * c4d.g_ms2 * length / 2 * c4d.cos(rb.theta)
245
+ ... rb.X = c4d.eqm.int6(rb, np.zeros(3), [0, tau_g, 0], dt)
246
+
247
+
248
+ .. code::
249
+
250
+ >>> rb.plot('theta')
251
+
252
+ .. figure:: /_examples/eqm/int6.png
253
+
254
+
255
+ 2. `scipy.odeint`
256
+
257
+ .. code::
258
+
259
+ >>> def pend(y, t):
260
+ ... theta, omega = y
261
+ ... dydt = [omega, -rb.mass * c4d.g_ms2 * length / 2 * c4d.cos(theta) / Iyy]
262
+ ... return dydt
263
+ >>> sol = odeint(pend, [theta0, q0], t)
264
+
265
+
266
+ Compare to `int6`:
267
+
268
+ .. code::
269
+
270
+ >>> plt.plot(*rb.data('theta', c4d.r2d), 'm', label = 'c4dynamics.int6') # doctest: +IGNORE_OUTPUT
271
+ >>> plt.plot(t, sol[:, 0] * c4d.r2d, 'c', label = 'scipy.odeint') # doctest: +IGNORE_OUTPUT
272
+ >>> c4d.plotdefaults(plt.gca(), 'Equations of Motion Integration ($\\theta$)', 'Time', 'degrees', fontsize = 12)
273
+ >>> plt.legend() # doctest: +IGNORE_OUTPUT
274
+
275
+
276
+ .. figure:: /_examples/eqm/int6_vs_scipy.png
277
+
278
+
279
+ **Note - Differences Between Scipy and C4dynamics Integration**
280
+
281
+ The difference in the results derive from the method of delivering the
282
+ forces and moments.
283
+ scipy.odeint gets as input the function that caluclates the derivatives,
284
+ where the forces and moments are included in it:
285
+
286
+ `dydt = [omega, -rb.mass * c4d.g_ms2 * length / 2 * c4d.cos(theta) / Iyy]`
287
+
288
+ This way, the forces and moments are recalculated for each step of
289
+ the integration.
290
+
291
+ c4dynamics.eqm.int6 on the other hand, gets the vectors of forces and moments
292
+ only once when the function is called and therefore refer to them as constant
293
+ for the four steps of integration.
294
+
295
+ When external factors may vary quickly over time and a high level of
296
+ accuracy is required, using other methods, like scipy.odeint, is recommanded.
297
+ If computational resources are available, a decrement of the step-size
298
+ may be a workaround to achieve high accuracy results.
299
+
300
+
301
+ '''
302
+
303
+ # x, y, z, vx, vy, vz, phi, theta, psi, p, q, r
304
+ x0 = rb.X
305
+ X = rb.X
306
+
307
+ # step 1
308
+ h1 = eqm6(rb, forces, moments)
309
+ X = x0 + dt / 2 * h1
310
+
311
+ # step 2
312
+ h2 = eqm6(rb, forces, moments)
313
+ X = x0 + dt / 2 * h2
314
+
315
+ # step 3
316
+ h3 = eqm6(rb, forces, moments)
317
+ X = x0 + dt * h3
318
+
319
+ # step 4
320
+ h4 = eqm6(rb, forces, moments)
321
+
322
+
323
+ X = x0 + dt / 6 * (h1 + 2 * h2 + 2 * h3 + h4)
324
+
325
+ if not derivs_out:
326
+ return X
327
+
328
+ # return also the derivatives.
329
+ # 0 1 2 3 4 5 6 7 8 9 10 11
330
+ # h4 = np.array([dx, dy, dz, dvx, dvy, dvz, dphi, dtheta, dpsi, dp, dq, dr])
331
+ return X, np.concatenate([h4[3 : 6], h4[9 : 12]]) # X, [dvx, dvy, dvz, dp, dq, dr]
332
+
333
+ ##
334
+
335
+
336
+ if __name__ == "__main__":
337
+
338
+ import doctest, contextlib, os
339
+ from c4dynamics import IgnoreOutputChecker, cprint
340
+
341
+ # Register the custom OutputChecker
342
+ doctest.OutputChecker = IgnoreOutputChecker
343
+
344
+ tofile = False
345
+ optionflags = doctest.FAIL_FAST
346
+
347
+ if tofile:
348
+ with open(os.path.join('tests', '_out', 'output.txt'), 'w') as f:
349
+ with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f):
350
+ result = doctest.testmod(optionflags = optionflags)
351
+ else:
352
+ result = doctest.testmod(optionflags = optionflags)
353
+
354
+ if result.failed == 0:
355
+ cprint(os.path.basename(__file__) + ": all tests passed!", 'g')
356
+ else:
357
+ print(f"{result.failed}")
358
+
359
+