Simbody

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-11 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 {
00058 typedef Vec<2,   Vec3>              SpatialVec;
00061 typedef Vec<2,   Vec<3,float> >    fSpatialVec;
00064 typedef Vec<2,   Vec<3,double> >   dSpatialVec;
00065 
00068 typedef Row<2,   Row3>              SpatialRow;
00071 typedef Row<2,   Row<3,float> >    fSpatialRow;
00074 typedef Row<2,   Row<3,double> >   dSpatialRow;
00075 
00080 typedef Mat<2,2, Mat33>             SpatialMat;
00083 typedef Mat<2,2, Mat<3,3,float> >  fSpatialMat;
00086 typedef Mat<2,2, Mat<3,3,double> > dSpatialMat;
00087 
00088 // These are templatized by precision (float or double).
00089 template <class P> class UnitInertia_;
00090 template <class P> class Inertia_;
00091 template <class P> class SpatialInertia_;
00092 template <class P> class ArticulatedInertia_;
00093 template <class P> class MassProperties_;
00094 
00095 // The "no trailing underscore" typedefs use whatever the 
00096 // compile-time precision is set to.
00097 
00099 typedef UnitInertia_<Real>          UnitInertia;
00101 typedef UnitInertia_<float>        fUnitInertia;
00103 typedef UnitInertia_<double>       dUnitInertia;
00104 
00106 typedef Inertia_<Real>              Inertia;
00108 typedef Inertia_<float>            fInertia;
00110 typedef Inertia_<double>           dInertia;
00111 
00113 typedef MassProperties_<Real>       MassProperties;
00115 typedef MassProperties_<float>     fMassProperties;
00117 typedef MassProperties_<double>    dMassProperties;
00118 
00120 typedef SpatialInertia_<Real>       SpatialInertia;
00122 typedef SpatialInertia_<float>     fSpatialInertia;
00124 typedef SpatialInertia_<double>    dSpatialInertia;
00125 
00127 typedef ArticulatedInertia_<Real>    ArticulatedInertia;
00129 typedef ArticulatedInertia_<float>  fArticulatedInertia;
00131 typedef ArticulatedInertia_<double> dArticulatedInertia;
00132 
00134 typedef UnitInertia  Gyration;
00135 
00136 // -----------------------------------------------------------------------------
00137 //                             INERTIA MATRIX
00138 // -----------------------------------------------------------------------------
00200 template <class P>
00201 class SimTK_SimTKCOMMON_EXPORT Inertia_ {
00202     typedef P               RealP;
00203     typedef Vec<3,P>        Vec3P;
00204     typedef SymMat<3,P>     SymMat33P;
00205     typedef Mat<3,3,P>      Mat33P;
00206     typedef Rotation_<P>    RotationP;
00207 public:
00210 Inertia_() : I_OF_F(NTraits<P>::getNaN()) {}
00211 
00212 // Default copy constructor, copy assignment, destructor.
00213 
00220 explicit Inertia_(const RealP& moment) : I_OF_F(moment) 
00221 {   errChk("Inertia::Inertia(moment)"); }
00222 
00226 Inertia_(const Vec3P& p, const RealP& mass) : I_OF_F(pointMassAt(p,mass)) {}
00227 
00232 explicit Inertia_(const Vec3P& moments, const Vec3P& products=Vec3P(0)) 
00233 {   I_OF_F.updDiag()  = moments;
00234     I_OF_F.updLower() = products;
00235     errChk("Inertia::Inertia(moments,products)"); }
00236 
00238 Inertia_(const RealP& xx, const RealP& yy, const RealP& zz) 
00239 {   I_OF_F = SymMat33P(xx,
00240                         0, yy,
00241                         0,  0, zz);
00242     errChk("Inertia::setInertia(xx,yy,zz)"); }
00243 
00246 Inertia_(const RealP& xx, const RealP& yy, const RealP& zz,
00247             const RealP& xy, const RealP& xz, const RealP& yz) 
00248 {   I_OF_F = SymMat33P(xx,
00249                         xy, yy,
00250                         xz, yz, zz);
00251     errChk("Inertia::setInertia(xx,yy,zz,xy,xz,yz)"); }
00252 
00255 explicit Inertia_(const SymMat33P& I) : I_OF_F(I) 
00256 {   errChk("Inertia::Inertia(SymMat33)"); }
00257 
00261 explicit Inertia_(const Mat33P& m)
00262 {   SimTK_ERRCHK(m.isNumericallySymmetric(), 
00263                     "Inertia(Mat33)", "The supplied matrix was not symmetric.");
00264     I_OF_F = SymMat33P(m);
00265     errChk("Inertia(Mat33)"); }
00266 
00267 
00270 Inertia_& setInertia(const RealP& xx, const RealP& yy, const RealP& zz) {
00271     I_OF_F = RealP(0); I_OF_F(0,0) = xx; I_OF_F(1,1) = yy;  I_OF_F(2,2) = zz;
00272     errChk("Inertia::setInertia(xx,yy,zz)");
00273     return *this;
00274 }
00275 
00278 Inertia_& setInertia(const Vec3P& moments, const Vec3P& products=Vec3P(0)) {
00279     I_OF_F.updDiag()  = moments;
00280     I_OF_F.updLower() = products;
00281     errChk("Inertia::setInertia(moments,products)");
00282     return *this;
00283 }
00284 
00290 Inertia_& setInertia(const RealP& xx, const RealP& yy, const RealP& zz,
00291                         const RealP& xy, const RealP& xz, const RealP& yz) {
00292     setInertia(Vec3P(xx,yy,zz), Vec3P(xy,xz,yz));
00293     errChk("Inertia::setInertia(xx,yy,zz,xy,xz,yz)");
00294     return *this;
00295 }
00296 
00297 
00300 Inertia_& operator+=(const Inertia_& I) 
00301 {   I_OF_F += I.I_OF_F; 
00302     errChk("Inertia::operator+=()");
00303     return *this; }
00304 
00307 Inertia_& operator-=(const Inertia_& I) 
00308 {   I_OF_F -= I.I_OF_F; 
00309     errChk("Inertia::operator-=()");
00310     return *this; }
00311 
00313 Inertia_& operator*=(const P& s) {I_OF_F *= s; return *this;}
00314 
00317 Inertia_& operator/=(const P& s) {I_OF_F /= s; return *this;}
00318 
00328 Inertia_ shiftToMassCenter(const Vec3P& CF, const RealP& mass) const 
00329 {   Inertia_ I(*this); I -= pointMassAt(CF, mass);
00330     I.errChk("Inertia::shiftToMassCenter()");
00331     return I; }
00332 
00343 Inertia_& shiftToMassCenterInPlace(const Vec3P& CF, const RealP& mass) 
00344 {   (*this) -= pointMassAt(CF, mass);
00345     errChk("Inertia::shiftToMassCenterInPlace()");
00346     return *this; }
00347 
00355 Inertia_ shiftFromMassCenter(const Vec3P& p, const RealP& mass) const
00356 {   Inertia_ I(*this); I += pointMassAt(p, mass);
00357     I.errChk("Inertia::shiftFromMassCenter()");
00358     return I; }
00359 
00368 Inertia_& shiftFromMassCenterInPlace(const Vec3P& p, const RealP& mass)
00369 {   (*this) += pointMassAt(p, mass);
00370     errChk("Inertia::shiftFromMassCenterInPlace()");
00371     return *this; }
00372 
00383 Inertia_ reexpress(const Rotation_<P>& R_FB) const 
00384 {   return Inertia_((~R_FB).reexpressSymMat33(I_OF_F)); }
00385 
00388 Inertia_ reexpress(const InverseRotation_<P>& R_FB) const 
00389 {   return Inertia_((~R_FB).reexpressSymMat33(I_OF_F)); }
00390 
00395 Inertia_& reexpressInPlace(const Rotation_<P>& R_FB)
00396 {   I_OF_F = (~R_FB).reexpressSymMat33(I_OF_F); return *this; }
00397 
00400 Inertia_& reexpressInPlace(const InverseRotation_<P>& R_FB)
00401 {   I_OF_F = (~R_FB).reexpressSymMat33(I_OF_F); return *this; }
00402 
00403 RealP trace() const {return I_OF_F.trace();}
00404 
00406 operator const SymMat33P&() const {return I_OF_F;}
00407 
00409 const SymMat33P& asSymMat33() const {return I_OF_F;}
00410 
00413 Mat33P toMat33() const {return Mat33P(I_OF_F);}
00414 
00416 const Vec3P& getMoments()  const {return I_OF_F.getDiag();}
00419 const Vec3P& getProducts() const {return I_OF_F.getLower();}
00420 
00421 bool isNaN()    const {return I_OF_F.isNaN();}
00422 bool isInf()    const {return I_OF_F.isInf();}
00423 bool isFinite() const {return I_OF_F.isFinite();}
00424 
00428 bool isNumericallyEqual(const Inertia_<P>& other) const 
00429 {   return I_OF_F.isNumericallyEqual(other.I_OF_F); }
00430 
00434 bool isNumericallyEqual(const Inertia_<P>& other, double tol) const 
00435 {   return I_OF_F.isNumericallyEqual(other.I_OF_F, tol); }
00436 
00440 static bool isValidInertiaMatrix(const SymMat33P& m) {
00441     const RealP Slop = NTraits<P>::getSignificant();
00442     if (m.isNaN()) return false;
00443     const Vec3P& d = m.diag();
00444     if (!(d >= 0)) return false; // diagonals must be nonnegative
00445     if (!(d[0]+d[1]+Slop>=d[2] && d[0]+d[2]+Slop>=d[1] && d[1]+d[2]+Slop>=d[0]))
00446         return false; // must satisfy triangle inequality
00447     //TODO: what else?
00448     return true;
00449 }
00450 
00453 static Inertia_ pointMassAtOrigin() {return Inertia_(0);}
00454 
00459 static Inertia_ pointMassAt(const Vec3P& p, const RealP& m) {
00460     const Vec3P mp = m*p;       // 3 flops
00461     const RealP mxx = mp[0]*p[0];
00462     const RealP myy = mp[1]*p[1];
00463     const RealP mzz = mp[2]*p[2];
00464     const RealP nmx = -mp[0];
00465     const RealP nmy = -mp[1];
00466     return Inertia_( myy+mzz,  mxx+mzz,  mxx+myy,
00467                         nmx*p[1], nmx*p[2], nmy*p[2] );
00468 }
00469 
00475 
00476 
00479 inline static Inertia_ sphere(const RealP& r);
00480 
00483 inline static Inertia_ cylinderAlongZ(const RealP& r, const RealP& hz);
00484 
00487 inline static Inertia_ cylinderAlongY(const RealP& r, const RealP& hy);
00488 
00491 inline static Inertia_ cylinderAlongX(const RealP& r, const RealP& hx);
00492 
00496 inline static Inertia_ brick(const RealP& hx, const RealP& hy, const RealP& hz);
00497 
00499 inline static Inertia_ brick(const Vec3P& halfLengths);
00500 
00502 inline static Inertia_ ellipsoid(const RealP& hx, const RealP& hy, const RealP& hz);
00503 
00505 inline static Inertia_ ellipsoid(const Vec3P& halfLengths);
00506 
00508 
00509 protected:
00510 // Reinterpret this Inertia matrix as a UnitInertia matrix, that is, as the
00511 // inertia of something with unit mass. This is useful in implementing
00512 // methods of the UnitInertia class in terms of Inertia methods. Be sure you
00513 // know that this is a unit-mass inertia!
00514 const UnitInertia_<P>& getAsUnitInertia() const
00515 {   return *reinterpret_cast<const UnitInertia_<P>*>(this); }
00516 UnitInertia_<P>& updAsUnitInertia()
00517 {   return *reinterpret_cast<UnitInertia_<P>*>(this); }
00518 
00519 // If error checking is enabled (typically only in Debug mode), this 
00520 // method will run some tests on the current contents of this Inertia 
00521 // matrix and throw an error message if it is not valid. This should be 
00522 // the same set of tests as run by the isValidInertiaMatrix() method above.
00523 void errChk(const char* methodName) const {
00524     const RealP Slop = NTraits<P>::getSignificant();
00525     SimTK_ERRCHK(!isNaN(), methodName,
00526         "Inertia matrix contains a NaN.");
00527     const Vec3P& d = I_OF_F.diag();
00528     SimTK_ERRCHK3(d >= 0, methodName,
00529         "Diagonals of an Inertia matrix must be nonnegative; got %g,%g,%g.",
00530         (double)d[0],(double)d[1],(double)d[2]);
00531     SimTK_ERRCHK3(d[0]+d[1]+Slop>=d[2] && d[0]+d[2]+Slop>=d[1] && d[1]+d[2]+Slop>=d[0],
00532         methodName,
00533         "Diagonals of an Inertia matrix must satisfy the triangle "
00534         "inequality; got %g,%g,%g.",
00535         (double)d[0],(double)d[1],(double)d[2]);
00536 }
00537 
00538 // Inertia expressed in frame F and about F's origin OF. Note that frame F
00539 // is implicit here; all we actually have are the inertia scalars.
00540 SymMat33P I_OF_F; 
00541 };
00542 
00547 template <class P> inline Inertia_<P>
00548 operator+(const Inertia_<P>& l, const Inertia_<P>& r) 
00549 {   return Inertia_<P>(l) += r; }
00550 
00556 template <class P> inline Inertia_<P>
00557 operator-(const Inertia_<P>& l, const Inertia_<P>& r) 
00558 {   return Inertia_<P>(l) -= r; }
00559 
00562 template <class P> inline Inertia_<P>
00563 operator*(const Inertia_<P>& i, const P& r) 
00564 {   return Inertia_<P>(i) *= r; }
00565 
00568 template <class P> inline Inertia_<P>
00569 operator*(const P& r, const Inertia_<P>& i) 
00570 {   return Inertia_<P>(i) *= r; }
00571 
00572 
00576 template <class P> inline Inertia_<P>
00577 operator*(const Inertia_<P>& i, int r) 
00578 {   return Inertia_<P>(i) *= P(r); }
00579 
00583 template <class P> inline Inertia_<P>
00584 operator*(int r, const Inertia_<P>& i) 
00585 {   return Inertia_<P>(i) *= P(r); }
00586 
00590 template <class P> inline Inertia_<P>
00591 operator/(const Inertia_<P>& i, const P& r) 
00592 {   return Inertia_<P>(i) /= r; }
00593 
00597 template <class P> inline Inertia_<P>
00598 operator/(const Inertia_<P>& i, int r) 
00599 {   return Inertia_<P>(i) /= P(r); }
00600 
00604 template <class P> inline Vec<3,P>
00605 operator*(const Inertia_<P>& I, const Vec<3,P>& w) 
00606 {   return I.asSymMat33() * w; }
00607 
00612 template <class P> inline bool
00613 operator==(const Inertia_<P>& i1, const Inertia_<P>& i2) 
00614 {   return i1.asSymMat33() == i2.asSymMat33(); }
00615 
00619 template <class P> inline std::ostream& 
00620 operator<<(std::ostream& o, const Inertia_<P>& inertia)
00621 {   return o << inertia.toMat33(); }
00622 
00623 
00624 // -----------------------------------------------------------------------------
00625 //                            UNIT INERTIA MATRIX
00626 // -----------------------------------------------------------------------------
00647 template <class P>
00648 class SimTK_SimTKCOMMON_EXPORT UnitInertia_ : public Inertia_<P> {
00649     typedef P               RealP;
00650     typedef Vec<3,P>        Vec3P;
00651     typedef SymMat<3,P>     SymMat33P;
00652     typedef Mat<3,3,P>      Mat33P;
00653     typedef Rotation_<P>    RotationP;
00654     typedef Inertia_<P>     InertiaP;
00655 public:
00658 UnitInertia_() {}
00659 
00660 // Default copy constructor, copy assignment, destructor.
00661 
00665 explicit UnitInertia_(const RealP& moment) : InertiaP(moment) {}
00666 
00671 explicit UnitInertia_(const Vec3P& moments, const Vec3P& products=Vec3P(0))
00672 :   InertiaP(moments,products) {}
00673 
00675 UnitInertia_(const RealP& xx, const RealP& yy, const RealP& zz)
00676 :   InertiaP(xx,yy,zz) {}   
00677 
00680 UnitInertia_(const RealP& xx, const RealP& yy, const RealP& zz,
00681             const RealP& xy, const RealP& xz, const RealP& yz)
00682 :   InertiaP(xx,yy,zz,xy,xz,yz) {}
00683 
00686 explicit UnitInertia_(const SymMat33P& m) : InertiaP(m) {}
00687 
00691 explicit UnitInertia_(const Mat33P& m) : InertiaP(m) {}
00692 
00697 explicit UnitInertia_(const Inertia_<P>& I) : InertiaP(I) {}
00698 
00702 UnitInertia_& setUnitInertia(const RealP& xx, const RealP& yy, const RealP& zz) 
00703 {   InertiaP::setInertia(xx,yy,zz); return *this; }
00704 
00707 UnitInertia_& setUnitInertia(const Vec3P& moments, const Vec3P& products=Vec3P(0)) 
00708 {   InertiaP::setInertia(moments,products); return *this; }
00709 
00715 UnitInertia_& setUnitInertia(const RealP& xx, const RealP& yy, const RealP& zz,
00716                         const RealP& xy, const RealP& xz, const RealP& yz) 
00717 {   InertiaP::setInertia(xx,yy,zz,xy,xz,yz); return *this; }
00718 
00719 
00720 // No +=, -=, etc. operators because those don't result in a UnitInertia 
00721 // matrix. The parent class ones are suppressed below.
00722 
00732 UnitInertia_ shiftToCentroid(const Vec3P& CF) const 
00733 {   UnitInertia_ G(*this); 
00734     G.Inertia_<P>::operator-=(pointMassAt(CF));
00735     return G; }
00736 
00749 UnitInertia_& shiftToCentroidInPlace(const Vec3P& CF) 
00750 {   InertiaP::operator-=(pointMassAt(CF));
00751     return *this; }
00752 
00760 UnitInertia_ shiftFromCentroid(const Vec3P& p) const
00761 {   UnitInertia_ G(*this); 
00762     G.Inertia_<P>::operator+=(pointMassAt(p));
00763     return G; }
00764 
00773 UnitInertia_& shiftFromCentroidInPlace(const Vec3P& p)
00774 {   InertiaP::operator+=(pointMassAt(p));
00775     return *this; }
00776 
00787 UnitInertia_ reexpress(const Rotation_<P>& R_FB) const 
00788 {   return UnitInertia_((~R_FB).reexpressSymMat33(this->I_OF_F)); }
00789 
00792 UnitInertia_ reexpress(const InverseRotation_<P>& R_FB) const 
00793 {   return UnitInertia_((~R_FB).reexpressSymMat33(this->I_OF_F)); }
00794 
00799 UnitInertia_& reexpressInPlace(const Rotation_<P>& R_FB)
00800 {   InertiaP::reexpressInPlace(R_FB); return *this; }
00801 
00804 UnitInertia_& reexpressInPlace(const InverseRotation_<P>& R_FB)
00805 {   InertiaP::reexpressInPlace(R_FB); return *this; }
00806 
00807 
00809 operator const SymMat33P&() const {return this->I_OF_F;}
00810 
00814 const Inertia_<P>& asUnitInertia() const 
00815 {   return *static_cast<const Inertia_<P>*>(this); }
00816 
00819 UnitInertia_& setFromUnitInertia(const Inertia_<P>& I)
00820 {   Inertia_<P>::operator=(I);
00821     return *this; }
00822 
00826 static bool isValidUnitInertiaMatrix(const SymMat33P& m) 
00827 {   return isValidInertiaMatrix(m); }
00828 
00835 
00836 
00839 static UnitInertia_ pointMassAtOrigin() {return UnitInertia_(0);}
00840 
00845 static UnitInertia_ pointMassAt(const Vec3P& p) 
00846 {   return UnitInertia_(crossMatSq(p)); }
00847 
00850 static UnitInertia_ sphere(const RealP& r) {return UnitInertia_(RealP(0.4)*r*r);}
00851 
00854 static UnitInertia_ cylinderAlongZ(const RealP& r, const RealP& hz) {
00855     const RealP Ixx = (r*r)/4 + (hz*hz)/3;
00856     return UnitInertia_(Ixx,Ixx,(r*r)/2);
00857 }
00858 
00861 static UnitInertia_ cylinderAlongY(const RealP& r, const RealP& hy) {
00862     const RealP Ixx = (r*r)/4 + (hy*hy)/3;
00863     return UnitInertia_(Ixx,(r*r)/2,Ixx);
00864 }
00865 
00868 static UnitInertia_ cylinderAlongX(const RealP& r, const RealP& hx) {
00869     const RealP Iyy = (r*r)/4 + (hx*hx)/3;
00870     return UnitInertia_((r*r)/2,Iyy,Iyy);
00871 }
00872 
00876 static UnitInertia_ brick(const RealP& hx, const RealP& hy, const RealP& hz) {
00877     const RealP oo3 = RealP(1)/RealP(3);
00878     const RealP hx2=hx*hx, hy2=hy*hy, hz2=hz*hz;
00879     return UnitInertia_(oo3*(hy2+hz2), oo3*(hx2+hz2), oo3*(hx2+hy2));
00880 }
00881 
00883 static UnitInertia_ brick(const Vec3P& halfLengths)
00884 {   return brick(halfLengths[0],halfLengths[1],halfLengths[2]); }
00885 
00887 static UnitInertia_ ellipsoid(const RealP& hx, const RealP& hy, const RealP& hz) {
00888     const RealP hx2=hx*hx, hy2=hy*hy, hz2=hz*hz;
00889     return UnitInertia_((hy2+hz2)/5, (hx2+hz2)/5, (hx2+hy2)/5);
00890 }
00891 
00893 static UnitInertia_ ellipsoid(const Vec3P& halfLengths)
00894 {   return ellipsoid(halfLengths[0],halfLengths[1],halfLengths[2]); }
00895 
00897 private:
00898 // Suppress Inertia_ methods which are not allowed for UnitInertia_.
00899 
00900 // These kill all flavors of Inertia_::setInertia() and the
00901 // Inertia_ assignment ops.
00902 void setInertia() {}
00903 void operator+=(int) {}
00904 void operator-=(int) {}
00905 void operator*=(int) {}
00906 void operator/=(int) {}
00907 };
00908 
00909 // Implement Inertia methods which are pass-throughs to UnitInertia methods.
00910 
00911 template <class P> inline Inertia_<P> Inertia_<P>::
00912 sphere(const RealP& r) 
00913 {   return UnitInertia_<P>::sphere(r); }
00914 template <class P> inline Inertia_<P> Inertia_<P>::
00915 cylinderAlongZ(const RealP& r, const RealP& hz)
00916 {   return UnitInertia_<P>::cylinderAlongZ(r,hz); }
00917 template <class P> inline Inertia_<P> Inertia_<P>::
00918 cylinderAlongY(const RealP& r, const RealP& hy)
00919 {   return UnitInertia_<P>::cylinderAlongY(r,hy); }
00920 template <class P> inline Inertia_<P> Inertia_<P>::
00921 cylinderAlongX(const RealP& r, const RealP& hx)
00922 {   return UnitInertia_<P>::cylinderAlongX(r,hx); }
00923 template <class P> inline Inertia_<P> Inertia_<P>::
00924 brick(const RealP& hx, const RealP& hy, const RealP& hz)
00925 {   return UnitInertia_<P>::brick(hx,hy,hz); }
00926 template <class P> inline Inertia_<P> Inertia_<P>::
00927 brick(const Vec3P& halfLengths)
00928 {   return UnitInertia_<P>::brick(halfLengths); }
00929 template <class P> inline Inertia_<P> Inertia_<P>::
00930 ellipsoid(const RealP& hx, const RealP& hy, const RealP& hz)
00931 {   return UnitInertia_<P>::ellipsoid(hx,hy,hz); }
00932 template <class P> inline Inertia_<P> Inertia_<P>::
00933 ellipsoid(const Vec3P& halfLengths)
00934 {   return UnitInertia_<P>::ellipsoid(halfLengths); }
00935 
00936 
00937 // -----------------------------------------------------------------------------
00938 //                           SPATIAL INERTIA MATRIX
00939 // -----------------------------------------------------------------------------
00971 template <class P> 
00972 class SimTK_SimTKCOMMON_EXPORT SpatialInertia_ {
00973     typedef P               RealP;
00974     typedef Vec<3,P>        Vec3P;
00975     typedef UnitInertia_<P> UnitInertiaP;
00976     typedef Mat<3,3,P>      Mat33P;
00977     typedef Rotation_<P>    RotationP;
00978     typedef Transform_<P>   TransformP;
00979     typedef Inertia_<P>     InertiaP;
00980 public:
00982 SpatialInertia_() 
00983 :   m(nanP()), p(nanP()) {} // inertia is already NaN
00984 SpatialInertia_(RealP mass, const Vec3P& com, const UnitInertiaP& gyration) 
00985 :   m(mass), p(com), G(gyration) {}
00986 
00987 // default copy constructor, copy assignment, destructor
00988 
00989 SpatialInertia_& setMass(RealP mass)
00990 {   SimTK_ERRCHK1(mass >= 0, "SpatialInertia::setMass()",
00991         "Negative mass %g is illegal.", (double)mass);
00992     m=mass; return *this; }
00993 SpatialInertia_& setMassCenter(const Vec3P& com)
00994 {   p=com; return *this;} 
00995 SpatialInertia_& setUnitInertia(const UnitInertiaP& gyration) 
00996 {   G=gyration; return *this; }
00997 
00998 RealP            getMass()       const {return m;}
00999 const Vec3P&     getMassCenter() const {return p;}
01000 const UnitInertiaP& getUnitInertia()   const {return G;}
01001 
01004 Vec3P calcMassMoment() const {return m*p;}
01005 
01008 InertiaP calcInertia() const {return m*G;}
01009 
01014 SpatialInertia_& operator+=(const SpatialInertia_& src) {
01015     SimTK_ERRCHK(m+src.m != 0, "SpatialInertia::operator+=()",
01016         "The combined mass cannot be zero.");
01017     const RealP mtot = m+src.m, oomtot = 1/mtot;                    // ~11 flops
01018     p = oomtot*(calcMassMoment() + src.calcMassMoment());           // 10 flops
01019     G.setFromUnitInertia(oomtot*(calcInertia()+src.calcInertia())); // 19 flops
01020     m = mtot; // must do this last
01021     return *this;
01022 }
01023 
01028 SpatialInertia_& operator-=(const SpatialInertia_& src) {
01029     SimTK_ERRCHK(m != src.m, "SpatialInertia::operator-=()",
01030         "The combined mass cannot be zero.");
01031     const RealP mtot = m-src.m, oomtot = 1/mtot;                    // ~11 flops
01032     p = oomtot*(calcMassMoment() - src.calcMassMoment());           // 10 flops
01033     G.setFromUnitInertia(oomtot*(calcInertia()-src.calcInertia())); // 19 flops
01034     m = mtot; // must do this last
01035     return *this;
01036 }
01037 
01040 SpatialInertia_& operator*=(const RealP& s) {m *= s; return *this;}
01041 
01044 SpatialInertia_& operator/=(const RealP& s) {m /= s; return *this;}
01045 
01051 SpatialInertia_ reexpress(const Rotation_<P>& R_FB) const
01052 {   return SpatialInertia_(*this).reexpressInPlace(R_FB); }
01053 
01056 SpatialInertia_ reexpress(const InverseRotation_<P>& R_FB) const
01057 {   return SpatialInertia_(*this).reexpressInPlace(R_FB); }
01058 
01063 SpatialInertia_& reexpressInPlace(const Rotation_<P>& R_FB)
01064 {   p = (~R_FB)*p; G.reexpressInPlace(R_FB); return *this; }
01065 
01068 SpatialInertia_& reexpressInPlace(const InverseRotation_<P>& R_FB)
01069 {   p = (~R_FB)*p; G.reexpressInPlace(R_FB); return *this; }
01070 
01075 SpatialInertia_ shift(const Vec3P& S) const 
01076 {   return SpatialInertia_(*this).shiftInPlace(S); }
01077 
01082 SpatialInertia_& shiftInPlace(const Vec3P& S) {
01083     G.shiftToCentroidInPlace(p);    // change to central inertia
01084     G.shiftFromCentroidInPlace(S);  // now inertia is about S
01085     p -= S; // was p=com-OF, now want p'=com-(OF+S)=p-S
01086     return *this;
01087 }
01088 
01097 SpatialInertia_ transform(const Transform_<P>& X_FB) const 
01098 {   return SpatialInertia_(*this).transformInPlace(X_FB); }
01099 
01102 SpatialInertia_ transform(const InverseTransform_<P>& X_FB) const 
01103 {   return SpatialInertia_(*this).transformInPlace(X_FB); }
01104 
01114 SpatialInertia_& transformInPlace(const Transform_<P>& X_FB) {
01115     shiftInPlace(X_FB.p());     // shift to the new origin OB.
01116     reexpressInPlace(X_FB.R()); // get everything in B
01117     return *this;
01118 }
01119 
01122 SpatialInertia_& transformInPlace(const InverseTransform_<P>& X_FB) {
01123     shiftInPlace(X_FB.p());     // shift to the new origin OB.
01124     reexpressInPlace(X_FB.R()); // get everything in B
01125     return *this;
01126 }
01127 
01128 private:
01129 RealP           m;  // mass of this rigid body F
01130 Vec3P           p;  // location of body's COM from OF, expressed in F
01131 UnitInertiaP    G;  // mass distribution; inertia is mass*gyration
01132 
01133 static P nanP() {return NTraits<P>::getNaN();} 
01134 };
01135 
01138 template <class P> inline SpatialInertia_<P> 
01139 operator+(const SpatialInertia_<P>& l, const SpatialInertia_<P>& r)
01140 {   return SpatialInertia_<P>(l) += r; } 
01141 
01145 template <class P> inline SpatialInertia_<P> 
01146 operator-(const SpatialInertia_<P>& l, const SpatialInertia_<P>& r)
01147 {   return SpatialInertia_<P>(l) -= r; } 
01148 
01149 
01150 // -----------------------------------------------------------------------------
01151 //                        ARTICULATED BODY INERTIA MATRIX
01152 // -----------------------------------------------------------------------------
01199 template <class P> 
01200 class ArticulatedInertia_ {
01201     typedef P               RealP;
01202     typedef Vec<3,P>        Vec3P;
01203     typedef UnitInertia_<P>    UnitInertiaP;
01204     typedef Mat<3,3,P>      Mat33P;
01205     typedef SymMat<3,P>     SymMat33P;
01206     typedef Mat<2,2,Mat33P> SpatialMatP;
01207     typedef Rotation_<P>    RotationP;
01208     typedef Transform_<P>   TransformP;
01209     typedef Inertia_<P>     InertiaP;
01210 public:
01211 ArticulatedInertia_() {}
01212 ArticulatedInertia_(const SymMat33P& mass, const Mat33P& massMoment, const SymMat33P& inertia)
01213 :   M(mass), J(inertia), F(massMoment) {}
01214 
01217 explicit ArticulatedInertia_(const SpatialInertia_<P>& rbi)
01218 :   M(rbi.getMass()), J(rbi.calcInertia()), F(crossMat(rbi.calcMassMoment())) {}
01219 
01220 ArticulatedInertia_& setMass      (const SymMat33P& mass)       {M=mass;       return *this;}
01221 ArticulatedInertia_& setMassMoment(const Mat33P&    massMoment) {F=massMoment; return *this;}
01222 ArticulatedInertia_& setInertia   (const SymMat33P& inertia)    {J=inertia;    return *this;}
01223 
01224 const SymMat33P& getMass()       const {return M;}
01225 const Mat33P&    getMassMoment() const {return F;}
01226 const SymMat33P& getInertia()    const {return J;}
01227 
01228 // default destructor, copy constructor, copy assignment
01229 
01230 ArticulatedInertia_& operator+=(const ArticulatedInertia_& src)
01231 {   M+=src.M; J+=src.J; F+=src.F; return *this; }
01232 ArticulatedInertia_& operator-=(const ArticulatedInertia_& src)
01233 {   M-=src.M; J-=src.J; F-=src.F; return *this; }
01234 
01242 SimTK_SimTKCOMMON_EXPORT ArticulatedInertia_ shift(const Vec3P& s) const;
01243 
01246 SimTK_SimTKCOMMON_EXPORT ArticulatedInertia_& shiftInPlace(const Vec3P& s);
01247 
01248 const SpatialMatP toSpatialMat() const {
01249     return SpatialMatP( Mat33P(J),     F,
01250                             ~F,       Mat33P(M) );
01251 }
01252 private:
01253 SymMat33P M;
01254 SymMat33P J;
01255 Mat33P    F;
01256 };
01257 
01258 
01259 // -----------------------------------------------------------------------------
01260 //                              MASS PROPERTIES
01261 // -----------------------------------------------------------------------------
01273 template <class P>
01274 class SimTK_SimTKCOMMON_EXPORT MassProperties_ {
01275     typedef P               RealP;
01276     typedef Vec<3,P>        Vec3P;
01277     typedef UnitInertia_<P> UnitInertiaP;
01278     typedef Mat<3,3,P>      Mat33P;
01279     typedef Mat<6,6,P>      Mat66P;
01280     typedef SymMat<3,P>     SymMat33P;
01281     typedef Mat<2,2,Mat33P> SpatialMatP;
01282     typedef Rotation_<P>    RotationP;
01283     typedef Transform_<P>   TransformP;
01284     typedef Inertia_<P>     InertiaP;
01285 public:
01288 MassProperties_() { setMassProperties(0,Vec3P(0),InertiaP()); }
01291 MassProperties_(const RealP& m, const Vec3P& com, const InertiaP& inertia)
01292     { setMassProperties(m,com,inertia); }
01296 MassProperties_(const RealP& m, const Vec3P& com, const UnitInertiaP& gyration)
01297     { setMassProperties(m,com,gyration); }
01298 
01301 MassProperties_& setMassProperties
01302    (const RealP& m, const Vec3P& com, const InertiaP& inertia)
01303 {   mass=m; comInB=com; inertia_OB_B=inertia; return *this; }
01304 
01308 MassProperties_& setMassProperties
01309    (const RealP& m, const Vec3P& com, const UnitInertiaP& gyration)
01310 {   mass=m; comInB=com; inertia_OB_B=m*gyration; return *this; }
01311 
01313 const RealP&    getMass()       const { return mass; }
01318 const Vec3P&    getMassCenter() const { return comInB; }
01323 const InertiaP& getInertia()    const { return inertia_OB_B; }
01324 
01328 InertiaP calcCentralInertia() const {
01329     return inertia_OB_B - InertiaP(comInB, mass);
01330 }
01335 InertiaP calcShiftedInertia(const Vec3P& newOriginB) const {
01336     return calcCentralInertia() + InertiaP(newOriginB-comInB, mass);
01337 }
01342 InertiaP calcTransformedInertia(const TransformP& X_BC) const {
01343     return calcShiftedInertia(X_BC.p()).reexpress(X_BC.R());
01344 }
01350 MassProperties_ calcShiftedMassProps(const Vec3P& newOriginB) const {
01351     return MassProperties_(mass, comInB-newOriginB,
01352                             calcShiftedInertia(newOriginB));
01353 }
01354 
01364 MassProperties_ calcTransformedMassProps(const TransformP& X_BC) const {
01365     return MassProperties_(mass, ~X_BC*comInB, calcTransformedInertia(X_BC));
01366 }
01367 
01376 MassProperties_ reexpress(const RotationP& R_BC) const {
01377     return MassProperties_(mass, ~R_BC*comInB, inertia_OB_B.reexpress(R_BC));
01378 }
01379 
01383 bool isExactlyMassless()   const { return mass==0; }
01389 bool isNearlyMassless(const RealP& tol=SignificantReal) const { 
01390     return mass <= tol; 
01391 }
01392 
01396 bool isExactlyCentral() const { return comInB==Vec3P(0); }
01402 bool isNearlyCentral(const RealP& tol=SignificantReal) const {
01403     return comInB.normSqr() <= tol*tol;
01404 }
01405 
01408 bool isNaN() const {return SimTK::isNaN(mass) || comInB.isNaN() || inertia_OB_B.isNaN();}
01413 bool isInf() const {
01414     if (isNaN()) return false;
01415     return SimTK::isInf(mass) || comInB.isInf() || inertia_OB_B.isInf();
01416 }
01420 bool isFinite() const {
01421     return SimTK::isFinite(mass) && comInB.isFinite() && inertia_OB_B.isFinite();
01422 }
01423 
01427 SpatialMatP toSpatialMat() const {
01428     SpatialMatP M;
01429     M(0,0) = inertia_OB_B.toMat33();
01430     M(0,1) = mass*crossMat(comInB);
01431     M(1,0) = ~M(0,1);
01432     M(1,1) = mass; // a diagonal matrix
01433     return M;
01434 }
01435 
01441 Mat66P toMat66() const {
01442     Mat66P M;
01443     M.template updSubMat<3,3>(0,0) = inertia_OB_B.toMat33();
01444     M.template updSubMat<3,3>(0,3) = mass*crossMat(comInB);
01445     M.template updSubMat<3,3>(3,0) = ~M.template getSubMat<3,3>(0,3);
01446     M.template updSubMat<3,3>(3,3) = mass; // a diagonal matrix
01447     return M;
01448 }
01449 
01450 private:
01451 RealP     mass;
01452 Vec3P     comInB;         // meas. from B origin, expr. in B
01453 InertiaP  inertia_OB_B;   // about B origin, expr. in B
01454 };
01455 
01458 template <class P> static inline std::ostream& 
01459 operator<<(std::ostream& o, const MassProperties_<P>& mp) {
01460     return o << "{ mass=" << mp.getMass() 
01461              << "\n  com=" << mp.getMassCenter()
01462              << "\n  Ixx,yy,zz=" << mp.getInertia().getMoments()
01463              << "\n  Ixy,xz,yz=" << mp.getInertia().getProducts()
01464              << "\n}\n";
01465 }
01466 
01467 } // namespace SimTK
01468 
01469 #endif // SimTK_SIMMATRIX_MASS_PROPERTIES_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines