Tensors, matrices, and MATLAB

A common source of confusion and error when dealing with different representations of rotations is to inadvertently juxtapose matrix and tensor notations. The resulting error can be further compounded when implementing rotations in computing environments such as MATLAB or Mathematica. Here, we attempt to clear up the source of this confusion. Our main point of emphasis is as follows. Given a rotation, we can use a matrix representation and express the rotation in terms of a matrix \mathsf{R}. Alternatively, we can represent the rotation using a rotation tensor {\bf Q}. We show that the components of these two quantities are related by

(1)   \begin{equation*} \left[ \begin{array}{c c c} R_{11} & R_{12} & R_{13} \\ R_{21} & R_{22} & R_{23} \\ R_{31} & R_{32} & R_{33} \end{array} \right] = \left[ \begin{array}{c c c} Q_{11} & Q_{12} & Q_{13} \\ Q_{21} & Q_{22} & Q_{23} \\ Q_{31} & Q_{32} & Q_{33} \end{array} \right]^T. \end{equation*}

We also address this correspondence in MATLAB implementations of rotations and discuss compound rotations. Because matrix representations of rotations commonly feature in computer codes, our remarks pertaining to compound rotations are also relevant to codes.

Rotation tensors and their equivalent rotation matrices

Consider a counterclockwise rotation through an angle \theta about an axis {\bf p}_3 that transforms the set of right-handed basis vectors \left\{{\bf p}_1, \, {\bf p}_2, \, {\bf p}_3\right\} into a new set of basis vectors \left\{{\bf t}_1, \, {\bf t}_2, \, {\bf t}_3\right\}. The transformation between the two bases is achieved by a rotation matrix \mathsf{R} and can be expressed in the following manners:

(2)   \begin{equation*} \left[ \begin{array} {c} {\bf t}_1 \\ {\bf t}_2 \\ {\bf t}_3 \end{array} \right] = \left[ \begin{array}{c c c} \cos(\theta) & \sin(\theta) & 0 \\ -\sin(\theta) & \cos(\theta) & 0 \\ 0 & 0 & 1 \end{array} \right] \left[ \begin{array}{c} {\bf p}_1 \\ {\bf p}_2 \\ {\bf p}_3 \end{array} \right] = \left[ \begin{array}{c c c} R_{11} & R_{12} & R_{13} \\ R_{21} & R_{22} & R_{23} \\ R_{31} & R_{32} & R_{33} \end{array} \right] \left[ \begin{array}{c} {\bf p}_1 \\ {\bf p}_2 \\ {\bf p}_3 \end{array} \right] = \mathsf{R} \left[ \begin{array}{c} {\bf p}_1 \\ {\bf p}_2 \\ {\bf p}_3 \end{array} \right]. \hspace{1in} \scalebox{0.001}{\textrm{\textcolor{white}{.}}} \end{equation*}

Notice that if \theta is negative, then the direction of the rotation becomes clockwise. The corresponding rotation matrix is the transpose of \mathsf{R} = \left[R_{ij}\right] (i, j = 1, \, 2, \, 3), denoted by \mathsf{R}^T. This inverse rotation is also observed when the new basis \left\{{\bf t}_1, \, {\bf t}_2, \, {\bf t}_3\right\} is transformed to the original basis \left\{{\bf p}_1, \, {\bf p}_2, \, {\bf p}_3\right\}:

(3)   \begin{equation*} \left[ \begin{array}{c} {\bf p}_1 \\ {\bf p}_2 \\ {\bf p}_3 \end{array} \right] = \mathsf{R}^T \left[ \begin{array}{c} {\bf t}_1 \\ {\bf t}_2 \\ {\bf t}_3 \end{array} \right]. \end{equation*}

Extrapolating from the above example, for a transformation corresponding to a rotation through an angle \theta about an axis {\bf r}, we can express the basis vectors \left\{{\bf t}_1, \, {\bf t}_2, \, {\bf t}_3\right\} as a linear combination of the vectors forming the basis \left\{{\bf p}_1, \, {\bf p}_2, \, {\bf p}_3\right\}:

(4)   \begin{equation*} {\bf t}_k = \sum_{j \, \, = \, 1}^{3} R_{kj} {\bf p}_j \quad (k = 1, \, 2, \, 3) . \end{equation*}

It is of interest here to compare the representation (4) to the corresponding representation using a rotation tensor. To this end, we consider the same transformation from \left\{{\bf p}_1, \, {\bf p}_2, \, {\bf p}_3\right\} to \left\{{\bf t}_1, \, {\bf t}_2, \, {\bf t}_3\right\} expressed using a rotation tensor {\bf Q}:

(5)   \begin{equation*} {\bf t}_k = {\bf Q} {\bf p}_k = \left( \sum_{i \, \, = \, 1}^{3} {\bf t}_i \otimes {\bf p}_i \right) {\bf p}_k. \end{equation*}

The components Q_{ij} of the rotation tensor {\bf Q} are defined by the representation

(6)   \begin{equation*} {\bf Q} = \sum_{i \, \, = \, 1}^{3} \sum_{j \, \, = \, 1}^{3} Q_{ij} {\bf p}_i \otimes {\bf p}_j. \end{equation*}

How are the components of the tensor {\bf Q} related to the components of the matrix \mathsf{R}? To compare and contrast (6) and (4), one can consider a vector {\bf p}_k acted upon by {\bf Q}. Observing that there are two equivalent representations for the transformation {\bf t}_k = {\bf Q}{\bf p}_k,

(7)   \begin{equation*} {\bf t}_k = \underbrace{\sum_{j \, \, = \, 1}^{3} R_{kj} {\bf p}_j}_{\textrm{From} \ (4)} = \underbrace{\sum_{i \, \, = \, 1}^{3} {Q}_{ik} {\bf p}_i}_{\textrm{From} \ (6)} = \sum_{j \, \, = \, 1}^{3} Q_{jk} {\bf p}_j. \end{equation*}

As a result, we can conclude that

(8)   \begin{equation*} R_{kj} = Q_{jk}. \end{equation*}

An alternative method to determine how the tensor components Q_{ik} relate to the matrix components R_{ik} is to start with (5) and (6) and then invoke (4) as follows:

(9)   \begin{equation*} {\bf Q} = \sum_{i \, \, = \, 1}^{3} \sum_{j \, \, = \, 1}^{3} Q_{ij} {\bf p}_i \otimes {\bf p}_j = \sum_{i \, \, = \, 1}^{3} {\bf t}_i \otimes {\bf p}_i = \sum_{i \, \, = \, 1}^{3} \left( \sum_{j \, \, = \, 1}^{3} R_{ij} {\bf p}_j \right) \otimes {\bf p}_i = \sum_{i \, \, = \, 1}^{3} \sum_{j \, \, = \, 1}^{3} R_{ji} {\bf p}_i \otimes {\bf p}_j. \hspace{1in} \scalebox{0.001}{\textrm{\textcolor{white}{.}}} \end{equation*}

Note the relabeling of the indices in the final representation. Comparing the final representation to the first in (9) yields the conclusion (8). Often, the components Q_{ij} of the rotation tensor {\bf Q} are written in the matrix form \left[Q_{ij}\right]. This matrix is easily confused with the rotation matrix {\mathsf R}. Because the rotation tensor is generally not assumed to be symmetric, this confusion will cause the direction of the rotation to be reversed.

To illustrate (8), let us return to the example of a rotation about an axis {\bf p}_3 through an angle \theta. Expressed as a tensor, this rotation has the representation

(10)   \begin{eqnarray*} {\bf Q} \!\!\!\!\! &=& \!\!\!\!\! \sum_{i \, \, = \, 1}^{3} {\bf t}_i \otimes {\bf p}_i = (\cos(\theta) {\bf p}_1 + \sin(\theta) {\bf p}_2) \otimes {\bf p}_1 + (-\sin(\theta) {\bf p}_1 + \cos(\theta) {\bf p}_2) \otimes {\bf p}_2 + {\bf p}_3 \otimes {\bf p}_3 \hspace{1in} \scalebox{0.001}{\textrm{\textcolor{white}{.}}} \\ \\ &=& \!\!\!\!\! \cos(\theta) ( {\bf p}_1 \otimes {\bf p}_1) + \sin(\theta) ({\bf p}_2 \otimes {\bf p}_1) -\sin(\theta) ({\bf p}_1 \otimes {\bf p}_2) + \cos(\theta) ({\bf p}_2 \otimes {\bf p}_2) + {\bf p}_3 \otimes {\bf p}_3. \end{eqnarray*}

The components of the rotation tensor {\bf Q} expressed as an array [Q_{ij}] are readily compared to the components of the corresponding rotation matrix \mathsf{R} in (2):

(11)   \begin{equation*} [Q_{ij}] = \left[ \begin{array}{c c c} \cos(\theta) & -\sin(\theta) & 0 \\ \sin(\theta) & \cos(\theta) & 0 \\ 0 & 0 & 1 \end{array} \right] = [R_{ji}] = {\mathsf R}^T. \end{equation*}

As expected, the relationship between the components of {\bf Q} and \mathsf{R} agrees with (8).

MATLAB implementation

One of the most convenient manners to represent vectors in MATLAB is to express them as column vectors. However, the downside of this approach is that we can only write the components of a vector {\bf V} in just one basis, say, \left\{{\bf p}_1, \, {\bf p}_2, \, {\bf p}_3\right\}:

(12)   \begin{equation*} \mathbf{V} = V_1 {\bf p}_1 + V_2 {\bf p}_2 + V_3 {\bf p}_3 \qquad \longleftrightarrow \qquad \texttt{V = [V1; V2; V3]}. \hspace{1in} \scalebox{0.001}{\textrm{\textcolor{white}{.}}} \end{equation*}

Consequently, if we wish to express the rotated vector {\bf v} = {\bf QV} as a column vector in MATLAB, we must write it in components relative to the basis \left\{{\bf p}_1, \, {\bf p}_2, \, {\bf p}_3\right\}. However, we can take advantage of the tensor representation

(13)   \begin{equation*} {\bf v} = \sum_{i \, \, = \, 1}^{3} v_i {\bf p}_i = {\bf Q} {\bf V} = \left( \sum_{i \, \, = \, 1}^{3} \sum_{j \, \, = \, 1}^{3} Q_{ij} {\bf p}_i \otimes {\bf p}_j \right) \left( \sum_{k \, \, = \, 1}^{3} V_k {\bf p}_k \right) = \sum_{i \, \, = \, 1}^{3} \sum_{j \, \, = \, 1}^{3} Q_{ij} V_j {\bf p}_i. \hspace{1in} \scalebox{0.001}{\textrm{\textcolor{white}{.}}} \end{equation*}

When implemented as a matrix-vector operation,

(14)   \begin{equation*} \left[ \begin{array}{c} v_1 \\ v_2 \\ v_3 \end{array} \right] = \sum_{j \, \, = \, 1}^{3} \left[ \begin{array}{c} Q_{1j} V_j \\ Q_{2j} V_j \\ Q_{3j} V_j \end{array} \right] = [Q_{ij}] \left[ \begin{array}{c} V_1 \\ V_2 \\ V_3 \end{array} \right] \qquad \longleftrightarrow \qquad \texttt{v = Q*[V1; V2; V3]} , \hspace{1in} \scalebox{0.001}{\textrm{\textcolor{white}{.}}} \end{equation*}

where {\texttt{Q}} is a 3 \times 3 array representing the matrix [Q_{ij}] of the components of the rotation tensor {\bf Q} such that \texttt{Q(i,j)} = Q_{ij}. Again, [Q_{ij}] should not be confused with the corresponding rotation matrix \mathsf{R}.

Compound rotations

Consider the following sequence of rotations associated with a 3-2-1 set of Euler angles: {\mathsf R}_3 through \psi about {\bf p}_3, then {\mathsf R}_2 through \theta about {\bf t}_2', and lastly {\mathsf R}_1 through \phi about {\bf t}_1. The rotation matrix \mathsf{R}_c that corresponds to the compound rotation is

(15)   \begin{equation*} \mathsf{R}_c = {\mathsf R}_1 {\mathsf R}_2 {\mathsf R}_3 = \left[ \begin{array}{c c c} 1 & 0 & 0 \\ 0 & \cos(\phi) & \sin(\phi) \\ 0 & -\sin(\phi) & \cos(\phi) \end{array} \right] \left[ \begin{array}{c c c} \cos(\theta) & 0 & -\sin(\theta) \\ 0 & 1 & 0 \\ \sin(\theta) & 0 & \cos(\theta) \end{array} \right] \left[ \begin{array}{c c c} \cos(\psi) & \sin(\psi) & 0 \\ -\sin(\psi) & \cos(\psi) & 0 \\ 0 & 0 & 1 \end{array} \right]. \hspace{1in} \scalebox{0.001}{\textrm{\textcolor{white}{.}}} \end{equation*}

The order of multiplication for the three matrices is important to note. We know from (8) that the array \left[ Q_{c_{ij}}\right] (i, j = 1, \, 2, \, 3) of the components of the associated rotation tensor {\bf Q}_c is related to the rotation matrix \mathsf{R}_c as follows:

(16)   \begin{equation*} \left[Q_{c_{ij}}\right] = \mathsf{R}_c^T = ({\mathsf R}_1 {\mathsf R}_2 {\mathsf R}_3)^T = {\mathsf R}_3^T {\mathsf R}_2^T {\mathsf R}_1^T = [R_{3,ij}]^T [R_{2,ij}]^T [R_{1,ij}]^T. \hspace{1in} \scalebox{0.001}{\textrm{\textcolor{white}{.}}} \end{equation*}

Explicitly,

(17)   \begin{equation*} \left[ \begin{array}{c c c} Q_{c_{11}} & Q_{c_{12}} & Q_{c_{13}} \\ Q_{c_{21}} & Q_{c_{22}} & Q_{c_{23}} \\ Q_{c_{31}} & Q_{c_{32}} & Q_{c_{33}} \end{array} \right] = \left[ \begin{array}{c c c} \cos(\psi) & -\sin(\psi) & 0 \\ \sin(\psi) & \cos(\psi) & 0 \\ 0 & 0 & 1 \end{array} \right] \left[ \begin{array}{c c c} \cos(\theta) & 0 & \sin(\theta) \\ 0 & 1 & 0 \\ -\sin(\theta) & 0 & \cos(\theta) \end{array} \right] \left[ \begin{array}{c c c} 1 & 0 & 0 \\ 0 & \cos(\phi) & -\sin(\phi) \\ 0 & \sin(\phi) & \cos(\phi) \end{array} \right]. \hspace{1in} \scalebox{0.001}{\textrm{\textcolor{white}{.}}} \end{equation*}

Thus, the compound rotation tensor {\bf Q}_c can be represented in MATLAB as a 3 \times 3 array \texttt{Qc} populated with the tensor components Q_{c_{ij}} such that \texttt{Qc(i,j)} = Q_{c_{ij}}, where \texttt{Qc} is easily constructed by the matrix multiplication in (17).