Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 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 /
avatar image
12
Question by robinking · Nov 26, 2010 at 12:36 PM · rotationquaternion

Problem finding relative rotation from one quaternion to another

I want to find a relative rotation between two quaternions quatA and quatB, i.e. quatC is a quaternion rotation that if applied to quatA would result in quatB. Basically I want something like this:

quatC = Quaternion.RelativeRotation( quatA, quatB );

The only way I can think of to do it is to make two Transforms modA and modB, with modB the child of modA, and use the following code:

modA.rotation = quatA;
modB.rotation = quatB;
quatC = modB.localRotation;

However I would prefer not to use Transforms, and just use quaternions instead.

This previous answer suggests the following code would work:

Quaternion rotationDelta = Quaternion.FromToRotation(modelA.transform.forward, modelB.transform.forward);

But it doesn't appear to work after all, as it only inputs two direction vectors, not rotations. To demonstrate this, attach the following script to a basic cube dragged into an empty scene. The code will position and size the cube.

Modify rotations for models A and/or B. Model C should display the RELATIVE rotation FROM A TO B. In other words, applying C's rotation to A's rotation should result in B's rotation.

Model D shows the ACTUAL result of applying C's rotation to A's rotation. If C showed the actual relative rotation, D would be identical to B. As you will see, this is NOT the case. Hopefully I'm just missing something, but if not, is there a way to get quatC only with code?

var modA : Transform; var modB : Transform; var modC : Transform; var modD : Transform; var D_Rot_Equals_B_Rot = true;

// Nothing in Start is important to the question, it just sets up // other objects to help demonstrate the problem function Start() { modA = transform; modA.gameObject.name = "Model A"; modA.position = Vector3(0,0,0); modA.rotation = Quaternion.identity; modA.localScale = Vector3(.1,.1,.8); modB = GameObject.CreatePrimitive(PrimitiveType.Cube).transform; modB.gameObject.name = "Model B"; modB.position = Vector3(1,0,0); modB.localScale = Vector3(.1,.1,.8); modC = GameObject.CreatePrimitive(PrimitiveType.Cube).transform; modC.gameObject.name = "Model C"; modC.position = Vector3(2,0,0); modC.localScale = Vector3(.1,.1,.8); modD = GameObject.CreatePrimitive(PrimitiveType.Cube).transform; modD.gameObject.name = "Model D"; modD.position = Vector3(3,0,0); modD.localScale = Vector3(.1,.1,.8); var bump : Transform; bump = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform; bump.gameObject.name = "Angle Helper"; bump.localScale = Vector3(.2,.2,.2); bump.position = Vector3(0,.15,-.3); bump.parent = modA; bump = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform; bump.gameObject.name = "Angle Helper"; bump.localScale = Vector3(.2,.2,.2); bump.position = Vector3(1,.15,-.3); bump.parent = modB; bump = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform; bump.gameObject.name = "Angle Helper"; bump.localScale = Vector3(.2,.2,.2); bump.position = Vector3(2,.15,-.3); bump.parent = modC; bump = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform; bump.gameObject.name = "Angle Helper"; bump.localScale = Vector3(.2,.2,.2); bump.position = Vector3(3,.15,-.3); bump.parent = modD; }

function Update () {

 // Modify rotations for models A and/or B.
 // Model C should display the RELATIVE rotation FROM A TO B.
 // In other words, applying C's rotation to A's rotation should result in B's rotation.
 // Model D shows the ACTUAL result of applying C's rotation to A's rotation.
 // If C showed the actual relative rotation, D would be identical to B.
 // As you will see, this is NOT the case.

 modC.rotation = Quaternion.FromToRotation(modA.forward, modB.forward);
 modD.rotation = modA.rotation * modC.rotation;

 if (modD.rotation==modB.rotation) {
     D_Rot_Equals_B_Rot = true;
 } else {
     D_Rot_Equals_B_Rot = false;
 }

}

Comment
Add comment
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

4 Replies

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

Answer by Mike 3 · Nov 26, 2010 at 12:57 PM

This should do it:

Quaternion relative = Quaternion.Inverse(a) * b;
Comment
Add comment · Show 13 · 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 robinking · Nov 27, 2010 at 05:23 PM 1
Share

Nearly! I tested it both ways and it's actually the other way round - "Quaternion relative = Quaternion.Inverse(a) * b;" works a charm. Thanks! I'll tick this answer, maybe you could update it?

avatar image Mike 3 · Nov 27, 2010 at 05:50 PM 0
Share

Oh strange, I tested that like 5 times, I must have had a thinko when I wrote it in here. Fixing it now

avatar image Mahamed9628 · Mar 30, 2012 at 08:44 AM 0
Share

Thanks! It helped me too. I used to have headache from some problem with planets, and had been suffered with that for weeks, and with this solution anything got to work. Thanks again.:)

avatar image Max-Pixel · Nov 29, 2014 at 07:23 PM 1
Share

Weird, I wonder why in Unity the from is inverted and comes first, while in regular mathematics (at least according the the following link), the from is still inverted but comes last. http://stackoverflow.com/questions/1755631/difference-between-two-quaternions

avatar image Slugslinger · Jan 17, 2016 at 02:49 PM 1
Share

I have the same doubt that @$$anonymous$$ax-Pixel, can someone explain why in Unity we put the Inverse first? Is this really correct or the Inverse in last can work as well?

Show more comments
avatar image
0

Answer by HonoraryBob · Jul 06, 2018 at 09:53 PM

I tried to use the suggested code, but for some reason the result is always (0,0,0,1) even when there is a difference between the two quaternions as proven by using debug.log. Here's the code I'm using:

 var ThisRot:Quaternion = transform.rotation;
 var RotChange:Quaternion =  Quaternion.Inverse(LastRot) * ThisRot;
 Debug.Log("LastRot ="+LastRot+" ThisRot="+ThisRot+" RotChange="+RotChange);
 LastRot = ThisRot;

Anyone know why this doesn't work?

[Edit: it turns out that it only seemed it didn't work because when Debug.Log prints out quaternions there's a one-digit limit for the fractional value, which means small angles don't show up.]

Comment
Add comment · 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
0

Answer by LarryTheBrave · Apr 27, 2019 at 05:24 PM

I would convert the rotations to Euler Angles, do a Vector3 difference, then convert back to Quaternions. This can be done with .eulerAngles against the transform.rotation and then Quaternion.Euler outside the parentheses enclosing the Vector3 subtraction. To simply get the angle you can do Quaternion.Angle.

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 Owen-Reynolds · Aug 21, 2019 at 11:01 PM 0
Share

Surprisingly, this is wrong. It makes sense, but it's completely not-even-close wrong. If you have two eulerAngle rotations, the inverse is not Quaternion.Euler(difference-in-xyz's). Put another way q1*(difference in xyz's) != q2. Not the other way around, either. You can test by computing the inverse and printing the euler angles.

It's because in q1*q2, q2 is on the local axis of the q1. If you went 20 on the real y, you can't cancel it by going -20 on the local y.

avatar image
0

Answer by n-gist · Feb 13 at 12:35 AM

"quaternion rotation that if applied to quatA would result in quatB" is:

 quatB * Quaternion.Inverse(quatA)

Here is how you can check it:

 var quatA = Quaternion.Euler(10, 10, 10);
 var quatB = Quaternion.Euler(15, 20, 25);
 var relative1 = quatB * Quaternion.Inverse(quatA);
 var relative2 = Quaternion.Inverse(quatA) * quatB;
 var check1 = relative1 * quatA;
 var check2 = relative2 * quatA;

 Debug.Log(relative1.eulerAngles);
 Debug.Log(relative2.eulerAngles);
 Debug.Log("check relative1 " + check1.eulerAngles);
 Debug.Log("check relative2 " + check2.eulerAngles);

Output:

 (7.75, 7.65, 13.43) // Just to show that
 (6.75, 8.66, 13.34) // order is important
 check relative1 (15.00, 20.00, 25.00) // Correct one, equal to quatB
 check relative2 (14.04, 20.95, 24.69)
Comment
Add comment · 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

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

15 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Workaround for Quaternion.eulerAngles 360 Degree Limit? 1 Answer

Object not rotating when the associated trigger is triggered 1 Answer

How can I get the rotation between two objects 1 Answer

Rotate object following mouse movement. Object jumps/ flips 1 Answer

Quaternion.FromToRotation misunderstanding 2 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