Jump to content

Unity Rotation code for pitch roll yaw question


Recommended Posts

Disclosure I also posted this question on the kOS Reddit.

I was wondering if anyone can explain to me what the quanterion multplication is doing in the follow code from MechJeb2 ie how the rotations produce the desired result:

rotationSurface = Quaternion.LookRotation(north, up);
rotationVesselSurface = Quaternion.Inverse(Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(vessel.GetTransform().rotation) * rotationSurface);

What appears to get returned is the pitch, roll and yaw values like what you would see on the KSP Navball.

I am trying to reverse-engineer the code because I am impressed and I want to understand for my education. But I keep getting results that do  not agree with MechJeb2 results. The strange thing is my version almost works if I remove the Euler(90,0,0) rotation - the need for this rotation is really puzzling.

I do accept that quanterions can give counter-intuitive results so I will accept it just works, but I do need to know the order the rotations are being performed in.

BTW why GetTransform instead of the Unity Transform?

Link to comment
Share on other sites

12 hours ago, Harry Twinotter said:

BTW why GetTransform instead of the Unity Transform?

GetTransform on the vessel returns the transform of the current "control as" part. 

As for the Quats (black) magic... I would rather not go there :)

 

Link to comment
Share on other sites

Just a couple of tips that may or may not help:

Every game object in unity has a transform. Transform is probably (Unity is not open sourced) a tuple of parent transform, local translation vector, local scaling vector and local rotation quaternion. Cached global (wich take parent transform in mind) translation\scaling\rotation are usually maintained under the hood. Essentially, transform gives each object it's own euclidean space (consisting of origin and three axels), and each transform describes, how to get from global, universal unity euclidean space to this game object's space, and vice versa.

Now imagine a KSP aircraft. It has cockpit. Cockpit is a "control from here" part, it is a game object, it has it's own space, it has transform. KSP has these conventions:

  • "right" unity vector of cockpit's transform is an X axel of cockpit's euclidean space. It's usually directed towards your right hand\wing.
  • "up" is Y axel, it's usually the direction the plane\rocket is flying. When simple rocket is just spawned from VAB, it's command pod's "up" vector is directed towards zenith.
  • "forward" is Z axel, it's usually directed towards plane's belly.

Keep in mind Unity uses left-handed coordinate systems.
Now, if you take vector (1, 0, 0) in cockpit's space, wich corresponds to the direction of the right wing, and apply cockpit transform's rotation to it (by multiplying it on rotation quaternion), you will get the direction the right wing is facing in global unity reference frame (in KSP this frame is usually non-moving relative to closest's planet surface, and planetarium axis-aligned, iirc).

Now, there's a little gotcha in multiplication order in Unity, I'm sure sarbian will not mind this private message disclosure:
2uaPriZ.png

Edited by Boris-Barboris
Link to comment
Share on other sites

2 hours ago, Boris-Barboris said:

Just a couple of tips that may or may not help:

Every game object in unity has a transform. Transform is probably (Unity is not open sourced) a tuple of parent transform, local translation vector, local scaling vector and local rotation quaternion. Cached global (wich take parent transform in mind) translation\scaling\rotation are usually maintained under the hood. Essentially, transform gives each object it's own euclidean space (consisting of origin and three axels), and each transform describes, how to get from global, universal unity euclidean space to this game object's space, and vice versa.

Now imagine a KSP aircraft. It has cockpit. Cockpit is a "control from here" part, it is a game object, it has it's own space, it has transform. KSP has these conventions:

  • "right" unity vector of cockpit's transform is an X axel of cockpit's euclidean space. It's usually directed towards your right hand\wing.
  • "up" is Y axel, it's usually the direction the plane\rocket is flying. When simple rocket is just spawned from VAB, it's command pod's "up" vector is directed towards zenith.
  • "forward" is Z axel, it's usually directed towards plane's belly.

Keep in mind Unity uses left-handed coordinate systems.
Now, if you take vector (1, 0, 0) in cockpit's space, wich corresponds to the direction of the right wing, and apply cockpit transform's rotation to it (by multiplying it on rotation quaternion), you will get the direction the right wing is facing in global unity reference frame (in KSP this frame is usually non-moving relative to closest's planet surface, and planetarium axis-aligned, iirc).

Now, there's a little gotcha in multiplication order in Unity, I'm sure sarbian will not mind this private message disclosure:
2uaPriZ.png

Thanks. I did get the impression the multiplication order was right to left, not left to right (at least when it come to applying rotations to orientations). The Unity doco is ambiguous. And I get that context is everything, you need to get your head around whether the quant you are interested in is a rotation for rotating a real object (hence the quants coordinates have no meaning in world space), or if the quant is an orientation of a real object and the coordinates do have a meaning in world space.

Edited by Harry Twinotter
Link to comment
Share on other sites

3 hours ago, sarbian said:

GetTransform on the vessel returns the transform of the current "control as" part. 

As for the Quats (black) magic... I would rather not go there :)

 

Thanks - that makes a lot of sense. I must test that, perhaps my vessel has a misaligned control part somewhere? Using MechJeb,  kOS and a command pod means I have 3 potential control points on the vessel maybe. It won't take me long to check. I remember the NavBall going nuts if I built a rover wrong.

Link to comment
Share on other sites

Changing the orientation of the MechJeb2 module does appear to make my code return the correct values in all cases, as long as I removed the r(90,0,0) from the multiplication.

I better test this again more carefully, I am tired. I will report back in a day or so.

Edited by Harry Twinotter
Link to comment
Share on other sites

  • 2 weeks later...
On 12/15/2017 at 8:40 AM, Harry Twinotter said:

Disclosure I also posted this question on the kOS Reddit.

I was wondering if anyone can explain to me what the quanterion multplication is doing in the follow code from MechJeb2 ie how the rotations produce the desired result:

rotationSurface = Quaternion.LookRotation(north, up);
rotationVesselSurface = Quaternion.Inverse(Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(vessel.GetTransform().rotation) * rotationSurface);

What appears to get returned is the pitch, roll and yaw values like what you would see on the KSP Navball.

I am trying to reverse-engineer the code because I am impressed and I want to understand for my education. But I keep getting results that do  not agree with MechJeb2 results. The strange thing is my version almost works if I remove the Euler(90,0,0) rotation - the need for this rotation is really puzzling.

I do accept that quanterions can give counter-intuitive results so I will accept it just works, but I do need to know the order the rotations are being performed in.

BTW why GetTransform instead of the Unity Transform?

OK I think I have worked out why the code gives the results it does. Once I found the error in my vessel (a misaligned MechJeb control pod), I started to get consistent results.

The "magic" works like this (if I am not wrong of course):

1. Create an orientation where the vessel's pitch,roll and yaw are said to be zero. Call this the reference orientation.
2. Create a relative rotation by multiplying the reference orientation with the inverse of the vessel's orientation. In effect this relative rotation then contains the roll, pitch and yaw of the vessel relative to the reference orientation.  
3. Take the inverse of the relative rotation. This has the effect of converting the relative rotation's roll, pitch and yaw back into absolute terms which can then be simply read from the X,Y,Z values of the quaternion.

a. I get confused because quaternions are used to store both rotations and orientations. That is because rotations and orientations are the same thing, it's the context/semantics that is different.
b. I still have not worked why Euler(90,0,0) is necessary in the MechJeb C# code, but is not necessary in kOS. I am aware that kOS "tweaks" some of the Unity API details, so maybe this is the explanation. 

Link to comment
Share on other sites

On 12/15/2017 at 10:34 PM, Boris-Barboris said:

Just a couple of tips that may or may not help:

Every game object in unity has a transform. Transform is probably (Unity is not open sourced) a tuple of parent transform, local translation vector, local scaling vector and local rotation quaternion. Cached global (wich take parent transform in mind) translation\scaling\rotation are usually maintained under the hood. Essentially, transform gives each object it's own euclidean space (consisting of origin and three axels), and each transform describes, how to get from global, universal unity euclidean space to this game object's space, and vice versa.

Now imagine a KSP aircraft. It has cockpit. Cockpit is a "control from here" part, it is a game object, it has it's own space, it has transform. KSP has these conventions:

  • "right" unity vector of cockpit's transform is an X axel of cockpit's euclidean space. It's usually directed towards your right hand\wing.
  • "up" is Y axel, it's usually the direction the plane\rocket is flying. When simple rocket is just spawned from VAB, it's command pod's "up" vector is directed towards zenith.
  • "forward" is Z axel, it's usually directed towards plane's belly.

Keep in mind Unity uses left-handed coordinate systems.
Now, if you take vector (1, 0, 0) in cockpit's space, wich corresponds to the direction of the right wing, and apply cockpit transform's rotation to it (by multiplying it on rotation quaternion), you will get the direction the right wing is facing in global unity reference frame (in KSP this frame is usually non-moving relative to closest's planet surface, and planetarium axis-aligned, iirc).

Now, there's a little gotcha in multiplication order in Unity, I'm sure sarbian will not mind this private message disclosure:
2uaPriZ.png

Thanks.  I assumed the convention of the Z axis being the direction the vessel points in was also used in KSP. Apparently not - I am a bit surprised but I am sure they has their reasons.

This explains why they need to rotate by Euler(90,0,0) in KSP, this is to align the way the vessel is pointing with the Z axis that the LookRotation defines (the lookat axis is the Z axis) . This is not required in kOS as it has already been done, the doco says the vessel "facing" direction is aligned with the Z axis.

I hope I got all this straight, the semantics are a bit wobbly in natural language, it might have been easier expressing it in mathematics, if I knew enough mathematics :-)

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...