MobilizedBody.h

Go to the documentation of this file.
00001 #ifndef SimTK_SIMBODY_MOBILIZED_BODY_H_
00002 #define SimTK_SIMBODY_MOBILIZED_BODY_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                      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-8 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 
00046 #include "SimTKmath.h"
00047 #include "simbody/internal/common.h"
00048 #include "simbody/internal/Body.h"
00049 
00050 #include <cassert>
00051 #include <vector>
00052 
00053 namespace SimTK {
00054 
00055 class SimbodyMatterSubsystem;
00056 class MobilizedBody;
00057 class MobilizedBodyImpl;
00058 
00059 // We only want the template instantiation to occur once. This symbol is defined in the SimTK core
00060 // compilation unit that instantiates the mobilized body class but should not be defined any other time.
00061 #ifndef SimTK_SIMBODY_DEFINING_MOBILIZED_BODY
00062     extern template class PIMPLHandle<MobilizedBody, MobilizedBodyImpl, true>;
00063 #endif
00064 
00112 class SimTK_SIMBODY_EXPORT MobilizedBody : public PIMPLHandle<MobilizedBody, MobilizedBodyImpl, true> {
00113 public:
00114 
00115 
00117         // STATE ACCESS METHODS //
00119 
00123 
00124 
00137     const Transform& getBodyTransform(const State&) const; // X_GB
00138 
00147     const Rotation& getBodyRotation(const State& s) const {
00148         return getBodyTransform(s).R();
00149     }
00154     const Vec3& getBodyOriginLocation(const State& s) const {
00155         return getBodyTransform(s).T();
00156     }
00157 
00161     const Transform& getMobilizerTransform(const State&) const; // X_FM
00162 
00168     const SpatialVec& getBodyVelocity(const State&) const;          // V_GB
00169 
00173     const Vec3& getBodyAngularVelocity(const State& s) const {      // w_GB
00174         return getBodyVelocity(s)[0]; 
00175     }
00181     const Vec3& getBodyOriginVelocity(const State& s) const {       // v_GB
00182         return getBodyVelocity(s)[1];
00183     }
00184 
00190     const SpatialVec& getMobilizerVelocity(const State&) const;     // V_FM
00191 
00197     const SpatialVec& getBodyAcceleration(const State& s) const;    // A_GB
00198 
00202     const Vec3& getBodyAngularAcceleration(const State& s) const {  // b_GB
00203         return getBodyAcceleration(s)[0]; 
00204     }
00205 
00210     const Vec3& getBodyOriginAcceleration(const State& s) const {   // a_GB
00211         return getBodyAcceleration(s)[1];
00212     }
00213 
00219     const SpatialVec& getMobilizerAcceleration(const State&) const { // A_FM
00220         SimTK_ASSERT_ALWAYS(!"unimplemented method", 
00221             "MobilizedBody::getMobilizerAcceleration() is not yet implemented -- any volunteers?");
00222         return *(new SpatialVec());
00223     }
00224 
00227     const MassProperties& getBodyMassProperties(const State&) const;
00228 
00230     Real getBodyMass(const State& s) const {
00231         return getBodyMassProperties(s).getMass();
00232     }
00233 
00237     const Vec3& getBodyMassCenterStation(const State& s) const {
00238         return getBodyMassProperties(s).getMassCenter();
00239     }
00240 
00244     const Inertia& getBodyInertiaAboutBodyOrigin(const State& s) const {
00245         return getBodyMassProperties(s).getInertia();
00246     }
00247 
00252     const Transform& getInboardFrame (const State&) const;  // X_PF
00257     const Transform& getOutboardFrame(const State&) const;  // X_BM
00258 
00261     void setInboardFrame (State&, const Transform& X_PF) const;
00264     void setOutboardFrame(State&, const Transform& X_BM) const;
00265 
00266     // End of State Access - Bodies
00268 
00272 
00273 
00274 
00275     int getNumQ(const State&) const;
00278     int getNumU(const State&) const;
00279 
00283     Real getOneQ(const State&, int which) const;
00284 
00288     Real getOneU(const State&, int which) const;
00289 
00293     Vector getQAsVector(const State&) const;
00297     Vector getUAsVector(const State&) const;
00298 
00302     Real getOneQDot   (const State&, int which) const;
00306     Vector getQDotAsVector(const State&) const;
00307 
00311     Real getOneUDot   (const State&, int which) const;
00315     Real getOneQDotDot(const State&, int which) const;
00319     Vector getUDotAsVector   (const State&) const;
00323     Vector getQDotDotAsVector(const State&) const;
00324 
00328     void setOneQ(State&, int which, Real v) const;
00332     void setOneU(State&, int which, Real v) const;
00333 
00336     void setQFromVector(State& s, const Vector& v) const;
00339     void setUFromVector(State& s, const Vector& v) const;
00340 
00376 
00377     void setQToFitTransform      (State&, const Transform& X_FM) const;
00382     void setQToFitRotation       (State&, const Rotation&  R_FM) const;
00388     void setQToFitTranslation    (State&, const Vec3&      p_FM) const;
00389 
00396     void setUToFitVelocity          (State&, const SpatialVec& V_FM) const;
00403     void setUToFitAngularVelocity   (State&, const Vec3&       w_FM) const;
00410     void setUToFitLinearVelocity    (State&, const Vec3&       v_FM) const;
00411 
00412     // End of State Access Methods.
00414 
00416         // BASIC OPERATORS //
00418 
00420 
00443 
00445 
00451     Transform findBodyTransformInAnotherBody(const State& s, 
00452                                              const MobilizedBody& inBodyA) const
00453     {
00454         const Transform& X_GA = inBodyA.getBodyTransform(s);
00455         const Transform& X_GB = this->getBodyTransform(s);
00456 
00457         return ~X_GA*X_GB; // X_AB=X_AG*X_GB
00458     }
00459 
00465     Rotation findBodyRotationInAnotherBody(const State& s, 
00466                                             const MobilizedBody& inBodyA) const
00467     {
00468         const Rotation& R_GA = inBodyA.getBodyRotation(s);
00469         const Rotation& R_GB = this->getBodyRotation(s);
00470 
00471         return ~R_GA*R_GB; // R_AB=R_AG*R_GB
00472     }
00473 
00479     Vec3 findBodyOriginLocationInAnotherBody(const State& s, const MobilizedBody& toBodyA) const {
00480         return toBodyA.findStationAtGroundPoint(s,getBodyOriginLocation(s));
00481     }
00482 
00488     SpatialVec findBodyVelocityInAnotherBody(const State& s,
00489                                              const MobilizedBody& inBodyA) const
00490     {
00491         const SpatialVec& V_GB   = this->getBodyVelocity(s);
00492         const SpatialVec& V_GA   = inBodyA.getBodyVelocity(s);
00493         const Vec3        w_AB_G = V_GB[0]-V_GA[0]; // angular velocity of B in A, exp in G   ( 3 flops)
00494 
00495         // Angular velocity was easy, but for linear velocity we have to add in an wXr term.
00496         const Transform&  X_GB       = getBodyTransform(s);
00497         const Transform&  X_GA       = inBodyA.getBodyTransform(s);
00498         const Vec3        p_AB_G     = X_GB.T() - X_GA.T(); // vector from OA to OB, exp in G ( 3 flops)
00499         const Vec3        p_AB_G_dot = V_GB[1]  - V_GA[1];  // d/dt p taken in G              ( 3 flops)
00500 
00501         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)
00502 
00503         // We're done, but the answer is expressed in Ground. Reexpress in A and return.
00504         return ~X_GA.R()*SpatialVec(w_AB_G, v_AB_G);        //                                (30 flops)
00505     }
00506 
00511     Vec3 findBodyAngularVelocityInAnotherBody(const State& s,
00512                                        const MobilizedBody& inBodyA) const 
00513     {
00514         const Vec3& w_GB   = getBodyAngularVelocity(s);
00515         const Vec3& w_GA   = inBodyA.getBodyAngularVelocity(s);
00516         const Vec3  w_AB_G = w_GB-w_GA; // angular velocity of B in A, exp in G ( 3 flops)
00517 
00518         // Now reexpress in A.
00519         return inBodyA.expressGroundVectorInBodyFrame(s, w_AB_G); //            (15 flops)
00520     }
00521 
00526     Vec3 findBodyOriginVelocityInAnotherBody(const State& s,
00527                                       const MobilizedBody& inBodyA) const
00528     {
00529         // Doesn't save much to special case this one.
00530         return findBodyVelocityInAnotherBody(s,inBodyA)[1];
00531     }
00532 
00537     SpatialVec findBodyAccelerationInAnotherBody(const State& s,
00538                                                  const MobilizedBody& inBodyA) const
00539     {
00540         const Vec3&       p_GB = this->getBodyOriginLocation(s);
00541         const Transform&  X_GA = inBodyA.getBodyTransform(s);
00542         const SpatialVec& V_GB = this->getBodyVelocity(s);
00543         const SpatialVec& V_GA = inBodyA.getBodyVelocity(s);
00544         const SpatialVec& A_GB = this->getBodyAcceleration(s);
00545         const SpatialVec& A_GA = inBodyA.getBodyAcceleration(s);
00546         const Vec3&       p_GA = X_GA.T();
00547         const Vec3&       w_GA = V_GA[0];
00548         const Vec3&       w_GB = V_GB[0];
00549         const Vec3&       b_GA = A_GA[0];
00550         const Vec3&       b_GB = A_GB[0];
00551 
00552         const Vec3 p_AB_G        = p_GB     - p_GA;         // vector from OA to OB, in G   ( 3 flops)
00553         const Vec3 p_AB_G_dot    = V_GB[1]  - V_GA[1];      // d/dt p taken in G            ( 3 flops)
00554         const Vec3 p_AB_G_dotdot = A_GB[1]  - A_GA[1];      // d^2/dt^2 taken in G          ( 3 flops)
00555 
00556         const Vec3 w_AB_G     = w_GB - w_GA;                // relative ang. vel. of B in A, exp. in G (3 flops)
00557         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)
00558 
00559         const Vec3 w_AB_G_dot = b_GB - b_GA;                // d/dt of w_AB_G taken in G    ( 3 flops)
00560         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
00561                                                                                      //     (24 flops)
00562 
00563         // We have the derivative in G; change it to derivative in A by adding in contribution caused
00564         // by motion of G in A, that is w_AG X w_AB_G. (Note that w_AG=-w_GA.)
00565         const Vec3 b_AB_G = w_AB_G_dot - w_GA % w_AB_G; // ang. accel. of B in A            (12 flops)
00566         const Vec3 a_AB_G = v_AB_G_dot - w_GA % v_AB_G; // taken in A, exp. in G            (12 flops)
00567 
00568         return ~X_GA.R() * SpatialVec(b_AB_G, a_AB_G); // taken in A, expressed in A        (30 flops)
00569     }
00570 
00575     Vec3 findBodyAngularAccelerationInAnotherBody(const State& s,
00576                                                   const MobilizedBody& inBodyA) const
00577     {
00578         const Rotation& R_GA = inBodyA.getBodyRotation(s);
00579         const Vec3&     w_GA = inBodyA.getBodyAngularVelocity(s);
00580         const Vec3&     w_GB = this->getBodyAngularVelocity(s);
00581         const Vec3&     b_GA = inBodyA.getBodyAngularAcceleration(s);
00582         const Vec3&     b_GB = this->getBodyAngularAcceleration(s);
00583 
00584         const Vec3 w_AB_G     = w_GB - w_GA;                // relative ang. vel. of B in A, exp. in G (3 flops)
00585         const Vec3 w_AB_G_dot = b_GB - b_GA;                // d/dt of w_AB_G taken in G    ( 3 flops)
00586 
00587         // We have the derivative in G; change it to derivative in A by adding in contribution caused
00588         // by motion of G in A, that is w_AG X w_AB_G. (Note that w_AG=-w_GA.)
00589         const Vec3 b_AB_G = w_AB_G_dot - w_GA % w_AB_G; // ang. accel. of B in A            (12 flops)
00590 
00591         return ~R_GA * b_AB_G; // taken in A, expressed in A                                (15 flops)
00592     }
00593 
00598     Vec3 findBodyOriginAccelerationInAnotherBody(const State& s, 
00599                                           const MobilizedBody& inBodyA) const
00600     {
00601         // Not much to be saved by trying to optimize this since the linear part
00602         // is the most expensive to calculate.
00603         return findBodyAccelerationInAnotherBody(s,inBodyA)[1];
00604     }
00605 
00611     Vec3 findStationLocationInGround(const State& s, const Vec3& stationOnB) const {
00612         return getBodyTransform(s) * stationOnB;
00613     }
00614 
00615 
00624     Vec3 findStationLocationInAnotherBody(const State& s, const Vec3& stationOnB, 
00625                                const MobilizedBody& toBodyA) const
00626     {
00627         return toBodyA.findStationAtGroundPoint(s, findStationLocationInGround(s,stationOnB));
00628     }
00629 
00633     Vec3 findStationVelocityInGround(const State& s, const Vec3& stationOnB) const {
00634         const Vec3& w = getBodyAngularVelocity(s); // in G
00635         const Vec3& v = getBodyOriginVelocity(s);  // in G
00636         const Vec3  r = expressVectorInGroundFrame(s,stationOnB); // 15 flops
00637         return v + w % r;                                         // 12 flops
00638     }
00639 
00640 
00645     Vec3 findStationVelocityInAnotherBody(const State& s, 
00646                                           const Vec3&          stationOnBodyB, // p_BS
00647                                           const MobilizedBody& inBodyA) const
00648     {
00649         const SpatialVec V_AB   = findBodyVelocityInAnotherBody(s,inBodyA); // (51 flops)
00650          // OB->S rexpressed in A but not shifted to OA
00651         const Vec3       p_BS_A = expressVectorInAnotherBodyFrame(s, stationOnBodyB, inBodyA);
00652                                                                             // (30 flops)
00653         return V_AB[1] + (V_AB[0] % p_BS_A);                                // (12 flops)
00654     }
00655 
00656       
00660     Vec3 findStationAccelerationInGround(const State& s, const Vec3& stationOnB) const {
00661         const Vec3& w = getBodyAngularVelocity(s);     // in G
00662         const Vec3& b = getBodyAngularAcceleration(s); // in G
00663         const Vec3& a = getBodyOriginAcceleration(s);  // in G
00664 
00665         const Vec3  r = expressVectorInGroundFrame(s,stationOnB); // 15 flops
00666         return a + b % r + w % (w % r);                           // 33 flops
00667     }
00668 
00673     Vec3 findStationAccelerationInAnotherBody(const State& s,
00674                                               const Vec3&          stationOnBodyB, 
00675                                               const MobilizedBody& inBodyA) const 
00676     {
00677         const Vec3       w_AB = findBodyAngularVelocityInAnotherBody(s,inBodyA);  // ( 18 flops)
00678         const SpatialVec A_AB = findBodyAccelerationInAnotherBody(s,inBodyA);     // (105 flops)
00679          // OB->S rexpressed in A but not shifted to OA
00680         const Vec3       p_BS_A = expressVectorInAnotherBodyFrame(s, stationOnBodyB, inBodyA);
00681                                                                                   // ( 30 flops)
00682 
00683         return A_AB[1] + (A_AB[0] % p_BS_A) + w_AB % (w_AB % p_BS_A);             // ( 33 flops)
00684     }
00685 
00689     void findStationLocationAndVelocityInGround(const State& s, const Vec3& locationOnB,
00690                                                 Vec3& locationOnGround, Vec3& velocityInGround) const
00691     {
00692         const Vec3& p_GB   = getBodyOriginLocation(s);
00693         const Vec3  p_BS_G = expressVectorInGroundFrame(s,locationOnB); // 15 flops
00694         locationOnGround = p_GB + p_BS_G;                               //  3 flops
00695 
00696         const Vec3& w_GB = getBodyAngularVelocity(s);
00697         const Vec3& v_GB = getBodyOriginVelocity(s);
00698         velocityInGround = v_GB + w_GB % p_BS_G;                        // 12 flops
00699     }
00700 
00701 
00705     void findStationLocationVelocityAndAccelerationInGround
00706        (const State& s, const Vec3& locationOnB,
00707         Vec3& locationOnGround, Vec3& velocityInGround, Vec3& accelerationInGround) const
00708     {
00709         const Rotation&  R_GB = getBodyRotation(s);
00710         const Vec3&      p_GB = getBodyOriginLocation(s);
00711 
00712         const Vec3 r = R_GB*locationOnB; // re-express station vector p_BS in G (15 flops)
00713         locationOnGround  = p_GB + r;    // 3 flops
00714 
00715         const Vec3& w = getBodyAngularVelocity(s);      // in G
00716         const Vec3& v = getBodyOriginVelocity(s);       // in G
00717         const Vec3& b = getBodyAngularAcceleration(s);  // in G
00718         const Vec3& a = getBodyOriginAcceleration(s);   // in G
00719 
00720         const Vec3 wXr = w % r; // "whipping" velocity w X r due to angular velocity (9 flops)
00721         velocityInGround     = v + wXr;                 // v + w X r (3 flops)
00722         accelerationInGround = a + b % r + w % wXr;     // 24 flops
00723     }
00724 
00727     Vec3 findMassCenterLocationInGround(const State& s) const {
00728         return findStationLocationInGround(s,getBodyMassCenterStation(s));
00729     }
00730 
00734     Vec3 findMassCenterLocationInAnotherBody(const State& s, const MobilizedBody& toBodyA) const {
00735         return findStationLocationInAnotherBody(s,getBodyMassCenterStation(s),toBodyA);
00736     }
00737 
00743     Vec3 findStationAtGroundPoint(const State& s, const Vec3& locationInG) const {
00744         return ~getBodyTransform(s) * locationInG;
00745     }
00746 
00752     Vec3 findStationAtAnotherBodyStation(const State& s, const MobilizedBody& fromBodyA, 
00753                                 const Vec3& stationOnA) const {
00754         return fromBodyA.findStationLocationInAnotherBody(s, stationOnA, *this);
00755     }
00756 
00760     Vec3 findStationAtAnotherBodyOrigin(const State& s, const MobilizedBody& fromBodyA) const {
00761         return findStationAtGroundPoint(s,fromBodyA.getBodyOriginLocation(s));
00762     }
00763 
00767     Vec3 findStationAtAnotherBodyMassCenter(const State& s, const MobilizedBody& fromBodyA) const {
00768         return fromBodyA.findStationLocationInAnotherBody(s,getBodyMassCenterStation(s),*this);
00769     }
00770 
00774     Vec3 expressVectorInGroundFrame(const State& s, const Vec3& vectorInB) const {
00775         return getBodyRotation(s)*vectorInB;
00776     }
00777 
00781     Vec3 expressGroundVectorInBodyFrame(const State& s, const Vec3& vectorInG) const {
00782         return ~getBodyRotation(s)*vectorInG;
00783     }
00784 
00790     Vec3 expressVectorInAnotherBodyFrame(const State& s, const Vec3& vectorInB,
00791                                          const MobilizedBody& inBodyA) const
00792     {
00793         return inBodyA.expressGroundVectorInBodyFrame(s, expressVectorInGroundFrame(s,vectorInB));
00794     }
00795 
00799     MassProperties expressMassPropertiesInGroundFrame(const State& s) {
00800             const MassProperties& M_OB_B = getBodyMassProperties(s);
00801             const Rotation&       R_GB   = getBodyRotation(s);
00802             return M_OB_B.reexpress(~R_GB);
00803     }
00804 
00808     MassProperties expressMassPropertiesInAnotherBodyFrame(const State& s, const MobilizedBody& inBodyA) {
00809             const MassProperties& M_OB_B = getBodyMassProperties(s);
00810             const Rotation        R_AB   = findBodyRotationInAnotherBody(s,inBodyA);
00811             return M_OB_B.reexpress(~R_AB);
00812     }
00813 
00814     // End of Basic Operators.
00816 
00821 
00822 
00824 
00844     SpatialMat calcBodySpatialInertiaMatrixInGround(const State& s) const
00845     {
00846         if (isGround())
00847             return SpatialMat(Mat33(Infinity)); // sets diagonals to Inf
00848 
00849         const MassProperties& mp   = getBodyMassProperties(s);
00850         const Rotation&       R_GB = getBodyRotation(s);
00851          // re-express in Ground without shifting, convert to spatial mat.
00852         return mp.reexpress(~R_GB).toSpatialMat();
00853     }
00854 
00860     Inertia calcBodyCentralInertia(const State& s, 
00861                                    MobilizedBodyIndex objectBodyB) const
00862     {
00863         return getBodyMassProperties(s).calcCentralInertia();
00864     }
00865 
00869     Inertia calcBodyInertiaAboutAnotherBodyStation(const State& s,
00870                                                    const MobilizedBody& inBodyA, 
00871                                                    const Vec3&          aboutLocationOnBodyA) const
00872     {
00873         // get B's mass props MB, measured about OB, exp. in B
00874         const MassProperties& MB_OB_B = getBodyMassProperties(s);
00875 
00876         // Calculate the vector from the body B origin (current "about" point) to the new "about" point PA,
00877         // expressed in B.
00878         const Vec3 r_OB_PA = findStationAtAnotherBodyStation(s, inBodyA, aboutLocationOnBodyA);
00879 
00880         // Now shift the "about" point for body B's inertia IB to PA, but still expressed in B.
00881         const Inertia IB_PA_B = MB_OB_B.calcShiftedInertia(r_OB_PA);
00882         
00883         // Finally reexpress the inertia in the A frame.
00884         const Rotation R_BA    = inBodyA.findBodyRotationInAnotherBody(s, *this);
00885         const Inertia  IB_PA_A = IB_PA_B.reexpress(R_BA);
00886         return IB_PA_A;
00887     }
00888 
00889 
00892     SpatialVec calcBodyMomentumAboutBodyOriginInGround(const State& s) {
00893         const MassProperties M_OB_G = expressMassPropertiesInGroundFrame(s);
00894         const SpatialVec&    V_GB   = getBodyVelocity(s);
00895         return M_OB_G.toSpatialMat() * V_GB;
00896     }
00897 
00900     SpatialVec calcBodyMomentumAboutBodyMassCenterInGround(const State& s) const {
00901         const MassProperties& M_OB_B = getBodyMassProperties(s);
00902         const Rotation&       R_GB   = getBodyRotation(s);
00903 
00904         // Given a central inertia matrix I, angular velocity w, and mass center velocity v,
00905         // the central angular momentum is Iw and linear momentum is mv.
00906         const Inertia I_CB_B = M_OB_B.calcCentralInertia();
00907         const Inertia I_CB_G = I_CB_B.reexpress(~R_GB);
00908         const Real    mb     = M_OB_B.getMass();
00909         const Vec3&   w_GB   = getBodyAngularVelocity(s);
00910         Vec3          v_G_CB = findStationVelocityInGround(s, M_OB_B.getMassCenter());
00911 
00912         return SpatialVec( I_CB_G*w_GB, mb*v_G_CB );
00913     }
00914 
00918     Real calcStationToStationDistance(const State& s,
00919                                       const Vec3&          locationOnBodyB,
00920                                       const MobilizedBody& bodyA,
00921                                       const Vec3&          locationOnBodyA) const
00922     {
00923         if (isSameMobilizedBody(bodyA))
00924             return (locationOnBodyA-locationOnBodyB).norm();
00925 
00926         const Vec3 r_OG_PB = this->findStationLocationInGround(s,locationOnBodyB);
00927         const Vec3 r_OG_PA = bodyA.findStationLocationInGround(s,locationOnBodyA);
00928         return (r_OG_PA - r_OG_PB).norm();
00929     }
00930 
00935     Real calcStationToStationDistanceTimeDerivative(const State& s,
00936                                                     const Vec3&          locationOnBodyB,
00937                                                     const MobilizedBody& bodyA,
00938                                                     const Vec3&          locationOnBodyA) const
00939     {
00940         if (isSameMobilizedBody(bodyA))
00941             return 0;
00942 
00943         Vec3 rB, rA, vB, vA;
00944         this->findStationLocationAndVelocityInGround(s,locationOnBodyB,rB,vB);
00945         bodyA.findStationLocationAndVelocityInGround(s,locationOnBodyA,rA,vA);
00946         const Vec3 r = rA-rB, v = vA-vB;
00947         const Real d = r.norm();
00948 
00949         // When the points are coincident, the rate of change of distance is just their relative speed.
00950         // Otherwise, it is the speed along the direction of separation. 
00951         if (d==0) return v.norm();
00952         else return dot(v, r/d);
00953     }
00954 
00955 
00960     Real calcStationToStationDistance2ndTimeDerivative(const State& s,
00961                                                        const Vec3&          locationOnBodyB,
00962                                                        const MobilizedBody& bodyA,
00963                                                        const Vec3&          locationOnBodyA) const
00964     {
00965         if (isSameMobilizedBody(bodyA))
00966             return 0;
00967 
00968         Vec3 rB, rA, vB, vA, aB, aA;
00969         this->findStationLocationVelocityAndAccelerationInGround(s,locationOnBodyB,rB,vB,aB);
00970         bodyA.findStationLocationVelocityAndAccelerationInGround(s,locationOnBodyA,rA,vA,aA);
00971 
00972         const Vec3 r = rA-rB, v = vA-vB, a = aA-aB;
00973         const Real d = r.norm();
00974         
00975         // This method is the time derivative of calcFixedPointToPointDistanceTimeDerivative(), so it
00976         // must follow the same two cases. That is, when the points are coincident the change in 
00977         // separation rate is the time derivative of the speed |v|, otherwise it is the time
00978         // derivative of the speed along the separation vector.
00979 
00980         if (d==0) {
00981             // Return d/dt |v|. This has two cases: if |v| is zero, the rate of change of speed is
00982             // just the points' relative acceleration magnitude. Otherwise, it is the acceleration
00983             // in the direction of the current relative velocity vector.
00984             const Real s = v.norm(); // speed
00985             if (s==0) return a.norm();
00986             else return dot(a, v/s);
00987         }
00988 
00989         // Points are separated.
00990         const Vec3 u = r/d;             // u is the separation direction (a unit vector from B to A) 
00991         const Vec3 vp = v - dot(v,u)*u; // velocity perpendicular to separation direction
00992         return dot(a,u) + dot(vp,v)/d;
00993     }
00994 
00995 
00998     Vec3 calcBodyMovingPointVelocityInBody(const State& s,
00999                                            const Vec3& locationOnBodyB, 
01000                                            const Vec3& velocityOnBodyB,
01001                                            const MobilizedBody& inBodyA) const
01002     {
01003         SimTK_ASSERT_ALWAYS(!"unimplemented method", 
01004             "MobilizedBody::calcBodyMovingPointVelocityInBody() is not yet implemented -- any volunteers?");
01005         return Vec3::getNaN();
01006     }
01007 
01008 
01011     Vec3 calcBodyMovingPointAccelerationInBody(const State& s, 
01012                                                const Vec3&          locationOnBodyB, 
01013                                                const Vec3&          velocityOnBodyB, 
01014                                                const Vec3&          accelerationOnBodyB,
01015                                                const MobilizedBody& inBodyA) const
01016     {
01017         SimTK_ASSERT_ALWAYS(!"unimplemented method", 
01018             "MobilizedBody::calcBodyMovingPointAccelerationInBody() is not yet implemented -- any volunteers?");
01019         return Vec3::getNaN();
01020     }
01021 
01028     Real calcMovingPointToPointDistanceTimeDerivative(const State& s,
01029                                                       const Vec3&          locationOnBodyB,
01030                                                       const Vec3&          velocityOnBodyB,
01031                                                       const MobilizedBody& bodyA,
01032                                                       const Vec3&          locationOnBodyA,
01033                                                       const Vec3&          velocityOnBodyA) const
01034     {
01035         SimTK_ASSERT_ALWAYS(!"unimplemented method", 
01036             "MobilizedBody::calcMovingPointToPointDistanceTimeDerivative() is not yet implemented -- any volunteers?");
01037         return NaN;
01038     }
01039 
01046     Real calcMovingPointToPointDistance2ndTimeDerivative(const State& s,
01047                                                          const Vec3&          locationOnBodyB,
01048                                                          const Vec3&          velocityOnBodyB,
01049                                                          const Vec3&          accelerationOnBodyB,
01050                                                          const MobilizedBody& bodyA,
01051                                                          const Vec3&          locationOnBodyA,
01052                                                          const Vec3&          velocityOnBodyA,
01053                                                          const Vec3&          accelerationOnBodyA) const
01054     {
01055         SimTK_ASSERT_ALWAYS(!"unimplemented method", 
01056             "MobilizedBody::calcMovingPointToPointDistance2ndTimeDerivative() is not yet implemented -- any volunteers?");
01057         return NaN;
01058     }
01059 
01060 
01061     // End of High Level Operators.
01063 
01064 
01066             // CONSTRUCTION METHODS //
01068 
01072     MobilizedBody();
01073 
01075     explicit MobilizedBody(MobilizedBodyImpl* r);
01076 
01081 
01082 
01088     MobilizedBody& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) {
01089         (void)updBody().addDecoration(X_BD,g);
01090         return *this;
01091     }
01092 
01096     MobilizedBody& addOutboardDecoration(const Transform& X_MD,  const DecorativeGeometry&);
01097 
01101     MobilizedBody& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry&);
01102 
01104     const Body& getBody() const;
01108     Body& updBody();
01109 
01115     MobilizedBody& setBody(const Body&);
01116 
01123     MobilizedBody& setDefaultMassProperties(const MassProperties& m) {
01124         updBody().setDefaultRigidBodyMassProperties(m); // might not be allowed
01125         return *this;
01126     }
01127 
01129     const MassProperties& getDefaultMassProperties() const {
01130         return getBody().getDefaultRigidBodyMassProperties(); // every body type can do this
01131     }
01132 
01138     MobilizedBody& setDefaultInboardFrame (const Transform& X_PF);
01144     MobilizedBody& setDefaultOutboardFrame(const Transform& X_BM);
01145 
01150     const Transform& getDefaultInboardFrame()  const; // X_PF
01154     const Transform& getDefaultOutboardFrame() const; // X_BM
01155 
01158     operator MobilizedBodyIndex() const {return getMobilizedBodyIndex();}
01159 
01162     MobilizedBodyIndex     getMobilizedBodyIndex()  const;
01163 
01166     const MobilizedBody&   getParentMobilizedBody() const;
01167 
01171     const MobilizedBody&   getBaseMobilizedBody()   const;
01172 
01175     const SimbodyMatterSubsystem& getMatterSubsystem()      const;
01178     SimbodyMatterSubsystem&       updMatterSubsystem();
01179 
01181     bool isInSubsystem() const;
01182 
01186     bool isInSameSubsystem(const MobilizedBody&) const;
01187 
01192     bool isSameMobilizedBody(const MobilizedBody& mBody) const;
01193 
01196     bool isGround() const;
01197 
01202     int getLevelInMultibodyTree() const;
01203     
01206     MobilizedBody& cloneForNewParent(MobilizedBody& parent) const;
01207 
01208         // Utility operators //
01209 
01213     Real  getOneFromQPartition(const State&, int which, const Vector& qlike) const;
01214 
01219     Real& updOneFromQPartition(const State&, int which, Vector& qlike) const;
01220 
01224     Real  getOneFromUPartition(const State&, int which, const Vector& ulike) const;
01225 
01230     Real& updOneFromUPartition(const State&, int which, Vector& ulike) const;
01231 
01237     void applyOneMobilityForce(const State& s, int which, Real f, 
01238                                Vector& mobilityForces) const
01239     {
01240         updOneFromUPartition(s,which,mobilityForces) += f;
01241     }
01242 
01249     void applyBodyForce(const State& s, const SpatialVec& spatialForceInG, 
01250                         Vector_<SpatialVec>& bodyForcesInG) const;
01251 
01257     void applyBodyTorque(const State& s, const Vec3& torqueInG, 
01258                          Vector_<SpatialVec>& bodyForcesInG) const;
01259 
01269     void applyForceToBodyPoint(const State& s, const Vec3& pointInB, const Vec3& forceInG,
01270                                Vector_<SpatialVec>& bodyForcesInG) const;
01271 
01272     // End of Construction and Misc Methods.
01274 
01276         // BUILT IN MOBILIZER DECLARATIONS //
01278 
01279     // These are the built-in MobilizedBody types. Types on the same line are
01280     // synonymous. Each of these has a known number of coordinates and speeds 
01281     // (at least a default number) so
01282     // can define routines which return and accept specific-size arguments, e.g.
01283     // Real (for 1-dof mobilizer) and Vec5 (for 5-dof mobilizer). Here is the
01284     // conventional interface that each built-in should provide. The base type
01285     // provides similar routines but using variable-sized or "one at a time"
01286     // arguments. (Vec<1> here will actually be a Real; assume the built-in
01287     // MobilizedBody class is "BuiltIn")
01288     //
01289     //    BuiltIn&       setDefaultQ(const Vec<nq>&);
01290     //    const Vec<nq>& getDefaultQ() const;
01291     //
01292     //    const Vec<nq>& getQ[Dot[Dot]](const State&) const;
01293     //    const Vec<nu>& getU[Dot](const State&) const;
01294     //
01295     //    void setQ(State&, const Vec<nq>&) const;
01296     //    void setU(State&, const Vec<nu>&) const;
01297     //
01298     //    const Vec<nq>& getMyPartQ(const State&, const Vector& qlike) const;
01299     //    const Vec<nu>& getMyPartU(const State&, const Vector& ulike) const;
01300     //   
01301     //    Vec<nq>& updMyPartQ(const State&, Vector& qlike) const;
01302     //    Vec<nu>& updMyPartU(const State&, Vector& ulike) const;
01303     //      
01304 
01305 
01306     class Pin;         typedef Pin    Torsion;
01307     class Slider;      typedef Slider Prismatic;
01308     class Universal;
01309     class Cylinder;
01310     class BendStretch;
01311     class Planar;
01312     class Gimbal;
01313     class Ball; typedef Ball Orientation, Spherical;
01314     class Translation; typedef Translation Cartesian;
01315     class Free;
01316     class LineOrientation;
01317     class FreeLine;
01318     class Weld;
01319     class Screw;
01320     class Ellipsoid;
01321     class Custom;
01322     class Ground;
01323     class FunctionBased;
01324     
01325     class PinImpl;
01326     class SliderImpl;
01327     class UniversalImpl;
01328     class CylinderImpl;
01329     class BendStretchImpl;
01330     class PlanarImpl;
01331     class GimbalImpl;
01332     class BallImpl;
01333     class TranslationImpl;
01334     class FreeImpl;
01335     class LineOrientationImpl;
01336     class FreeLineImpl;
01337     class WeldImpl;
01338     class ScrewImpl;
01339     class EllipsoidImpl;
01340     class CustomImpl;
01341     class GroundImpl;
01342     class FunctionBasedImpl;
01343 
01344 };
01345 
01349 class SimTK_SIMBODY_EXPORT MobilizedBody::Pin : public MobilizedBody {
01350 public:
01351         // SPECIALIZED INTERFACE FOR PIN MOBILIZER
01352 
01353     // "Angle" is just a nicer name for a pin joint's lone generalized coordinate q.
01354     Pin& setDefaultAngle(Real angleInRadians) {return setDefaultQ(angleInRadians);}
01355     Real getDefaultAngle() const              {return getDefaultQ();}
01356 
01357         // Friendly, mobilizer-specific access to generalized coordinates and speeds.
01358 
01359     void setAngle(State& s, Real angleInRadians) {setQ(s, angleInRadians);}
01360     Real getAngle(const State& s) const {return getQ(s);}
01361 
01362     void setRate(State& s, Real rateInRadiansPerTime) {setU(s, rateInRadiansPerTime);}
01363     Real getRate(const State& s) const {return getU(s);}
01364 
01365     // Mobility forces are "u-like", that is, one per dof.
01366     Real getAppliedPinTorque(const State& s, const Vector& mobilityForces) const {
01367         return getMyPartU(s,mobilityForces);
01368     }
01369     void applyPinTorque(const State& s, Real torque, Vector& mobilityForces) const {
01370         updMyPartU(s,mobilityForces) += torque;
01371     }
01372 
01373         // STANDARDIZED MOBILIZED BODY INTERFACE
01374 
01375         // required constructors
01376     Pin();
01377     Pin(MobilizedBody& parent, const Body&);
01378     Pin(MobilizedBody& parent, const Transform& inbFrame,
01379         const Body&,           const Transform& outbFrame);
01380 
01381         // access to generalized coordinates q and generalized speeds u
01382     Pin& setDefaultQ(Real);
01383     Real getDefaultQ() const;
01384 
01385     Real getQ(const State&) const;
01386     Real getQDot(const State&) const;
01387     Real getQDotDot(const State&) const;
01388     Real getU(const State&) const;
01389     Real getUDot(const State&) const;
01390 
01391     void setQ(State&, Real) const;
01392     void setU(State&, Real) const;
01393 
01394     Real getMyPartQ(const State&, const Vector& qlike) const;
01395     Real getMyPartU(const State&, const Vector& ulike) const;
01396    
01397     Real& updMyPartQ(const State&, Vector& qlike) const;
01398     Real& updMyPartU(const State&, Vector& ulike) const;
01399 
01400         // specialize return type for convenience
01401     Pin& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g)
01402       { (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; }
01403     Pin& addOutboardDecoration(const Transform& X_MD,  const DecorativeGeometry& g)
01404       { (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this; }
01405     Pin& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g)
01406       { (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this; }
01407     Pin& setDefaultInboardFrame(const Transform& X_PF)
01408       { (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this; }
01409     Pin& setDefaultOutboardFrame(const Transform& X_BM)
01410       { (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this; }
01411     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Pin, PinImpl, MobilizedBody);
01412 };
01413 
01417 class SimTK_SIMBODY_EXPORT MobilizedBody::Slider : public MobilizedBody {
01418 public:
01419         // SPECIALIZED INTERFACE FOR SLIDER MOBILIZER
01420 
01421     // "Length" is just a nicer name for a sliding joint's lone generalized coordinate q.
01422     Slider& setDefaultLength(Real length) {return setDefaultQ(length);}
01423     Real getDefaultLength() const         {return getDefaultQ();}
01424 
01425         // Friendly, mobilizer-specific access to generalized coordinates and speeds.
01426 
01427     void setLength(State& s, Real length) {setQ(s, length);}
01428     Real getLength(const State& s) {return getQ(s);}
01429 
01430     void setRate(State& s, Real rateInLengthPerTime) {setU(s, rateInLengthPerTime);}
01431     Real getRate(const State& s) {return getU(s);}
01432 
01433     // Mobility forces are "u-like", that is, one per dof.
01434     Real getAppliedForce(const State& s, const Vector& mobilityForces) const {
01435         return getMyPartU(s,mobilityForces);
01436     }
01437     void applyForce(const State& s, Real force, Vector& mobilityForces) const {
01438         updMyPartU(s,mobilityForces) += force;
01439     }
01440 
01441         // STANDARDIZED MOBILIZED BODY INTERFACE
01442 
01443         // required constructors
01444     Slider();
01445     Slider(MobilizedBody& parent, const Body&);
01446     Slider(MobilizedBody& parent, const Transform& inbFrame,
01447         const Body&,           const Transform& outbFrame);
01448 
01449         // access to generalized coordinates q and generalized speeds u
01450     Slider& setDefaultQ(Real);
01451     Real getDefaultQ() const;
01452 
01453     Real getQ(const State&) const;
01454     Real getQDot(const State&) const;
01455     Real getQDotDot(const State&) const;
01456     Real getU(const State&) const;
01457     Real getUDot(const State&) const;
01458 
01459     void setQ(State&, Real) const;
01460     void setU(State&, Real) const;
01461 
01462     Real getMyPartQ(const State&, const Vector& qlike) const;
01463     Real getMyPartU(const State&, const Vector& ulike) const;
01464    
01465     Real& updMyPartQ(const State&, Vector& qlike) const;
01466     Real& updMyPartU(const State&, Vector& ulike) const;
01467 
01468         // specialize return type for convenience
01469     Slider& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g)
01470       { (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this; }
01471     Slider& addOutboardDecoration(const Transform& X_MD,  const DecorativeGeometry& g)
01472       { (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this; }
01473     Slider& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g)
01474       { (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this; }
01475     Slider& setDefaultInboardFrame(const Transform& X_PF)
01476       { (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this; }
01477     Slider& setDefaultOutboardFrame(const Transform& X_BM)
01478       { (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this; }
01479     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Slider, SliderImpl, MobilizedBody);
01480 };
01481 
01487 class SimTK_SIMBODY_EXPORT MobilizedBody::Screw : public MobilizedBody {
01488 public:
01489     Screw(Real pitch);
01490 
01493     Screw(MobilizedBody& parent, const Body&, Real pitch);
01494 
01497     Screw(MobilizedBody& parent, const Transform& inbFrame,
01498          const Body&,           const Transform& outbFrame,
01499          Real pitch);
01500 
01501     Screw& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) {
01502         (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this;
01503     }
01504     Screw& addOutboardDecoration(const Transform& X_MD,  const DecorativeGeometry& g) {
01505         (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this;
01506     }
01507     Screw& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) {
01508         (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this;
01509     }
01510 
01511     Screw& setDefaultInboardFrame(const Transform& X_PF) {
01512         (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this;
01513     }
01514 
01515     Screw& setDefaultOutboardFrame(const Transform& X_BM) {
01516         (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this;
01517     }
01518 
01519     Screw& setDefaultPitch(Real pitch);
01520     Real   getDefaultPitch() const;
01521 
01522     Screw& setDefaultQ(Real);
01523     Real   getDefaultQ() const;
01524 
01525     Real getQ(const State&) const;
01526     Real getQDot(const State&) const;
01527     Real getQDotDot(const State&) const;
01528     Real getU(const State&) const;
01529     Real getUDot(const State&) const;
01530 
01531     void setQ(State&, Real) const;
01532     void setU(State&, Real) const;
01533 
01534     Real getMyPartQ(const State&, const Vector& qlike) const;
01535     Real getMyPartU(const State&, const Vector& ulike) const;
01536    
01537     Real& updMyPartQ(const State&, Vector& qlike) const;
01538     Real& updMyPartU(const State&, Vector& ulike) const;
01539     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Screw, ScrewImpl, MobilizedBody);
01540 };
01541 
01545 class SimTK_SIMBODY_EXPORT MobilizedBody::Universal : public MobilizedBody {
01546 public:
01547     Universal();
01548 
01551     Universal(MobilizedBody& parent, const Body&);
01552 
01555     Universal(MobilizedBody& parent, const Transform& inbFrame,
01556               const Body&,           const Transform& outbFrame);
01557 
01558     Universal& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) {
01559         (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this;
01560     }
01561     Universal& addOutboardDecoration(const Transform& X_MD,  const DecorativeGeometry& g) {
01562         (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this;
01563     }
01564     Universal& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) {
01565         (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this;
01566     }
01567 
01568     Universal& setDefaultInboardFrame(const Transform& X_PF) {
01569         (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this;
01570     }
01571 
01572     Universal& setDefaultOutboardFrame(const Transform& X_BM) {
01573         (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this;
01574     }
01575     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Universal, UniversalImpl, MobilizedBody);
01576 };
01577 
01580 class SimTK_SIMBODY_EXPORT MobilizedBody::Cylinder : public MobilizedBody {
01581 public:
01582     Cylinder();
01583 
01586     Cylinder(MobilizedBody& parent, const Body&);
01587 
01590     Cylinder(MobilizedBody& parent, const Transform& inbFrame,
01591          const Body&,           const Transform& outbFrame);
01592 
01593     Cylinder& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) {
01594         (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this;
01595     }
01596     Cylinder& addOutboardDecoration(const Transform& X_MD,  const DecorativeGeometry& g) {
01597         (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this;
01598     }
01599     Cylinder& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) {
01600         (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this;
01601     }
01602 
01603     Cylinder& setDefaultInboardFrame(const Transform& X_PF) {
01604         (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this;
01605     }
01606 
01607     Cylinder& setDefaultOutboardFrame(const Transform& X_BM) {
01608         (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this;
01609     }
01610     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Cylinder, CylinderImpl, MobilizedBody);
01611 };
01612 
01619 class SimTK_SIMBODY_EXPORT MobilizedBody::BendStretch : public MobilizedBody {
01620 public:
01621     BendStretch();
01622 
01625     BendStretch(MobilizedBody& parent, const Body&);
01626 
01629     BendStretch(MobilizedBody& parent, const Transform& inbFrame,
01630                 const Body&,           const Transform& outbFrame);
01631 
01632     BendStretch& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) {
01633         (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this;
01634     }
01635     BendStretch& addOutboardDecoration(const Transform& X_MD,  const DecorativeGeometry& g) {
01636         (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this;
01637     }
01638     BendStretch& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) {
01639         (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this;
01640     }
01641 
01642     BendStretch& setDefaultInboardFrame(const Transform& X_PF) {
01643         (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this;
01644     }
01645 
01646     BendStretch& setDefaultOutboardFrame(const Transform& X_BM) {
01647         (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this;
01648     }
01649     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(BendStretch, BendStretchImpl, MobilizedBody);
01650 };
01651 
01656 class SimTK_SIMBODY_EXPORT MobilizedBody::Planar : public MobilizedBody {
01657 public:
01658     Planar();
01659 
01662     Planar(MobilizedBody& parent, const Body&);
01663 
01666     Planar(MobilizedBody& parent, const Transform& inbFrame,
01667            const Body&,           const Transform& outbFrame);
01668 
01669     Planar& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) {
01670         (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this;
01671     }
01672     Planar& addOutboardDecoration(const Transform& X_MD,  const DecorativeGeometry& g) {
01673         (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this;
01674     }
01675     Planar& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) {
01676         (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this;
01677     }
01678 
01679     Planar& setDefaultInboardFrame(const Transform& X_PF) {
01680         (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this;
01681     }
01682 
01683     Planar& setDefaultOutboardFrame(const Transform& X_BM) {
01684         (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this;
01685     }
01686 
01687     // Friendly, mobilizer-specific access to coordinates and speeds.
01688     Planar& setDefaultAngle(Real a) {
01689         Vec3 q = getDefaultQ(); q[0] = a; setDefaultQ(q);
01690         return *this;
01691     }
01692     Planar& setDefaultTranslation(const Vec2& r) {
01693         Vec3 q = getDefaultQ(); q.updSubVec<2>(1) = r; setDefaultQ(q);
01694         return *this;
01695     }
01696 
01697     Real getDefaultAngle() const {return getDefaultQ()[0];}
01698     const Vec2& getDefaultTranslation() const {return getDefaultQ().getSubVec<2>(1);}
01699 
01700     void setAngle      (State& s, Real        a) {setOneQ(s,0,a);}
01701     void setTranslation(State& s, const Vec2& r) {setOneQ(s,1,r[0]); setOneQ(s,2,r[1]);}
01702 
01703     Real getAngle(const State& s) const {return getQ(s)[0];}
01704     const Vec2& getTranslation(const State& s) const {return getQ(s).getSubVec<2>(1);}
01705 
01706     // Generic default state Topology methods.
01707     const Vec3& getDefaultQ() const;
01708     Planar& setDefaultQ(const Vec3& q);
01709 
01710     const Vec3& getQ(const State&) const;
01711     const Vec3& getQDot(const State&) const;
01712     const Vec3& getQDotDot(const State&) const;
01713     const Vec3& getU(const State&) const;
01714     const Vec3& getUDot(const State&) const;
01715 
01716     void setQ(State&, const Vec3&) const;
01717     void setU(State&, const Vec3&) const;
01718 
01719     const Vec3& getMyPartQ(const State&, const Vector& qlike) const;
01720     const Vec3& getMyPartU(const State&, const Vector& ulike) const;
01721    
01722     Vec3& updMyPartQ(const State&, Vector& qlike) const;
01723     Vec3& updMyPartU(const State&, Vector& ulike) const;
01724     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Planar, PlanarImpl, MobilizedBody);
01725 };
01726 
01730 class SimTK_SIMBODY_EXPORT MobilizedBody::Gimbal : public MobilizedBody {
01731 public:
01732     Gimbal();
01733 
01736     Gimbal(MobilizedBody& parent, const Body&);
01737 
01740     Gimbal(MobilizedBody& parent, const Transform& inbFrame,
01741            const Body&,           const Transform& outbFrame);
01742 
01743     Gimbal& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) {
01744         (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this;
01745     }
01746     Gimbal& addOutboardDecoration(const Transform& X_MD,  const DecorativeGeometry& g) {
01747         (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this;
01748     }
01749     Gimbal& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) {
01750         (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this;
01751     }
01752 
01753     Gimbal& setDefaultInboardFrame(const Transform& X_PF) {
01754         (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this;
01755     }
01756 
01757     Gimbal& setDefaultOutboardFrame(const Transform& X_BM) {
01758         (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this;
01759     }
01760 
01761     // This is just a nicer name for the generalized coordinate.
01762     Gimbal& setDefaultRotation(const Rotation& R_FM) {
01763         return setDefaultQ(R_FM.convertRotationToBodyFixedXYZ());
01764     }
01765     Rotation getDefaultRotation() const {
01766         const Vec3& q = getDefaultQ();
01767         return Rotation(BodyRotationSequence,
01768             q[0], XAxis, q[1], YAxis, q[2], ZAxis);
01769     }
01770 
01771     // This is used only for visualization.
01772     Gimbal& setDefaultRadius(Real r);
01773     Real getDefaultRadius() const;
01774 
01775     // Generic default state Topology methods.
01776     const Vec3& getDefaultQ() const; // X,Y,Z body-fixed Euler angles
01777     Gimbal& setDefaultQ(const Vec3& q);
01778 
01779     const Vec3& getQ(const State&) const;
01780     const Vec3& getQDot(const State&) const;
01781     const Vec3& getQDotDot(const State&) const;
01782     const Vec3& getU(const State&) const;
01783     const Vec3& getUDot(const State&) const;
01784 
01785     void setQ(State&, const Vec3&) const;
01786     void setU(State&, const Vec3&) const;
01787 
01788     const Vec3& getMyPartQ(const State&, const Vector& qlike) const;
01789     const Vec3& getMyPartU(const State&, const Vector& ulike) const;
01790    
01791     Vec3& updMyPartQ(const State&, Vector& qlike) const;
01792     Vec3& updMyPartU(const State&, Vector& ulike) const;
01793     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Gimbal, GimbalImpl, MobilizedBody);
01794 };
01795 
01800 class SimTK_SIMBODY_EXPORT MobilizedBody::Ball : public MobilizedBody {
01801 public:
01802     explicit Ball();
01803 
01806     Ball(MobilizedBody& parent, const Body&);
01807 
01810     Ball(MobilizedBody& parent, const Transform& inbFrame,
01811          const Body&,           const Transform& outbFrame);
01812 
01813     Ball& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) {
01814         (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this;
01815     }
01816     Ball& addOutboardDecoration(const Transform& X_MD,  const DecorativeGeometry& g) {
01817         (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this;
01818     }
01819     Ball& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) {
01820         (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this;
01821     }
01822 
01823     Ball& setDefaultInboardFrame(const Transform& X_PF) {
01824         (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this;
01825     }
01826 
01827     Ball& setDefaultOutboardFrame(const Transform& X_BM) {
01828         (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this;
01829     }
01830 
01831     // This is just a nicer name for the generalized coordinate.
01832     Ball& setDefaultRotation(const Rotation& R_FM) {
01833         return setDefaultQ(R_FM.convertRotationToQuaternion());
01834     }
01835     Rotation getDefaultRotation() const {return Rotation(getDefaultQ());}
01836 
01837     // This is used only for visualization.
01838     Ball& setDefaultRadius(Real r);
01839     Real getDefaultRadius() const;
01840 
01841     // Generic default state Topology methods.
01842     const Quaternion& getDefaultQ() const;
01843     Ball& setDefaultQ(const Quaternion& q);
01844 
01845     const Vec4& getQ(const State&) const;
01846     const Vec4& getQDot(const State&) const;
01847     const Vec4& getQDotDot(const State&) const;
01848     const Vec3& getU(const State&) const;
01849     const Vec3& getUDot(const State&) const;
01850 
01851     void setQ(State&, const Vec4&) const;
01852     void setU(State&, const Vec3&) const;
01853 
01854     const Vec4& getMyPartQ(const State&, const Vector& qlike) const;
01855     const Vec3& getMyPartU(const State&, const Vector& ulike) const;
01856    
01857     Vec4& updMyPartQ(const State&, Vector& qlike) const;
01858     Vec3& updMyPartU(const State&, Vector& ulike) const;
01859     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Ball, BallImpl, MobilizedBody);
01860 };
01861 
01866 class SimTK_SIMBODY_EXPORT MobilizedBody::Ellipsoid : public MobilizedBody {
01867 public:
01868     // The ellipsoid is placed on the mobilizer's inboard frame F, with
01869     // half-axis dimensions along F's x,y,z respectively.
01870     Ellipsoid(); // not very useful until radii are set, but has some defaults
01871     explicit Ellipsoid(const Vec3& radii);
01872     Ellipsoid(Real a, Real b, Real c);
01873 
01876     Ellipsoid(MobilizedBody& parent, const Body&);
01877 
01880     Ellipsoid(MobilizedBody& parent, const Transform& inbFrame,
01881               const Body&,           const Transform& outbFrame);
01882 
01883     Ellipsoid& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) {
01884         (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this;
01885     }
01886     Ellipsoid& addOutboardDecoration(const Transform& X_MD,  const DecorativeGeometry& g) {
01887         (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this;
01888     }
01889     Ellipsoid& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) {
01890         (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this;
01891     }
01892 
01893     Ellipsoid& setDefaultInboardFrame(const Transform& X_PF) {
01894         (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this;
01895     }
01896 
01897     Ellipsoid& setDefaultOutboardFrame(const Transform& X_BM) {
01898         (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this;
01899     }
01900 
01901     // This is just a nicer name for the generalized coordinate.
01902     Ellipsoid& setDefaultRotation(const Rotation& R_FM) {
01903         return setDefaultQ(R_FM.convertRotationToQuaternion());
01904     }
01905     Rotation getDefaultRotation() const {return Rotation(getDefaultQ());}
01906 
01907     Ellipsoid& setDefaultRadii(const Vec3& r);
01908     const Vec3& getDefaultRadii() const;
01909 
01910     // Generic default state Topology methods.
01911     const Quaternion& getDefaultQ() const;
01912     Quaternion& updDefaultQ();
01913     Ellipsoid& setDefaultQ(const Quaternion& q) {updDefaultQ()=q; return *this;}
01914     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Ellipsoid, EllipsoidImpl, MobilizedBody);
01915 };
01916 
01919 class SimTK_SIMBODY_EXPORT MobilizedBody::Translation : public MobilizedBody {
01920 public:
01921     Translation();
01922 
01925     Translation(MobilizedBody& parent, const Body&);
01926 
01929     Translation(MobilizedBody& parent, const Transform& inbFrame,
01930          const Body&,           const Transform& outbFrame);
01931 
01932     Translation& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) {
01933         (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this;
01934     }
01935     Translation& addOutboardDecoration(const Transform& X_MD,  const DecorativeGeometry& g) {
01936         (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this;
01937     }
01938     Translation& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) {
01939         (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this;
01940     }
01941 
01942     Translation& setDefaultInboardFrame(const Transform& X_PF) {
01943         (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this;
01944     }
01945 
01946     Translation& setDefaultOutboardFrame(const Transform& X_BM) {
01947         (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this;
01948     }
01949 
01950     // This is just a nicer name for setting this mobilizer's generalized coordinates,
01951     // which together constitute the vector from the F frame's origin to the M
01952     // frame's origin, expressed in F.
01953 
01954     // Set the topological default values for the initial q's.
01955     Translation& setDefaultTranslation(const Vec3& p_FM) {
01956         return setDefaultQ(p_FM);
01957     }
01958 
01959     // Get the topological default values for the initial q's.
01960     const Vec3& getDefaultTranslation() const {
01961         return getDefaultQ();
01962     }
01963 
01964     // Set the current value of q's in the given State. Note that this is
01965     // the *cross-mobilizer* translation, not location in the Ground frame.
01966     void setMobilizerTranslation(State& s, const Vec3& p_FM) const {
01967         setQ(s,p_FM);
01968     }
01969 
01970     // Get the current value of the q's for this mobilizer from the given State.
01971     const Vec3& getMobilizerTranslation(const State& s) const {
01972         return getQ(s);
01973     }
01974 
01975 
01976     // Set the current value of u's in the given State. Note that this is
01977     // the *cross-mobilizer* velocity v_FM, not velocity in the Ground frame.
01978     void setMobilizerVelocity(State& s, const Vec3& v_FM) const {
01979         setU(s,v_FM);
01980     }
01981 
01982     // Get the current value of the u's for this mobilizer from the given State.
01983     const Vec3& getMobilizerVelocity(const State& s) const {
01984         return getU(s);
01985     }
01986 
01987     // Get the value of the udot's for this mobilizer from the given State.
01988     const Vec3& getMobilizerAcceleration(const State& s) const {
01989         return getUDot(s);
01990     }
01991 
01992     // Generic default state Topology methods.
01993     const Vec3& getDefaultQ() const;
01994     Translation& setDefaultQ(const Vec3& q);
01995 
01996     const Vec3& getQ(const State&) const;
01997     const Vec3& getQDot(const State&) const;
01998     const Vec3& getQDotDot(const State&) const;
01999     const Vec3& getU(const State&) const;
02000     const Vec3& getUDot(const State&) const;
02001 
02002     void setQ(State&, const Vec3&) const;
02003     void setU(State&, const Vec3&) const;
02004 
02005     const Vec3& getMyPartQ(const State&, const Vector& qlike) const;
02006     const Vec3& getMyPartU(const State&, const Vector& ulike) const;
02007    
02008     Vec3& updMyPartQ(const State&, Vector& qlike) const;
02009     Vec3& updMyPartU(const State&, Vector& ulike) const;
02010     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Translation, TranslationImpl, MobilizedBody);
02011 };
02012 
02019 class SimTK_SIMBODY_EXPORT MobilizedBody::Free : public MobilizedBody {
02020 public:
02021     Free();
02022 
02025     Free(MobilizedBody& parent, const Body&);
02026 
02029     Free(MobilizedBody& parent, const Transform& inbFrame,
02030          const Body&,           const Transform& outbFrame);
02031 
02032     Free& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) {
02033         (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this;
02034     }
02035     Free& addOutboardDecoration(const Transform& X_MD,  const DecorativeGeometry& g) {
02036         (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this;
02037     }
02038     Free& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) {
02039         (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this;
02040     }
02041 
02042     Free& setDefaultInboardFrame(const Transform& X_PF) {
02043         (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this;
02044     }
02045 
02046     Free& setDefaultOutboardFrame(const Transform& X_BM) {
02047         (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this;
02048     }
02049 
02050     // Leaves rotation unchanged.
02051     Free& setDefaultTranslation(const Vec3&);
02052 
02053     // Leaves translation unchanged. The internal representation is a quaternion
02054     // so we guarantee that the stored value is numerically identical to the
02055     // supplied one.
02056     Free& setDefaultQuaternion(const Quaternion&);
02057 
02058     // Leaves translation unchanged. The Rotation matrix will be converted to
02059     // a quaternion for storage.
02060     Free& setDefaultRotation(const Rotation&);
02061     // Sets both translation and rotation. The Rotation part of the Transform 
02062     // will be converted to a quaternion for storage.
02063     Free& setDefaultTransform(const Transform&);
02064 
02065     // These return references to the stored default values.
02066     const Vec3& getDefaultTranslation() const;
02067     const Quaternion& getDefaultQuaternion() const;
02068 
02069     // These next two are derived from the stored values.
02070     Rotation getDefaultRotation() const {
02071         return Rotation(getDefaultQuaternion());
02072     }
02073     Transform getDefaultTransform() const {
02074         return Transform(Rotation(getDefaultQuaternion()), getDefaultTranslation());
02075     }
02076 
02077     // Generic default state Topology methods.
02078 
02079     // Returns (Vec4,Vec3) where the Vec4 is a normalized quaternion.
02080     const Vec7& getDefaultQ() const;
02081 
02082     // Interprets the supplied q as (Vec4,Vec3) where the Vec4 is a possibly
02083     // unnormalized quaternion. The quaternion will be normalized before it is
02084     // stored here, so you may not get back exactly the value supplied here if
02085     // you call getDefaultQ().
02086     Free& setDefaultQ(const Vec7& q);
02087 
02088     // Note that there is no guarantee that the quaternion part of the returned Q is normalized.
02089     const Vec7& getQ(const State&) const;
02090     const Vec7& getQDot(const State&) const;
02091     const Vec7& getQDotDot(const State&) const;
02092 
02093     const Vec6& getU(const State&) const;
02094     const Vec6& getUDot(const State&) const;
02095 
02096     // The Q's in the state are set exactly as supplied without normalization.
02097     void setQ(State&, const Vec7&) const;
02098     void setU(State&, const Vec6&) const;
02099 
02100     const Vec7& getMyPartQ(const State&, const Vector& qlike) const;
02101     const Vec6& getMyPartU(const State&, const Vector& ulike) const;
02102    
02103     Vec7& updMyPartQ(const State&, Vector& qlike) const;
02104     Vec6& updMyPartU(const State&, Vector& ulike) const;
02105     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Free, FreeImpl, MobilizedBody);
02106 };
02107 
02108 
02109 // These are special "ball" and "free" joints designed to allow arbitrary orientations
02110 // for "linear" bodies, such as a CO2 molecule consisting only of point masses arranged
02111 // along a straight line. Such bodies have no inertia about the line and cause singularities
02112 // in the equations of motion if attached to Orientation or Free mobilizers. Instead, use the
02113 // LineOrientation and LineFree moblizers, making sure that the inertialess direction is
02114 // along the outboard body's z axis (that is, Mz). These mobilizers introduce only two
02115 // mobilities (generalized speeds u), being incapable of representing non-zero angular
02116 // velocity of M in F about Mz. The generalized speeds are in fact the wx and wy 
02117 // components of w_FM_M, that is, the x and y components of the angular velocity of M
02118 // in F *expressed in M*. However, at least three generalized coordinates (q's)
02119 // are required to represent the orientation. By default we use four quaternions for
02120 // unconditional stability. Alternatively, you can request a 1-2-3 body fixed 
02121 // Euler angle sequence (that is, about x, then new y, then new z) which will
02122 // suffer a singularity when the y rotation is 90 degrees since that aligns the
02123 // first rotation axis (x) with the last (z) which is the inertialess direction.
02124 
02130 class SimTK_SIMBODY_EXPORT MobilizedBody::LineOrientation : public MobilizedBody {
02131 public:
02132     LineOrientation();
02133 
02134 
02137     LineOrientation(MobilizedBody& parent, const Body&);
02138 
02141     LineOrientation(MobilizedBody& parent, const Transform& inbFrame,
02142                     const Body&,           const Transform& outbFrame);
02143 
02144     LineOrientation& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) {
02145         (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this;
02146     }
02147     LineOrientation& addOutboardDecoration(const Transform& X_MD,  const DecorativeGeometry& g) {
02148         (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this;
02149     }
02150     LineOrientation& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) {
02151         (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this;
02152     }
02153 
02154     LineOrientation& setDefaultInboardFrame(const Transform& X_PF) {
02155         (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this;
02156     }
02157 
02158     LineOrientation& setDefaultOutboardFrame(const Transform& X_BM) {
02159         (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this;
02160     }
02161     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(LineOrientation, LineOrientationImpl, MobilizedBody);
02162 };
02163 
02168 class SimTK_SIMBODY_EXPORT MobilizedBody::FreeLine : public MobilizedBody {
02169 public:
02170     FreeLine();
02171 
02174     FreeLine(MobilizedBody& parent, const Body&);
02175 
02178     FreeLine(MobilizedBody& parent, const Transform& inbFrame,
02179              const Body&,           const Transform& outbFrame);
02180 
02181     FreeLine& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) {
02182         (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this;
02183     }
02184     FreeLine& addOutboardDecoration(const Transform& X_MD,  const DecorativeGeometry& g) {
02185         (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this;
02186     }
02187     FreeLine& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) {
02188         (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this;
02189     }
02190 
02191     FreeLine& setDefaultInboardFrame(const Transform& X_PF) {
02192         (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this;
02193     }
02194 
02195     FreeLine& setDefaultOutboardFrame(const Transform& X_BM) {
02196         (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this;
02197     }
02198     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(FreeLine, FreeLineImpl, MobilizedBody);
02199 };
02200 
02204 class SimTK_SIMBODY_EXPORT MobilizedBody::Weld : public MobilizedBody {
02205 public:
02206     Weld();
02207 
02208 
02211     Weld(MobilizedBody& parent, const Body&);
02212 
02215     Weld(MobilizedBody& parent, const Transform& inbFrame,
02216          const Body&,           const Transform& outbFrame);
02217 
02218     Weld& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) {
02219         (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this;
02220     }
02221     Weld& addOutboardDecoration(const Transform& X_MD,  const DecorativeGeometry& g) {
02222         (void)MobilizedBody::addOutboardDecoration(X_MD,g); return *this;
02223     }
02224     Weld& addInboardDecoration (const Transform& X_FD, const DecorativeGeometry& g) {
02225         (void)MobilizedBody::addInboardDecoration(X_FD,g); return *this;
02226     }
02227 
02228     Weld& setDefaultInboardFrame(const Transform& X_PF) {
02229         (void)MobilizedBody::setDefaultInboardFrame(X_PF); return *this;
02230     }
02231 
02232     Weld& setDefaultOutboardFrame(const Transform& X_BM) {
02233         (void)MobilizedBody::setDefaultOutboardFrame(X_BM); return *this;
02234     }
02235     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Weld, WeldImpl, MobilizedBody);
02236 };
02237 
02238 
02242 class SimTK_SIMBODY_EXPORT MobilizedBody::Ground : public MobilizedBody {
02243 public:
02244     Ground();
02245     Ground& addBodyDecoration(const Transform& X_BD, const DecorativeGeometry& g) {
02246         (void)MobilizedBody::addBodyDecoration(X_BD,g); return *this;
02247     }
02248     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Ground, GroundImpl, MobilizedBody);
02249 };
02250 
02251 
02283 class SimTK_SIMBODY_EXPORT MobilizedBody::Custom : public MobilizedBody {
02284 public:
02285     class Implementation;
02286     class ImplementationImpl;
02287 
02288     /* Create a Custom MobilizedBody.
02289      * 
02290      * @param parent         the MobilizedBody's parent body
02291      * @param implementation the object which implements the custom mobilized body.  The MobilizedBody::Custom takes over
02292      *                       ownership of the implementation object, and deletes it when the MobilizedBody itself
02293      *                       is deleted.
02294      * @param body           describes this MobilizedBody's physical properties
02295      */
02296     explicit Custom(MobilizedBody& parent, Implementation* implementation, const Body& body);
02297     /* Create a Custom MobilizedBody.
02298      * 
02299      * @param parent         the MobilizedBody's parent body
02300      * @param implementation the object which implements the custom mobilized body.  The MobilizedBody::Custom takes over
02301      *                       ownership of the implementation object, and deletes it when the MobilizedBody itself
02302      *                       is deleted.
02303      * @param inbFrame       the MobilizedBody's inboard reference frame
02304      * @param body           describes this MobilizedBody's physical properties
02305      * @param outbFrame      the MobilizedBody's outboard reference frame
02306      */
02307     explicit Custom(MobilizedBody& parent, Implementation* implementation, const Transform& inbFrame, const Body& body, const Transform& outbFrame);
02308     SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(Custom, CustomImpl, MobilizedBody);
02309 protected:
02310     const Implementation& getImplementation() const;
02311     Implementation&       updImplementation();
02312 };
02313 
02314 // We only want the template instantiation to occur once. This symbol is defined in the SimTK core
02315 // compilation unit that defines the MobilizedBody class but should not be defined any other time.
02316 // BE SURE TO DEAL WITH THIS IN MobilizedBody_Instantiation.cpp.
02317 #ifndef SimTK_SIMBODY_DEFINING_MOBILIZED_BODY
02318     extern template class PIMPLHandle<MobilizedBody::Custom::Implementation, MobilizedBody::Custom::ImplementationImpl>;
02319 #endif
02320 
02321 
02322 class SimTK_SIMBODY_EXPORT MobilizedBody::Custom::Implementation 
02323   : public PIMPLHandle<Implementation,ImplementationImpl> 
02324 {
02325 public:
02326     // No default constructor because you have to supply at least the SimbodyMatterSubsystem
02327     // to which this MobilizedBody belongs.
02328 
02330     virtual ~Implementation();
02331 
02336     virtual Implementation* clone() const = 0;
02337 
02361     Implementation(SimbodyMatterSubsystem&, int nu, int nq, int nAngles=0);
02362 
02366     Vector getQ(const State& s) const;
02367     
02369     Vector getU(const State& s) const;
02370 
02374     Vector getQDot(const State& s) const;
02375 
02377     Vector getUDot(const State& s) const;
02378     
02382     Vector getQDotDot(const State& s) const;
02383 
02387     const Transform& getMobilizerTransform(const State& s) const;
02388 
02393     const SpatialVec& getMobilizerVelocity(const State& s) const;
02394 
02403     bool getUseEulerAngles(const State& s) const;
02404 
02411     void invalidateTopologyCache() const;
02412 
02417 
02418 
02423     virtual Transform calcMobilizerTransformFromQ(const State& s, int nq, const Real* q) const = 0;
02424 
02425 
02433 
02434     // TODO: UGLY CAVEAT -- I believe that the "H" I'm using here is the transpose of what
02435     // is used in the code internally. That's because unfortunately for historical reasons
02436     // Abhi Jain used H^T as the joint kinematics Jacobian, with H being the force transmission
02437     // matrix which no mobilizer-writing user is going to care about. It would be best to 
02438     // use the matrix in this friendlier way (or perhaps call it something else like "J" for
02439     // Jacobian, although that is heavily overloaded) at least here in the interface but 
02440     // ideally we would change the sense of the matrix everywhere. In Schwieters' paper he
02441     // reversed Jain's body numbering scheme but not the sense of H. Perhaps I'm wrong and
02442     // we ought just to leave the sense alone since users have to give us both H and H^T 
02443     // operators here.
02444     virtual SpatialVec multiplyByHMatrix(const State& s, int nu, const Real* u) const = 0;
02445 
02452     virtual void multiplyByHTranspose(const State& s, const SpatialVec& F, int nu, Real* f) const = 0;
02453 
02463     virtual SpatialVec multiplyByHDotMatrix(const State& s, int nu, const Real* u) const = 0;
02464 
02473     virtual void multiplyByHDotTranspose(const State& s, const SpatialVec& F, int nu, Real* f) const = 0;
02474 
02485     virtual void multiplyByQMatrix(const State& s, bool transposeMatrix, 
02486                            int nIn, const Real* in, int nOut, Real* out) const;
02487 
02498     virtual void multiplyByQInverse(const State& s, bool transposeMatrix, 
02499                                            int nIn, const Real* in, int nOut, Real* out) const;
02500 
02511     virtual void multiplyByQDotMatrix(const State& s, bool transposeMatrix, 
02512                                              int nIn, const Real* in, int nOut, Real* out) const;
02513 
02514         // Methods for setting Mobilizer initial conditions. Note -- I've stripped this
02515         // down to the two basic routines but the built-ins have 8 so that you can 
02516         // specify only rotations or translations. I'm not sure that's needed here and
02517         // I suppose you could add more routines later if needed.
02518         // Eventually it might be nice to provide default implementation here that would
02519         // use a root finder to attempt to solve these initial condition problems. For
02520         // most joints there is a much more direct way to do it, and sometimes there
02521         // are behavioral choices to make, which is why it is nice to have mobilizer-specific
02522         // overrides for these.
02523 
02532     virtual void setQToFitTransform(const State&, const Transform& X_FM, int nq, Real* q) const;
02533 
02545     virtual void setUToFitVelocity(const State&, const SpatialVec& V_FM, int nu, Real* u) const;
02546 
02553     virtual void calcDecorativeGeometryAndAppend
02554        (const State& s, Stage stage, std::vector<DecorativeGeometry>& geom) const
02555     {
02556     }
02558 
02559 
02568 
02570 
02571 
02572 
02573 
02574 
02575 
02576 
02577 
02578     virtual void realizeTopology(State&) const { }
02579 
02588     virtual void realizeModel(State&) const { }
02589 
02593     virtual void realizeInstance(const State&) const { }
02594 
02599     virtual void realizeTime(const State&) const { }
02600 
02607     virtual void realizePosition(const State&) const { }
02608 
02615     virtual void realizeVelocity(const State&) const { }
02616 
02623     virtual void realizeDynamics(const State&) const { }
02624 
02631     virtual void realizeAcceleration(const State&) const { }
02632 
02638     virtual void realizeReport(const State&) const { }
02640 
02641     friend class MobilizedBody::CustomImpl;
02642 };
02643 
02655 class SimTK_SIMBODY_EXPORT MobilizedBody::FunctionBased : public MobilizedBody::Custom {
02656 public:
02657     /* Create a FunctionBased MobilizedBody.
02658      * 
02659      * @param parent         the MobilizedBody's parent body
02660      * @param body           describes this MobilizedBody's physical properties
02661      * @param nmobilities    the number of generalized coordinates belonging to this MobilizedBody
02662      * @param functions      the Functions describing how the body moves based on its generalized coordinates.
02663      *                       This must be of length 6.  The elements correspond to, in order, x rotation, y rotation, z rotation,
02664      *                       x translation, y translation, and z translation.  The MobilizedBody takes over ownership of the functions,
02665      *                       and automatically deletes them when the MobilizedBody is deleted.
02666      * @param coordIndices   the indices of the generalized coordinates that are inputs to each function.  For example, if coordIndices[2] = {0, 1},
02667      *                       that means that functions[2] takes two input arguments, and q[0] and q[1] respectively should be passed as those arguments.
02668      */
02669     FunctionBased(MobilizedBody& parent, const Body& body, int nmobilities, const std::vector<const Function<1>*>& functions, const std::vector<std::vector<int> >& coordIndices);
02670     /* Create a FunctionBased MobilizedBody.
02671      * 
02672      * @param parent         the MobilizedBody's parent body
02673      * @param inbFrame       the default inboard frame
02674      * @param body           describes this MobilizedBody's physical properties
02675      * @param outbFrame      the default outboard frame
02676      * @param nmobilities    the number of generalized coordinates belonging to this MobilizedBody
02677      * @param functions      the Functions describing how the body moves based on its generalized coordinates.
02678      *                       This must be of length 6.  The elements correspond to, in order, x rotation, y rotation, z rotation,
02679      *                       x translation, y translation, and z translation.  The MobilizedBody takes over ownership of the functions,
02680      *                       and automatically deletes them when the MobilizedBody is deleted.
02681      * @param coordIndices   the indices of the generalized coordinates that are inputs to each function.  For example, if coordIndices[2] = {0, 1},
02682      *                       that means that functions[2] takes two input arguments, and q[0] and q[1] respectively should be passed as those arguments.
02683      */
02684     FunctionBased(MobilizedBody& parent, const Transform& inbFrame, const Body& body, const Transform& outbFrame, int nmobilities, const std::vector<const Function<1>*>& functions, const std::vector<std::vector<int> >& coordIndices);
02685     /* Create a FunctionBased MobilizedBody.
02686      * 
02687      * @param parent         the MobilizedBody's parent body
02688      * @param body           describes this MobilizedBody's physical properties
02689      * @param nmobilities    the number of generalized coordinates belonging to this MobilizedBody
02690      * @param functions      the Functions describing how the body moves based on its generalized coordinates.
02691      *                       This must be of length 6.  The elements correspond to, in order, x rotation, y rotation, z rotation,
02692      *                       x translation, y translation, and z translation.  The MobilizedBody takes over ownership of the functions,
02693      *                       and automatically deletes them when the MobilizedBody is deleted.
02694      * @param coordIndices   the indices of the generalized coordinates that are inputs to each function.  For example, if coordIndices[2] = {0, 1},
02695      *                       that means that functions[2] takes two input arguments, and q[0] and q[1] respectively should be passed as those arguments.
02696      * @param axes           the axes directions (as Vec3's) for each spatial coordinate, which each function describes, and is therefore length 6.
02697      *                       First 3 and last 3 axes must be linearly independent, otherwise there will be redundant speeds for the same motion.
02698      */
02699     FunctionBased(MobilizedBody& parent, const Body& body, int nmobilities, const std::vector<const Function<1>*>& functions, const std::vector<std::vector<int> >& coordIndices, const std::vector<Vec3>& axes);
02700     /* Create a FunctionBased MobilizedBody.
02701      * 
02702      * @param parent         the MobilizedBody's parent body
02703      * @param inbFrame       the default inboard frame
02704      * @param body           describes this MobilizedBody's physical properties
02705      * @param outbFrame      the default outboard frame
02706      * @param nmobilities    the number of generalized coordinates belonging to this MobilizedBody
02707      * @param functions      the Functions describing how the body moves based on its generalized coordinates.
02708      *                       This must be of length 6.  The elements correspond to, in order, x rotation, y rotation, z rotation,
02709      *                       x translation, y translation, and z translation.  The MobilizedBody takes over ownership of the functions,
02710      *                       and automatically deletes them when the MobilizedBody is deleted.
02711      * @param coordIndices   the indices of the generalized coordinates that are inputs to each function.  For example, if coordIndices[2] = {0, 1},
02712      *                       that means that functions[2] takes two input arguments, and q[0] and q[1] respectively should be passed as those arguments.
02713      * @param axes           the axes directions (as Vec3's) for each spatial coordinate, which each function describes, and is therefore length 6.
02714      *                       First 3 and last 3 axes must be linearly independent, otherwise there will be redundant speeds for the same motion.
02715      */
02716     FunctionBased(MobilizedBody& parent, const Transform& inbFrame, const Body& body, const Transform& outbFrame, int nmobilities, const std::vector<const Function<1>*>& functions, const std::vector<std::vector<int> >& coordIndices, const std::vector<Vec3>& axes);
02717 };
02718 
02719 } // namespace SimTK
02720 
02721 #endif // SimTK_SIMBODY_MOBILIZED_BODY_H_
02722 
02723 
02724 

Generated on Fri Sep 26 07:44:15 2008 for SimTKcore by  doxygen 1.5.6