Rigid joint question

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

Rigid joint question

Postby xavram » Wed Mar 17, 2010 3:41 pm

I'm trying to create a simple tank, where the body of the tank is one object and the treads are another. I want the treads and the body to always stay together; the treads orientation should always be the same as the body.

So I thought, I'll create a Hinge Joint to connect the two and then limit the hinge joint as much as possible. I did so, limiting the joint to the Y axis and setting its min/max limits to 0.

This "seems" to work fine for the most part but as I drive the tank around (using SetVelocity and SetRotation of the tread object), every now and then the back end of the tank lifts up, kind of like a car with rear hydraulics...definately not what I want!!!

how can I prevent this? Have I set up the hinge wrong? the body and treads appear to be properly placed relative to each other, I used the position of the treads as the position of the joint, and a vector of (0,1,0) as the hinge axis.

Mind you, I'm using Newton through the 3d engine, Truevision, so my nomenclature might be a bit off. But I'm still hoping someone may have some insights.
xavram
 
Posts: 10
Joined: Wed Mar 17, 2010 2:04 pm

Re: Rigid joint question

Postby xavram » Thu Mar 18, 2010 12:45 am

Not sure if this will help, but a screenshot of the issue, showing the body rising up from the treads, when the hinge shouldn't allow any movement.

Image
xavram
 
Posts: 10
Joined: Wed Mar 17, 2010 2:04 pm

Re: Rigid joint question

Postby JernejL » Thu Mar 18, 2010 4:51 am

Post a picture of debug render of that scene, but it looks as if your hinge joint is setup wrong..
Help improving the Newton Game Dynamics WIKI
User avatar
JernejL
 
Posts: 1587
Joined: Mon Dec 06, 2004 2:00 pm
Location: Slovenia

Re: Rigid joint question

Postby xavram » Thu Mar 18, 2010 12:05 pm

Right, that's what I assumed...but like I had said, I'm restricting it to the Y axis, with a min/max limit of 0.

Would that not be correct?

And when you say the "debug render", are you talking about where you can see the wire frames of the physics objects? Just want to make sure I'm on the same page...
xavram
 
Posts: 10
Joined: Wed Mar 17, 2010 2:04 pm

Re: Rigid joint question

Postby JernejL » Thu Mar 18, 2010 1:55 pm

It depends on what the Y axis is for your game and what it is for the joint!

and yes, that's what i mean by a debug renderer.
Help improving the Newton Game Dynamics WIKI
User avatar
JernejL
 
Posts: 1587
Joined: Mon Dec 06, 2004 2:00 pm
Location: Slovenia

Re: Rigid joint question

Postby xavram » Thu Mar 18, 2010 2:50 pm

Okay, here's the code I'm using to set up the hinge (again, mind you, this is TrueVision)

Dim temp As Integer = Physics.CreateHingeJoint(pPropulsionId, pBodyId, mPropulsion.GetPosition, New TV_3DVECTOR(0, 1, 0))
Physics.SetHingeJointLimits(temp, True, 0, 0)

And here's the picutre with the debugger renderer on. There is a weird thing going on in the TV side of things that is causing the treads mesh to render off and on, so the mesh is there, it just didnt' render...but that's not a physics issue.

Image
xavram
 
Posts: 10
Joined: Wed Mar 17, 2010 2:04 pm

Re: Rigid joint question

Postby Julio Jerez » Thu Mar 18, 2010 3:01 pm

Had you look at the code that implement similar tank in the SDk?

Is the demo that put few tanks in the scene, Maybe you can check tha out
this is the code for teh joint.

Code: Select all
class FrictionTrank: public RenderPrimitive
{
   class FrictionTractionControl: public NewtonCustomJoint 
   {
      public:
      FrictionTractionControl (const NewtonBody* tankBody, const NewtonBody* leftTrack, const NewtonBody* rightTrack)
         :NewtonCustomJoint(1, tankBody, NULL)
      {
         m_veloc = 0.0f;
         m_turnVeloc = 0.0f;

         // hack the tank to move in circles
         m_veloc = 5.0f;
         m_turnVeloc = 1.0f;

         m_leftTrack = leftTrack;
         m_rightTrack = rightTrack;
      }

      void ApplyTracktionForce (dFloat timestep, const NewtonBody* track)
      {
         dVector veloc;
         dVector omega;
         dMatrix matrix;

         NewtonBodyGetOmega(m_body0, &omega[0]);
         NewtonBodyGetVelocity(m_body0, &veloc[0]);
         NewtonBodyGetMatrix (m_body0, &matrix[0][0]);
         

         // itetate over the contact list and condition each contact direction anc contact acclerations
         for (NewtonJoint* contactJoint = NewtonBodyGetFirstContactJoint (track); contactJoint; contactJoint = NewtonBodyGetNextContactJoint (track, contactJoint)) {
            _ASSERTE ((NewtonJointGetBody0 (contactJoint) == track) || (NewtonJointGetBody1 (contactJoint) == track));

            #ifdef REMOVE_REDUNDAT_CONTACT   
            int contactCount;
            contactCount = NewtonContactJointGetContactCount(contactJoint);
            if (contactCount > 2) {
               // project the contact to the bounday of the conve hull o fteh trhread foot ptint
               dFloat maxDist;
               dFloat minDist;
               void* minContact;
               void* maxContact;
               
               dMatrix matrix;
         
               minContact = NULL;
                maxContact = NULL;
               NewtonBodyGetMatrix (track, &matrix[0][0]);

               maxDist = -1.0e10f;
               minDist = -1.0e10f;
               //find the best two contacts and remove all others
               for (void* contact = NewtonContactJointGetFirstContact (contactJoint); contact; contact = NewtonContactJointGetNextContact (contactJoint, contact)) {
                  dFloat dist;
                  dVector point;
                  dVector normal;
                  NewtonMaterial* material;

                   material = NewtonContactGetMaterial (contact);
                  NewtonMaterialGetContactPositionAndNormal(material, &point[0], &normal[0]);
                  
                  dist = matrix.m_front % point;
                  if (dist > maxDist) {
                     maxDist = dist;
                     maxContact = contact;
                  }
                  if (-dist > minDist) {
                     minDist = -dist;
                     minContact = contact;
                  }
                  
               }

               // now delete all reduntact contacts
               void* nextContact;
               NewtonWorld* world;

               world = NewtonBodyGetWorld (track);
               NewtonWorldCriticalSectionLock(world);
               for (void* contact = NewtonContactJointGetFirstContact (contactJoint); contact; contact = nextContact) {
                  nextContact = NewtonContactJointGetNextContact (contactJoint, contact);
                  if (!((contact == minContact) || (contact == maxContact))) {
                     NewtonContactJointRemoveContact (contactJoint, contact);
                  }
               }
               NewtonWorldCriticalSectionUnlock(world);
            }

            #endif

         
            for (void* contact = NewtonContactJointGetFirstContact (contactJoint); contact; contact = NewtonContactJointGetNextContact (contactJoint, contact)) {
               dFloat speed;
               dFloat accel;
               dVector point;
               dVector normal;
               dVector dir0;
               dVector dir1;
               NewtonMaterial* material;

                material = NewtonContactGetMaterial (contact);
               NewtonMaterialContactRotateTangentDirections (material, &matrix.m_front[0]);
               NewtonMaterialGetContactPositionAndNormal(material, &point[0], &normal[0]);
               NewtonMaterialGetContactTangentDirections (material, &dir0[0], &dir1[0]);


               dVector posit (point - matrix.m_posit);
               veloc += omega * posit;
               speed = veloc % dir0;
            //   accel = m_accel - 0.1f * speed + (((posit % m_matrix.m_right) > 0.0f) ? m_turnAccel : - m_turnAccel);
               accel = m_veloc + (((posit % matrix.m_right) > 0.0f) ? m_turnVeloc : - m_turnVeloc);

               accel = (accel - speed) * 0.5f / timestep;

         //      NewtonMaterialSetContactStaticFrictionCoef (material, 1.0f, 0);
         //      NewtonMaterialSetContactKineticFrictionCoef (material, 1.0f, 0);
               NewtonMaterialSetContactFrictionCoef (material, 1.0f, 1.0f, 0);

         //      NewtonMaterialSetContactStaticFrictionCoef (material, 0.5f, 1);
         //      NewtonMaterialSetContactKineticFrictionCoef (material, 0.5f, 1);
               NewtonMaterialSetContactFrictionCoef (material, 0.5f, 0.5f, 1);
               
               NewtonMaterialSetContactTangentAcceleration (material, accel, 0);
            }

            // for debug purpose show the contact
            ShowJointContacts (contactJoint);
         }
      }

      void SubmitConstraints (dFloat timestep, int threadIndex)
      {
         // apply the friction due to contact
         ApplyTracktionForce (timestep, m_leftTrack);
         ApplyTracktionForce (timestep, m_rightTrack);
      }

      dFloat m_veloc;
      dFloat m_turnVeloc;
      const NewtonBody* m_leftTrack;
      const NewtonBody* m_rightTrack;
   };

   class FrictionTrankThreaSuspention: public CustomSlidingContact
   {
      public:
      FrictionTrankThreaSuspention(const dMatrix& pinsAndPivoFrame, const NewtonBody* child, const NewtonBody* parent)
         : CustomSlidingContact (pinsAndPivoFrame, child, parent)
      {
         dMatrix childMatrix;
         dMatrix parentMatrix;
         dVector maxPointFront;
         dVector minPointFront;

         NewtonCollision* collision;
         collision = NewtonBodyGetCollision(child);

         NewtonBodyGetMatrix(child, &childMatrix[0][0]);
         NewtonBodyGetMatrix(parent, &parentMatrix[0][0]);

         // find the the extreme front and rear point, this is used to calculate the position of the suspension points
         dVector frontDir (childMatrix.UnrotateVector(parentMatrix.m_front));
         NewtonCollisionSupportVertex(collision, &frontDir[0], &maxPointFront[0]);

         dVector rearDir (frontDir.Scale (-1.0f));
         NewtonCollisionSupportVertex(collision, &rearDir[0], &minPointFront[0]);


         // calculate the front suspension points
         dVector frontHardPoint (childMatrix.m_posit + childMatrix.RotateVector(frontDir.Scale (maxPointFront % frontDir)));
         m_frontHarpointOnParent = parentMatrix.UntransformVector(frontHardPoint);
         m_frontHarpointOnThread = childMatrix.UntransformVector(frontHardPoint);

         // calculate the front rear suspension points
         dVector rearHardPoint (childMatrix.m_posit + childMatrix.RotateVector(rearDir.Scale (minPointFront % rearDir)));
         m_rearHarpointOnParent = parentMatrix.UntransformVector(rearHardPoint);
         m_rearHarpointOnThread = childMatrix.UntransformVector(rearHardPoint);

      
         dFloat Ixx;
         dFloat Iyy;
         dFloat Izz;
         dFloat mass0;
         dFloat mass1;
         NewtonBodyGetMassMatrix(child, &mass0, &Ixx, &Iyy, &Izz);
         NewtonBodyGetMassMatrix(parent, &mass1, &Ixx, &Iyy, &Izz);
         m_massScale = (mass0 * mass1) / (mass0 + mass1);
      }

      ~FrictionTrankThreaSuspention()
      {   
         //do nothig at thsi time
      }

      void ApplySuspesionForce (
         dFloat timestep,
         const NewtonBody* thread, const dVector& threadPointLocal, const dMatrix& threadMatrix, const dVector& threadCOM, const dVector& threadVeloc, const dVector& threadOmega,
         const NewtonBody* parent, const dVector& parentPointLocal, const dMatrix& parentMatrix, const dVector& parentCOM, const dVector& parentVeloc, const dVector& parentOmega)
      {
         dFloat dist;
         dFloat speed;
         dFloat forceMag;

         // calculate separation and speed of hard points
         dVector threadPoint (threadMatrix.TransformVector(threadPointLocal));
         dVector parentPoint (parentMatrix.TransformVector(parentPointLocal));
         dist = (parentPoint - threadPoint) % parentMatrix.m_up;
         speed = ((parentVeloc + parentOmega * (parentPoint - parentCOM) -
                 threadVeloc - threadOmega * (threadPoint - threadCOM)) % parentMatrix.m_up);

         if (dist > MAX_COMPRESION_DIST) {
            NewtonUserJointAddLinearRow (m_joint, &threadPoint[0], &threadPoint[0], &parentMatrix.m_up[0]);
            NewtonUserJointSetRowMinimumFriction(m_joint, 0.0f);
         } else if (dist < MIN_EXPANSION_DIST) {
            // submit a contact constraint to prevent the body
            NewtonUserJointAddLinearRow (m_joint, &threadPoint[0], &threadPoint[0], &parentMatrix.m_up[0]);
            NewtonUserJointSetRowMaximumFriction(m_joint, 0.0f);
         }

         // apply the spring force
         forceMag = NewtonCalculateSpringDamperAcceleration (timestep, SPRING_CONST, dist, DAMPER_CONST, speed) * m_massScale;


         dVector forceParent (parentMatrix.m_up.Scale (forceMag));
         dVector torqueParent ((parentPoint - parentCOM) * forceParent);
         NewtonBodyAddForce(m_body1, &forceParent[0]);
         NewtonBodyAddTorque(m_body1, &torqueParent[0]);
         
      
         dVector forceThread (forceParent.Scale (-1.0f));
         dVector torqueThread ((threadPoint - threadCOM) * forceThread);
         NewtonBodyAddForce(m_body0, &forceThread[0]);
         NewtonBodyAddTorque(m_body0, &torqueThread[0]);
      }

      void SubmitConstraints (dFloat timestep, int threadIndex)
      {
         // calculate suspension bumpers and forces
         dMatrix threadMatrix;
         dMatrix parentMatrix;

         dVector threadCOM;
         dVector parentCOM;
         dVector threadVeloc;
         dVector parentVeloc;
         dVector threadOmega;
         dVector parentOmega;


         // get the physics body state;
         NewtonBodyGetOmega(m_body0, &threadOmega[0]);
         NewtonBodyGetOmega(m_body1, &parentOmega[0]);

         NewtonBodyGetVelocity(m_body0, &threadVeloc[0]);
         NewtonBodyGetVelocity(m_body1, &parentVeloc[0]);

         NewtonBodyGetCentreOfMass(m_body0, &threadCOM[0]);
         NewtonBodyGetCentreOfMass(m_body1, &parentCOM[0]);

         NewtonBodyGetMatrix(m_body0, &threadMatrix[0][0]);
         NewtonBodyGetMatrix(m_body1, &parentMatrix[0][0]);

         threadCOM = threadMatrix.TransformVector(threadCOM);
         parentCOM = parentMatrix.TransformVector(parentCOM);
         
         ApplySuspesionForce (timestep,
            m_body0, m_rearHarpointOnThread, threadMatrix, threadCOM, threadVeloc, threadOmega,
            m_body1, m_rearHarpointOnParent, parentMatrix, parentCOM, parentVeloc, parentOmega);

         ApplySuspesionForce (timestep,
            m_body0, m_frontHarpointOnThread, threadMatrix, threadCOM, threadVeloc, threadOmega,
            m_body1, m_frontHarpointOnParent, parentMatrix, parentCOM, parentVeloc, parentOmega);


         CustomSlidingContact::SubmitConstraints (timestep, threadIndex);
      }


      dFloat m_massScale;
      dVector m_frontHarpointOnParent;
      dVector m_frontHarpointOnThread;

      dVector m_rearHarpointOnParent;
      dVector m_rearHarpointOnThread;
   };


   public:
   FrictionTrank(const dModel& sourceModel, SceneManager* system, NewtonWorld* nWorld, const dMatrix& matrix, int bodyID, int tracksID)
      :RenderPrimitive(matrix, NULL)
   {
      // open the level data
      InitFromModel (sourceModel);
      system->Append (this);   
      SetMatrix (matrix);

      // create the main body physic object
      m_mainBone = FindBone ("mainBody");
      m_mainBody = CreateBodyPart (m_mainBone, nWorld, 100.0f);
      NewtonBodySetTransformCallback (m_mainBody, SetTransform);

      // create the right thread body
      m_rightThread = FindBone ("track_right");
      m_rightThreadBody = CreateBodyPart (m_rightThread, nWorld, 100.0f);

      // create the left thread body
      m_leftThread = FindBone ("track_left");
      m_leftThreadBody = CreateBodyPart (m_leftThread, nWorld, 100.0f);

      // lower the center of mass of the main body to give more stability
      dVector com;
      NewtonBodyGetCentreOfMass(m_mainBody, &com[0]);
      com.m_y -= 0.5f;
      NewtonBodySetCentreOfMass(m_mainBody, &com[0]);

      // set the material ID for the threads
      NewtonBodySetMaterialGroupID(m_mainBody, bodyID);
      NewtonBodySetMaterialGroupID(m_leftThreadBody, tracksID);
      NewtonBodySetMaterialGroupID(m_rightThreadBody, tracksID);

      dMatrix leftThreadPinAndPivot;
      NewtonBodyGetMatrix (m_leftThreadBody, &leftThreadPinAndPivot[0][0]);
      leftThreadPinAndPivot.m_front = matrix.m_up;
      leftThreadPinAndPivot.m_up = matrix.m_right;
      leftThreadPinAndPivot.m_right = leftThreadPinAndPivot.m_front * leftThreadPinAndPivot.m_up;
      new FrictionTrankThreaSuspention (leftThreadPinAndPivot, m_leftThreadBody, m_mainBody);

      dMatrix rightThreadPinAndPivot;
      NewtonBodyGetMatrix (m_rightThreadBody, &rightThreadPinAndPivot[0][0]);
      rightThreadPinAndPivot.m_front = matrix.m_up;
      rightThreadPinAndPivot.m_up = matrix.m_right;
      rightThreadPinAndPivot.m_right = rightThreadPinAndPivot.m_front * rightThreadPinAndPivot.m_up;
      new FrictionTrankThreaSuspention (rightThreadPinAndPivot, m_rightThreadBody, m_mainBody);

      // add a track control joint
      m_controller = new FrictionTractionControl (m_mainBody, m_leftThreadBody, m_rightThreadBody);
   }


   ~FrictionTrank(void)
   {
   }

/*
   NewtonBody* GetBody() const
   {
      return m_myBody;
   }

   void SetSteering (float steer)
   {
      m_controller->m_turnVeloc = steer * 3.0f;
      
   }

   void SetTireTorque(float torque)
   {
      m_controller->m_veloc = torque * 6.0f;
   }

*/

   static void SetTransform (const NewtonBody* body, const dFloat* matrix, int threadIndex)
   {
      FrictionTrank* me;
      me = (FrictionTrank*) NewtonBodyGetUserData (body);

      const dMatrix& rootMatrix = *((dMatrix*) matrix);
//      me->m_matrix = me->m_mainBone->m_localMatrix.Inverse() * rootMatrix;
      me->SetMatrix(rootMatrix);

      // calculate the local matrix of the threads
      dMatrix threadMatrix;
      NewtonBodyGetMatrix (me->m_leftThreadBody, &threadMatrix[0][0]);
      me->m_leftThread->m_localMatrix = threadMatrix * me->m_leftThread->GetParent()->CalcGlobalMatrix().Inverse();

      NewtonBodyGetMatrix (me->m_rightThreadBody, &threadMatrix[0][0]);
      me->m_rightThread->m_localMatrix = threadMatrix * me->m_rightThread->GetParent()->CalcGlobalMatrix().Inverse();;
   }

   private:
   NewtonBody* CreateBodyPart (dBone* bone, NewtonWorld* nWorld, dFloat mass) const
   {
      dFloat Ixx;
      dFloat Iyy;
      dFloat Izz;
      dMesh* geomtry;
      NewtonBody* body;
      NewtonCollision* collision;
      dVector origin;
      dVector inertia;
      //dVector vertex[1024 * 32];

      // find the main body part
      geomtry = FindMesh (bone->GetName());

      // iterate again collecting the vertex array
      collision = NewtonCreateConvexHull (nWorld, geomtry->m_vertexCount, geomtry->m_vertex, 3 * sizeof (dFloat), 0.1f, 0, NULL);

      //create the rigid body
      body = NewtonCreateBody (nWorld, collision);


      // release the collision
      NewtonReleaseCollision (nWorld, collision);   

      // save the pointer to the graphic object with the body.
      NewtonBodySetUserData (body, (void*)this);

      // set the material group id for vehicle
      NewtonBodySetMaterialGroupID (body, 0);

      // set a destructor for this rigid body
      NewtonBodySetDestructorCallback (body, PhysicsBodyDestructor);

      // set the force and torque call back function
      NewtonBodySetForceAndTorqueCallback (body, PhysicsApplyGravityForce);

      // calculate the moment of inertia and the relative center of mass of the solid
      NewtonConvexCollisionCalculateInertialMatrix (collision, &inertia[0], &origin[0]);   

      Ixx = mass * inertia[0];
      Iyy = mass * inertia[1];
      Izz = mass * inertia[2];

      // set the mass matrix
      NewtonBodySetMassMatrix (body, mass, Ixx, Iyy, Izz);

      // Set the vehicle Center of mass
      // the rear spoilers race the center of mass by a lot for a race car
      // we need to lower some more for the geometrical value of the y axis
      NewtonBodySetCentreOfMass (body, &origin[0]);

      // set the matrix for both the rigid body and the graphic body
      dMatrix matrix (bone->CalcGlobalMatrix(FindBone(0)) * GetMatrix());
      NewtonBodySetMatrix (body, &matrix[0][0]);

      return body;
   }

   dBone* m_mainBone;
   dBone* m_leftThread;
   dBone* m_rightThread;

   

   NewtonBody* m_mainBody;
   NewtonBody* m_leftThreadBody;
   NewtonBody* m_rightThreadBody;
   FrictionTractionControl* m_controller;
};


that joint is not part of teh standrd joint library because it is is a very special joint,
it is similar to the sliding contact joint, but not exatly the same.
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Rigid joint question

Postby xavram » Thu Mar 18, 2010 4:43 pm

I'll take a look Julio thanks...will have to see how to "translate" this into what's available in TV.
xavram
 
Posts: 10
Joined: Wed Mar 17, 2010 2:04 pm


Return to General Discussion

Who is online

Users browsing this forum: No registered users and 2 guests