Simbody  3.4 (development)
MobilizedBody.h
Go to the documentation of this file.
00001 #ifndef SimTK_SIMBODY_MOBILIZED_BODY_H_
00002 #define SimTK_SIMBODY_MOBILIZED_BODY_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                               Simbody(tm)                                  *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK biosimulation toolkit originating from           *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
00011  *                                                                            *
00012  * Portions copyright (c) 2007-13 Stanford University and the Authors.        *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors: Paul Mitiguy, Peter Eastman                                  *
00015  *                                                                            *
00016  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
00017  * not use this file except in compliance with the License. You may obtain a  *
00018  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
00019  *                                                                            *
00020  * Unless required by applicable law or agreed to in writing, software        *
00021  * distributed under the License is distributed on an "AS IS" BASIS,          *
00022  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
00023  * See the License for the specific language governing permissions and        *
00024  * limitations under the License.                                             *
00025  * -------------------------------------------------------------------------- */
00026 
00039 #include "SimTKmath.h"
00040 #include "simbody/internal/common.h"
00041 #include "simbody/internal/Body.h"
00042 #include "simbody/internal/Motion.h"
00043 
00044 #include <cassert>
00045 
00046 namespace SimTK {
00047 
00048 class SimbodyMatterSubsystem;
00049 class Motion;
00050 class MobilizedBody;
00051 class MobilizedBodyImpl;
00052 
00053 // We only want the template instantiation to occur once. This symbol is 
00054 // defined in the SimTK core compilation unit that instantiates the mobilized 
00055 // body class but should not be defined any other time.
00056 #ifndef SimTK_SIMBODY_DEFINING_MOBILIZED_BODY
00057     extern template class PIMPLHandle<MobilizedBody, MobilizedBodyImpl, true>;
00058 #endif
00059 
00063 typedef MobilizedBody Mobod;
00064 
00065 
00066 
00067 //==============================================================================
00068 //                             MOBILIZED BODY
00069 //==============================================================================
00167 class SimTK_SIMBODY_EXPORT MobilizedBody 
00168 :   public PIMPLHandle<MobilizedBody, MobilizedBodyImpl, true> {
00169 public:
00170 
00180 enum Direction {
00181     Forward = 0, 
00182     Reverse = 1  
00183 };
00184 
00185 //------------------------------------------------------------------------------
00219 void lock(State& state, Motion::Level level=Motion::Position) const;
00220 
00229 void lockAt(State& state, Real value, 
00230             Motion::Level level=Motion::Position) const;
00231 
00240 void lockAt(State& state, const Vector& value, 
00241             Motion::Level level=Motion::Position) const;
00242 
00252 template <int N> SimTK_SIMBODY_EXPORT // instantiated in library
00253 void lockAt(State& state, const Vec<N>& value,
00254             Motion::Level level=Motion::Position) const;
00255 
00259 void unlock(State& state) const;
00260 
00262 bool isLocked(const State& state) const 
00263 {   return getLockLevel(state)!=Motion::NoLevel; }
00264 
00267 Motion::Level getLockLevel(const State& state) const;
00268 
00272 Vector getLockValueAsVector(const State& state) const;
00273 
00282 MobilizedBody& lockByDefault(Motion::Level level=Motion::Position);
00283 
00285 bool isLockedByDefault() const 
00286 {   return getLockByDefaultLevel()!=Motion::NoLevel; }
00287 
00290 Motion::Level getLockByDefaultLevel() const;
00293 
00294     // STATE ACCESS METHODS //
00296 
00297 //------------------------------------------------------------------------------
00315 const Transform& getBodyTransform(const State& state) const; // X_GB
00316 
00325 const Rotation& getBodyRotation(const State& state) const {
00326     return getBodyTransform(state).R();
00327 }
00332 const Vec3& getBodyOriginLocation(const State& state) const {
00333     return getBodyTransform(state).p();
00334 }
00335 
00339 const Transform& getMobilizerTransform(const State& state) const;   // X_FM
00340 
00347 const SpatialVec& getBodyVelocity(const State& state) const;        // V_GB
00348 
00353 const Vec3& getBodyAngularVelocity(const State& state) const {      // w_GB
00354     return getBodyVelocity(state)[0]; 
00355 }
00360 const Vec3& getBodyOriginVelocity(const State& state) const {       // v_GB
00361     return getBodyVelocity(state)[1];
00362 }
00363 
00368 const SpatialVec& getMobilizerVelocity(const State& state) const;   // V_FM
00369 
00376 const SpatialVec& getBodyAcceleration(const State& state) const;    // A_GB
00377 
00382 const Vec3& getBodyAngularAcceleration(const State& state) const {  // b_GB
00383     return getBodyAcceleration(state)[0]; 
00384 }
00385 
00390 const Vec3& getBodyOriginAcceleration(const State& state) const {   // a_GB
00391     return getBodyAcceleration(state)[1];
00392 }
00393 
00399 const SpatialVec& getMobilizerAcceleration(const State& state) const { // A_FM
00400     SimTK_ASSERT_ALWAYS(!"unimplemented method", 
00401 "MobilizedBody::getMobilizerAcceleration() not yet implemented -- volunteers?");
00402     return *(new SpatialVec());
00403 }
00404 
00407 const MassProperties& getBodyMassProperties(const State& state) const;
00408 
00412 const SpatialInertia& getBodySpatialInertiaInGround(const State& state) const;
00413 
00416 Real getBodyMass(const State& state) const {
00417     return getBodyMassProperties(state).getMass();
00418 }
00419 
00423 const Vec3& getBodyMassCenterStation(const State& state) const {
00424     return getBodyMassProperties(state).getMassCenter();
00425 }
00426 
00430 const UnitInertia& getBodyUnitInertiaAboutBodyOrigin(const State& state) const {
00431     return getBodyMassProperties(state).getUnitInertia();
00432 }
00433 
00439 const Transform& getInboardFrame (const State& state) const;    // X_PF
00445 const Transform& getOutboardFrame(const State& state) const;    // X_BM
00446 
00450 void setInboardFrame (State& state, const Transform& X_PF) const;
00454 void setOutboardFrame(State& state, const Transform& X_BM) const;
00455 
00456 // End of State Access - Bodies
00460 //------------------------------------------------------------------------------
00467 int getNumQ(const State& state) const;
00470 int getNumU(const State& state) const;
00471 
00474 QIndex getFirstQIndex(const State& state) const;
00475 
00478 UIndex getFirstUIndex(const State& state) const;
00479 
00482 Motion::Method getQMotionMethod(const State& state) const;
00485 Motion::Method getUMotionMethod(const State& state) const;
00488 Motion::Method getUDotMotionMethod(const State& state) const;
00489 
00494 Real getOneQ(const State& state, int which) const;
00495 
00499 Real getOneU(const State& state, int which) const;
00500 
00504 Vector getQAsVector(const State& state) const;
00508 Vector getUAsVector(const State& state) const;
00509 
00514 Real getOneQDot   (const State& state, int which) const;
00518 Vector getQDotAsVector(const State& state) const;
00519 
00524 Real getOneUDot(const State& state, int which) const;
00529 Real getOneQDotDot(const State& state, int which) const;
00533 Vector getUDotAsVector(const State& state) const;
00538 Vector getQDotDotAsVector(const State& state) const;
00539 
00549 Vector getTauAsVector(const State& state) const;
00550 
00555 Real getOneTau(const State& state, MobilizerUIndex which) const;
00556 
00561 void setOneQ(State& state, int which, Real v) const;
00566 void setOneU(State& state, int which, Real v) const;
00567 
00571 void setQFromVector(State& state, const Vector& v) const;
00575 void setUFromVector(State& state, const Vector& v) const;
00576 
00610 void setQToFitTransform(State& state, const Transform& X_FM) const;
00611 
00616 void setQToFitRotation(State& state, const Rotation& R_FM) const;
00617 
00623 void setQToFitTranslation(State& state, const Vec3& p_FM) const;
00624 
00631 void setUToFitVelocity(State& state, const SpatialVec& V_FM) const;
00632 
00637 void setUToFitAngularVelocity(State& state, const Vec3& w_FM) const;
00638 
00644 void setUToFitLinearVelocity(State& state, const Vec3& v_FM) const;
00645 
00655 SpatialVec getHCol(const State& state, MobilizerUIndex ux) const;
00656 
00663 SpatialVec getH_FMCol(const State& state, MobilizerUIndex ux) const;
00664 
00665 // End of State Access Methods.
00668 
00669     // BASIC OPERATORS //
00671 
00672 //------------------------------------------------------------------------------
00716 Transform findBodyTransformInAnotherBody(const State& state, 
00717                                          const MobilizedBody& inBodyA) const
00718 {
00719     const Transform& X_GA = inBodyA.getBodyTransform(state);
00720     const Transform& X_GB = this->getBodyTransform(state);
00721 
00722     return ~X_GA*X_GB; // X_AB=X_AG*X_GB
00723 }
00724 
00730 Rotation findBodyRotationInAnotherBody(const State& state, 
00731                                        const MobilizedBody& inBodyA) const
00732 {
00733     const Rotation& R_GA = inBodyA.getBodyRotation(state);
00734     const Rotation& R_GB = this->getBodyRotation(state);
00735 
00736     return ~R_GA*R_GB; // R_AB=R_AG*R_GB
00737 }
00738 
00745 Vec3 findBodyOriginLocationInAnotherBody
00746    (const State& state, const MobilizedBody& toBodyA) const {   
00747     return toBodyA.findStationAtGroundPoint(state,
00748                                             getBodyOriginLocation(state)); 
00749 }
00750 
00756 SpatialVec findBodyVelocityInAnotherBody
00757    (const State& state, const MobilizedBody& inBodyA) const
00758 {
00759     const SpatialVec& V_GB   = this->getBodyVelocity(state);
00760     const SpatialVec& V_GA   = inBodyA.getBodyVelocity(state);
00761     // angular velocity of B in A, exp in G
00762     const Vec3        w_AB_G = V_GB[0]-V_GA[0];             //  3 flops 
00763 
00764     // Angular vel. was easy, but for linear vel. we have to add in an wXr term.
00765 
00766     const Transform&  X_GB       = getBodyTransform(state);
00767     const Transform&  X_GA       = inBodyA.getBodyTransform(state);
00768     // vector from Ao to Bo, exp in G
00769     const Vec3        p_AB_G     = X_GB.p() - X_GA.p();     //  3 flops
00770     // d/dt p taken in G
00771     const Vec3        p_AB_G_dot = V_GB[1]  - V_GA[1];      //  3 flops
00772 
00773     // d/dt p taken in A, exp in G 
00774     const Vec3 v_AB_G = p_AB_G_dot - V_GA[0] % p_AB_G;      // 12 flops
00775 
00776     // We're done, but answer is expressed in Ground. Reexpress in A and return.
00777     return ~X_GA.R()*SpatialVec(w_AB_G, v_AB_G);            // 30 flops
00778 }
00779 
00785 Vec3 findBodyAngularVelocityInAnotherBody(const State& state,
00786                                           const MobilizedBody& inBodyA) const 
00787 {
00788     const Vec3& w_GB   = getBodyAngularVelocity(state);
00789     const Vec3& w_GA   = inBodyA.getBodyAngularVelocity(state);
00790     // angular velocity of B in A, exp in G
00791     const Vec3  w_AB_G = w_GB-w_GA;                                 //  3 flops
00792 
00793     // Now reexpress in A.
00794     return inBodyA.expressGroundVectorInBodyFrame(state, w_AB_G);   // 15 flops
00795 }
00796 
00802 Vec3 findBodyOriginVelocityInAnotherBody(const State& state,
00803                                          const MobilizedBody& inBodyA) const
00804 {
00805     // Doesn't save much to special case this one.
00806     return findBodyVelocityInAnotherBody(state,inBodyA)[1];
00807 }
00808 
00815 SpatialVec findBodyAccelerationInAnotherBody(const State& state,
00816                                              const MobilizedBody& inBodyA) const
00817 {
00818     const Transform&  X_GA = inBodyA.getBodyTransform(state);
00819     const SpatialVec& V_GA = inBodyA.getBodyVelocity(state);
00820     const SpatialVec& A_GA = inBodyA.getBodyAcceleration(state);
00821     const Transform&  X_GB = this->getBodyTransform(state);
00822     const SpatialVec& V_GB = this->getBodyVelocity(state);
00823     const SpatialVec& A_GB = this->getBodyAcceleration(state);
00824 
00825     return findRelativeAcceleration(X_GA, V_GA, A_GA,
00826                                     X_GB, V_GB, A_GB);
00827 }
00828 
00834 Vec3 findBodyAngularAccelerationInAnotherBody
00835    (const State& state, const MobilizedBody& inBodyA) const
00836 {
00837     const Rotation& R_GA = inBodyA.getBodyRotation(state);
00838     const Vec3&     w_GA = inBodyA.getBodyAngularVelocity(state);
00839     const Vec3&     w_GB = this->getBodyAngularVelocity(state);
00840     const Vec3&     b_GA = inBodyA.getBodyAngularAcceleration(state);
00841     const Vec3&     b_GB = this->getBodyAngularAcceleration(state);
00842 
00843     // relative ang. vel. of B in A, exp. in G
00844     const Vec3 w_AB_G     = w_GB - w_GA; // 3 flops
00845     const Vec3 w_AB_G_dot = b_GB - b_GA; // d/dt of w_AB_G taken in G; 3 flops
00846 
00847     // We have the derivative in G; change it to derivative in A by adding 
00848     // in contribution caused by motion of G in A, that is w_AG X w_AB_G. 
00849     // (Note that w_AG=-w_GA.)
00850     const Vec3 b_AB_G = w_AB_G_dot - w_GA % w_AB_G; // ang. accel. of B in A
00851                                                     // 12 flops
00852 
00853     return ~R_GA * b_AB_G; // taken in A, expressed in A; 15 flops
00854 }
00855 
00862 Vec3 findBodyOriginAccelerationInAnotherBody(const State& state, 
00863                                              const MobilizedBody& inBodyA) const
00864 {
00865     // Not much to be saved by trying to optimize this since the linear part
00866     // is the most expensive to calculate.
00867     return findBodyAccelerationInAnotherBody(state,inBodyA)[1];
00868 }
00869 
00877 SpatialVec findMobilizerReactionOnBodyAtMInGround(const State& state) const;
00878 
00885 SpatialVec findMobilizerReactionOnBodyAtOriginInGround
00886    (const State& state) const;
00887 
00896 SpatialVec findMobilizerReactionOnParentAtFInGround(const State& state) const;
00897 
00905 SpatialVec findMobilizerReactionOnParentAtOriginInGround
00906    (const State& state) const;
00907 
00914 Vec3 findStationLocationInGround
00915    (const State& state, const Vec3& stationOnB) const {
00916     return getBodyTransform(state) * stationOnB;
00917 }
00918 
00919 
00928 Vec3 findStationLocationInAnotherBody
00929    (const State& state, const Vec3& stationOnB, const MobilizedBody& toBodyA) 
00930     const 
00931 {
00932     return toBodyA.findStationAtGroundPoint(state, 
00933                                 findStationLocationInGround(state,stationOnB));
00934 }
00935 
00942 Vec3 findStationVelocityInGround
00943    (const State& state, const Vec3& stationOnB) const {
00944     const Vec3& w = getBodyAngularVelocity(state); // in G
00945     const Vec3& v = getBodyOriginVelocity(state);  // in G
00946     const Vec3  r = expressVectorInGroundFrame(state,stationOnB);   // 15 flops
00947     return v + w % r;                                               // 12 flops
00948 }
00949 
00950 
00956 Vec3 findStationVelocityInAnotherBody(const State&         state, 
00957                                       const Vec3&          stationOnBodyB,//p_BS
00958                                       const MobilizedBody& inBodyA) const
00959 {
00960     const SpatialVec V_AB = 
00961         findBodyVelocityInAnotherBody(state, inBodyA); //51 flops
00962     // Bo->S rexpressed in A but not shifted to Ao
00963     const Vec3 p_BS_A = 
00964         expressVectorInAnotherBodyFrame(state, stationOnBodyB, inBodyA); //30
00965     return V_AB[1] + (V_AB[0] % p_BS_A);                              //12 flops
00966 }
00967 
00968       
00976 Vec3 findStationAccelerationInGround
00977    (const State& state, const Vec3& stationOnB) const {
00978     const Vec3& w = getBodyAngularVelocity(state);     // in G
00979     const Vec3& b = getBodyAngularAcceleration(state); // in G
00980     const Vec3& a = getBodyOriginAcceleration(state);  // in G
00981 
00982     const Vec3  r = expressVectorInGroundFrame(state,stationOnB); // 15 flops
00983     return a + b % r + w % (w % r);                               // 33 flops
00984 }
00985 
00991 Vec3 findStationAccelerationInAnotherBody(const State&         state,
00992                                           const Vec3&          stationOnBodyB, 
00993                                           const MobilizedBody& inBodyA) const 
00994 {
00995     const Vec3       w_AB = 
00996         findBodyAngularVelocityInAnotherBody(state,inBodyA); // 18 flops
00997     const SpatialVec A_AB = 
00998         findBodyAccelerationInAnotherBody(state,inBodyA);    // 105 flops
00999     // Bo->S rexpressed in A but not shifted to Ao
01000     const Vec3       p_BS_A = 
01001         expressVectorInAnotherBodyFrame(state, stationOnBodyB, inBodyA); // 30
01002 
01003     return A_AB[1] + (A_AB[0] % p_BS_A) + w_AB % (w_AB % p_BS_A);    // 33 flops
01004 }
01005 
01009 void findStationLocationAndVelocityInGround
01010    (const State& state, const Vec3& locationOnB,
01011     Vec3& locationOnGround, Vec3& velocityInGround) const
01012 {
01013     const Vec3& p_GB   = getBodyOriginLocation(state);
01014     const Vec3  p_BS_G = expressVectorInGroundFrame(state,locationOnB);//15flops
01015     locationOnGround = p_GB + p_BS_G;                                  // 3flops
01016 
01017     const Vec3& w_GB = getBodyAngularVelocity(state);
01018     const Vec3& v_GB = getBodyOriginVelocity(state);
01019     velocityInGround = v_GB + w_GB % p_BS_G;                         // 12 flops
01020 }
01021 
01022 
01027 void findStationLocationVelocityAndAccelerationInGround
01028    (const State& state, const Vec3& locationOnB,
01029     Vec3& locationOnGround, Vec3& velocityInGround, Vec3& accelerationInGround) 
01030     const
01031 {
01032     const Rotation&  R_GB = getBodyRotation(state);
01033     const Vec3&      p_GB = getBodyOriginLocation(state);
01034 
01035     // re-express station vector p_BS in G
01036     const Vec3 r = R_GB*locationOnB;  // 15 flops
01037     locationOnGround  = p_GB + r;     //  3 flops
01038 
01039     const Vec3& w = getBodyAngularVelocity(state);      // in G
01040     const Vec3& v = getBodyOriginVelocity(state);       // in G
01041     const Vec3& b = getBodyAngularAcceleration(state);  // in G
01042     const Vec3& a = getBodyOriginAcceleration(state);   // in G
01043 
01044     const Vec3 wXr = w % r; // "whipping" velocity w X r due to ang vel; 9 flops
01045     velocityInGround     = v + wXr;                 // v + w X r (3 flops)
01046     accelerationInGround = a + b % r + w % wXr;     // 24 flops
01047 }
01048 
01051 Vec3 findMassCenterLocationInGround(const State& state) const {
01052     return findStationLocationInGround(state,getBodyMassCenterStation(state));
01053 }
01054 
01058 Vec3 findMassCenterLocationInAnotherBody
01059    (const State& state, const MobilizedBody& toBodyA) const {
01060     return findStationLocationInAnotherBody(state,
01061                                     getBodyMassCenterStation(state),toBodyA);
01062 }
01063 
01070 Vec3 findStationAtGroundPoint
01071    (const State& state, const Vec3& locationInG) const {
01072     return ~getBodyTransform(state) * locationInG;
01073 }
01074 
01080 Vec3 findStationAtAnotherBodyStation
01081    (const State& state, const MobilizedBody& fromBodyA, 
01082     const Vec3& stationOnA) const {
01083     return fromBodyA.findStationLocationInAnotherBody(state, stationOnA, *this);
01084 }
01085 
01089 Vec3 findStationAtAnotherBodyOrigin
01090    (const State& state, const MobilizedBody& fromBodyA) const {
01091     return findStationAtGroundPoint(state,
01092                                     fromBodyA.getBodyOriginLocation(state));
01093 }
01094 
01098 Vec3 findStationAtAnotherBodyMassCenter
01099    (const State& state, const MobilizedBody& fromBodyA) const {
01100     return fromBodyA.findStationLocationInAnotherBody(state,
01101                                         getBodyMassCenterStation(state),*this);
01102 }
01103 
01107 Transform findFrameTransformInGround
01108     (const State& state, const Transform& frameOnB) const {
01109     return getBodyTransform(state) * frameOnB;
01110 }
01111 
01117 SpatialVec findFrameVelocityInGround
01118    (const State& state, const Transform& frameOnB) const {
01119     return SpatialVec(getBodyAngularVelocity(state),
01120                       findStationVelocityInGround(state,frameOnB.p()));
01121 }
01122 
01128 SpatialVec findFrameAccelerationInGround
01129     (const State& state, const Transform& frameOnB) const {
01130     return SpatialVec(getBodyAngularAcceleration(state),
01131                       findStationAccelerationInGround(state,frameOnB.p()));
01132 }
01133 
01137 Vec3 expressVectorInGroundFrame
01138    (const State& state, const Vec3& vectorInB) const {
01139     return getBodyRotation(state)*vectorInB;
01140 }
01141 
01146 Vec3 expressGroundVectorInBodyFrame
01147    (const State& state, const Vec3& vectorInG) const {
01148     return ~getBodyRotation(state)*vectorInG;
01149 }
01150 
01156 Vec3 expressVectorInAnotherBodyFrame
01157    (const State& state, const Vec3& vectorInB, 
01158     const MobilizedBody& inBodyA) const
01159 {
01160     return inBodyA.expressGroundVectorInBodyFrame(state, 
01161                                 expressVectorInGroundFrame(state,vectorInB));
01162 }
01163 
01168 MassProperties expressMassPropertiesInGroundFrame(const State& state) const {
01169     const MassProperties& M_Bo_B = getBodyMassProperties(state);
01170     const Rotation&       R_GB   = getBodyRotation(state);
01171     return M_Bo_B.reexpress(~R_GB);
01172 }
01173 
01178 MassProperties expressMassPropertiesInAnotherBodyFrame
01179    (const State& state, const MobilizedBody& inBodyA) const {
01180     const MassProperties& M_Bo_B = getBodyMassProperties(state);
01181     const Rotation        R_AB   = findBodyRotationInAnotherBody(state,inBodyA);
01182     return M_Bo_B.reexpress(~R_AB);
01183 }
01184 
01185 // End of Basic Operators.
01188 //------------------------------------------------------------------------------
01211 SpatialMat calcBodySpatialInertiaMatrixInGround(const State& state) const
01212 {
01213     if (isGround())
01214         return SpatialMat(Mat33(Infinity)); // sets diagonals to Inf
01215 
01216     const MassProperties& mp   = getBodyMassProperties(state);
01217     const Rotation&       R_GB = getBodyRotation(state);
01218         // re-express in Ground without shifting, convert to spatial mat.
01219     return mp.reexpress(~R_GB).toSpatialMat();
01220 }
01221 
01225 
01227 Inertia calcBodyCentralInertia(const State& state, 
01228                                 MobilizedBodyIndex objectBodyB) const
01229 {
01230     return getBodyMassProperties(state).calcCentralInertia();
01231 }
01232 
01236 Inertia calcBodyInertiaAboutAnotherBodyStation
01237    (const State& state, const MobilizedBody& inBodyA, 
01238     const Vec3& aboutLocationOnBodyA) const
01239 {
01240     // get B's mass props MB, measured about Bo, exp. in B
01241     const MassProperties& MB_Bo_B = getBodyMassProperties(state);
01242 
01243     // Calculate the vector from the body B origin (current "about" point) to 
01244     // the new "about" point PA, expressed in B.
01245     const Vec3 p_Bo_PA = 
01246         findStationAtAnotherBodyStation(state, inBodyA, aboutLocationOnBodyA);
01247 
01248     // Now shift the "about" point for body B's inertia IB to PA, but still 
01249     // expressed in B.
01250     const Inertia IB_PA_B = MB_Bo_B.calcShiftedInertia(p_Bo_PA);
01251         
01252     // Finally reexpress the inertia in the A frame.
01253     const Rotation R_BA    = 
01254         inBodyA.findBodyRotationInAnotherBody(state, *this);
01255     const Inertia  IB_PA_A = IB_PA_B.reexpress(R_BA);
01256     return IB_PA_A;
01257 }
01258 
01259 
01262 SpatialVec calcBodyMomentumAboutBodyOriginInGround(const State& state) {
01263     const MassProperties M_Bo_G = expressMassPropertiesInGroundFrame(state);
01264     const SpatialVec&    V_GB   = getBodyVelocity(state);
01265     return M_Bo_G.toSpatialMat() * V_GB;
01266 }
01267 
01270 SpatialVec calcBodyMomentumAboutBodyMassCenterInGround
01271    (const State& state) const {
01272     const MassProperties& M_Bo_B = getBodyMassProperties(state);
01273     const Rotation&       R_GB   = getBodyRotation(state);
01274 
01275     // Given a central inertia matrix I, angular velocity w, and mass center 
01276     // velocity v, the central angular momentum is Iw and linear momentum is mv.
01277     const Inertia I_Bc_B = M_Bo_B.calcCentralInertia();
01278     const Inertia I_Bc_G = I_Bc_B.reexpress(~R_GB);
01279     const Real  mb    = M_Bo_B.getMass();
01280     const Vec3& w_GB  = getBodyAngularVelocity(state);
01281     Vec3        v_GBc = 
01282         findStationVelocityInGround(state, M_Bo_B.getMassCenter());
01283 
01284     return SpatialVec( I_Bc_G*w_GB, mb*v_GBc );
01285 }
01286 
01290 Real calcStationToStationDistance(const State&         state,
01291                                   const Vec3&          locationOnBodyB,
01292                                   const MobilizedBody& bodyA,
01293                                   const Vec3&          locationOnBodyA) const
01294 {
01295     if (isSameMobilizedBody(bodyA))
01296         return (locationOnBodyA-locationOnBodyB).norm();
01297 
01298     const Vec3 r_Go_PB = 
01299         this->findStationLocationInGround(state,locationOnBodyB);
01300     const Vec3 r_Go_PA = 
01301         bodyA.findStationLocationInGround(state,locationOnBodyA);
01302     return (r_Go_PA - r_Go_PB).norm();
01303 }
01304 
01310 Real calcStationToStationDistanceTimeDerivative
01311    (const State&         state,
01312     const Vec3&          locationOnBodyB,
01313     const MobilizedBody& bodyA,
01314     const Vec3&          locationOnBodyA) const
01315 {
01316     if (isSameMobilizedBody(bodyA))
01317         return 0;
01318 
01319     Vec3 rB, rA, vB, vA;
01320     this->findStationLocationAndVelocityInGround(state,locationOnBodyB,rB,vB);
01321     bodyA.findStationLocationAndVelocityInGround(state,locationOnBodyA,rA,vA);
01322     const Vec3 r = rA-rB, v = vA-vB;
01323     const Real d = r.norm();
01324 
01325     // When the points are coincident, the rate of change of distance is just 
01326     // their relative speed. Otherwise, it is the speed along the direction of 
01327     // separation. 
01328     if (d==0) return v.norm();
01329     else return dot(v, r/d);
01330 }
01331 
01332 
01338 Real calcStationToStationDistance2ndTimeDerivative
01339    (const State&         state,
01340     const Vec3&          locationOnBodyB,
01341     const MobilizedBody& bodyA,
01342     const Vec3&          locationOnBodyA) const
01343 {
01344     if (isSameMobilizedBody(bodyA))
01345         return 0;
01346 
01347     Vec3 rB, rA, vB, vA, aB, aA;
01348     this->findStationLocationVelocityAndAccelerationInGround
01349                                             (state,locationOnBodyB,rB,vB,aB);
01350     bodyA.findStationLocationVelocityAndAccelerationInGround
01351                                             (state,locationOnBodyA,rA,vA,aA);
01352 
01353     const Vec3 r = rA-rB, v = vA-vB, a = aA-aB;
01354     const Real d = r.norm();
01355         
01356     // This method is the time derivative of 
01357     // calcFixedPointToPointDistanceTimeDerivative(), so it must follow the same
01358     // two cases. That is, when the points are coincident the change in 
01359     // separation rate is the time derivative of the speed |v|, otherwise it is 
01360     // the time derivative of the speed along the separation vector.
01361 
01362     if (d==0) {
01363         // Return d/dt |v|. This has two cases: if |v| is zero, the rate of 
01364         // change of speed is just the points' relative acceleration magnitude. 
01365         // Otherwise, it is the acceleration in the direction of the current 
01366         // relative velocity vector.
01367         const Real s = v.norm(); // speed
01368         if (s==0) return a.norm();
01369         else return dot(a, v/s);
01370     }
01371 
01372     // Points are separated.
01373     const Vec3 u = r/d; // u is separation direction (a unit vector from B to A) 
01374     const Vec3 vp = v - dot(v,u)*u; // velocity perp. to separation direction
01375     return dot(a,u) + dot(vp,v)/d;
01376 }
01377 
01378 
01381 Vec3 calcBodyMovingPointVelocityInBody
01382    (const State&         state,
01383     const Vec3&          locationOnBodyB, 
01384     const Vec3&          velocityOnBodyB,
01385     const MobilizedBody& inBodyA) const
01386 {
01387     SimTK_ASSERT_ALWAYS(!"unimplemented method", 
01388                         "MobilizedBody::calcBodyMovingPointVelocityInBody()"
01389                         " is not yet implemented -- any volunteers?");
01390     return Vec3::getNaN();
01391 }
01392 
01393 
01397 Vec3 calcBodyMovingPointAccelerationInBody
01398    (const State&         state, 
01399     const Vec3&          locationOnBodyB, 
01400     const Vec3&          velocityOnBodyB, 
01401     const Vec3&          accelerationOnBodyB,
01402     const MobilizedBody& inBodyA) const
01403 {
01404     SimTK_ASSERT_ALWAYS(!"unimplemented method", 
01405                         "MobilizedBody::calcBodyMovingPointAccelerationInBody()"
01406                         " is not yet implemented -- any volunteers?");
01407     return Vec3::getNaN();
01408 }
01409 
01416 Real calcMovingPointToPointDistanceTimeDerivative
01417    (const State&         state,
01418     const Vec3&          locationOnBodyB,
01419     const Vec3&          velocityOnBodyB,
01420     const MobilizedBody& bodyA,
01421     const Vec3&          locationOnBodyA,
01422     const Vec3&          velocityOnBodyA) const
01423 {
01424     SimTK_ASSERT_ALWAYS(!"unimplemented method", 
01425                 "MobilizedBody::calcMovingPointToPointDistanceTimeDerivative()"
01426                 " is not yet implemented -- any volunteers?");
01427     return NaN;
01428 }
01429 
01437 Real calcMovingPointToPointDistance2ndTimeDerivative
01438    (const State&         state,
01439     const Vec3&          locationOnBodyB,
01440     const Vec3&          velocityOnBodyB,
01441     const Vec3&          accelerationOnBodyB,
01442     const MobilizedBody& bodyA,
01443     const Vec3&          locationOnBodyA,
01444     const Vec3&          velocityOnBodyA,
01445     const Vec3&          accelerationOnBodyA) const
01446 {
01447     SimTK_ASSERT_ALWAYS(!"unimplemented method", 
01448             "MobilizedBody::calcMovingPointToPointDistance2ndTimeDerivative()"
01449             " is not yet implemented -- any volunteers?");
01450     return NaN;
01451 }
01452 
01453 
01454 // End of High Level Operators.
01458 
01459         // CONSTRUCTION METHODS //
01461 
01464 MobilizedBody() {}
01465 
01467 explicit MobilizedBody(MobilizedBodyImpl* r);
01468 
01469 //------------------------------------------------------------------------------
01479 const Body& getBody() const;
01480 
01485 Body& updBody();
01486 
01492 MobilizedBody& setBody(const Body&);
01493 
01501 int addBodyDecoration(const Transform&          X_BD, 
01502                       const DecorativeGeometry& geometry) {
01503     return updBody().addDecoration(X_BD, geometry);
01504 }
01507 int addBodyDecoration(const DecorativeGeometry& geometry) {
01508     return updBody().addDecoration(geometry);
01509 }
01510 
01517 int addOutboardDecoration(const Transform&          X_MD, 
01518                           const DecorativeGeometry& geometry);
01520 int getNumOutboardDecorations() const;
01522 const DecorativeGeometry& getOutboardDecoration(int i) const;
01524 DecorativeGeometry& updOutboardDecoration(int i);
01525 
01532 int addInboardDecoration(const Transform&          X_FD, 
01533                          const DecorativeGeometry& geometry);
01535 int getNumInboardDecorations() const;
01537 const DecorativeGeometry& getInboardDecoration(int i) const;
01539 DecorativeGeometry& updInboardDecoration(int i);
01540 
01547 MobilizedBody& setDefaultMassProperties(const MassProperties& m) {
01548     updBody().setDefaultRigidBodyMassProperties(m); // might not be allowed
01549     return *this;
01550 }
01551 
01553 const MassProperties& getDefaultMassProperties() const {
01554      // every body type can do this
01555     return getBody().getDefaultRigidBodyMassProperties();
01556 }
01557 
01565 void adoptMotion(Motion& ownerHandle);
01566 
01570 void clearMotion();
01571 
01575 bool hasMotion() const;
01576 
01583 const Motion& getMotion() const;
01584 
01590 MobilizedBody& setDefaultInboardFrame (const Transform& X_PF);
01596 MobilizedBody& setDefaultOutboardFrame(const Transform& X_BM);
01597 
01602 const Transform& getDefaultInboardFrame()  const; // X_PF
01606 const Transform& getDefaultOutboardFrame() const; // X_BM
01607 
01612 operator MobilizedBodyIndex() const {return getMobilizedBodyIndex();}
01613 
01619 MobilizedBodyIndex getMobilizedBodyIndex()  const;
01620 
01624 const MobilizedBody& getParentMobilizedBody() const;
01625 
01630 const MobilizedBody& getBaseMobilizedBody()   const;
01631 
01635 const SimbodyMatterSubsystem& getMatterSubsystem() const;
01639 SimbodyMatterSubsystem& updMatterSubsystem();
01640 
01643 bool isInSubsystem() const;
01644 
01648 bool isInSameSubsystem(const MobilizedBody& mobod) const;
01649 
01654 bool isSameMobilizedBody(const MobilizedBody& mobod) const;
01655 
01658 bool isGround() const;
01659 
01664 int getLevelInMultibodyTree() const;
01665     
01669 MobilizedBody& cloneForNewParent(MobilizedBody& parent) const;
01670 
01671 
01672     // Utility operators //
01673 
01677 Real getOneFromQPartition
01678    (const State& state, int which, const Vector& qlike) const;
01679 
01684 Real& updOneFromQPartition
01685    (const State& state, int which, Vector& qlike) const;
01686 
01690 Real getOneFromUPartition
01691    (const State& state, int which, const Vector& ulike) const;
01692 
01697 Real& updOneFromUPartition(const State& state, int which, Vector& ulike) const;
01698 
01704 void applyOneMobilityForce(const State& state, int which, Real f, 
01705                            Vector& mobilityForces) const
01706 {
01707     updOneFromUPartition(state,which,mobilityForces) += f;
01708 }
01709 
01746 void convertQForceToUForce(const State&                        state,
01747                            const Array_<Real,MobilizerQIndex>& fq,
01748                            Array_<Real,MobilizerUIndex>&       fu) const;
01749 
01756 void applyBodyForce(const State& state, const SpatialVec& spatialForceInG, 
01757                     Vector_<SpatialVec>& bodyForcesInG) const;
01758 
01764 void applyBodyTorque(const State& state, const Vec3& torqueInG, 
01765                      Vector_<SpatialVec>& bodyForcesInG) const;
01766 
01777 void applyForceToBodyPoint
01778    (const State& state, const Vec3& pointInB, const Vec3& forceInG,
01779     Vector_<SpatialVec>& bodyForcesInG) const;
01780 
01781 // End of Construction and Misc Methods.
01784 
01785     // BUILT IN MOBILIZER DECLARATIONS //
01787 
01788 //------------------------------------------------------------------------------
01789 // These are the built-in MobilizedBody types. Each of these has a known 
01790 // number of coordinates and speeds (at least a default number) so
01791 // can define routines which return and accept specific-size arguments, e.g.
01792 // Real (for 1-dof mobilizer) and Vec5 (for 5-dof mobilizer). Here is the
01793 // conventional interface that each built-in should provide. The base type
01794 // provides similar routines but using variable-sized or "one at a time"
01795 // arguments. (Vec<1> here will actually be a Real; assume the built-in
01796 // MobilizedBody class is "BuiltIn")
01797 //
01798 //    BuiltIn&       setDefaultQ(const Vec<nq>&);
01799 //    const Vec<nq>& getDefaultQ() const;
01800 //
01801 //    const Vec<nq>& getQ[Dot[Dot]](const State&) const;
01802 //    const Vec<nu>& getU[Dot](const State&) const;
01803 //
01804 //    void setQ(State&, const Vec<nq>&) const;
01805 //    void setU(State&, const Vec<nu>&) const;
01806 //
01807 //    const Vec<nq>& getMyPartQ(const State&, const Vector& qlike) const;
01808 //    const Vec<nu>& getMyPartU(const State&, const Vector& ulike) const;
01809 //   
01810 //    Vec<nq>& updMyPartQ(const State&, Vector& qlike) const;
01811 //    Vec<nu>& updMyPartU(const State&, Vector& ulike) const;
01812 //
01813 // Each built in mobilized body type is declared in its own header
01814 // file using naming convention MobilizedBody_Pin.h, for example. All the
01815 // built-in headers are collected in MobilizedBody_BuiltIns.h; you should
01816 // include new ones there also.
01817 
01818 
01819 class Pin;              
01820 typedef Pin Torsion;  
01821 typedef Pin Revolute; 
01822 
01823 class Universal;
01824 class Cylinder;
01825 class Weld;
01826 
01827 class Slider;           
01828 typedef Slider Prismatic; 
01829 
01830 class Translation;      
01831 typedef Translation Cartesian;       
01832 typedef Translation CartesianCoords; 
01833 
01834 class BendStretch;      
01835 typedef BendStretch PolarCoords; 
01836 
01837 class SphericalCoords;
01838 class LineOrientation;
01839 
01840 class Planar;
01841 class Gimbal;
01842 class Bushing;
01843 
01844 class Ball;             
01845 typedef Ball Orientation;   
01846 typedef Ball Spherical;     
01847 
01848 class Free;
01849 class FreeLine;
01850 class Screw;
01851 class Ellipsoid;
01852 class Custom;
01853 class Ground;
01854 class FunctionBased;
01855     
01856 // Internal use only.
01857 class PinImpl;
01858 class SliderImpl;
01859 class UniversalImpl;
01860 class CylinderImpl;
01861 class BendStretchImpl;
01862 class PlanarImpl;
01863 class GimbalImpl;
01864 class BushingImpl;
01865 class BallImpl;
01866 class TranslationImpl;
01867 class SphericalCoordsImpl;
01868 class FreeImpl;
01869 class LineOrientationImpl;
01870 class FreeLineImpl;
01871 class WeldImpl;
01872 class ScrewImpl;
01873 class EllipsoidImpl;
01874 class CustomImpl;
01875 class GroundImpl;
01876 class FunctionBasedImpl;
01877 };
01878 
01879 } // namespace SimTK
01880 
01881 #endif // SimTK_SIMBODY_MOBILIZED_BODY_H_
01882 
01883 
01884 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines