Definition of pitch, yaw, roll in jMonkeyEngine

Hi,

I’m a bit confused by the definition of pitch, yaw and roll in jMonkeyEngine.

In the Quaternion documentation: http://www.jmonkeyengine.com/doc/com/jme/math/Quaternion.html it says that:

yaw rotates around x

roll rotates around y

pitch rotates around z.



However, when I look at the following definition from http://www.flipcode.com/documents/matrfaq.html#Q32 it says the following:



Pitch then becomes rotation in the X-axis, Yaw becomes rotation in the

Y-axis and Roll becomes rotation in the Z-axis.



Why is there a difference between them?

1 Like

jME uses a right handed coordinate system.

Cheers,

Normen

Thanks for the info. That explains why there seemed to be differences in definitions.

1 Like

I think there is an error though in the doc…

In the doc you refer to it’s also a right handed coordinate system

I talk with momoko_fan about this and it’s seems the methods works correctly, but the doc is wrong

pitch should be around x, yaw around y and roll around z

1 Like
nehon said:
I think there is an error though in the doc...
In the doc you refer to it's also a right handed coordinate system
I talk with momoko_fan about this and it's seems the methods works correctly, but the doc is wrong
pitch should be around x, yaw around y and roll around z


So, with the following method:
public Quaternion fromAngles(float yaw, float roll, float pitch)

Is the order correct? Something I did notice though is when I set yaw to be 270 degrees, then convert it to radians as 4.71, when I do the reciprocal method: toAngles, this gives the yaw to be -1.57 radians.

When I was doing some experiments, I was using the following code with yaw incrementing every 90 degrees (1.57, 3.14, 4.71, 0)

rotation.fromAngles(yaw, roll, pitch);
arrowShape.setLocalRotation(rotation);

I noticed that the arrow would rotate towards out of the screen at 90 degrees, then downwards, then into the screen, then upwards. I suppose this is what is meant by rotating along the x-axis.

I am getting more confused by the statement that the documentation is wrong.
1 Like

Something else that I have noticed is if I do the following:



rotation.fromAngles(0, 0, angle);

arrowShape.setLocalRotation(rotation);



When I use the following code to output the angles, I get some strange output.



float yawrollpitch[] = new float[3];

arrowShape.getLocalRotation().toAngles(yawrollpitch);

System.out.printf (“After set: %.2f %.2f %.2fnn”, yawrollpitch[0],yawrollpitch[1],yawrollpitch[2]);



Now, yawrollpitch gives the following output, where input is the angle that was placed in the code earlier:



Input: 0.00 0.00 4.71

After set: 0.00 -6.28 -1.57



What I am wondering, is why does that happen? It’s only supposed to rotate along one axis.

1 Like

Wow. Looking at the file history, apparently I created this doc in 2007. The content sounds familiar, but I don’t remember publishing it. :roll:



“Roll” goes around X axis which goes along the length of the aircraft fuselage – if you look at it from the side.

“Yaw” is always around the Y axis (like shaking you head “no”).

“Pitch” means the nose of the plane goes down (nose dive) – if you look at the plane from the side, that goes around the Z axis.



So I’d say the variables are named wrong… :stuck_out_tongue: The variable are “X = yaw, Y= roll, Z= pitch”… Yaw is never the X axis… not even if you look at the aircraft from the front.

I assume the person who implemented the algorithm used a book with a different convention / different coordinate system.



Question to the developers, do you want to refactor this? It’s “only” variable names, no accessors or constructors will be affected. (On the other hand, it’s a whole lot of variable names…)



Here’s the javadoc – the author obviously used a different convention: because I m pretty sure bank == roll?!



[java] / ** the Euler yaw of rotation (in radians). (aka Bank, often rot around x)

  • the Euler roll of rotation (in radians). (aka Heading, often rot around y)
  • the Euler pitch of rotation (in radians). (aka Attitude, often rot around z) **/ [/java]



    Weird.

PS: I just tested rotate(x,y,z) with a loaded model.



x is the axis going from left to right. – rot around x is roll/bank

y is the one going from bottom up. – rot around y is yaw

z goes towards to onlooker. – rot around z is pitch



I am looking at this explanation of “pitch, yaw, bank=roll” here

http://ministryoftype.co.uk/words/article/pitch_bank_and_yaw/



Apparently, aircraft call the downward axis Z…? Aaarrrggh.

naddie said:
Something else that I have noticed is if I do the following:

rotation.fromAngles(0, 0, angle);
arrowShape.setLocalRotation(rotation);

When I use the following code to output the angles, I get some strange output.

float yawrollpitch[] = new float[3];
arrowShape.getLocalRotation().toAngles(yawrollpitch);
System.out.printf ("After set: %.2f %.2f %.2fnn", yawrollpitch[0],yawrollpitch[1],yawrollpitch[2]);

Now, yawrollpitch gives the following output, where input is the angle that was placed in the code earlier:

Input: 0.00 0.00 4.71
After set: 0.00 -6.28 -1.57

What I am wondering, is why does that happen? It's only supposed to rotate along one axis.


Ignore what I wrote there. I noticed a rogue addition in the affected rotation command. How embarrassing.

I am using the fish model that is in the jmetest directory in the svn’s src directory, and I have the following code to test the rotations.



[java]

import com.jme.app.SimpleGame;

import com.jme.scene.Node;

import com.jme.math.Vector3f;

import com.jme.math.Quaternion;



// For model importing

import java.net.URL;

import com.jmex.model.ogrexml.MaterialLoader;

import com.jmex.model.ogrexml.OgreLoader;

import com.jmex.model.ogrexml.anim.MeshAnimationController;



public class Rotate extends SimpleGame {

Node n;

public static void main(String[] args) {

Rotate app = new Rotate(); // Create Object

// Signal to show properties dialog

app.setConfigShowMode(ConfigShowMode.AlwaysShow);

app.start(); // Start the program

}



protected void simpleInitGame() {

n = getOgreMesh(“fish.mesh.xml”, “Example.material”);

n.setLocalTranslation(0,0,0);

n.setLocalScale(0.2f);

// that will throw nullpointer-exception if no animation is added!!

MeshAnimationController animC = (MeshAnimationController)n.getController(0);

// replace Action with the Animationname you want to play

animC.setAnimation(“swim”);

animC.setActive(true);

rootNode.attachChild(n); // Put it in the scene graph

}



public static Node getOgreMesh(String mesh,String mat)

{

OgreLoader loader = new OgreLoader();

MaterialLoader matLoader = new MaterialLoader();

try {

URL matURL = Rotate.class.getClassLoader().getResource(mat);

URL meshURL = Rotate.class.getClassLoader().getResource(mesh);

if (matURL != null){

matLoader.load(matURL.openStream());

if (matLoader.getMaterials().size() > 0)

loader.setMaterials(matLoader.getMaterials());

}

Node model = (Node) loader.loadModel(meshURL);

return model;

}

catch (Exception e) {

e.printStackTrace();

return null;

}

}



protected void simpleUpdate() {

float yawrollpitch[] = new float[3];

Quaternion rotation = new Quaternion();

rotation.fromAngles(0,1.57f,0);

n.setLocalRotation(rotation);

n.getLocalRotation().toAngles(yawrollpitch);

//System.out.printf (“After set: %.2f %.2f %.2fnn”, yawrollpitch[0],yawrollpitch[1],yawrollpitch[2]);

}

}

[/java]



In the simpleUpdate() method, when I have

[java]rotation.fromAngles(0,1.57f,0);[/java]



The fish is facing me. However, when I use

[java]rotation.fromAngles(1.57f,1.57f,0);[/java]



The fish is supposed to be looking down. Instead it lies on its side.



[java]rotation.fromAngles(0,1.57f,1.57f);[/java]



This one gives the fish looking down.



With regards to the rotation, is it in the order of rotation around (x,y,z), or is it (z,y,x)? My brain is getting fried by this!



Thanks

Sorry to raise a dang ol’ zombie, but the problems in javadoc for the crucial Quaternion object appear to persist into JME3.



Javadoc for Quaternion.fromAngles() currently cites this reference:



Maths - Conversion Euler to Quaternion - Martin Baker



which naturally leads us to this page of definitions:



Maths - Standards - Martin Baker



…in which the author defines his site as adhering to a right-handed cartesian sytem with:



+X to the right

+Y straight up

+Z axis toward viewer



…which matches what the JME3 “for dummies” tutorials say, and what I’ve seen in most math books. So far, so good.



Then, for an airplane flying towards a destination at X=+infinity, as shown in the diagram at bottom of page



Heading = rotation about y axis = YAW - applied first

Attitude = rotation about z axis = PITCH - applied second

Bank = rotation about x axis = ROLL - applied third



…which matches how most other sources define these rotations conceptually, although as others have mentioned, the labeling of x,y,z axes is sometimes different.



However, our java method arguments are currently specified as:



fromAngles(float yaw, float roll, float pitch)



which the javadoc explains using this textual disaster, which was no doubt written by a sequential committee of well-meaning coders, who was each attempting to correct previous mistakes.

[java]

  • <code>fromAngles</code> builds a Quaternion from the Euler rotation
  • angles (y,r,p). Note that we are applying in order: roll, pitch, yaw but
  • we’ve ordered them in x, y, and z for convenience.
  • @see <a href="Maths - Conversion Euler to Quaternion - Martin Baker">Maths - Conversion Euler to Quaternion - Martin Baker</a>

    *
  • @param yaw
  •        the Euler yaw of rotation (in radians). (aka Bank, often rot<br />
    
  •        around x)<br />
    
  • @param roll
  •        the Euler roll of rotation (in radians). (aka Heading, often<br />
    
  •        rot around y)<br />
    
  • @param pitch
  •        the Euler pitch of rotation (in radians). (aka Attitude, often<br />
    
  •        rot around z)<br />
    

[/java]

To me (and I think to a large swath of the audience for JMonkeyEngine), this is one of the single most important methods in JME3, and I would like to be able to rely on the documentation. I hope that we can promptly update the docs and argument names here (and in the rest of the methods of Quaternion) so that they agree with each other and what the EuclideanSpace.com explanations say. (And, of course, confirm that the implementation code then matches those argument names and docs, in particular regarding the order of application of the angles). I am happy to help with this effort, though I am not currently a JME3 committer.

1 Like

I find yaw, roll, pitch confusing each time, why not just use x,y,z? ^^ Anyway, yaw means rotation around Y, pitch means rotating around X and roll means rotating around Z if you take the default jme/opengl settings.

Yeah, the javadoc is still wrong.



The parameters should be: pitch, yaw, roll and the descriptions of those parameters are also wrong. And in a way that is not right except for the very strangest of coordinate systems: “yaw - the Euler yaw of rotation (in radians). (aka Bank, often rot around x)” Even if you use a Z-up coordinate system, that’s not right.



I don’t know why it hasn’t been fixed in all of this time… but I also don’t know why I haven’t fixed it myself. :slight_smile: A long time ago, I started thinking about the parameters as xAxis, yAxis, zAxis and never think about the javadocs until it confuses someone else.

The diagram Normen posted sort of implies that direction of travel = out of the screen, which appeals to our intuition that “forward” is colinear with the way we face our screens, which is I think how @pspeed arrived at “pitch,yaw,roll”.



However, if we accept the convention of EuclideanSpace.com that [bold]the airplane is flying towards a destination at X=+infinity[/bold], then the JME3 parameters should be labeled something like:



roll_about_X, yaw_about_Y, pitch_about_Z



meaning -

roll = rotation about X

yaw = rotation about Y

pitch = rotation about Z



@Normen asked:

why not just use x,y,z?


Proposed Solution Part 1 - Change the param names to say "xRot, yRot, zRot", then specify clearly what order these rotations are actually applied to construct our Quaternion rotation operator (because the rotation operator is non-commutative, as we all know quite well ;) )

THEN, we could simply leave it at that, and put a link to EuclideanSpace.com for people who want to go into airplane terminology. Or, we could continue on to:

Proposed Solution Part 2 - Get the airplane words correctly attached to the JMonkey X,Y,Z axes. The key to doing that is to correctly label (in our minds) the axes in Normen's airplane diagram above. On the cited EuclideanSpace.com reference page that is currently in the Javadocs, the definition is that the X-Axis = Roll-Axis = Direction of Forward Travel, and the Y Axis = Yaw-Axis = Vertical-up for a level-flying plane (this contradicts Normen's diagram in that EuclideanSpace.com chooses YAW = "up" rather than "down", but the author there justifies his reasons and cites references and standards, and it matches the idea in JMonkey that positive-Y = "up", so, can we just go with that?)

Again, in this labeling, the Airplane's destination is at X=+infinity.

So then, to match up Normen's airplane diagram with JMonkey's definition of X=Right, Y=Up, Z=Out-of-screen towards us,
we merely rotate the plane so it is flying on our X-Axis, towards the right of our screens (and label yaw axis as "up", not "down"), as shown on the diagram I cited at:

http://www.euclideanspace.com/maths/standards/index.htm

Then
JMonkey X axis = Roll-Axis = Bank-Axis
JMonkey Y axis = Yaw-Axis = Heading-Axis
JMonkey Z axis = Pitch-Axis = Attitude-Axis

In my own code, I am currently using
[java]q.fromAngles(rot_X_bank, rot_Y_heading, rot_Z_attitude); [/java]
to try to drown out the roar of incorrectly labeled yaw,roll.

I have verified that these interpretations are correct using the current JMonkey runtime.

All the above seems pretty unambiguous to me, if we are actually using EuclideanSpace.com as our reference. If we're not, then let's just fall back to proposed solution part #1 (xRot, yRot, zRot) - and please say what order they are applied in!
@stub22 said:
Sorry to contradict @pspeed, but I think the JME3 parameters, in airplane lingo, if we accept the convention of EuclideanSpace.com that the airplane is flying towards a destination at X=+infinity, should be:


No, we can't accept that convention because in JME the camera is looking down the Z axis and Y axis is up.

So, yaw is rotation about the Y axis. Pitch is rotation about the X axis. Roll is rotation about the Z axis.

Since the fromAngles() method takes, essentially xAxis, yAxis, zAxis, that's the same as pitch, yaw, roll.

More to the point, in JME everything related to a “direction vector” is the Z axis. Forward/back is always along the Z axis of the quaternion.

I agree that the JME3 Camera is pointing at Z=negative-infinity, but I don’t agree that “the airplane” is flying on the Z-axis, in the same (actually exact opposite) direction as “the camera” is pointing (although the one on Normen’s diagram appears to be). It’s intuitive to say that it is, but we can’t do that and also cite EuclideanSpace.com (which does have a diagram!) as a reference. If we want to strike the EuclideanSpace.com reference, and then find a reference that says “the camera is pointing at the nose of the airplane, which is flying out of the screen, along the Z azis”, then we’d have clarity around @pspeed’s labeling, and that would be fine.

Man, you can label the axes whatever you want… but in JME, Z axis is direction. For the camera, for the Spatials, for the Quaternions.



If you call Quaternion.lookAt() you are setting where the Z axis points. Anything that JME includes that does movement in a direction will be doing it in the Z axis. (When you think about it, it’s very convenient that all of these things are in agreement.)



So anything but fromAngles(pitch, yaw, roll) is going to be very confusing since if you swap pitch and roll then pitch would effectively control roll and roll would effectively control yaw.



I don’t make the conventions… I just point to them.

OK, I hear you. So let’s just call the parameters xRot, yRot, zRot, and strike the EuclideanSpace.com reference from the Javadoc. We agree that the current Javadoc labeling is 100% wrong - we are debating pitch and roll, but sure as heck not yaw! I notice that the “JME3 Math for Dummies” slideshow does not mention the airplane notation. There is a JME2 page which matches @pspeed 's conventions:



http://www.hub.jmonkeyengine.org/wiki/doku.php/jme2:rotate



If we can create our own clearly labeled diagram and put it on the JME3 website, and make sure that all the other pages / tutorials use the same conventions, then we will be in great shape.



I like your intuitive framework for roll+pitch, but keeping a Javadoc reference link to a website using a different notation is torture for the person trying to use a Quaternion properly (which is obviously one of the challenging things for a game-programmer newbie, right?).



For posterity, here is the airplane diagram from EuclideanSpace.com which we are now agreeing to not use :wink:

http://www.euclideanspace.com/maths/geometry/rotations/euler/aeroplaneGlobal1.png

I always thought pictures like that were kind of funny… since a compass heading is degrees from North… which would be down the Y or Z axis depending on whether you were Z-up or Y-up.



Whether you point the plane down X or Z in a picture like that is rather arbitrary. I just find it funny that they chose to pick the one that will confuse the most people.



Most of the vis-sim stuff I’ve used thankfully treats X as left to right… whether Y is up or Z is up.