3
$\begingroup$

I tried to calculate the angle between two vectors.

First 3 Quaternion rotations (qx,qy,qz) are defined and multiplied to q. A vector v (1,0,0) is rotated by q.

From the vectors q and qrot I want to recreate the original roation qcalc but the x-value of qcalc is always 0.

from math import cos,sin,radians,degrees,sqrt
from mathutils import Quaternion,Vector

def eprint(e):
    print("euler X=%f Y=%f Z=%f" % (degrees( e.x ),degrees( e.y ),degrees( e.z )))    


qx =  Quaternion((1.0, 0.0, 0.0), radians( 15.0 )) # <--- has no influence to the result
qy =  Quaternion((0.0, 1.0, 0.0), radians( 30.0 ))
qz =  Quaternion((0.0, 0.0, 1.0), radians( 45.0 ))
q = qz * qy *qx
#q = qx * qy *qz
print("-"*40)
eprint(q.to_euler('XYZ'))
print(str(q))

v = Vector(( 1.0 , 0.0 , 0.0 ))
print("v=" + str(v))
vrot =  q * v 
print("vrot=" + str(vrot))
qcalc = v.rotation_difference( vrot )
eprint( qcalc.to_euler( 'XYZ' ))
print(str(qcalc))

prints

----------------------------------------
euler X=14.999997 Y=30.000008 Z=45.000005
<Quaternion (w=0.8977, x=0.0183, y=0.2853, z=0.3353)>
v=<Vector (1.0000, 0.0000, 0.0000)>
vrot=<Vector (0.6124, 0.6124, -0.5000)>
euler X=12.666476 Y=30.000008 Z=45.000008
<Quaternion (w=0.8979, x=-0.0000, y=0.2784, z=0.3410)>

It doesn't matter which value for x-rotation is used for qx the result is always X=12.666471 why is that? The Quaternion should be WXYZ: .898, .018, .285, .335

I verified the rotation order in the console with enabled mathvis addon:

# show quaternion rotation order
qx =  Quaternion((1.0, 0.0, 0.0), radians( 15.0 ))
qy =  Quaternion((0.0, 1.0, 0.0), radians( 30.0 ))
qz =  Quaternion((0.0, 0.0, 1.0), radians( 45.0 ))
q = qz * qy *qx
qx = qy = qz = None
o = Vector((0,0,0))
right = Vector((1,0,0))
r2 = q * right
r3 = [o,r2]

enter image description here

Another implementation I've adapted from ogre has the same issue (x-rot in quaternion is 0)

# https://bitbucket.org/sinbad/ogre/src/9db75e3ba05c/OgreMain/include/OgreVector3.h?fileviewer=file-view-default#cl-651
def rotation_between2( u,  v):
    cross = u.cross(v)
    cross.normalize()
    ul2 = u.length * u.length
    vl2 = v.length * v.length
    d = u.dot(v)
    l = d / sqrt(ul2 * vl2) 
    w = acos(l)
    q = Quaternion( cross , w )
    q.normalize()
    return q
$\endgroup$

1 Answer 1

2
$\begingroup$

The issue is the test data, the vector v = Vector(( 1.0 , 0.0 , 0.0 )) lies exactly on the x-axis and a rotation around x has absolutely no effect, therefore the information is lost.

In order to get the rotation from v to vrot it is requiresd to invoke rotation_difference() on v insteadof vrot.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .