Simbody
3.4 (development)
|
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