Shaking Revolute Joints

gmz1982

11-03-2009 15:18:08

Hi,

I created two actors and joined them together with a revolute joint. The problem is that they are shaking and moving around.

http://www.youtube.com/watch?v=RZzJLP2hoC4


NxOgre::Actor* box1 = NULL;
NxOgre::Actor* box2 = NULL;

box1 = PXScene->createActor("Actora1", new NxOgre::Cube(0.2, 1.5, 0.2), Vector3(-2, 2, -3), "mass: 5.0" );
box2 = PXScene->createActor("Actora2", new NxOgre::Cube(0.2, 1.5, 0.2), Vector3(-2, 4, -3), "mass: 5.0" );

NxVec3 globalAnchor = NxVec3(-2, 3 ,-3);
NxVec3 globalAxis = NxVec3(0,0,1);

NxRevoluteJoint* revJoint = NULL;
revJoint = CreateRevoluteJoint(box1->getNxActor(), box2->getNxActor(), globalAnchor, globalAxis);



NxRevoluteJoint* CreateRevoluteJoint( NxActor* a0, NxActor* a1, NxVec3 globalAnchor, NxVec3 globalAxis)
{
NxRevoluteJointDesc revDesc;

revDesc.actor[0] = a0;
revDesc.actor[1] = a1;
revDesc.setGlobalAnchor(globalAnchor);
revDesc.setGlobalAxis(globalAxis);

revDesc.jointFlags |= NX_JF_COLLISION_ENABLED;

//revDesc.projectionMode = NX_JPM_POINT_MINDIST;
//revDesc.projectionDistance = 1.0f;
//revDesc.projectionAngle = 5.0f;
//revDesc.actor[0]->setLinearDamping( 10.0 );
//revDesc.actor[1]->setLinearDamping( 10.0 );

return (NxRevoluteJoint*)PXScene->getNxScene()->createJoint(revDesc);
}


I have searched the forum and found out that others have / had this problem also but I did not found a solution. The code is basically a copy/paste from the PhysX SDK.

I have tried:
- moving the joint the the edge of one of the boxes
- joining the two actors with 2 joints
- projection ( which is commented out in the code )

Interesting is that the remote controller says, the mass of one of the actors is 5.0, the mass of the other actor is -1.0. If I log the masses, each are separatelly 5.0.
The code seems to be "out of the box" so I assume the problem is somewhere else.

Could anyone give me a hint about this?

Thanks in advance!

[edit] I noticed that they are shake until the actor's localNormal get pependicular to each other. Maybe I am missing the basic concepts of joints? :(

gmz1982

11-03-2009 19:47:17


NxRevoluteJointDesc revDesc;

revDesc.actor[0] = a0;
revDesc.actor[1] = a1;

revDesc.setGlobalAnchor(globalAnchor);
revDesc.setGlobalAxis(globalAxis);

revDesc.localAxis[0] = NxVec3( 0, 0, 1 );//blue
revDesc.localAxis[1] = NxVec3( 0, 0, 1 );//blue

revDesc.localNormal[0] = NxVec3( 1, 0, 0 );//red
revDesc.localNormal[1] = NxVec3( 1, 0, 0 );//red

revDesc.localAnchor[0] = NxVec3( 0, 1, 0 );//green
revDesc.localAnchor[1] = NxVec3( 0, -1, 0 );//green


The joint's localAxis is the dark (black) arrow, the red arrow is the joint's localNormal ( barely visible ).
I noticed that the green arrow is pointing down while tha actors axis are pointing up. ( the point of the green arrow is also barely visible :) )

Maybe the actors space is calculated otherwise then the joint's space?

gmz1982

14-03-2009 06:54:19

As an experiment I started a new project but this time without using NxOgre and using only the PhysX SDK.

It looks like I ended up with the same results that I am having for some time.
I share the code provided in the ragdoll tutorials:


#define NOMINMAX
#include "NxPhysics.h"

// Physics SDK globals
NxPhysicsSDK* gPhysicsSDK = NULL;
NxScene* gScene = NULL;
NxVec3 gDefaultGravity(0,-9.8,0);

NxActor* ground = NULL;

NxActor* CreateGroundPlane()
{
// Create a plane with default descriptor
NxPlaneShapeDesc planeDesc;
NxActorDesc actorDesc;
actorDesc.shapes.pushBack(&planeDesc);
return gScene->createActor(actorDesc);
};


Ragdoll code:

NxActor* CreateSphere(const NxVec3& pos, const NxReal radius, const NxReal density)
{
// Add a single-shape actor to the scene
NxActorDesc actorDesc;
NxBodyDesc bodyDesc;

// The actor has one shape, a sphere
NxSphereShapeDesc sphereDesc;
sphereDesc.radius = radius;
sphereDesc.localPose.t = NxVec3(0,radius,0);
actorDesc.shapes.pushBack(&sphereDesc);

if (density)
{
actorDesc.body = &bodyDesc;
actorDesc.density = density;
}
else
{
actorDesc.body = NULL;
}
actorDesc.globalPose.t = pos;

NxActor* a = gScene->createActor(actorDesc);
a->setAngularDamping( 2.0f );
a->setLinearDamping( 2.0f );

return a;
}


NxActor* CreateCapsule(const NxVec3& pos, const NxReal height, const NxReal radius, const NxReal density)
{
// Add a single-shape actor to the scene
NxActorDesc actorDesc;
NxBodyDesc bodyDesc;

// The actor has one shape, a capsule
NxCapsuleShapeDesc capsuleDesc;
capsuleDesc.height = height;
capsuleDesc.radius = radius;
capsuleDesc.localPose.t = NxVec3(0,radius+0.5*height,0);
actorDesc.shapes.pushBack(&capsuleDesc);

if (density)
{
actorDesc.body = &bodyDesc;
actorDesc.density = density;
}
else
{
actorDesc.body = NULL;
}
actorDesc.globalPose.t = pos;

NxActor* a = gScene->createActor(actorDesc);
a->setAngularDamping( 2.0f );
a->setLinearDamping( 2.0f );

return a;
}

NxActor* CreateBox(const NxVec3& pos, const NxVec3& boxDim, const NxReal density)
{
// Add a single-shape actor to the scene
NxActorDesc actorDesc;
NxBodyDesc bodyDesc;

// The actor has one shape, a box
NxBoxShapeDesc boxDesc;
boxDesc.dimensions.set(boxDim.x,boxDim.y,boxDim.z);
boxDesc.localPose.t = NxVec3(0,boxDim.y,0);
actorDesc.shapes.pushBack(&boxDesc);

if (density)
{
actorDesc.body = &bodyDesc;
actorDesc.density = density;
}
else
{
actorDesc.body = NULL;
}
actorDesc.globalPose.t = pos;

NxActor* pActor = gScene->createActor(actorDesc);
pActor->setAngularDamping( 2.0f );
pActor->setLinearDamping( 2.0f );

return pActor;
}



NxSphericalJoint* CreateBodySphericalJoint(NxActor* a0, NxActor* a1, const NxVec3& globalAnchor, const NxVec3& globalAxis)
{
NxSphericalJointDesc sphericalDesc;
sphericalDesc.actor[0] = a0;
sphericalDesc.actor[1] = a1;
sphericalDesc.setGlobalAnchor(globalAnchor);
sphericalDesc.setGlobalAxis(globalAxis);

sphericalDesc.flags |= NX_SJF_TWIST_LIMIT_ENABLED;
sphericalDesc.twistLimit.low.value = -(NxReal)0.025*NxPi;
sphericalDesc.twistLimit.low.hardness = 0.5;
sphericalDesc.twistLimit.low.restitution = 0.5;
sphericalDesc.twistLimit.high.value = (NxReal)0.025*NxPi;
sphericalDesc.twistLimit.high.hardness = 0.5;
sphericalDesc.twistLimit.high.restitution = 0.5;

sphericalDesc.flags |= NX_SJF_SWING_LIMIT_ENABLED;
sphericalDesc.swingLimit.value = (NxReal)0.25*NxPi;
sphericalDesc.swingLimit.hardness = 0.5;
sphericalDesc.swingLimit.restitution = 0.5;

sphericalDesc.flags |= NX_SJF_TWIST_SPRING_ENABLED;
sphericalDesc.twistSpring.spring = 0.5;
sphericalDesc.twistSpring.damper = 1;

sphericalDesc.flags |= NX_SJF_SWING_SPRING_ENABLED;
sphericalDesc.swingSpring.spring = 0.5;
sphericalDesc.swingSpring.damper = 1;

// sphericalDesc.flags |= NX_SJF_JOINT_SPRING_ENABLED;
// sphericalDesc.jointSpring.spring = 0.5;
// sphericalDesc.jointSpring.damper = 1;

sphericalDesc.projectionDistance = (NxReal)0.15;
sphericalDesc.projectionMode = NX_JPM_POINT_MINDIST;

return (NxSphericalJoint*)gScene->createJoint(sphericalDesc);
}


NxRevoluteJoint* CreateRevoluteJoint2(NxActor* a0, NxActor* a1, const NxVec3& localAnchor0,const NxVec3& localAnchor1, const NxVec3& localAxis0, const NxVec3& localAxis1)
{
NxRevoluteJointDesc revDesc;
revDesc.actor[0] = a0;
revDesc.actor[1] = a1;
//revDesc.setGlobalAnchor(globalAnchor);
//revDesc.setGlobalAxis(globalAxis);
revDesc.localAnchor[0]=localAnchor0;
revDesc.localAnchor[1]=localAnchor1;
revDesc.localAxis[0] =localAxis0;
revDesc.localAxis[1] =localAxis1;
revDesc.projectionMode = NX_JPM_POINT_MINDIST;
return (NxRevoluteJoint*)gScene->createJoint(revDesc);
}
/* -------------------------------------------------------------------------------------- */

class Ragdoll
{
public:
Ragdoll(const NxVec3& pos)
{
NxReal mmass = 10.0;

NxQuat qRotLeft, qRotRight, qRotAround;
qRotLeft.fromAngleAxis(90, NxVec3(0,0,1));
qRotRight.fromAngleAxis(-90, NxVec3(0,0,1));
qRotAround.fromAngleAxis(180, NxVec3(0,0,1));

NxMat33 mRotLeft, mRotRight, mRotAround;
mRotLeft.fromQuat(qRotLeft);
mRotRight.fromQuat(qRotRight);
mRotAround.fromQuat(qRotAround);

// Create body parts
head = CreateSphere(NxVec3(0,8.8,0), 0.5, mmass);
torso = CreateSphere(NxVec3(0,7,0), 0.95, mmass);
pelvis = CreateSphere(NxVec3(0,5.8,0), 0.7, mmass);

leftUpperArm = CreateCapsule(NxVec3(0.5,8.5,0), 1, 0.4, mmass);
leftUpperArm->setGlobalOrientationQuat(qRotRight);
leftForeArm = CreateCapsule(NxVec3(2,8.5,0), 1, 0.3, mmass);
leftForeArm->setGlobalOrientationQuat(qRotRight);
leftHand = CreateBox(NxVec3(3.5,8.5,0), NxVec3(0.3,0.3,0.1), mmass);
leftHand->setGlobalOrientationQuat(qRotRight);

rightUpperArm = CreateCapsule(NxVec3(-0.5,8.5,0), 1, 0.4, mmass);
rightUpperArm->setGlobalOrientationQuat(qRotLeft);
rightForeArm = CreateCapsule(NxVec3(-2,8.5,0), 1, 0.3, mmass);
rightForeArm->setGlobalOrientationQuat(qRotLeft);
rightHand = CreateBox(NxVec3(-3.5,8.5,0), NxVec3(0.3,0.3,0.1), mmass);
rightHand->setGlobalOrientationQuat(qRotLeft);

leftThigh = CreateCapsule(NxVec3(0.6,6,0), 1.5, 0.5, mmass);
leftThigh->setGlobalOrientationQuat(qRotAround);
leftCalf = CreateCapsule(NxVec3(0.6,3.5,0), 1.5, 0.35, mmass);
leftCalf->setGlobalOrientationQuat(qRotAround);
leftFoot = CreateBox(NxVec3(0.6,1.5,0.2), NxVec3(0.4,0.2,0.75), mmass);
leftFoot->setGlobalOrientationQuat(qRotAround);

rightThigh = CreateCapsule(NxVec3(-0.6,6,0), 1.5, 0.5, mmass);
rightThigh->setGlobalOrientationQuat(qRotAround);
rightCalf = CreateCapsule(NxVec3(-0.6,3.5,0), 1.5, 0.35, mmass);
rightCalf->setGlobalOrientationQuat(qRotAround);
rightFoot = CreateBox(NxVec3(-0.6,1.5,0.2), NxVec3(0.4,0.2,0.75), mmass);
rightFoot->setGlobalOrientationQuat(qRotAround);

// Joint body parts together
neck = CreateBodySphericalJoint(head,torso,NxVec3(0,8.8,0),NxVec3(0,1,0));
leftShoulder = CreateBodySphericalJoint(leftUpperArm,torso,NxVec3(0.5,8.5,0),NxVec3(1,0,0));
rightShoulder = CreateBodySphericalJoint(rightUpperArm,torso,NxVec3(-0.5,8.5,0),NxVec3(-1,0,0));
spine = CreateBodySphericalJoint(torso,pelvis,NxVec3(0,7,0),NxVec3(0,-1,0));
leftHip = CreateBodySphericalJoint(leftThigh,pelvis,NxVec3(0.6,6,0),NxVec3(0,-1,0));
rightHip = CreateBodySphericalJoint(rightThigh,pelvis,NxVec3(-0.6,6,0),NxVec3(0,-1,0));

leftElbow = CreateRevoluteJoint(leftForeArm,leftUpperArm,NxVec3(2,8.5,0),NxVec3(0,0,-1));
rightElbow = CreateRevoluteJoint(rightForeArm,rightUpperArm,NxVec3(-2,8.5,0),NxVec3(0,0,-1));

leftWrist = CreateRevoluteJoint2(leftHand,leftForeArm,NxVec3(0,-0.15,0),NxVec3(0,1.3,0),NxVec3(0,1,0),NxVec3(0,1,0));
rightWrist = CreateRevoluteJoint2(rightHand,rightForeArm,NxVec3(0,-0.15,0),NxVec3(0,1.3,0),NxVec3(0,1,0),NxVec3(0,1,0));

leftKnee = CreateRevoluteJoint(leftCalf,leftThigh,NxVec3(0.6,3.5,0),NxVec3(1,0,0));
rightKnee = CreateRevoluteJoint(rightCalf,rightThigh,NxVec3(-0.6,3.5,0),NxVec3(-1,0,0));

leftAnkle = CreateRevoluteJoint(leftFoot,leftCalf,NxVec3(0.6,1.3,0),NxVec3(1,0,0));
rightAnkle = CreateRevoluteJoint(rightFoot,rightCalf,NxVec3(-0.6,1.3,0),NxVec3(-1,0,0));
};

NxActor* head;
NxActor* torso;
NxActor* pelvis;
NxActor* leftUpperArm;
NxActor* rightUpperArm;
NxActor* leftForeArm;
NxActor* rightForeArm;
NxActor* leftHand;
NxActor* rightHand;
NxActor* leftThigh;
NxActor* rightThigh;
NxActor* leftCalf;
NxActor* rightCalf;
NxActor* leftFoot;
NxActor* rightFoot;

NxSphericalJoint* neck;
NxSphericalJoint* leftShoulder;
NxSphericalJoint* rightShoulder;
NxSphericalJoint* spine;
NxSphericalJoint* leftHip;
NxSphericalJoint* rightHip;

NxRevoluteJoint* leftElbow;
NxRevoluteJoint* rightElbow;
NxRevoluteJoint* leftWrist;
NxRevoluteJoint* rightWrist;
NxRevoluteJoint* leftKnee;
NxRevoluteJoint* rightKnee;
NxRevoluteJoint* leftAnkle;
NxRevoluteJoint* rightAnkle;
};
/* -------------------------------------------------------------------------------------- */



void InitNx()
{
// Create the physics SDK
gPhysicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION);
if (!gPhysicsSDK) return;

gPhysicsSDK->getFoundationSDK().getRemoteDebugger()->connect ("localhost", 5425);
gPhysicsSDK->setParameter(NX_SKIN_WIDTH, 0.01);
gPhysicsSDK->setParameter(NX_VISUALIZATION_SCALE, 1);
gPhysicsSDK->setParameter(NX_VISUALIZE_COLLISION_SHAPES, 1);
gPhysicsSDK->setParameter(NX_VISUALIZE_ACTOR_AXES, 1);

// Create the scene
NxSceneDesc sceneDesc;

sceneDesc.gravity = gDefaultGravity;
sceneDesc.simType = NX_SIMULATION_HW;
gScene = gPhysicsSDK->createScene(sceneDesc);

if(!gScene)
{
sceneDesc.simType = NX_SIMULATION_SW;
gScene = gPhysicsSDK->createScene(sceneDesc);
if(!gScene) return;
}

// Create the default material
NxMaterial* defaultMaterial = gScene->getMaterialFromIndex(0);
defaultMaterial->setRestitution(0.5);
defaultMaterial->setStaticFriction(0.5);
defaultMaterial->setDynamicFriction(0.5);

ground = CreateGroundPlane();
//mbox = CreateBox();
}

void UpdateNxFrame( NxReal deltaTime )
{
gScene->simulate( deltaTime );
gScene->flushStream();

while ( !gScene->fetchResults( NX_RIGID_BODY_FINISHED, false ) );
};


Ogre createScene():

void createScene()
{

InitNx();

Ragdoll* guy = NULL;
guy = new Ragdoll( NxVec3(0.0, 0.0, 0.0) );
}


.. and in the Ogre framelistener I update it by using:

class OgreWithFunctionAppFrameListener : public FrameListener
{
public: bool frameStarted(const FrameEvent& evt)
{

UpdateNxFrame( evt.timeSinceLastFrame );

return true;
}

};


As far as I can tell, the code is the same thing in the tutorial but looks very differently and had the exact same results in NxOgre also :(
http://www.youtube.com/watch?v=9esI88cjouk
http://www.youtube.com/watch?v=ZuB13jBtons

The only difference I noticed is the update method where I pass through evt.timeSinceLastFrame.

Does anyone have an idea what I could check?

gmz1982

14-03-2009 08:56:39

OK, I made a very big mistake with the ragdoll :oops:

After I recreated everything for the fourth time but this time very-very slowly, I noticed that I already had a NxRevoluteJoint* CreateRevoluteJoint(..) where I enabled intercollisions:
//revDesc.jointFlags |= NX_JF_COLLISION_ENABLED;//
In the SDK tutorial it just was not enabled :D
Now the fall of the ragdoll looks the exact same way it looks in the SDK executable..

Anyway, my original problem is still present with the two connected cube actors. Is this the "normal" behaviour with joints with enabled intercollisions between the two actors?

nargil

14-03-2009 12:15:09

does it work with the robot.mesh ?