Relative Joint Rotation

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
w00f
Posts: 10
Joined: Sun Dec 11, 2011 11:29 am

Relative Joint Rotation

Post by w00f »

I am currently working on a project using Kinect to control the Irrlicht virtual avatar;

From the Kinect, I was able to get the vectors

kShoulder = Neck->Shoulder, kUpArm = Shoulder->Elbow and kForeArm = Elbow to Hand.


Image

Then I follow this code to get the rotation for the foreArm joint.
I use the quaternion.h from Irrlicht 1.8 SDK so I believe the toEuler bug has been fixed.
However the result is weird. Only some positions are mirrored correctly.

Can soneone help me find anything wrong with my approach?

Code: Select all

 
        core::quaternion lElbowRotationQ;
        vector3df       lElbowRotationEuler;
        vector3df   lElbowRotationDeg;
        lElbowRotationQ.rotationFromTo(kForeArmL,kUpArmL);
        lElbowRotationQ.normalize();
        lElbowRotationQ.toEuler(lElbowRotationEuler);
        lElbowRotationDeg = lElbowRotationEuler * core::RADTODEG;
 
 
        foreArmL->setRotation(lElbowRotationDeg);
RdR
Competition winner
Posts: 273
Joined: Tue Mar 29, 2011 2:58 pm
Contact:

Re: Relative Joint Rotation

Post by RdR »

Not sure if I miss something, but why this:

lElbowRotationDeg = lElbowRotationEuler * core::RADTODEG;

Isn't lElbowRotationEuler already the correct rotation by using lElbowRotationQ.toEuler(lElbowRotationEuler); ?
w00f
Posts: 10
Joined: Sun Dec 11, 2011 11:29 am

Re: Relative Joint Rotation

Post by w00f »

That function to convert Radian to Degree. The rotation function uses Degree not Radian :D

Do I have to reset the joint to the initial rotation before rotate it to a new rotation ?
RdR
Competition winner
Posts: 273
Joined: Tue Mar 29, 2011 2:58 pm
Contact:

Re: Relative Joint Rotation

Post by RdR »

w00f wrote:That function to convert Radian to Degree. The rotation function uses Degree not Radian :D

Do I have to reset the joint to the initial rotation before rotate it to a new rotation ?
Yeah i know it converts it, but which function uses radians? :wink:
No you can set it right away. Just like setPosition()
w00f
Posts: 10
Joined: Sun Dec 11, 2011 11:29 am

Re: Relative Joint Rotation

Post by w00f »

This function RdR

foreArmL->setRotation(lElbowRotationDeg);

foreArmL is a Joint Node :D

I just have a thought that the result from my calculation is rotation degree in world coordinate not relative joint coordinate. I must have a way to convert it to relative coordinate before apply the rotation. <--- But I am not sure about this.
RdR
Competition winner
Posts: 273
Joined: Tue Mar 29, 2011 2:58 pm
Contact:

Re: Relative Joint Rotation

Post by RdR »

w00f wrote: I just have a thought that the result from my calculation is rotation degree in world coordinate not relative joint coordinate. I must have a way to convert it to relative coordinate before apply the rotation. <--- But I am not sure about this.
Yeah, that is true lElbowRotationQ.rotationFromTo(kForeArmL,kUpArmL); is calculating the absolute rotation between those two nodes.
Just set the rotation for each joint, starting from the neck and working your way to the hand

Code: Select all

 
        irr::core::quaternion quaternion;
        irr::scene::ISceneNode* neckNode;
        irr::scene::ISceneNode* shoulderNode;
        irr::scene::ISceneNode* elbowNode;
        irr::core::vector3df rotation;
        
        // Shoulder
        quaternion.rotationFromTo(neckNode->getAbsolutePosition(), shoulderNode->getAbsolutePosition());
        rotation = quaternion.getMatrix().getRotationDegrees();
        
        neckNode->setRotation(rotation);
        
        // Upper arm
        quaternion.rotationFromTo(shoulderNode->getAbsolutePosition(), elbowNode->getAbsolutePosition());
        rotation = quaternion.getMatrix().getRotationDegrees();
        
        shoulderNode->setRotation(rotation);
        
        // etc
 
Tekkai
Posts: 24
Joined: Tue Mar 30, 2010 2:02 pm
Contact:

Re: Relative Joint Rotation

Post by Tekkai »

Hi,

I left working with quaternionsbecause of my last tests when working with Kinect. I'm not pretty sure about that but I guess that maybe the expected format of the setRotation Eueler convention is not the same Euler convention that the quaterion is exporting. I mean, there are twelve conventions (extracted from wikipedia) of how to create Euler Angles, maybe the one created by the quaternion classes and the one that setRotation is expecting is not the same. Maybe someone more understood on this could help you with that, but what I've done, and my recomendation if you want to follow with that, is that you start using Matrix instead of quaternions.

Cheers.
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Relative Joint Rotation

Post by mongoose7 »

Irrlicht doesn't use "Euler angles", it uses Tait-Bryan angles, so there is no problem going to and from.
w00f
Posts: 10
Joined: Sun Dec 11, 2011 11:29 am

Re: Relative Joint Rotation

Post by w00f »

@RdR

That looks correct, but not working either. The joint movement is still not correct. :(

@Tekkai:

I think that in your previous work, after you get the Euler angle, you should apply the rotation by the order(euler.Z,euer.X,euler.Y)
Btw how is your project with Kinect atm. Have you managed to get it working? Would you mind share with me your method to get the rotation correct? :D :roll:
w00f
Posts: 10
Joined: Sun Dec 11, 2011 11:29 am

Re: Relative Joint Rotation

Post by w00f »

Rdr, I think that your method only find out the World Rotation. You have to convert it into local rotation before apply the setRotation.

How can I convert from world rotation to local rotation?

I have been thinking about using the inverse absolute transformation matrix but this only works with position not rotation.

I tried something as:

Code: Select all

        
        matrix4 n;
        n = foreArmR->getAbsoluteTransformation();
        n.setRotationDegrees(vector3df(0,0,-90));
        n.makeInverse();
        foreArmR->setRotation(n.getRotationDegrees());
 
The joint not rotate as expected. :-?
docWild
Posts: 38
Joined: Wed Nov 30, 2011 4:29 pm

Re: Relative Joint Rotation

Post by docWild »

I may be telling you wrong, but don't you need two matrices to set a relative rotation?

Code: Select all

 irr::core::matrix4 m;
    m.setRotationDegrees(bodyNode->getRotation());
    irr::core::matrix4 n;
    n.setRotationDegrees(rot);
    m *= n;
    bodyNode->setRotation( m.getRotationDegrees() );
    bodyNode->updateAbsolutePosition();
Will set a rotation by rot degrees, relative to bodyNode's rotation.
Tekkai
Posts: 24
Joined: Tue Mar 30, 2010 2:02 pm
Contact:

Re: Relative Joint Rotation

Post by Tekkai »

Hi, I'm planning to share my code, which are two classes that should do everything for you. You will just have to make sure that you're mesh have a bones named as I specify, and that's all you will have to do. The problem is that I'm in the middle of something and don't want to share it yet, as I also have to speak with some people about it. If I don't get the permission I will help you with the steps.

From now I can tell you two tips that will help you. The axis of Kinect and Irrlicht are not the same, you have to invert X in order to get it working (x = -x). Also you have to take care with the initial rotation. You will have to calculate the bind pose and it's inverse, but you also have to sum at the end of the process the initial rotation of the bone, because when you do a setRotation, initial rotation is not being used by irrlicht.
w00f
Posts: 10
Joined: Sun Dec 11, 2011 11:29 am

Re: Relative Joint Rotation

Post by w00f »

Thank you Tekkai, it's good to know that someone actually done this is helping me cause I'm really stuck at the moment and if I cannot find a solution soon I might have to change the rendering engine. But for now knowing you have actually done this I will stick with Irrlicht :lol:

I have already invert X and Y also since my character import to Irrlicht is up-side-down.

I don't understand the purpose of the initial rotation that you mentioned. If I just load the mesh and display it without any rotational change, my mesh still display its initial pose as it is suppose to be in the modeling software (I use blender). Also if not using quaternion, how can you know the rotation angle between two vectors? Can you share me your idea with that?

And the result from the quaternion rotation

Code: Select all

        core::quaternion lElbowRotationQ;
        vector3df       lElbowRotationEuler;
        vector3df   lElbowRotationDeg;
        lElbowRotationQ.rotationFromTo(kForeArmL,kUpArmL);
 
        lElbowRotationDeg = lElbowRotationQ.getMatrix().getRotationDegrees();
produce different result compare to

Code: Select all

        core::quaternion lElbowRotationQ;
        vector3df       lElbowRotationEuler;
        vector3df   lElbowRotationDeg;
        lElbowRotationQ.rotationFromTo(kForeArmL,kUpArmL);
        lElbowRotationQ.normalize();
        lElbowRotationQ.toEuler(lElbowRotationEuler);
        lElbowRotationDeg = lElbowRotationEuler * core::RADTODEG;
What is the correct Rotation Deg in world coordinate?
w00f
Posts: 10
Joined: Sun Dec 11, 2011 11:29 am

Re: Relative Joint Rotation

Post by w00f »

Up with my problem :(

@Tekkai would you mind explain more about the initial rotation? :(

Image
Tekkai
Posts: 24
Joined: Tue Mar 30, 2010 2:02 pm
Contact:

Re: Relative Joint Rotation

Post by Tekkai »

Hey, sorry for the delay.

About the initial rotation: Try to set every bone rotation to (0.0f,0.0f,0.0f) and you will probably see what I mean. You can also cout << the rotation of each bone to see the same result. Maybe it's just a thing of 3D Studio Max (that's the program I used) but the bones have initial rotations in the bind pose. This rotations are already in "local pose" so you don't have to do anything with them, just add them at the end of the rotations.

About how to calculate the matrix. My libraries of Kinect (NITE) are giving the information with matrix format also. So I just have to make an inverse of one of the bones, and multiply it by the other. I cannot remember the order, but you can try both and see what's the correct one.

Cheers,
Post Reply