|
a |
|
b/Tools/AnyMocap/RotationAxisAngles.any |
|
|
1 |
#ifndef _ANYMOCAP_ROTATION_AXIS_ANGLES_ANY_ |
|
|
2 |
#define _ANYMOCAP_ROTATION_AXIS_ANGLES_ANY_ |
|
|
3 |
/* |
|
|
4 |
--- |
|
|
5 |
group: Utilities |
|
|
6 |
topic: Angles |
|
|
7 |
descr: | |
|
|
8 |
Class template to calculate Bryant (euler) angles for the z-y-x rotation |
|
|
9 |
sequence given a a rotation matrix. |
|
|
10 |
--- |
|
|
11 |
|
|
|
12 |
To use these drivers import the file: |
|
|
13 |
#include "<AMMR_TOOLS>/AnyMoCap/RotationAxisAngles.any" |
|
|
14 |
|
|
|
15 |
See the individual classes for more information. |
|
|
16 |
|
|
|
17 |
*/ |
|
|
18 |
|
|
|
19 |
|
|
|
20 |
// |
|
|
21 |
// Calculates the Bryant (euler) angles for the z-y-x rotation sequence given a |
|
|
22 |
// rotation matrix |
|
|
23 |
// |
|
|
24 |
// :::{rubric} Example |
|
|
25 |
// ::: |
|
|
26 |
// Here is an example of how to use the class. |
|
|
27 |
// |
|
|
28 |
// ```{code-block} AnyScriptDoc |
|
|
29 |
// |
|
|
30 |
// RotAxisAnglesZYX Angles(ROT = .SomeSeg.Axes0) = {}; |
|
|
31 |
// |
|
|
32 |
// // Results are in radians |
|
|
33 |
// AnyVar zRot = Angles.zRot; |
|
|
34 |
// AnyVar yRot = Angles.yRot; |
|
|
35 |
// AnyVar xRot = Angles.xRot; |
|
|
36 |
// |
|
|
37 |
// ``` |
|
|
38 |
// |
|
|
39 |
// The class can also calculate the relative |
|
|
40 |
// rotation angles between two segments. |
|
|
41 |
// |
|
|
42 |
// ```{code-block} AnyScriptDoc |
|
|
43 |
// |
|
|
44 |
// RotAxisAnglesZYX Angles(ROT = .SomeSeg.Axes0) = { |
|
|
45 |
// ROT_rel = .SomeOtherSeg.Axes0; |
|
|
46 |
// }; |
|
|
47 |
// |
|
|
48 |
// ``` |
|
|
49 |
// |
|
|
50 |
#class_template RotAxisAnglesZYX (ROT){ |
|
|
51 |
// Arguments |
|
|
52 |
// ----------- |
|
|
53 |
// RotAxisAnglesZYX#ROT |
|
|
54 |
// The rotation matrix to calculate the angles from |
|
|
55 |
|
|
|
56 |
|
|
|
57 |
// RotAxisAnglesZYX |
|
|
58 |
/// A relative rotation matrix so the angles are calculated |
|
|
59 |
/// between these two rotation matrices. |
|
|
60 |
#var AnyMat33 ROT_rel = eye(3); |
|
|
61 |
|
|
|
62 |
AnyFolder Calculations = { |
|
|
63 |
|
|
|
64 |
|
|
|
65 |
AnyMat33 Rot = .ROT_rel'*.ROT; |
|
|
66 |
|
|
|
67 |
AnyVar yRot1 = asin(-Rot[2][0]); |
|
|
68 |
AnyVar yRot2 = pi - yRot1; |
|
|
69 |
|
|
|
70 |
AnyVar zRot1 = atan2(Rot[1][0]/cos(yRot1), Rot[0][0]/cos(yRot1)); |
|
|
71 |
AnyVar zRot2 = atan2(Rot[1][0]/cos(yRot2), Rot[0][0]/cos(yRot2)); |
|
|
72 |
|
|
|
73 |
AnyVar xRot1 = atan2(Rot[2][1]/cos(yRot1),Rot[2][2]/cos(yRot1)); |
|
|
74 |
AnyVar xRot2 = atan2(Rot[2][1]/cos(yRot2),Rot[2][2]/cos(yRot2)); |
|
|
75 |
AnyVar abs1 = abs(zRot1)+abs(yRot1)+abs(zRot1); |
|
|
76 |
AnyVar abs2 = abs(zRot2)+abs(yRot2)+abs(zRot2); |
|
|
77 |
}; |
|
|
78 |
|
|
|
79 |
AnyVar zRot = iffun(gtfun(Calculations.abs1,Calculations.abs2), Calculations.zRot2,Calculations.zRot1); |
|
|
80 |
AnyVar yRot = iffun(gtfun(Calculations.abs1,Calculations.abs2), Calculations.yRot2,Calculations.yRot1); |
|
|
81 |
AnyVar xRot = iffun(gtfun(Calculations.abs1,Calculations.abs2), Calculations.xRot2,Calculations.xRot1) ; |
|
|
82 |
}; |
|
|
83 |
|
|
|
84 |
|
|
|
85 |
|
|
|
86 |
/* |
|
|
87 |
Class to bind two segments together with drivers based on their load time positions. The |
|
|
88 |
driver constraint type can be controlled by the `_CTYPE` arg |
|
|
89 |
|
|
|
90 |
The class adds a node on Seg1 with position and velocity set to 0. This helps certain |
|
|
91 |
situations where gimbal lock might occur. |
|
|
92 |
|
|
|
93 |
The class can also add add the forces between the segments using strong recruited |
|
|
94 |
actuators. (Recruited actuators are used to avoid statically indeterminate systems, |
|
|
95 |
which could easily occur with normal reaction forces.) |
|
|
96 |
|
|
|
97 |
|
|
|
98 |
DriverBasedOnLoadPos driver1(Seg1=..Mass1,Seg2=..Mass2, NodeName = Node1) ={}; |
|
|
99 |
|
|
|
100 |
|
|
|
101 |
|
|
|
102 |
*/ |
|
|
103 |
|
|
|
104 |
#class_template DriverBasedOnLoadPos(AnySeg &Seg1,AnySeg &Seg2, NodeName, RECRUITMENT_CONSTRAINTS = 1, _CTYPE = Soft){ |
|
|
105 |
|
|
|
106 |
RotAxisAnglesZYX RotPos (ROT=.Seg2.Axes0)= {ROT_rel=.Seg1.Axes0;}; |
|
|
107 |
|
|
|
108 |
|
|
|
109 |
Seg1= { |
|
|
110 |
// AnyDrawSeg drw2 ={}; |
|
|
111 |
AnyRefNode NodeName ={ |
|
|
112 |
sRel=(..Seg2.r0-.r0)*.Axes0; |
|
|
113 |
ARel= RotMat(..RotPos.zRot,z)*RotMat(..RotPos.yRot,y)*RotMat(..RotPos.xRot,x); |
|
|
114 |
}; |
|
|
115 |
}; |
|
|
116 |
|
|
|
117 |
AnyKinEqSimpleDriver driver ={ |
|
|
118 |
AnyKinLinear lin ={ |
|
|
119 |
AnyRefFrame &ref1=..Seg1.NodeName; |
|
|
120 |
AnyRefFrame &ref2=..Seg2; |
|
|
121 |
}; |
|
|
122 |
AnyKinRotational rot ={ |
|
|
123 |
AnyRefFrame &ref1=..Seg1.NodeName; |
|
|
124 |
AnyRefFrame &ref2=..Seg2; |
|
|
125 |
Type=RotVector; |
|
|
126 |
}; |
|
|
127 |
|
|
|
128 |
DriverPos={0,0,0,0,0,0}; |
|
|
129 |
DriverVel={0,0,0,0,0,0}; |
|
|
130 |
Reaction.Type={Off,Off,Off,Off,Off,Off}; |
|
|
131 |
CType={_CTYPE,_CTYPE,_CTYPE,_CTYPE,_CTYPE,_CTYPE}; |
|
|
132 |
}; |
|
|
133 |
|
|
|
134 |
#if RECRUITMENT_CONSTRAINTS |
|
|
135 |
AnyRecruitedActuator RecruitedReactions_1 = { |
|
|
136 |
AnyKinMeasure &lin=.driver.lin; |
|
|
137 |
AnyKinMeasure &rot=.driver.rot; |
|
|
138 |
Type = NonNegative; |
|
|
139 |
Strength = {2000,2000,2000,2000,2000,2000}; |
|
|
140 |
SET_DEFAULT_ACTUATOR_VOLUME; |
|
|
141 |
}; |
|
|
142 |
AnyRecruitedActuator RecruitedReactions_2 = { |
|
|
143 |
AnyKinMeasure &lin=.driver.lin; |
|
|
144 |
AnyKinMeasure &rot=.driver.rot; |
|
|
145 |
Type = NonPositive; |
|
|
146 |
Strength = {2000,2000,2000,2000,2000,2000}; |
|
|
147 |
SET_DEFAULT_ACTUATOR_VOLUME; |
|
|
148 |
}; |
|
|
149 |
#endif |
|
|
150 |
}; |
|
|
151 |
|
|
|
152 |
|
|
|
153 |
|
|
|
154 |
#endif |