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-7 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
00057 class InverseTransform;
00058 
00059 
00060 //-----------------------------------------------------------------------------
00119 //-----------------------------------------------------------------------------
00120 class Transform {
00121 public:
00123     Transform() : R_BF(),  T_BF(0) { }
00124 
00126     Transform( const Rotation& R, const Vec3& T ) : R_BF(R), T_BF(T) { }
00127 
00130     Transform( const Rotation& R ) : R_BF(R), T_BF(0) { }
00131 
00134     Transform( const Vec3& T ) : R_BF(),  T_BF(T) { }
00135 
00136     // default copy, assignment, destructor
00137 
00145     // (Definition is below after InverseTransform is declared.)
00146     inline Transform&  operator=( const InverseTransform& X );
00147 
00151     Transform&  set( const Rotation& R, const Vec3& T ) { T_BF=T; R_BF=R; return *this; }
00152 
00156     Transform&  setToZero()  { R_BF.setRotationToIdentityMatrix();  T_BF = 0.;  return *this; }
00157 
00162     Transform&  setToNaN()  { R_BF.setRotationToNaN();  T_BF.setToNaN();  return *this; }
00163 
00166     const InverseTransform&  invert() const  { return *reinterpret_cast<const InverseTransform*>(this); }
00167 
00170     InverseTransform&  updInvert()  { return *reinterpret_cast<InverseTransform*>(this); }
00171 
00173     const InverseTransform&  operator~() const  {return invert();}
00174 
00176     InverseTransform&        operator~()        {return updInvert();}
00177 
00180     Transform compose(const Transform& X_FY) const {
00181         return Transform( R_BF * X_FY.R(),  T_BF + R_BF * X_FY.T() );
00182     }
00183 
00189     // (Definition is below after InverseTransform is declared.)
00190     inline Transform  compose( const InverseTransform& X_FY ) const;
00191 
00195     Vec3  xformFrameVecToBase( const Vec3& vF ) const {return R_BF*vF;}
00196 
00200     Vec3  xformBaseVecToFrame( const Vec3& vB ) const  { return ~R_BF*vB; }
00201 
00205     Vec3  shiftFrameStationToBase( const Vec3& sF ) const { return T_BF + xformFrameVecToBase(sF); }
00206 
00210     Vec3  shiftBaseStationToFrame( const Vec3& sB ) const { return xformBaseVecToFrame(sB - T_BF); }
00211 
00213     const Rotation&  R() const  { return R_BF; }
00214 
00216     Rotation&  updR()           { return R_BF; }
00217 
00220     const Rotation::ColType&  x() const  { return R().x(); }
00223     const Rotation::ColType&  y() const  { return R().y(); }
00226     const Rotation::ColType&  z() const  { return R().z(); }
00227 
00230     const InverseRotation&  RInv() const  { return ~R_BF; }
00231 
00234     InverseRotation&  updRInv()  { return ~R_BF; }
00235 
00237     const Vec3&  T() const  { return T_BF; }
00238 
00241     Vec3&  updT()  { return T_BF; }
00242 
00247     Transform&  setT( const Vec3& T )  { T_BF=T; return *this; }
00248 
00252     Vec3  TInv() const  { return -(~R_BF*T_BF); }
00253 
00261     Transform&  setTInv( const Vec3& T_FB )  { T_BF = -(R_BF*T_FB); return *this; }
00262 
00266     const Mat34&  asMat34() const  { return Mat34::getAs(reinterpret_cast<const Real*>(this)); }
00267 
00269     Mat34  toMat34() const  { return asMat34(); }
00270 
00272     Mat44 toMat44() const {
00273         Mat44 tmp;
00274         tmp.updSubMat<3,4>(0,0) = asMat34();
00275         tmp[3]                  = Row4(0,0,0,1);
00276         return tmp;
00277     }
00278 private:
00279     //TODO: these might not pack correctly; should use an array of 12 Reals.
00280     Rotation R_BF;   // rotation matrix that expresses F's axes in R
00281     Vec3     T_BF;   // location of F's origin measured from B's origin, expressed in B 
00282 };
00283 
00284 
00285 //-----------------------------------------------------------------------------
00298 //-----------------------------------------------------------------------------
00299 class InverseTransform {
00300 public:
00301     InverseTransform() : R_FB(), T_FB(0) { }
00302     // default copy, assignment, destructor
00303 
00304     // Implicit conversion to Transform
00305     operator Transform() const  { return Transform( R(), T() ); }
00306 
00307     // Assignment from Transform. This means that the inverse
00308     // transform we're assigning to must end up with the same meaning
00309     // as the inverse transform X has, so we'll need:
00310     //          T* == X.TInv()
00311     //          R* == X.RInv()
00312     // Cost: one frame conversion and a negation for TInv, 18 flops.
00313     InverseTransform&  operator=( const Transform& X ) {
00314         // Be careful to do this in the right order in case X and this
00315         // are the same object, i.e. ~X = X which is weird but has
00316         // the same meaning as X = ~X, i.e. invert X in place.
00317         T_FB = X.TInv(); // This might change X.T ...
00318         R_FB = X.RInv(); // ... but this doesn't depend on X.T.
00319         return *this;
00320     }
00321 
00322     // Inverting one of these just recasts it back to a Transform.
00323     const Transform&  invert() const  { return *reinterpret_cast<const Transform*>(this); }
00324     Transform&  updInvert()           { return *reinterpret_cast<Transform*>(this); }
00325 
00326     // Overload transpose to mean inversion.
00327     const Transform&  operator~() const  { return invert(); }
00328     Transform&        operator~()        { return updInvert(); }
00329 
00330     // Return X_BY=X_BF*X_FY, where X_BF (this) is represented here as ~X_FB. This
00331     // costs exactly the same as a composition of two Transforms (63 flops).
00332     Transform  compose(const Transform& X_FY) const {
00333         return Transform( ~R_FB * X_FY.R(),  ~R_FB *(X_FY.T() - T_FB) );
00334     }
00335     // Return X_BY=X_BF*X_FY, but now both xforms are represented by their inverses.
00336     // This costs one extra vector transformation and a negation (18 flops) more
00337     // than a composition of two Transforms, for a total of 81 flops.
00338     Transform  compose(const InverseTransform& X_FY) const { 
00339         return Transform(  ~R_FB * X_FY.R(),  ~R_FB *(X_FY.T() - T_FB)  ); 
00340     }
00341 
00342     // Forward and inverse vector transformations cost the same here as
00343     // for a Transform (or for that matter, a Rotation): 15 flops.
00344     Vec3  xformFrameVecToBase(const Vec3& vF) const {return ~R_FB*vF;}
00345     Vec3  xformBaseVecToFrame(const Vec3& vB) const {return  R_FB*vB;}
00346 
00347     // Forward and inverse station shift & transform cost the same here as for a Transform: 18 flops.
00348     Vec3  shiftFrameStationToBase(const Vec3& sF) const  { return ~R_FB*(sF-T_FB); }
00349     Vec3  shiftBaseStationToFrame(const Vec3& sB) const  { return R_FB*sB + T_FB; }
00350     
00351     const InverseRotation&  R() const  {return ~R_FB;}
00352     InverseRotation&        updR()     {return ~R_FB;}
00353 
00354     const InverseRotation::ColType&  x() const  {return R().x();}
00355     const InverseRotation::ColType&  y() const  {return R().y();}
00356     const InverseRotation::ColType&  z() const  {return R().z();}
00357 
00358     const Rotation&  RInv() const  {return R_FB;}
00359     Rotation&        updRInv()     {return R_FB;}
00360 
00361     // Costs 18 flops to look at the real translation vector.
00362     Vec3  T() const  { return -(~R_FB*T_FB); }
00363     // no updT lvalue
00364 
00365     // Sorry, can't update translation as an lvalue, but here we
00366     // want -(R_BF*T_FB)=T_BF => T_FB=-(R_FB*T_BF). Cost: 18 flops.
00367     void  setT( const Vec3& T_BF )  { T_FB = -(R_FB*T_BF); }
00368 
00369     // Inverse translation is free.
00370     const Vec3&  TInv() const              { return T_FB; }
00371     void         setTInv( const Vec3& T )  { T_FB = T; }
00372 
00375     Mat34  toMat34() const  { return Transform(*this).asMat34(); }
00376 
00378     Mat44  toMat44() const  { return Transform(*this).toMat44(); }
00379 
00380 private:
00381     // DATA LAYOUT MUST BE IDENTICAL TO Transform !!
00382     // TODO: redo packing here when it is done for Transform.
00383     Rotation R_FB; // transpose of our rotation matrix, R_BF
00384     Vec3     T_FB; // our translation is -(R_BF*T_FB)=-(~R_FB*T_FB)
00385 };
00386 
00387 
00390 inline Vec3  operator*( const Transform& X_BF,        const Vec3& s_F )  { return X_BF.shiftFrameStationToBase(s_F); }
00391 inline Vec3  operator*( const InverseTransform& X_BF, const Vec3& s_F )  { return X_BF.shiftFrameStationToBase(s_F); }
00392 
00396 //-----------------------------------------------------------------------
00397 inline Vec4  operator*( const Transform& X_BF, const Vec4& a_F ) {
00398     assert(a_F[3]==0 || a_F[3]==1);
00399     const Vec3& v_F = Vec3::getAs(&a_F[0]); // recast the 1st 3 elements as Vec3
00400 
00401     Vec4 out;
00402     if( a_F[3] == 0 ) { Vec3::updAs(&out[0]) = X_BF.xformFrameVecToBase(v_F);      out[3] = 0; } 
00403     else              { Vec3::updAs(&out[0]) = X_BF.shiftFrameStationToBase(v_F);  out[3] = 1; }
00404     return out;
00405 }
00406 
00407 //-----------------------------------------------------------------------
00408 inline Vec4  operator*( const InverseTransform& X_BF, const Vec4& a_F ) {
00409     assert(a_F[3]==0 || a_F[3]==1);
00410     const Vec3& v_F = Vec3::getAs(&a_F[0]); // recast the 1st 3 elements as Vec3
00411 
00412     Vec4 out;
00413     if( a_F[3] == 0 ) { Vec3::updAs(&out[0]) = X_BF.xformFrameVecToBase(v_F);      out[3] = 0; } 
00414     else              { Vec3::updAs(&out[0]) = X_BF.shiftFrameStationToBase(v_F);  out[3] = 1; }
00415     return out;
00416 }
00417 
00419 
00420 template <class E>
00421 inline Vector_<E> operator*(const Transform& T, const VectorBase<E>& v) {
00422     Vector_<E> result(v.size());
00423     for (int i = 0; i < v.size(); ++i)
00424         result[i] = T*v[i];
00425     return result;
00426 }
00427 template <class E>
00428 inline Vector_<E> operator*(const VectorBase<E>& v, const Transform& T) {
00429     Vector_<E> result(v.size());
00430     for (int i = 0; i < v.size(); ++i)
00431         result[i] = T*v[i];
00432     return result;
00433 }
00434 template <class E>
00435 inline RowVector_<E> operator*(const Transform& T, const RowVectorBase<E>& v) {
00436     RowVector_<E> result(v.size());
00437     for (int i = 0; i < v.size(); ++i)
00438         result[i] = T*v[i];
00439     return result;
00440 }
00441 template <class E>
00442 inline RowVector_<E> operator*(const RowVectorBase<E>& v, const Transform& T) {
00443     RowVector_<E> result(v.size());
00444     for (int i = 0; i < v.size(); ++i)
00445         result[i] = T*v[i];
00446     return result;
00447 }
00448 template <class E>
00449 inline Matrix_<E> operator*(const Transform& T, const MatrixBase<E>& v) {
00450     Matrix_<E> result(v.nrow(), v.ncol());
00451     for (int i = 0; i < v.nrow(); ++i)
00452         for (int j = 0; j < v.ncol(); ++j)
00453             result(i, j) = T*v(i, j);
00454     return result;
00455 }
00456 template <class E>
00457 inline Matrix_<E> operator*(const MatrixBase<E>& v, const Transform& T) {
00458     Matrix_<E> result(v.nrow(), v.ncol());
00459     for (int i = 0; i < v.nrow(); ++i)
00460         for (int j = 0; j < v.ncol(); ++j)
00461             result(i, j) = T*v(i, j);
00462     return result;
00463 }
00464 template <int N, class E>
00465 inline Vec<N,E> operator*(const Transform& T, const Vec<N,E>& v) {
00466     Vec<N,E> result;
00467     for (int i = 0; i < N; ++i)
00468         result[i] = T*v[i];
00469     return result;
00470 }
00471 template <int N, class E>
00472 inline Vec<N,E> operator*(const Vec<N,E>& v, const Transform& T) {
00473     Vec<N,E> result;
00474     for (int i = 0; i < N; ++i)
00475         result[i] = T*v[i];
00476     return result;
00477 }
00478 template <int N, class E>
00479 inline Row<N,E> operator*(const Transform& T, const Row<N,E>& v) {
00480     Row<N,E> result;
00481     for (int i = 0; i < N; ++i)
00482         result[i] = T*v[i];
00483     return result;
00484 }
00485 template <int N, class E>
00486 inline Row<N,E> operator*(const Row<N,E>& v, const Transform& T) {
00487     Row<N,E> result;
00488     for (int i = 0; i < N; ++i)
00489         result[i] = T*v[i];
00490     return result;
00491 }
00492 template <int M, int N, class E>
00493 inline Mat<M,N,E> operator*(const Transform& T, const Mat<M,N,E>& v) {
00494     Mat<M,N,E> result;
00495     for (int i = 0; i < M; ++i)
00496         for (int j = 0; j < N; ++j)
00497             result(i, j) = T*v(i, j);
00498     return result;
00499 }
00500 template <int M, int N, class E>
00501 inline Mat<M,N,E> operator*(const Mat<M,N,E>& v, const Transform& T) {
00502     Mat<M,N,E> result;
00503     for (int i = 0; i < M; ++i)
00504         for (int j = 0; j < N; ++j)
00505             result(i, j) = T*v(i, j);
00506     return result;
00507 }
00508 
00510 
00511 // These Transform definitions had to wait for InverseTransform to be declared.
00512 inline Transform&  Transform::operator=( const InverseTransform& X ) {
00513     // Be careful to do this in the right order in case X and this
00514     // are the same object, i.e. we're doing X = ~X, inverting X in place.
00515     T_BF = X.T(); // This might change X.T ...
00516     R_BF = X.R(); // ... but this doesn't depend on X.T.
00517     return *this;
00518 }
00519 
00520 inline Transform  Transform::compose( const InverseTransform& X_FY ) const {
00521     return Transform( R_BF * X_FY.R(), T_BF + R_BF * X_FY.T() );
00522 }
00523 
00524 inline Transform  operator*( const Transform& X1,        const Transform& X2 )         { return X1.compose(X2); }
00525 inline Transform  operator*( const Transform& X1,        const InverseTransform& X2 )  { return X1.compose(X2); }
00526 inline Transform  operator*( const InverseTransform& X1, const Transform& X2 )         { return X1.compose(X2); }
00527 inline Transform  operator*( const InverseTransform& X1, const InverseTransform& X2 )  { return X1.compose(X2); }
00528 
00529 inline bool  operator==( const Transform& X1,        const Transform& X2 )         { return X1.R()==X2.R() && X1.T()==X2.T(); }
00530 inline bool  operator==( const InverseTransform& X1, const InverseTransform& X2 )  { return X1.R()==X2.R() && X1.T()==X2.T(); }
00531 inline bool  operator==( const Transform& X1,        const InverseTransform& X2 )  { return X1.R()==X2.R() && X1.T()==X2.T(); }
00532 inline bool  operator==( const InverseTransform& X1, const Transform& X2 )         { return X1.R()==X2.R() && X1.T()==X2.T(); }
00533 
00534 SimTK_SimTKCOMMON_EXPORT std::ostream&  operator<<( std::ostream& o, const Transform& );
00535 
00536 
00537 //------------------------------------------------------------------------------
00538 }  // End of namespace SimTK
00539 
00540 //--------------------------------------------------------------------------
00541 #endif // SimTK_TRANSFORM_H_
00542 //--------------------------------------------------------------------------
00543 

Generated on Thu Feb 28 01:34:33 2008 for SimTKcommon by  doxygen 1.4.7