MassProperties.h

Go to the documentation of this file.
00001 #ifndef SimTK_SIMMATRIX_MASS_PROPERTIES_H_
00002 #define SimTK_SIMMATRIX_MASS_PROPERTIES_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                      SimTK Core: SimTK Simmatrix(tm)                       *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK Core 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.               *
00011  *                                                                            *
00012  * Portions copyright (c) 2005-9 Stanford University and the Authors.         *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors:                                                              *
00015  *                                                                            *
00016  * Permission is hereby granted, free of charge, to any person obtaining a    *
00017  * copy of this software and associated documentation files (the "Software"), *
00018  * to deal in the Software without restriction, including without limitation  *
00019  * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
00020  * and/or sell copies of the Software, and to permit persons to whom the      *
00021  * Software is furnished to do so, subject to the following conditions:       *
00022  *                                                                            *
00023  * The above copyright notice and this permission notice shall be included in *
00024  * all copies or substantial portions of the Software.                        *
00025  *                                                                            *
00026  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
00027  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
00028  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
00029  * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
00030  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
00031  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
00032  * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
00033  * -------------------------------------------------------------------------- */
00034 
00041 #include "SimTKcommon/Scalar.h"
00042 #include "SimTKcommon/SmallMatrix.h"
00043 #include "SimTKcommon/Orientation.h"
00044 
00045 #include <iostream>
00046 
00047 namespace SimTK {
00048 // Spatial vectors are used for (orientation,translation) quantities.
00049 // These include
00050 //      spatial velocity     = (angularVelocity,linearVelocity)
00051 //      spatial acceleration = (angularAcceleration,linearAcceleration)
00052 //      generalized forces   = (torque,force)
00053 // Spatial configuration has to be handled differently though since
00054 // orientation is not a vector quantity. (We use "Transform" for this concept
00055 // which includes an orientation matrix and a translation vector.)
00056 typedef Vec<2,   Vec3>              SpatialVec;
00057 typedef Vec<2,   Vec<3,float> >    fSpatialVec;
00058 typedef Vec<2,   Vec<3,double> >   dSpatialVec;
00059 
00060 typedef Row<2,   Row3>              SpatialRow;
00061 typedef Row<2,   Row<3,float> >    fSpatialRow;
00062 typedef Row<2,   Row<3,double> >   dSpatialRow;
00063 
00064 typedef Mat<2,2, Mat33>              SpatialMat;
00065 typedef Mat<2,2, Mat<3,3,float> >   fSpatialMat;
00066 typedef Mat<2,2, Mat<3,3,double> >  dSpatialMat;
00067 
00068 // These are templatized by precision (float or double).
00069 template <class P> class Gyration_;
00070 template <class P> class Inertia_;
00071 template <class P> class SpatialInertia_;
00072 template <class P> class ArticulatedInertia_;
00073 
00074 // The "no trailing underscore" typedefs use whatever the 
00075 // compile-time precision is set to.
00076 
00078 typedef Gyration_<Real>              Gyration;
00080 typedef Gyration_<float>            fGyration;
00082 typedef Gyration_<double>           dGyration;
00083 
00085 typedef Inertia_<Real>               Inertia;
00087 typedef Inertia_<float>             fInertia;
00089 typedef Inertia_<double>            dInertia;
00090 
00092 typedef SpatialInertia_<Real>        SpatialInertia;
00094 typedef SpatialInertia_<float>      fSpatialInertia;
00096 typedef SpatialInertia_<double>     dSpatialInertia;
00097 
00099 typedef ArticulatedInertia_<Real>    ArticulatedInertia;
00101 typedef ArticulatedInertia_<float>  fArticulatedInertia;
00103 typedef ArticulatedInertia_<double> dArticulatedInertia;
00104 
00105 
00106 // -----------------------------------------------------------------------------
00107 //                             INERTIA MATRIX
00108 // -----------------------------------------------------------------------------
00109 
00166 template <class P>
00167 class SimTK_SimTKCOMMON_EXPORT Inertia_ {
00168     typedef P               RealP;
00169     typedef Vec<3,P>        Vec3P;
00170     typedef SymMat<3,P>     SymMat33P;
00171     typedef Mat<3,3,P>      Mat33P;
00172     typedef Rotation_<P>    RotationP;
00173 public:
00176     Inertia_() : I_OF_F(NTraits<P>::getNaN()) {}
00177 
00178     // Default copy constructor, copy assignment, destructor.
00179 
00186     explicit Inertia_(const RealP& moment) : I_OF_F(moment) 
00187     {   errChk("Inertia::Inertia(moment)"); }
00188 
00192     Inertia_(const Vec3P& p, const RealP& mass) : I_OF_F(pointMassAt(p,mass)) {}
00193 
00198     explicit Inertia_(const Vec3P& moments, const Vec3P& products=Vec3P(0)) 
00199     {   I_OF_F.updDiag()  = moments;
00200         I_OF_F.updLower() = products;
00201         errChk("Inertia::Inertia(moments,products)"); }
00202 
00204     Inertia_(const RealP& xx, const RealP& yy, const RealP& zz) 
00205     {   I_OF_F = SymMat33P(xx,
00206                             0, yy,
00207                             0,  0, zz);
00208         errChk("Inertia::setInertia(xx,yy,zz)"); }
00209 
00212     Inertia_(const RealP& xx, const RealP& yy, const RealP& zz,
00213              const RealP& xy, const RealP& xz, const RealP& yz) 
00214     {   I_OF_F = SymMat33P(xx,
00215                            xy, yy,
00216                            xz, yz, zz);
00217         errChk("Inertia::setInertia(xx,yy,zz,xy,xz,yz)"); }
00218 
00221     explicit Inertia_(const SymMat33P& I) : I_OF_F(I) 
00222     {   errChk("Inertia::Inertia(SymMat33)"); }
00223 
00227     explicit Inertia_(const Mat33P& m)
00228     {   SimTK_ERRCHK(m.isNumericallySymmetric(), 
00229                      "Inertia(Mat33)", "The supplied matrix was not symmetric.");
00230         I_OF_F = SymMat33P(m);
00231         errChk("Inertia(Mat33)"); }
00232 
00233 
00236     Inertia_& setInertia(const RealP& xx, const RealP& yy, const RealP& zz) {
00237         I_OF_F = RealP(0); I_OF_F(0,0) = xx; I_OF_F(1,1) = yy;  I_OF_F(2,2) = zz;
00238         errChk("Inertia::setInertia(xx,yy,zz)");
00239         return *this;
00240     }
00241 
00244     Inertia_& setInertia(const Vec3P& moments, const Vec3P& products=Vec3P(0)) {
00245         I_OF_F.updDiag()  = moments;
00246         I_OF_F.updLower() = products;
00247         errChk("Inertia::setInertia(moments,products)");
00248         return *this;
00249     }
00250 
00256     Inertia_& setInertia(const RealP& xx, const RealP& yy, const RealP& zz,
00257                          const RealP& xy, const RealP& xz, const RealP& yz) {
00258         setInertia(Vec3P(xx,yy,zz), Vec3P(xy,xz,yz));
00259         errChk("Inertia::setInertia(xx,yy,zz,xy,xz,yz)");
00260         return *this;
00261     }
00262 
00263 
00266     Inertia_& operator+=(const Inertia_& I) 
00267     {   I_OF_F += I.I_OF_F; 
00268         errChk("Inertia::operator+=()");
00269         return *this; }
00270 
00273     Inertia_& operator-=(const Inertia_& I) 
00274     {   I_OF_F -= I.I_OF_F; 
00275         errChk("Inertia::operator-=()");
00276         return *this; }
00277 
00279     Inertia_& operator*=(const P& s) {I_OF_F *= s; return *this;}
00280 
00283     Inertia_& operator/=(const P& s) {I_OF_F /= s; return *this;}
00284 
00294     Inertia_ shiftToMassCenter(const Vec3P& CF, const RealP& mass) const 
00295     {   Inertia_ I(*this); I -= pointMassAt(CF, mass);
00296         I.errChk("Inertia::shiftToMassCenter()");
00297         return I; }
00298 
00309     Inertia_& shiftToMassCenterInPlace(const Vec3P& CF, const RealP& mass) 
00310     {   (*this) -= pointMassAt(CF, mass);
00311         errChk("Inertia::shiftToMassCenterInPlace()");
00312         return *this; }
00313 
00321     Inertia_ shiftFromMassCenter(const Vec3P& p, const RealP& mass) const
00322     {   Inertia_ I(*this); I += pointMassAt(p, mass);
00323         I.errChk("Inertia::shiftFromMassCenter()");
00324         return I; }
00325 
00334     Inertia_& shiftFromMassCenterInPlace(const Vec3P& p, const RealP& mass)
00335     {   (*this) += pointMassAt(p, mass);
00336         errChk("Inertia::shiftFromMassCenterInPlace()");
00337         return *this; }
00338 
00349     Inertia_ reexpress(const Rotation_<P>& R_FB) const 
00350     {   return Inertia_((~R_FB).reexpressSymMat33(I_OF_F)); }
00351 
00354     Inertia_ reexpress(const InverseRotation_<P>& R_FB) const 
00355     {   return Inertia_((~R_FB).reexpressSymMat33(I_OF_F)); }
00356 
00361     Inertia_& reexpressInPlace(const Rotation_<P>& R_FB)
00362     {   I_OF_F = (~R_FB).reexpressSymMat33(I_OF_F); return *this; }
00363 
00366     Inertia_& reexpressInPlace(const InverseRotation_<P>& R_FB)
00367     {   I_OF_F = (~R_FB).reexpressSymMat33(I_OF_F); return *this; }
00368 
00369     RealP trace() const {return I_OF_F.trace();}
00370 
00372     operator const SymMat33P&() const {return I_OF_F;}
00373 
00375     const SymMat33P& asSymMat33() const {return I_OF_F;}
00376 
00379     Mat33P toMat33() const {return Mat33P(I_OF_F);}
00380 
00382     const Vec3P& getMoments()  const {return I_OF_F.getDiag();}
00385     const Vec3P& getProducts() const {return I_OF_F.getLower();}
00386 
00387     bool isNaN()    const {return I_OF_F.isNaN();}
00388     bool isInf()    const {return I_OF_F.isInf();}
00389     bool isFinite() const {return I_OF_F.isFinite();}
00390 
00394     bool isNumericallyEqual(const Inertia_<P>& other) const 
00395     {   return I_OF_F.isNumericallyEqual(other.I_OF_F); }
00396 
00400     bool isNumericallyEqual(const Inertia_<P>& other, double tol) const 
00401     {   return I_OF_F.isNumericallyEqual(other.I_OF_F, tol); }
00402 
00406     static bool isValidInertiaMatrix(const SymMat33P& m) {
00407         const RealP Slop = NTraits<P>::getSignificant();
00408         if (m.isNaN()) return false;
00409         const Vec3P& d = m.diag();
00410         if (!(d >= 0)) return false; // diagonals must be nonnegative
00411         if (!(d[0]+d[1]+Slop>=d[2] && d[0]+d[2]+Slop>=d[1] && d[1]+d[2]+Slop>=d[0]))
00412             return false; // must satisfy triangle inequality
00413         //TODO: what else?
00414         return true;
00415     }
00416 
00419     static Inertia_ pointMassAtOrigin() {return Inertia_(0);}
00420 
00425     static Inertia_ pointMassAt(const Vec3P& p, const RealP& m) {
00426         const Vec3P mp = m*p;       // 3 flops
00427         const RealP mxx = mp[0]*p[0];
00428         const RealP myy = mp[1]*p[1];
00429         const RealP mzz = mp[2]*p[2];
00430         const RealP nmx = -mp[0];
00431         const RealP nmy = -mp[1];
00432         return Inertia_( myy+mzz,  mxx+mzz,  mxx+myy,
00433                          nmx*p[1], nmx*p[2], nmy*p[2] );
00434     }
00435 
00441 
00442 
00445     inline static Inertia_ sphere(const RealP& r);
00446 
00449     inline static Inertia_ cylinderAlongZ(const RealP& r, const RealP& hz);
00450 
00453     inline static Inertia_ cylinderAlongY(const RealP& r, const RealP& hy);
00454 
00457     inline static Inertia_ cylinderAlongX(const RealP& r, const RealP& hx);
00458 
00462     inline static Inertia_ brick(const RealP& hx, const RealP& hy, const RealP& hz);
00463 
00465     inline static Inertia_ brick(const Vec3P& halfLengths);
00466 
00468     inline static Inertia_ ellipsoid(const RealP& hx, const RealP& hy, const RealP& hz);
00469 
00471     inline static Inertia_ ellipsoid(const Vec3P& halfLengths);
00472 
00474 
00475 protected:
00476     // Reinterpret this Inertia matrix as a Gyration matrix, that is, as the
00477     // inertia of something with unit mass. This is useful in implementing
00478     // methods of the Gyration class in terms of Inertia methods. Be sure you
00479     // know that this is a unit-mass inertia!
00480     const Gyration_<P>& getAsGyration() const
00481     {   return *reinterpret_cast<const Gyration_<P>*>(this); }
00482     Gyration_<P>& updAsGyration()
00483     {   return *reinterpret_cast<Gyration_<P>*>(this); }
00484 
00485     // If error checking is enabled (typically only in Debug mode), this 
00486     // method will run some tests on the current contents of this Inertia 
00487     // matrix and throw an error message if it is not valid. This should be 
00488     // the same set of tests as run by the isValidInertiaMatrix() method above.
00489     void errChk(const char* methodName) const {
00490         const RealP Slop = NTraits<P>::getSignificant();
00491         SimTK_ERRCHK(!isNaN(), methodName,
00492             "Inertia matrix contains a NaN.");
00493         const Vec3P& d = I_OF_F.diag();
00494         SimTK_ERRCHK3(d >= 0, methodName,
00495             "Diagonals of an Inertia matrix must be nonnegative; got %g,%g,%g.",
00496             (double)d[0],(double)d[1],(double)d[2]);
00497         SimTK_ERRCHK3(d[0]+d[1]+Slop>=d[2] && d[0]+d[2]+Slop>=d[1] && d[1]+d[2]+Slop>=d[0],
00498             methodName,
00499             "Diagonals of an Inertia matrix must satisfy the triangle "
00500             "inequality; got %g,%g,%g.",
00501             (double)d[0],(double)d[1],(double)d[2]);
00502     }
00503 
00504     // Inertia expressed in frame F and about F's origin OF. Note that frame F
00505     // is implicit here; all we actually have are the inertia scalars.
00506     SymMat33P I_OF_F; 
00507 };
00508 
00513 template <class P> inline Inertia_<P>
00514 operator+(const Inertia_<P>& l, const Inertia_<P>& r) 
00515 {   return Inertia_<P>(l) += r; }
00516 
00522 template <class P> inline Inertia_<P>
00523 operator-(const Inertia_<P>& l, const Inertia_<P>& r) 
00524 {   return Inertia_<P>(l) -= r; }
00525 
00528 template <class P> inline Inertia_<P>
00529 operator*(const Inertia_<P>& i, const P& r) 
00530 {   return Inertia_<P>(i) *= r; }
00531 
00534 template <class P> inline Inertia_<P>
00535 operator*(const P& r, const Inertia_<P>& i) 
00536 {   return Inertia_<P>(i) *= r; }
00537 
00538 
00542 template <class P> inline Inertia_<P>
00543 operator*(const Inertia_<P>& i, int r) 
00544 {   return Inertia_<P>(i) *= P(r); }
00545 
00549 template <class P> inline Inertia_<P>
00550 operator*(int r, const Inertia_<P>& i) 
00551 {   return Inertia_<P>(i) *= P(r); }
00552 
00556 template <class P> inline Inertia_<P>
00557 operator/(const Inertia_<P>& i, const P& r) 
00558 {   return Inertia_<P>(i) /= r; }
00559 
00563 template <class P> inline Inertia_<P>
00564 operator/(const Inertia_<P>& i, int r) 
00565 {   return Inertia_<P>(i) /= P(r); }
00566 
00570 template <class P> inline Vec<3,P>
00571 operator*(const Inertia_<P>& I, const Vec<3,P>& w) 
00572 {   return I.asSymMat33() * w; }
00573 
00578 template <class P> inline bool
00579 operator==(const Inertia_<P>& i1, const Inertia_<P>& i2) 
00580 {   return i1.asSymMat33() == i2.asSymMat33(); }
00581 
00585 template <class P> inline std::ostream& 
00586 operator<<(std::ostream& o, const Inertia_<P>& inertia)
00587 {   return o << inertia.toMat33(); }
00588 
00589 
00590 // -----------------------------------------------------------------------------
00591 //                             GYRATION MATRIX
00592 // -----------------------------------------------------------------------------
00593 
00605 template <class P>
00606 class SimTK_SimTKCOMMON_EXPORT Gyration_ : public Inertia_<P> {
00607     typedef P               RealP;
00608     typedef Vec<3,P>        Vec3P;
00609     typedef SymMat<3,P>     SymMat33P;
00610     typedef Mat<3,3,P>      Mat33P;
00611     typedef Rotation_<P>    RotationP;
00612     typedef Inertia_<P>     InertiaP;
00613 public:
00616     Gyration_() {}
00617 
00618     // Default copy constructor, copy assignment, destructor.
00619 
00623     explicit Gyration_(const RealP& moment) : InertiaP(moment) {}
00624 
00629     explicit Gyration_(const Vec3P& moments, const Vec3P& products=Vec3P(0))
00630     :   InertiaP(moments,products) {}
00631 
00633     Gyration_(const RealP& xx, const RealP& yy, const RealP& zz)
00634     :   InertiaP(xx,yy,zz) {}   
00635 
00638     Gyration_(const RealP& xx, const RealP& yy, const RealP& zz,
00639               const RealP& xy, const RealP& xz, const RealP& yz)
00640     :   InertiaP(xx,yy,zz,xy,xz,yz) {}
00641 
00644     explicit Gyration_(const SymMat33P& m) : InertiaP(m) {}
00645 
00649     explicit Gyration_(const Mat33P& m) : InertiaP(m) {}
00650 
00655     explicit Gyration_(const Inertia_<P>& I) : InertiaP(I) {}
00656 
00659     Gyration_& setGyration(const RealP& xx, const RealP& yy, const RealP& zz) 
00660     {   InertiaP::setInertia(xx,yy,zz); return *this; }
00661 
00664     Gyration_& setGyration(const Vec3P& moments, const Vec3P& products=Vec3P(0)) 
00665     {   InertiaP::setInertia(moments,products); return *this; }
00666 
00672     Gyration_& setGyration(const RealP& xx, const RealP& yy, const RealP& zz,
00673                            const RealP& xy, const RealP& xz, const RealP& yz) 
00674     {   InertiaP::setInertia(xx,yy,zz,xy,xz,yz); return *this; }
00675 
00676 
00677     // No +=, -=, etc. operators because those don't result in a Gyration matrix.
00678     // The parent class ones are suppressed below.
00679 
00689     Gyration_ shiftToCentroid(const Vec3P& CF) const 
00690     {   Gyration_ G(*this); 
00691         G.Inertia_<P>::operator-=(pointMassAt(CF));
00692         return G; }
00693 
00706     Gyration_& shiftToCentroidInPlace(const Vec3P& CF) 
00707     {   InertiaP::operator-=(pointMassAt(CF));
00708         return *this; }
00709 
00717     Gyration_ shiftFromCentroid(const Vec3P& p) const
00718     {   Gyration_ G(*this); 
00719         G.Inertia_<P>::operator+=(pointMassAt(p));
00720         return G; }
00721 
00730     Gyration_& shiftFromCentroidInPlace(const Vec3P& p)
00731     {   InertiaP::operator+=(pointMassAt(p));
00732         return *this; }
00733 
00744     Gyration_ reexpress(const Rotation_<P>& R_FB) const 
00745     {   return Gyration_((~R_FB).reexpressSymMat33(this->I_OF_F)); }
00746 
00749     Gyration_ reexpress(const InverseRotation_<P>& R_FB) const 
00750     {   return Gyration_((~R_FB).reexpressSymMat33(this->I_OF_F)); }
00751 
00756     Gyration_& reexpressInPlace(const Rotation_<P>& R_FB)
00757     {   InertiaP::reexpressInPlace(R_FB); return *this; }
00758 
00761     Gyration_& reexpressInPlace(const InverseRotation_<P>& R_FB)
00762     {   InertiaP::reexpressInPlace(R_FB); return *this; }
00763 
00764 
00766     operator const SymMat33P&() const {return this->I_OF_F;}
00767 
00771     const Inertia_<P>& asUnitInertia() const 
00772     {   return *static_cast<const Inertia_<P>*>(this); }
00773 
00776     Gyration_& setFromUnitInertia(const Inertia_<P>& I)
00777     {   Inertia_<P>::operator=(I);
00778         return *this; }
00779 
00783     static bool isValidGyrationMatrix(const SymMat33P& m) 
00784     {   return isValidInertiaMatrix(m); }
00785 
00792 
00793 
00796     static Gyration_ pointMassAtOrigin() {return Gyration_(0);}
00797 
00802     static Gyration_ pointMassAt(const Vec3P& p) 
00803     {   return Gyration_(crossMatSq(p)); }
00804 
00807     static Gyration_ sphere(const RealP& r) {return Gyration_(RealP(0.4)*r*r);}
00808 
00811     static Gyration_ cylinderAlongZ(const RealP& r, const RealP& hz) {
00812         const RealP Ixx = (r*r)/4 + (hz*hz)/3;
00813         return Gyration_(Ixx,Ixx,(r*r)/2);
00814     }
00815 
00818     static Gyration_ cylinderAlongY(const RealP& r, const RealP& hy) {
00819         const RealP Ixx = (r*r)/4 + (hy*hy)/3;
00820         return Gyration_(Ixx,(r*r)/2,Ixx);
00821     }
00822 
00825     static Gyration_ cylinderAlongX(const RealP& r, const RealP& hx) {
00826         const RealP Iyy = (r*r)/4 + (hx*hx)/3;
00827         return Gyration_((r*r)/2,Iyy,Iyy);
00828     }
00829 
00833     static Gyration_ brick(const RealP& hx, const RealP& hy, const RealP& hz) {
00834         const RealP oo3 = RealP(1)/RealP(3);
00835         const RealP hx2=hx*hx, hy2=hy*hy, hz2=hz*hz;
00836         return Gyration_(oo3*(hy2+hz2), oo3*(hx2+hz2), oo3*(hx2+hy2));
00837     }
00838 
00840     static Gyration_ brick(const Vec3P& halfLengths)
00841     {   return brick(halfLengths[0],halfLengths[1],halfLengths[2]); }
00842 
00844     static Gyration_ ellipsoid(const RealP& hx, const RealP& hy, const RealP& hz) {
00845         const RealP hx2=hx*hx, hy2=hy*hy, hz2=hz*hz;
00846         return Gyration_((hy2+hz2)/5, (hx2+hz2)/5, (hx2+hy2)/5);
00847     }
00848 
00850     static Gyration_ ellipsoid(const Vec3P& halfLengths)
00851     {   return ellipsoid(halfLengths[0],halfLengths[1],halfLengths[2]); }
00852 
00854 private:
00855     // Suppress Inertia_ methods which are not allowed for Gyration_.
00856 
00857     // These kill all flavors of Inertia_::setInertia() and the
00858     // Inertia_ assignment ops.
00859     void setInertia() {}
00860     void operator+=(int) {}
00861     void operator-=(int) {}
00862     void operator*=(int) {}
00863     void operator/=(int) {}
00864 };
00865 
00866 // Implement Inertia methods which are pass-throughs to Gyration methods.
00867 
00868 template <class P> inline Inertia_<P> Inertia_<P>::
00869 sphere(const RealP& r) 
00870 {   return Gyration_<P>::sphere(r); }
00871 template <class P> inline Inertia_<P> Inertia_<P>::
00872 cylinderAlongZ(const RealP& r, const RealP& hz)
00873 {   return Gyration_<P>::cylinderAlongZ(r,hz); }
00874 template <class P> inline Inertia_<P> Inertia_<P>::
00875 cylinderAlongY(const RealP& r, const RealP& hy)
00876 {   return Gyration_<P>::cylinderAlongY(r,hy); }
00877 template <class P> inline Inertia_<P> Inertia_<P>::
00878 cylinderAlongX(const RealP& r, const RealP& hx)
00879 {   return Gyration_<P>::cylinderAlongX(r,hx); }
00880 template <class P> inline Inertia_<P> Inertia_<P>::
00881 brick(const RealP& hx, const RealP& hy, const RealP& hz)
00882 {   return Gyration_<P>::brick(hx,hy,hz); }
00883 template <class P> inline Inertia_<P> Inertia_<P>::
00884 brick(const Vec3P& halfLengths)
00885 {   return Gyration_<P>::brick(halfLengths); }
00886 template <class P> inline Inertia_<P> Inertia_<P>::
00887 ellipsoid(const RealP& hx, const RealP& hy, const RealP& hz)
00888 {   return Gyration_<P>::ellipsoid(hx,hy,hz); }
00889 template <class P> inline Inertia_<P> Inertia_<P>::
00890 ellipsoid(const Vec3P& halfLengths)
00891 {   return Gyration_<P>::ellipsoid(halfLengths); }
00892 
00893 
00894 // -----------------------------------------------------------------------------
00895 //                           SPATIAL INERTIA MATRIX
00896 // -----------------------------------------------------------------------------
00897 
00925 template <class P> 
00926 class SimTK_SimTKCOMMON_EXPORT SpatialInertia_ {
00927     typedef P               RealP;
00928     typedef Vec<3,P>        Vec3P;
00929     typedef Gyration_<P>    GyrationP;
00930     typedef Mat<3,3,P>      Mat33P;
00931     typedef Rotation_<P>    RotationP;  // TODO: need template argument
00932     typedef Transform_<P>   TransformP; //   "
00933     typedef Inertia_<P>     InertiaP;   //   "
00934 public:
00936     SpatialInertia_() 
00937     :   m(nanP()), p(nanP()) {} // gyration is already NaN
00938     SpatialInertia_(RealP mass, const Vec3P& com, const GyrationP& gyration) 
00939     :   m(mass), p(com), G(gyration) {}
00940 
00941     // default copy constructor, copy assignment, destructor
00942 
00943     SpatialInertia_& setMass(RealP mass)
00944     {   SimTK_ERRCHK1(mass >= 0, "SpatialInertia::setMass()",
00945             "Negative mass %g is illegal.", (double)mass);
00946         m=mass; return *this; }
00947     SpatialInertia_& setMassCenter(const Vec3P& com)
00948     {   p=com; return *this;} 
00949     SpatialInertia_& setGyration(const GyrationP& gyration) 
00950     {   G=gyration; return *this; }
00951 
00952     RealP            getMass()       const {return m;}
00953     const Vec3P&     getMassCenter() const {return p;}
00954     const GyrationP& getGyration()   const {return G;}
00955 
00958     Vec3P calcMassMoment() const {return m*p;}
00959 
00962     InertiaP calcInertia() const {return m*G;}
00963 
00968     SpatialInertia_& operator+=(const SpatialInertia_& src) {
00969         SimTK_ERRCHK(m+src.m != 0, "SpatialInertia::operator+=()",
00970             "The combined mass cannot be zero.");
00971         const RealP mtot = m+src.m, oomtot = 1/mtot;                    // ~11 flops
00972         p = oomtot*(calcMassMoment() + src.calcMassMoment());           // 10 flops
00973         G.setFromUnitInertia(oomtot*(calcInertia()+src.calcInertia())); // 19 flops
00974         m = mtot; // must do this last
00975         return *this;
00976     }
00977 
00982     SpatialInertia_& operator-=(const SpatialInertia_& src) {
00983         SimTK_ERRCHK(m != src.m, "SpatialInertia::operator-=()",
00984             "The combined mass cannot be zero.");
00985         const RealP mtot = m-src.m, oomtot = 1/mtot;                    // ~11 flops
00986         p = oomtot*(calcMassMoment() - src.calcMassMoment());           // 10 flops
00987         G.setFromUnitInertia(oomtot*(calcInertia()-src.calcInertia())); // 19 flops
00988         m = mtot; // must do this last
00989         return *this;
00990     }
00991 
00994     SpatialInertia_& operator*=(const RealP& s) {m *= s; return *this;}
00995 
00998     SpatialInertia_& operator/=(const RealP& s) {m /= s; return *this;}
00999 
01005     SpatialInertia_ reexpress(const Rotation_<P>& R_FB) const
01006     {   return SpatialInertia_(*this).reexpressInPlace(R_FB); }
01007 
01010     SpatialInertia_ reexpress(const InverseRotation_<P>& R_FB) const
01011     {   return SpatialInertia_(*this).reexpressInPlace(R_FB); }
01012 
01017     SpatialInertia_& reexpressInPlace(const Rotation_<P>& R_FB)
01018     {   p = (~R_FB)*p; G.reexpressInPlace(R_FB); return *this; }
01019 
01022     SpatialInertia_& reexpressInPlace(const InverseRotation_<P>& R_FB)
01023     {   p = (~R_FB)*p; G.reexpressInPlace(R_FB); return *this; }
01024 
01029     SpatialInertia_ shift(const Vec3P& S) const 
01030     {   return SpatialInertia_(*this).shiftInPlace(S); }
01031 
01036     SpatialInertia_& shiftInPlace(const Vec3P& S) {
01037         G.shiftToCentroidInPlace(p);    // change to central gyration
01038         G.shiftFromCentroidInPlace(S);  // now gyration is about S
01039         p -= S; // was p=com-OF, now want p'=com-(OF+S)=p-S
01040         return *this;
01041     }
01042 
01051     SpatialInertia_ transform(const Transform_<P>& X_FB) const 
01052     {   return SpatialInertia_(*this).transformInPlace(X_FB); }
01053 
01056     SpatialInertia_ transform(const InverseTransform_<P>& X_FB) const 
01057     {   return SpatialInertia_(*this).transformInPlace(X_FB); }
01058 
01068     SpatialInertia_& transformInPlace(const Transform_<P>& X_FB) {
01069         shiftInPlace(X_FB.p());     // shift to the new origin OB.
01070         reexpressInPlace(X_FB.R()); // get everything in B
01071         return *this;
01072     }
01073 
01076     SpatialInertia_& transformInPlace(const InverseTransform_<P>& X_FB) {
01077         shiftInPlace(X_FB.p());     // shift to the new origin OB.
01078         reexpressInPlace(X_FB.R()); // get everything in B
01079         return *this;
01080     }
01081 
01082 private:
01083     RealP       m;  
01084     Vec3P       p;  
01085     GyrationP   G;  
01086 
01087     static P nanP() {return NTraits<P>::getNaN();} 
01088 };
01089 
01092 template <class P> inline SpatialInertia_<P> 
01093 operator+(const SpatialInertia_<P>& l, const SpatialInertia_<P>& r)
01094 {   return SpatialInertia_<P>(l) += r; } 
01095 
01099 template <class P> inline SpatialInertia_<P> 
01100 operator-(const SpatialInertia_<P>& l, const SpatialInertia_<P>& r)
01101 {   return SpatialInertia_<P>(l) -= r; } 
01102 
01103 
01104 // -----------------------------------------------------------------------------
01105 //                        ARTICULATED BODY INERTIA MATRIX
01106 // -----------------------------------------------------------------------------
01107     
01147 template <class P> 
01148 class ArticulatedInertia_ {
01149     typedef P               RealP;
01150     typedef Vec<3,P>        Vec3P;
01151     typedef Gyration_<P>    GyrationP;
01152     typedef Mat<3,3,P>      Mat33P;
01153     typedef SymMat<3,P>     SymMat33P;
01154     typedef Mat<2,2,Mat33P> SpatialMatP;
01155     typedef Rotation_<P>    RotationP;  // TODO: need template argument
01156     typedef Transform_<P>   TransformP; //   "
01157     typedef Inertia_<P>     InertiaP;   //   "
01158 public:
01159     ArticulatedInertia_() {}
01160     ArticulatedInertia_(const SymMat33P& mass, const Mat33P& massMoment, const SymMat33P& inertia)
01161     :   M(mass), J(inertia), F(massMoment) {}
01162 
01165     explicit ArticulatedInertia_(const SpatialInertia_<P>& rbi)
01166     :   M(rbi.getMass()), J(rbi.calcInertia()), F(crossMat(rbi.calcMassMoment())) {}
01167 
01168     ArticulatedInertia_& setMass      (const SymMat33P& mass)       {M=mass;       return *this;}
01169     ArticulatedInertia_& setMassMoment(const Mat33P&    massMoment) {F=massMoment; return *this;}
01170     ArticulatedInertia_& setInertia   (const SymMat33P& inertia)    {J=inertia;    return *this;}
01171 
01172     const SymMat33P& getMass()       const {return M;}
01173     const Mat33P&    getMassMoment() const {return F;}
01174     const SymMat33P& getInertia()    const {return J;}
01175 
01176     // default destructor, copy constructor, copy assignment
01177 
01178     ArticulatedInertia_& operator+=(const ArticulatedInertia_& src)
01179     {   M+=src.M; J+=src.J; F+=src.F; return *this; }
01180     ArticulatedInertia_& operator-=(const ArticulatedInertia_& src)
01181     {   M-=src.M; J-=src.J; F-=src.F; return *this; }
01182 
01190     SimTK_SimTKCOMMON_EXPORT ArticulatedInertia_ shift(const Vec3P& s) const;
01191 
01194     SimTK_SimTKCOMMON_EXPORT ArticulatedInertia_& shiftInPlace(const Vec3P& s);
01195 
01196     const SpatialMatP toSpatialMat() const {
01197         return SpatialMatP( Mat33P(J),     F,
01198                               ~F,       Mat33P(M) );
01199     }
01200 private:
01201     SymMat33P M;
01202     SymMat33P J;
01203     Mat33P    F;
01204 };
01205 
01206 
01207 // -----------------------------------------------------------------------------
01208 //                              MASS PROPERTIES
01209 // -----------------------------------------------------------------------------
01210    
01216 class SimTK_SimTKCOMMON_EXPORT MassProperties {
01217 public:
01218     MassProperties() { setMassProperties(0.,Vec3(0.),Inertia()); }
01219     MassProperties(const Real& m, const Vec3& com, const Inertia& inertia)
01220       { setMassProperties(m,com,inertia); }
01221 
01224     MassProperties& setMassProperties(const Real& m, const Vec3& com, const Inertia& inertia)
01225       { mass=m; comInB=com; inertia_OB_B=inertia; return *this; }
01226 
01227     const Real&    getMass()       const { return mass; }
01228     const Vec3&    getMassCenter() const { return comInB; }
01229     const Inertia& getInertia()    const { return inertia_OB_B; }
01230 
01231     Inertia calcCentralInertia() const {
01232         return inertia_OB_B - Inertia(comInB, mass);
01233     }
01234     Inertia calcShiftedInertia(const Vec3& newOriginB) const {
01235         return calcCentralInertia() + Inertia(newOriginB-comInB, mass);
01236     }
01237     Inertia calcTransformedInertia(const Transform& X_BC) const {
01238         return calcShiftedInertia(X_BC.p()).reexpress(X_BC.R());
01239     }
01240     MassProperties calcShiftedMassProps(const Vec3& newOriginB) const {
01241         return MassProperties(mass, comInB-newOriginB,
01242                               calcShiftedInertia(newOriginB));
01243     }
01244     // Transform a body's mass properties from the (implicit) B frame
01245     // to a new frame C.
01246     MassProperties calcTransformedMassProps(const Transform& X_BC) const {
01247         return MassProperties(mass, ~X_BC*comInB, calcTransformedInertia(X_BC));
01248     }
01249 
01250     // Re-express these mass properties in frame C. Currently the mass properties
01251     // are expressed in the (implicit) frame B, so we need the Rotation matrix
01252     // that takes us from B to C.
01253     MassProperties reexpress(const Rotation& R_BC) const {
01254         return MassProperties(mass, ~R_BC*comInB, inertia_OB_B.reexpress(R_BC));
01255     }
01256 
01257     bool isExactlyMassless()   const { return mass==0.; }
01258     bool isNearlyMassless(const Real& tol=SignificantReal) const { 
01259         return mass <= tol; 
01260     }
01261 
01262     bool isExactlyCentral() const { return comInB==Vec3(0); }
01263     bool isNearlyCentral(const Real& tol=SignificantReal) const {
01264         return comInB.normSqr() <= tol*tol;
01265     }
01266 
01267     bool isNaN() const {return SimTK::isNaN(mass) || comInB.isNaN() || inertia_OB_B.isNaN();}
01268     bool isInf() const {
01269         if (isNaN()) return false;
01270         return SimTK::isInf(mass) || comInB.isInf() || inertia_OB_B.isInf();
01271     }
01272     bool isFinite() const {
01273         return SimTK::isFinite(mass) && comInB.isFinite() && inertia_OB_B.isFinite();
01274     }
01275 
01276     SpatialMat toSpatialMat() const {
01277         SpatialMat M;
01278         M(0,0) = inertia_OB_B.toMat33();
01279         M(0,1) = mass*crossMat(comInB);
01280         M(1,0) = ~M(0,1);
01281         M(1,1) = mass; // a diagonal matrix
01282         return M;
01283     }
01284 
01287     Mat66 toMat66() const {
01288         Mat66 M;
01289         M.updSubMat<3,3>(0,0) = inertia_OB_B.toMat33();
01290         M.updSubMat<3,3>(0,3) = mass*crossMat(comInB);
01291         M.updSubMat<3,3>(3,0) = ~M.getSubMat<3,3>(0,3);
01292         M.updSubMat<3,3>(3,3) = mass; // a diagonal matrix
01293         return M;
01294     }
01295 
01296 private:
01297     Real     mass;
01298     Vec3     comInB;         // meas. from B origin, expr. in B
01299     Inertia  inertia_OB_B;   // about B origin, expr. in B
01300 };
01301 
01302 SimTK_SimTKCOMMON_EXPORT std::ostream& 
01303 operator<<(std::ostream& o, const MassProperties&);
01304 
01305 } // namespace SimTK
01306 
01307 #endif // SimTK_SIMMATRIX_MASS_PROPERTIES_H_

Generated on Thu Aug 12 16:37:07 2010 for SimTKcore by  doxygen 1.6.1