Rotate an orthonormal Vector3f base using Quaternions?

Hello!



I hope you've time to answer my newbie question, I know it's kind of basic but I'm stuck:



I extended a node which contains a global yaw pitch and roll axis, starting with ordinary unity vectors. So there are three Vector3fs.



Now I can align my extended node with these axis simply by doing the following:


Quaternion rot=new Quaternion();
rot.fromAxes(pitchAxis, yawAxis, RollAxis);
setLocalRotation(rot);



Now, as I make some control input, let's say to pitch up by angle alpha, the roll and yaw axis would have to be rotated around the pitch axis by angle alpha. Now, the thing is:
How can I make jME calculate the new Vector3fs for my yaw and roll axis?
Is there a way to rotate an orthonormal vector base using Quaternions?

I just don't get it  :? :? :?, please help me if you can!

cjet

Ok this is an update to my situation:



I tried several ways for rotating an object around its own 'local' roll pitch and yaw axes. I do believe that you cannot just "use" jME Quaternions on Vector3fs - Correct me if I'm wrong.

Now what I've figured out is that you cannot combine all three rotations in one matrix because it might lead to a gimbal lock. (…and I couldn't find a matrix behaving the way I wanted it to…  :wink: )



What I've done is to do 3 separate steps of rotation, each step rotates 2 axes:

Rotation of pitch means rotation of the yaw and roll axes and so on…



Maybe someone got stuck with the same problem, so here is the code for my solution:

Be careful when using it, it does not use current angles but rates.



// =============================================================================
   public void update()
// =============================================================================
{
  .
  :

// Roll rotation
   Matrix3f rollRot=rotateFromAxis(localRollRate, rollAxis);
   pitchAxis=rollRot.mult(pitchAxis);
   yawAxis=rollRot.mult(yawAxis);
// Pitch rotation
   Matrix3f pitchRot=rotateFromAxis(localPitchRate, pitchAxis);
   rollAxis=pitchRot.mult(rollAxis);
   yawAxis=pitchRot.mult(yawAxis);
// Yaw rotation
   Matrix3f yawRot=rotateFromAxis(localYawRate, yawAxis);
   rollAxis=yawRot.mult(rollAxis);
   pitchAxis=yawRot.mult(pitchAxis);
} // update =====================================================================


// =============================================================================
   private Matrix3f rotateFromAxis(float angle, Vector3f axis)
// =============================================================================
{  float ax=axis.getX();
   float ay=axis.getY();
   float az=axis.getZ();
  
   float s=FastMath.sin(angle);
   float c=FastMath.cos(angle);
   float u=1f-FastMath.cos(angle);
  
   return new Matrix3f(
      ax*ax*u+c,        ay*ax*u-az*s,     az*ax*u+ay*s,
      ax*ay*u+az*s,     ay*ay*u+c,        az*ay*u-ax*s,
      ax*az*u-ay*s,     ay*az*u+ax*s,     az*az*u+c
   );
} // rotateFromAxis ===============================================================



rgds,
cjet

Hi, I just tripped over this link to a wiki page in a tutorial section:



http://www.jmonkeyengine.com/wiki/doku.php?id=rotate&s=rotation



It might explain quaternions for you, I kinda know they're used to avoid gimbal lock, but that sounds like a throat infection!!!  :roll:



I've been using two nodes to rotate vector3f's. If I have a node at [0,0,0] and add a child at my vector3f location, and I rotate the parent by the quaternion, then the world position of the child vector3f will be the result of the rotation on the vector3f:



Node parent = new Node("parent");
Node child = new Node("child");
child.setLocalTranslation(vectorToRotate);
parent.attachChild(child);
parent.setLocalRotation(quaternion);
rootNode.attachChild(parent);
Vector3f result = child.getWorldTranslation();



To get the pitch, yaw and roll from the quaternion, you can use:


Vector3f pitch = new Vector3f();
Vector3f yaw = new Vector3f();
Vector3f roll = new Vector3f();

quaternion.getRotationColumn(0, pitch);
quaternion.getRotationColumn(1, yaw);
quaternion.getRotationColumn(2, roll);

Nodes are just a logical concept that jME uses to wrap almost every Object (program not visual).  It depends on how you use the Node as to whether it is rendered or not.  What I am trying to say is using Nodes to facilitate your program design is on of jMEs greatest advantages.  Don't be scared to use an extra Node or two if it makes your life easier, that's what they are there for.  :smiley:

Thank you for your response.

I wanted to avoid making extra nodes for performing these rotations but it gives me a good idea of this possibility. Don't know yet what would be better for this purpose.  :slight_smile:

Why not just make the quaternion multiply the vector which you want to rotate? The result is the rotated vector by the quaternion!  Try the following code:


import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;

public class RotateVector3f {

   /**
    * @param args
    */
   public static void main(String[] args) {
      Quaternion quat = new Quaternion();
      quat.fromAngleAxis(FastMath.PI / 4, Vector3f.UNIT_Z);
      Vector3f v = new Vector3f(1, 0, 0);
      quat.mult(v, v);
      System.out.println(v);
   }
}



The result is [X=0.7071067, Y=0.7071068, Z=0.0].
1 Like