Search code examples
python-3.xnumpyvectorscipylinear-algebra

Find angular components between 2 vectors


How to find angle between 2 vector using python, preferably numpy or scipy; in terms of components of rotation about x,y,z axes?

For example in the code below, utilizing this, we can find the angle between 2 vectors.

import numpy as np

a = np.array([5,7,5])-np.array([1,2,3])
b = np.array([3.25842, 8.14983, 4.44192])-np.array([1,2,3])

def angle(v1, v2, acute):
    angle = np.arccos(np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2)))
    if (acute == True):
        return angle
    else:
        return 2 * np.pi - angle

print(np.rad2deg(angle(v1=a, v2=b, acute=True)))
# returns: 18.531657948873978

Desired angles are alpha_ x,y,z components.

enter image description here


Solution

  • I would suggest using the SciPy Rotation API.

    If you have two vectors, you can find the rotation between them with Rotation.align_vectors(). SciPy then gives you six choices for how to represent the rotation. (See the documentation, and the six methods beginning with as_, for a list of which output formats you can use.)

    The one which seems most similar to your question is Euler angles.

    Example:

    from scipy.spatial.transform import Rotation
    rot, rssd = Rotation.align_vectors(a, b)
    print(rot.as_euler('XYZ', degrees=True))
    

    Output:

    [  6.7385178    0.60887791 -17.29830824]
    

    Notes:

    • as_euler() accepts an order of angles, and doing the rotations in a different order can give different results. I recommend reading the Wikipedia page to understand why.
    • as_euler() gives you a choice between intrinsic and extrinsic rotation angles. Use rot.as_euler('xyz', degrees=True) for extrinsic angles.
    • The rssd variable returned by align_vectors() represents distance between vectors after the rotation. See docs for more.