--- a +++ b/Tools/AnyMocap/RotationAxisAngles.any @@ -0,0 +1,154 @@ +#ifndef _ANYMOCAP_ROTATION_AXIS_ANGLES_ANY_ +#define _ANYMOCAP_ROTATION_AXIS_ANGLES_ANY_ +/* +--- +group: Utilities +topic: Angles +descr: | + Class template to calculate Bryant (euler) angles for the z-y-x rotation + sequence given a a rotation matrix. +--- + +To use these drivers import the file: +#include "<AMMR_TOOLS>/AnyMoCap/RotationAxisAngles.any" + +See the individual classes for more information. + +*/ + + +// +// Calculates the Bryant (euler) angles for the z-y-x rotation sequence given a +// rotation matrix +// +// :::{rubric} Example +// ::: +// Here is an example of how to use the class. +// +// ```{code-block} AnyScriptDoc +// +// RotAxisAnglesZYX Angles(ROT = .SomeSeg.Axes0) = {}; +// +// // Results are in radians +// AnyVar zRot = Angles.zRot; +// AnyVar yRot = Angles.yRot; +// AnyVar xRot = Angles.xRot; +// +// ``` +// +// The class can also calculate the relative +// rotation angles between two segments. +// +// ```{code-block} AnyScriptDoc +// +// RotAxisAnglesZYX Angles(ROT = .SomeSeg.Axes0) = { +// ROT_rel = .SomeOtherSeg.Axes0; +// }; +// +// ``` +// +#class_template RotAxisAnglesZYX (ROT){ + // Arguments + // ----------- + // RotAxisAnglesZYX#ROT + // The rotation matrix to calculate the angles from + + + // RotAxisAnglesZYX + /// A relative rotation matrix so the angles are calculated + /// between these two rotation matrices. + #var AnyMat33 ROT_rel = eye(3); + + AnyFolder Calculations = { + + + AnyMat33 Rot = .ROT_rel'*.ROT; + + AnyVar yRot1 = asin(-Rot[2][0]); + AnyVar yRot2 = pi - yRot1; + + AnyVar zRot1 = atan2(Rot[1][0]/cos(yRot1), Rot[0][0]/cos(yRot1)); + AnyVar zRot2 = atan2(Rot[1][0]/cos(yRot2), Rot[0][0]/cos(yRot2)); + + AnyVar xRot1 = atan2(Rot[2][1]/cos(yRot1),Rot[2][2]/cos(yRot1)); + AnyVar xRot2 = atan2(Rot[2][1]/cos(yRot2),Rot[2][2]/cos(yRot2)); + AnyVar abs1 = abs(zRot1)+abs(yRot1)+abs(zRot1); + AnyVar abs2 = abs(zRot2)+abs(yRot2)+abs(zRot2); + }; + + AnyVar zRot = iffun(gtfun(Calculations.abs1,Calculations.abs2), Calculations.zRot2,Calculations.zRot1); + AnyVar yRot = iffun(gtfun(Calculations.abs1,Calculations.abs2), Calculations.yRot2,Calculations.yRot1); + AnyVar xRot = iffun(gtfun(Calculations.abs1,Calculations.abs2), Calculations.xRot2,Calculations.xRot1) ; +}; + + + +/* + Class to bind two segments together with drivers based on their load time positions. The + driver constraint type can be controlled by the `_CTYPE` arg + + The class adds a node on Seg1 with position and velocity set to 0. This helps certain + situations where gimbal lock might occur. + + The class can also add add the forces between the segments using strong recruited + actuators. (Recruited actuators are used to avoid statically indeterminate systems, + which could easily occur with normal reaction forces.) + + + DriverBasedOnLoadPos driver1(Seg1=..Mass1,Seg2=..Mass2, NodeName = Node1) ={}; + + + +*/ + +#class_template DriverBasedOnLoadPos(AnySeg &Seg1,AnySeg &Seg2, NodeName, RECRUITMENT_CONSTRAINTS = 1, _CTYPE = Soft){ + + RotAxisAnglesZYX RotPos (ROT=.Seg2.Axes0)= {ROT_rel=.Seg1.Axes0;}; + + + Seg1= { + // AnyDrawSeg drw2 ={}; + AnyRefNode NodeName ={ + sRel=(..Seg2.r0-.r0)*.Axes0; + ARel= RotMat(..RotPos.zRot,z)*RotMat(..RotPos.yRot,y)*RotMat(..RotPos.xRot,x); + }; + }; + + AnyKinEqSimpleDriver driver ={ + AnyKinLinear lin ={ + AnyRefFrame &ref1=..Seg1.NodeName; + AnyRefFrame &ref2=..Seg2; + }; + AnyKinRotational rot ={ + AnyRefFrame &ref1=..Seg1.NodeName; + AnyRefFrame &ref2=..Seg2; + Type=RotVector; + }; + + DriverPos={0,0,0,0,0,0}; + DriverVel={0,0,0,0,0,0}; + Reaction.Type={Off,Off,Off,Off,Off,Off}; + CType={_CTYPE,_CTYPE,_CTYPE,_CTYPE,_CTYPE,_CTYPE}; + }; + + #if RECRUITMENT_CONSTRAINTS + AnyRecruitedActuator RecruitedReactions_1 = { + AnyKinMeasure &lin=.driver.lin; + AnyKinMeasure &rot=.driver.rot; + Type = NonNegative; + Strength = {2000,2000,2000,2000,2000,2000}; + SET_DEFAULT_ACTUATOR_VOLUME; + }; + AnyRecruitedActuator RecruitedReactions_2 = { + AnyKinMeasure &lin=.driver.lin; + AnyKinMeasure &rot=.driver.rot; + Type = NonPositive; + Strength = {2000,2000,2000,2000,2000,2000}; + SET_DEFAULT_ACTUATOR_VOLUME; + }; + #endif +}; + + + +#endif