rot_a_to_b๏ƒ

plasmapy.formulary.mathematics.rot_a_to_b(a: ndarray, b: ndarray) ndarray[source]๏ƒ

Calculates the 3D rotation matrix that will rotate vector a to be aligned with vector b.

Parameters:
  • a (ndarray, shape (3,)) โ€“ Vector to be rotated. Should be a 1D, 3-element unit vector. If a is not normalized, then it will be normalized.

  • b (ndarray, shape (3,)) โ€“ Vector representing the desired orientation after rotation. Should be a 1D, 3-element unit vector. If b is not normalized, then it will be.

Returns:

R โ€“ The rotation matrix that will rotate vector a onto vector b.

Return type:

ndarray, shape (3,3)

Raises:

ValueError โ€“ If the argument is not of shape (3,).

Notes

The rotation matrix is calculated as follows. Let

\[\vec v = \vec a ร— \vec b\]

and let \(ฮธ\) be the angle between \(\vec a\) and \(\vec b\) such that the projection of \(\vec a\) along \(\vec b\) is

\[c = \vec a ยท \vec b \cos{ฮธ}\]

Then the rotation matrix \(R\) is

\[R = I + v_x + v_x^2 \frac{1}{1 + c}\]

where \(I\) is the identity matrix and \(v_x\) is the skew-symmetric cross-product matrix of \(v\) defined as

\[\begin{split}v_x = \begin{bmatrix} 0 & -v_3 & v_2 \\ v_3 & 0 & -v_1 \\ -v_2 & v_1 & 0 \end{bmatrix}\end{split}\]

Note that this algorithm fails when \(1+c=0\), which occurs when \(a\) and \(b\) are anti-parallel. However, since the correct rotation matrix in this case is simply \(R=-I\), this function just handles this special case explicitly.

This algorithm is based on this discussion on StackExchange.

Examples

>>> a = np.array([0., 1., 0.])
>>> b = np.array([1., 0., 0.])
>>> rot_a_to_b(a, b)
array([[ 0., -1.,  0.],
       [ 1.,  0.,  0.],
       [ 0.,  0.,  1.]])
>>> a = np.array([-0.14, 2.2, 3.98])
>>> b = np.array([9.10, 4.17, -9.35])
>>> rot_a_to_b(a, b)
array([[ 0.20118147, -0.9613676 , -0.18787857],
       [-0.30014001,  0.12207629, -0.94605145],
       [ 0.93243873,  0.2467179 , -0.2639854 ]])