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,123 @@
1
+ import numpy as np
2
+ import sys
3
+ from typing import Optional
4
+
5
+ sys.path.append('.')
6
+ import c4dynamics as c4d
7
+
8
+
9
+ class lowpass(c4d.state):
10
+ """
11
+ A first-order low-pass filter for smoothing signals, supporting both discrete and continuous systems.
12
+
13
+ Parameters
14
+ ----------
15
+ alpha : float, optional
16
+ Smoothing factor for a discrete system. Must be in the range (0, 1). Defaults to None.
17
+ dt : float, optional
18
+ Time step for a continuous system. Must be positive. Defaults to None.
19
+ tau : float, optional
20
+ Time constant for a continuous system. Must be positive. Defaults to None.
21
+ y0 : float, optional
22
+ Initial value of the state. Defaults to 0.
23
+
24
+ Raises
25
+ ------
26
+ ValueError
27
+ If neither `alpha` nor both `dt` and `tau` are provided.
28
+ If `alpha` is out of the range (0, 1) for a discrete system.
29
+ If `dt` or `tau` is non-positive for a continuous system.
30
+
31
+ Notes
32
+ -----
33
+ - For a continuous system, `dt` and `tau` are required, and `alpha` is calculated as `dt / tau`.
34
+ - For a discrete system, `alpha` alone is required and directly specifies the smoothing factor.
35
+
36
+ Example
37
+ -------
38
+
39
+ .. code::
40
+
41
+ >>> filter_continuous = lowpass(dt=0.01, tau=0.1, y0=0)
42
+ >>> filter_discrete = lowpass(alpha=0.5, y0=1)
43
+ >>> filter_continuous.sample(1.0) # doctest: +ELLIPSIS
44
+ 0.09...
45
+ >>> filter_discrete.sample(2.0)
46
+ 1.5
47
+ """
48
+
49
+ def __init__(self, alpha: Optional[float] = None, dt: Optional[float] = None,
50
+ tau: Optional[float] = None, y0: float = 0) -> None:
51
+ # Initialize alpha based on the provided parameters
52
+ if dt is not None and tau is not None:
53
+ if dt <= 0 or tau <= 0:
54
+ raise ValueError("For a continuous system, `dt` and `tau` must be positive.")
55
+ self.alpha = dt / tau
56
+ elif alpha is not None:
57
+ if not (0 < alpha < 1):
58
+ raise ValueError("For a discrete system, `alpha` must be in the range (0, 1).")
59
+ self.alpha = alpha
60
+ else:
61
+ raise ValueError("Provide either `alpha` for a discrete system or both `dt` and `tau` for a continuous system.")
62
+
63
+ self.y = y0 # Initial state value
64
+
65
+ def sample(self, x: float) -> float:
66
+ """
67
+ Applies the low-pass filter to the input value and returns the filtered output.
68
+
69
+ Parameters
70
+ ----------
71
+ x : float
72
+ Input value to be filtered.
73
+
74
+ Returns
75
+ -------
76
+ float
77
+ The filtered output value after applying the low-pass filter.
78
+
79
+ Notes
80
+ -----
81
+ - For a continuous system: `y'(t) = -y(t) / tau + x(t) / tau`
82
+ - For a discrete system: `y[k] = (1 - alpha) * y[k-1] + alpha * x[k]`
83
+ - The filter's state (`self.y`) is updated in place.
84
+
85
+ Example
86
+ -------
87
+
88
+ .. code::
89
+
90
+ >>> lp_filter = lowpass(alpha=0.5)
91
+ >>> lp_filter.sample(2.0)
92
+ 1.0
93
+ >>> lp_filter.sample(3.0)
94
+ 2.0
95
+ """
96
+ # Update the filter's state
97
+ self.y = (1 - self.alpha) * self.y + self.alpha * x
98
+ return self.y
99
+
100
+
101
+ if __name__ == "__main__":
102
+ import doctest
103
+ import contextlib
104
+ import os
105
+ from c4dynamics import IgnoreOutputChecker, cprint
106
+
107
+ # Register the custom OutputChecker
108
+ doctest.OutputChecker = IgnoreOutputChecker
109
+
110
+ tofile = False
111
+ optionflags = doctest.FAIL_FAST
112
+
113
+ if tofile:
114
+ with open('tests/_out/output.txt', 'w') as f:
115
+ with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f):
116
+ result = doctest.testmod(optionflags=optionflags)
117
+ else:
118
+ result = doctest.testmod(optionflags=optionflags)
119
+
120
+ if result.failed == 0:
121
+ cprint(os.path.basename(__file__) + ": all tests passed!", 'g')
122
+ else:
123
+ print(f"{result.failed} test(s) failed.")
@@ -0,0 +1,97 @@
1
+ import numpy as np
2
+
3
+ class luenberger:
4
+ '''
5
+ Luenberger (Asymptotic) Observer.
6
+
7
+
8
+ Parameters
9
+ ==========
10
+ TODO complete
11
+
12
+
13
+ luenberger estimator
14
+ agranovich,
15
+ modern control 72
16
+
17
+ ### Luenberger Filter
18
+ The Luenberger observer is given by:
19
+
20
+ \[ \dot{\hat{x}}(t) = A \hat{x}(t) + B u(t) + L (y(t) - C \hat{x}(t)) \]
21
+
22
+ where \( L \) is the observer gain matrix.
23
+
24
+ '''
25
+
26
+ A = 0
27
+ c = 0
28
+ obsv = 0
29
+ Aest = 0
30
+
31
+ def __init__(obj, A, c):
32
+ obj.A = A
33
+ obj.c = c
34
+ obj.obsv = np.copy(obj.c)
35
+ for n in range(len(obj.A) - 1):
36
+ obj.obsv = np.vstack((obj.obsv, obj.c @ obj.A**(n + 1))).copy()
37
+
38
+ def isobservable(obj):
39
+ return np.linalg.matrix_rank(obj.obsv) == len(obj.A)
40
+
41
+ def eig(obj):
42
+ return np.linalg.eig(obj.A)[0]
43
+
44
+ def setest(obj, s):
45
+ n = len(obj.A)
46
+
47
+ # coefficients from the desired eigenvalues
48
+ an_d = np.polynomial.polynomial.polyfromroots(s)
49
+ # the extended system eigenvalues are including the luenberger gains which are currently unknown.
50
+ # the polynomial that represents the system is given by the determinant of s*I-Aest. where Aest is the extended system matrix which inclueds the gains.
51
+ # the desired eigenvalues are given in the input argument s.
52
+ # assuming the prime coefficient is one in the both systems, there are n-1 coefficients to compare.
53
+
54
+
55
+ #
56
+ # the calculation of luenberger gains
57
+ # rational:
58
+ # 1 calculate the luenberger gains of the equivalent canonical model
59
+ # 2 find the model transform matrix
60
+ # 3 tranform the gains
61
+ ##
62
+
63
+ # a canonical equivalent system matrix:
64
+ # | 0 0 .. -a0 |
65
+ # | 1 0 .. -a1 |
66
+ # | .. |
67
+ # |0 0 .. 1 -an-1|
68
+ # where a0..an-1 are the coefficients of the system polynomial.
69
+
70
+ an = np.polynomial.polynomial.polyfromroots(np.linalg.eig(obj.A)[0])
71
+ # canA = np.zeros((n, n))
72
+ # for i in range(n):
73
+ # canA[i, -1] = -an[i]
74
+ # if i == 0:
75
+ # continue
76
+ # canA[i, i - 1] = 1
77
+
78
+ # luenberger gains for the canonical system
79
+ Lc = np.zeros(n) # Lcanonical
80
+ for i in range(n):
81
+ Lc[i] = an_d[i] - an[i]
82
+
83
+ # model transformation matrix
84
+ cmu = np.zeros(n)
85
+ cmu[-1] = 1
86
+ mu = np.linalg.solve(obj.obsv, cmu.reshape((-1, 1)))
87
+
88
+ M = np.copy(mu)
89
+ for n in range(n - 1):
90
+ M = np.hstack((M, obj.A**(n + 1) @ mu)).copy()
91
+
92
+ # 3 tranform the gains
93
+ L = M @ Lc
94
+
95
+ obj.Aest = obj.A - L @ obj.c
96
+
97
+
@@ -0,0 +1,141 @@
1
+ '''
2
+
3
+ Rotational Matrix Operations
4
+ ============================
5
+
6
+
7
+
8
+ Background Material
9
+ -------------------
10
+
11
+ A rotation matrix is a mathematical representation of a
12
+ rotation in three-dimensional space.
13
+
14
+ It's a 3x3 matrix that, when multiplied with a vector,
15
+ transforms the vector to represent a new orientation.
16
+
17
+ Each element of the matrix corresponds to a directional cosine,
18
+ capturing the rotation's effect on the x, y, and z axes.
19
+
20
+
21
+ Euler Angles Order
22
+ ^^^^^^^^^^^^^^^^^^
23
+
24
+ Frame based vectors are related through a Direction Cosine Matrix (DCM). [HS]_
25
+
26
+ When Euler angles are employed in the transformation of
27
+ a vector expressed in one reference frame to the expression
28
+ of the vector in a different reference frame, any order of the
29
+ three Euler rotations is possible, but the resulting transformation
30
+ equations depend on the order selected. [MIs]_
31
+
32
+ In aerospace applications for example,
33
+ the common order is that the first Euler rotation is about the z-axis,
34
+ the second is about the y-axis, and the third is about the Xaxis.
35
+ Such a transformation order is called z-y-x, or 3-2-1.
36
+ With reference to a body orientation, the resulting
37
+ order is yaw, pitch, and roll.
38
+ With reference to geographical
39
+ orientation, the resulting order is azimuth (heading),
40
+ elevation (pitch), and roll (bank angle).
41
+
42
+
43
+ Right Hand Frame
44
+ ^^^^^^^^^^^^^^^^
45
+
46
+ The positive directions of coordinate system
47
+ axes and the directions of positive rotations
48
+ about the axes are arbitrary.
49
+ In right-handed systems:
50
+
51
+ ::
52
+
53
+ i x j = k
54
+ j x k = i
55
+ k x i = j
56
+
57
+ where i is the unit vector in the direction of the x-axis,
58
+ j is the unit vector in the direction of the y-axis,
59
+ k is the unit vector in the direction of the z-axis.
60
+
61
+ Positive rotations are clockwise
62
+ when viewed from the origin, looking out along the
63
+ positive direction of the axis.
64
+
65
+ These conventions are illustrated
66
+ in Fig-1.
67
+
68
+
69
+ .. figure:: /_architecture/frame_conventions.svg
70
+
71
+ Fig-1: Coordinate System Conventions
72
+
73
+
74
+ References
75
+ ----------
76
+
77
+ .. [HS] Hanspeter Schaub, "Spacecraft Dynamics and Control" lecture notes, module 2: rigidbody kinematics.
78
+ .. [MIs] Ch 4 in "Missile Flight Simulation Part One Surface-to-Air Missiles", Military Handbook, 1995, MIL-HDBK-1211(MI).
79
+
80
+
81
+
82
+ Examples
83
+ --------
84
+
85
+ For examples, see the various functions.
86
+
87
+ '''
88
+ # spacecraft dyanmics and control
89
+
90
+ # Rotating Reference Frame
91
+ # ^^^^^^^^^^^^^^^^^^^^^^^^
92
+
93
+ # A vector resolved in a given reference frame is said to be
94
+ # **expressed** in that frame (sometimes said **referred to**).
95
+
96
+ # The rate of change of a vector, as viewed by an observer fixed to and moving
97
+ # with a given reference frame,
98
+ # is said to be **relative to** or **with respect to** that reference frame.
99
+
100
+ # It's important to note here that the rate of change of a vector must be
101
+ # relative to an inertial reference frame,
102
+ # but it can be expressed in any reference frame.
103
+
104
+
105
+ import sys
106
+ sys.path.append('.')
107
+
108
+ from c4dynamics.rotmat.rotmat import rotx, roty, rotz, dcm321, dcm321euler
109
+ from c4dynamics.rotmat.animate import animate
110
+
111
+
112
+
113
+ if __name__ == "__main__":
114
+
115
+ import doctest, contextlib, os
116
+ from c4dynamics import IgnoreOutputChecker, cprint
117
+
118
+ # Register the custom OutputChecker
119
+ doctest.OutputChecker = IgnoreOutputChecker
120
+
121
+ tofile = False
122
+ optionflags = doctest.FAIL_FAST
123
+
124
+ if tofile:
125
+ with open(os.path.join('tests', '_out', 'output.txt'), 'w') as f:
126
+ with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f):
127
+ result = doctest.testmod(optionflags = optionflags)
128
+ else:
129
+ result = doctest.testmod(optionflags = optionflags)
130
+
131
+ if result.failed == 0:
132
+ cprint(os.path.basename(__file__) + ": all tests passed!", 'g')
133
+ else:
134
+ print(f"{result.failed}")
135
+
136
+
137
+
138
+
139
+
140
+
141
+