Simbody
3.4 (development)
|
00001 #ifndef SimTK_SimTKCOMMON_TRANSFORM_H 00002 #define SimTK_SimTKCOMMON_TRANSFORM_H 00003 00004 /* -------------------------------------------------------------------------- * 00005 * Simbody(tm): SimTKcommon * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. * 00011 * * 00012 * Portions copyright (c) 2005-12 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: Paul Mitiguy * 00015 * * 00016 * Licensed under the Apache License, Version 2.0 (the "License"); you may * 00017 * not use this file except in compliance with the License. You may obtain a * 00018 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 00019 * * 00020 * Unless required by applicable law or agreed to in writing, software * 00021 * distributed under the License is distributed on an "AS IS" BASIS, * 00022 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 00023 * See the License for the specific language governing permissions and * 00024 * limitations under the License. * 00025 * -------------------------------------------------------------------------- */ 00026 00027 //----------------------------------------------------------------------------- 00028 #include "SimTKcommon/SmallMatrix.h" 00029 #include "SimTKcommon/internal/BigMatrix.h" 00030 #include "SimTKcommon/internal/UnitVec.h" 00031 #include "SimTKcommon/internal/Quaternion.h" 00032 #include "SimTKcommon/internal/Rotation.h" 00033 //----------------------------------------------------------------------------- 00034 #include <iosfwd> // Forward declaration of iostream 00035 //----------------------------------------------------------------------------- 00036 00037 00038 //----------------------------------------------------------------------------- 00039 namespace SimTK { 00040 00041 //----------------------------------------------------------------------------- 00042 // Forward declarations (everything is templatized by precision). 00043 template <class P> class Transform_; 00044 template <class P> class InverseTransform_; 00045 00046 typedef Transform_<Real> Transform; 00047 typedef Transform_<float> fTransform; 00048 typedef Transform_<double> dTransform; 00049 00050 00051 //----------------------------------------------------------------------------- 00106 //----------------------------------------------------------------------------- 00107 template <class P> 00108 class Transform_ { 00109 public: 00111 Transform_() : R_BF(), p_BF(0) { } 00112 00114 Transform_( const Rotation_<P>& R, const Vec<3,P>& p ) : R_BF(R), p_BF(p) { } 00115 00118 Transform_( const Rotation_<P>& R ) : R_BF(R), p_BF(0) { } 00119 00122 Transform_( const Vec<3,P>& p ) : R_BF(), p_BF(p) { } 00123 00124 // default copy, assignment, destructor 00125 00133 // (Definition is below after InverseTransform is declared.) 00134 inline Transform_& operator=( const InverseTransform_<P>& X ); 00135 00138 template <int S> 00139 Transform_& operator+=(const Vec<3,P,S>& offset_B) 00140 { p_BF += offset_B; return *this; } 00141 00144 template <int S> 00145 Transform_& operator-=(const Vec<3,P,S>& offset_B) 00146 { p_BF -= offset_B; return *this; } 00147 00151 Transform_& set( const Rotation_<P>& R, const Vec<3,P>& p ) { p_BF=p; R_BF=R; return *this; } 00152 00156 Transform_& setToZero() { R_BF.setRotationToIdentityMatrix(); p_BF = P(0); return *this; } 00157 00162 Transform_& setToNaN() { R_BF.setRotationToNaN(); p_BF.setToNaN(); return *this; } 00163 00166 const InverseTransform_<P>& invert() const { return *reinterpret_cast<const InverseTransform_<P>*>(this); } 00167 00170 InverseTransform_<P>& updInvert() { return *reinterpret_cast<InverseTransform_<P>*>(this); } 00171 00173 const InverseTransform_<P>& operator~() const {return invert();} 00174 00176 InverseTransform_<P>& operator~() {return updInvert();} 00177 00180 Transform_ compose(const Transform_& X_FY) const { 00181 return Transform_( R_BF * X_FY.R(), p_BF + R_BF * X_FY.p() ); 00182 } 00183 00189 // (Definition is below after InverseTransform_ is declared.) 00190 inline Transform_ compose( const InverseTransform_<P>& X_FY ) const; 00191 00195 Vec<3,P> xformFrameVecToBase( const Vec<3,P>& vF ) const {return R_BF*vF;} 00196 00200 Vec<3,P> xformBaseVecToFrame( const Vec<3,P>& vB ) const { return ~R_BF*vB; } 00201 00205 Vec<3,P> shiftFrameStationToBase( const Vec<3,P>& sF ) const 00206 { return p_BF + xformFrameVecToBase(sF); } 00207 00211 Vec<3,P> shiftBaseStationToFrame( const Vec<3,P>& sB ) const 00212 { return xformBaseVecToFrame(sB - p_BF); } 00213 00215 const Rotation_<P>& R() const { return R_BF; } 00216 00218 Rotation_<P>& updR() { return R_BF; } 00219 00222 const typename Rotation_<P>::ColType& x() const { return R().x(); } 00225 const typename Rotation_<P>::ColType& y() const { return R().y(); } 00228 const typename Rotation_<P>::ColType& z() const { return R().z(); } 00229 00232 const InverseRotation_<P>& RInv() const { return ~R_BF; } 00233 00236 InverseRotation_<P>& updRInv() { return ~R_BF; } 00237 00239 const Vec<3,P>& p() const { return p_BF; } 00240 00243 Vec<3,P>& updP() { return p_BF; } 00244 00249 Transform_<P>& setP( const Vec<3,P>& p ) { p_BF=p; return *this; } 00250 00254 Vec<3,P> pInv() const { return -(~R_BF*p_BF); } 00255 00263 Transform_<P>& setPInv( const Vec<3,P>& p_FB ) { p_BF = -(R_BF*p_FB); return *this; } 00264 00268 const Mat<3,4,P>& asMat34() const { return Mat<3,4,P>::getAs(reinterpret_cast<const P*>(this)); } 00269 00271 Mat<3,4,P> toMat34() const { return asMat34(); } 00272 00274 Mat<4,4,P> toMat44() const { 00275 Mat<4,4,P> tmp; 00276 tmp.template updSubMat<3,4>(0,0) = asMat34(); 00277 tmp[3] = Row<4,P>(0,0,0,1); 00278 return tmp; 00279 } 00280 00281 // OBSOLETE -- alternate name for p 00282 const Vec<3,P>& T() const {return p();} 00283 Vec<3,P>& updT() {return updP();} 00284 00285 private: 00286 //TODO: these might not pack correctly; should use an array of 12 Reals. 00287 Rotation_<P> R_BF; // rotation matrix that expresses F's axes in R 00288 Vec<3,P> p_BF; // location of F's origin measured from B's origin, expressed in B 00289 }; 00290 00291 00292 //----------------------------------------------------------------------------- 00304 //----------------------------------------------------------------------------- 00305 template <class P> 00306 class InverseTransform_ { 00307 public: 00309 InverseTransform_() : R_FB(), p_FB(0) { } 00310 00311 // default copy, assignment, destructor 00312 00314 operator Transform_<P>() const { return Transform_<P>( R(), p() ); } 00315 00316 // Assignment from Transform. This means that the inverse 00317 // transform we're assigning to must end up with the same meaning 00318 // as the inverse transform X has, so we'll need: 00319 // p* == X.pInv() 00320 // R* == X.RInv() 00321 // Cost: one frame conversion and a negation for pInv, 18 flops. 00322 InverseTransform_& operator=( const Transform_<P>& X ) { 00323 // Be careful to do this in the right order in case X and this 00324 // are the same object, i.e. ~X = X which is weird but has 00325 // the same meaning as X = ~X, i.e. invert X in place. 00326 p_FB = X.pInv(); // This might change X.p ... 00327 R_FB = X.RInv(); // ... but this doesn't depend on X.p. 00328 return *this; 00329 } 00330 00331 // Inverting one of these just recasts it back to a Transform_<P>. 00332 const Transform_<P>& invert() const { return *reinterpret_cast<const Transform_<P>*>(this); } 00333 Transform_<P>& updInvert() { return *reinterpret_cast<Transform_<P>*>(this); } 00334 00335 // Overload transpose to mean inversion. 00336 const Transform_<P>& operator~() const { return invert(); } 00337 Transform_<P>& operator~() { return updInvert(); } 00338 00339 // Return X_BY=X_BF*X_FY, where X_BF (this) is represented here as ~X_FB. This 00340 // costs exactly the same as a composition of two Transforms (63 flops). 00341 Transform_<P> compose(const Transform_<P>& X_FY) const { 00342 return Transform_<P>( ~R_FB * X_FY.R(), ~R_FB *(X_FY.p() - p_FB) ); 00343 } 00344 // Return X_BY=X_BF*X_FY, but now both xforms are represented by their inverses. 00345 // This costs one extra vector transformation and a negation (18 flops) more 00346 // than a composition of two Transforms, for a total of 81 flops. 00347 Transform_<P> compose(const InverseTransform_<P>& X_FY) const { 00348 return Transform_<P>( ~R_FB * X_FY.R(), ~R_FB *(X_FY.p() - p_FB) ); 00349 } 00350 00351 // Forward and inverse vector transformations cost the same here as 00352 // for a Transform_<P> (or for that matter, a Rotation_<P>): 15 flops. 00353 Vec<3,P> xformFrameVecToBase(const Vec<3,P>& vF) const {return ~R_FB*vF;} 00354 Vec<3,P> xformBaseVecToFrame(const Vec<3,P>& vB) const {return R_FB*vB;} 00355 00356 // Forward and inverse station shift & transform cost the same here as for a Transform_<P>: 18 flops. 00357 Vec<3,P> shiftFrameStationToBase(const Vec<3,P>& sF) const { return ~R_FB*(sF-p_FB); } 00358 Vec<3,P> shiftBaseStationToFrame(const Vec<3,P>& sB) const { return R_FB*sB + p_FB; } 00359 00360 const InverseRotation_<P>& R() const {return ~R_FB;} 00361 InverseRotation_<P>& updR() {return ~R_FB;} 00362 00363 const typename InverseRotation_<P>::ColType& x() const {return R().x();} 00364 const typename InverseRotation_<P>::ColType& y() const {return R().y();} 00365 const typename InverseRotation_<P>::ColType& z() const {return R().z();} 00366 00367 const Rotation_<P>& RInv() const {return R_FB;} 00368 Rotation_<P>& updRInv() {return R_FB;} 00369 00373 Vec<3,P> p() const { return -(~R_FB*p_FB); } 00374 00375 00376 // no updP lvalue 00377 00378 // Sorry, can't update translation as an lvalue, but here we 00379 // want -(R_BF*p_FB)=p_BF => p_FB=-(R_FB*p_BF). Cost: 18 flops. 00380 void setP( const Vec<3,P>& p_BF ) { p_FB = -(R_FB*p_BF); } 00381 00382 // Inverse translation is free. 00383 const Vec<3,P>& pInv() const { return p_FB; } 00384 void setPInv( const Vec<3,P>& p ) { p_FB = p; } 00385 00388 Mat<3,4,P> toMat34() const { return Transform_<P>(*this).asMat34(); } 00389 00391 Mat<4,4,P> toMat44() const { return Transform_<P>(*this).toMat44(); } 00392 00393 // OBSOLETE -- alternate name for p. 00394 Vec<3,P> T() const {return p();} 00395 00396 private: 00397 // DATA LAYOUT MUST BE IDENTICAL TO Transform_<P> !! 00398 // TODO: redo packing here when it is done for Transform_<P>. 00399 Rotation_<P> R_FB; // transpose of our rotation matrix, R_BF 00400 Vec<3,P> p_FB; // our translation is -(R_BF*p_FB)=-(~R_FB*p_FB) 00401 }; 00402 00408 template <class P, int S> inline Vec<3,P> 00409 operator*(const Transform_<P>& X_BF, const Vec<3,P,S>& s_F) 00410 { return X_BF.shiftFrameStationToBase(s_F); } 00411 template <class P, int S> inline Vec<3,P> 00412 operator*(const InverseTransform_<P>& X_BF, const Vec<3,P,S>& s_F) 00413 { return X_BF.shiftFrameStationToBase(s_F); } 00414 template <class P, int S> inline Vec<3,P> 00415 operator*(const Transform_<P>& X_BF, const Vec<3,negator<P>,S>& s_F) 00416 { 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) 00419 { return X_BF*Vec<3,P>(s_F); } 00420 00423 template <class P, int S> inline Transform_<P> 00424 operator+(const Transform_<P>& X_BF, const Vec<3,P,S>& offset_B) 00425 { return Transform_<P>(X_BF) += offset_B; } 00428 template <class P, int S> inline Transform_<P> 00429 operator+(const Vec<3,P,S>& offset_B, const Transform_<P>& X_BF) 00430 { return Transform_<P>(X_BF) += offset_B; } 00431 00434 template <class P, int S> inline Transform_<P> 00435 operator-(const Transform_<P>& X_BF, const Vec<3,P,S>& offset_B) 00436 { return Transform_<P>(X_BF) -= offset_B; } 00437 00438 //----------------------------------------------------------------------------- 00444 template <class P, int S> inline Vec<4,P> 00445 operator*(const Transform_<P>& X_BF, const Vec<4,P,S>& a_F) { 00446 assert(a_F[3]==0 || a_F[3]==1); 00447 const Vec<3,P,S>& v_F = Vec<3,P,S>::getAs(&a_F[0]); // recast the 1st 3 elements as Vec3 00448 00449 Vec<4,P> out; 00450 if( a_F[3] == 0 ) { Vec<3,P>::updAs(&out[0]) = X_BF.xformFrameVecToBase(v_F); out[3] = 0; } 00451 else { Vec<3,P>::updAs(&out[0]) = X_BF.shiftFrameStationToBase(v_F); out[3] = 1; } 00452 return out; 00453 } 00454 00455 template <class P, int S> inline Vec<4,P> 00456 operator*(const InverseTransform_<P>& X_BF, const Vec<4,P,S>& a_F ) { 00457 assert(a_F[3]==0 || a_F[3]==1); 00458 const Vec<3,P,S>& v_F = Vec<3,P,S>::getAs(&a_F[0]); // recast the 1st 3 elements as Vec3 00459 00460 Vec<4,P> out; 00461 if( a_F[3] == 0 ) { Vec<3,P>::updAs(&out[0]) = X_BF.xformFrameVecToBase(v_F); out[3] = 0; } 00462 else { Vec<3,P>::updAs(&out[0]) = X_BF.shiftFrameStationToBase(v_F); out[3] = 1; } 00463 return out; 00464 } 00465 template <class P, int S> inline Vec<4,P> 00466 operator*(const Transform_<P>& X_BF, const Vec<4,negator<P>,S>& s_F) {return X_BF*Vec<4,P>(s_F);} 00467 template <class P, int S> inline Vec<4,P> 00468 operator*(const InverseTransform_<P>& X_BF, const Vec<4,negator<P>,S>& s_F) {return X_BF*Vec<4,P>(s_F);} 00469 //----------------------------------------------------------------------------- 00470 00474 template <class P, class E> inline Vector_<E> 00475 operator*(const Transform_<P>& X, const VectorBase<E>& v) { 00476 Vector_<E> result(v.size()); 00477 for (int i = 0; i < v.size(); ++i) 00478 result[i] = X*v[i]; 00479 return result; 00480 } 00481 template <class P, class E> inline Vector_<E> 00482 operator*(const VectorBase<E>& v, const Transform_<P>& X) { 00483 Vector_<E> result(v.size()); 00484 for (int i = 0; i < v.size(); ++i) 00485 result[i] = X*v[i]; 00486 return result; 00487 } 00488 template <class P, class E> inline RowVector_<E> 00489 operator*(const Transform_<P>& X, const RowVectorBase<E>& v) { 00490 RowVector_<E> result(v.size()); 00491 for (int i = 0; i < v.size(); ++i) 00492 result[i] = X*v[i]; 00493 return result; 00494 } 00495 template <class P, class E> inline RowVector_<E> 00496 operator*(const RowVectorBase<E>& v, const Transform_<P>& X) { 00497 RowVector_<E> result(v.size()); 00498 for (int i = 0; i < v.size(); ++i) 00499 result[i] = X*v[i]; 00500 return result; 00501 } 00502 template <class P, class E> inline Matrix_<E> 00503 operator*(const Transform_<P>& X, const MatrixBase<E>& v) { 00504 Matrix_<E> result(v.nrow(), v.ncol()); 00505 for (int i = 0; i < v.nrow(); ++i) 00506 for (int j = 0; j < v.ncol(); ++j) 00507 result(i, j) = X*v(i, j); 00508 return result; 00509 } 00510 template <class P, class E> inline Matrix_<E> 00511 operator*(const MatrixBase<E>& v, const Transform_<P>& X) { 00512 Matrix_<E> result(v.nrow(), v.ncol()); 00513 for (int i = 0; i < v.nrow(); ++i) 00514 for (int j = 0; j < v.ncol(); ++j) 00515 result(i, j) = X*v(i, j); 00516 return result; 00517 } 00518 template <class P, int N, class E, int S> inline Vec<N,E> 00519 operator*(const Transform_<P>& X, const Vec<N,E,S>& v) { 00520 Vec<N,E> result; 00521 for (int i = 0; i < N; ++i) 00522 result[i] = X*v[i]; 00523 return result; 00524 } 00525 template <class P, int N, class E, int S> inline Vec<N,E> 00526 operator*(const Vec<N,E,S>& v, const Transform_<P>& X) { 00527 Vec<N,E> result; 00528 for (int i = 0; i < N; ++i) 00529 result[i] = X*v[i]; 00530 return result; 00531 } 00532 template <class P, int N, class E, int S> inline Row<N,E> 00533 operator*(const Transform_<P>& X, const Row<N,E,S>& v) { 00534 Row<N,E> result; 00535 for (int i = 0; i < N; ++i) 00536 result[i] = X*v[i]; 00537 return result; 00538 } 00539 template <class P, int N, class E, int S> inline Row<N,E> 00540 operator*(const Row<N,E,S>& v, const Transform_<P>& X) { 00541 Row<N,E> result; 00542 for (int i = 0; i < N; ++i) 00543 result[i] = X*v[i]; 00544 return result; 00545 } 00546 template <class P, int M, int N, class E, int CS, int RS> inline Mat<M,N,E> 00547 operator*(const Transform_<P>& X, const Mat<M,N,E,CS,RS>& v) { 00548 Mat<M,N,E> result; 00549 for (int i = 0; i < M; ++i) 00550 for (int j = 0; j < N; ++j) 00551 result(i, j) = X*v(i, j); 00552 return result; 00553 } 00554 template <class P, int M, int N, class E, int CS, int RS> inline Mat<M,N,E> 00555 operator*(const Mat<M,N,E,CS,RS>& v, const Transform_<P>& X) { 00556 Mat<M,N,E> result; 00557 for (int i = 0; i < M; ++i) 00558 for (int j = 0; j < N; ++j) 00559 result(i, j) = X*v(i, j); 00560 return result; 00561 } 00562 00563 // These Transform definitions had to wait for InverseTransform to be declared. 00564 00565 template <class P> inline Transform_<P>& 00566 Transform_<P>::operator=( const InverseTransform_<P>& X ) { 00567 // Be careful to do this in the right order in case X and this 00568 // are the same object, i.e. we're doing X = ~X, inverting X in place. 00569 p_BF = X.p(); // This might change X.p ... 00570 R_BF = X.R(); // ... but this doesn't depend on X.p. 00571 return *this; 00572 } 00573 00574 template <class P> inline Transform_<P> 00575 Transform_<P>::compose( const InverseTransform_<P>& X_FY ) const { 00576 return Transform_<P>( R_BF * X_FY.R(), p_BF + R_BF * X_FY.p() ); 00577 } 00578 00582 template <class P> inline Transform_<P> 00583 operator*(const Transform_<P>& X1, const Transform_<P>& X2) {return X1.compose(X2);} 00584 template <class P> inline Transform_<P> 00585 operator*(const Transform_<P>& X1, const InverseTransform_<P>& X2) {return X1.compose(X2);} 00586 template <class P> inline Transform_<P> 00587 operator*(const InverseTransform_<P>& X1, const Transform_<P>& X2) {return X1.compose(X2);} 00588 template <class P> inline Transform_<P> 00589 operator*(const InverseTransform_<P>& X1, const InverseTransform_<P>& X2) {return X1.compose(X2);} 00590 00594 template <class P> inline bool 00595 operator==(const Transform_<P>& X1, const Transform_<P>& X2) {return X1.R()==X2.R() && X1.p()==X2.p();} 00596 template <class P> inline bool 00597 operator==(const InverseTransform_<P>& X1, const InverseTransform_<P>& X2) {return X1.R()==X2.R() && X1.p()==X2.p();} 00598 template <class P> inline bool 00599 operator==(const Transform_<P>& X1, const InverseTransform_<P>& X2) {return X1.R()==X2.R() && X1.p()==X2.p();} 00600 template <class P> inline bool 00601 operator==(const InverseTransform_<P>& X1, const Transform_<P>& X2) {return X1.R()==X2.R() && X1.p()==X2.p();} 00602 00605 template <class P> SimTK_SimTKCOMMON_EXPORT std::ostream& 00606 operator<<(std::ostream&, const Transform_<P>&); 00609 template <class P> SimTK_SimTKCOMMON_EXPORT std::ostream& 00610 operator<<(std::ostream&, const InverseTransform_<P>&); 00611 00612 00613 00614 //------------------------------------------------------------------------------ 00615 } // End of namespace SimTK 00616 00617 //-------------------------------------------------------------------------- 00618 #endif // SimTK_SimTKCOMMON_TRANSFORM_H 00619 //-------------------------------------------------------------------------- 00620