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$
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.

| improve this answer | |
$\endgroup$

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.