00001 #ifndef SimTK_SIMMATRIX_MASS_PROPERTIES_H_
00002 #define SimTK_SIMMATRIX_MASS_PROPERTIES_H_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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
00049
00050
00051
00052
00053
00054
00055
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
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
00075
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
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
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;
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;
00413
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;
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
00477
00478
00479
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
00486
00487
00488
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
00505
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
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
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
00678
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
00856
00857
00858
00859 void setInertia() {}
00860 void operator+=(int) {}
00861 void operator-=(int) {}
00862 void operator*=(int) {}
00863 void operator/=(int) {}
00864 };
00865
00866
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
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;
00932 typedef Transform_<P> TransformP;
00933 typedef Inertia_<P> InertiaP;
00934 public:
00936 SpatialInertia_()
00937 : m(nanP()), p(nanP()) {}
00938 SpatialInertia_(RealP mass, const Vec3P& com, const GyrationP& gyration)
00939 : m(mass), p(com), G(gyration) {}
00940
00941
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;
00972 p = oomtot*(calcMassMoment() + src.calcMassMoment());
00973 G.setFromUnitInertia(oomtot*(calcInertia()+src.calcInertia()));
00974 m = mtot;
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;
00986 p = oomtot*(calcMassMoment() - src.calcMassMoment());
00987 G.setFromUnitInertia(oomtot*(calcInertia()-src.calcInertia()));
00988 m = mtot;
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);
01038 G.shiftFromCentroidInPlace(S);
01039 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());
01070 reexpressInPlace(X_FB.R());
01071 return *this;
01072 }
01073
01076 SpatialInertia_& transformInPlace(const InverseTransform_<P>& X_FB) {
01077 shiftInPlace(X_FB.p());
01078 reexpressInPlace(X_FB.R());
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
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;
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
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
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
01245
01246 MassProperties calcTransformedMassProps(const Transform& X_BC) const {
01247 return MassProperties(mass, ~X_BC*comInB, calcTransformedInertia(X_BC));
01248 }
01249
01250
01251
01252
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;
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;
01293 return M;
01294 }
01295
01296 private:
01297 Real mass;
01298 Vec3 comInB;
01299 Inertia inertia_OB_B;
01300 };
01301
01302 SimTK_SimTKCOMMON_EXPORT std::ostream&
01303 operator<<(std::ostream& o, const MassProperties&);
01304
01305 }
01306
01307 #endif // SimTK_SIMMATRIX_MASS_PROPERTIES_H_