Simbody  3.7
SimTK::MultibodyGraphMaker Class Reference

Construct a reasonably good spanning-tree-plus-constraints structure for modeling a given set of bodies and joints with a generalized coordinate multibody system like Simbody. More...

Classes

class  Body
 Local class that collects information about bodies. More...
 
class  Joint
 Local class that collects information about joints. More...
 
class  JointType
 Local class that defines the properties of a known joint type. More...
 
class  LoopConstraint
 Local class that represents one of the constraints that were added to close topological loops that were cut to form the spanning tree. More...
 
class  Mobilizer
 Local class that represents one of the mobilizers (tree joints) in the generated spanning tree. More...
 

Public Member Functions

 MultibodyGraphMaker ()
 Construct an empty MultibodyGraphMaker object and set the default names for weld and free joints to "weld" and "free". More...
 
int addJointType (const std::string &name, int numMobilities, bool haveGoodLoopJointAvailable=false, void *userRef=0)
 Specify relevant properties of a joint type. More...
 
void addBody (const std::string &name, double mass, bool mustBeBaseBody, void *userRef=0)
 Add a new body (link) to the set of input bodies. More...
 
bool deleteBody (const std::string &name)
 Delete a body (link) from the set of input bodies. More...
 
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. More...
 
bool deleteJoint (const std::string &name)
 Delete an existing joint from the set of input joints. More...
 
void generateGraph ()
 Generate a new multibody graph from the input data. More...
 
void clearGraph ()
 Throw away the multibody graph produced by generateGraph(). More...
 
void dumpGraph (std::ostream &out) const
 Output a text representation of the multibody graph for debugging. More...
 
int getNumMobilizers () const
 Returns the number of mobilizers (tree joints) in the spanning tree. More...
 
const MobilizergetMobilizer (int mobilizerNum) const
 Get a Mobilizer object by its mobilizer number, ordered outwards by topological distance from Ground. More...
 
int getNumLoopConstraints () const
 Return the number of loop joint constraints that were used to close loops in the graph topology. More...
 
const LoopConstraintgetLoopConstraint (int loopConstraintNum) const
 Get a loop constraint by its assigned number. More...
 
int getNumBodies () const
 Return the number of bodies, including all input bodies, a ground body, and any slave bodies. More...
 
const BodygetBody (int bodyNum) const
 Get a Body object by its assigned number. More...
 
int getBodyNum (const std::string &bodyName) const
 Return the body number assigned to the input body with the given name. More...
 
int getNumJoints () const
 Return the number of joints, including all input joints, and all joints added to connect otherwise disconnected bodies to Ground. More...
 
const JointgetJoint (int jointNum) const
 Get a Joint object by its assigned number. More...
 
int getJointNum (const std::string &jointName) const
 Return the joint number assigned to the input joint with the given name. More...
 
int getNumJointTypes () const
 Return the number of registered joint types. More...
 
const JointTypegetJointType (int jointTypeNum) const
 Get a JointType object by its assigned number. More...
 
int getJointTypeNum (const std::string &jointTypeName) const
 Get the assigned number for a joint type from the type name. More...
 
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 constraints). More...
 
const std::string & getWeldJointTypeName () const
 Return the name currently being used to identify the weld joint type and weld loop constraint type. More...
 
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 constraint type. More...
 
const std::string & getFreeJointTypeName () const
 Return the name currently being used to identify the free joint type and free loop constraint type. More...
 
const std::string & getGroundBodyName () const
 Return the name we recognize as the Ground (or World) body. More...
 

Detailed Description

Construct a reasonably good spanning-tree-plus-constraints structure for modeling a given set of bodies and joints with a generalized coordinate multibody system like Simbody.

Each body has a unique name; each joint connects two distinct bodies with one designated as the "parent" body and the other the "child". We will output a spanning tree with Ground as the root, containing a mobilizer for every body. Each mobilizer corresponds to one of the joints from the input and has an "inboard" (topologically closer to Ground) and "outboard" (further from Ground) body, chosen from the parent and child bodies of the joint but possibly reordered in which case the mobilizer is marked as "reversed". Additional "free" mobilizers are added as needed between bodies and Ground so that there is a path from every body in the inboard direction all the way to Ground.

Results

The output is

  1. A sequence of mobilizers (tree joints) in ascending order from Ground to a set of terminal bodies. Every input body will be mobilized by one of these, and there may also be some additional mobilized "slave" bodies.
  2. A set of constraints, representing either welds to attach slave bodies to their masters, or loop joint constraints that correspond to particular input joints.
  3. A correspondence between input bodies and mobilized bodies, with some mobilized bodies designated as slaves to particular master input bodies. That is, more than one mobilized body may correspond to the same input body.
  4. A correspondence between mobilizers and input joints, with some extra mobilizers having been added to connect base bodies to Ground.
  5. Statistics and diagnostics.

Then to build a multibody model

  1. Run through the mobilizers in order, adding one mobilized body to the tree each time, setting the "reversed" flag if appropriate (that just affects the interpretation of the generalized coordinates). Mass properties and joint information are obtained from the original bodies and joints; they are not stored here.
  2. Run through the list of constraints adding master-slave welds or loop joint constraints as indicated.

Inputs

  • bodies: name, mass, mustBeBaseBody flag
  • joints: name, type, parent body, child body, mustBeLoopJoint flag
  • joint type: name, # dofs, haveGoodLoopJoint flag
  • names for the Ground body and important joint types weld and free

The first body you add is assumed to be Ground and its name is used for recognizing Ground connections later in joints. The default names for weld and free joints are, not surprisingly, "weld" and "free" but you can change them.

Loop joints

Normally every joint produces a corresponding mobilizer. A joint that would form a loop is marked as such, and then its child body is split to form a new "slave" body that can be mobilized by the joint. We expect that in the constructed multibody model, a master body and its slaves will be reconnected via weld constraints. This provides for uniform treatment of all joints, such as providing pin joint coordinates that can wrap. However, for some joint types that doesn't matter because the multibody system has equally good "loop joint" constraints. For example, Simbody's Ball mobilizer uses quaternions for orientation and hence has no wrapping; it can be replaced with a Ball constraint which removes the 3-dof mobilizer and 6 weld constraint equations, leaving just 3 translational constraints and indistinguishable behavior. Similarly a loop- closing Weld joint can just be replaced by a Weld constraint, and a loop- closing Free joint can simply be ignored.

The algorithm normally decides which joints are the loop-breakers, however you can specify in the input that certain joints must be loop joints.

Massless bodies

Massless bodies can be very useful in defining compound joints, by composing pin and slider joints, for example. This is fine in an internal coordinate code as long as no massless (or inertialess) body is a terminal (most outboard) body in the spanning tree. (Terminal massless bodies are OK if their inboard joint has no dofs, i.e. is a weld mobilizer.) Bodies can have a mass provided; if a movable body has zero mass the algorithm will try to avoid ending any branch of the spanning tree there. If it fails, the resulting spanning tree is no good and an exception will be thrown. If no mass is provided we assume it is 1.

Base bodies

A body in the spanning tree that is directly connected to Ground is called a "base" body. If its mobilizer is a free joint then it can be given an arbitrary pose with respect to Ground and everything outboard of it moves together. This is a nice property and you can influence this choice by providing an explicit joint to Ground or designating some bodies as base bodies. Note that although you will then have a set of generalized coordinates permitting you to place these bodies arbitrarily, there is no guarantee that such placement will satisfy constraints. If you don't designate base bodies, the algorithm will pick them heuristically, which often leads to a good choice. The heuristic is to pick the body that has the most children but does not itself appear as a child. Failing that, pick the body that has the most children. In case of tie, pick the first body among the tied ones.

Ground body

The first body you supply in the input will be interpreted as the Ground body. Its name will be used to recognize joints that connect other bodies to Ground. Typical names are "ground" or "world".

Levels

Each body in the spanning tree will be assigned a level, an integer that measures how many edges must be traversed to get from the body to Ground. Ground is at level 0, bodies that have a direct connection to Ground (base bodies) are at level 1, bodies whose mobilizer connects them to base bodies are at level 2, and so on. Multibody models need to be constructed in order of increasing level, so that the inboard body is already in the tree when the outboard body is added. We consider the level of a mobilizer to be the same as the level of its outboard body. Loop joints are not mobilizers and do not have a level.

Constructor & Destructor Documentation

◆ MultibodyGraphMaker()

SimTK::MultibodyGraphMaker::MultibodyGraphMaker ( )

Construct an empty MultibodyGraphMaker object and set the default names for weld and free joints to "weld" and "free".

Member Function Documentation

◆ addJointType()

int SimTK::MultibodyGraphMaker::addJointType ( const std::string &  name,
int  numMobilities,
bool  haveGoodLoopJointAvailable = false,
void *  userRef = 0 
)

Specify relevant properties of a joint type.

Type name must be unique. Weld and free types are predefined and their names are reserved (though you can change the names to be used).

Returns
Small integer joint type number used for referencing.

◆ addBody()

void SimTK::MultibodyGraphMaker::addBody ( const std::string &  name,
double  mass,
bool  mustBeBaseBody,
void *  userRef = 0 
)

Add a new body (link) to the set of input bodies.

Parameters
[in]name
A unique string identifying this body. There are no other restrictions on the contents of name. The first body you add is considered to be Ground, and its name is remembered and recognized when used in joints.
[in]mass
The mass here is used as a graph-building hint. If the body is massless, be sure to set mass=0 so that the algorithm can avoid making this a terminal body. The algorithm might also use mass to preferentially choose heavier bodies as terminal to improve conditioning.
[in]mustBeBaseBodyIf you feel strongly that this body should be able to move freely with respect to Ground, set this flag so that the algorithm will connect it to Ground by a free joint before attempting to build the rest of the tree. Alternatively, provide a joint that connects this body directly to Ground, in which case you should not set this flag.
[in]userRefThis is a generic user reference pointer that is kept with the body and can be used by the caller to map back to his or her own data structure containing body information.
See also
deleteBody()

◆ deleteBody()

bool SimTK::MultibodyGraphMaker::deleteBody ( const std::string &  name)

Delete a body (link) from the set of input bodies.

All the joints that reference this body will be deleted too.

Parameters
[in]name
A unique string identifying this body. There are no other restrictions on the contents of name. Don't delete the Ground body.
Returns
true if the body is successfully deleted, false if it didn't exist.

◆ addJoint()

void SimTK::MultibodyGraphMaker::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.

Parameters
[in]nameA string uniquely identifying this joint. There are no other restrictions on the contents of name.
[in]typeA string designating the type of this joint, such as "revolute" or "ball". This must be chosen from the set of joint types previously specified.
[in]parentBodyNameThis must be the name of a body that was already specified in an earlier addBody() call, or it must be the designated name for the Ground body. If possible, this will be used as the inboard body for the corresponding mobilizer.
[in]childBodyNameThis must be the name of a body that was already specified in an earlier addBody() call, or it must be the designated name for the Ground body. It must be distinct from parentBodyName. If possible, this will be used as the outboard body for the corresponding mobilizer.
[in]mustBeLoopJointIf you feel strongly that this joint should be chosen as a loop joint, set this flag. In that case the joint will not appear in the list of joints that are candidates for mobilizers (tree joints). Only after the tree has been successfully built will this joint be added, either using a loop joint equivalent if one is available, or by splitting the child body into master and slave otherwise. In the latter case this joint will be made into a mobilizer but a loop weld joint will be added to attach the child slave body to its master.
[in]userRefThis is a generic user reference pointer that is kept with the joint and can be used by the caller to map back to his or her own data structure containing joint information.
See also
deleteJoint()

◆ deleteJoint()

bool SimTK::MultibodyGraphMaker::deleteJoint ( const std::string &  name)

Delete an existing joint from the set of input joints.

The bodies(links) referenced by the joint are expected to exist and their references to this joint will be removed as well.

Parameters
[in]nameA string uniquely identifying this joint. There are no other restrictions on the contents of name.
Returns
true if the joint is successfully deleted, false if it didn't exist.

◆ generateGraph()

void SimTK::MultibodyGraphMaker::generateGraph ( )

Generate a new multibody graph from the input data.

Throws an std::exception if it fails, with a message in the what() string.

◆ clearGraph()

void SimTK::MultibodyGraphMaker::clearGraph ( )

Throw away the multibody graph produced by generateGraph().

◆ dumpGraph()

void SimTK::MultibodyGraphMaker::dumpGraph ( std::ostream &  out) const

Output a text representation of the multibody graph for debugging.

◆ getNumMobilizers()

int SimTK::MultibodyGraphMaker::getNumMobilizers ( ) const
inline

Returns the number of mobilizers (tree joints) in the spanning tree.

These are numbered in order of level. The 0th mobilizer has level 0 and is just a placeholder for Ground's immobile connection to the universe. After that come the base mobilizers at level 1, then mobilizers that connect children to base bodies at level 2, and so on. This is also the number of mobilized bodies, including Ground and slave bodies.

◆ getMobilizer()

const Mobilizer& SimTK::MultibodyGraphMaker::getMobilizer ( int  mobilizerNum) const
inline

Get a Mobilizer object by its mobilizer number, ordered outwards by topological distance from Ground.

◆ getNumLoopConstraints()

int SimTK::MultibodyGraphMaker::getNumLoopConstraints ( ) const
inline

Return the number of loop joint constraints that were used to close loops in the graph topology.

These do not include loops that were broken by cutting a body to make a slave body, just those where the joint itself was implemented using a constraint rather than a mobilizer plus a slave. The latter occurs only if were told there is a perfectly good loop joint constraint available; typically that applies for ball joints and not much else.

◆ getLoopConstraint()

const LoopConstraint& SimTK::MultibodyGraphMaker::getLoopConstraint ( int  loopConstraintNum) const
inline

Get a loop constraint by its assigned number.

These are assigned in an arbitrary order.

◆ getNumBodies()

int SimTK::MultibodyGraphMaker::getNumBodies ( ) const
inline

Return the number of bodies, including all input bodies, a ground body, and any slave bodies.

◆ getBody()

const Body& SimTK::MultibodyGraphMaker::getBody ( int  bodyNum) const
inline

Get a Body object by its assigned number.

These are assigned first to input bodies, then we add one for Ground, then we add slave bodies created by body splitting after that.

◆ getBodyNum()

int SimTK::MultibodyGraphMaker::getBodyNum ( const std::string &  bodyName) const
inline

Return the body number assigned to the input body with the given name.

Returns -1 if the body name is not recognized. You can't look up by name slave bodies that were added by the graph-making algorithm.

◆ getNumJoints()

int SimTK::MultibodyGraphMaker::getNumJoints ( ) const
inline

Return the number of joints, including all input joints, and all joints added to connect otherwise disconnected bodies to Ground.

Don't confuse these with mobilizers, which are an ordered subset of the joints that are chosen to form a spanning tree connecting all the bodies.

◆ getJoint()

const Joint& SimTK::MultibodyGraphMaker::getJoint ( int  jointNum) const
inline

Get a Joint object by its assigned number.

These are assigned first to input joints, then we add additional joints to Ground as needed.

◆ getJointNum()

int SimTK::MultibodyGraphMaker::getJointNum ( const std::string &  jointName) const
inline

Return the joint number assigned to the input joint with the given name.

Returns -1 if the joint name is not recognized. You can't look up by name extra joints that were added by the graph-making algorithm.

◆ getNumJointTypes()

int SimTK::MultibodyGraphMaker::getNumJointTypes ( ) const
inline

Return the number of registered joint types.

◆ getJointType()

const JointType& SimTK::MultibodyGraphMaker::getJointType ( int  jointTypeNum) const
inline

Get a JointType object by its assigned number.

◆ getJointTypeNum()

int SimTK::MultibodyGraphMaker::getJointTypeNum ( const std::string &  jointTypeName) const
inline

Get the assigned number for a joint type from the type name.

◆ setWeldJointTypeName()

void SimTK::MultibodyGraphMaker::setWeldJointTypeName ( const std::string &  name)
inline

Change the name to be used to identify the weld joint type (0 dof) and weld loop constraint type (6 constraints).

The default is "weld". Changing this name clears and reinitializes this MultibodyGraphMaker object.

◆ getWeldJointTypeName()

const std::string& SimTK::MultibodyGraphMaker::getWeldJointTypeName ( ) const
inline

Return the name currently being used to identify the weld joint type and weld loop constraint type.

◆ setFreeJointTypeName()

void SimTK::MultibodyGraphMaker::setFreeJointTypeName ( const std::string &  name)
inline

Change the name to be used to identify the free (6 dof) joint type and free (0 constraints) loop constraint type.

The default is "free". Changing this name clears and reinitializes this MultibodyGraphMaker object.

◆ getFreeJointTypeName()

const std::string& SimTK::MultibodyGraphMaker::getFreeJointTypeName ( ) const
inline

Return the name currently being used to identify the free joint type and free loop constraint type.

◆ getGroundBodyName()

const std::string& SimTK::MultibodyGraphMaker::getGroundBodyName ( ) const

Return the name we recognize as the Ground (or World) body.

This is the name that was provided in the first addBody() call.


The documentation for this class was generated from the following file: