Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 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
5
Question by dansav · Jul 22, 2012 at 04:17 AM · quaternioncomparedebug.log

how do I compare Quaternions?

I'm trying to compare two rotations. I'm checking to see if they are equal like this

 if(rot==prevrot){
 dosomething;
 }
 else{
 dosomethingelse
 }


Here's an example of the Debug.Log of two that were not equal according to the if statement. But look at the output...

 prevrot=(0.0, 0.0, 0.0, 1.0) rot=(0.0, 0.0, 0.0, 1.0)

Why doesn't the Debug.Log output match the if statement?

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

6 Replies

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

Answer by ScroodgeM · Jul 22, 2012 at 06:32 AM

internally quaternion stored as 4 floats, so two quaternions can be different but both logs as (0,0,0,1) due to precision of float.

http://docs.unity3d.com/Documentation/ScriptReference/Quaternion.Angle.html

use this to compare two rotations by angle between them - for example if angle is lower then some threshold then these quaternions are same

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 dansav · Jul 22, 2012 at 07:22 AM 0
Share

Thanks for the clear explanation and solutions.

avatar image
3

Answer by silentreaver · Oct 09, 2019 at 10:45 AM

Just to formalise @reddtoric's answer into something you can use:

 public static bool Approximately(this Quaternion quatA, Quaternion value, float acceptableRange)
 {
      return 1 - Mathf.Abs(Quaternion.Dot(quatA, value)) < acceptableRange;
 }   

That'll extend the Quaternion class so you can use it in future to compare two quaternions

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
2

Answer by SoxwareInteractive · Jan 02, 2017 at 09:23 AM

You should note that Quaternion.Angle() will sometimes not return 0 even though the Quaternions are an exact copy of each other. The same applies for the "==" equality operator of quaternions.

 Quaterion q2 = q1;
 
 if (q1 == q2)
 {
    Debug.Log("That's what you would expect!");
 }
 else
 {
    // Please note that the result depends on the value q1 has.
    Debug.Log("That's what happens!");
 }

This is due to floating point errors introduced by the Mathf() functions used in the implementations of Quaternion.Angle() and the equality operator. The equality operator for example uses the dot product of the two quaternions to compare them.

The Equal() method on the other hand compares each element of the quaterion (x, y, z, w) binary wise. So when you have exact copies it is guaranteed to return true. But it will have troubles if the 2 quaternions are really close to each other but due to some floating point rounding errors they may be binary wise not exactly the same. That's when the equality operator does a better job.

So something like this would combine the best of both:

 public bool QuaternionsEqual(Quaternion q1, Quaternion q2)
 {
    return (q1.Equals(q2) || (q1 == q2));
 }

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
2

Answer by winxalex · Sep 30, 2017 at 06:14 PM

  public static bool Approximately(Quaternion val, Quaternion about, float range) {
             return Quaternion.Dot(val,about) > 1f-range;
         }
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 ackleyrc · Mar 10, 2018 at 03:39 AM 0
Share

This worked for me, although I did have to use the absolute value of the dot product as it sometimes returns the opposite sign

avatar image
1

Answer by reddtoric · Jul 12, 2019 at 04:46 AM

Improvement on winxalex's answer

  • More understandable variable names and some explanation.

  • If anyone has any suggestions to a better solution for the precision variable, please chime in. For example, a float representing the angle of acceptance across all 3 axes rather than what it is now. (I usually use 0.01f or 0.001f to check approx. but in this case for 1 degree on 1 axis results in 0.0000004f difference which is very small and I don't go that small but the results isn't what I want.

If okay with 1 degree difference on 1 axis:

 bool isQ1Q2Exact = isApproximate(q1, q2, 0.0000004f);


 public static bool isApproximate(Quaternion q1, Quaternion q2, float precision)
 {
     return Mathf.Abs(Quaternion.Dot(q1, q2)) >= 1 - precision;
 }


Quaternion.Dot method returns a value between 1 and -1. If it returns 1 or -1, it means the 2 quaternions are "exact". It's like 0 degrees and 360 degrees. If it returns 0, it is far from exact. Closer to Mathf.Abs(1) means more exact. Closer to 0 means further from exact.

 Quaternion zero = Quaternion.identity;
 
 // returns 0.9999996 => precision = 0.0000004
 Quaternion tenthDegree1Axis = Quaternion.Euler(0.1f, 0, 0);
 float veryClose = Quaternion.Dot(zero, tenthDegree1Axis);
 
 // returns 0.9999619 => precision = 0.0000381
 Quaternion oneDegree1Axis = Quaternion.Euler(1f, 0, 0);
 float alsoVeryClose = Quaternion.Dot(zero, oneDegree1Axis);
 
 // returns -4.371139E-08 ≈ 0
 Quaternion _180Degree1Axis = Quaternion.Euler(180f, 0, 0);
 float farFromClose = Quaternion.Dot(zero, _180Degree1Axis);
 
 // returns => 0.5
 Quaternion _90Degree2Axis = Quaternion.Euler(90f, 90f, 0);
 float alsoFarFromClose = Quaternion.Dot(zero, _90Degree2Axis);
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
  • 1
  • 2
  • ›

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

12 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

Related Questions

preventing errors by calling Debug.Log on a property 1 Answer

How to compare rotation position with an Int value (2D game) 1 Answer

Setting world rotation in a Quaternion 1 Answer

Workaround for Quaternion.eulerAngles 360 Degree Limit? 1 Answer

Snap a direction vector 1 Answer


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