How to create a new IPSA joint

How to create a new SoJoint subclass named SoJointExample:

SoJointExample.h
 #include "SoJoint.h"
 #include <Inventor/fields/SoSFVec3f.h>
 #include <Inventor/SbString.h>

 class SoJointExample : public SoJoint
 {
 SO_KIT_HEADER(SoJointExample);  // set up the necessary information for the headerfile

 public:
   SoJointExample(const SbString& BodyOne = "", const SbString& BodyTwo = "", const SbString& nodeName = "");
   virtual ~SoJointExample();

   static void initClass();
   virtual void setParams();

   SoSFVec3f jointAnchor;

   SoSFFloat odeParameter1;
   SoSFFloat odeParameter2;
 protected:
   virtual void createOdeJoint(const dWorldID soWorldId);
   virtual void updateOdeJointProperties(const SbMatrix& modelMatrix);
   virtual SoNode* createVisualisation();
 };

SoJointExample.cpp

 #include "../include/SoJointExample.h"

 #include <Inventor/SbLinear.h>
 #include <Inventor/nodes/SoCone.h>
 #include <Inventor/nodes/SoTranslation.h>
 #include <Inventor/nodekits/SoShapeKit.h>

 #include <iostream>

 SO_KIT_SOURCE(SoJointExample);  // set up the necessary information for the implementation file

 // Initialises the class and it's type id variables.
 void SoJointExample::initClass()
 {
   SO_KIT_INIT_CLASS(SoJointExample, SoJoint, "Joint");
 }

 // set up the class structure
 SoJointExample::SoJointExample(const SbString& BodyOne, const SbString& BodyTwo, const SbString& nodeName)
 : SoJoint(BodyOne,BodyTwo,nodeName)
 {
   // define the Coin constructor
   SO_KIT_CONSTRUCTOR(SoJointExample);
   // only write necessary member fields to files and not more
   isBuiltIn = TRUE;

   // define the field variables
   SO_KIT_ADD_FIELD(jointAnchor, (0.0, 0.0, 0.0));
   SO_KIT_ADD_FIELD(odeParameter1,(0.5));
   SO_KIT_ADD_FIELD(odeParameter2,(1.6));

   // set up the instance
   SO_KIT_INIT_INSTANCE();

   // monitor the parameter fields for changes to automatically update them in the ODE enginge
   updateOdeParametersTrigger.appendConnection(&odeParameter1);
   updateOdeParametersTrigger.appendConnection(&odeParameter2);
 }

 SoJointExample::~SoJointExample()
 {
   // release objects created with new
 }

 // method which sets the ODE parameters on the internal ODE object
 void SoJointExample::setParams()
 {
   dJointSetExampleParam(soJointId, dParamParameter1, odeParameter1.getValue());
   dJointSetExampleParam(soJointId, dParamParameter2, odeParameter2.getValue());
 }

 // method which creates the ODE internal joint object
 void SoJointExample::createOdeJoint(const dWorldID soWorldId)
 {
   // create the joint (dJointCreateExample is an invented function)
   this->soJointId = dJointCreateExample(soWorldId, soJointGroupId);
   // maybe save some initial values in member variables afterwards
 }

 // this method sets for example the anchor on the ODE joint
 void SoJointExample::updateOdeJointProperties(const SbMatrix& modelMatrix)
 {
   // get translation and rotation from coin
   // to translate and rotate anchor
   SbVec3f anchorbase = jointAnchor.getValue();
   SbVec3f rotatedAnchorbase;

   // Transformation: rotate first and translate the anchor
   SbMatrix mm = modelMatrix;
   mm.multVecMatrix(anchorbase, rotatedAnchorbase);

   // NOTE: this is an invented function
   dJointSetSampleAnchor(soJointId, rotatedAnchorbase[0], rotatedAnchorbase[1], rotatedAnchorbase[2]);
 }

 // method which creates a Coin visualisation for the joint
 SoNode* SoJointExample::createVisualisation()
 {
   // create a shapekit which holds the visualisatin and additional transformation or material properties
   SoShapeKit* result = new SoShapeKit;

   // create the visualisation object and use examplePoperty1 to specify the appearance
   SoCone* cone = new SoCone;
   cone->height.setValue(exampleProperty1 * VisualisationScale.getValue());
   result->setPart("shape", cone);

   // translate the visualisation from its origin
   SoTranslation* translation = new SoTranslation;
   translation->translation.setValue(SbVec3d(1.0, 2.0, 0.0));
   result->setPart("transform", translation);

   return result;
 }

Steps to take:

  1. Create a subclass of SoJoint.
  2. Add additional members if necessary (like exampleProperty1, odeParameter1 and odeParameter2).
  3. In the cpp file call
     SO_KIT_SOURCE(SoJointExample); 
    
  4. Implement the method
     SoJointExample::initClass() { SO_KIT_INIT_CLASS(SoJointExample, SoJoint, "Joint"); } 
    
  5. Implement the Constructor:
    1. Call
       SO_KIT_CONSTRUCTOR(SoJointExample);
      
    2. Set
       isBuiltin = TRUE; 
      
    3. Add any field with:
       SO_KIT_ADD_FIELD(fieldname,(defaultvalue)); 
      
    4. Call
       SO_KIT_INIT_INSTANCE(); 
      
    5. For each ODE parameter call
       updateOdeParametersTrigger.appendConnection(&odeParameterName); 
      
      This enables the SoJoint class to automatically update the ODE parameters in the engine if they change in the class.
  6. Override the destructor if objects where allocated in the constructor and need to be destroyed. Otherwise leave it out of the header file and don't implement it.
  7. Implement the method setParams() which sets the parameters on the internal ODE object.
  8. Implement the method createOdeJoint() which creates the ODE joint.
  9. Implement the method updateOdeJointProperties() which sets the properties and parameters of the ODE joint.
  10. Implement the method createVisualisation() which returns an OpenInventor visualisation of the joint.
  11. Add the line
     #include "SoJointExample.h" 
    
    into the file
    $(IPSA_HOME)/include/ipsaclasses.h 
    .
  12. The last thing to do is to register the initialisation method in the global initialisation routine. This is done by adding one line to SoWorldPhysics::initClasses(). In the example the line would looke like this:
     SoJointExample::initClass(); 
    

See the Joint Classes page for all joint classes existing in IPSA. Details on how to implement the different methods can be taken from the individual joint classes.


Get IPSA - Inventor Physics Simulation API at SourceForge.net. Fast, secure and Free Open Source software downloads
Generated on Sat Mar 10 20:00:17 2012 for IPSA by  doxygen 1.5.8