Given a unit vector find the two angles of rotation that aligns that vector with an axis Given a unit vector find the two angles of rotation that aligns that vector with an axis numpy numpy

Given a unit vector find the two angles of rotation that aligns that vector with an axis


Taking advantage of the fixed target alignment, this can be done in a straightforward manner with just trigonometry:

import mathdef to_y(x,y,z):  rx=-math.atan2(z,y)              # or +math.atan2(z,-y)  y2=y*math.cos(rx)-z*math.sin(rx) # -> (x,y2,0)  return rx,math.atan2(x,y2)

The rotations are defined as counterclockwise when looking at the origin from +x or +z (the right-hand rule); the rotation direction is always that with the smaller magnitude, but it may be possible to find a physically smaller rotation as indicated in the comment. Note that the input need not be normalized, and NaN is never produced (unless it appears in the input).


Hum, non-standard problem, required thinking a little.

Given v1 and v2 you want to rotate_z(rotate_x(v1, alpha), beta) to be on the same direction as v2.

We know that the aligned vector can be obtained by simply scaling scaling v2, this will gives x1,y3,z3 = v3 = v2 * |v1| / |v2|. Since rotation around z-axis, does not affect the z coordinate, we can determine alpha such that the z coordinate of rotate_x(v1, alpha) equals z3. After that we determine the angle beta to align place the X and Y coordinates properly

import numpy as npdef alignment_angles(v1, v2):    x1,y1,z1 = v1 # initial vector    x2,y2,z2 = v2 # reference vector    # magnitude of the two vectors    r1 = np.sqrt(x1**2 + y1**2 + z1**2)    r2 = np.sqrt(x2**2 + y2**2 + z2**2)    # this will be the result when aligning v1 to v2    # it has the magnitude of v1 and the direction of v2    x3,y3,z3 = x2*r1/r2, y2*r1/r2, z2*r1/r2    # the rotation in x must set the z coordinate to the    # final value, since the rotation over the z axis will    # not affect the z coordinate (this have two solutions)    rho1 = np.sqrt(z1**2 + y1**2)    if(abs(z3 / rho1) > 1):        raise ValueError('Cannot align these vectors')    alpha = np.arcsin(z3 / rho1) - np.arctan2(z1, y1);    # apply the rotation to make easier to calcualte the next stage    y1, z1 = (y1 * np.cos(alpha) - z1 * np.sin(alpha),               y1 * np.sin(alpha) + z1 * np.cos(alpha))    np.allclose(rho1, np.sqrt(z1**2 + y1**2))    #assert(np.allclose(z1, z3))    # now it is just a matter of aligning (x1, y1) to (x3, y3)    beta = np.arctan2(y3, x3) - np.arctan2(y1, x1)    x1, y1 = (x1 * np.cos(beta) - y1 * np.sin(beta),               x1 * np.sin(beta) + y1 * np.cos(beta))        # ensure the fotated v1 was correctly aligned    assert(np.allclose([x1, y1, z1], [x3, y3, z3]))        return alpha, beta

Then you just call

alignment_angles((1,2,3), (3,4,5))

or you can also use numpy arrays with 3 rows.

Initially I thought it would be an application of spherical coordinates, that would be the case if the axis for the second rotation was the z-axis rotated accordingly to the first rotation.

Edit

There are some vectors that cannot be aligned with a rotation on x and a rotation on y.Suppose you want to align the vector v1 = (1, 0, 0) to the vector v2 = (0, 0, 1) the rotation in x will not affect v1, it will always point in the direction x, then when you rotate around the z axis it will always be on the XY plan.

The example you gave was really giving the wrong answer because asin is not injective.

I changed the function to raise a value error when you cannot align the given vectors.