Simbody

Transform.h

Go to the documentation of this file.
00001 //-----------------------------------------------------------------------------
00002 // File:     Transform.h
00003 // Class:    Transform and InverseTransform 
00004 // Parent:   None:  Data contains Rotation (for orientation) and Vec3 (translation)
00005 // Purpose:  Transform (orientation and translation) relating two right-handed orthogonal bases
00006 //-----------------------------------------------------------------------------
00007 #ifndef SimTK_TRANSFORM_H 
00008 #define SimTK_TRANSFORM_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: Michael Sherman                                                   *
00020  * Contributors: Paul Mitiguy                                                 *
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 #include "SimTKcommon/SmallMatrix.h"
00043 #include "SimTKcommon/internal/BigMatrix.h"
00044 #include "SimTKcommon/internal/UnitVec.h"
00045 #include "SimTKcommon/internal/Quaternion.h"
00046 #include "SimTKcommon/internal/Rotation.h"
00047 //-----------------------------------------------------------------------------
00048 #include <iosfwd>  // Forward declaration of iostream
00049 //-----------------------------------------------------------------------------
00050 
00051 
00052 //-----------------------------------------------------------------------------
00053 namespace SimTK {
00054 
00055 //-----------------------------------------------------------------------------
00056 // Forward declarations (everything is templatized by precision).
00057 template <class P> class Transform_;
00058 template <class P> class InverseTransform_;
00059 
00060 typedef Transform_<Real>    Transform;
00061 typedef Transform_<float>   fTransform;
00062 typedef Transform_<double>  dTransform;
00063 
00064 
00065 //-----------------------------------------------------------------------------
00120 //-----------------------------------------------------------------------------
00121 template <class P>
00122 class Transform_ {
00123 public:
00125     Transform_() : R_BF(),  p_BF(0) { }
00126 
00128     Transform_( const Rotation_<P>& R, const Vec<3,P>& p ) : R_BF(R), p_BF(p) { }
00129 
00132     Transform_( const Rotation_<P>& R ) : R_BF(R), p_BF(0) { }
00133 
00136     Transform_( const Vec<3,P>& p ) : R_BF(),  p_BF(p) { }
00137 
00138     // default copy, assignment, destructor
00139 
00147     // (Definition is below after InverseTransform is declared.)
00148     inline Transform_&  operator=( const InverseTransform_<P>& X );
00149 
00153     Transform_&  set( const Rotation_<P>& R, const Vec<3,P>& p ) { p_BF=p; R_BF=R; return *this; }
00154 
00158     Transform_&  setToZero()  { R_BF.setRotationToIdentityMatrix();  p_BF = P(0);  return *this; }
00159 
00164     Transform_&  setToNaN()  { R_BF.setRotationToNaN();  p_BF.setToNaN();  return *this; }
00165 
00168     const InverseTransform_<P>&  invert() const  { return *reinterpret_cast<const InverseTransform_<P>*>(this); }
00169 
00172     InverseTransform_<P>&  updInvert()  { return *reinterpret_cast<InverseTransform_<P>*>(this); }
00173 
00175     const InverseTransform_<P>&  operator~() const  {return invert();}
00176 
00178     InverseTransform_<P>&        operator~()        {return updInvert();}
00179 
00182     Transform_ compose(const Transform_& X_FY) const {
00183         return Transform_( R_BF * X_FY.R(),  p_BF + R_BF * X_FY.p() );
00184     }
00185 
00191     // (Definition is below after InverseTransform_ is declared.)
00192     inline Transform_  compose( const InverseTransform_<P>& X_FY ) const;
00193 
00197     Vec<3,P>  xformFrameVecToBase( const Vec<3,P>& vF ) const {return R_BF*vF;}
00198 
00202     Vec<3,P>  xformBaseVecToFrame( const Vec<3,P>& vB ) const  { return ~R_BF*vB; }
00203 
00207     Vec<3,P>  shiftFrameStationToBase( const Vec<3,P>& sF ) const 
00208     {   return p_BF + xformFrameVecToBase(sF); }
00209 
00213     Vec<3,P>  shiftBaseStationToFrame( const Vec<3,P>& sB ) const 
00214     {   return xformBaseVecToFrame(sB - p_BF); }
00215 
00217     const Rotation_<P>&  R() const  { return R_BF; }
00218 
00220     Rotation_<P>&  updR()           { return R_BF; }
00221 
00224     const typename Rotation_<P>::ColType&  x() const  { return R().x(); }
00227     const typename Rotation_<P>::ColType&  y() const  { return R().y(); }
00230     const typename Rotation_<P>::ColType&  z() const  { return R().z(); }
00231 
00234     const InverseRotation_<P>&  RInv() const  { return ~R_BF; }
00235 
00238     InverseRotation_<P>&  updRInv()  { return ~R_BF; }
00239 
00241     const Vec<3,P>&  p() const  { return p_BF; }
00242 
00245     Vec<3,P>&  updP()  { return p_BF; }
00246 
00251     Transform_<P>&  setP( const Vec<3,P>& p )  { p_BF=p; return *this; }
00252 
00256     Vec<3,P>  pInv() const  { return -(~R_BF*p_BF); }
00257 
00265     Transform_<P>&  setPInv( const Vec<3,P>& p_FB )  { p_BF = -(R_BF*p_FB); return *this; }
00266 
00270     const Mat<3,4,P>&  asMat34() const  { return Mat<3,4,P>::getAs(reinterpret_cast<const P*>(this)); }
00271 
00273     Mat<3,4,P>  toMat34() const  { return asMat34(); }
00274 
00276     Mat<4,4,P> toMat44() const {
00277         Mat<4,4,P> tmp;
00278         tmp.template updSubMat<3,4>(0,0) = asMat34();
00279         tmp[3]                  = Row<4,P>(0,0,0,1);
00280         return tmp;
00281     }
00282 
00283     // OBSOLETE -- alternate name for p
00284     const Vec<3,P>& T() const {return p();}
00285     Vec<3,P>&  updT()  {return updP();}
00286 
00287 private:
00288     //TODO: these might not pack correctly; should use an array of 12 Reals.
00289     Rotation_<P> R_BF;   // rotation matrix that expresses F's axes in R
00290     Vec<3,P>     p_BF;   // location of F's origin measured from B's origin, expressed in B 
00291 };
00292 
00293 
00294 //-----------------------------------------------------------------------------
00306 //-----------------------------------------------------------------------------
00307 template <class P>
00308 class InverseTransform_ {
00309 public:
00311     InverseTransform_() : R_FB(), p_FB(0) { }
00312 
00313     // default copy, assignment, destructor
00314 
00316     operator Transform_<P>() const  { return Transform_<P>( R(), p() ); }
00317 
00318     // Assignment from Transform. This means that the inverse
00319     // transform we're assigning to must end up with the same meaning
00320     // as the inverse transform X has, so we'll need:
00321     //          p* == X.pInv()
00322     //          R* == X.RInv()
00323     // Cost: one frame conversion and a negation for pInv, 18 flops.
00324     InverseTransform_&  operator=( const Transform_<P>& X ) {
00325         // Be careful to do this in the right order in case X and this
00326         // are the same object, i.e. ~X = X which is weird but has
00327         // the same meaning as X = ~X, i.e. invert X in place.
00328         p_FB = X.pInv(); // This might change X.p ...
00329         R_FB = X.RInv(); // ... but this doesn't depend on X.p.
00330         return *this;
00331     }
00332 
00333     // Inverting one of these just recasts it back to a Transform_<P>.
00334     const Transform_<P>&  invert() const  { return *reinterpret_cast<const Transform_<P>*>(this); }
00335     Transform_<P>&  updInvert()           { return *reinterpret_cast<Transform_<P>*>(this); }
00336 
00337     // Overload transpose to mean inversion.
00338     const Transform_<P>&  operator~() const  { return invert(); }
00339     Transform_<P>&        operator~()        { return updInvert(); }
00340 
00341     // Return X_BY=X_BF*X_FY, where X_BF (this) is represented here as ~X_FB. This
00342     // costs exactly the same as a composition of two Transforms (63 flops).
00343     Transform_<P>  compose(const Transform_<P>& X_FY) const {
00344         return Transform_<P>( ~R_FB * X_FY.R(),  ~R_FB *(X_FY.p() - p_FB) );
00345     }
00346     // Return X_BY=X_BF*X_FY, but now both xforms are represented by their inverses.
00347     // This costs one extra vector transformation and a negation (18 flops) more
00348     // than a composition of two Transforms, for a total of 81 flops.
00349     Transform_<P>  compose(const InverseTransform_<P>& X_FY) const { 
00350         return Transform_<P>(  ~R_FB * X_FY.R(),  ~R_FB *(X_FY.p() - p_FB)  ); 
00351     }
00352 
00353     // Forward and inverse vector transformations cost the same here as
00354     // for a Transform_<P> (or for that matter, a Rotation_<P>): 15 flops.
00355     Vec<3,P>  xformFrameVecToBase(const Vec<3,P>& vF) const {return ~R_FB*vF;}
00356     Vec<3,P>  xformBaseVecToFrame(const Vec<3,P>& vB) const {return  R_FB*vB;}
00357 
00358     // Forward and inverse station shift & transform cost the same here as for a Transform_<P>: 18 flops.
00359     Vec<3,P>  shiftFrameStationToBase(const Vec<3,P>& sF) const  { return ~R_FB*(sF-p_FB); }
00360     Vec<3,P>  shiftBaseStationToFrame(const Vec<3,P>& sB) const  { return R_FB*sB + p_FB; }
00361     
00362     const InverseRotation_<P>&  R() const  {return ~R_FB;}
00363     InverseRotation_<P>&        updR()     {return ~R_FB;}
00364 
00365     const typename InverseRotation_<P>::ColType&  x() const  {return R().x();}
00366     const typename InverseRotation_<P>::ColType&  y() const  {return R().y();}
00367     const typename InverseRotation_<P>::ColType&  z() const  {return R().z();}
00368 
00369     const Rotation_<P>&  RInv() const  {return R_FB;}
00370     Rotation_<P>&        updRInv()     {return R_FB;}
00371 
00375     Vec<3,P>  p() const  { return -(~R_FB*p_FB); }
00376 
00377 
00378     // no updP lvalue
00379 
00380     // Sorry, can't update translation as an lvalue, but here we
00381     // want -(R_BF*p_FB)=p_BF => p_FB=-(R_FB*p_BF). Cost: 18 flops.
00382     void  setP( const Vec<3,P>& p_BF )  { p_FB = -(R_FB*p_BF); }
00383 
00384     // Inverse translation is free.
00385     const Vec<3,P>&  pInv() const              { return p_FB; }
00386     void         setPInv( const Vec<3,P>& p )  { p_FB = p; }
00387 
00390     Mat<3,4,P>  toMat34() const  { return Transform_<P>(*this).asMat34(); }
00391 
00393     Mat<4,4,P>  toMat44() const  { return Transform_<P>(*this).toMat44(); }
00394 
00395     // OBSOLETE -- alternate name for p.
00396     Vec<3,P> T() const {return p();}
00397 
00398 private:
00399     // DATA LAYOUT MUST BE IDENTICAL TO Transform_<P> !!
00400     // TODO: redo packing here when it is done for Transform_<P>.
00401     Rotation_<P> R_FB; // transpose of our rotation matrix, R_BF
00402     Vec<3,P>     p_FB; // our translation is -(R_BF*p_FB)=-(~R_FB*p_FB)
00403 };
00404 
00405 
00410 
00411 template <class P, int S> inline Vec<3,P>  
00412 operator*(const Transform_<P>& X_BF,        const Vec<3,P,S>& s_F)  {return X_BF.shiftFrameStationToBase(s_F);}
00413 template <class P, int S> inline Vec<3,P>  
00414 operator*(const InverseTransform_<P>& X_BF, const Vec<3,P,S>& s_F)  {return X_BF.shiftFrameStationToBase(s_F);}
00415 template <class P, int S> inline Vec<3,P>  
00416 operator*(const Transform_<P>& X_BF,        const Vec<3,negator<P>,S>& s_F)  {return X_BF*Vec<3,P>(s_F);}
00417 template <class P, int S> inline Vec<3,P>  
00418 operator*(const InverseTransform_<P>& X_BF, const Vec<3,negator<P>,S>& s_F)  {return X_BF*Vec<3,P>(s_F);}
00420 
00421 //-----------------------------------------------------------------------------
00426 
00427 template <class P, int S> inline Vec<4,P> 
00428 operator*(const Transform_<P>& X_BF, const Vec<4,P,S>& a_F) {
00429     assert(a_F[3]==0 || a_F[3]==1);
00430     const Vec<3,P,S>& v_F = Vec<3,P,S>::getAs(&a_F[0]); // recast the 1st 3 elements as Vec3
00431 
00432     Vec<4,P> out;
00433     if( a_F[3] == 0 ) { Vec<3,P>::updAs(&out[0]) = X_BF.xformFrameVecToBase(v_F);      out[3] = 0; } 
00434     else              { Vec<3,P>::updAs(&out[0]) = X_BF.shiftFrameStationToBase(v_F);  out[3] = 1; }
00435     return out;
00436 }
00437 
00438 template <class P, int S> inline Vec<4,P> 
00439 operator*(const InverseTransform_<P>& X_BF, const Vec<4,P,S>& a_F ) {
00440     assert(a_F[3]==0 || a_F[3]==1);
00441     const Vec<3,P,S>& v_F = Vec<3,P,S>::getAs(&a_F[0]); // recast the 1st 3 elements as Vec3
00442 
00443     Vec<4,P> out;
00444     if( a_F[3] == 0 ) { Vec<3,P>::updAs(&out[0]) = X_BF.xformFrameVecToBase(v_F);      out[3] = 0; } 
00445     else              { Vec<3,P>::updAs(&out[0]) = X_BF.shiftFrameStationToBase(v_F);  out[3] = 1; }
00446     return out;
00447 }
00448 template <class P, int S> inline Vec<4,P>  
00449 operator*(const Transform_<P>& X_BF,        const Vec<4,negator<P>,S>& s_F)  {return X_BF*Vec<4,P>(s_F);}
00450 template <class P, int S> inline Vec<4,P>  
00451 operator*(const InverseTransform_<P>& X_BF, const Vec<4,negator<P>,S>& s_F)  {return X_BF*Vec<4,P>(s_F);}
00453 //-----------------------------------------------------------------------------
00454 
00457 
00458 template <class P, class E> inline Vector_<E> 
00459 operator*(const Transform_<P>& X, const VectorBase<E>& v) {
00460     Vector_<E> result(v.size());
00461     for (int i = 0; i < v.size(); ++i)
00462         result[i] = X*v[i];
00463     return result;
00464 }
00465 template <class P, class E> inline Vector_<E> 
00466 operator*(const VectorBase<E>& v, const Transform_<P>& X) {
00467     Vector_<E> result(v.size());
00468     for (int i = 0; i < v.size(); ++i)
00469         result[i] = X*v[i];
00470     return result;
00471 }
00472 template <class P, class E> inline RowVector_<E> 
00473 operator*(const Transform_<P>& X, const RowVectorBase<E>& v) {
00474     RowVector_<E> result(v.size());
00475     for (int i = 0; i < v.size(); ++i)
00476         result[i] = X*v[i];
00477     return result;
00478 }
00479 template <class P, class E> inline RowVector_<E> 
00480 operator*(const RowVectorBase<E>& v, const Transform_<P>& X) {
00481     RowVector_<E> result(v.size());
00482     for (int i = 0; i < v.size(); ++i)
00483         result[i] = X*v[i];
00484     return result;
00485 }
00486 template <class P, class E> inline Matrix_<E> 
00487 operator*(const Transform_<P>& X, const MatrixBase<E>& v) {
00488     Matrix_<E> result(v.nrow(), v.ncol());
00489     for (int i = 0; i < v.nrow(); ++i)
00490         for (int j = 0; j < v.ncol(); ++j)
00491             result(i, j) = X*v(i, j);
00492     return result;
00493 }
00494 template <class P, class E> inline Matrix_<E> 
00495 operator*(const MatrixBase<E>& v, const Transform_<P>& X) {
00496     Matrix_<E> result(v.nrow(), v.ncol());
00497     for (int i = 0; i < v.nrow(); ++i)
00498         for (int j = 0; j < v.ncol(); ++j)
00499             result(i, j) = X*v(i, j);
00500     return result;
00501 }
00502 template <class P, int N, class E, int S> inline Vec<N,E> 
00503 operator*(const Transform_<P>& X, const Vec<N,E,S>& v) {
00504     Vec<N,E> result;
00505     for (int i = 0; i < N; ++i)
00506         result[i] = X*v[i];
00507     return result;
00508 }
00509 template <class P, int N, class E, int S> inline Vec<N,E> 
00510 operator*(const Vec<N,E,S>& v, const Transform_<P>& X) {
00511     Vec<N,E> result;
00512     for (int i = 0; i < N; ++i)
00513         result[i] = X*v[i];
00514     return result;
00515 }
00516 template <class P, int N, class E, int S> inline Row<N,E> 
00517 operator*(const Transform_<P>& X, const Row<N,E,S>& v) {
00518     Row<N,E> result;
00519     for (int i = 0; i < N; ++i)
00520         result[i] = X*v[i];
00521     return result;
00522 }
00523 template <class P, int N, class E, int S> inline Row<N,E> 
00524 operator*(const Row<N,E,S>& v, const Transform_<P>& X) {
00525     Row<N,E> result;
00526     for (int i = 0; i < N; ++i)
00527         result[i] = X*v[i];
00528     return result;
00529 }
00530 template <class P, int M, int N, class E, int CS, int RS> inline Mat<M,N,E> 
00531 operator*(const Transform_<P>& X, const Mat<M,N,E,CS,RS>& v) {
00532     Mat<M,N,E> result;
00533     for (int i = 0; i < M; ++i)
00534         for (int j = 0; j < N; ++j)
00535             result(i, j) = X*v(i, j);
00536     return result;
00537 }
00538 template <class P, int M, int N, class E, int CS, int RS> inline Mat<M,N,E> 
00539 operator*(const Mat<M,N,E,CS,RS>& v, const Transform_<P>& X) {
00540     Mat<M,N,E> result;
00541     for (int i = 0; i < M; ++i)
00542         for (int j = 0; j < N; ++j)
00543             result(i, j) = X*v(i, j);
00544     return result;
00545 }
00546 
00548 
00549 // These Transform definitions had to wait for InverseTransform to be declared.
00550 
00551 template <class P> inline Transform_<P>&
00552 Transform_<P>::operator=( const InverseTransform_<P>& X ) {
00553     // Be careful to do this in the right order in case X and this
00554     // are the same object, i.e. we're doing X = ~X, inverting X in place.
00555     p_BF = X.p(); // This might change X.p ...
00556     R_BF = X.R(); // ... but this doesn't depend on X.p.
00557     return *this;
00558 }
00559 
00560 template <class P> inline Transform_<P>
00561 Transform_<P>::compose( const InverseTransform_<P>& X_FY ) const {
00562     return Transform_<P>( R_BF * X_FY.R(), p_BF + R_BF * X_FY.p() );
00563 }
00564 
00567 
00568 template <class P> inline Transform_<P>
00569 operator*(const Transform_<P>& X1,        const Transform_<P>& X2)         {return X1.compose(X2);}
00570 template <class P> inline Transform_<P>
00571 operator*(const Transform_<P>& X1,        const InverseTransform_<P>& X2)  {return X1.compose(X2);}
00572 template <class P> inline Transform_<P>
00573 operator*(const InverseTransform_<P>& X1, const Transform_<P>& X2)         {return X1.compose(X2);}
00574 template <class P> inline Transform_<P>
00575 operator*(const InverseTransform_<P>& X1, const InverseTransform_<P>& X2)  {return X1.compose(X2);}
00577 
00580 
00581 template <class P> inline bool
00582 operator==(const Transform_<P>& X1,        const Transform_<P>& X2)         {return X1.R()==X2.R() && X1.p()==X2.p();}
00583 template <class P> inline bool
00584 operator==(const InverseTransform_<P>& X1, const InverseTransform_<P>& X2)  {return X1.R()==X2.R() && X1.p()==X2.p();}
00585 template <class P> inline bool
00586 operator==(const Transform_<P>& X1,        const InverseTransform_<P>& X2)  {return X1.R()==X2.R() && X1.p()==X2.p();}
00587 template <class P> inline bool
00588 operator==(const InverseTransform_<P>& X1, const Transform_<P>& X2)         {return X1.R()==X2.R() && X1.p()==X2.p();}
00590 
00592 template <class P> SimTK_SimTKCOMMON_EXPORT std::ostream&
00593 operator<<(std::ostream&, const Transform_<P>&);
00595 template <class P> SimTK_SimTKCOMMON_EXPORT std::ostream&
00596 operator<<(std::ostream&, const InverseTransform_<P>&);
00597 
00598 
00599 
00600 //------------------------------------------------------------------------------
00601 }  // End of namespace SimTK
00602 
00603 //--------------------------------------------------------------------------
00604 #endif // SimTK_TRANSFORM_H_
00605 //--------------------------------------------------------------------------
00606 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines