Simbody  3.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MultibodyGraphMaker.h
Go to the documentation of this file.
1 #ifndef SimTK_SIMMATH_MULTIBODY_GRAPH_MAKER_H_
2 #define SimTK_SIMMATH_MULTIBODY_GRAPH_MAKER_H_
3 
4 /* -------------------------------------------------------------------------- *
5  * Simbody(tm): Multibody Graph Maker *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from *
8  * Simbios, the NIH National Center for Physics-Based Simulation of *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11  * *
12  * Portions copyright (c) 2013 Stanford University and the Authors. *
13  * Authors: Michael Sherman *
14  * Contributors: Kevin He *
15  * *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may *
17  * not use this file except in compliance with the License. You may obtain a *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
19  * *
20  * Unless required by applicable law or agreed to in writing, software *
21  * distributed under the License is distributed on an "AS IS" BASIS, *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
23  * See the License for the specific language governing permissions and *
24  * limitations under the License. *
25  * -------------------------------------------------------------------------- */
26 
32 #include "SimTKcommon.h"
34 
35 #include <utility>
36 #include <string>
37 #include <vector>
38 #include <map>
39 #include <iosfwd>
40 
41 namespace SimTK {
42 
43 //==============================================================================
44 // MULTIBODY GRAPH MAKER
45 //==============================================================================
147 public:
148  // Local classes.
149  class Body;
150  class Joint;
151  class JointType;
152  class Mobilizer;
153  class LoopConstraint;
154 
158 
159 
164  int addJointType(const std::string& name,
165  int numMobilities,
166  bool haveGoodLoopJointAvailable = false,
167  void* userRef = 0);
168 
169 
191  void addBody(const std::string& name,
192  double mass,
193  bool mustBeBaseBody,
194  void* userRef = 0);
195 
204  bool deleteBody(const std::string& name);
205 
238  void addJoint(const std::string& name,
239  const std::string& type,
240  const std::string& parentBodyName,
241  const std::string& childBodyName,
242  bool mustBeLoopJoint,
243  void* userRef = 0);
244 
253  bool deleteJoint(const std::string& name);
254 
257  void generateGraph();
258  void clearGraph();
259 
261  void dumpGraph(std::ostream& out) const;
262 
269  int getNumMobilizers() const {return (int)mobilizers.size();}
272  const Mobilizer& getMobilizer(int mobilizerNum) const
273  { return mobilizers[mobilizerNum]; }
274 
282  int getNumLoopConstraints() const {return (int)constraints.size();}
285  const LoopConstraint& getLoopConstraint(int loopConstraintNum) const
286  { return constraints[loopConstraintNum]; }
287 
290  int getNumBodies() const {return (int)bodies.size();}
294  const Body& getBody(int bodyNum) const {return bodies[bodyNum];}
298  int getBodyNum(const std::string& bodyName) const {
299  std::map<std::string,int>::const_iterator p =
300  bodyName2Num.find(bodyName);
301  return p==bodyName2Num.end() ? -1 : p->second;
302  }
303 
308  int getNumJoints() const {return (int)joints.size();}
311  const Joint& getJoint(int jointNum) const {return joints[jointNum];}
315  int getJointNum(const std::string& jointName) const {
316  std::map<std::string,int>::const_iterator p =
317  jointName2Num.find(jointName);
318  return p==jointName2Num.end() ? -1 : p->second;
319  }
320 
322  int getNumJointTypes() const {return (int)jointTypes.size();}
324  const JointType& getJointType(int jointTypeNum) const
325  { return jointTypes[jointTypeNum]; }
327  int getJointTypeNum(const std::string& jointTypeName) const {
328  std::map<std::string,int>::const_iterator p =
329  jointTypeName2Num.find(jointTypeName);
330  return p==jointTypeName2Num.end() ? -1 : p->second;
331  }
332 
336  void setWeldJointTypeName(const std::string& name)
337  { weldTypeName=name; initialize(); }
340  const std::string& getWeldJointTypeName() const {return weldTypeName;}
341 
345  void setFreeJointTypeName(const std::string& name)
346  { freeTypeName=name; initialize(); }
349  const std::string& getFreeJointTypeName() const {return freeTypeName;}
350 
353  const std::string& getGroundBodyName() const;
354 private:
355  // Get writable access to bodies and joints.
356  Body& updBody(int bodyNum) {return bodies[bodyNum];}
357  Joint& updJoint(int jointNum) {return joints[jointNum];}
358  Joint& updJoint(const std::string& name) {return joints[jointName2Num[name]];}
359 
360  void initialize();
361  int splitBody(int bodyNum);
362  int chooseNewBaseBody() const;
363  void connectBodyToGround(int bodyNum);
364  int addMobilizerForJoint(int jointNum);
365  int findHeaviestUnassignedForwardJoint(int inboardBody) const;
366  int findHeaviestUnassignedReverseJoint(int inboardBody) const;
367  void growTree();
368  void breakLoops();
369  bool bodiesAreConnected(int b1, int b2) const;
370 
371  // Clear everything except for default names.
372  void clear() {
373  bodies.clear(); joints.clear(); jointTypes.clear();
374  bodyName2Num.clear(); jointName2Num.clear(); jointTypeName2Num.clear();
375  mobilizers.clear(); constraints.clear();
376  }
377 
378  std::string weldTypeName, freeTypeName;
379  std::vector<Body> bodies; // ground + input bodies + slaves
380  std::vector<Joint> joints; // input joints + added joints
381  std::vector<JointType> jointTypes;
382  std::map<std::string,int> bodyName2Num;
383  std::map<std::string,int> jointName2Num;
384  std::map<std::string,int> jointTypeName2Num;
385 
386  // Calculated by generateGraph()
387  std::vector<Mobilizer> mobilizers; // mobilized bodies
388  std::vector<LoopConstraint> constraints;
389 };
390 
391 //------------------------------------------------------------------------------
392 // MULTIBODY GRAPH MAKER :: BODY
393 //------------------------------------------------------------------------------
396 public:
397  explicit Body(const std::string& name,
398  double mass,
399  bool mustBeBaseBody,
400  void* userRef)
401  : name(name), mass(mass), mustBeBaseBody(mustBeBaseBody),
402  userRef(userRef), level(-1), mobilizer(-1), master(-1) {}
403 
404  void forgetGraph(MultibodyGraphMaker& graph);
405  int getNumFragments() const {return 1 + getNumSlaves();}
406  int getNumSlaves() const {return (int)slaves.size();}
407  int getNumJoints() const
408  { return int(jointsAsChild.size() + jointsAsParent.size()); }
409  bool isSlave() const {return master >= 0;}
410  bool isMaster() const {return getNumSlaves()>0;}
411  bool isInTree() const {return level>=0;}
412 
413  // Inputs
414  std::string name;
415  double mass;
417  void* userRef;
418 
419  // How this body appears in joints (input and added).
420  std::vector<int> jointsAsChild; // where this body is the child
421  std::vector<int> jointsAsParent; // where this body is the parent
422 
423  // Disposition of this body in the spanning tree.
424 
425  int level; // Ground=0, connected to Ground=1, contact to that=2, etc.
426  int mobilizer; // the unique mobilizer where this is the outboard body
427 
428  int master; // >=0 if this is a slave
429  std::vector<int> slaves; // slave links, if this is a master
430 };
431 
432 //------------------------------------------------------------------------------
433 // MULTIBODY GRAPH MAKER :: JOINT
434 //------------------------------------------------------------------------------
437 public:
438  Joint(const std::string& name, int jointTypeNum,
439  int parentBodyNum, int childBodyNum,
440  bool mustBeLoopJoint, void* userRef)
441  : name(name), jointTypeNum(jointTypeNum),
442  parentBodyNum(parentBodyNum), childBodyNum(childBodyNum),
443  mustBeLoopJoint(mustBeLoopJoint), userRef(userRef),
444  isAddedBaseJoint(false), mobilizer(-1), loopConstraint(-1) {}
445 
448  bool forgetGraph(MultibodyGraphMaker& graph);
449 
450  // Only one of these will be true -- we don't consider it a LoopConstraint
451  // if we split a body and weld it back.
452  bool hasMobilizer() const {return mobilizer>=0;}
453  bool hasLoopConstraint() const {return loopConstraint>=0;}
454 
455  // Inputs
456  std::string name;
458  void* userRef;
459 
460  // Mapping of strings to indices for fast lookup.
463 
464  bool isAddedBaseJoint; // true if this wasn't one of the input joints
465 
466  // Disposition of this joint in the multibody graph.
467  int mobilizer; // if this joint is part of the spanning tree, else -1
468  int loopConstraint; // if this joint used a loop constraint, else -1
469 };
470 
471 //------------------------------------------------------------------------------
472 // MULTIBODY GRAPH MAKER :: JOINT TYPE
473 //------------------------------------------------------------------------------
476 public:
477  JointType(const std::string& name, int numMobilities,
479  : name(name), numMobilities(numMobilities),
480  haveGoodLoopJointAvailable(haveGoodLoopJointAvailable),
481  userRef(userRef) {}
482  std::string name;
485  void* userRef;
486 };
487 
488 //------------------------------------------------------------------------------
489 // MULTIBODY GRAPH MAKER :: MOBILIZER
490 //------------------------------------------------------------------------------
495 public:
497  : joint(-1), level(-1), inboardBody(-1), outboardBody(-1),
498  isReversed(false), mgm(0) {}
499  Mobilizer(int jointNum, int level, int inboardBodyNum, int outboardBodyNum,
500  bool isReversed, MultibodyGraphMaker* graphMaker)
501  : joint(jointNum), level(level), inboardBody(inboardBodyNum),
502  outboardBody(outboardBodyNum), isReversed(isReversed),
503  mgm(graphMaker) {}
504 
511  bool isAddedBaseMobilizer() const
512  { return mgm->getJoint(joint).isAddedBaseJoint; }
516  void* getJointRef() const
517  { return mgm->getJoint(joint).userRef; }
522  void* getInboardBodyRef() const
523  { return mgm->getBody(inboardBody).userRef; }
529  void* getOutboardBodyRef() const
530  { return mgm->getBody(outboardBody).userRef; }
536  { return mgm->getBody(getOutboardMasterBodyNum()).userRef; }
538  const std::string& getJointTypeName() const
539  { return mgm->getJointType(mgm->getJoint(joint).jointTypeNum).name; }
542  void* getJointTypeRef() const
543  { return mgm->getJointType(mgm->getJoint(joint).jointTypeNum).userRef; }
546  bool isSlaveMobilizer() const
547  { return mgm->getBody(outboardBody).isSlave(); }
553  int getNumFragments() const
554  { return mgm->getBody(getOutboardMasterBodyNum()).getNumFragments(); }
559  bool isReversedFromJoint() const {return isReversed;}
560 
561 private:
562 friend class MultibodyGraphMaker;
563 
564  int getOutboardMasterBodyNum() const
565  { const Body& outb = mgm->getBody(outboardBody);
566  return outb.isSlave() ? outb.master : outboardBody; }
567 
568  int joint;
569  int level;
570  int inboardBody;
571  int outboardBody;
572  bool isReversed;
573 
574  MultibodyGraphMaker* mgm; // just a reference to container
575 };
576 
577 
578 //------------------------------------------------------------------------------
579 // MULTIBODY GRAPH MAKER :: LOOP CONSTRAINT
580 //------------------------------------------------------------------------------
584 public:
585  LoopConstraint() : joint(-1), parentBody(-1), childBody(-1), mgm(0) {}
586  LoopConstraint(const std::string& type, int jointNum,
587  int parentBodyNum, int childBodyNum,
588  MultibodyGraphMaker* graphMaker)
589  : type(type), joint(jointNum),
590  parentBody(parentBodyNum), childBody(childBodyNum),
591  mgm(graphMaker) {}
592 
595  void* getJointRef() const
596  { return mgm->getJoint(joint).userRef; }
599  const std::string& getJointTypeName() const
600  { return type; }
603  void* getParentBodyRef() const
604  { return mgm->getBody(parentBody).userRef; }
607  void* getChildBodyRef() const
608  { return mgm->getBody(childBody).userRef; }
609 
610 private:
611 friend class MultibodyGraphMaker;
612 
613  std::string type; // e.g., ball
614  int joint; // always one of the input joints
615  int parentBody; // parent from the joint
616  int childBody; // child from the joint
617 
618  MultibodyGraphMaker* mgm; // just a reference to container
619 };
620 
621 
622 } // namespace SimTK
623 
624 #endif // SimTK_SIMMATH_MULTIBODY_GRAPH_MAKER_H_
625