Simbody
|
00001 #ifndef SimTK_SIMBODY_MOBILIZED_BODY_H_ 00002 #define SimTK_SIMBODY_MOBILIZED_BODY_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * SimTK Core: SimTK Simbody(tm) * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK Core biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org. * 00011 * * 00012 * Portions copyright (c) 2007-10 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: Paul Mitiguy, Peter Eastman * 00015 * * 00016 * Permission is hereby granted, free of charge, to any person obtaining a * 00017 * copy of this software and associated documentation files (the "Software"), * 00018 * to deal in the Software without restriction, including without limitation * 00019 * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 00020 * and/or sell copies of the Software, and to permit persons to whom the * 00021 * Software is furnished to do so, subject to the following conditions: * 00022 * * 00023 * The above copyright notice and this permission notice shall be included in * 00024 * all copies or substantial portions of the Software. * 00025 * * 00026 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 00027 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * 00028 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * 00029 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 00030 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 00031 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * 00032 * USE OR OTHER DEALINGS IN THE SOFTWARE. * 00033 * -------------------------------------------------------------------------- */ 00034 00052 #include "SimTKmath.h" 00053 #include "simbody/internal/common.h" 00054 #include "simbody/internal/Body.h" 00055 #include "simbody/internal/Motion.h" 00056 00057 #include <cassert> 00058 00059 namespace SimTK { 00060 00061 class SimbodyMatterSubsystem; 00062 class Motion; 00063 class MobilizedBody; 00064 class MobilizedBodyImpl; 00065 00066 // We only want the template instantiation to occur once. This symbol is 00067 // defined in the SimTK core compilation unit that instantiates the mobilized 00068 // body class but should not be defined any other time. 00069 #ifndef SimTK_SIMBODY_DEFINING_MOBILIZED_BODY 00070 extern template class PIMPLHandle<MobilizedBody, MobilizedBodyImpl, true>; 00071 #endif 00072 00076 typedef MobilizedBody Mobod; 00077 00078 00133 class SimTK_SIMBODY_EXPORT MobilizedBody : public PIMPLHandle<MobilizedBody, MobilizedBodyImpl, true> { 00134 public: 00135 00141 enum Direction { 00142 Forward = 0, 00143 Reverse = 1 00144 }; 00145 00149 MobilizedBody& setDefaultMotionType(Motion::Level, Motion::Method=Motion::Prescribed); 00150 00152 void setMotionType(State&, Motion::Level, Motion::Method=Motion::Prescribed) const; 00153 00154 bool isAccelerationAlwaysZero(const State&) const; 00155 bool isVelocityAlwaysZero(const State&) const; 00156 00157 00159 // STATE ACCESS METHODS // 00161 00165 00166 00181 const Transform& getBodyTransform(const State&) const; // X_GB 00182 00191 const Rotation& getBodyRotation(const State& s) const { 00192 return getBodyTransform(s).R(); 00193 } 00198 const Vec3& getBodyOriginLocation(const State& s) const { 00199 return getBodyTransform(s).p(); 00200 } 00201 00205 const Transform& getMobilizerTransform(const State&) const; // X_FM 00206 00213 const SpatialVec& getBodyVelocity(const State&) const; // V_GB 00214 00218 const Vec3& getBodyAngularVelocity(const State& s) const { // w_GB 00219 return getBodyVelocity(s)[0]; 00220 } 00226 const Vec3& getBodyOriginVelocity(const State& s) const { // v_GB 00227 return getBodyVelocity(s)[1]; 00228 } 00229 00235 const SpatialVec& getMobilizerVelocity(const State&) const; // V_FM 00236 00242 const SpatialVec& getBodyAcceleration(const State& s) const; // A_GB 00243 00247 const Vec3& getBodyAngularAcceleration(const State& s) const { // b_GB 00248 return getBodyAcceleration(s)[0]; 00249 } 00250 00255 const Vec3& getBodyOriginAcceleration(const State& s) const { // a_GB 00256 return getBodyAcceleration(s)[1]; 00257 } 00258 00264 const SpatialVec& getMobilizerAcceleration(const State&) const { // A_FM 00265 SimTK_ASSERT_ALWAYS(!"unimplemented method", 00266 "MobilizedBody::getMobilizerAcceleration() is not yet implemented -- any volunteers?"); 00267 return *(new SpatialVec()); 00268 } 00269 00272 const MassProperties& getBodyMassProperties(const State&) const; 00273 00275 Real getBodyMass(const State& s) const { 00276 return getBodyMassProperties(s).getMass(); 00277 } 00278 00282 const Vec3& getBodyMassCenterStation(const State& s) const { 00283 return getBodyMassProperties(s).getMassCenter(); 00284 } 00285 00289 const Inertia& getBodyInertiaAboutBodyOrigin(const State& s) const { 00290 return getBodyMassProperties(s).getInertia(); 00291 } 00292 00297 const Transform& getInboardFrame (const State&) const; // X_PF 00302 const Transform& getOutboardFrame(const State&) const; // X_BM 00303 00306 void setInboardFrame (State&, const Transform& X_PF) const; 00309 void setOutboardFrame(State&, const Transform& X_BM) const; 00310 00311 // End of State Access - Bodies 00313 00317 00318 00319 00320 int getNumQ(const State&) const; 00323 int getNumU(const State&) const; 00324 00327 QIndex getFirstQIndex(const State&) const; 00328 00331 UIndex getFirstUIndex(const State&) const; 00332 00333 00337 Real getOneQ(const State&, int which) const; 00338 00342 Real getOneU(const State&, int which) const; 00343 00347 Vector getQAsVector(const State&) const; 00351 Vector getUAsVector(const State&) const; 00352 00356 Real getOneQDot (const State&, int which) const; 00360 Vector getQDotAsVector(const State&) const; 00361 00366 Real getOneUDot(const State&, int which) const; 00372 Real getOneQDotDot(const State&, int which) const; 00377 Vector getUDotAsVector(const State&) const; 00382 Vector getQDotDotAsVector(const State&) const; 00383 00394 Vector getTauAsVector(const State&) const; 00400 Real getOneTau(const State&, MobilizerUIndex which) const; 00401 00402 00406 void setOneQ(State&, int which, Real v) const; 00410 void setOneU(State&, int which, Real v) const; 00411 00414 void setQFromVector(State& s, const Vector& v) const; 00417 void setUFromVector(State& s, const Vector& v) const; 00418 00454 00455 void setQToFitTransform (State&, const Transform& X_FM) const; 00460 void setQToFitRotation (State&, const Rotation& R_FM) const; 00466 void setQToFitTranslation (State&, const Vec3& p_FM) const; 00467 00474 void setUToFitVelocity (State&, const SpatialVec& V_FM) const; 00481 void setUToFitAngularVelocity (State&, const Vec3& w_FM) const; 00488 void setUToFitLinearVelocity (State&, const Vec3& v_FM) const; 00489 00500 SpatialVec getHCol(const State& s, MobilizerUIndex ux) const; 00501 00509 SpatialVec getH_FMCol(const State& s, MobilizerUIndex ux) const; 00510 00511 // End of State Access Methods. 00513 00515 // BASIC OPERATORS // 00517 00519 00551 00553 00559 Transform findBodyTransformInAnotherBody(const State& s, 00560 const MobilizedBody& inBodyA) const 00561 { 00562 const Transform& X_GA = inBodyA.getBodyTransform(s); 00563 const Transform& X_GB = this->getBodyTransform(s); 00564 00565 return ~X_GA*X_GB; // X_AB=X_AG*X_GB 00566 } 00567 00573 Rotation findBodyRotationInAnotherBody(const State& s, 00574 const MobilizedBody& inBodyA) const 00575 { 00576 const Rotation& R_GA = inBodyA.getBodyRotation(s); 00577 const Rotation& R_GB = this->getBodyRotation(s); 00578 00579 return ~R_GA*R_GB; // R_AB=R_AG*R_GB 00580 } 00581 00588 Vec3 findBodyOriginLocationInAnotherBody(const State& s, 00589 const MobilizedBody& toBodyA) const 00590 { return toBodyA.findStationAtGroundPoint(s,getBodyOriginLocation(s)); } 00591 00598 SpatialVec findBodyVelocityInAnotherBody(const State& s, 00599 const MobilizedBody& inBodyA) const 00600 { 00601 const SpatialVec& V_GB = this->getBodyVelocity(s); 00602 const SpatialVec& V_GA = inBodyA.getBodyVelocity(s); 00603 const Vec3 w_AB_G = V_GB[0]-V_GA[0]; // angular velocity of B in A, exp in G ( 3 flops) 00604 00605 // Angular velocity was easy, but for linear velocity we have to add in an wXr term. 00606 const Transform& X_GB = getBodyTransform(s); 00607 const Transform& X_GA = inBodyA.getBodyTransform(s); 00608 const Vec3 p_AB_G = X_GB.p() - X_GA.p(); // vector from OA to OB, exp in G ( 3 flops) 00609 const Vec3 p_AB_G_dot = V_GB[1] - V_GA[1]; // d/dt p taken in G ( 3 flops) 00610 00611 const Vec3 v_AB_G = p_AB_G_dot - V_GA[0] % p_AB_G; // d/dt p taken in A, exp in G (12 flops) 00612 00613 // We're done, but the answer is expressed in Ground. Reexpress in A and return. 00614 return ~X_GA.R()*SpatialVec(w_AB_G, v_AB_G); // (30 flops) 00615 } 00616 00622 Vec3 findBodyAngularVelocityInAnotherBody(const State& s, 00623 const MobilizedBody& inBodyA) const 00624 { 00625 const Vec3& w_GB = getBodyAngularVelocity(s); 00626 const Vec3& w_GA = inBodyA.getBodyAngularVelocity(s); 00627 const Vec3 w_AB_G = w_GB-w_GA; // angular velocity of B in A, exp in G ( 3 flops) 00628 00629 // Now reexpress in A. 00630 return inBodyA.expressGroundVectorInBodyFrame(s, w_AB_G); // (15 flops) 00631 } 00632 00638 Vec3 findBodyOriginVelocityInAnotherBody(const State& s, 00639 const MobilizedBody& inBodyA) const 00640 { 00641 // Doesn't save much to special case this one. 00642 return findBodyVelocityInAnotherBody(s,inBodyA)[1]; 00643 } 00644 00651 SpatialVec findBodyAccelerationInAnotherBody(const State& s, 00652 const MobilizedBody& inBodyA) const 00653 { 00654 const Vec3& p_GB = this->getBodyOriginLocation(s); 00655 const Transform& X_GA = inBodyA.getBodyTransform(s); 00656 const SpatialVec& V_GB = this->getBodyVelocity(s); 00657 const SpatialVec& V_GA = inBodyA.getBodyVelocity(s); 00658 const SpatialVec& A_GB = this->getBodyAcceleration(s); 00659 const SpatialVec& A_GA = inBodyA.getBodyAcceleration(s); 00660 const Vec3& p_GA = X_GA.p(); 00661 const Vec3& w_GA = V_GA[0]; 00662 const Vec3& w_GB = V_GB[0]; 00663 const Vec3& b_GA = A_GA[0]; 00664 const Vec3& b_GB = A_GB[0]; 00665 00666 const Vec3 p_AB_G = p_GB - p_GA; // vector from OA to OB, in G ( 3 flops) 00667 const Vec3 p_AB_G_dot = V_GB[1] - V_GA[1]; // d/dt p taken in G ( 3 flops) 00668 const Vec3 p_AB_G_dotdot = A_GB[1] - A_GA[1]; // d^2/dt^2 taken in G ( 3 flops) 00669 00670 const Vec3 w_AB_G = w_GB - w_GA; // relative ang. vel. of B in A, exp. in G (3 flops) 00671 const Vec3 v_AB_G = p_AB_G_dot - w_GA % p_AB_G; // d/dt p taken in A, exp in G (12 flops) 00672 00673 const Vec3 w_AB_G_dot = b_GB - b_GA; // d/dt of w_AB_G taken in G ( 3 flops) 00674 const Vec3 v_AB_G_dot = p_AB_G_dotdot - (b_GA % p_AB_G + w_GA % p_AB_G_dot); // d/dt v_AB_G taken in G 00675 // (24 flops) 00676 00677 // We have the derivative in G; change it to derivative in A by adding in contribution caused 00678 // by motion of G in A, that is w_AG X w_AB_G. (Note that w_AG=-w_GA.) 00679 const Vec3 b_AB_G = w_AB_G_dot - w_GA % w_AB_G; // ang. accel. of B in A (12 flops) 00680 const Vec3 a_AB_G = v_AB_G_dot - w_GA % v_AB_G; // taken in A, exp. in G (12 flops) 00681 00682 return ~X_GA.R() * SpatialVec(b_AB_G, a_AB_G); // taken in A, expressed in A (30 flops) 00683 } 00684 00691 Vec3 findBodyAngularAccelerationInAnotherBody(const State& s, 00692 const MobilizedBody& inBodyA) const 00693 { 00694 const Rotation& R_GA = inBodyA.getBodyRotation(s); 00695 const Vec3& w_GA = inBodyA.getBodyAngularVelocity(s); 00696 const Vec3& w_GB = this->getBodyAngularVelocity(s); 00697 const Vec3& b_GA = inBodyA.getBodyAngularAcceleration(s); 00698 const Vec3& b_GB = this->getBodyAngularAcceleration(s); 00699 00700 const Vec3 w_AB_G = w_GB - w_GA; // relative ang. vel. of B in A, exp. in G (3 flops) 00701 const Vec3 w_AB_G_dot = b_GB - b_GA; // d/dt of w_AB_G taken in G ( 3 flops) 00702 00703 // We have the derivative in G; change it to derivative in A by adding 00704 // in contribution caused by motion of G in A, that is w_AG X w_AB_G. 00705 // (Note that w_AG=-w_GA.) 00706 const Vec3 b_AB_G = w_AB_G_dot - w_GA % w_AB_G; // ang. accel. of B in A (12 flops) 00707 00708 return ~R_GA * b_AB_G; // taken in A, expressed in A (15 flops) 00709 } 00710 00717 Vec3 findBodyOriginAccelerationInAnotherBody(const State& s, 00718 const MobilizedBody& inBodyA) const 00719 { 00720 // Not much to be saved by trying to optimize this since the linear part 00721 // is the most expensive to calculate. 00722 return findBodyAccelerationInAnotherBody(s,inBodyA)[1]; 00723 } 00724 00731 Vec3 findStationLocationInGround(const State& s, const Vec3& stationOnB) const { 00732 return getBodyTransform(s) * stationOnB; 00733 } 00734 00735 00745 Vec3 findStationLocationInAnotherBody(const State& s, const Vec3& stationOnB, 00746 const MobilizedBody& toBodyA) const 00747 { 00748 return toBodyA.findStationAtGroundPoint(s, findStationLocationInGround(s,stationOnB)); 00749 } 00750 00758 Vec3 findStationVelocityInGround(const State& s, const Vec3& stationOnB) const { 00759 const Vec3& w = getBodyAngularVelocity(s); // in G 00760 const Vec3& v = getBodyOriginVelocity(s); // in G 00761 const Vec3 r = expressVectorInGroundFrame(s,stationOnB); // 15 flops 00762 return v + w % r; // 12 flops 00763 } 00764 00765 00772 Vec3 findStationVelocityInAnotherBody(const State& s, 00773 const Vec3& stationOnBodyB, // p_BS 00774 const MobilizedBody& inBodyA) const 00775 { 00776 const SpatialVec V_AB = findBodyVelocityInAnotherBody(s,inBodyA); // (51 flops) 00777 // OB->S rexpressed in A but not shifted to OA 00778 const Vec3 p_BS_A = expressVectorInAnotherBodyFrame(s, stationOnBodyB, inBodyA); 00779 // (30 flops) 00780 return V_AB[1] + (V_AB[0] % p_BS_A); // (12 flops) 00781 } 00782 00783 00791 Vec3 findStationAccelerationInGround(const State& s, const Vec3& stationOnB) const { 00792 const Vec3& w = getBodyAngularVelocity(s); // in G 00793 const Vec3& b = getBodyAngularAcceleration(s); // in G 00794 const Vec3& a = getBodyOriginAcceleration(s); // in G 00795 00796 const Vec3 r = expressVectorInGroundFrame(s,stationOnB); // 15 flops 00797 return a + b % r + w % (w % r); // 33 flops 00798 } 00799 00805 Vec3 findStationAccelerationInAnotherBody(const State& s, 00806 const Vec3& stationOnBodyB, 00807 const MobilizedBody& inBodyA) const 00808 { 00809 const Vec3 w_AB = findBodyAngularVelocityInAnotherBody(s,inBodyA); // ( 18 flops) 00810 const SpatialVec A_AB = findBodyAccelerationInAnotherBody(s,inBodyA); // (105 flops) 00811 // OB->S rexpressed in A but not shifted to OA 00812 const Vec3 p_BS_A = expressVectorInAnotherBodyFrame(s, stationOnBodyB, inBodyA); 00813 // ( 30 flops) 00814 00815 return A_AB[1] + (A_AB[0] % p_BS_A) + w_AB % (w_AB % p_BS_A); // ( 33 flops) 00816 } 00817 00822 void findStationLocationAndVelocityInGround(const State& s, const Vec3& locationOnB, 00823 Vec3& locationOnGround, Vec3& velocityInGround) const 00824 { 00825 const Vec3& p_GB = getBodyOriginLocation(s); 00826 const Vec3 p_BS_G = expressVectorInGroundFrame(s,locationOnB); // 15 flops 00827 locationOnGround = p_GB + p_BS_G; // 3 flops 00828 00829 const Vec3& w_GB = getBodyAngularVelocity(s); 00830 const Vec3& v_GB = getBodyOriginVelocity(s); 00831 velocityInGround = v_GB + w_GB % p_BS_G; // 12 flops 00832 } 00833 00834 00839 void findStationLocationVelocityAndAccelerationInGround 00840 (const State& s, const Vec3& locationOnB, 00841 Vec3& locationOnGround, Vec3& velocityInGround, Vec3& accelerationInGround) const 00842 { 00843 const Rotation& R_GB = getBodyRotation(s); 00844 const Vec3& p_GB = getBodyOriginLocation(s); 00845 00846 const Vec3 r = R_GB*locationOnB; // re-express station vector p_BS in G (15 flops) 00847 locationOnGround = p_GB + r; // 3 flops 00848 00849 const Vec3& w = getBodyAngularVelocity(s); // in G 00850 const Vec3& v = getBodyOriginVelocity(s); // in G 00851 const Vec3& b = getBodyAngularAcceleration(s); // in G 00852 const Vec3& a = getBodyOriginAcceleration(s); // in G 00853 00854 const Vec3 wXr = w % r; // "whipping" velocity w X r due to angular velocity (9 flops) 00855 velocityInGround = v + wXr; // v + w X r (3 flops) 00856 accelerationInGround = a + b % r + w % wXr; // 24 flops 00857 } 00858 00861 Vec3 findMassCenterLocationInGround(const State& s) const { 00862 return findStationLocationInGround(s,getBodyMassCenterStation(s)); 00863 } 00864 00868 Vec3 findMassCenterLocationInAnotherBody(const State& s, const MobilizedBody& toBodyA) const { 00869 return findStationLocationInAnotherBody(s,getBodyMassCenterStation(s),toBodyA); 00870 } 00871 00878 Vec3 findStationAtGroundPoint(const State& s, const Vec3& locationInG) const { 00879 return ~getBodyTransform(s) * locationInG; 00880 } 00881 00887 Vec3 findStationAtAnotherBodyStation(const State& s, const MobilizedBody& fromBodyA, 00888 const Vec3& stationOnA) const { 00889 return fromBodyA.findStationLocationInAnotherBody(s, stationOnA, *this); 00890 } 00891 00895 Vec3 findStationAtAnotherBodyOrigin(const State& s, const MobilizedBody& fromBodyA) const { 00896 return findStationAtGroundPoint(s,fromBodyA.getBodyOriginLocation(s)); 00897 } 00898 00902 Vec3 findStationAtAnotherBodyMassCenter(const State& s, const MobilizedBody& fromBodyA) const { 00903 return fromBodyA.findStationLocationInAnotherBody(s,getBodyMassCenterStation(s),*this); 00904 } 00905 00909 Transform findFrameTransformInGround 00910 (const State& s, const Transform& frameOnB) const { 00911 return getBodyTransform(s) * frameOnB; 00912 } 00913 00919 SpatialVec findFrameVelocityInGround 00920 (const State& s, const Transform& frameOnB) const { 00921 return SpatialVec(getBodyAngularVelocity(s), 00922 findStationVelocityInGround(s,frameOnB.p())); 00923 } 00924 00931 SpatialVec findFrameAccelerationInGround 00932 (const State& s, const Transform& frameOnB) const { 00933 return SpatialVec(getBodyAngularAcceleration(s), 00934 findStationAccelerationInGround(s,frameOnB.p())); 00935 } 00936 00940 Vec3 expressVectorInGroundFrame(const State& s, const Vec3& vectorInB) const { 00941 return getBodyRotation(s)*vectorInB; 00942 } 00943 00947 Vec3 expressGroundVectorInBodyFrame(const State& s, const Vec3& vectorInG) const { 00948 return ~getBodyRotation(s)*vectorInG; 00949 } 00950 00956 Vec3 expressVectorInAnotherBodyFrame(const State& s, const Vec3& vectorInB, 00957 const MobilizedBody& inBodyA) const 00958 { 00959 return inBodyA.expressGroundVectorInBodyFrame(s, expressVectorInGroundFrame(s,vectorInB)); 00960 } 00961 00965 MassProperties expressMassPropertiesInGroundFrame(const State& s) const { 00966 const MassProperties& M_OB_B = getBodyMassProperties(s); 00967 const Rotation& R_GB = getBodyRotation(s); 00968 return M_OB_B.reexpress(~R_GB); 00969 } 00970 00974 MassProperties expressMassPropertiesInAnotherBodyFrame 00975 (const State& s, const MobilizedBody& inBodyA) const 00976 { 00977 const MassProperties& M_OB_B = getBodyMassProperties(s); 00978 const Rotation R_AB = findBodyRotationInAnotherBody(s,inBodyA); 00979 return M_OB_B.reexpress(~R_AB); 00980 } 00981 00982 // End of Basic Operators. 00984 00989 00990 00992 01012 SpatialMat calcBodySpatialInertiaMatrixInGround(const State& s) const 01013 { 01014 if (isGround()) 01015 return SpatialMat(Mat33(Infinity)); // sets diagonals to Inf 01016 01017 const MassProperties& mp = getBodyMassProperties(s); 01018 const Rotation& R_GB = getBodyRotation(s); 01019 // re-express in Ground without shifting, convert to spatial mat. 01020 return mp.reexpress(~R_GB).toSpatialMat(); 01021 } 01022 01028 Inertia calcBodyCentralInertia(const State& s, 01029 MobilizedBodyIndex objectBodyB) const 01030 { 01031 return getBodyMassProperties(s).calcCentralInertia(); 01032 } 01033 01037 Inertia calcBodyInertiaAboutAnotherBodyStation(const State& s, 01038 const MobilizedBody& inBodyA, 01039 const Vec3& aboutLocationOnBodyA) const 01040 { 01041 // get B's mass props MB, measured about OB, exp. in B 01042 const MassProperties& MB_OB_B = getBodyMassProperties(s); 01043 01044 // Calculate the vector from the body B origin (current "about" point) to the new "about" point PA, 01045 // expressed in B. 01046 const Vec3 r_OB_PA = findStationAtAnotherBodyStation(s, inBodyA, aboutLocationOnBodyA); 01047 01048 // Now shift the "about" point for body B's inertia IB to PA, but still expressed in B. 01049 const Inertia IB_PA_B = MB_OB_B.calcShiftedInertia(r_OB_PA); 01050 01051 // Finally reexpress the inertia in the A frame. 01052 const Rotation R_BA = inBodyA.findBodyRotationInAnotherBody(s, *this); 01053 const Inertia IB_PA_A = IB_PA_B.reexpress(R_BA); 01054 return IB_PA_A; 01055 } 01056 01057 01060 SpatialVec calcBodyMomentumAboutBodyOriginInGround(const State& s) { 01061 const MassProperties M_OB_G = expressMassPropertiesInGroundFrame(s); 01062 const SpatialVec& V_GB = getBodyVelocity(s); 01063 return M_OB_G.toSpatialMat() * V_GB; 01064 } 01065 01068 SpatialVec calcBodyMomentumAboutBodyMassCenterInGround(const State& s) const { 01069 const MassProperties& M_OB_B = getBodyMassProperties(s); 01070 const Rotation& R_GB = getBodyRotation(s); 01071 01072 // Given a central inertia matrix I, angular velocity w, and mass center velocity v, 01073 // the central angular momentum is Iw and linear momentum is mv. 01074 const Inertia I_CB_B = M_OB_B.calcCentralInertia(); 01075 const Inertia I_CB_G = I_CB_B.reexpress(~R_GB); 01076 const Real mb = M_OB_B.getMass(); 01077 const Vec3& w_GB = getBodyAngularVelocity(s); 01078 Vec3 v_G_CB = findStationVelocityInGround(s, M_OB_B.getMassCenter()); 01079 01080 return SpatialVec( I_CB_G*w_GB, mb*v_G_CB ); 01081 } 01082 01086 Real calcStationToStationDistance(const State& s, 01087 const Vec3& locationOnBodyB, 01088 const MobilizedBody& bodyA, 01089 const Vec3& locationOnBodyA) const 01090 { 01091 if (isSameMobilizedBody(bodyA)) 01092 return (locationOnBodyA-locationOnBodyB).norm(); 01093 01094 const Vec3 r_OG_PB = this->findStationLocationInGround(s,locationOnBodyB); 01095 const Vec3 r_OG_PA = bodyA.findStationLocationInGround(s,locationOnBodyA); 01096 return (r_OG_PA - r_OG_PB).norm(); 01097 } 01098 01103 Real calcStationToStationDistanceTimeDerivative(const State& s, 01104 const Vec3& locationOnBodyB, 01105 const MobilizedBody& bodyA, 01106 const Vec3& locationOnBodyA) const 01107 { 01108 if (isSameMobilizedBody(bodyA)) 01109 return 0; 01110 01111 Vec3 rB, rA, vB, vA; 01112 this->findStationLocationAndVelocityInGround(s,locationOnBodyB,rB,vB); 01113 bodyA.findStationLocationAndVelocityInGround(s,locationOnBodyA,rA,vA); 01114 const Vec3 r = rA-rB, v = vA-vB; 01115 const Real d = r.norm(); 01116 01117 // When the points are coincident, the rate of change of distance is just their relative speed. 01118 // Otherwise, it is the speed along the direction of separation. 01119 if (d==0) return v.norm(); 01120 else return dot(v, r/d); 01121 } 01122 01123 01128 Real calcStationToStationDistance2ndTimeDerivative(const State& s, 01129 const Vec3& locationOnBodyB, 01130 const MobilizedBody& bodyA, 01131 const Vec3& locationOnBodyA) const 01132 { 01133 if (isSameMobilizedBody(bodyA)) 01134 return 0; 01135 01136 Vec3 rB, rA, vB, vA, aB, aA; 01137 this->findStationLocationVelocityAndAccelerationInGround(s,locationOnBodyB,rB,vB,aB); 01138 bodyA.findStationLocationVelocityAndAccelerationInGround(s,locationOnBodyA,rA,vA,aA); 01139 01140 const Vec3 r = rA-rB, v = vA-vB, a = aA-aB; 01141 const Real d = r.norm(); 01142 01143 // This method is the time derivative of calcFixedPointToPointDistanceTimeDerivative(), so it 01144 // must follow the same two cases. That is, when the points are coincident the change in 01145 // separation rate is the time derivative of the speed |v|, otherwise it is the time 01146 // derivative of the speed along the separation vector. 01147 01148 if (d==0) { 01149 // Return d/dt |v|. This has two cases: if |v| is zero, the rate of change of speed is 01150 // just the points' relative acceleration magnitude. Otherwise, it is the acceleration 01151 // in the direction of the current relative velocity vector. 01152 const Real s = v.norm(); // speed 01153 if (s==0) return a.norm(); 01154 else return dot(a, v/s); 01155 } 01156 01157 // Points are separated. 01158 const Vec3 u = r/d; // u is the separation direction (a unit vector from B to A) 01159 const Vec3 vp = v - dot(v,u)*u; // velocity perpendicular to separation direction 01160 return dot(a,u) + dot(vp,v)/d; 01161 } 01162 01163 01166 Vec3 calcBodyMovingPointVelocityInBody(const State& s, 01167 const Vec3& locationOnBodyB, 01168 const Vec3& velocityOnBodyB, 01169 const MobilizedBody& inBodyA) const 01170 { 01171 SimTK_ASSERT_ALWAYS(!"unimplemented method", 01172 "MobilizedBody::calcBodyMovingPointVelocityInBody() is not yet implemented -- any volunteers?"); 01173 return Vec3::getNaN(); 01174 } 01175 01176 01179 Vec3 calcBodyMovingPointAccelerationInBody(const State& s, 01180 const Vec3& locationOnBodyB, 01181 const Vec3& velocityOnBodyB, 01182 const Vec3& accelerationOnBodyB, 01183 const MobilizedBody& inBodyA) const 01184 { 01185 SimTK_ASSERT_ALWAYS(!"unimplemented method", 01186 "MobilizedBody::calcBodyMovingPointAccelerationInBody() is not yet implemented -- any volunteers?"); 01187 return Vec3::getNaN(); 01188 } 01189 01196 Real calcMovingPointToPointDistanceTimeDerivative(const State& s, 01197 const Vec3& locationOnBodyB, 01198 const Vec3& velocityOnBodyB, 01199 const MobilizedBody& bodyA, 01200 const Vec3& locationOnBodyA, 01201 const Vec3& velocityOnBodyA) const 01202 { 01203 SimTK_ASSERT_ALWAYS(!"unimplemented method", 01204 "MobilizedBody::calcMovingPointToPointDistanceTimeDerivative() is not yet implemented -- any volunteers?"); 01205 return NaN; 01206 } 01207 01214 Real calcMovingPointToPointDistance2ndTimeDerivative(const State& s, 01215 const Vec3& locationOnBodyB, 01216 const Vec3& velocityOnBodyB, 01217 const Vec3& accelerationOnBodyB, 01218 const MobilizedBody& bodyA, 01219 const Vec3& locationOnBodyA, 01220 const Vec3& velocityOnBodyA, 01221 const Vec3& accelerationOnBodyA) const 01222 { 01223 SimTK_ASSERT_ALWAYS(!"unimplemented method", 01224 "MobilizedBody::calcMovingPointToPointDistance2ndTimeDerivative() is not yet implemented -- any volunteers?"); 01225 return NaN; 01226 } 01227 01228 01229 // End of High Level Operators. 01231 01232 01234 // CONSTRUCTION METHODS // 01236 01240 MobilizedBody(); 01241 01243 explicit MobilizedBody(MobilizedBodyImpl* r); 01244 01249 01250 01256 MobilizedBody& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) { 01257 (void)updBody().addDecoration(X_BD,g); 01258 return *this; 01259 } 01260 01264 MobilizedBody& addOutboardDecoration(const Transform& X_MD, const DecorativeGeometry&); 01265 01269 MobilizedBody& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry&); 01270 01272 const Body& getBody() const; 01276 Body& updBody(); 01277 01283 MobilizedBody& setBody(const Body&); 01284 01291 MobilizedBody& setDefaultMassProperties(const MassProperties& m) { 01292 updBody().setDefaultRigidBodyMassProperties(m); // might not be allowed 01293 return *this; 01294 } 01295 01297 const MassProperties& getDefaultMassProperties() const { 01298 return getBody().getDefaultRigidBodyMassProperties(); // every body type can do this 01299 } 01300 01308 void adoptMotion(Motion& ownerHandle); 01309 01313 void clearMotion(); 01314 01318 bool hasMotion() const; 01319 01326 const Motion& getMotion() const; 01327 01333 MobilizedBody& setDefaultInboardFrame (const Transform& X_PF); 01339 MobilizedBody& setDefaultOutboardFrame(const Transform& X_BM); 01340 01345 const Transform& getDefaultInboardFrame() const; // X_PF 01349 const Transform& getDefaultOutboardFrame() const; // X_BM 01350 01356 operator MobilizedBodyIndex() const {return getMobilizedBodyIndex();} 01357 01363 MobilizedBodyIndex getMobilizedBodyIndex() const; 01364 01368 const MobilizedBody& getParentMobilizedBody() const; 01369 01374 const MobilizedBody& getBaseMobilizedBody() const; 01375 01379 const SimbodyMatterSubsystem& getMatterSubsystem() const; 01383 SimbodyMatterSubsystem& updMatterSubsystem(); 01384 01387 bool isInSubsystem() const; 01388 01392 bool isInSameSubsystem(const MobilizedBody&) const; 01393 01398 bool isSameMobilizedBody(const MobilizedBody& mBody) const; 01399 01402 bool isGround() const; 01403 01408 int getLevelInMultibodyTree() const; 01409 01413 MobilizedBody& cloneForNewParent(MobilizedBody& parent) const; 01414 01415 01416 // Utility operators // 01417 01422 Real getOneFromQPartition(const State&, int which, const Vector& qlike) const; 01423 01428 Real& updOneFromQPartition(const State&, int which, Vector& qlike) const; 01429 01433 Real getOneFromUPartition(const State&, int which, const Vector& ulike) const; 01434 01439 Real& updOneFromUPartition(const State&, int which, Vector& ulike) const; 01440 01446 void applyOneMobilityForce(const State& s, int which, Real f, 01447 Vector& mobilityForces) const 01448 { 01449 updOneFromUPartition(s,which,mobilityForces) += f; 01450 } 01451 01458 void applyBodyForce(const State& s, const SpatialVec& spatialForceInG, 01459 Vector_<SpatialVec>& bodyForcesInG) const; 01460 01466 void applyBodyTorque(const State& s, const Vec3& torqueInG, 01467 Vector_<SpatialVec>& bodyForcesInG) const; 01468 01478 void applyForceToBodyPoint(const State& s, const Vec3& pointInB, const Vec3& forceInG, 01479 Vector_<SpatialVec>& bodyForcesInG) const; 01480 01481 // End of Construction and Misc Methods. 01483 01485 // BUILT IN MOBILIZER DECLARATIONS // 01487 01488 // These are the built-in MobilizedBody types. Types on the same line are 01489 // synonymous. Each of these has a known number of coordinates and speeds 01490 // (at least a default number) so 01491 // can define routines which return and accept specific-size arguments, e.g. 01492 // Real (for 1-dof mobilizer) and Vec5 (for 5-dof mobilizer). Here is the 01493 // conventional interface that each built-in should provide. The base type 01494 // provides similar routines but using variable-sized or "one at a time" 01495 // arguments. (Vec<1> here will actually be a Real; assume the built-in 01496 // MobilizedBody class is "BuiltIn") 01497 // 01498 // BuiltIn& setDefaultQ(const Vec<nq>&); 01499 // const Vec<nq>& getDefaultQ() const; 01500 // 01501 // const Vec<nq>& getQ[Dot[Dot]](const State&) const; 01502 // const Vec<nu>& getU[Dot](const State&) const; 01503 // 01504 // void setQ(State&, const Vec<nq>&) const; 01505 // void setU(State&, const Vec<nu>&) const; 01506 // 01507 // const Vec<nq>& getMyPartQ(const State&, const Vector& qlike) const; 01508 // const Vec<nu>& getMyPartU(const State&, const Vector& ulike) const; 01509 // 01510 // Vec<nq>& updMyPartQ(const State&, Vector& qlike) const; 01511 // Vec<nu>& updMyPartU(const State&, Vector& ulike) const; 01512 // 01513 01514 01515 class Pin; typedef Pin Torsion; 01516 class Universal; 01517 class Cylinder; 01518 01519 class Weld; 01520 class Slider; typedef Slider Prismatic; 01521 class Translation2D; typedef Translation2D Cartesian2D, CartesianCoords2D; 01522 class Translation; typedef Translation Cartesian, CartesianCoords; 01523 class BendStretch; typedef BendStretch PolarCoords; 01524 class TorsionStretch; typedef TorsionStretch ConicalCoords2D; 01525 class SphericalCoords; 01526 class CylindricalCoords; 01527 class LineOrientation; 01528 01529 01530 class Planar; 01531 class Gimbal; 01532 class Ball; typedef Ball Orientation, Spherical; 01533 class Free; 01534 class FreeLine; 01535 class Screw; 01536 class Ellipsoid; 01537 class Custom; 01538 class Ground; 01539 class FunctionBased; 01540 01541 class PinImpl; 01542 class SliderImpl; 01543 class UniversalImpl; 01544 class CylinderImpl; 01545 class BendStretchImpl; 01546 class TorsionStretchImpl; 01547 class PlanarImpl; 01548 class GimbalImpl; 01549 class BallImpl; 01550 class TranslationImpl; 01551 class SphericalCoordsImpl; 01552 class FreeImpl; 01553 class LineOrientationImpl; 01554 class FreeLineImpl; 01555 class WeldImpl; 01556 class ScrewImpl; 01557 class EllipsoidImpl; 01558 class CustomImpl; 01559 class GroundImpl; 01560 class FunctionBasedImpl; 01561 01562 }; 01563 01567 class SimTK_SIMBODY_EXPORT MobilizedBody::Pin : public MobilizedBody { 01568 public: 01569 // SPECIALIZED INTERFACE FOR PIN MOBILIZER 01570 01571 // "Angle" is just a nicer name for a pin joint's lone generalized coordinate q. 01572 Pin& setDefaultAngle(Real angleInRadians) {return setDefaultQ(angleInRadians);} 01573 Real getDefaultAngle() const {return getDefaultQ();} 01574 01575 // Friendly, mobilizer-specific access to generalized coordinates and speeds. 01576 01577 void setAngle(State& s, Real angleInRadians) {setQ(s, angleInRadians);} 01578 Real getAngle(const State& s) const {return getQ(s);} 01579 01580 void setRate(State& s, Real rateInRadiansPerTime) {setU(s, rateInRadiansPerTime);} 01581 Real getRate(const State& s) const {return getU(s);} 01582 01583 // Mobility forces are "u-like", that is, one per dof. 01584 Real getAppliedPinTorque(const State& s, const Vector& mobilityForces) const { 01585 return getMyPartU(s,mobilityForces); 01586 } 01587 void applyPinTorque(const State& s, Real torque, Vector& mobilityForces) const { 01588 updMyPartU(s,mobilityForces) += torque; 01589 } 01590 01591 // STANDARDIZED MOBILIZED BODY INTERFACE 01592 01593 // required constructors 01594 explicit Pin(Direction=Forward); 01595 Pin(MobilizedBody& parent, const Body&, Direction=Forward); 01596 Pin(MobilizedBody& parent, const Transform& inbFrame, 01597 const Body&, const Transform& outbFrame, 01598 Direction=Forward); 01599 01600 // access to generalized coordinates q and generalized speeds u 01601 Pin& setDefaultQ(Real); 01602 Real getDefaultQ() const; 01603 01604 Real getQ(const State&) const; 01605 Real getQDot(const State&) const; 01606 Real getQDotDot(const State&) const; 01607 Real getU(const State&) const; 01608 Real getUDot(const State&) const; 01609 01610 void setQ(State&, Real) const; 01611 void setU(State&, Real) const; 01612 01613 Real getMyPartQ(const State&, const Vector& qlike) const; 01614 Real getMyPartU(const State&, const Vector& ulike) const; 01615 01616 Real& updMyPartQ(const State&, Vector& qlike) const; 01617 Real& updMyPartU(const State&, Vector& ulike) const; 01618 01619 // specialize return type for convenience 01620 Pin& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) 01621 { (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; } 01622 Pin& addOutboardDecoration(const Transform& X_MD, const DecorativeGeometry& g) 01623 { (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this; } 01624 Pin& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) 01625 { (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this; } 01626 Pin& setDefaultInboardFrame(const Transform& X_PF) 01627 { (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this; } 01628 Pin& setDefaultOutboardFrame(const Transform& X_BM) 01629 { (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this; } 01630 SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Pin, PinImpl, MobilizedBody); 01631 }; 01632 01636 class SimTK_SIMBODY_EXPORT MobilizedBody::Slider : public MobilizedBody { 01637 public: 01638 // SPECIALIZED INTERFACE FOR SLIDER MOBILIZER 01639 01640 // "Length" is just a nicer name for a sliding joint's lone generalized coordinate q. 01641 Slider& setDefaultLength(Real length) {return setDefaultQ(length);} 01642 Real getDefaultLength() const {return getDefaultQ();} 01643 01644 // Friendly, mobilizer-specific access to generalized coordinates and speeds. 01645 01646 void setLength(State& s, Real length) {setQ(s, length);} 01647 Real getLength(const State& s) const {return getQ(s);} 01648 01649 void setRate(State& s, Real rateInLengthPerTime) {setU(s, rateInLengthPerTime);} 01650 Real getRate(const State& s) const {return getU(s);} 01651 01652 // Mobility forces are "u-like", that is, one per dof. 01653 Real getAppliedForce(const State& s, const Vector& mobilityForces) const { 01654 return getMyPartU(s,mobilityForces); 01655 } 01656 void applyForce(const State& s, Real force, Vector& mobilityForces) const { 01657 updMyPartU(s,mobilityForces) += force; 01658 } 01659 01660 // STANDARDIZED MOBILIZED BODY INTERFACE 01661 01662 // required constructors 01663 explicit Slider(Direction=Forward); 01664 Slider(MobilizedBody& parent, const Body&, Direction=Forward); 01665 Slider(MobilizedBody& parent, const Transform& inbFrame, 01666 const Body&, const Transform& outbFrame, Direction=Forward); 01667 01668 // access to generalized coordinates q and generalized speeds u 01669 Slider& setDefaultQ(Real); 01670 Real getDefaultQ() const; 01671 01672 Real getQ(const State&) const; 01673 Real getQDot(const State&) const; 01674 Real getQDotDot(const State&) const; 01675 Real getU(const State&) const; 01676 Real getUDot(const State&) const; 01677 01678 void setQ(State&, Real) const; 01679 void setU(State&, Real) const; 01680 01681 Real getMyPartQ(const State&, const Vector& qlike) const; 01682 Real getMyPartU(const State&, const Vector& ulike) const; 01683 01684 Real& updMyPartQ(const State&, Vector& qlike) const; 01685 Real& updMyPartU(const State&, Vector& ulike) const; 01686 01687 // specialize return type for convenience 01688 Slider& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) 01689 { (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; } 01690 Slider& addOutboardDecoration(const Transform& X_MD, const DecorativeGeometry& g) 01691 { (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this; } 01692 Slider& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) 01693 { (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this; } 01694 Slider& setDefaultInboardFrame(const Transform& X_PF) 01695 { (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this; } 01696 Slider& setDefaultOutboardFrame(const Transform& X_BM) 01697 { (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this; } 01698 SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Slider, SliderImpl, MobilizedBody); 01699 }; 01700 01706 class SimTK_SIMBODY_EXPORT MobilizedBody::Screw : public MobilizedBody { 01707 public: 01708 explicit Screw(Real pitch, Direction=Forward); 01709 01712 Screw(MobilizedBody& parent, const Body&, Real pitch, Direction=Forward); 01713 01716 Screw(MobilizedBody& parent, const Transform& inbFrame, 01717 const Body&, const Transform& outbFrame, 01718 Real pitch, Direction=Forward); 01719 01720 Screw& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) { 01721 (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; 01722 } 01723 Screw& addOutboardDecoration(const Transform& X_MD, const DecorativeGeometry& g) { 01724 (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this; 01725 } 01726 Screw& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) { 01727 (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this; 01728 } 01729 01730 Screw& setDefaultInboardFrame(const Transform& X_PF) { 01731 (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this; 01732 } 01733 01734 Screw& setDefaultOutboardFrame(const Transform& X_BM) { 01735 (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this; 01736 } 01737 01738 Screw& setDefaultPitch(Real pitch); 01739 Real getDefaultPitch() const; 01740 01741 Screw& setDefaultQ(Real); 01742 Real getDefaultQ() const; 01743 01744 Real getQ(const State&) const; 01745 Real getQDot(const State&) const; 01746 Real getQDotDot(const State&) const; 01747 Real getU(const State&) const; 01748 Real getUDot(const State&) const; 01749 01750 void setQ(State&, Real) const; 01751 void setU(State&, Real) const; 01752 01753 Real getMyPartQ(const State&, const Vector& qlike) const; 01754 Real getMyPartU(const State&, const Vector& ulike) const; 01755 01756 Real& updMyPartQ(const State&, Vector& qlike) const; 01757 Real& updMyPartU(const State&, Vector& ulike) const; 01758 SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Screw, ScrewImpl, MobilizedBody); 01759 }; 01760 01764 class SimTK_SIMBODY_EXPORT MobilizedBody::Universal : public MobilizedBody { 01765 public: 01766 explicit Universal(Direction=Forward); 01767 01770 Universal(MobilizedBody& parent, const Body&, Direction=Forward); 01771 01774 Universal(MobilizedBody& parent, const Transform& inbFrame, 01775 const Body&, const Transform& outbFrame, Direction=Forward); 01776 01777 Universal& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) { 01778 (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; 01779 } 01780 Universal& addOutboardDecoration(const Transform& X_MD, const DecorativeGeometry& g) { 01781 (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this; 01782 } 01783 Universal& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) { 01784 (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this; 01785 } 01786 01787 Universal& setDefaultInboardFrame(const Transform& X_PF) { 01788 (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this; 01789 } 01790 01791 Universal& setDefaultOutboardFrame(const Transform& X_BM) { 01792 (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this; 01793 } 01794 SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Universal, UniversalImpl, MobilizedBody); 01795 }; 01796 01799 class SimTK_SIMBODY_EXPORT MobilizedBody::Cylinder : public MobilizedBody { 01800 public: 01801 explicit Cylinder(Direction=Forward); 01802 01805 Cylinder(MobilizedBody& parent, const Body&, Direction=Forward); 01806 01809 Cylinder(MobilizedBody& parent, const Transform& inbFrame, 01810 const Body&, const Transform& outbFrame, Direction=Forward); 01811 01812 Cylinder& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) { 01813 (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; 01814 } 01815 Cylinder& addOutboardDecoration(const Transform& X_MD, const DecorativeGeometry& g) { 01816 (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this; 01817 } 01818 Cylinder& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) { 01819 (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this; 01820 } 01821 01822 Cylinder& setDefaultInboardFrame(const Transform& X_PF) { 01823 (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this; 01824 } 01825 01826 Cylinder& setDefaultOutboardFrame(const Transform& X_BM) { 01827 (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this; 01828 } 01829 SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Cylinder, CylinderImpl, MobilizedBody); 01830 }; 01831 01840 class SimTK_SIMBODY_EXPORT MobilizedBody::BendStretch : public MobilizedBody { 01841 public: 01842 explicit BendStretch(Direction=Forward); 01843 01846 BendStretch(MobilizedBody& parent, const Body&, Direction=Forward); 01847 01850 BendStretch(MobilizedBody& parent, const Transform& inbFrame, 01851 const Body&, const Transform& outbFrame, Direction=Forward); 01852 01853 BendStretch& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) { 01854 (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; 01855 } 01856 BendStretch& addOutboardDecoration(const Transform& X_MD, const DecorativeGeometry& g) { 01857 (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this; 01858 } 01859 BendStretch& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) { 01860 (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this; 01861 } 01862 01863 BendStretch& setDefaultInboardFrame(const Transform& X_PF) { 01864 (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this; 01865 } 01866 01867 BendStretch& setDefaultOutboardFrame(const Transform& X_BM) { 01868 (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this; 01869 } 01870 SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(BendStretch, BendStretchImpl, MobilizedBody); 01871 }; 01872 01877 class SimTK_SIMBODY_EXPORT MobilizedBody::Planar : public MobilizedBody { 01878 public: 01879 explicit Planar(Direction=Forward); 01880 01883 Planar(MobilizedBody& parent, const Body&, Direction=Forward); 01884 01887 Planar(MobilizedBody& parent, const Transform& inbFrame, 01888 const Body&, const Transform& outbFrame, 01889 Direction=Forward); 01890 01891 Planar& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) { 01892 (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; 01893 } 01894 Planar& addOutboardDecoration(const Transform& X_MD, const DecorativeGeometry& g) { 01895 (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this; 01896 } 01897 Planar& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) { 01898 (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this; 01899 } 01900 01901 Planar& setDefaultInboardFrame(const Transform& X_PF) { 01902 (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this; 01903 } 01904 01905 Planar& setDefaultOutboardFrame(const Transform& X_BM) { 01906 (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this; 01907 } 01908 01909 // Friendly, mobilizer-specific access to coordinates and speeds. 01910 Planar& setDefaultAngle(Real a) { 01911 Vec3 q = getDefaultQ(); q[0] = a; setDefaultQ(q); 01912 return *this; 01913 } 01914 Planar& setDefaultTranslation(const Vec2& r) { 01915 Vec3 q = getDefaultQ(); q.updSubVec<2>(1) = r; setDefaultQ(q); 01916 return *this; 01917 } 01918 01919 Real getDefaultAngle() const {return getDefaultQ()[0];} 01920 const Vec2& getDefaultTranslation() const {return getDefaultQ().getSubVec<2>(1);} 01921 01922 void setAngle (State& s, Real a) {setOneQ(s,0,a);} 01923 void setTranslation(State& s, const Vec2& r) {setOneQ(s,1,r[0]); setOneQ(s,2,r[1]);} 01924 01925 Real getAngle(const State& s) const {return getQ(s)[0];} 01926 const Vec2& getTranslation(const State& s) const {return getQ(s).getSubVec<2>(1);} 01927 01928 // Generic default state Topology methods. 01929 const Vec3& getDefaultQ() const; 01930 Planar& setDefaultQ(const Vec3& q); 01931 01932 const Vec3& getQ(const State&) const; 01933 const Vec3& getQDot(const State&) const; 01934 const Vec3& getQDotDot(const State&) const; 01935 const Vec3& getU(const State&) const; 01936 const Vec3& getUDot(const State&) const; 01937 01938 void setQ(State&, const Vec3&) const; 01939 void setU(State&, const Vec3&) const; 01940 01941 const Vec3& getMyPartQ(const State&, const Vector& qlike) const; 01942 const Vec3& getMyPartU(const State&, const Vector& ulike) const; 01943 01944 Vec3& updMyPartQ(const State&, Vector& qlike) const; 01945 Vec3& updMyPartU(const State&, Vector& ulike) const; 01946 SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Planar, PlanarImpl, MobilizedBody); 01947 }; 01948 01973 class SimTK_SIMBODY_EXPORT MobilizedBody::SphericalCoords : public MobilizedBody { 01974 public: 01975 explicit SphericalCoords(Direction=Forward); 01976 01979 SphericalCoords(MobilizedBody& parent, const Body&, Direction=Forward); 01980 01985 SphericalCoords(MobilizedBody& parent, const Transform& inbFrame, 01986 const Body&, const Transform& outbFrame, 01987 Direction=Forward); 01988 01990 SphericalCoords(MobilizedBody& parent, const Transform& inbFrame, 01991 const Body&, const Transform& outbFrame, 01992 Real azimuthOffset, bool azimuthNegated, 01993 Real zenithOffset, bool zenithNegated, 01994 CoordinateAxis radialAxis, bool radialNegated, 01995 Direction=Forward); 01996 01997 SphericalCoords& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) { 01998 (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; 01999 } 02000 SphericalCoords& addOutboardDecoration(const Transform& X_MD, const DecorativeGeometry& g) { 02001 (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this; 02002 } 02003 SphericalCoords& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) { 02004 (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this; 02005 } 02006 02007 SphericalCoords& setDefaultInboardFrame(const Transform& X_PF) { 02008 (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this; 02009 } 02010 02011 SphericalCoords& setDefaultOutboardFrame(const Transform& X_BM) { 02012 (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this; 02013 } 02014 02015 // Friendly, mobilizer-specific access to coordinates and speeds. 02016 SphericalCoords& setDefaultAngles(const Vec2& a) { 02017 Vec3 q = getDefaultQ(); q.updSubVec<2>(0) = a; setDefaultQ(q); 02018 return *this; 02019 } 02020 SphericalCoords& setDefaultRadius(Real r) { 02021 Vec3 q = getDefaultQ(); q[2] = r; setDefaultQ(q); 02022 return *this; 02023 } 02024 SphericalCoords& setRadialAxis(CoordinateAxis); 02025 SphericalCoords& setNegateAzimuth(bool); 02026 SphericalCoords& setNegateZenith(bool); 02027 SphericalCoords& setNegateRadial(bool); 02028 02029 const Vec2& getDefaultAngles() const {return getDefaultQ().getSubVec<2>(0);} 02030 Real getDefaultTranslation() const {return getDefaultQ()[2];} 02031 02032 CoordinateAxis getRadialAxis() const; 02033 bool isAzimuthNegated() const; 02034 bool isZenithNegated() const; 02035 bool isRadialNegated() const; 02036 02037 void setAngles(State& s, const Vec2& a) {setOneQ(s,0,a[0]); setOneQ(s,1,a[1]);} 02038 void setRadius(State& s, Real r) {setOneQ(s,2,r);} 02039 02040 const Vec2& getAngles(const State& s) const {return getQ(s).getSubVec<2>(0);} 02041 Real getRadius(const State& s) const {return getQ(s)[2];} 02042 02043 // Generic default state Topology methods. 02044 const Vec3& getDefaultQ() const; 02045 SphericalCoords& setDefaultQ(const Vec3& q); 02046 02047 const Vec3& getQ(const State&) const; 02048 const Vec3& getQDot(const State&) const; 02049 const Vec3& getQDotDot(const State&) const; 02050 const Vec3& getU(const State&) const; 02051 const Vec3& getUDot(const State&) const; 02052 02053 void setQ(State&, const Vec3&) const; 02054 void setU(State&, const Vec3&) const; 02055 02056 const Vec3& getMyPartQ(const State&, const Vector& qlike) const; 02057 const Vec3& getMyPartU(const State&, const Vector& ulike) const; 02058 02059 Vec3& updMyPartQ(const State&, Vector& qlike) const; 02060 Vec3& updMyPartU(const State&, Vector& ulike) const; 02061 02062 SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(SphericalCoords, SphericalCoordsImpl, MobilizedBody); 02063 }; 02064 02068 class SimTK_SIMBODY_EXPORT MobilizedBody::Gimbal : public MobilizedBody { 02069 public: 02070 explicit Gimbal(Direction=Forward); 02071 02074 Gimbal(MobilizedBody& parent, const Body&, Direction=Forward); 02075 02078 Gimbal(MobilizedBody& parent, const Transform& inbFrame, 02079 const Body&, const Transform& outbFrame, Direction=Forward); 02080 02081 Gimbal& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) { 02082 (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; 02083 } 02084 Gimbal& addOutboardDecoration(const Transform& X_MD, const DecorativeGeometry& g) { 02085 (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this; 02086 } 02087 Gimbal& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) { 02088 (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this; 02089 } 02090 02091 Gimbal& setDefaultInboardFrame(const Transform& X_PF) { 02092 (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this; 02093 } 02094 02095 Gimbal& setDefaultOutboardFrame(const Transform& X_BM) { 02096 (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this; 02097 } 02098 02099 // This is just a nicer name for the generalized coordinate. 02100 Gimbal& setDefaultRotation(const Rotation& R_FM) { 02101 return setDefaultQ(R_FM.convertRotationToBodyFixedXYZ()); 02102 } 02103 Rotation getDefaultRotation() const { 02104 const Vec3& q = getDefaultQ(); 02105 return Rotation(BodyRotationSequence, 02106 q[0], XAxis, q[1], YAxis, q[2], ZAxis); 02107 } 02108 02109 // This is used only for visualization. 02110 Gimbal& setDefaultRadius(Real r); 02111 Real getDefaultRadius() const; 02112 02113 // Generic default state Topology methods. 02114 const Vec3& getDefaultQ() const; // X,Y,Z body-fixed Euler angles 02115 Gimbal& setDefaultQ(const Vec3& q); 02116 02117 const Vec3& getQ(const State&) const; 02118 const Vec3& getQDot(const State&) const; 02119 const Vec3& getQDotDot(const State&) const; 02120 const Vec3& getU(const State&) const; 02121 const Vec3& getUDot(const State&) const; 02122 02123 void setQ(State&, const Vec3&) const; 02124 void setU(State&, const Vec3&) const; 02125 02126 const Vec3& getMyPartQ(const State&, const Vector& qlike) const; 02127 const Vec3& getMyPartU(const State&, const Vector& ulike) const; 02128 02129 Vec3& updMyPartQ(const State&, Vector& qlike) const; 02130 Vec3& updMyPartU(const State&, Vector& ulike) const; 02131 SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Gimbal, GimbalImpl, MobilizedBody); 02132 }; 02133 02138 class SimTK_SIMBODY_EXPORT MobilizedBody::Ball : public MobilizedBody { 02139 public: 02140 explicit Ball(Direction=Forward); 02141 02144 Ball(MobilizedBody& parent, const Body&, Direction=Forward); 02145 02148 Ball(MobilizedBody& parent, const Transform& inbFrame, 02149 const Body&, const Transform& outbFrame, Direction=Forward); 02150 02151 Ball& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) { 02152 (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; 02153 } 02154 Ball& addOutboardDecoration(const Transform& X_MD, const DecorativeGeometry& g) { 02155 (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this; 02156 } 02157 Ball& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) { 02158 (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this; 02159 } 02160 02161 Ball& setDefaultInboardFrame(const Transform& X_PF) { 02162 (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this; 02163 } 02164 02165 Ball& setDefaultOutboardFrame(const Transform& X_BM) { 02166 (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this; 02167 } 02168 02169 // This is just a nicer name for the generalized coordinate. 02170 Ball& setDefaultRotation(const Rotation& R_FM) { 02171 return setDefaultQ(R_FM.convertRotationToQuaternion()); 02172 } 02173 Rotation getDefaultRotation() const {return Rotation(getDefaultQ());} 02174 02175 // This is used only for visualization. 02176 Ball& setDefaultRadius(Real r); 02177 Real getDefaultRadius() const; 02178 02179 // Generic default state Topology methods. 02180 const Quaternion& getDefaultQ() const; 02181 Ball& setDefaultQ(const Quaternion& q); 02182 02183 const Vec4& getQ(const State&) const; 02184 const Vec4& getQDot(const State&) const; 02185 const Vec4& getQDotDot(const State&) const; 02186 const Vec3& getU(const State&) const; 02187 const Vec3& getUDot(const State&) const; 02188 02189 void setQ(State&, const Vec4&) const; 02190 void setU(State&, const Vec3&) const; 02191 02192 const Vec4& getMyPartQ(const State&, const Vector& qlike) const; 02193 const Vec3& getMyPartU(const State&, const Vector& ulike) const; 02194 02195 Vec4& updMyPartQ(const State&, Vector& qlike) const; 02196 Vec3& updMyPartU(const State&, Vector& ulike) const; 02197 SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Ball, BallImpl, MobilizedBody); 02198 }; 02199 02204 class SimTK_SIMBODY_EXPORT MobilizedBody::Ellipsoid : public MobilizedBody { 02205 public: 02208 explicit Ellipsoid(Direction=Forward); // not very useful until radii are set, but has some defaults 02209 02212 Ellipsoid(MobilizedBody& parent, const Body&, Direction=Forward); 02213 02216 Ellipsoid(MobilizedBody& parent, const Transform& inbFrame, 02217 const Body&, const Transform& outbFrame, 02218 Direction=Forward); 02219 02223 Ellipsoid(MobilizedBody& parent, const Transform& inbFrame, 02224 const Body&, const Transform& outbFrame, 02225 const Vec3& radii, 02226 Direction=Forward); 02227 02228 Ellipsoid& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) { 02229 (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; 02230 } 02231 Ellipsoid& addOutboardDecoration(const Transform& X_MD, const DecorativeGeometry& g) { 02232 (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this; 02233 } 02234 Ellipsoid& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) { 02235 (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this; 02236 } 02237 02238 Ellipsoid& setDefaultInboardFrame(const Transform& X_PF) { 02239 (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this; 02240 } 02241 02242 Ellipsoid& setDefaultOutboardFrame(const Transform& X_BM) { 02243 (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this; 02244 } 02245 02246 // This is just a nicer name for the generalized coordinate. 02247 Ellipsoid& setDefaultRotation(const Rotation& R_FM) { 02248 return setDefaultQ(R_FM.convertRotationToQuaternion()); 02249 } 02250 Rotation getDefaultRotation() const {return Rotation(getDefaultQ());} 02251 02252 Ellipsoid& setDefaultRadii(const Vec3& r); 02253 const Vec3& getDefaultRadii() const; 02254 02255 // Generic default state Topology methods. 02256 const Quaternion& getDefaultQ() const; 02257 Quaternion& updDefaultQ(); 02258 Ellipsoid& setDefaultQ(const Quaternion& q) {updDefaultQ()=q; return *this;} 02259 02260 const Vec4& getQ(const State&) const; 02261 const Vec4& getQDot(const State&) const; 02262 const Vec4& getQDotDot(const State&) const; 02263 const Vec3& getU(const State&) const; 02264 const Vec3& getUDot(const State&) const; 02265 02266 void setQ(State&, const Vec4&) const; 02267 void setU(State&, const Vec3&) const; 02268 02269 const Vec4& getMyPartQ(const State&, const Vector& qlike) const; 02270 const Vec3& getMyPartU(const State&, const Vector& ulike) const; 02271 02272 Vec4& updMyPartQ(const State&, Vector& qlike) const; 02273 Vec3& updMyPartU(const State&, Vector& ulike) const; 02274 02275 SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Ellipsoid, EllipsoidImpl, MobilizedBody); 02276 }; 02277 02280 class SimTK_SIMBODY_EXPORT MobilizedBody::Translation : public MobilizedBody { 02281 public: 02282 explicit Translation(Direction=Forward); 02283 02286 Translation(MobilizedBody& parent, const Body&, Direction=Forward); 02287 02290 Translation(MobilizedBody& parent, const Transform& inbFrame, 02291 const Body&, const Transform& outbFrame, Direction=Forward); 02292 02293 Translation& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) { 02294 (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; 02295 } 02296 Translation& addOutboardDecoration(const Transform& X_MD, const DecorativeGeometry& g) { 02297 (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this; 02298 } 02299 Translation& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) { 02300 (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this; 02301 } 02302 02303 Translation& setDefaultInboardFrame(const Transform& X_PF) { 02304 (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this; 02305 } 02306 02307 Translation& setDefaultOutboardFrame(const Transform& X_BM) { 02308 (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this; 02309 } 02310 02311 // This is just a nicer name for setting this mobilizer's generalized coordinates, 02312 // which together constitute the vector from the F frame's origin to the M 02313 // frame's origin, expressed in F. 02314 02315 // Set the topological default values for the initial q's. 02316 Translation& setDefaultTranslation(const Vec3& p_FM) { 02317 return setDefaultQ(p_FM); 02318 } 02319 02320 // Get the topological default values for the initial q's. 02321 const Vec3& getDefaultTranslation() const { 02322 return getDefaultQ(); 02323 } 02324 02325 // Set the current value of q's in the given State. Note that this is 02326 // the *cross-mobilizer* translation, not location in the Ground frame. 02327 void setMobilizerTranslation(State& s, const Vec3& p_FM) const { 02328 setQ(s,p_FM); 02329 } 02330 02331 // Get the current value of the q's for this mobilizer from the given State. 02332 const Vec3& getMobilizerTranslation(const State& s) const { 02333 return getQ(s); 02334 } 02335 02336 02337 // Set the current value of u's in the given State. Note that this is 02338 // the *cross-mobilizer* velocity v_FM, not velocity in the Ground frame. 02339 void setMobilizerVelocity(State& s, const Vec3& v_FM) const { 02340 setU(s,v_FM); 02341 } 02342 02343 // Get the current value of the u's for this mobilizer from the given State. 02344 const Vec3& getMobilizerVelocity(const State& s) const { 02345 return getU(s); 02346 } 02347 02348 // Get the value of the udot's for this mobilizer from the given State. 02349 const Vec3& getMobilizerAcceleration(const State& s) const { 02350 return getUDot(s); 02351 } 02352 02353 // Generic default state Topology methods. 02354 const Vec3& getDefaultQ() const; 02355 Translation& setDefaultQ(const Vec3& q); 02356 02357 const Vec3& getQ(const State&) const; 02358 const Vec3& getQDot(const State&) const; 02359 const Vec3& getQDotDot(const State&) const; 02360 const Vec3& getU(const State&) const; 02361 const Vec3& getUDot(const State&) const; 02362 02363 void setQ(State&, const Vec3&) const; 02364 void setU(State&, const Vec3&) const; 02365 02366 const Vec3& getMyPartQ(const State&, const Vector& qlike) const; 02367 const Vec3& getMyPartU(const State&, const Vector& ulike) const; 02368 02369 Vec3& updMyPartQ(const State&, Vector& qlike) const; 02370 Vec3& updMyPartU(const State&, Vector& ulike) const; 02371 SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Translation, TranslationImpl, MobilizedBody); 02372 }; 02373 02380 class SimTK_SIMBODY_EXPORT MobilizedBody::Free : public MobilizedBody { 02381 public: 02382 explicit Free(Direction=Forward); 02383 02386 Free(MobilizedBody& parent, const Body&, Direction=Forward); 02387 02390 Free(MobilizedBody& parent, const Transform& inbFrame, 02391 const Body&, const Transform& outbFrame, 02392 Direction=Forward); 02393 02394 Free& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) { 02395 (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; 02396 } 02397 Free& addOutboardDecoration(const Transform& X_MD, const DecorativeGeometry& g) { 02398 (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this; 02399 } 02400 Free& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) { 02401 (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this; 02402 } 02403 02404 Free& setDefaultInboardFrame(const Transform& X_PF) { 02405 (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this; 02406 } 02407 02408 Free& setDefaultOutboardFrame(const Transform& X_BM) { 02409 (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this; 02410 } 02411 02412 // Leaves rotation unchanged. 02413 Free& setDefaultTranslation(const Vec3&); 02414 02415 // Leaves translation unchanged. The internal representation is a quaternion 02416 // so we guarantee that the stored value is numerically identical to the 02417 // supplied one. 02418 Free& setDefaultQuaternion(const Quaternion&); 02419 02420 // Leaves translation unchanged. The Rotation matrix will be converted to 02421 // a quaternion for storage. 02422 Free& setDefaultRotation(const Rotation&); 02423 // Sets both translation and rotation. The Rotation part of the Transform 02424 // will be converted to a quaternion for storage. 02425 Free& setDefaultTransform(const Transform&); 02426 02427 // These return references to the stored default values. 02428 const Vec3& getDefaultTranslation() const; 02429 const Quaternion& getDefaultQuaternion() const; 02430 02431 // These next two are derived from the stored values. 02432 Rotation getDefaultRotation() const { 02433 return Rotation(getDefaultQuaternion()); 02434 } 02435 Transform getDefaultTransform() const { 02436 return Transform(Rotation(getDefaultQuaternion()), getDefaultTranslation()); 02437 } 02438 02439 // Generic default state Topology methods. 02440 02441 // Returns (Vec4,Vec3) where the Vec4 is a normalized quaternion. 02442 const Vec7& getDefaultQ() const; 02443 02444 // Interprets the supplied q as (Vec4,Vec3) where the Vec4 is a possibly 02445 // unnormalized quaternion. The quaternion will be normalized before it is 02446 // stored here, so you may not get back exactly the value supplied here if 02447 // you call getDefaultQ(). 02448 Free& setDefaultQ(const Vec7& q); 02449 02450 // Note that there is no guarantee that the quaternion part of the returned Q is normalized. 02451 const Vec7& getQ(const State&) const; 02452 const Vec7& getQDot(const State&) const; 02453 const Vec7& getQDotDot(const State&) const; 02454 02455 const Vec6& getU(const State&) const; 02456 const Vec6& getUDot(const State&) const; 02457 02458 // The Q's in the state are set exactly as supplied without normalization. 02459 void setQ(State&, const Vec7&) const; 02460 void setU(State&, const Vec6&) const; 02461 02462 const Vec7& getMyPartQ(const State&, const Vector& qlike) const; 02463 const Vec6& getMyPartU(const State&, const Vector& ulike) const; 02464 02465 Vec7& updMyPartQ(const State&, Vector& qlike) const; 02466 Vec6& updMyPartU(const State&, Vector& ulike) const; 02467 SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Free, FreeImpl, MobilizedBody); 02468 }; 02469 02470 02471 // These are special "ball" and "free" joints designed to allow arbitrary orientations 02472 // for "linear" bodies, such as a CO2 molecule consisting only of point masses arranged 02473 // along a straight line. Such bodies have no inertia about the line and cause singularities 02474 // in the equations of motion if attached to Orientation or Free mobilizers. Instead, use the 02475 // LineOrientation and LineFree moblizers, making sure that the inertialess direction is 02476 // along the outboard body's z axis (that is, Mz). These mobilizers introduce only two 02477 // mobilities (generalized speeds u), being incapable of representing non-zero angular 02478 // velocity of M in F about Mz. The generalized speeds are in fact the wx and wy 02479 // components of w_FM_M, that is, the x and y components of the angular velocity of M 02480 // in F *expressed in M*. However, at least three generalized coordinates (q's) 02481 // are required to represent the orientation. By default we use four quaternions for 02482 // unconditional stability. Alternatively, you can request a 1-2-3 body fixed 02483 // Euler angle sequence (that is, about x, then new y, then new z) which will 02484 // suffer a singularity when the y rotation is 90 degrees since that aligns the 02485 // first rotation axis (x) with the last (z) which is the inertialess direction. 02486 02492 class SimTK_SIMBODY_EXPORT MobilizedBody::LineOrientation : public MobilizedBody { 02493 public: 02494 explicit LineOrientation(Direction=Forward); 02495 02498 LineOrientation(MobilizedBody& parent, const Body&, Direction=Forward); 02499 02502 LineOrientation(MobilizedBody& parent, const Transform& inbFrame, 02503 const Body&, const Transform& outbFrame, Direction=Forward); 02504 02505 LineOrientation& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) { 02506 (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; 02507 } 02508 LineOrientation& addOutboardDecoration(const Transform& X_MD, const DecorativeGeometry& g) { 02509 (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this; 02510 } 02511 LineOrientation& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) { 02512 (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this; 02513 } 02514 02515 LineOrientation& setDefaultInboardFrame(const Transform& X_PF) { 02516 (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this; 02517 } 02518 02519 LineOrientation& setDefaultOutboardFrame(const Transform& X_BM) { 02520 (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this; 02521 } 02522 02523 // This is just a nicer name for the generalized coordinate. 02524 LineOrientation& setDefaultRotation(const Rotation& R_FM) { 02525 return setDefaultQ(R_FM.convertRotationToQuaternion()); 02526 } 02527 Rotation getDefaultRotation() const {return Rotation(getDefaultQ());} 02528 02529 // Generic default state Topology methods. 02530 const Quaternion& getDefaultQ() const; 02531 LineOrientation& setDefaultQ(const Quaternion& q); 02532 02533 const Vec4& getQ(const State&) const; 02534 const Vec4& getQDot(const State&) const; 02535 const Vec4& getQDotDot(const State&) const; 02536 const Vec2& getU(const State&) const; 02537 const Vec2& getUDot(const State&) const; 02538 02539 void setQ(State&, const Vec4&) const; 02540 void setU(State&, const Vec2&) const; 02541 02542 const Vec4& getMyPartQ(const State&, const Vector& qlike) const; 02543 const Vec2& getMyPartU(const State&, const Vector& ulike) const; 02544 02545 Vec4& updMyPartQ(const State&, Vector& qlike) const; 02546 Vec2& updMyPartU(const State&, Vector& ulike) const; 02547 SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(LineOrientation, LineOrientationImpl, MobilizedBody); 02548 }; 02549 02554 class SimTK_SIMBODY_EXPORT MobilizedBody::FreeLine : public MobilizedBody { 02555 public: 02556 explicit FreeLine(Direction=Forward); 02557 02560 FreeLine(MobilizedBody& parent, const Body&, Direction=Forward); 02561 02564 FreeLine(MobilizedBody& parent, const Transform& inbFrame, 02565 const Body&, const Transform& outbFrame, Direction=Forward); 02566 02567 FreeLine& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) { 02568 (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; 02569 } 02570 FreeLine& addOutboardDecoration(const Transform& X_MD, const DecorativeGeometry& g) { 02571 (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this; 02572 } 02573 FreeLine& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) { 02574 (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this; 02575 } 02576 02577 FreeLine& setDefaultInboardFrame(const Transform& X_PF) { 02578 (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this; 02579 } 02580 02581 FreeLine& setDefaultOutboardFrame(const Transform& X_BM) { 02582 (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this; 02583 } 02584 SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(FreeLine, FreeLineImpl, MobilizedBody); 02585 }; 02586 02589 class SimTK_SIMBODY_EXPORT MobilizedBody::Weld : public MobilizedBody { 02590 public: 02593 Weld(); 02594 02597 Weld(MobilizedBody& parent, const Body&); 02598 02601 Weld(MobilizedBody& parent, const Transform& inbFrame, 02602 const Body&, const Transform& outbFrame); 02603 02604 Weld& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) { 02605 (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; 02606 } 02607 Weld& addOutboardDecoration(const Transform& X_MD, const DecorativeGeometry& g) { 02608 (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this; 02609 } 02610 Weld& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) { 02611 (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this; 02612 } 02613 02614 Weld& setDefaultInboardFrame(const Transform& X_PF) { 02615 (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this; 02616 } 02617 02618 Weld& setDefaultOutboardFrame(const Transform& X_BM) { 02619 (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this; 02620 } 02621 SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Weld, WeldImpl, MobilizedBody); 02622 }; 02623 02624 02628 class SimTK_SIMBODY_EXPORT MobilizedBody::Ground : public MobilizedBody { 02629 public: 02631 Ground(); 02632 Ground& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) { 02633 (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; 02634 } 02635 SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Ground, GroundImpl, MobilizedBody); 02636 }; 02637 02638 02670 class SimTK_SIMBODY_EXPORT MobilizedBody::Custom : public MobilizedBody { 02671 public: 02672 class Implementation; 02673 class ImplementationImpl; 02674 02675 /* Create a Custom MobilizedBody. 02676 * 02677 * @param parent the MobilizedBody's parent body 02678 * @param implementation the object which implements the custom mobilized body. The MobilizedBody::Custom takes over 02679 * ownership of the implementation object, and deletes it when the MobilizedBody itself 02680 * is deleted. 02681 * @param body describes this MobilizedBody's physical properties 02682 * @param direction whether you want the coordinates defined as though parent & child were swapped 02683 */ 02684 Custom(MobilizedBody& parent, Implementation* implementation, const Body& body, Direction direction=Forward); 02685 /* Create a Custom MobilizedBody. 02686 * 02687 * @param parent the MobilizedBody's parent body 02688 * @param implementation the object which implements the custom mobilized body. The MobilizedBody::Custom takes over 02689 * ownership of the implementation object, and deletes it when the MobilizedBody itself 02690 * is deleted. 02691 * @param inbFrame the MobilizedBody's inboard reference frame 02692 * @param body describes this MobilizedBody's physical properties 02693 * @param outbFrame the MobilizedBody's outboard reference frame 02694 * @param direction whether you want the coordinates defined as though parent & child were swapped 02695 */ 02696 Custom(MobilizedBody& parent, Implementation* implementation, 02697 const Transform& inbFrame, const Body& body, const Transform& outbFrame, 02698 Direction direction=Forward); 02699 SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Custom, CustomImpl, MobilizedBody); 02700 protected: 02701 const Implementation& getImplementation() const; 02702 Implementation& updImplementation(); 02703 02704 Custom() {} 02705 }; 02706 02707 // We only want the template instantiation to occur once. This symbol is defined in the SimTK core 02708 // compilation unit that defines the MobilizedBody class but should not be defined any other time. 02709 // BE SURE TO DEAL WITH THIS IN MobilizedBody_Instantiation.cpp. 02710 #ifndef SimTK_SIMBODY_DEFINING_MOBILIZED_BODY 02711 extern template class PIMPLHandle<MobilizedBody::Custom::Implementation, MobilizedBody::Custom::ImplementationImpl>; 02712 #endif 02713 02714 02715 class SimTK_SIMBODY_EXPORT MobilizedBody::Custom::Implementation 02716 : public PIMPLHandle<Implementation,ImplementationImpl> 02717 { 02718 public: 02719 // No default constructor because you have to supply at least the SimbodyMatterSubsystem 02720 // to which this MobilizedBody belongs. 02721 02723 virtual ~Implementation(); 02724 02729 virtual Implementation* clone() const = 0; 02730 02754 Implementation(SimbodyMatterSubsystem&, int nu, int nq, int nAngles=0); 02755 02759 Vector getQ(const State& s) const; 02760 02762 Vector getU(const State& s) const; 02763 02767 Vector getQDot(const State& s) const; 02768 02770 Vector getUDot(const State& s) const; 02771 02775 Vector getQDotDot(const State& s) const; 02776 02781 Transform getMobilizerTransform(const State& s) const; 02782 02789 SpatialVec getMobilizerVelocity(const State& s) const; 02790 02799 bool getUseEulerAngles(const State& s) const; 02800 02807 void invalidateTopologyCache() const; 02808 02813 02814 02819 virtual Transform calcMobilizerTransformFromQ(const State& s, int nq, const Real* q) const = 0; 02820 02821 02838 virtual SpatialVec multiplyByHMatrix(const State& s, int nu, const Real* u) const = 0; 02839 02848 virtual void multiplyByHTranspose(const State& s, const SpatialVec& F, int nu, Real* f) const = 0; 02849 02859 virtual SpatialVec multiplyByHDotMatrix(const State& s, int nu, const Real* u) const = 0; 02860 02869 virtual void multiplyByHDotTranspose(const State& s, const SpatialVec& F, int nu, Real* f) const = 0; 02870 02881 virtual void multiplyByN(const State& s, bool transposeMatrix, 02882 int nIn, const Real* in, int nOut, Real* out) const; 02883 02894 virtual void multiplyByNInv(const State& s, bool transposeMatrix, 02895 int nIn, const Real* in, int nOut, Real* out) const; 02896 02907 virtual void multiplyByNDot(const State& s, bool transposeMatrix, 02908 int nIn, const Real* in, int nOut, Real* out) const; 02909 02910 // Methods for setting Mobilizer initial conditions. Note -- I've stripped this 02911 // down to the two basic routines but the built-ins have 8 so that you can 02912 // specify only rotations or translations. I'm not sure that's needed here and 02913 // I suppose you could add more routines later if needed. 02914 // Eventually it might be nice to provide default implementation here that would 02915 // use a root finder to attempt to solve these initial condition problems. For 02916 // most joints there is a much more direct way to do it, and sometimes there 02917 // are behavioral choices to make, which is why it is nice to have mobilizer-specific 02918 // overrides for these. 02919 02928 virtual void setQToFitTransform(const State&, const Transform& X_FM, int nq, Real* q) const; 02929 02941 virtual void setUToFitVelocity(const State&, const SpatialVec& V_FM, int nu, Real* u) const; 02942 02949 virtual void calcDecorativeGeometryAndAppend 02950 (const State& s, Stage stage, Array_<DecorativeGeometry>& geom) const 02951 { 02952 } 02954 02955 02964 02966 02967 02968 02969 02970 02971 02972 02973 02974 virtual void realizeTopology(State&) const { } 02975 02984 virtual void realizeModel(State&) const { } 02985 02989 virtual void realizeInstance(const State&) const { } 02990 02995 virtual void realizeTime(const State&) const { } 02996 03003 virtual void realizePosition(const State&) const { } 03004 03011 virtual void realizeVelocity(const State&) const { } 03012 03019 virtual void realizeDynamics(const State&) const { } 03020 03027 virtual void realizeAcceleration(const State&) const { } 03028 03034 virtual void realizeReport(const State&) const { } 03036 03037 friend class MobilizedBody::CustomImpl; 03038 }; 03039 03051 class SimTK_SIMBODY_EXPORT MobilizedBody::FunctionBased : public MobilizedBody::Custom { 03052 public: 03053 /* Create a FunctionBased MobilizedBody. 03054 * 03055 * @param parent the MobilizedBody's parent body 03056 * @param body describes this MobilizedBody's physical properties 03057 * @param nmobilities the number of generalized coordinates belonging to this MobilizedBody 03058 * @param functions the Functions describing how the body moves based on its generalized coordinates. 03059 * This must be of length 6. The elements correspond to, in order, x rotation, y rotation, z rotation, 03060 * x translation, y translation, and z translation. The MobilizedBody takes over ownership of the functions, 03061 * and automatically deletes them when the MobilizedBody is deleted. 03062 * @param coordIndices the indices of the generalized coordinates that are inputs to each function. For example, if coordIndices[2] = {0, 1}, 03063 * that means that functions[2] takes two input arguments, and q[0] and q[1] respectively should be passed as those arguments. 03064 * @param direction whether you want the coordinates defined as though parent & child were swapped 03065 */ 03066 FunctionBased(MobilizedBody& parent, const Body& body, 03067 int nmobilities, const Array_<const Function*>& functions, 03068 const Array_<Array_<int> >& coordIndices, 03069 Direction direction=Forward); 03070 03072 FunctionBased(MobilizedBody& parent, const Body& body, 03073 int nmobilities, const std::vector<const Function*>& functions, 03074 const std::vector<std::vector<int> >& coordIndices, 03075 Direction direction=Forward) 03076 { 03077 Array_< Array_<int> > coordCopy(coordIndices); // sorry, must copy 03078 // Use the above constructor. 03079 new(this) FunctionBased(parent,body,nmobilities, 03080 ArrayViewConst_<const Function*>(functions), 03081 coordCopy, direction); 03082 } 03083 03084 /* Create a FunctionBased MobilizedBody. 03085 * 03086 * @param parent the MobilizedBody's parent body 03087 * @param inbFrame the default inboard frame 03088 * @param body describes this MobilizedBody's physical properties 03089 * @param outbFrame the default outboard frame 03090 * @param nmobilities the number of generalized coordinates belonging to this MobilizedBody 03091 * @param functions the Functions describing how the body moves based on its generalized coordinates. 03092 * This must be of length 6. The elements correspond to, in order, x rotation, y rotation, z rotation, 03093 * x translation, y translation, and z translation. The MobilizedBody takes over ownership of the functions, 03094 * and automatically deletes them when the MobilizedBody is deleted. 03095 * @param coordIndices the indices of the generalized coordinates that are inputs to each function. For example, if coordIndices[2] = {0, 1}, 03096 * that means that functions[2] takes two input arguments, and q[0] and q[1] respectively should be passed as those arguments. 03097 * @param direction whether you want the coordinates defined as though parent & child were swapped 03098 */ 03099 FunctionBased(MobilizedBody& parent, const Transform& inbFrame, 03100 const Body& body, const Transform& outbFrame, 03101 int nmobilities, const Array_<const Function*>& functions, 03102 const Array_<Array_<int> >& coordIndices, 03103 Direction direction=Forward); 03104 03106 FunctionBased(MobilizedBody& parent, const Transform& inbFrame, 03107 const Body& body, const Transform& outbFrame, 03108 int nmobilities, const std::vector<const Function*>& functions, 03109 const std::vector<std::vector<int> >& coordIndices, 03110 Direction direction=Forward) 03111 { 03112 Array_< Array_<int> > coordCopy(coordIndices); // sorry, must copy 03113 // Use the above constructor. 03114 new(this) FunctionBased(parent,inbFrame,body,outbFrame, 03115 nmobilities, ArrayViewConst_<const Function*>(functions), 03116 coordCopy, direction); 03117 } 03118 03119 /* Create a FunctionBased MobilizedBody. 03120 * 03121 * @param parent the MobilizedBody's parent body 03122 * @param body describes this MobilizedBody's physical properties 03123 * @param nmobilities the number of generalized coordinates belonging to this MobilizedBody 03124 * @param functions the Functions describing how the body moves based on its generalized coordinates. 03125 * This must be of length 6. The elements correspond to, in order, x rotation, y rotation, z rotation, 03126 * x translation, y translation, and z translation. The MobilizedBody takes over ownership of the functions, 03127 * and automatically deletes them when the MobilizedBody is deleted. 03128 * @param coordIndices the indices of the generalized coordinates that are inputs to each function. For example, if coordIndices[2] = {0, 1}, 03129 * that means that functions[2] takes two input arguments, and q[0] and q[1] respectively should be passed as those arguments. 03130 * @param axes the axes directions (as Vec3's) for each spatial coordinate, which each function describes, and is therefore length 6. 03131 * First 3 and last 3 axes must be linearly independent, otherwise there will be redundant speeds for the same motion. 03132 * @param direction whether you want the coordinates defined as though parent & child were swapped 03133 */ 03134 FunctionBased(MobilizedBody& parent, const Body& body, 03135 int nmobilities, const Array_<const Function*>& functions, 03136 const Array_<Array_<int> >& coordIndices, const Array_<Vec3>& axes, 03137 Direction direction=Forward); 03138 03140 FunctionBased(MobilizedBody& parent, const Body& body, 03141 int nmobilities, const std::vector<const Function*>& functions, 03142 const std::vector<std::vector<int> >& coordIndices, const std::vector<Vec3>& axes, 03143 Direction direction=Forward) 03144 { 03145 Array_< Array_<int> > coordCopy(coordIndices); // sorry, must copy 03146 // Use the above constructor. 03147 new(this) FunctionBased(parent,body, 03148 nmobilities, ArrayViewConst_<const Function*>(functions), 03149 coordCopy, ArrayViewConst_<Vec3>(axes), 03150 direction); 03151 } 03152 03153 /* Create a FunctionBased MobilizedBody. 03154 * 03155 * @param parent the MobilizedBody's parent body 03156 * @param inbFrame the default inboard frame 03157 * @param body describes this MobilizedBody's physical properties 03158 * @param outbFrame the default outboard frame 03159 * @param nmobilities the number of generalized coordinates belonging to this MobilizedBody 03160 * @param functions the Functions describing how the body moves based on its generalized coordinates. 03161 * This must be of length 6. The elements correspond to, in order, x rotation, y rotation, z rotation, 03162 * x translation, y translation, and z translation. The MobilizedBody takes over ownership of the functions, 03163 * and automatically deletes them when the MobilizedBody is deleted. 03164 * @param coordIndices the indices of the generalized coordinates that are inputs to each function. For example, if coordIndices[2] = {0, 1}, 03165 * that means that functions[2] takes two input arguments, and q[0] and q[1] respectively should be passed as those arguments. 03166 * @param axes the axes directions (as Vec3's) for each spatial coordinate, which each function describes, and is therefore length 6. 03167 * First 3 and last 3 axes must be linearly independent, otherwise there will be redundant speeds for the same motion. 03168 * @param direction whether you want the coordinates defined as though parent & child were swapped 03169 */ 03170 FunctionBased(MobilizedBody& parent, const Transform& inbFrame, 03171 const Body& body, const Transform& outbFrame, 03172 int nmobilities, const Array_<const Function*>& functions, 03173 const Array_<Array_<int> >& coordIndices, const Array_<Vec3>& axes, 03174 Direction direction=Forward); 03175 03177 FunctionBased(MobilizedBody& parent, const Transform& inbFrame, 03178 const Body& body, const Transform& outbFrame, 03179 int nmobilities, const std::vector<const Function*>& functions, 03180 const std::vector<std::vector<int> >& coordIndices, const std::vector<Vec3>& axes, 03181 Direction direction=Forward) 03182 { 03183 Array_< Array_<int> > coordCopy(coordIndices); // sorry, must copy 03184 // Use the above constructor. 03185 new(this) FunctionBased(parent,inbFrame,body,outbFrame, 03186 nmobilities, ArrayViewConst_<const Function*>(functions), 03187 coordCopy, ArrayViewConst_<Vec3>(axes), 03188 direction); 03189 } 03190 private: 03191 FunctionBased() {} 03192 }; 03193 03194 } // namespace SimTK 03195 03196 #endif // SimTK_SIMBODY_MOBILIZED_BODY_H_ 03197 03198 03199