Simbody  3.8
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-4 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 //==============================================================================
153 public:
154  // Local classes.
155 
157  class Body {
158  public:
159  explicit Body(const std::string& name,
160  double mass,
161  bool mustBeBaseBody,
162  void* userRef)
163  : name(name), mass(mass), mustBeBaseBody(mustBeBaseBody),
164  userRef(userRef), level(-1), mobilizer(-1), master(-1) {}
165 
167  int getNumFragments() const {return 1 + getNumSlaves();}
168  int getNumSlaves() const {return (int)slaves.size();}
169  int getNumJoints() const
170  { return int(jointsAsChild.size() + jointsAsParent.size()); }
171  bool isSlave() const {return master >= 0;}
172  bool isMaster() const {return getNumSlaves()>0;}
173  bool isInTree() const {return level>=0;}
174 
175  // Inputs
176  std::string name;
177  double mass;
179  void* userRef;
180 
181  // How this body appears in joints (input and added).
182  std::vector<int> jointsAsChild; // where this body is the child
183  std::vector<int> jointsAsParent; // where this body is the parent
184 
185  // Disposition of this body in the spanning tree.
186 
187  int level; // Ground=0, connected to Ground=1, contact to that=2, etc.
188  int mobilizer; // the unique mobilizer where this is the outboard body
189 
190  int master; // >=0 if this is a slave
191  std::vector<int> slaves; // slave links, if this is a master
192  };
193 
195  class Joint {
196  public:
197  Joint(const std::string& name, int jointTypeNum,
198  int parentBodyNum, int childBodyNum,
199  bool mustBeLoopJoint, void* userRef)
200  : name(name),
201  mustBeLoopJoint(mustBeLoopJoint),
202  userRef(userRef),
203  parentBodyNum(parentBodyNum),
204  childBodyNum(childBodyNum),
205  jointTypeNum(jointTypeNum),
206  isAddedBaseJoint(false),
207  mobilizer(-1),
208  loopConstraint(-1) {}
209 
213 
214  // Only one of these will be true -- we don't consider it a LoopConstraint
215  // if we split a body and weld it back.
216  bool hasMobilizer() const {return mobilizer>=0;}
217  bool hasLoopConstraint() const {return loopConstraint>=0;}
218 
219  // Inputs
220  std::string name;
222  void* userRef;
223 
224  // Mapping of strings to indices for fast lookup.
225  int parentBodyNum, childBodyNum;
227 
228  bool isAddedBaseJoint; // true if this wasn't one of the input joints
229 
230  // Disposition of this joint in the multibody graph.
231  int mobilizer; // if this joint is part of the spanning tree, else -1
232  int loopConstraint; // if this joint used a loop constraint, else -1
233  };
234 
236  class JointType {
237  public:
238  JointType(const std::string& name, int numMobilities,
239  bool haveGoodLoopJointAvailable, void* userRef)
240  : name(name), numMobilities(numMobilities),
241  haveGoodLoopJointAvailable(haveGoodLoopJointAvailable),
242  userRef(userRef) {}
243  std::string name;
246  void* userRef;
247  };
248 
252  class Mobilizer {
253  public:
255  : joint(-1), level(-1), inboardBody(-1), outboardBody(-1),
256  isReversed(false), mgm(0) {}
257  Mobilizer(int jointNum, int level, int inboardBodyNum, int outboardBodyNum,
258  bool isReversed, MultibodyGraphMaker* graphMaker)
259  : joint(jointNum), level(level), inboardBody(inboardBodyNum),
260  outboardBody(outboardBodyNum), isReversed(isReversed),
261  mgm(graphMaker) {}
262 
269  bool isAddedBaseMobilizer() const
270  { return mgm->getJoint(joint).isAddedBaseJoint; }
274  void* getJointRef() const
275  { return mgm->getJoint(joint).userRef; }
280  void* getInboardBodyRef() const
281  { return mgm->getBody(inboardBody).userRef; }
287  void* getOutboardBodyRef() const
288  { return mgm->getBody(outboardBody).userRef; }
294  { return mgm->getBody(getOutboardMasterBodyNum()).userRef; }
296  const std::string& getJointTypeName() const
297  { return mgm->getJointType(mgm->getJoint(joint).jointTypeNum).name; }
300  void* getJointTypeRef() const
301  { return mgm->getJointType(mgm->getJoint(joint).jointTypeNum).userRef; }
304  bool isSlaveMobilizer() const
305  { return mgm->getBody(outboardBody).isSlave(); }
311  int getNumFragments() const
312  { return mgm->getBody(getOutboardMasterBodyNum()).getNumFragments(); }
317  bool isReversedFromJoint() const {return isReversed;}
319  int getLevel() const {return level;}
320 
321  private:
322  friend class MultibodyGraphMaker;
323 
324  int getOutboardMasterBodyNum() const
325  { const Body& outb = mgm->getBody(outboardBody);
326  return outb.isSlave() ? outb.master : outboardBody; }
327 
328  int joint;
329  int level;
330  int inboardBody;
331  int outboardBody;
332  bool isReversed;
333 
334  MultibodyGraphMaker* mgm; // just a reference to container
335  };
336 
340  public:
341  LoopConstraint() : joint(-1), parentBody(-1), childBody(-1), mgm(0) {}
342  LoopConstraint(const std::string& type, int jointNum,
343  int parentBodyNum, int childBodyNum,
344  MultibodyGraphMaker* graphMaker)
345  : type(type), joint(jointNum),
346  parentBody(parentBodyNum), childBody(childBodyNum),
347  mgm(graphMaker) {}
348 
351  void* getJointRef() const
352  { return mgm->getJoint(joint).userRef; }
355  const std::string& getJointTypeName() const
356  { return type; }
359  void* getParentBodyRef() const
360  { return mgm->getBody(parentBody).userRef; }
363  void* getChildBodyRef() const
364  { return mgm->getBody(childBody).userRef; }
365 
366  private:
367  friend class MultibodyGraphMaker;
368 
369  std::string type; // e.g., ball
370  int joint; // always one of the input joints
371  int parentBody; // parent from the joint
372  int childBody; // child from the joint
373 
374  MultibodyGraphMaker* mgm; // just a reference to container
375  };
376 
380 
381 
386  int addJointType(const std::string& name,
387  int numMobilities,
388  bool haveGoodLoopJointAvailable = false,
389  void* userRef = 0);
390 
391 
413  void addBody(const std::string& name,
414  double mass,
415  bool mustBeBaseBody,
416  void* userRef = 0);
417 
425  bool deleteBody(const std::string& name);
426 
459  void addJoint(const std::string& name,
460  const std::string& type,
461  const std::string& parentBodyName,
462  const std::string& childBodyName,
463  bool mustBeLoopJoint,
464  void* userRef = 0);
465 
474  bool deleteJoint(const std::string& name);
475 
480  void clearGraph();
481 
483  void dumpGraph(std::ostream& out) const;
484 
491  int getNumMobilizers() const {return (int)mobilizers.size();}
494  const Mobilizer& getMobilizer(int mobilizerNum) const
495  { return mobilizers[mobilizerNum]; }
496 
504  int getNumLoopConstraints() const {return (int)constraints.size();}
507  const LoopConstraint& getLoopConstraint(int loopConstraintNum) const
508  { return constraints[loopConstraintNum]; }
509 
512  int getNumBodies() const {return (int)bodies.size();}
516  const Body& getBody(int bodyNum) const {return bodies[bodyNum];}
520  int getBodyNum(const std::string& bodyName) const {
521  std::map<std::string,int>::const_iterator p =
522  bodyName2Num.find(bodyName);
523  return p==bodyName2Num.end() ? -1 : p->second;
524  }
525 
530  int getNumJoints() const {return (int)joints.size();}
533  const Joint& getJoint(int jointNum) const {return joints[jointNum];}
537  int getJointNum(const std::string& jointName) const {
538  std::map<std::string,int>::const_iterator p =
539  jointName2Num.find(jointName);
540  return p==jointName2Num.end() ? -1 : p->second;
541  }
542 
544  int getNumJointTypes() const {return (int)jointTypes.size();}
546  const JointType& getJointType(int jointTypeNum) const
547  { return jointTypes[jointTypeNum]; }
549  int getJointTypeNum(const std::string& jointTypeName) const {
550  std::map<std::string,int>::const_iterator p =
551  jointTypeName2Num.find(jointTypeName);
552  return p==jointTypeName2Num.end() ? -1 : p->second;
553  }
554 
558  void setWeldJointTypeName(const std::string& name)
559  { weldTypeName=name; initialize(); }
562  const std::string& getWeldJointTypeName() const {return weldTypeName;}
563 
567  void setFreeJointTypeName(const std::string& name)
568  { freeTypeName=name; initialize(); }
571  const std::string& getFreeJointTypeName() const {return freeTypeName;}
572 
575  const std::string& getGroundBodyName() const;
576 private:
577  // Get writable access to bodies and joints.
578  Body& updBody(int bodyNum) {return bodies[bodyNum];}
579  Joint& updJoint(int jointNum) {return joints[jointNum];}
580  Joint& updJoint(const std::string& name) {return joints[jointName2Num[name]];}
581 
582  void initialize();
583  int splitBody(int bodyNum);
584  int chooseNewBaseBody() const;
585  void connectBodyToGround(int bodyNum);
586  int addMobilizerForJoint(int jointNum);
587  int findHeaviestUnassignedForwardJoint(int inboardBody) const;
588  int findHeaviestUnassignedReverseJoint(int inboardBody) const;
589  void growTree();
590  void breakLoops();
591  bool bodiesAreConnected(int b1, int b2) const;
592 
593  // Clear everything except for default names.
594  void clear() {
595  bodies.clear(); joints.clear(); jointTypes.clear();
596  bodyName2Num.clear(); jointName2Num.clear(); jointTypeName2Num.clear();
597  mobilizers.clear(); constraints.clear();
598  }
599 
600  std::string weldTypeName, freeTypeName;
601  std::vector<Body> bodies; // ground + input bodies + slaves
602  std::vector<Joint> joints; // input joints + added joints
603  std::vector<JointType> jointTypes;
604  std::map<std::string,int> bodyName2Num;
605  std::map<std::string,int> jointName2Num;
606  std::map<std::string,int> jointTypeName2Num;
607 
608  // Calculated by generateGraph()
609  std::vector<Mobilizer> mobilizers; // mobilized bodies
610  std::vector<LoopConstraint> constraints;
611 };
612 
613 } // namespace SimTK
614 
615 #endif // SimTK_SIMMATH_MULTIBODY_GRAPH_MAKER_H_
616 
Includes internal headers providing declarations for the basic SimTK Core classes,...
This is the header file that every Simmath compilation unit should include first.
#define SimTK_SIMMATH_EXPORT
Definition: SimTKmath/include/simmath/internal/common.h:64
Local class that collects information about bodies.
Definition: MultibodyGraphMaker.h:157
Body(const std::string &name, double mass, bool mustBeBaseBody, void *userRef)
Definition: MultibodyGraphMaker.h:159
int master
Definition: MultibodyGraphMaker.h:190
void forgetGraph(MultibodyGraphMaker &graph)
int level
Definition: MultibodyGraphMaker.h:187
std::vector< int > jointsAsChild
Definition: MultibodyGraphMaker.h:182
bool isMaster() const
Definition: MultibodyGraphMaker.h:172
int getNumJoints() const
Definition: MultibodyGraphMaker.h:169
int getNumFragments() const
Definition: MultibodyGraphMaker.h:167
int mobilizer
Definition: MultibodyGraphMaker.h:188
std::vector< int > jointsAsParent
Definition: MultibodyGraphMaker.h:183
double mass
Definition: MultibodyGraphMaker.h:177
int getNumSlaves() const
Definition: MultibodyGraphMaker.h:168
std::string name
Definition: MultibodyGraphMaker.h:176
std::vector< int > slaves
Definition: MultibodyGraphMaker.h:191
void * userRef
Definition: MultibodyGraphMaker.h:179
bool isInTree() const
Definition: MultibodyGraphMaker.h:173
bool mustBeBaseBody
Definition: MultibodyGraphMaker.h:178
bool isSlave() const
Definition: MultibodyGraphMaker.h:171
Local class that defines the properties of a known joint type.
Definition: MultibodyGraphMaker.h:236
JointType(const std::string &name, int numMobilities, bool haveGoodLoopJointAvailable, void *userRef)
Definition: MultibodyGraphMaker.h:238
bool haveGoodLoopJointAvailable
Definition: MultibodyGraphMaker.h:245
std::string name
Definition: MultibodyGraphMaker.h:243
int numMobilities
Definition: MultibodyGraphMaker.h:244
void * userRef
Definition: MultibodyGraphMaker.h:246
Local class that collects information about joints.
Definition: MultibodyGraphMaker.h:195
std::string name
Definition: MultibodyGraphMaker.h:220
bool isAddedBaseJoint
Definition: MultibodyGraphMaker.h:228
int mobilizer
Definition: MultibodyGraphMaker.h:231
bool hasMobilizer() const
Definition: MultibodyGraphMaker.h:216
Joint(const std::string &name, int jointTypeNum, int parentBodyNum, int childBodyNum, bool mustBeLoopJoint, void *userRef)
Definition: MultibodyGraphMaker.h:197
bool mustBeLoopJoint
Definition: MultibodyGraphMaker.h:221
void * userRef
Definition: MultibodyGraphMaker.h:222
int jointTypeNum
Definition: MultibodyGraphMaker.h:226
bool hasLoopConstraint() const
Definition: MultibodyGraphMaker.h:217
bool forgetGraph(MultibodyGraphMaker &graph)
Return true if the joint is deleted as a result of restoring it to the state prior to generateGraph()...
int childBodyNum
Definition: MultibodyGraphMaker.h:225
int loopConstraint
Definition: MultibodyGraphMaker.h:232
Local class that represents one of the constraints that were added to close topological loops that we...
Definition: MultibodyGraphMaker.h:339
LoopConstraint(const std::string &type, int jointNum, int parentBodyNum, int childBodyNum, MultibodyGraphMaker *graphMaker)
Definition: MultibodyGraphMaker.h:342
const std::string & getJointTypeName() const
Get the loop constraint type name of the constraint that should be used here.
Definition: MultibodyGraphMaker.h:355
void * getJointRef() const
Get the user reference pointer for the joint associated with this loop constraint.
Definition: MultibodyGraphMaker.h:351
void * getChildBodyRef() const
Get the user reference pointer for the child body defined by the joint associated with this loop cons...
Definition: MultibodyGraphMaker.h:363
void * getParentBodyRef() const
Get the user reference pointer for the parent body defined by the joint associated with this loop con...
Definition: MultibodyGraphMaker.h:359
LoopConstraint()
Definition: MultibodyGraphMaker.h:341
Local class that represents one of the mobilizers (tree joints) in the generated spanning tree.
Definition: MultibodyGraphMaker.h:252
bool isAddedBaseMobilizer() const
Return true if this mobilizer does not represent one of the input joints, but is instead a joint we a...
Definition: MultibodyGraphMaker.h:269
bool isReversedFromJoint() const
Return true if this mobilizer represents one of the input joints but the sense of inboard->outboard i...
Definition: MultibodyGraphMaker.h:317
void * getJointRef() const
Get the user reference pointer for the joint associated with this mobilizer, if there is such a joint...
Definition: MultibodyGraphMaker.h:274
int getNumFragments() const
Return the number of fragments into which we chopped the outboard body of this mobilizer.
Definition: MultibodyGraphMaker.h:311
bool isSlaveMobilizer() const
Return true if the outboard body of this mobilizer is a slave we created in order to cut a loop,...
Definition: MultibodyGraphMaker.h:304
void * getInboardBodyRef() const
Get the user reference pointer for the inboard body of this mobilizer.
Definition: MultibodyGraphMaker.h:280
void * getOutboardMasterBodyRef() const
Get the user reference pointer for the outboard body of this mobilizer, if it is one of the input bod...
Definition: MultibodyGraphMaker.h:293
Mobilizer(int jointNum, int level, int inboardBodyNum, int outboardBodyNum, bool isReversed, MultibodyGraphMaker *graphMaker)
Definition: MultibodyGraphMaker.h:257
Mobilizer()
Definition: MultibodyGraphMaker.h:254
int getLevel() const
Return the level of the outboard body (Ground is level 0)
Definition: MultibodyGraphMaker.h:319
void * getJointTypeRef() const
Get the reference pointer (if any) that was provided when this mobilizer's joint type was defined in ...
Definition: MultibodyGraphMaker.h:300
const std::string & getJointTypeName() const
Get the joint type name of the joint that this mobilizer represents.
Definition: MultibodyGraphMaker.h:296
void * getOutboardBodyRef() const
Get the user reference pointer for the outboard body of this mobilizer.
Definition: MultibodyGraphMaker.h:287
Construct a reasonably good spanning-tree-plus-constraints structure for modeling a given set of bodi...
Definition: MultibodyGraphMaker.h:152
const JointType & getJointType(int jointTypeNum) const
Get a JointType object by its assigned number.
Definition: MultibodyGraphMaker.h:546
int getNumLoopConstraints() const
Return the number of loop joint constraints that were used to close loops in the graph topology.
Definition: MultibodyGraphMaker.h:504
int addJointType(const std::string &name, int numMobilities, bool haveGoodLoopJointAvailable=false, void *userRef=0)
Specify relevant properties of a joint type.
void dumpGraph(std::ostream &out) const
Output a text representation of the multibody graph for debugging.
void setWeldJointTypeName(const std::string &name)
Change the name to be used to identify the weld joint type (0 dof) and weld loop constraint type (6 c...
Definition: MultibodyGraphMaker.h:558
const std::string & getGroundBodyName() const
Return the name we recognize as the Ground (or World) body.
const std::string & getWeldJointTypeName() const
Return the name currently being used to identify the weld joint type and weld loop constraint type.
Definition: MultibodyGraphMaker.h:562
void setFreeJointTypeName(const std::string &name)
Change the name to be used to identify the free (6 dof) joint type and free (0 constraints) loop cons...
Definition: MultibodyGraphMaker.h:567
int getNumJoints() const
Return the number of joints, including all input joints, and all joints added to connect otherwise di...
Definition: MultibodyGraphMaker.h:530
void clearGraph()
Throw away the multibody graph produced by generateGraph().
int getJointNum(const std::string &jointName) const
Return the joint number assigned to the input joint with the given name.
Definition: MultibodyGraphMaker.h:537
int getNumBodies() const
Return the number of bodies, including all input bodies, a ground body, and any slave bodies.
Definition: MultibodyGraphMaker.h:512
const Mobilizer & getMobilizer(int mobilizerNum) const
Get a Mobilizer object by its mobilizer number, ordered outwards by topological distance from Ground.
Definition: MultibodyGraphMaker.h:494
const Body & getBody(int bodyNum) const
Get a Body object by its assigned number.
Definition: MultibodyGraphMaker.h:516
const LoopConstraint & getLoopConstraint(int loopConstraintNum) const
Get a loop constraint by its assigned number.
Definition: MultibodyGraphMaker.h:507
int getBodyNum(const std::string &bodyName) const
Return the body number assigned to the input body with the given name.
Definition: MultibodyGraphMaker.h:520
int getJointTypeNum(const std::string &jointTypeName) const
Get the assigned number for a joint type from the type name.
Definition: MultibodyGraphMaker.h:549
MultibodyGraphMaker()
Construct an empty MultibodyGraphMaker object and set the default names for weld and free joints to "...
bool deleteBody(const std::string &name)
Delete a body (link) from the set of input bodies.
void addBody(const std::string &name, double mass, bool mustBeBaseBody, void *userRef=0)
Add a new body (link) to the set of input bodies.
int getNumJointTypes() const
Return the number of registered joint types.
Definition: MultibodyGraphMaker.h:544
void addJoint(const std::string &name, const std::string &type, const std::string &parentBodyName, const std::string &childBodyName, bool mustBeLoopJoint, void *userRef=0)
Add a new joint to the set of input joints.
const Joint & getJoint(int jointNum) const
Get a Joint object by its assigned number.
Definition: MultibodyGraphMaker.h:533
bool deleteJoint(const std::string &name)
Delete an existing joint from the set of input joints.
void generateGraph()
Generate a new multibody graph from the input data.
const std::string & getFreeJointTypeName() const
Return the name currently being used to identify the free joint type and free loop constraint type.
Definition: MultibodyGraphMaker.h:571
int getNumMobilizers() const
Returns the number of mobilizers (tree joints) in the spanning tree.
Definition: MultibodyGraphMaker.h:491
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition: Assembler.h:37