More power to JointLibrary

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

More power to JointLibrary

Postby kallaspriit » Thu Dec 31, 2009 5:11 am

I know NGD itself is a rather low-level library but there is no reason for the JointLibrary to be one. For example, every now and then there are questions how to motorize a hinge.

With a hinge joint, one usually wants to do the following things:
- apply angle limits
- get current angle
- make it move to a desired angle (optionally set maximum force applied to get there)
- apply torque
- get the speed at which the joint is turning
- brake the rotation of the hinge (optionally set the maximum force)

These are exactly what I needed and instead of making another custom joint, I modified the one in JointLibrary. I am not sure whether I implemented these correctly, but here is the source:

CustomHinge.h
Code: Select all
/* Copyright (c) <2009> <Newton Game Dynamics>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely
*/

// CustomHinge.h: interface for the CustomHinge class.
//
//////////////////////////////////////////////////////////////////////


#if !defined(AFX_CUSTOMHINGE_H__B631F556_468B_4331_B7D7_F85ECF3E9ADE__INCLUDED_)
#define AFX_CUSTOMHINGE_H__B631F556_468B_4331_B7D7_F85ECF3E9ADE__INCLUDED_

#include "NewtonCustomJoint.h"

class JOINTLIBRARY_API CustomHinge: public NewtonCustomJoint 
{
   public:
   CustomHinge (const dMatrix& pinsAndPivoFrame, const NewtonBody* child, const NewtonBody* parent = NULL);
   virtual ~CustomHinge();

   void EnableLimits(bool state);
   void SetLimis(dFloat minAngle, dFloat maxAngle);

   //! Try to move to this angle, has effect for single frame
   void ApplyDesiredAngle(dFloat angle, dFloat minFriction = 0, dFloat maxFriction = 0);

   //! Apply given torque for one frame
   void ApplyTorque(dFloat torque);

   //! Apply brake for one frame
   //  -1: brake with infinite force
   //   0: no brake
   // > 0: brake with limited force
   void ApplyBrake(dFloat maxForce = -1);

   dFloat getCurrentAngle();
   dFloat getVelocity();

   protected:
   virtual void GetInfo (NewtonJointRecord* info) const;
   virtual void SubmitConstraints (dFloat timestep, int threadIndex);

   dMatrix m_localMatrix0;
   dMatrix m_localMatrix1;

   bool m_limitsOn;
   dFloat m_minAngle;
   dFloat m_maxAngle;

   bool m_motorOn;
   dFloat m_desiredAngle;
   dFloat m_motorMinFriction;
   dFloat m_motorMaxFriction;
   
   dFloat m_torque;
   dFloat m_brake;

   AngularIntegration m_curJointAngle;
};

#endif // !defined(AFX_CUSTOMHINGE_H__B631F556_468B_4331_B7D7_F85ECF3E9ADE__INCLUDED_)


CustomHinge.cpp
Code: Select all
/* Copyright (c) <2009> <Newton Game Dynamics>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely
*/



// CustomHinge.cpp: implementation of the CustomHinge class.
//
//////////////////////////////////////////////////////////////////////
#include "CustomJointLibraryStdAfx.h"
#include "CustomHinge.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

#define MIN_JOINT_PIN_LENGTH   50.0f


CustomHinge::CustomHinge (const dMatrix& pinAndPivotFrame, const NewtonBody* child, const NewtonBody* parent)
   :NewtonCustomJoint(6, child, parent), m_curJointAngle()
{
   m_limitsOn = false;
   m_minAngle = -45.0f * 3.141592f / 180.0f;
   m_maxAngle =  45.0f * 3.141592f / 180.0f;

   m_motorOn = false;
   m_desiredAngle = 0;
   m_motorMinFriction = 0;
   m_motorMaxFriction = 0;

   m_torque = 0;
   m_brake = 0;

   // calculate the two local matrix of the pivot point
   CalculateLocalMatrix (pinAndPivotFrame, m_localMatrix0, m_localMatrix1);
}

CustomHinge::~CustomHinge()
{
}


void CustomHinge::EnableLimits(bool state)
{
   m_limitsOn = state;
}

void CustomHinge::SetLimis(dFloat minAngle, dFloat maxAngle)
{
   //_ASSERTE (minAngle < 0.0f);
   //_ASSERTE (maxAngle > 0.0f);
   m_minAngle = minAngle;
   m_maxAngle = maxAngle;
   m_limitsOn = true;
}

void CustomHinge::ApplyDesiredAngle(dFloat angle, dFloat minFriction, dFloat maxFriction)
{
   m_desiredAngle = angle;
   m_motorMinFriction = minFriction;
   m_motorMaxFriction = maxFriction;
   m_motorOn = true;
}

void CustomHinge::ApplyTorque(dFloat torque)
{
   m_torque = torque;
}

void CustomHinge::ApplyBrake(dFloat maxForce)
{
   m_brake = maxForce;
}

void CustomHinge::SubmitConstraints (dFloat timestep, int threadIndex)
{
   dMatrix matrix0;
   dMatrix matrix1;

   // calculate the position of the pivot point and the Jacobian direction vectors, in global space.
   CalculateGlobalMatrix (m_localMatrix0, m_localMatrix1, matrix0, matrix1);

   // Restrict the movement on the pivot point along all tree orthonormal direction
   NewtonUserJointAddLinearRow (m_joint, &matrix0.m_posit[0], &matrix1.m_posit[0], &matrix0.m_front[0]);
   NewtonUserJointAddLinearRow (m_joint, &matrix0.m_posit[0], &matrix1.m_posit[0], &matrix0.m_up[0]);
   NewtonUserJointAddLinearRow (m_joint, &matrix0.m_posit[0], &matrix1.m_posit[0], &matrix0.m_right[0]);
   
   // get a point along the pin axis at some reasonable large distance from the pivot
   dVector q0 (matrix0.m_posit + matrix0.m_front.Scale(MIN_JOINT_PIN_LENGTH));
   dVector q1 (matrix1.m_posit + matrix1.m_front.Scale(MIN_JOINT_PIN_LENGTH));

   // two constraints row perpendicular to the pin vector
    NewtonUserJointAddLinearRow (m_joint, &q0[0], &q1[0], &matrix0.m_up[0]);
   NewtonUserJointAddLinearRow (m_joint, &q0[0], &q1[0], &matrix0.m_right[0]);

   // if limit or motor are enabled ...
   if (m_limitsOn || m_motorOn || m_torque != 0 || m_brake != 0) {
      dFloat angle;
      dFloat sinAngle;
      dFloat cosAngle;

      // the joint angle can be determine by getting the angle between any two non parallel vectors
      sinAngle = (matrix0.m_up * matrix1.m_up) % matrix0.m_front;
      cosAngle = matrix0.m_up % matrix1.m_up;
      angle = m_curJointAngle.CalculateJointAngle (cosAngle, sinAngle);

      if (m_limitsOn && angle < m_minAngle) {
         dFloat relAngle;

         relAngle = angle - m_minAngle;
         // the angle was clipped save the new clip limit
         m_curJointAngle.m_angle = m_minAngle;

         // tell joint error will minimize the exceeded angle error
         NewtonUserJointAddAngularRow (m_joint, relAngle, &matrix0.m_front[0]);

         // need high stiffness here
         NewtonUserJointSetRowStiffness (m_joint, 1.0f);

         // allow the joint to move back freely
         NewtonUserJointSetRowMaximumFriction (m_joint, 0.0f);

      } else if (m_limitsOn && angle  > m_maxAngle) {
         dFloat relAngle;

         relAngle = angle - m_maxAngle;

         // the angle was clipped save the new clip limit
         m_curJointAngle.m_angle = m_maxAngle;
         
         // tell joint error will minimize the exceeded angle error
         NewtonUserJointAddAngularRow (m_joint, relAngle, &matrix0.m_front[0]);

         // need high stiffness here
         NewtonUserJointSetRowStiffness (m_joint, 1.0f);

         // allow the joint to move back freely
         NewtonUserJointSetRowMinimumFriction (m_joint, 0.0f);

      } else if (m_motorOn) {
         // find relative angle
         dFloat relAngle = angle - m_desiredAngle;

         // the angle was clipped save the new clip limit
         m_curJointAngle.m_angle = m_desiredAngle;
         
         // tell joint error will minimize the exceeded angle error
         NewtonUserJointAddAngularRow (m_joint, relAngle, &matrix0.m_front[0]);

         // need high stiffness here
         NewtonUserJointSetRowStiffness (m_joint, 1.0f);

         // set minimum friction if available
         if (m_motorMinFriction < 0) {
            NewtonUserJointSetRowMinimumFriction (m_joint, m_motorMinFriction);
         }

         // set maximum friction if available
         if (m_motorMaxFriction > 0) {
            NewtonUserJointSetRowMaximumFriction (m_joint, m_motorMaxFriction);
         }

         m_motorOn = false;
      } else if (m_brake != 0) {
         // the angle was clipped save the new clip limit
         m_curJointAngle.m_angle = angle;
         
         // tell joint error will minimize the exceeded angle error
         NewtonUserJointAddAngularRow (m_joint, 0, &matrix0.m_front[0]);

         // need high stiffness here
         NewtonUserJointSetRowStiffness (m_joint, 1.0f);

         // set brake friction if available
         if (m_brake > 0) {
            NewtonUserJointSetRowMinimumFriction (m_joint, -m_brake);
            NewtonUserJointSetRowMaximumFriction (m_joint, m_brake);
         }

         m_brake = 0;
      } else if (m_torque != 0) {
         // add some torque directly to child body
         // not sure if this is correct or the best way
         dVector childTorqueVector = matrix0.m_front.Scale(m_torque);
         NewtonBodyAddTorque (m_body0, &childTorqueVector[0]);

         /* Would this be correct?
         if (m_body1)
         {
            dVector parentTorqueVector = matrix1.m_front.Scale(-m_torque);
            NewtonBodyAddTorque (m_body1, &parentTorqueVector[0]);
         }
         */

         m_torque = 0;
      }
   }
}

dFloat CustomHinge::getCurrentAngle()
{
   dMatrix matrix0;
   dMatrix matrix1;

   // calculate the position of the pivot point and the Jacobian direction vectors, in global space.
   CalculateGlobalMatrix (m_localMatrix0, m_localMatrix1, matrix0, matrix1);

   // the joint angle can be determine by getting the angle between any two non parallel vectors
   dFloat sinAngle = (matrix0.m_up * matrix1.m_up) % matrix0.m_front;
   dFloat cosAngle = matrix0.m_up % matrix1.m_up;
   
   return m_curJointAngle.CalculateJointAngle (cosAngle, sinAngle);
}

dFloat CustomHinge::getVelocity()
{
   dMatrix matrix0;
   dMatrix matrix1;

   // calculate the position of the pivot point and the Jacobian direction vectors, in global space.
   CalculateGlobalMatrix (m_localMatrix0, m_localMatrix1, matrix0, matrix1);

   dVector omega;
   NewtonBodyGetOmega(m_body0, &omega[0]);

   return omega % matrix0.m_front;
}

void CustomHinge::GetInfo (NewtonJointRecord* info) const
{
   strcpy (info->m_descriptionType, "hinge");

   info->m_attachBody_0 = m_body0;
   info->m_attachBody_1 = m_body1;

   info->m_minLinearDof[0] = 0.0f;
   info->m_maxLinearDof[0] = 0.0f;

   info->m_minLinearDof[1] = 0.0f;
   info->m_maxLinearDof[1] = 0.0f;;

   info->m_minLinearDof[2] = 0.0f;
   info->m_maxLinearDof[2] = 0.0f;


   // the joint angle can be determine by getting the angle between any two non parallel vectors


   if (m_limitsOn) {
      dFloat angle;
      dFloat sinAngle;
      dFloat cosAngle;
      dMatrix matrix0;
      dMatrix matrix1;
      // calculate the position of the pivot point and the Jacobian direction vectors, in global space.
      CalculateGlobalMatrix (m_localMatrix0, m_localMatrix1, matrix0, matrix1);
      sinAngle = (matrix0.m_up * matrix1.m_up) % matrix0.m_front;
      cosAngle = matrix0.m_up % matrix1.m_up;
      angle = dAtan2 (sinAngle, cosAngle);
      info->m_minAngularDof[0] = (m_minAngle - angle) * 180.0f / 3.141592f ;
      info->m_maxAngularDof[0] = (m_maxAngle - angle) * 180.0f / 3.141592f ;
   } else {
      info->m_minAngularDof[0] = -FLT_MAX ;
      info->m_maxAngularDof[0] = FLT_MAX ;
   }

   info->m_minAngularDof[1] = 0.0f;
   info->m_maxAngularDof[1] = 0.0f;

   info->m_minAngularDof[2] = 0.0f;
   info->m_maxAngularDof[2] = 0.0f;

   memcpy (info->m_attachmenMatrix_0, &m_localMatrix0, sizeof (dMatrix));
   memcpy (info->m_attachmenMatrix_1, &m_localMatrix1, sizeof (dMatrix));
}


Julio, could you please verify that what I am doing is correct (it probably is not entirely, I'm still a beginner :D) and perhaps this could then be added to the JointLibrary, so in the future, people would not have to invent the bike every time they need this common functionality :P
kallaspriit
 
Posts: 216
Joined: Sun Aug 14, 2005 6:31 pm

Re: More power to JointLibrary

Postby Stucuk » Thu Dec 31, 2009 7:00 am

We could try reviving the Nut's concept. Nuts which stands iirc for Newton Utility Toolkit was an idea thought up in 2004-2005 where users could create a library with common high level stuff. The idea was to make it so that Nuts would basically be a plugin system with the actual higher level "addon" stuff being in plugins (Which would allow anyone from any language to contribute rather than only C++ people for example). The plugin system side was developed but noone ever actualy make any Newton plugins to go with it(Well tehnicaly there was one).
User avatar
Stucuk
 
Posts: 801
Joined: Sat Mar 12, 2005 3:54 pm
Location: Scotland

Re: More power to JointLibrary

Postby Julio Jerez » Thu Dec 31, 2009 9:49 am

actaully the C inteface have that funtionalitity, basically it have three more functions,

GetJointAngle and Get Joint Omega,
with this tow method a hinge is very eassy to make, I promote the funtionality to base Hinge and then making motor will be eassier.
I will add a demostrations to Ogre Newton Constom Joint Demo using that idea.
Julio Jerez
Moderator
Moderator
 
Posts: 12452
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: More power to JointLibrary

Postby kallaspriit » Thu Dec 31, 2009 10:39 am

But you don't want to add this functionality to the JointLibrary? This way, everyone could use it and not have to invent it themselves.
kallaspriit
 
Posts: 216
Joined: Sun Aug 14, 2005 6:31 pm

Re: More power to JointLibrary

Postby Julio Jerez » Thu Dec 31, 2009 11:07 am

I am only adding, function GetJointAngle and GetJointOmega, those seems to be intrisic part of any hinge joint.
I keep doing it all over the place in the demos it I realize ther beeob to teh joint itself

I am not changing anything other than saving those values so tha the can be read from a derived joint
The joint changes to this.

Code: Select all
class JOINTLIBRARY_API CustomHinge: public NewtonCustomJoint 
{
   public:
   CustomHinge (const dMatrix& pinsAndPivoFrame, const NewtonBody* child, const NewtonBody* parent = NULL);
   virtual ~CustomHinge();

   void EnableLimits(bool state);
   void SetLimis(dFloat minAngle, dFloat maxAngle);
   dFloat GetJointAngle () const;
   dVector GetPinAxis () const;
   dFloat GetJointOmega () const;

   protected:
   virtual void GetInfo (NewtonJointRecord* info) const;
   virtual void SubmitConstraints (dFloat timestep, int threadIndex);

   dMatrix m_localMatrix0;
   dMatrix m_localMatrix1;

   bool m_limitsOn;
   dFloat m_minAngle;
   dFloat m_maxAngle;
   dFloat m_jointOmega;
   AngularIntegration m_curJointAngle;
};


Then you just simple derive from ogre Newt::Hinge or for the Hinge itesel and make your custom motorized ogre::hinge.
Julio Jerez
Moderator
Moderator
 
Posts: 12452
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: More power to JointLibrary

Postby Julio Jerez » Thu Dec 31, 2009 1:24 pm

Ok I added few more interface funtion to teh OgreNewt::Joint
http://www.newtondynamics.com/downloads/OgreNewt.rar

make sure you also get Newton 2.16 again as I made a small change to the custom hinge joint.
notice tha these updates do not change the engine in anyway they are just some funtions added to the joints for a cleaner interface.

To show the usage I added an example of how to make a motorized Hinge joint to the Custom joint demos.
all king of motorized joint can be made, limit, not limit, controll by velocity or by acceleration.

Ok not I am back into the ray cast car joint.
Tell me some thing in Ogre, how can I make a mesh with hierchcy, I knwo you cna make it by attaching node, by I do no see a way to export nodes as asset, tha leave Bones as teh only way to export articulated meshes
am I wrong or is there a way to make articulated mesh?
for example I like to export a car in one piece, teh body, the wheel and everrything. how can I do that in one Mesh?
Julio Jerez
Moderator
Moderator
 
Posts: 12452
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: More power to JointLibrary

Postby kallaspriit » Fri Jan 01, 2010 2:20 pm

I am not sure you can, there is a dotscene format that defines object positions and relations in an xml file, but this is too much for a simple demo.
kallaspriit
 
Posts: 216
Joined: Sun Aug 14, 2005 6:31 pm

Re: More power to JointLibrary

Postby PJani » Sat Jan 02, 2010 8:59 pm

Julio Jerez wrote:Ok I added few more interface funtion to teh OgreNewt::Joint
http://www.newtondynamics.com/downloads/OgreNewt.rar

Ok not I am back into the ray cast car joint.
Tell me some thing in Ogre, how can I make a mesh with hierchcy, I knwo you cna make it by attaching node, by I do no see a way to export nodes as asset, tha leave Bones as teh only way to export articulated meshes
am I wrong or is there a way to make articulated mesh?
for example I like to export a car in one piece, teh body, the wheel and everrything. how can I do that in one Mesh?


Hmm using xml and multiple bodies maybe? This way i builded multibody vehicles on newton 1.35.
| i7-5930k@4.2Ghz, EVGA 980Ti FTW, 32GB RAM@3000 |
| Dell XPS 13 9370, i7-8550U, 16GB RAM |
| Ogre 1.7.4 | VC++ 9 | custom OgreNewt, Newton 300 |
| C/C++, C# |
User avatar
PJani
 
Posts: 448
Joined: Mon Feb 02, 2009 7:18 pm
Location: Slovenia

Re: More power to JointLibrary

Postby Julio Jerez » Sat Jan 02, 2010 10:20 pm

Yes, I guess that's the only solution.

Anyway, I added more changes to teh wraper, maybe you can try it and let me know if it works for you.
How is the performance? since I do not have a way to test in medium to low end system. I do not know if I am loading the demos too much.

One thing I noticed, Ogre performance decay dramatically each tiem the descrete entity count adouble, in the car demo I first put 51 cars and Ogre could not keep up renderring them and that was in release mode.
the FPS when down to lower than 30 fps, were with 25 cars it is from 250 to 350 fps, and that is only 250 descrete pieces.
Julio Jerez
Moderator
Moderator
 
Posts: 12452
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: More power to JointLibrary

Postby Dave Gravel » Sun Jan 03, 2010 4:21 am

[Julio]
Maybe the problem is about how to render thing.
I'm not sure how the object and the render is implemented in ogre,
But the speed problem surely coming because the system load many mesh and do many texture change in the render pass.
If you use many times the same car, maybe you can create only one mesh of this car and render this one for all.
Maybe ogre have proxy render object or something similar too...
You search a nice physics solution, if you can read this message you're at the good place :wink:
OrionX3D Projects & Demos:
https://orionx3d.sytes.net
https://www.facebook.com/dave.gravel1
https://www.youtube.com/user/EvadLevarg/videos
User avatar
Dave Gravel
 
Posts: 808
Joined: Sat Apr 01, 2006 9:31 pm
Location: Quebec in Canada.

Re: More power to JointLibrary

Postby Julio Jerez » Sun Jan 03, 2010 8:37 am

It is not really an issue for me since I am not making a game.
but that is one of the thing you expect from a graphic have solve for you enginer, engien lei unreal do no show that revere dacay of performance with so litel entity count.

I am sure there have to be a way to make it better in Ogre but tha woll require me to do a depp studie o fteh engien and I do no have tiem for that. Maybe in the future if I decide to make a show case demo.
Julio Jerez
Moderator
Moderator
 
Posts: 12452
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: More power to JointLibrary

Postby Dave Gravel » Sun Jan 03, 2010 5:48 pm

Yes it's all times same, learning and learning about...
And sometimes it's not better in final, it can depend from many factor. :(
You search a nice physics solution, if you can read this message you're at the good place :wink:
OrionX3D Projects & Demos:
https://orionx3d.sytes.net
https://www.facebook.com/dave.gravel1
https://www.youtube.com/user/EvadLevarg/videos
User avatar
Dave Gravel
 
Posts: 808
Joined: Sat Apr 01, 2006 9:31 pm
Location: Quebec in Canada.

Re: More power to JointLibrary

Postby Julio Jerez » Sun Jan 03, 2010 7:01 pm

PJani wrote:
Julio Jerez wrote:Tell me something in Ogre, how can I make a mesh with hierarchy, I know you can make it by attaching node, by I do not see a way to export nodes as asset, that leave Bones as the only way to export articulated meshes
am I wrong or is there a way to make articulated mesh?
for example I like to export a car in one piece, the body, the wheel and everything. how can I do that in one Mesh?


Hmm using xml and multiple bodies maybe? This way i builded multibody vehicles on newton 1.35.


On of the thing I wast lot of time is writing little XSI semi exporters to convert from on format to the next.
I have a very limited set of assets, but the goal I Have is the wrapper is useful for people other than we.
What still bother me is the it is too difficult use the engine specially for people that are no to kin on physics and Ogre at the same time.
Sore we can keep using XML and other syntax but what we need is a format that unifies both the physics and the graphics. One format is Collada.

Plus we get the added bonus that most modeling packages like Max Maya and XSI comes with Plug-in for Collada, Plus last time I check over the Collada website they were working on binary version.

The last few days I learned enough about the Ogre format that believe I can take the Netwon Collada Viewer and make the Content tool for getting data into Ogre/OgreNewt.
http://www.newtondynamics.com/downloads/NewtonColladaViewer.msi.zip

A Collada file is a unifies way to export Ogre entire Scene, Skeleton, Material, Meshes, skeleton, animation, (both as asset or as data), all the Newton physics, etc
I vehicle for example can be exported as a scene node that is instantiated.

And we do not have to worried about having plugging since most packages already supports Collada plugging, What do you think about that proposition?
Julio Jerez
Moderator
Moderator
 
Posts: 12452
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: More power to JointLibrary

Postby PJani » Mon Jan 04, 2010 1:04 am

I think collada will do it just great!
| i7-5930k@4.2Ghz, EVGA 980Ti FTW, 32GB RAM@3000 |
| Dell XPS 13 9370, i7-8550U, 16GB RAM |
| Ogre 1.7.4 | VC++ 9 | custom OgreNewt, Newton 300 |
| C/C++, C# |
User avatar
PJani
 
Posts: 448
Joined: Mon Feb 02, 2009 7:18 pm
Location: Slovenia

Re: More power to JointLibrary

Postby kallaspriit » Tue Jan 05, 2010 5:09 pm

I'm sure Collada support for OgreNewt would be great but I am currently probably too busy to be of much help.
kallaspriit
 
Posts: 216
Joined: Sun Aug 14, 2005 6:31 pm

Next

Return to General Discussion

Who is online

Users browsing this forum: No registered users and 381 guests