Simbody

Rotation.h

Go to the documentation of this file.
00001 //-----------------------------------------------------------------------------
00002 // File:     Rotation.h
00003 // Class:    Rotation and InverseRotation 
00004 // Parent:   Mat33
00005 // Purpose:  3x3 rotation class relating two right-handed orthogonal bases
00006 //-----------------------------------------------------------------------------
00007 #ifndef SIMTK_ROTATION_H 
00008 #define SIMTK_ROTATION_H 
00009 
00010 /* -------------------------------------------------------------------------- *
00011  *                      SimTK Core: SimTK Simmatrix(tm)                       *
00012  * -------------------------------------------------------------------------- *
00013  * This is part of the SimTK Core biosimulation toolkit originating from      *
00014  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00015  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00016  * Medical Research, grant U54 GM072970. See https://simtk.org.               *
00017  *                                                                            *
00018  * Portions copyright (c) 2005-9 Stanford University and the Authors.         *
00019  * Authors: Paul Mitiguy and Michael Sherman                                  *
00020  * Contributors:                                                              *
00021  *                                                                            *
00022  * Permission is hereby granted, free of charge, to any person obtaining a    *
00023  * copy of this software and associated documentation files (the "Software"), *
00024  * to deal in the Software without restriction, including without limitation  *
00025  * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
00026  * and/or sell copies of the Software, and to permit persons to whom the      *
00027  * Software is furnished to do so, subject to the following conditions:       *
00028  *                                                                            *
00029  * The above copyright notice and this permission notice shall be included in *
00030  * all copies or substantial portions of the Software.                        *
00031  *                                                                            *
00032  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
00033  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
00034  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
00035  * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
00036  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
00037  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
00038  * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
00039  * -------------------------------------------------------------------------- */
00040 
00041 //------------------------------------------------------------------------------
00042 
00043 #include "SimTKcommon/SmallMatrix.h"
00044 #include "SimTKcommon/internal/CoordinateAxis.h"
00045 #include "SimTKcommon/internal/UnitVec.h"
00046 #include "SimTKcommon/internal/Quaternion.h"
00047 
00048 //------------------------------------------------------------------------------
00049 #include <iosfwd>  // Forward declaration of iostream
00050 //------------------------------------------------------------------------------
00051 
00052 //------------------------------------------------------------------------------
00053 namespace SimTK {
00054 
00055 
00056 enum BodyOrSpaceType { BodyRotationSequence=0, SpaceRotationSequence=1 };
00057 
00058 //------------------------------------------------------------------------------
00059 // Forward declarations
00060 template <class P> class Rotation_;
00061 template <class P> class InverseRotation_;
00062 
00063 typedef Rotation_<Real>             Rotation;
00064 typedef Rotation_<float>           fRotation;
00065 typedef Rotation_<double>          dRotation;
00066 
00067 typedef InverseRotation_<Real>      InverseRotation;
00068 typedef InverseRotation_<float>    fInverseRotation;
00069 typedef InverseRotation_<double>   dInverseRotation;
00070 
00071 //------------------------------------------------------------------------------
00116 //------------------------------------------------------------------------------
00117 template <class P> // templatized by precision
00118 class Rotation_ : public Mat<3,3,P> {
00119     typedef P               RealP;
00120     typedef Mat<2,2,P>      Mat22P;
00121     typedef Mat<3,2,P>      Mat32P;
00122     typedef Mat<3,3,P>      Mat33P;
00123     typedef Vec<2,P>        Vec2P;
00124     typedef Vec<3,P>        Vec3P;
00125     typedef Vec<4,P>        Vec4P;
00126     typedef UnitVec<P,1>    UnitVec3P; // stride is 1 here, length is always 3
00127     typedef SymMat<3,P>     SymMat33P;
00128     typedef Quaternion_<P>  QuaternionP;
00129 public:
00130     // Default constructor and constructor-like methods
00131     Rotation_() : Mat33P(1) {}    
00132     Rotation_&  setRotationToIdentityMatrix()  { Mat33P::operator=(RealP(1));  return *this; }
00133     Rotation_&  setRotationToNaN()             { Mat33P::setToNaN();    return *this; } 
00134 
00135     // Default copy constructor and assignment operator
00136     Rotation_( const Rotation_& R ) : Mat33P(R)  {}
00137     Rotation_&  operator=( const Rotation_& R )  { Mat33P::operator=( R.asMat33() );  return *this; }
00138 
00140 
00141     Rotation_( RealP angle, const CoordinateAxis& axis )             { setRotationFromAngleAboutAxis( angle, axis ); }
00142     Rotation_( RealP angle, const CoordinateAxis::XCoordinateAxis )  { setRotationFromAngleAboutX( std::cos(angle), std::sin(angle) ); }
00143     Rotation_( RealP angle, const CoordinateAxis::YCoordinateAxis )  { setRotationFromAngleAboutY( std::cos(angle), std::sin(angle) ); }
00144     Rotation_( RealP angle, const CoordinateAxis::ZCoordinateAxis )  { setRotationFromAngleAboutZ( std::cos(angle), std::sin(angle) ); }
00146 
00147 
00148     Rotation_&  setRotationFromAngleAboutAxis( RealP angle, const CoordinateAxis& axis )  { return axis.isXAxis() ? setRotationFromAngleAboutX(angle) : (axis.isYAxis() ? setRotationFromAngleAboutY(angle) : setRotationFromAngleAboutZ(angle) ); }
00149     Rotation_&  setRotationFromAngleAboutX( RealP angle )  { return setRotationFromAngleAboutX( std::cos(angle), std::sin(angle) ); }
00150     Rotation_&  setRotationFromAngleAboutY( RealP angle )  { return setRotationFromAngleAboutY( std::cos(angle), std::sin(angle) ); }
00151     Rotation_&  setRotationFromAngleAboutZ( RealP angle )  { return setRotationFromAngleAboutZ( std::cos(angle), std::sin(angle) ); }
00152     Rotation_&  setRotationFromAngleAboutX( RealP cosAngle, RealP sinAngle )  { Mat33P& R = *this;  R[0][0] = 1;   R[0][1] = R[0][2] = R[1][0] = R[2][0] = 0;   R[1][1] = R[2][2] = cosAngle;  R[1][2] = -(R[2][1] = sinAngle);  return *this; }
00153     Rotation_&  setRotationFromAngleAboutY( RealP cosAngle, RealP sinAngle )  { Mat33P& R = *this;  R[1][1] = 1;   R[0][1] = R[1][0] = R[1][2] = R[2][1] = 0;   R[0][0] = R[2][2] = cosAngle;  R[2][0] = -(R[0][2] = sinAngle);  return *this; }
00154     Rotation_&  setRotationFromAngleAboutZ( RealP cosAngle, RealP sinAngle )  { Mat33P& R = *this;  R[2][2] = 1;   R[0][2] = R[1][2] = R[2][0] = R[2][1] = 0;   R[0][0] = R[1][1] = cosAngle;  R[0][1] = -(R[1][0] = sinAngle);  return *this; }
00156 
00158 
00159     Rotation_( RealP angle, const UnitVec3P& unitVector ) { setRotationFromAngleAboutUnitVector(angle,unitVector); }
00160     Rotation_( RealP angle, const Vec3P& nonUnitVector )  { setRotationFromAngleAboutNonUnitVector(angle,nonUnitVector); }
00162 
00163 
00164     Rotation_&  setRotationFromAngleAboutNonUnitVector( RealP angle, const Vec3P& nonUnitVector )  { return setRotationFromAngleAboutUnitVector( angle, UnitVec3P(nonUnitVector) ); }
00165     SimTK_SimTKCOMMON_EXPORT Rotation_&  setRotationFromAngleAboutUnitVector( RealP angle, const UnitVec3P& unitVector );
00167 
00169     Rotation_( BodyOrSpaceType bodyOrSpace, RealP angle1, const CoordinateAxis& axis1, RealP angle2, const CoordinateAxis& axis2 )                                            { setRotationFromTwoAnglesTwoAxes(    bodyOrSpace,angle1,axis1,angle2,axis2); }
00171     Rotation_( BodyOrSpaceType bodyOrSpace, RealP angle1, const CoordinateAxis& axis1, RealP angle2, const CoordinateAxis& axis2, RealP angle3, const CoordinateAxis& axis3 )  { setRotationFromThreeAnglesThreeAxes(bodyOrSpace,angle1,axis1,angle2,axis2,angle3,axis3); }
00173     SimTK_SimTKCOMMON_EXPORT Rotation_&  setRotationFromTwoAnglesTwoAxes(     BodyOrSpaceType bodyOrSpace, RealP angle1, const CoordinateAxis& axis1, RealP angle2, const CoordinateAxis& axis2 ); 
00175     SimTK_SimTKCOMMON_EXPORT Rotation_&  setRotationFromThreeAnglesThreeAxes( BodyOrSpaceType bodyOrSpace, RealP angle1, const CoordinateAxis& axis1, RealP angle2, const CoordinateAxis& axis2, RealP angle3, const CoordinateAxis& axis3 );
00176 
00180     void setRotationToBodyFixedXY( const Vec2P& v)   { setRotationFromTwoAnglesTwoAxes(     BodyRotationSequence, v[0], XAxis, v[1], YAxis ); }
00185     void setRotationToBodyFixedXYZ( const Vec3P& v)  { setRotationFromThreeAnglesThreeAxes( BodyRotationSequence, v[0], XAxis, v[1], YAxis, v[2], ZAxis ); }
00186 
00188     explicit Rotation_( const QuaternionP& q )  { setRotationFromQuaternion(q); }
00190     SimTK_SimTKCOMMON_EXPORT Rotation_&  setRotationFromQuaternion( const QuaternionP& q );
00191 
00193     Rotation_( const Mat33P& m, bool ) : Mat33P(m) {}
00194 
00196     explicit Rotation_( const Mat33P& m )  { setRotationFromApproximateMat33(m); }
00198     SimTK_SimTKCOMMON_EXPORT Rotation_&  setRotationFromApproximateMat33( const Mat33P& m );
00199 
00202 
00203     Rotation_( const UnitVec3P& uvec, const CoordinateAxis axis )  { setRotationFromOneAxis(uvec,axis); }
00204     SimTK_SimTKCOMMON_EXPORT Rotation_&  setRotationFromOneAxis( const UnitVec3P& uvec, const CoordinateAxis axis );
00206 
00213 
00214     Rotation_( const UnitVec3P& uveci, const CoordinateAxis& axisi, const Vec3P& vecjApprox, const CoordinateAxis& axisjApprox )  { setRotationFromTwoAxes(uveci,axisi,vecjApprox,axisjApprox); }
00215     SimTK_SimTKCOMMON_EXPORT Rotation_&  setRotationFromTwoAxes( const UnitVec3P& uveci, const CoordinateAxis& axisi, const Vec3P& vecjApprox, const CoordinateAxis& axisjApprox );
00217 
00218     // Converts rotation matrix to one or two or three orientation angles.
00219     // Note:  The result is most meaningful if the Rotation_ matrix is one that can be produced by such a sequence.
00220     // Use1:  someRotation.convertOneAxisRotationToOneAngle( XAxis );
00221     // Use2:  someRotation.convertTwoAxesRotationToTwoAngles(     SpaceRotationSequence, YAxis, ZAxis );
00222     // Use3:  someRotation.convertThreeAxesRotationToThreeAngles( SpaceRotationSequence, ZAxis, YAxis, XAxis );
00223     // Use4:  someRotation.convertRotationToAngleAxis();   Return: [angleInRadians, unitVectorX, unitVectorY, unitVectorZ].
00224 
00227     SimTK_SimTKCOMMON_EXPORT RealP  convertOneAxisRotationToOneAngle( const CoordinateAxis& axis1 ) const;
00230     SimTK_SimTKCOMMON_EXPORT Vec2P  convertTwoAxesRotationToTwoAngles(     BodyOrSpaceType bodyOrSpace, const CoordinateAxis& axis1, const CoordinateAxis& axis2 ) const;
00233     SimTK_SimTKCOMMON_EXPORT Vec3P  convertThreeAxesRotationToThreeAngles( BodyOrSpaceType bodyOrSpace, const CoordinateAxis& axis1, const CoordinateAxis& axis2, const CoordinateAxis& axis3 ) const;
00235     SimTK_SimTKCOMMON_EXPORT QuaternionP convertRotationToQuaternion() const;
00237     Vec4P  convertRotationToAngleAxis() const  { return convertRotationToQuaternion().convertQuaternionToAngleAxis(); }
00238 
00240     Vec2P  convertRotationToBodyFixedXY() const   { return convertTwoAxesRotationToTwoAngles( BodyRotationSequence, XAxis, YAxis ); }
00242     Vec3P  convertRotationToBodyFixedXYZ() const  { return convertThreeAxesRotationToThreeAngles( BodyRotationSequence, XAxis, YAxis, ZAxis ); }
00243 
00251     SimTK_SimTKCOMMON_EXPORT SymMat33P reexpressSymMat33(const SymMat33P& S_BB) const;
00252 
00254 
00255     SimTK_SimTKCOMMON_EXPORT bool  isSameRotationToWithinAngle( const Rotation_& R, RealP okPointingAngleErrorRads ) const;
00256     bool isSameRotationToWithinAngleOfMachinePrecision( const Rotation_& R) const       
00257     {   return isSameRotationToWithinAngle( R, NTraits<P>::getSignificant() ); }
00259     RealP  getMaxAbsDifferenceInRotationElements( const Rotation_& R ) const {            
00260         const Mat33P& A = asMat33();  const Mat33P& B = R.asMat33();  RealP maxDiff = 0;  
00261         for( int i=0;  i<=2; i++ ) for( int j=0; j<=2; j++ ) 
00262         {   RealP absDiff = std::fabs(A[i][j] - B[i][j]);  
00263             if( absDiff > maxDiff ) maxDiff = absDiff; }  
00264         return maxDiff; 
00265     } 
00266 
00267     bool  areAllRotationElementsSameToEpsilon( const Rotation_& R, RealP epsilon ) const 
00268     {   return getMaxAbsDifferenceInRotationElements(R) <= epsilon ; }
00269     bool  areAllRotationElementsSameToMachinePrecision( const Rotation_& R ) const       
00270     {   return areAllRotationElementsSameToEpsilon( R, NTraits<P>::getSignificant() ); } 
00271 
00273     inline Rotation_( const InverseRotation_<P>& );
00275     inline Rotation_& operator=( const InverseRotation_<P>& );
00276 
00278     const InverseRotation_<P>&  invert() const  { return *reinterpret_cast<const InverseRotation_<P>*>(this); }
00280     InverseRotation_<P>&        updInvert()     { return *reinterpret_cast<InverseRotation_<P>*>(this); }
00281 
00284 
00285     const InverseRotation_<P>&  transpose() const  { return invert(); }
00286     const InverseRotation_<P>&  operator~() const  { return invert(); }
00287     InverseRotation_<P>&        updTranspose()     { return updInvert(); }
00288     InverseRotation_<P>&        operator~()        { return updInvert(); }
00290 
00292 
00293     inline Rotation_&  operator*=( const Rotation_<P>& R );
00294     inline Rotation_&  operator/=( const Rotation_<P>& R );
00295     inline Rotation_&  operator*=( const InverseRotation_<P>& );
00296     inline Rotation_&  operator/=( const InverseRotation_<P>& );
00298 
00301 
00302     const Mat33P&  asMat33() const  { return *static_cast<const Mat33P*>(this); }
00303     Mat33P         toMat33() const  { return asMat33(); }
00305 
00307     typedef  UnitVec<P,Mat33P::RowSpacing>  ColType;
00308     typedef  UnitRow<P,Mat33P::ColSpacing>  RowType;
00309     const RowType&  row( int i ) const         { return reinterpret_cast<const RowType&>(asMat33()[i]); }
00310     const ColType&  col( int j ) const         { return reinterpret_cast<const ColType&>(asMat33()(j)); }
00311     const ColType&  x() const                  { return col(0); }
00312     const ColType&  y() const                  { return col(1); }
00313     const ColType&  z() const                  { return col(2); }
00314     const RowType&  operator[]( int i ) const  { return row(i); }
00315     const ColType&  operator()( int j ) const  { return col(j); }
00316 
00318 
00319     Rotation_&  setRotationFromMat33TrustMe( const Mat33P& m )  
00320     {   Mat33P& R = *this; R=m;  return *this; }   
00321     Rotation_&  setRotationColFromUnitVecTrustMe( int colj, const UnitVec3P& uvecj )  
00322     {   Mat33P& R = *this; R(colj)=uvecj.asVec3(); return *this; }   
00323     Rotation_&  setRotationFromUnitVecsTrustMe( const UnitVec3P& colA, const UnitVec3P& colB, const UnitVec3P& colC )  
00324     {   Mat33P& R = *this; R(0)=colA.asVec3(); R(1)=colB.asVec3(); R(2)=colC.asVec3(); return *this; }  
00326 
00327 
00328 //--------------------------------- PAUL CONTINUE FROM HERE ----------------------------------
00329 public:
00330 //--------------------------------------------------------------------------------------------
00336     static Vec3P convertAngVelToBodyFixed321Dot(const Vec3P& q, const Vec3P& w_PB_B) {
00337         const RealP s1 = std::sin(q[1]), c1 = std::cos(q[1]);
00338         const RealP s2 = std::sin(q[2]), c2 = std::cos(q[2]);
00339         const RealP ooc1 = RealP(1)/c1;
00340         const RealP s2oc1 = s2*ooc1, c2oc1 = c2*ooc1;
00341 
00342         const Mat33P E( 0,    s2oc1  ,  c2oc1  ,
00343                         0,      c2   ,   -s2   ,
00344                         1,  s1*s2oc1 , s1*c2oc1 );
00345         return E * w_PB_B;
00346     }
00347 
00350     static Vec3P convertBodyFixed321DotToAngVel(const Vec3P& q, const Vec3P& qd) {
00351         const RealP s1 = std::sin(q[1]), c1 = std::cos(q[1]);
00352         const RealP s2 = std::sin(q[2]), c2 = std::cos(q[2]);
00353 
00354         const Mat33P Einv(  -s1  ,  0  ,  1 ,
00355                            c1*s2 ,  c2 ,  0 ,
00356                            c1*c2 , -s2 ,  0 );
00357         return Einv*qd;
00358     }
00359 
00360     // TODO: sherm: is this right? Warning: everything is measured in the
00361     // *PARENT* frame, but has to be expressed in the *BODY* frame.
00362     static Vec3P convertAngVelDotToBodyFixed321DotDot
00363         (const Vec3P& q, const Vec3P& w_PB_B, const Vec3P& wdot)
00364     {
00365         const RealP s1 = std::sin(q[1]), c1 = std::cos(q[1]);
00366         const RealP s2 = std::sin(q[2]), c2 = std::cos(q[2]);
00367         const RealP ooc1  = 1/c1;
00368         const RealP s2oc1 = s2*ooc1, c2oc1 = c2*ooc1;
00369 
00370         const Mat33P E( 0 ,   s2oc1  ,  c2oc1  ,
00371                        0 ,     c2   ,   -s2   ,
00372                        1 , s1*s2oc1 , s1*c2oc1 );
00373         const Vec3P qdot = E * w_PB_B;
00374 
00375         const RealP t =  qdot[1]*qdot[2]*s1*ooc1;
00376         const RealP a =  t*c2oc1; // d/dt s2oc1
00377         const RealP b = -t*s2oc1; // d/dt c2oc1
00378 
00379         const Mat33P Edot( 0 ,       a           ,         b         ,
00380                           0 ,   -qdot[2]*s2     ,    -qdot[2]*c2    ,
00381                           0 , s1*a + qdot[1]*s2 , s1*b + qdot[1]*c2 );
00382 
00383         return E*wdot + Edot*w_PB_B;
00384     }
00385     
00394     static Mat33P calcNForBodyXYZInBodyFrame(const Vec3P& q) {
00395         // Note: q[0] is not referenced so we won't waste time calculating
00396         // its cosine and sine here.
00397         return calcNForBodyXYZInBodyFrame(Vec3P(0,std::cos(q[1]),std::cos(q[2])),
00398                                           Vec3P(0,std::sin(q[1]),std::sin(q[2])));
00399     }
00400 
00406     static Mat33P calcNForBodyXYZInBodyFrame(const Vec3P& cq, const Vec3P& sq) {
00407         const RealP s1 = sq[1], c1 = cq[1];
00408         const RealP s2 = sq[2], c2 = cq[2];
00409         const RealP ooc1  = 1/c1;
00410         const RealP s2oc1 = s2*ooc1, c2oc1 = c2*ooc1;
00411 
00412         return Mat33P(    c2oc1  , -s2oc1  , 0,
00413                             s2   ,    c2   , 0,
00414                        -s1*c2oc1 , s1*s2oc1, 1 );
00415     }
00416 
00426     static Mat33P calcNDotForBodyXYZInBodyFrame(const Vec3P& q, const Vec3P& qdot) {
00427         // Note: q[0] is not referenced so we won't waste time calculating
00428         // its cosine and sine here.
00429         return calcNDotForBodyXYZInBodyFrame(Vec3P(0,std::cos(q[1]),std::cos(q[2])),
00430                                              Vec3P(0,std::sin(q[1]),std::sin(q[2])),
00431                                              qdot);
00432     }
00433 
00439     static Mat33P calcNDotForBodyXYZInBodyFrame(const Vec3P& cq, const Vec3P& sq, 
00440                                                 const Vec3P& qdot) 
00441     {
00442         const RealP s1 = sq[1], c1 = cq[1];
00443         const RealP s2 = sq[2], c2 = cq[2];
00444         const RealP ooc1  = 1/c1;
00445         const RealP s2oc1 = s2*ooc1, c2oc1 = c2*ooc1;
00446 
00447         const RealP t =  qdot[1]*qdot[2]*s1*ooc1;
00448         const RealP a =  t*c2oc1; // d/dt s2oc1
00449         const RealP b = -t*s2oc1; // d/dt c2oc1
00450 
00451         return Mat33P(       b           ,        -a         , 0,
00452                           qdot[2]*c2     ,    -qdot[2]*s2    , 0,
00453                       -s1*b - qdot[1]*c2 , s1*a + qdot[1]*s2 , 0 );
00454     }
00455 
00462     static Mat33P calcNInvForBodyXYZInBodyFrame(const Vec3P& q) {
00463         // Note: q[0] is not referenced so we won't waste time calculating
00464         // its cosine and sine here.
00465         return calcNInvForBodyXYZInBodyFrame(Vec3P(0,std::cos(q[1]),std::cos(q[2])),
00466                                              Vec3P(0,std::sin(q[1]),std::sin(q[2])));
00467     }
00468 
00474     static Mat33P calcNInvForBodyXYZInBodyFrame(const Vec3P& cq, const Vec3P& sq) 
00475     {
00476         const RealP s1 = sq[1], c1 = cq[1];
00477         const RealP s2 = sq[2], c2 = cq[2];
00478 
00479         return Mat33P( c1*c2 ,  s2 , 0 ,
00480                       -c1*s2 ,  c2 , 0 ,
00481                         s1   ,  0  , 1 );
00482     }
00483 
00492     static Vec3P convertAngVelInBodyFrameToBodyXYZDot(const Vec3P& q, const Vec3P& w_PB_B)
00493     {   return convertAngVelInBodyFrameToBodyXYZDot(Vec3P(0,std::cos(q[1]),std::cos(q[2])),
00494                                                     Vec3P(0,std::sin(q[1]),std::sin(q[2])),
00495                                                     w_PB_B); }
00496 
00502     static Vec3P convertAngVelInBodyFrameToBodyXYZDot
00503        (const Vec3P& cq, const Vec3P& sq, const Vec3P& w_PB_B) 
00504     {   return calcNForBodyXYZInBodyFrame(cq,sq)*w_PB_B; }
00505 
00511     static Vec3P convertBodyXYZDotToAngVelInBodyFrame(const Vec3P& q, const Vec3P& qdot)
00512     {   return convertBodyXYZDotToAngVelInBodyFrame(Vec3P(0,std::cos(q[1]),std::cos(q[2])),
00513                                                     Vec3P(0,std::sin(q[1]),std::sin(q[2])),
00514                                                     qdot); }
00515 
00521     static Vec3P convertBodyXYZDotToAngVelInBodyFrame
00522        (const Vec3P& cq, const Vec3P& sq, const Vec3P& qdot) 
00523     {   return calcNInvForBodyXYZInBodyFrame(cq,sq)*qdot; }
00524 
00530     static Vec3P convertAngVelDotInBodyFrameToBodyXYZDotDot
00531         (const Vec3P& q, const Vec3P& w_PB_B, const Vec3P& wdot_PB_B)
00532     {
00533         // Note: q[0] is not referenced so we won't waste time calculating
00534         // its cosine and sine here.
00535         return convertAngVelDotInBodyFrameToBodyXYZDotDot
00536                    (Vec3P(0,std::cos(q[1]),std::cos(q[2])),
00537                     Vec3P(0,std::sin(q[1]),std::sin(q[2])),
00538                     w_PB_B, wdot_PB_B);
00539     }
00540 
00546     static Vec3P convertAngVelDotInBodyFrameToBodyXYZDotDot
00547        (const Vec3P& cq, const Vec3P& sq, const Vec3P& w_PB_B, const Vec3P& wdot_PB_B)
00548     {
00549         const Mat33P N      = calcNForBodyXYZInBodyFrame(cq,sq);
00550         const Vec3P  qdot   = N * w_PB_B; // 15 flops
00551         const Mat33P NDot   = calcNDotForBodyXYZInBodyFrame(cq,sq,qdot);
00552 
00553         return N*wdot_PB_B + NDot*w_PB_B; // 33 flops
00554     }
00555 
00561     static Mat<4,3,P> calcUnnormalizedNForQuaternion(const Vec4P& q) {
00562         const Vec4P e = q/2;
00563         const RealP ne1 = -e[1], ne2 = -e[2], ne3 = -e[3];
00564         return Mat<4,3,P>( ne1,  ne2,  ne3,
00565                            e[0], e[3], ne2,
00566                            ne3,  e[0], e[1],
00567                            e[2], ne1,  e[0]);
00568     }
00569 
00576     static Mat<4,3,P> calcUnnormalizedNDotForQuaternion(const Vec4P& qdot) {
00577         const Vec4P ed = qdot/2;
00578         const RealP ned1 = -ed[1], ned2 = -ed[2], ned3 = -ed[3];
00579         return Mat<4,3,P>( ned1,  ned2,  ned3,
00580                            ed[0], ed[3], ned2,
00581                            ned3,  ed[0], ed[1],
00582                            ed[2], ned1,  ed[0]);
00583     }
00584 
00593     static Mat<3,4,P> calcUnnormalizedNInvForQuaternion(const Vec4P& q) {
00594         const Vec4P e = 2*q;
00595         const RealP ne1 = -e[1], ne2 = -e[2], ne3 = -e[3];
00596         return Mat<3,4,P>(ne1, e[0], ne3,  e[2],
00597                           ne2, e[3], e[0], ne1,
00598                           ne3, ne2,  e[1], e[0]);
00599     }
00600 
00601 
00606     static Vec4P convertAngVelToQuaternionDot(const Vec4P& q, const Vec3P& w_PB_P) {
00607         return calcUnnormalizedNForQuaternion(q)*w_PB_P;
00608     }
00609 
00613     static Vec3P convertQuaternionDotToAngVel(const Vec4P& q, const Vec4P& qdot) {
00614         return calcUnnormalizedNInvForQuaternion(q)*qdot;
00615     }
00616 
00622     static Vec4P convertAngVelDotToQuaternionDotDot
00623        (const Vec4P& q, const Vec3P& w_PB_P, const Vec3P& wdot_PB_P)
00624     {
00625         const Mat<4,3,P> N    = calcUnnormalizedNForQuaternion(q);
00626         const Vec4P      qdot = N*w_PB_P;   // 20 flops
00627         const Mat<4,3,P> NDot = calcUnnormalizedNDotForQuaternion(qdot);
00628 
00629         return  N*wdot_PB_P + NDot*w_PB_P;  // 44 flops
00630     }
00631 
00632 
00633 private:
00634     // This is only for the most trustworthy of callers, that is, methods of 
00635     // the Rotation_ class.  There are a lot of ways for this NOT to be a 
00636     // legitimate rotation matrix -- be careful!!
00637     // Note that these are supplied in rows.
00638     Rotation_( const RealP& xx, const RealP& xy, const RealP& xz,
00639                const RealP& yx, const RealP& yy, const RealP& yz,
00640                const RealP& zx, const RealP& zy, const RealP& zz )
00641     :   Mat33P( xx,xy,xz, yx,yy,yz, zx,zy,zz ) {}
00642 
00643     // These next methods are highly-efficient power-user methods. Read the 
00644     // code to understand them.
00645     SimTK_SimTKCOMMON_EXPORT Rotation_&  setTwoAngleTwoAxesBodyFixedForwardCyclicalRotation(     RealP cosAngle1, RealP sinAngle1, const CoordinateAxis& axis1, RealP cosAngle2, RealP sinAngle2, const CoordinateAxis& axis2 );
00646     SimTK_SimTKCOMMON_EXPORT Rotation_&  setThreeAngleTwoAxesBodyFixedForwardCyclicalRotation(   RealP cosAngle1, RealP sinAngle1, const CoordinateAxis& axis1, RealP cosAngle2, RealP sinAngle2, const CoordinateAxis& axis2, RealP cosAngle3, RealP sinAngle3 );
00647     SimTK_SimTKCOMMON_EXPORT Rotation_&  setThreeAngleThreeAxesBodyFixedForwardCyclicalRotation( RealP cosAngle1, RealP sinAngle1, const CoordinateAxis& axis1, RealP cosAngle2, RealP sinAngle2, const CoordinateAxis& axis2, RealP cosAngle3, RealP sinAngle3, const CoordinateAxis& axis3 );
00648 
00649     // These next methods are highly-efficient power-user methods to convert 
00650     // Rotation matrices to orientation angles.  Read the code to understand them.
00651     SimTK_SimTKCOMMON_EXPORT Vec2P  convertTwoAxesBodyFixedRotationToTwoAngles(     const CoordinateAxis& axis1, const CoordinateAxis& axis2 ) const;
00652     SimTK_SimTKCOMMON_EXPORT Vec3P  convertTwoAxesBodyFixedRotationToThreeAngles(   const CoordinateAxis& axis1, const CoordinateAxis& axis2 ) const;
00653     SimTK_SimTKCOMMON_EXPORT Vec3P  convertThreeAxesBodyFixedRotationToThreeAngles( const CoordinateAxis& axis1, const CoordinateAxis& axis2, const CoordinateAxis& axis3 ) const;
00654 
00655 //------------------------------------------------------------------------------
00656 // These are obsolete names from a previous release, listed here so that 
00657 // users will get a decipherable compilation error. (sherm 091101)
00658 //------------------------------------------------------------------------------
00659 private:
00660     // REPLACED BY: calcNForBodyXYZInBodyFrame()
00661     static Mat33P calcQBlockForBodyXYZInBodyFrame(const Vec3P& a)
00662     {   return calcNForBodyXYZInBodyFrame(a); }
00663     // REPLACED BY: calcNInvForBodyXYZInBodyFrame()
00664     static Mat33P calcQInvBlockForBodyXYZInBodyFrame(const Vec3P& a)
00665     {   return calcNInvForBodyXYZInBodyFrame(a); }
00666     // REPLACED BY: calcUnnormalizedNForQuaternion()
00667     static Mat<4,3,P> calcUnnormalizedQBlockForQuaternion(const Vec4P& q)
00668     {   return calcUnnormalizedNForQuaternion(q); }
00669     // REPLACED BY: calcUnnormalizedNInvForQuaternion()
00670     static Mat<3,4,P> calcUnnormalizedQInvBlockForQuaternion(const Vec4P& q)
00671     {   return calcUnnormalizedNInvForQuaternion(q); }
00672     // REPLACED BY: convertAngVelInBodyFrameToBodyXYZDot
00673     static Vec3P convertAngVelToBodyFixed123Dot(const Vec3P& q, const Vec3P& w_PB_B) 
00674     {   return convertAngVelInBodyFrameToBodyXYZDot(q,w_PB_B); }
00675     // REPLACED BY: convertBodyXYZDotToAngVelInBodyFrame
00676     static Vec3P convertBodyFixed123DotToAngVel(const Vec3P& q, const Vec3P& qdot) 
00677     {   return convertBodyXYZDotToAngVelInBodyFrame(q,qdot); }
00678     // REPLACED BY: convertAngVelDotInBodyFrameToBodyXYZDotDot
00679     static Vec3P convertAngVelDotToBodyFixed123DotDot
00680         (const Vec3P& q, const Vec3P& w_PB_B, const Vec3P& wdot_PB_B)
00681     {   return convertAngVelDotInBodyFrameToBodyXYZDotDot(q,w_PB_B,wdot_PB_B); }
00682 
00683 //------------------------------------------------------------------------------
00684 // The following code is obsolete - it is here temporarily for backward 
00685 // compatibility (Mitiguy 9/5/2007)
00686 //------------------------------------------------------------------------------
00687 private:
00688     // These static methods are like constructors with friendlier names.
00689     static Rotation_ zero() { return Rotation_(); }
00690     static Rotation_ NaN()  { Rotation_ r;  r.setRotationToNaN();  return r; }
00691 
00693     Rotation_&  setToZero()            { return setRotationToIdentityMatrix(); }
00694     Rotation_&  setToIdentityMatrix()  { return setRotationToIdentityMatrix(); }
00695     Rotation_&  setToNaN()             { return setRotationToNaN(); }
00696     static Rotation_  trustMe( const Mat33P& m )  { return Rotation_(m,true); }
00697 
00698     // One-angle rotations.
00699     static Rotation_ aboutX( const RealP& angleInRad ) { return Rotation_( angleInRad, XAxis ); }
00700     static Rotation_ aboutY( const RealP& angleInRad ) { return Rotation_( angleInRad, YAxis ); }
00701     static Rotation_ aboutZ( const RealP& angleInRad ) { return Rotation_( angleInRad, ZAxis ); }
00702     static Rotation_ aboutAxis( const RealP& angleInRad, const UnitVec3P& axis ) { return Rotation_(angleInRad,axis); }
00703     static Rotation_ aboutAxis( const RealP& angleInRad, const Vec3P& axis )     { return Rotation_(angleInRad,axis); }
00704     void  setToRotationAboutZ( const RealP& q ) { setRotationFromAngleAboutZ( q ); }
00705 
00706     // Two-angle space-fixed rotations.
00707     static Rotation_ aboutXThenOldY(const RealP& xInRad, const RealP& yInRad) { return Rotation_( SpaceRotationSequence, xInRad, XAxis, yInRad, YAxis ); }
00708     static Rotation_ aboutYThenOldX(const RealP& yInRad, const RealP& xInRad) { return Rotation_( SpaceRotationSequence, yInRad, YAxis, xInRad, XAxis ); }
00709     static Rotation_ aboutXThenOldZ(const RealP& xInRad, const RealP& zInRad) { return Rotation_( SpaceRotationSequence, xInRad, XAxis, zInRad, ZAxis ); }
00710     static Rotation_ aboutZThenOldX(const RealP& zInRad, const RealP& xInRad) { return Rotation_( SpaceRotationSequence, zInRad, ZAxis, xInRad, XAxis ); }
00711     static Rotation_ aboutYThenOldZ(const RealP& yInRad, const RealP& zInRad) { return Rotation_( SpaceRotationSequence, yInRad, YAxis, zInRad, ZAxis ); }
00712     static Rotation_ aboutZThenOldY(const RealP& zInRad, const RealP& yInRad) { return Rotation_( SpaceRotationSequence, zInRad, ZAxis, yInRad, YAxis ); }
00713 
00714     // Two-angle body fixed rotations (reversed space-fixed ones).
00715     static Rotation_ aboutXThenNewY(const RealP& xInRad, const RealP& yInRad) { return Rotation_( BodyRotationSequence, xInRad, XAxis, yInRad, YAxis ); }
00716     static Rotation_ aboutYThenNewX(const RealP& yInRad, const RealP& xInRad) { return aboutXThenOldY(xInRad, yInRad); }
00717     static Rotation_ aboutXThenNewZ(const RealP& xInRad, const RealP& zInRad) { return aboutZThenOldX(zInRad, xInRad); }
00718     static Rotation_ aboutZThenNewX(const RealP& zInRad, const RealP& xInRad) { return aboutXThenOldZ(xInRad, zInRad); }
00719     static Rotation_ aboutYThenNewZ(const RealP& yInRad, const RealP& zInRad) { return aboutZThenOldY(zInRad, yInRad); }
00720     static Rotation_ aboutZThenNewY(const RealP& zInRad, const RealP& yInRad) { return aboutYThenOldZ(yInRad, zInRad); }
00721 
00724     explicit Rotation_( const UnitVec3P& uvecZ )  { setRotationFromOneAxis(uvecZ,ZAxis); }
00725 
00727     //  We will take x seriously after normalizing, but use the y only to create z = normalize(x X y), 
00728     //  then y = z X x. Bad things happen if x and y are aligned but we may not catch it.
00729     Rotation_( const Vec3P& x, const Vec3P& yish )  { setRotationFromTwoAxes( UnitVec3P(x), XAxis, yish, YAxis ); }
00730 
00732     void setToQuaternion( const QuaternionP& q )  { setRotationFromQuaternion(q); }
00733 
00738     //  Similarly for BodyFixed123.
00739     void setToBodyFixed321( const Vec3P& v)  { setRotationFromThreeAnglesThreeAxes( BodyRotationSequence, v[0], ZAxis, v[1], YAxis, v[2], XAxis ); }
00740     void setToBodyFixed123( const Vec3P& v)  { setRotationToBodyFixedXYZ(v); }
00741 
00744     Vec4P convertToAngleAxis() const  { return convertRotationToAngleAxis(); }
00745 
00747     QuaternionP convertToQuaternion() const  { return convertRotationToQuaternion(); }
00748 
00751     void setToSpaceFixed12( const Vec2P& q ) { setRotationFromTwoAnglesTwoAxes( SpaceRotationSequence, q[0], XAxis, q[1], YAxis ); }
00752 
00756     Vec3P  convertToBodyFixed123() const  { return convertRotationToBodyFixedXYZ(); }
00757     Vec2P  convertToBodyFixed12() const   { return convertRotationToBodyFixedXY(); }
00758     Vec2P  convertToSpaceFixed12() const  { return convertTwoAxesRotationToTwoAngles( SpaceRotationSequence, XAxis, YAxis ); }
00759 };
00760 
00761 
00766 template <class P>
00767 class InverseRotation_ : public Mat<3,3,P>::TransposeType {
00768     typedef P               RealP;
00769     typedef Rotation_<P>    RotationP;
00770     typedef Mat<3,3,P>      Mat33P; // not the base type!
00771     typedef SymMat<3,P>     SymMat33P;
00772     typedef Mat<2,2,P>      Mat22P;
00773     typedef Mat<3,2,P>      Mat32P;
00774     typedef Vec<2,P>        Vec2P;
00775     typedef Vec<3,P>        Vec3P;
00776     typedef Vec<4,P>        Vec4P;
00777     typedef Quaternion_<P>  QuaternionP;
00778 public:
00781     typedef typename Mat<3,3,P>::TransposeType  BaseMat;
00782 
00785 
00786 
00787     typedef  UnitVec<P,BaseMat::RowSpacing>  ColType;
00789     typedef  UnitRow<P,BaseMat::ColSpacing>  RowType;
00791 
00795     InverseRotation_() : BaseMat(1) {}
00796 
00798     InverseRotation_( const InverseRotation_& R ) : BaseMat(R) {}
00800     InverseRotation_&  operator=( const InverseRotation_& R )  
00801     {   BaseMat::operator=(R.asMat33());  return *this; }
00802 
00809     SimTK_SimTKCOMMON_EXPORT SymMat33P reexpressSymMat33(const SymMat33P& S_BB) const;
00810 
00812 
00813     const RotationP&  invert() const {return *reinterpret_cast<const RotationP*>(this);}
00814     RotationP&        updInvert() {return *reinterpret_cast<RotationP*>(this);}
00816 
00819 
00820     const RotationP&  transpose() const  { return invert(); }
00821     const RotationP&  operator~() const  { return invert(); }
00822     RotationP&        updTranspose()     { return updInvert(); }
00823     RotationP&        operator~()        { return updInvert(); }
00825 
00831 
00832     const RowType&  row( int i ) const         { return reinterpret_cast<const RowType&>(asMat33()[i]); }
00833     const ColType&  col( int j ) const         { return reinterpret_cast<const ColType&>(asMat33()(j)); }
00834     const ColType&  x() const                  { return col(0); }
00835     const ColType&  y() const                  { return col(1); }
00836     const ColType&  z() const                  { return col(2); }
00837     const RowType&  operator[]( int i ) const  { return row(i); }
00838     const ColType&  operator()( int j ) const  { return col(j); }
00840 
00843 
00844     const BaseMat&  asMat33() const  { return *static_cast<const BaseMat*>(this); }
00845     BaseMat         toMat33() const  { return asMat33(); }
00847 };
00848 
00850 template <class P> SimTK_SimTKCOMMON_EXPORT std::ostream& 
00851 operator<<(std::ostream&, const Rotation_<P>&);
00853 template <class P> SimTK_SimTKCOMMON_EXPORT std::ostream& 
00854 operator<<(std::ostream&, const InverseRotation_<P>&);
00855 
00859 
00860 template <class P, int S> inline UnitVec<P,1>  
00861 operator*(const Rotation_<P>& R, const UnitVec<P,S>& v)        {return UnitVec<P,1>(R.asMat33()* v.asVec3(),  true);}
00862 template <class P, int S> inline UnitRow<P,1>  
00863 operator*(const UnitRow<P,S>& r, const Rotation_<P>& R)        {return UnitRow<P,1>(r.asRow3() * R.asMat33(), true);}
00864 template <class P, int S> inline UnitVec<P,1>  
00865 operator*(const InverseRotation_<P>& R, const UnitVec<P,S>& v) {return UnitVec<P,1>(R.asMat33()* v.asVec3(),  true);}
00866 template <class P, int S> inline UnitRow<P,1>  
00867 operator*(const UnitRow<P,S>& r, const InverseRotation_<P>& R) {return UnitRow<P,1>(r.asRow3() * R.asMat33(), true);}
00869 
00870 // Couldn't implement these Rotation_ methods until InverseRotation_ was defined.
00871 template <class P> inline
00872 Rotation_<P>::Rotation_(const InverseRotation_<P>& R) : Mat<3,3,P>( R.asMat33() ) {}
00873 template <class P> inline Rotation_<P>&  
00874 Rotation_<P>::operator=(const InverseRotation_<P>& R)  {static_cast<Mat<3,3,P>&>(*this)  = R.asMat33();    return *this;}
00875 template <class P> inline Rotation_<P>&  
00876 Rotation_<P>::operator*=(const Rotation_<P>& R)        {static_cast<Mat<3,3,P>&>(*this) *= R.asMat33();    return *this;}
00877 template <class P> inline Rotation_<P>&  
00878 Rotation_<P>::operator/=(const Rotation_<P>& R)        {static_cast<Mat<3,3,P>&>(*this) *= (~R).asMat33(); return *this;}
00879 template <class P> inline Rotation_<P>&  
00880 Rotation_<P>::operator*=(const InverseRotation_<P>& R) {static_cast<Mat<3,3,P>&>(*this) *= R.asMat33();    return *this;}
00881 template <class P> inline Rotation_<P>&  
00882 Rotation_<P>::operator/=(const InverseRotation_<P>& R) {static_cast<Mat<3,3,P>&>(*this) *= (~R).asMat33(); return *this;}
00883 
00885 
00886 template <class P> inline Rotation_<P>
00887 operator*(const Rotation_<P>&        R1, const Rotation_<P>&        R2)  {return Rotation_<P>(R1) *= R2;}
00888 template <class P> inline Rotation_<P>
00889 operator*(const Rotation_<P>&        R1, const InverseRotation_<P>& R2)  {return Rotation_<P>(R1) *= R2;}
00890 template <class P> inline Rotation_<P>
00891 operator*(const InverseRotation_<P>& R1, const Rotation_<P>&        R2)  {return Rotation_<P>(R1) *= R2;}
00892 template <class P> inline Rotation_<P>
00893 operator*(const InverseRotation_<P>& R1, const InverseRotation_<P>& R2)  {return Rotation_<P>(R1) *= R2;}
00895 
00898 
00899 template <class P> inline Rotation_<P>
00900 operator/( const Rotation_<P>&        R1, const Rotation_<P>&        R2 )  {return Rotation_<P>(R1) /= R2;}
00901 template <class P> inline Rotation_<P>
00902 operator/( const Rotation_<P>&        R1, const InverseRotation&     R2 )  {return Rotation_<P>(R1) /= R2;}
00903 template <class P> inline Rotation_<P>
00904 operator/( const InverseRotation_<P>& R1, const Rotation_<P>&        R2 )  {return Rotation_<P>(R1) /= R2;}
00905 template <class P> inline Rotation_<P>
00906 operator/( const InverseRotation_<P>& R1, const InverseRotation_<P>& R2 )  {return Rotation_<P>(R1) /= R2;}
00908 
00909 
00910 //------------------------------------------------------------------------------
00911 }  // End of namespace SimTK
00912 
00913 //--------------------------------------------------------------------------
00914 #endif // SIMTK_ROTATION_H_
00915 //--------------------------------------------------------------------------
00916 
00917 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines