Unless otherwise stated, the active rotation convention introduced in Section 21.1 is used throughout this section.
Euler's rotation theorem states: “in three-dimensional space, any displacement of a rigid body such that a point on the rigid body remains fixed, is equivalent to a single rotation about some axis that runs through the fixed point”, [1]. It also follows that the composition of two rotations is a rotation.
In the middle of the nineteenth century (1840) the French mathematician Olinde Rodrigues demonstrated the formula for composition of large rotations, [2]. Let’s consider two rotations:
rotation (a) of angle α around the unit vector l: a=(l,α), and
rotation (b) of angle β around the unit vector m: b=(m,β).
The composition of these two rotations gives the rotation of angle γ around the unit vector n: c=(n,γ).
The result of composition:
c=a∘bor(n,γ)=(l,α)∘(m,β)
The composition of finite rotations is not commutative; the result depends on the order of application of the rotations! In the composition considered here, rotation (b) is applied first and rotation (a) second. The angle γ and the unit vector n are:
More elegant expressions are obtained if we represent rotations as quaternions. More about quaternions in [3], [4]. Throughout this section, quaternions are written in scalar-first form. Let’s define two quaternions a and b as:
Quaternions may also be considered as an extension of complex numbers and they can be written like this:
a=a0+a1i+a2j+a3k
Composition of two rotations is equivalent to the multiplication of two quaternions written in this form and considering these basic multiplication rules:
This result is identical to (**). The product of two quaternions is not commutative!
The conjugate of:
a=a0+a1i+a2j+a3k
is:
a∗=a0−a1i−a2j−a3k
and:
aa∗=∣a∣2=a02+a12+a22+a32
03
Rotation representations
There are several ways to describe a rotation; four of them are considered here.
The most common and most used is the rotation matrix R (see Section 21.1). The composition of two rotations R1 and R2 (R1 is applied first) is:
R=R2R1
The axis-angle representation describes a rotation of angle φ and direction defined by the unit vector n=(nxnynz)T. Using the notation introduced in Section 21.1, the vector form is:
ρ=φn,∥ρ∥=φ.
Here ρ is a three-component rotation vector. The axis-angle parameter form is:
r=[nxnynzφ].
This is a four-parameter axis-angle array, as used by MATLAB functions such as axang2rotm and rotm2axang. The two forms contain the same physical information but are not the same mathematical object.
The equivalent rotation matrix (see Section 21.1) is expressed in axis-angle parameters:
MATLAB commands to convert different rotation representations are listed below. For the relationship between quaternions and Tait–Bryan angles, see also [5].
The MATLAB functions listed below use the active rotation convention adopted in Section 21.1. For Euler-angle conversions, MATLAB uses the intrinsic “ZYX” sequence by default, corresponding to yaw–pitch–roll. This is the same axis order used in Section 21.2; however, because Section 21.2 uses the global-to-local matrix convention, the corresponding rotation matrix is the transpose of MATLAB’s active rotation matrix.
The legacy functions vrrotmat2vec and vrrotvec2mat are deprecated and scheduled for removal. The modern functions rotm2axang and axang2rotm should be used instead.
05
Example
Let's consider two rotations:
a) α=4π around the direction defined by the vector d1=[132]. Direction cosines: l=d1/∥d1∥.
b) β=3π around the direction defined by the vector d2=[2−11]. Direction cosines: m=d2/∥d2∥.
The composition of these two rotations, first rotation (a) and then rotation (b), can be performed with these MATLAB programs:
The function R2axa treats γ≈0, 0<γ<π and γ≈π separately, clips the argument of acos to [−1,1], and normalizes the recovered axis:
R2axa.m
function r=R2axa(R)
%*** R2axa ***
% Convert an active rotation matrix to principal axis-angle form.
tol=1e-12;
c=(trace(R)-1)/2;
c=max(-1,min(1,c));
ga=acos(c);
w=[R(3,2)-R(2,3) R(1,3)-R(3,1) R(2,1)-R(1,2)]/2;
sn=norm(w);
if ga<1e-7
if sn<tol
r=[1 0 0 0];
return
end
ga=atan2(sn,c);
n=w/sn;
elseif pi-ga<1e-5
% Recover the axis without division by sin(ga).
A=(R+R'+2*eye(3))/4;
[~,k]=max(diag(A));
n=zeros(1,3);
n(k)=sqrt(max(A(k,k),0));
j=setdiff(1:3,k);
n(j)=A(j,k)'/n(k);
if dot(n,w)<0; n=-n; end
ga=atan2(sn,c);
else
n=w/sin(ga);
end
n=n/norm(n);
r=[n ga];
end
The result is: rc=[0.57660.02310.81671.3547], that is:
The function quat2axa normalizes the quaternion and selects the sign with q0≥0. It protects the argument of acos, treats zero rotation explicitly, and returns the principal angle 0≤γ≤π:
quat2axa.m
function r=quat2axa(q)
%*** quat2axa ***
% Convert a scalar-first quaternion to principal axis-angle form.
tol=1e-12;
q=q(:)';
nq=norm(q);
if nq==0; error('The quaternion must be nonzero.'); end
q=q/nq;
if q(1)<0; q=-q; end
c=max(-1,min(1,q(1)));
ga=2*acos(c);
sn=norm(q(2:4));
if sn<tol
r=[1 0 0 0];
return
end
if ga<1e-7; ga=2*atan2(sn,c); end
n=q(2:4)/sn;
n=n/norm(n);
r=[n ga];
end
For γ=0, the rotation axis is indeterminate; any unit vector represents the identity rotation. In the program, the conventional choice [100] is used.