2
$\begingroup$

i have a hard time figuring out why i get an axis flip when i try to convert the second matrix to quaternion. First matrix (f1) gives me positive quaternion values while the second matrix (f2) gives me negative values in x, y, and z. If i convert to euler instead, the values are stable ... Am i doing something wrong?

Thanks alot for your help!

from mathutils import Matrix

print("\n")

f1 = ((-0.8030, 0.2867, 0.5255, 1),
      ( 0.2980,-0.5660, 0.7686, 1),
      ( 0.5161, 0.7729, 0.3691, 1),
      ( 0.0000, 0.0000, 0.0000, 1))

f2 = ((-0.8153, 0.3279, 0.4773, 1),
      ( 0.2633,-0.5243, 0.8098, 1),
      ( 0.5158, 0.7859, 0.3412, 1),
      ( 0.0000, 0.0000, 0.0000, 1))

matrix_f1 = Matrix(f1)
matrix_f2 = Matrix(f2)

quat_f1 = matrix_f1.to_quaternion()
quat_f2 = matrix_f2.to_quaternion()
euler_f1 = matrix_f1.to_euler()
euler_f2 = matrix_f2.to_euler()

print(quat_f1)
print(quat_f2)
print(euler_f1)
print(euler_f2)

enter image description here

$\endgroup$
2
$\begingroup$

No, you are not doing anything wrong. It is rotation expressed as a normalized 4-dimensional vector. Do not worry about the values there, if they need to be negative that is fine - it is still a representation of the same rotation, it is only expressed in a way that makes some math easier. It is really hard to make sense of quaternion values just by looking at them.

You can make a plane and test the rotations on it. You need to set the rotation mode to quaternion in the n panel to be able to change bpy.context.object.rotation_quaternion and see it on the object. If you create another plane and run the script again changing the rotation in euler mode for bpy.context.object.rotation_euler instead, you will see the rotations match despite the negative values that happen to exist in a normalized 4-dimentional vector notation of the rotation. You can add this to the end of your code to see this. You will need a new object created and selected as the active object:

import bpy   
#bpy.context.object.rotation_quaternion = quat_f2
bpy.context.object.rotation_euler = euler_f2

You will be able to observe floating point/binary conversion precision errors if you decide to compare the results of quaternion to euler conversions by the numerical values doing something like this:

print( quat_f2.to_euler() )
print( euler_f2 )

The rotations are the same. Numbers differ because of the precision errors during the calculations. That is normal.

If you need to interpolate between the quaternions you face a problem that the same rotaion can be expresed with a negative and a positive quaternion and it is possible to rotate the long way or the short way around to the same rotation. If I am reading this correctly, the short path would be between two quaternions the dot product of which would be positive, so you can check if your current rotation from the previous is the short one evaluating if the dot product of the quaternions is negative or positive and then negate your current quaternion if needed:

if quat_f1.dot(quat_f2) < 0:
    quat_f2.negate()
| improve this answer | |
$\endgroup$
  • $\begingroup$ Thank you very much for your answer Martin, i really appreciate it! I should have been more clear though, i am writing an importer for a custom camera file format. The file contains a 4x4 matrix per frame. I set the .matrix_world of the new camera accordingly and set the keyframe in quaternion rotation mode. Position and orientation are working as expected. The problem is that if the quaternions switch to negative from one frame to another the camera rotates around all axis and the motion blur is going crazy. Euler works but fails on other frames. Any ideas? $\endgroup$ – ManuelGrad Sep 4 '18 at 20:32
  • $\begingroup$ I think the edited answer should help. $\endgroup$ – Martynas Žiemys Sep 4 '18 at 21:58
  • $\begingroup$ This worked out perfectly! Thank you very much for your help Martin! $\endgroup$ – ManuelGrad Sep 5 '18 at 10:27
  • 2
    $\begingroup$ @ManuelGrad If this answer solved your problem, please mark it as accepted by clicking the checkmark on the top left of the answer. $\endgroup$ – Leander Apr 18 '19 at 11:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.