Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
1
Question by lgbeno · Mar 31, 2016 at 10:02 PM · rotationtransformquaternion

Verifying Euler to Quaternion calculations

I'm new to Quaternions so to learn more about them I decided to read up on various resources and try to construct my own elementary Quaternion library in python and then validate it with results from Unity.

So what I do is create a new project and place a cube in space. I then add to that cube a new script that simply copies its transform.rotation to a public variable that I call "myQuaternion". A snippet of the innards of the script are:

 public Quaternion myQuaternion;
 
 void Update() {
   myQuaternion = transform.rotation;
 }

So that seems to be working as expected, I can inspect the cube, change its rotation and get different values in myQuaternion. Great.

So now based on this wikipedia section: https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Conversion

I create this python function:

 def euler_to_quaternion(phi,theta,psi):
     return [math.cos(math.pi*phi/360)*math.cos(math.pi*theta/360)*math.cos(math.pi*psi/360)+
             math.sin(math.pi*phi/360)*math.sin(math.pi*theta/360)*math.sin(math.pi*psi/360),
             math.sin(math.pi*phi/360)*math.cos(math.pi*theta/360)*math.cos(math.pi*psi/360)-
             math.cos(math.pi*phi/360)*math.sin(math.pi*theta/360)*math.sin(math.pi*psi/360),
             math.cos(math.pi*phi/360)*math.sin(math.pi*theta/360)*math.cos(math.pi*psi/360)+
             math.sin(math.pi*phi/360)*math.cos(math.pi*theta/360)*math.sin(math.pi*psi/360),
             math.cos(math.pi*phi/360)*math.cos(math.pi*theta/360)*math.sin(math.pi*psi/360)-
             math.sin(math.pi*phi/360)*math.sin(math.pi*theta/360)*math.cos(math.pi*psi/360)]

So now I run some tests:

For rotation (45,0,0):

  • Unity: w=0.9238795325112867 x=0.3826834323650898 y=0.0 z=0.0

  • Python: w=0.9238795325112867 x=0.3826834323650898 y=0.0 z=0.0

Looks good, they match

For rotation (0,45,0):

  • Unity: w=0.9238795325112867 x=0.0 y=0.3826834323650898 z=0.0

  • Python: w=0.9238795325112867 x=0.0 y=0.3826834323650898 z=0.0

Again, a match

For rotation (0,0,45):

  • Unity: w=0.9238795325112867 x=0.0 y=0.0 z=0.3826834323650898

  • Python: w=0.9238795325112867 x=0.0 y=0.0 z=0.3826834323650898

Again, a match

So here's the problem:

For rotation (0,45,45):

  • Unity: w=0.8535533905932737 x=0.14644660940672624 y=0.3535533905932738 z=0.3535533905932738

  • Python: w=0.8535533905932737 x=-0.14644660940672624 y=0.3535533905932738 z=0.3535533905932738

So the polarity for the value of x is different, not good...

For rotation (45,45,0):

  • Unity: w= 0.8446231986207332 x=0.46193976625564337 y=0.1913417161825449 z=0.1913417161825449

  • Python: w= 0.8446231986207332 x= 0.1913417161825449 y=0.46193976625564337 z= 0.1913417161825449

Now things look even more confusing, any idea what is going on?

Update: Doing more research and working through this issue, I've discovered that order of operations is very important when doing rotations. I found that I needed to break the rotations into 3 separate quaternions and then multiply them in a specific order, here's some additional python code:

 def quaternion_mult(q,r):
     return [r[0]*q[0]-r[1]*q[1]-r[2]*q[2]-r[3]*q[3],
             r[0]*q[1]+r[1]*q[0]-r[2]*q[3]+r[3]*q[2],
             r[0]*q[2]+r[1]*q[3]+r[2]*q[0]-r[3]*q[1],
             r[0]*q[3]-r[1]*q[2]+r[2]*q[1]+r[3]*q[0]]
 
 def unity_euler_to_quaternion(x,y,z):
     return quaternion_mult(quaternion_mult(euler_to_quaternion(0,y,0),
                                            euler_to_quaternion(x,0,0)),
                                            euler_to_quaternion(0,0,z))

Now when I do a unity_euler_to_quaternion(45,45,45), the answers match.

Whew!

Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Eno-Khaon · Mar 31, 2016 at 10:35 PM 0
Share

Ahh, yep. Looks like you did find what you were looking for. As an additional resource for others who may come across this:

The x, y, and z angles represent a rotation z degrees around the z axis, x degrees around the x axis, and y degrees around the y axis (in that order).

http://docs.unity3d.com/ScriptReference/Transform-eulerAngles.html

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Bunny83 · Mar 31, 2016 at 11:47 PM

Well, as you figured out yourself the order in which you apply the rotations matters. There is not just one valid euler angles representation. Unity uses the order Z-X-Y around worldspace axes. To express this combination by rotations around localspace axes you just need to reverse the order. So it's the same as Y-X-Z around the localspace axes.

I haven't looked at the conversion used on the wikipedia page, but i guess it's X-Y-Z or Z-Y-X so you need a different order of your rotations. That means the combination of all those sin / cos will look different.

You shouldn't use your "euler_to_quaternion" method inside your "unity_euler_to_quaternion" method. You do way to many calculations that way. You should first implement the AngleAxis method. I don't really know python so here's a C# example:

 public static Quaternion AngleAxis(float aAngle, float aX, float aY, float aZ)
 {
     float s = Mathf.Sin(aAngle/2f);
     return new Quaternion(Mathf.Cos(aAngle/2f), aX*s, aY*s, aZ*s);
 }

This method should create a quaternion rotation of "aAngle" radians around the normalized axis defined by (aX,aY,aZ)

To create your 3 rotations you would simply use:

 AngleAxis(x, 1f,0, 0 );
 AngleAxis(y, 0, 1f,0 );
 AngleAxis(z, 0, 0, 1f);

Finally multiply them in the right order. Keep in mind that you can calculate the combined result in one go just like the example on the wikipedia page. However i would recommend to cache each sin / cos value in a local variable. At the moment inside your "euler_to_quaternion" method you calculate each sin and cos value 4 times.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image lgbeno · Apr 01, 2016 at 12:57 PM 0
Share

Thanks! For the first cut of code, I wanted to write something as loyal to the reference as possible, not thinking about efficiency. Once it has proven itself, I'll go in and optimize and validate against the first version of inefficient code.

It would be excellent to distill the Sin & Cos combinations for the Unity style rotations so that I did not need to multiply Quaternions at all. That might take a few sheets of paper :)

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

Quaternion Rotation - AngleAxis/EulerAngle 2 Answers

How to preserve Y rotation while setting transform.up? 1 Answer

Rotating Vector3, linecast 1 Answer

How to know whether the two object parallel intersected or perpendicularly intersected ?? 0 Answers

Can't really grasp how to keep my player level on X and Z while using LookRotation 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges