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,124 @@
1
+ from tensorflow.keras.models import load_model
2
+ from tensorflow import image, expand_dims, split, reshape, shape, concat
3
+ from tensorflow.image import combined_non_max_suppression
4
+
5
+ # https://saturncloud.io/blog/how-to-resolve-python-kernel-dies-on-jupyter-notebook-with-tensorflow-2/
6
+ # from .detector_utils import *
7
+ import numpy as np
8
+ import os
9
+
10
+
11
+ MODEL_SIZE = (416, 416, 3)
12
+ NUM_OF_CLASSES = 80
13
+ MAX_OUTPUT_SIZE = 40
14
+ MAX_OUTPUT_SIZE_PER_CLASS = 20
15
+ IOU_THRESHOLD = 0.5
16
+ CONFIDENCE_THRESHOLD = 0.5
17
+
18
+
19
+ class yolo():
20
+
21
+ '''
22
+ The yolo3_detector class is a wrapper for object detection using the YOLO
23
+ (You Only Look Once) model.
24
+
25
+ 1. __init__(self, height=0, width=0):
26
+ The class constructor initializes the YOLO model by loading it
27
+ from the specified model path.
28
+ It also loads the class names for the detected objects.
29
+ The height and width parameters are used to set the dimensions of the video frame.
30
+
31
+ 2. measure(self, frame):
32
+ This method takes a frame as input and performs object detection
33
+ on it using the YOLO model.
34
+ It returns the bounding box coordinates of the detected objects
35
+ scaled according to the frame dimensions.
36
+
37
+ performs the actual object detection on the given frame.
38
+ It preprocesses the frame, resizes it to match the model's input size,
39
+ and passes it through the YOLO model to obtain the bounding box coordinates,
40
+ scores, class predictions, and the number of detected objects.
41
+
42
+
43
+
44
+
45
+ The yolo3_detector class encapsulates the functionality of object detection using the YOLO model,
46
+ providing methods to perform detection, extract measurements,
47
+ and visualize the results on the frame. The class works in conjunction
48
+ with the YOLO model, which is loaded externally and used for the actual detection process.
49
+
50
+
51
+ '''
52
+
53
+
54
+ def __init__(self, model, height = 0, width = 0):
55
+ self.model = model # load_model(modelpath, compile = False)
56
+
57
+ with open(os.path.join(os.getcwd(), 'c4dynamics', 'resources', 'detectors', 'yolo', 'v3', 'coco.names'), 'r') as f:
58
+ self.class_names = f.read().splitlines()
59
+
60
+ self.width = width
61
+ self.height = height
62
+
63
+
64
+
65
+
66
+
67
+ def detect(self, frame, t, outfile):
68
+ # frame (1080, 1920, 3), resized_frame tf([1, 416, 416, 3])
69
+ resized_frame = expand_dims(frame, 0)
70
+ resized_frame = image.resize(resized_frame, (MODEL_SIZE[0], MODEL_SIZE[1]))
71
+
72
+ detections = self.model.predict(resized_frame, verbose = 0).squeeze()
73
+ # detections shape: (1, 10647, 85)
74
+
75
+
76
+ xcenter = detections[:, 0].copy()
77
+ # top_left_x = center_x - width / 2.0
78
+ detections[:, 0] = xcenter - detections[:, 2] / 2.0 # top_left_x
79
+ # bottom_right_x = center_x + width / 2.0
80
+ detections[:, 2] = xcenter + detections[:, 2] / 2.0 # bottom_right_x
81
+ ycenter = detections[:, 1].copy()
82
+ # top_left_y = center_y - height / 2.0
83
+ detections[:, 1] = ycenter - detections[:, 3] / 2.0 # top_left_y
84
+ # bottom_right_y = center_y + height / 2.0
85
+ detections[:, 3] = ycenter + detections[:, 3] / 2.0 # bottom_right_y
86
+
87
+
88
+ bbox, confs, class_probs = split(detections, [4, 1, -1], axis = -1)
89
+ bbox = bbox / MODEL_SIZE[0]
90
+ scores = confs * class_probs
91
+
92
+
93
+ boxes, _, _, Nvalid = combined_non_max_suppression(
94
+ boxes = reshape(bbox, (1, -1, 1, 4)) # reshapedbox
95
+ , scores = expand_dims(scores, axis = 0) # reshape(scores, (1, -1, 1, 4)) # reshape(scores, (shape(scores)[0], -1, shape(scores)[-1]))
96
+ , max_output_size_per_class = MAX_OUTPUT_SIZE_PER_CLASS
97
+ , max_total_size = MAX_OUTPUT_SIZE
98
+ , iou_threshold = IOU_THRESHOLD
99
+ , score_threshold = CONFIDENCE_THRESHOLD)
100
+
101
+ # Extract class indices with highest confidence
102
+ class_indices = np.argmax(class_probs, axis = -1)
103
+
104
+ # Extract class labels using the class_indices and class_names
105
+ class_labels = [self.class_names[i] for i in class_indices]
106
+
107
+
108
+ N = Nvalid[0].numpy()
109
+ boxout = boxes[0][:N].numpy()
110
+
111
+ #
112
+ # translate the normalized diagnonal of the bounding box to the size of the recorded frame:
113
+ ##
114
+ boxout[:, [0, 2]] *= self.width # x1
115
+ # boxout[:, 2] = boxout[:, 2] * self.width # x2
116
+
117
+ boxout[:, [1, 3]] *= self.height # y1
118
+ # boxout[:, 3] = boxout[:, 3] * self.height # y2
119
+ # log
120
+ # normalized box out coordinates
121
+
122
+ # Return both bounding boxes and object classifications
123
+ return boxout, class_labels[:N]
124
+
@@ -0,0 +1,324 @@
1
+ '''
2
+
3
+ Background Material [MI]_
4
+ -------------------------
5
+
6
+ Introduction
7
+ ^^^^^^^^^^^^
8
+
9
+ Motion models for points (particles) and rigid bodies in space and time are based on mathematical
10
+ equations.
11
+
12
+ Three degrees of freedom models employ translational
13
+ equations of motion.
14
+ Six degrees of freedom models
15
+ incorporate both translational
16
+ and rotational equations of motion.
17
+
18
+ The inputs to the equations of motion are the
19
+ forces and moments acting on the body;
20
+ yielding body accelerations as outputs.
21
+
22
+
23
+ Nomenclature and Convention
24
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
25
+
26
+ Typically, the forces and moments on a body are
27
+ resolved into components in the body coordinate system.
28
+ Fig-1 shows the components of
29
+ force, moment velocity, and angular rate of a body
30
+ resolved in the body coordinate system.
31
+ The six projections
32
+ of the linear and angular velocity vectors on the moving
33
+ body frame axes are the six degrees of freedom.
34
+ The nomenclature and conventions for positive directions
35
+ are as shown in Fig-1 and in the following Table:
36
+
37
+
38
+ .. figure:: /_architecture/rigidbody.svg
39
+
40
+ Fig-1: Forces, velocities, moments, and angular rates in body reference frame
41
+
42
+
43
+
44
+ .. list-table::
45
+ :widths: 10 20 20 20 20 20 20
46
+ :header-rows: 1
47
+
48
+ * - Axis
49
+ - Force along axis
50
+ - Moment about axis
51
+ - Linear velocity
52
+ - Angular displacement
53
+ - Angular velocity
54
+ - Moment of Inertia
55
+ * - :math:`x_b`
56
+ - :math:`{F_x}_b`
57
+ - :math:`L`
58
+ - :math:`u`
59
+ - :math:`\\varphi`
60
+ - :math:`p`
61
+ - :math:`I_{xx}`
62
+ * - :math:`y_b`
63
+ - :math:`{F_y}_b`
64
+ - :math:`M`
65
+ - :math:`v`
66
+ - :math:`\\theta`
67
+ - :math:`q`
68
+ - :math:`I_{yy}`
69
+ * - :math:`z_b`
70
+ - :math:`{F_z}_b`
71
+ - :math:`N`
72
+ - :math:`w`
73
+ - :math:`\\psi`
74
+ - :math:`r`
75
+ - :math:`I_{zz}`
76
+
77
+
78
+ The position of the mass center of the body is given by
79
+ its Cartesian coordinates expressed in an inertial frame of
80
+ reference, such as the fixed-earth frame :math:`(x, y, z)`.
81
+
82
+ The body's angular orientation is defined by three rotations :math:`(\\psi, \\theta, \\varphi)`
83
+ relative to the inertial frame of reference.
84
+ These are
85
+ called Euler rotations, and the order of the successive rotations
86
+ is important.
87
+ Starting with the body coordinate frame
88
+ aligned with the earth coordinate frame, the adopted order here is 3-2-1, i.e.:
89
+
90
+ (1) Rotate the body frame about the :math:`z_b` axis through the heading angle :math:`\\psi`,
91
+ (2) Rotate about the :math:`y_b` axis through the pitch angle :math:`\\theta`, and
92
+ (3) Rotate about the :math:`x_b` axis through the roll angle :math:`\\varphi`
93
+
94
+ The total inertial velocity :math:`V` has components :math:`u, v`, and :math:`w` on the body frame axes,
95
+ and :math:`(v_x, v_y, v_z)` on the earth-frame axes.
96
+
97
+
98
+ Newton's Second Law
99
+ ^^^^^^^^^^^^^^^^^^^
100
+
101
+ Newton’s second law of motion establishes the foundational
102
+ equation governing the relationship among
103
+ force, mass, and acceleration.
104
+
105
+
106
+ in the context of Newton's second law, the force :math:`(F)`
107
+ acting on an object is the derivative of its momentum :math:`(m \\cdot v)`
108
+ with respect to time :math:`(t)`:
109
+
110
+ .. math::
111
+ F = {d(m \\cdot v) \\over dt}
112
+
113
+ Where:
114
+
115
+ - :math:`F` is the total force acting on the object
116
+ - :math:`m` is the mass of the object
117
+ - :math:`v` is the velocity
118
+ - :math:`t` is time
119
+
120
+ This equation yields the final form of the equations of linear motion.
121
+ In the final form, acceleration is represented by the rate of change of the velocity:
122
+
123
+ .. math::
124
+ F = m \\cdot \\dot{v}
125
+
126
+ Where:
127
+
128
+ - :math:`F` is the total force acting on the object
129
+ - :math:`m` is the mass of the object
130
+ - :math:`\\dot{v}` is the acceleration of the object
131
+
132
+
133
+ A direct extension of Newton's second law to rotational motion
134
+ reveals that the moment of force (torque) on a body
135
+ about a given axis equals the time rate of change of the
136
+ angular momentum of the paricle about that axis.
137
+
138
+
139
+ .. math::
140
+ M = {dh \\over dt}
141
+
142
+ Where:
143
+
144
+ - :math:`M` is the total moment (torque) acting on the object
145
+ - :math:`h` is the angular momentum vector of the object
146
+
147
+
148
+
149
+ Hence, the final form of the equations of angular motion is given by:
150
+
151
+ .. math::
152
+ M = [I] \\cdot \\dot{\\omega}
153
+
154
+ Where:
155
+
156
+ - :math:`M` is the total moment (torque) acting on the object
157
+
158
+ - :math:`[I]` is the inertia matrix of the body relative to the axis of rotation
159
+
160
+ - :math:`\\dot{\\omega}` is the absolute angular acceleration vector of the body
161
+
162
+
163
+
164
+
165
+ Translational Equations of Motion
166
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
167
+
168
+ The basis of the translational equation of motion was introduced
169
+ above.
170
+ The usual procedure used to solve this
171
+ equation is to sum the external forces
172
+ :math:`F` acting on the body, express them in an
173
+ inertial frame, and substitute :math:`F` into
174
+ the equation.
175
+ Once the acceleration, namely the forces
176
+ divided by the mass, is expressed in inertial coordinates,
177
+ it is integrated twice to yield the
178
+ translational displacement.
179
+
180
+
181
+ .. math::
182
+ dx = v_x
183
+
184
+ dy = v_y
185
+
186
+ dz = v_z
187
+
188
+ dv_x = {F[0] \\over m}
189
+
190
+ dv_y = {F[1] \\over m}
191
+
192
+ dv_z = {F[2] \\over m}
193
+
194
+ Where:
195
+
196
+ - :math:`dx, dy, dz` are the changes in position in the :math:`x, y, z` inertial directions, respectively
197
+ - :math:`dv_x, dv_y, dv_z` are the changes in velocity in the :math:`x, y, z` inertial directions, respectively
198
+ - :math:`v_x, v_y, v_z` are the velocities in the :math:`x, y, z` inertial directions, respectively
199
+ - :math:`f[0], f[1], f[2]` are the input force components in the :math:`x, y, z` inertial directions, respectively
200
+ - :math:`m` is the mass of the body.
201
+
202
+
203
+ These equations describe the dynamics of a datapoint in three-dimensional space (**3DOF**).
204
+ Which is
205
+ the rate of change of position
206
+ :math:`(x, y, z)` with respect to time equals to the velocity,
207
+ and the rate of change of velocity
208
+ :math:`(v_x, v_y, v_z)` with respect to time
209
+ equals to the force divided by the mass :math:`(m)`.
210
+
211
+
212
+
213
+
214
+ Rotational Equations of Motion
215
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
216
+
217
+ As mentioned earlier, the rotational analog
218
+ of Newton's law describes the relationship between torque,
219
+ moment of inertia, and angular acceleration.
220
+ We also saw that a double integration on the translational
221
+ acceleration produces the change of the body in position.
222
+
223
+ However, the angular accelerations
224
+ are typically expressed with respect to a body frame and
225
+ must be adjusted in order to produce the attitude of the
226
+ body.
227
+ For that purpose we introduced the euler angles (see Nomenclature and Conventions)
228
+ which describe the
229
+ body attitude with respect to an inertial frame of reference.
230
+
231
+ The orientation of the body reference frame is specified by the three
232
+ Euler angles, :math:`\\psi, \\theta, \\varphi`.
233
+
234
+ As a rigid body changes its orientation
235
+ in space, the Euler angles change.
236
+ The rates of change
237
+ of the Euler angles are related to the angular rates :math:`(p, q, r)` of the
238
+ body frame.
239
+
240
+ The rate of change of the Euler angles together with the rotational analog
241
+ of Newton's law provide the set of differential equations
242
+ that
243
+ describe the equations governing the motion of a rigid body:
244
+
245
+
246
+ .. math::
247
+
248
+ d\\varphi = p + (q \\cdot sin(\\varphi) + r \\cdot cos(\\varphi)) \\cdot tan(\\theta)
249
+
250
+ d\\theta = q \\cdot cos(\\varphi) - r \\cdot sin(\\varphi)
251
+
252
+ d\\psi = {q \\cdot sin(\\varphi) + r \\cdot cos(\\phi) \\over cos(\\theta)}
253
+
254
+ dp = {M[0] - q \\cdot r \\cdot (I_{zz} - I_{yy}) \\over I_{xx}}
255
+
256
+ dq = {M[1] - p \\cdot r \\cdot (I_{xx} - I_{zz}) \\over I_{yy}}
257
+
258
+ dr = {M[2] - p \\cdot q \\cdot (I_{yy} - I_{xx}) \\over I_{zz}}
259
+
260
+ Where:
261
+
262
+ - :math:`d\\varphi, d\\theta, d\\psi` are the changes in Euler roll, Euler pitch, and Euler yaw angles, respectively
263
+ - :math:`dp, dq, dr` are the changes in body roll rate, pitch rate, and yaw rate, respectively
264
+ - :math:`\\varphi, \\theta, \\psi` are the Euler roll, Euler pitch, and uler yaw angles, respectively
265
+ - :math:`p, q, r` are the body roll rate, pitch rate, and yaw rate, respcetively
266
+ - :math:`M[0], M[1], M[2]` are the input moment of force components about the :math:`x, y, z` in the body direction, respectively
267
+ - :math:`I_{xx}, I_{yy}, I_{zz}` are the moments of inertia about the :math:`x, y,` and :math:`z` in body direction, respectively
268
+
269
+
270
+ These equations describe the angular dynamics of a rigid body.
271
+ Together with the equations that describe the translational
272
+ motion of the body they form the six-dimensional motion in space (**6DOF**).
273
+
274
+
275
+ References
276
+ ----------
277
+
278
+ .. [MI] 17 July 1995, "Missile Flight Simulation, Part One, Surface-to-Air Missiles",
279
+ Ch 4 In: Military Handbook. 1995, MIL-HDBK-1211(MI)
280
+
281
+
282
+
283
+ Examples
284
+ --------
285
+
286
+ For examples, see the various functions.
287
+
288
+ '''
289
+ import sys, os
290
+ sys.path.append('.')
291
+
292
+
293
+ from c4dynamics.eqm.derivs import *
294
+ from c4dynamics.eqm.integrate import *
295
+
296
+
297
+
298
+
299
+ if __name__ == "__main__":
300
+
301
+ import doctest, contextlib
302
+ from c4dynamics import IgnoreOutputChecker, cprint
303
+
304
+ # Register the custom OutputChecker
305
+ doctest.OutputChecker = IgnoreOutputChecker
306
+
307
+ tofile = False
308
+ optionflags = doctest.FAIL_FAST
309
+
310
+ if tofile:
311
+ with open(os.path.join('tests', '_out', 'output.txt'), 'w') as f:
312
+ with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f):
313
+ result = doctest.testmod(optionflags = optionflags)
314
+ else:
315
+ result = doctest.testmod(optionflags = optionflags)
316
+
317
+ if result.failed == 0:
318
+ cprint(os.path.basename(__file__) + ": all tests passed!", 'g')
319
+ else:
320
+ print(f"{result.failed}")
321
+
322
+
323
+
324
+
@@ -0,0 +1,212 @@
1
+ from typing import Union
2
+ import numpy as np
3
+ import sys
4
+ sys.path.append('.')
5
+ from c4dynamics.utils.math import *
6
+ from c4dynamics import datapoint, rigidbody
7
+
8
+ def eqm3(dp: 'datapoint', F: Union[np.ndarray, list]) -> np.ndarray:
9
+ '''
10
+ Translational motion derivatives.
11
+
12
+ These equations represent a set of first-order ordinary
13
+ differential equations (ODEs) that describe the motion
14
+ of a datapoint in three-dimensional space under the influence
15
+ of external forces.
16
+
17
+ Parameters
18
+ ----------
19
+ dp : :class:`datapoint <c4dynamics.states.lib.datapoint.datapoint>`
20
+ C4dynamics' datapoint object for which the equations of motion are calculated.
21
+
22
+ F : array_like
23
+ Force vector :math:`[F_x, F_y, F_z]`
24
+
25
+ Returns
26
+ -------
27
+ out : numpy.array
28
+ :math:`[dx, dy, dz, dv_x, dv_y, dv_z]`
29
+ 6 derivatives of the equations of motion, 3 position derivatives,
30
+ and 3 velocity derivatives.
31
+
32
+ Examples
33
+ --------
34
+
35
+ Import required packages:
36
+
37
+ .. code::
38
+
39
+ >>> import c4dynamics as c4d
40
+ >>> from matplotlib import pyplot as plt
41
+ >>> import numpy as np
42
+
43
+
44
+ .. code::
45
+
46
+ >>> dp = c4d.datapoint()
47
+ >>> dp.mass = 10 # mass 10kg # doctest: +IGNORE_OUTPUT
48
+ >>> F = [0, 0, c4d.g_ms2] # g_ms2 = 9.8m/s^2
49
+ >>> c4d.eqm.eqm3(dp, F) # doctest: +NUMPY_FORMAT
50
+ array([0 0 0 0 0 0.980665])
51
+
52
+
53
+ Euler integration on the equations of motion of
54
+ mass in a free fall:
55
+
56
+
57
+ .. code::
58
+
59
+ >>> h0 = 10000
60
+ >>> pt = c4d.datapoint(z = 10000)
61
+ >>> while pt.z > 0:
62
+ ... pt.store()
63
+ ... dx = c4d.eqm.eqm3(pt, [0, 0, -c4d.g_ms2])
64
+ ... pt.X += dx # (dt = 1)
65
+ >>> pt.plot('z')
66
+ >>> # comapre to anayltic solution
67
+ >>> t = np.arange(len(pt.data('t')))
68
+ >>> z = h0 - .5 * c4d.g_ms2 * t**2
69
+ >>> plt.gca().plot(t[z > 0], z[z > 0], 'c', linewidth = 1) # doctest: +IGNORE_OUTPUT
70
+
71
+ .. figure:: /_examples/eqm/eqm3.png
72
+
73
+ '''
74
+
75
+ dx = dp.vx
76
+ dy = dp.vy
77
+ dz = dp.vz
78
+
79
+ dvx = F[0] / dp.mass
80
+ dvy = F[1] / dp.mass
81
+ dvz = F[2] / dp.mass
82
+
83
+ return np.array([dx, dy, dz, dvx, dvy, dvz])
84
+
85
+
86
+ def eqm6(rb: 'rigidbody', F: Union[np.ndarray, list], M: Union[np.ndarray, list]) -> np.ndarray:
87
+ '''
88
+ Translational and angular motion derivatives.
89
+
90
+ A set of first-order ordinary
91
+ differential equations (ODEs) that describe the motion
92
+ of a rigid body in three-dimensional space under the influence
93
+ of external forces and moments.
94
+
95
+ Parameters
96
+ ----------
97
+ rb : :class:`rigidbody <c4dynamics.states.lib.rigidbody.rigidbody>`
98
+ C4dynamics' rigidbody object for which the
99
+ equations of motion are calculated on.
100
+ F : array_like
101
+ Force vector :math:`[F_x, F_y, F_z]`
102
+ M : array_like
103
+ Moments vector :math:`[M_x, M_y, M_z]`
104
+
105
+ Returns
106
+ -------
107
+ out : numpy.array
108
+ :math:`[dx, dy, dz, dv_x, dv_y, dv_z, d\\varphi, d\\theta, d\\psi, dp, dq, dr]`
109
+
110
+ 12 total derivatives; 6 of translational motion, 6 of rotational motion.
111
+
112
+ Examples
113
+ --------
114
+ Euler integration on the equations of motion of
115
+ a stick fixed at one edge:
116
+
117
+ (mass: 0.5 kg, moment of inertia about y: 0.4 kg*m^2,
118
+ Length: 1m, initial Euler pitch angle: 80° (converted to radians))
119
+
120
+
121
+ Import required packages:
122
+
123
+ .. code::
124
+
125
+ >>> import c4dynamics as c4d
126
+ >>> import numpy as np
127
+
128
+ Settings and initial conditions
129
+
130
+ .. code::
131
+
132
+ >>> dt = 0.5e-3
133
+ >>> t = np.arange(0, 10, dt)
134
+ >>> length = 1 # metter
135
+ >>> rb = c4d.rigidbody(theta = 80 * c4d.d2r)
136
+ >>> rb.mass = 0.5 # kg
137
+ >>> rb.I = [0, 0.4, 0]
138
+
139
+
140
+ Main loop:
141
+
142
+ .. code::
143
+
144
+ >>> for ti in t:
145
+ ... rb.store(ti)
146
+ ... tau_g = -rb.mass * c4d.g_ms2 * length / 2 * c4d.cos(rb.theta)
147
+ ... dx = c4d.eqm.eqm6(rb, np.zeros(3), [0, tau_g, 0])
148
+ ... rb.X += dx * dt
149
+ >>> rb.plot('theta')
150
+
151
+ .. figure:: /_examples/eqm/eqm3.png
152
+
153
+ '''
154
+
155
+ ixx, iyy, izz = rb.I
156
+ #
157
+ # translational motion derivatives
158
+ ##
159
+ dx = rb.vx
160
+ dy = rb.vy
161
+ dz = rb.vz
162
+
163
+ dvx = F[0] / rb.mass
164
+ dvy = F[1] / rb.mass
165
+ dvz = F[2] / rb.mass
166
+
167
+ #
168
+ # euler angles derivatives
169
+ ##
170
+ dphi = (rb.q * sin(rb.phi) + rb.r * cos(rb.phi)) * tan(rb.theta) + rb.p
171
+ dtheta = rb.q * cos(rb.phi) - rb.r * sin(rb.phi)
172
+ dpsi = (rb.q * sin(rb.phi) + rb.r * cos(rb.phi)) / cos(rb.theta)
173
+
174
+ #
175
+ # angular motion derivatives
176
+ ##
177
+ # dp = (lA - q * r * (izz - iyy)) / ixx
178
+ dp = 0 if ixx == 0 else (M[0] - rb.q * rb.r * (izz - iyy)) / ixx
179
+ dq = 0 if iyy == 0 else (M[1] - rb.p * rb.r * (ixx - izz)) / iyy
180
+ dr = 0 if izz == 0 else (M[2] - rb.p * rb.q * (iyy - ixx)) / izz
181
+
182
+ # 0 1 2 3 4 5 6 7 8 9 10 11
183
+ return np.array([dx, dy, dz, dvx, dvy, dvz, dphi, dtheta, dpsi, dp, dq, dr])
184
+
185
+
186
+
187
+
188
+
189
+ if __name__ == "__main__":
190
+
191
+ import doctest, contextlib, os
192
+ from c4dynamics import IgnoreOutputChecker, cprint
193
+
194
+ # Register the custom OutputChecker
195
+ doctest.OutputChecker = IgnoreOutputChecker
196
+
197
+ tofile = False
198
+ optionflags = doctest.FAIL_FAST
199
+
200
+ if tofile:
201
+ with open(os.path.join('tests', '_out', 'output.txt'), 'w') as f:
202
+ with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f):
203
+ result = doctest.testmod(optionflags = optionflags)
204
+ else:
205
+ result = doctest.testmod(optionflags = optionflags)
206
+
207
+ if result.failed == 0:
208
+ cprint(os.path.basename(__file__) + ": all tests passed!", 'g')
209
+ else:
210
+ print(f"{result.failed}")
211
+
212
+