2D Rotation

A 2D rotation has only one parameter, θ. When the basis vectors i^=[1,0] and j^=[0,1] are rotated by an angle θ:

p=cosθi^+sinθj^q=sinθi^+cosθj^

Which builds the rotation matrix:

R(θ)=[pq]=[cosθsinθsinθcosθ]

When a vector v is transformed by this matrix, we know that the vector will be a linear combination of the basis, which are p and q:

v=vR(θ)=vxp+vyq=vx[cosθsinθ]+vy[sinθcosθ]=[vxcosθvysinθvxsinθ+vycosθ]T

Using a matrix to encode this operation:

v=vR(θ)=[vxvy][cosθsinθsinθcosθ]=[vxcosθvysinθvxsinθ+vycosθ]T

See also complex numbers .

3D Rotation

About Cardinal Axes

Rx(α)=[1000cosαsinα0sinαcosα]
Ry(β)=[cosβ0sinβ010sinβ0cosβ]
Rz(γ)=[cosγsinγ0sinγcosγ0001]

See also:

About an Arbitrary Axis

Given an axis n^ and an amount of rotation around it θ, our goal is to find a rotation matrix that rotates about n^ by the angle θ:

v=R(n^,θ)v

The basic idea is to solve this problem in a plane perpendicular to n^, which becomes a 2D problem.

Separate v into two vectors: a vector parallel to v^ called v and a vector perpendicular to v^ called v such that v+v=v:

v=(vn^)n^v=vv

After the rotation, it’s obvious that the v component will be the same, and only the vector v will be rotated.

A plane can be defined with two vectors that lie on it. Since we have v and we also know the normal of the plane (which is n^), any vector perpendicular to both vectors will also lie in the plane. We can use the cross product to find this vector:

w=n^×v

The length of w is:

w=n^vsin90°=v

Which means that w has the same length as v. Note that even though they have the same length, they don’t necessarily have unit length.

w and v now form a 2D coordinate space where the x-axis is v and the y-axis is w.

Let v be a vector that is the result of rotating v by an angle θ. We can find the projection of it onto the x-axis and the y-axis as follows:

v,x=(vcosθ)v^=cosθvv,y=(vsinθ)w^=sinθw
  • Expressing v as a linear combination of the basis:
v=cosθv+sinθw

Reconstructing the solution from the observations above:

v=(vn^)n^v=vv=v(vn^)n^w=n^×v=n^×(vv)=n^×vn^×v=n^×v

Finally:

v=v+v=cosθv+sinθw+(vn^)n^=cosθ(v(vn^)n^)+sinθ(n^×v)+(vn^)n^=cosθvcosθ(vn^)n^+sinθ(n^×v)+(vn^)n^(1)=cosθv+sinθ(n^×v)+(1cosθ)(vn^)n^

Now we can compute what the basis vectors are after the transformation above (by using each of the basis vectors as v on (1)) to construct a rotation matrix:

p=[100]p=[nx2(1cosθ)+cosθnxny(1cosθ)+nzsinθnxnz(1cosθ)nzsinθ]q=[010]q=[nynx(1cosθ)nzsinθny2(1cosθ)+cosθnynz(1cosθ)+nxsinθ]r=[001]r=[nznx(1cosθ)+nysinθnzny(1cosθ)nxsinθnz2(1cosθ)+cosθ]

Constructing the matrix from these vectors:

R(n^,θ)=[pqr]

3D Rotations Using Quaternions

A complex rotor is a unit norm complex number that rotates another complex number by the angle θ and has the form:

eiθ=cosθ+isinθ

Hamilton had hoped that a unit-norm quaternion q could be used to rotate a vector, which is stored as a pure quaternion p. The unit norm quaternion is given by:

(2)q=[s,λn^]s,λR,n^R3|n^|=1s2+λ2=1
p=[0,v]vR3

Let’s compute the product p=qp:

p=qp=[s,λn^][0,v](3)=[λn^v,sv+λn^×v]

Special Case

What if n^ is perpendicular to v? Then the scalar quantity of (3) is zero, and we are left with the pure quaternion:

(4)p=[0,sv+λn^×v]given that n^ is perpendicular to v

Let’s analyze the vector part of (4) (which is now a 3D entity because it’s a pure quaternion). Since n^ is perpendicular to v, then the vector n^×v will have a norm equal to n^×v=n^vsin90°. Also, since n^ is a unit vector, then n^×v=v, which means that we have two orthogonal vectors with the same length.

To rotate the vector v about n^, let’s transform v to the 2D space whose basis vectors are v and n^×v and perform the rotation there, which is trivially [cosθ,sinθ]. Therefore, all we have to do in (4) is make the scalar quantities multiplying each vector equal to the projection of the rotated vector over the basis:

p=[0,cosθv+sinθn^×v]

Which makes the quaternion q have the form:

(5)q=[cosθ,sinθn^]

And it acts as a rotor only when n^ is perpendicular to v.

Important notes/facts about orthogonal quaternions:

  • If q is a rotor about the unit vector n^ by an angle θ whose vector term is perpendicular to the pure quaternion p:
    • qp and pq1 rotate p by an angle θ about n^.
    • pq and q1p rotate p by an angle θ about n^.
    • Each of these products leaves p unscaled (because q is a unit norm quaternion).

General Case

Let’s use (2) as the starting point. Note that this time its vector part is not necessarily perpendicular to the pure quaternion p. The product qp yields:

qp=[s,λn^][0,v]=[λn^v,sv+λn^×v]

Note that the term λn^v does not vanish since for the general case, n^ and v are no longer perpendicular. What’s more important is that the product qp is no longer a pure quaternion. Multiplying a vector by a non-orthogonal quaternion has converted some of the vector information into the quaternion’s scalar component.

What happens if we post-multiply qp by q1? Could it reverse the operation? (Note that since q is a norm quaternion, q1=q.)

qpq1=[λn^v,sv+λn^×v][s,λn^]

Let’s first check if doing this multiplication makes the scalar component vanish:

qpq1=[λsn^v(sv+λn^×v)(λn^),]=[λsn^v+(sv)(λn^)+(λn^×v)(λn^),]=[λsn^v+(sv)(λn^)+0,]since n^ is perpendicular to n^×v =[λsn^v+λsvn^),]=[0,]

Indeed, it magically made the scalar component vanish! Now let’s look at the vector component of qpq1:

qpq1=[0,s(sv+λn^×v)+(λn^v)(λn^)+(sv+λn^×v)×(λn^)]=[0,s2v+sλ(n^×v)+λ2(n^v)n^sλ(v×n^)λ2(n^×v×n^)]

Let’s expand the cross product :

(n^×v)×n^=(n^n^)v(vn^)n^=v(vn^)n^

Therefore:

qpq1=[0,s2v+sλ(n^×v)+λ2(n^v)n^sλ(v×n^)λ2(v(vn^)n^)]=[0,s2v+sλ(n^×v)+λ2(n^v)n^sλ(v×n^)λ2v+λ2(vn^)n^)]=[0,s2v+2sλ(n^×v)+λ2(n^v)n^λ2v+λ2(vn^)n^)]=[0,(s2λ2)v+2sλ(n^×v)+2λ2(vn^)n^]

Let’s make s=cosθ and λ=sinθ, just like in (5) (it worked as a rotor when it was orthogonal to p; it might work with the general case too):

qpq1=[0,(cos2θsin2θ)v+2cosθsinθ(n^×v)+2sin2θ(vn^)n^]

Which involves double-angle terms. Replacing these terms with double-angle identities :

qpq1=[0,cos2θv+sin2θ(n^×v)+(1cos2θ)(vn^)n^]

The product created a pure quaternion equal to v rotated by an angle of 2θ. If we want to rotate v by an angle of θ, we must build a half-angle θ quaternion q (note above that q was equal to (5)):

(6)q=[cos12θ,sin12θn^]

Using (6), the product is:

qpq1=[0,cosθv+sinθ(n^×v)+(1cosθ)(vn^)n^]

Note that the vector part of qpq1 is identical to (1).

Quaternion Difference and Dot Product

Let a and b be two unit norm quaternions (rotors that have the same form as (6)). The quaternion to rotate from a to b is given by da=b and is known as quaternion difference. Finding the value of d given that we know a and b:

da=bd(aa)=basince a is a unit norm quaternion, its inverse is equal to its conjugated=ba

Expanding the product:

d=[sb,b][sa,a]=[sbsa+ba,sba+sabb×a]

Note that the scalar part of this quaternion is equal to the inner product (a generalization of the dot product to abstract vector spaces) between two quaternions:

d=[a,b,sba+sabb×a]

Remembering that a rotor is given by (6), we can relate the inner product between rotor quaternions with the scalar quantity of (6) and interpret it geometrically, just like the dot product between two vectors in 3D/2D space, but this time noticing that the dot product gives the cosine of half the angle between the quaternions:

ab=cosθ2

This means that the angle between a and b is equal to:

θ=2arccos(ab)

Or using the half-angle formulas :

cos2θ2=12(1+cosθ)(ab)2=12(1+cosθ)cosθ=2(ab)21θ=arccos(2(ab)21)

The second formula works for all cases, as noted here (the first one doesn’t work when ab<0).