Simbody  3.4 (development)
MultibodyGraphMaker.h
Go to the documentation of this file.
00001 #ifndef SimTK_SIMMATH_MULTIBODY_GRAPH_MAKER_H_
00002 #define SimTK_SIMMATH_MULTIBODY_GRAPH_MAKER_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                     Simbody(tm): Multibody Graph Maker                     *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK biosimulation toolkit originating from           *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
00011  *                                                                            *
00012  * Portions copyright (c) 2013 Stanford University and the Authors.           *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors: Kevin He                                                     *
00015  *                                                                            *
00016  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
00017  * not use this file except in compliance with the License. You may obtain a  *
00018  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
00019  *                                                                            *
00020  * Unless required by applicable law or agreed to in writing, software        *
00021  * distributed under the License is distributed on an "AS IS" BASIS,          *
00022  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
00023  * See the License for the specific language governing permissions and        *
00024  * limitations under the License.                                             *
00025  * -------------------------------------------------------------------------- */
00026 
00032 #include "SimTKcommon.h"
00033 #include "simmath/internal/common.h"
00034 
00035 #include <utility>
00036 #include <string>
00037 #include <vector>
00038 #include <map>
00039 #include <iosfwd>
00040 
00041 namespace SimTK {
00042 
00043 //==============================================================================
00044 //                          MULTIBODY GRAPH MAKER
00045 //==============================================================================
00146 class SimTK_SIMMATH_EXPORT MultibodyGraphMaker {
00147 public:
00148     // Local classes.
00149     class Body;
00150     class Joint;
00151     class JointType;
00152     class Mobilizer;
00153     class LoopConstraint;
00154 
00157     MultibodyGraphMaker();
00158 
00159 
00164     int addJointType(const std::string& name,
00165                      int                numMobilities,
00166                      bool               haveGoodLoopJointAvailable = false,
00167                      void*              userRef                    = 0);
00168 
00169 
00191     void addBody(const std::string&  name, 
00192                  double              mass, 
00193                  bool                mustBeBaseBody,
00194                  void*               userRef = 0);
00195 
00204     bool deleteBody(const std::string&  name);
00205 
00238     void addJoint(const std::string& name,
00239                   const std::string& type,
00240                   const std::string& parentBodyName,
00241                   const std::string& childBodyName,
00242                   bool               mustBeLoopJoint,
00243                   void*              userRef = 0);
00244 
00253     bool deleteJoint(const std::string& name);
00254 
00257     void generateGraph();
00258     void clearGraph();
00259 
00261     void dumpGraph(std::ostream& out) const;
00262 
00269     int getNumMobilizers() const {return (int)mobilizers.size();}
00272     const Mobilizer& getMobilizer(int mobilizerNum) const
00273     {   return mobilizers[mobilizerNum]; }
00274 
00282     int getNumLoopConstraints() const {return (int)constraints.size();}
00285     const LoopConstraint& getLoopConstraint(int loopConstraintNum) const
00286     {   return constraints[loopConstraintNum]; }
00287 
00290     int getNumBodies() const {return (int)bodies.size();}
00294     const Body& getBody(int bodyNum) const {return bodies[bodyNum];}
00298     int getBodyNum(const std::string& bodyName) const {
00299         std::map<std::string,int>::const_iterator p = 
00300             bodyName2Num.find(bodyName);
00301         return p==bodyName2Num.end() ? -1 : p->second;
00302     }
00303 
00308     int getNumJoints() const {return (int)joints.size();}
00311     const Joint& getJoint(int jointNum) const {return joints[jointNum];}
00315     int getJointNum(const std::string& jointName) const {
00316         std::map<std::string,int>::const_iterator p = 
00317             jointName2Num.find(jointName);
00318         return p==jointName2Num.end() ? -1 : p->second;
00319     }
00320 
00322     int getNumJointTypes() const {return (int)jointTypes.size();}
00324     const JointType& getJointType(int jointTypeNum) const 
00325     {   return jointTypes[jointTypeNum]; }
00327     int getJointTypeNum(const std::string& jointTypeName) const {
00328         std::map<std::string,int>::const_iterator p = 
00329             jointTypeName2Num.find(jointTypeName);
00330         return p==jointTypeName2Num.end() ? -1 : p->second;
00331     }
00332 
00336     void setWeldJointTypeName(const std::string& name) 
00337     {   weldTypeName=name; initialize(); }
00340     const std::string& getWeldJointTypeName() const {return weldTypeName;}
00341 
00345     void setFreeJointTypeName(const std::string& name) 
00346     {   freeTypeName=name; initialize(); }
00349     const std::string& getFreeJointTypeName() const {return freeTypeName;}
00350 
00353     const std::string& getGroundBodyName() const;
00354 private:
00355     // Get writable access to bodies and joints.
00356     Body& updBody(int bodyNum) {return bodies[bodyNum];}
00357     Joint& updJoint(int jointNum) {return joints[jointNum];}
00358     Joint& updJoint(const std::string& name) {return joints[jointName2Num[name]];}
00359 
00360     void initialize();
00361     int splitBody(int bodyNum);
00362     int chooseNewBaseBody() const;
00363     void connectBodyToGround(int bodyNum);
00364     int addMobilizerForJoint(int jointNum);
00365     int findHeaviestUnassignedForwardJoint(int inboardBody) const;
00366     int findHeaviestUnassignedReverseJoint(int inboardBody) const;
00367     void growTree();
00368     void breakLoops();
00369     bool bodiesAreConnected(int b1, int b2) const;
00370 
00371     // Clear everything except for default names.
00372     void clear() {
00373         bodies.clear(); joints.clear(); jointTypes.clear();
00374         bodyName2Num.clear(); jointName2Num.clear(); jointTypeName2Num.clear();
00375         mobilizers.clear(); constraints.clear();
00376     }
00377 
00378     std::string                 weldTypeName, freeTypeName;
00379     std::vector<Body>           bodies; // ground + input bodies + slaves
00380     std::vector<Joint>          joints; // input joints + added joints
00381     std::vector<JointType>      jointTypes;
00382     std::map<std::string,int>   bodyName2Num;
00383     std::map<std::string,int>   jointName2Num;
00384     std::map<std::string,int>   jointTypeName2Num;
00385 
00386     // Calculated by generateGraph()
00387     std::vector<Mobilizer>      mobilizers; // mobilized bodies
00388     std::vector<LoopConstraint> constraints;
00389 };
00390 
00391 //------------------------------------------------------------------------------
00392 //                      MULTIBODY GRAPH MAKER :: BODY
00393 //------------------------------------------------------------------------------
00395 class MultibodyGraphMaker::Body {
00396 public:
00397     explicit Body(const std::string&    name, 
00398                     double              mass, 
00399                     bool                mustBeBaseBody,
00400                     void*               userRef) 
00401     :   name(name), mass(mass), mustBeBaseBody(mustBeBaseBody), 
00402         userRef(userRef), level(-1), mobilizer(-1), master(-1) {}
00403 
00404     void forgetGraph(MultibodyGraphMaker& graph);
00405     int getNumFragments() const {return 1 + getNumSlaves();}
00406     int getNumSlaves() const {return (int)slaves.size();}
00407     int getNumJoints() const 
00408     {   return int(jointsAsChild.size() + jointsAsParent.size()); }
00409     bool isSlave() const {return master >= 0;}
00410     bool isMaster() const {return getNumSlaves()>0;}
00411     bool isInTree() const {return level>=0;}
00412 
00413     // Inputs
00414     std::string name;
00415     double      mass;
00416     bool        mustBeBaseBody;
00417     void*       userRef;
00418 
00419     // How this body appears in joints (input and added).
00420     std::vector<int>    jointsAsChild;  // where this body is the child
00421     std::vector<int>    jointsAsParent; // where this body is the parent
00422 
00423     // Disposition of this body in the spanning tree.
00424 
00425     int level; // Ground=0, connected to Ground=1, contact to that=2, etc.
00426     int mobilizer; // the unique mobilizer where this is the outboard body
00427 
00428     int                 master; // >=0 if this is a slave
00429     std::vector<int>    slaves; // slave links, if this is a master
00430 };
00431 
00432 //------------------------------------------------------------------------------
00433 //                      MULTIBODY GRAPH MAKER :: JOINT
00434 //------------------------------------------------------------------------------
00436 class MultibodyGraphMaker::Joint {
00437 public:
00438     Joint(const std::string& name, int jointTypeNum, 
00439           int parentBodyNum, int childBodyNum,
00440           bool mustBeLoopJoint, void* userRef)
00441     :   name(name), jointTypeNum(jointTypeNum), 
00442         parentBodyNum(parentBodyNum), childBodyNum(childBodyNum),
00443         mustBeLoopJoint(mustBeLoopJoint), userRef(userRef),
00444         isAddedBaseJoint(false), mobilizer(-1), loopConstraint(-1) {}
00445 
00448     bool forgetGraph(MultibodyGraphMaker& graph);
00449 
00450     // Only one of these will be true -- we don't consider it a LoopConstraint
00451     // if we split a body and weld it back.
00452     bool hasMobilizer() const {return mobilizer>=0;}
00453     bool hasLoopConstraint() const {return loopConstraint>=0;}
00454 
00455     // Inputs
00456     std::string name;
00457     bool        mustBeLoopJoint;
00458     void*       userRef;
00459 
00460     // Mapping of strings to indices for fast lookup.
00461     int parentBodyNum, childBodyNum;
00462     int jointTypeNum;
00463 
00464     bool isAddedBaseJoint; // true if this wasn't one of the input joints
00465 
00466     // Disposition of this joint in the multibody graph.
00467     int mobilizer;      // if this joint is part of the spanning tree, else -1
00468     int loopConstraint; // if this joint used a loop constraint, else -1
00469 };
00470 
00471 //------------------------------------------------------------------------------
00472 //                   MULTIBODY GRAPH MAKER :: JOINT TYPE
00473 //------------------------------------------------------------------------------
00475 class MultibodyGraphMaker::JointType {
00476 public:
00477     JointType(const std::string& name, int numMobilities, 
00478               bool haveGoodLoopJointAvailable, void* userRef)
00479     :   name(name), numMobilities(numMobilities), 
00480         haveGoodLoopJointAvailable(haveGoodLoopJointAvailable),
00481         userRef(userRef) {}
00482     std::string name;
00483     int         numMobilities;
00484     bool        haveGoodLoopJointAvailable;
00485     void*       userRef;
00486 };
00487 
00488 //------------------------------------------------------------------------------
00489 //                   MULTIBODY GRAPH MAKER :: MOBILIZER
00490 //------------------------------------------------------------------------------
00494 class MultibodyGraphMaker::Mobilizer {
00495 public:
00496     Mobilizer() 
00497     :   joint(-1), level(-1), inboardBody(-1), outboardBody(-1),
00498         isReversed(false), mgm(0) {}
00499     Mobilizer(int jointNum, int level, int inboardBodyNum, int outboardBodyNum, 
00500               bool isReversed, MultibodyGraphMaker* graphMaker)
00501     :   joint(jointNum), level(level), inboardBody(inboardBodyNum), 
00502         outboardBody(outboardBodyNum), isReversed(isReversed),
00503         mgm(graphMaker) {}
00504 
00511     bool isAddedBaseMobilizer() const
00512     {   return mgm->getJoint(joint).isAddedBaseJoint; }
00516     void* getJointRef() const
00517     {   return mgm->getJoint(joint).userRef; } 
00522     void* getInboardBodyRef() const
00523     {   return mgm->getBody(inboardBody).userRef; }   
00529     void* getOutboardBodyRef() const
00530     {   return mgm->getBody(outboardBody).userRef; }
00535     void* getOutboardMasterBodyRef() const
00536     {   return mgm->getBody(getOutboardMasterBodyNum()).userRef; }
00538     const std::string& getJointTypeName() const
00539     {   return mgm->getJointType(mgm->getJoint(joint).jointTypeNum).name; }
00542     void* getJointTypeRef() const
00543     {   return mgm->getJointType(mgm->getJoint(joint).jointTypeNum).userRef; }
00546     bool isSlaveMobilizer() const
00547     {   return mgm->getBody(outboardBody).isSlave(); }
00553     int getNumFragments() const 
00554     {   return mgm->getBody(getOutboardMasterBodyNum()).getNumFragments(); }
00559     bool isReversedFromJoint() const {return isReversed;}
00560 
00561 private:
00562 friend class MultibodyGraphMaker;
00563 
00564     int getOutboardMasterBodyNum() const
00565     {   const Body& outb = mgm->getBody(outboardBody);
00566         return outb.isSlave() ? outb.master : outboardBody; }
00567 
00568     int  joint;         
00569     int  level;         
00570     int  inboardBody;   
00571     int  outboardBody;  
00572     bool isReversed;    
00573 
00574     MultibodyGraphMaker*    mgm; // just a reference to container
00575 };
00576 
00577 
00578 //------------------------------------------------------------------------------
00579 //                  MULTIBODY GRAPH MAKER :: LOOP CONSTRAINT
00580 //------------------------------------------------------------------------------
00583 class MultibodyGraphMaker::LoopConstraint {
00584 public:
00585     LoopConstraint() : joint(-1), parentBody(-1), childBody(-1), mgm(0) {}
00586     LoopConstraint(const std::string& type, int jointNum, 
00587                    int parentBodyNum, int childBodyNum,
00588                    MultibodyGraphMaker* graphMaker) 
00589     :   type(type), joint(jointNum), 
00590         parentBody(parentBodyNum), childBody(childBodyNum), 
00591         mgm(graphMaker) {}
00592 
00595     void* getJointRef() const
00596     {   return mgm->getJoint(joint).userRef; } 
00599     const std::string& getJointTypeName() const
00600     {   return type; }
00603     void* getParentBodyRef() const
00604     {   return mgm->getBody(parentBody).userRef; }   
00607     void* getChildBodyRef() const
00608     {   return mgm->getBody(childBody).userRef; }
00609 
00610 private:
00611 friend class MultibodyGraphMaker;
00612 
00613     std::string type;        // e.g., ball
00614     int         joint;       // always one of the input joints
00615     int         parentBody;  // parent from the joint
00616     int         childBody;   // child from the joint
00617 
00618     MultibodyGraphMaker*    mgm; // just a reference to container
00619 };
00620 
00621 
00622 } // namespace SimTK
00623 
00624 #endif // SimTK_SIMMATH_MULTIBODY_GRAPH_MAKER_H_
00625 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines