In many areas of robotics, computer vision and graphic is a need to rotate points or objects by certain angle around a given axis. One way to do it is to use Rodrigue's rotation formula.

Where the is a skew symmetric of normalized vector of the rotation axis and is the rotation angle in radians. The result is a 3x3 rotation matrix

It's simple to use and implement in every programming language but what's under the bonnet? How does it work? Ok lets work it out. There are actually at least two ways how to derive this formula, one purely geometric and the other more mathematical based on the matrix exponential. I will describe the geometric approach first.

So let's start from the beginning. The Rodrigues formula is used to perform angle-axis rotation, or simply said it rotates a point in the space around a given axis by given angle. It also outputs standard rotation matrix that I'm sure most people reading this article are familiar with. The most basic way of representing a rotation are Euler Angles.

## Euler Angles

Any rotation in the space is represented by three 2D rotations in planes xy, yz, and xz. The matrix form of these rotation is

The rotation matrix is a product of the three discrete 2D rotations.

It's clear the result depends on the order in which we perform the rotations. Rotating around X->Y->Z axes results in different final position than X->Z->Y. This is also given by that fact matrix multiplication is not commutative. The Euler angles rotation is simple to understand and visualize however is not really practical in many applications. Among problems associated with this technique is that the rotation is not smooth (a small change in position of the object can result in dramatic change of one or more Euler angles) and there is also risk of gimbal lock. Angle-axis rotation solves these problems and on top of that is also very simple to understand and work with.

## Angle-axis

Angle-axis rotation is more common the one may think. For instance everything on the Earth is rotation around the Earth's axis which is not the same as the solar system or our galaxy axes. Other example would be a car. Wheels are rotating around their axes that are different from the axis of the steering wheel or the engine crankshaft. Let's look at some more mathematical description.

Let say we have a point that we want to rotate by angle around axis to the final position

To do that we first define a vector from the origin to the point and a plane in the origin perpendicular to the axis of rotation We also normalize the vector representing the axis of rotation Second step is to project the vector on the axis of rotation and also on the plane in the origin. The vector projected on the rotation axis is called We will calculate it as a vector projection which is basically a dot product of the vector with the unit vector in the direction of

To get the vector we simply subtract from

The vector is called vector rejection Now we create a vector perpendicular to the plane We will use this vector to rotate the image of the by the angle on the plane in the origin.

It turns out that the cross product between unit vector and the vector has the same length as the vector rejection To do that we perform a 2D rotation of the vector in the plane . We will call this new vector

We are almost done. There's one more step. To get from the plane in the origin to the point we just need to add vectors and

Let's recap all equations and pull them together.

If we substitute all equations we get

We can simplify this equation by converting the dot and cross products to multiplication. Assuming that all vectors are column vectors the dot product is calculated as:

To calculate the cross product we use a skew-symmetric matrix trick 🙂 We first convert the vector to the skew-symmetric matrix and then multiply it with the vector The vector in the skew-symmetric matrix form is

Substituting the dot and cross product equations we get the Rodrigues formula.

So now we have a way to rotate point around the rotation axis by angle . To get the rotation matrix we need to split this equation in the and components.

thus

We can still simplify it a bit. We use the identity of the outer product

Where is the identity matrix.

This identity can be proved by following a few steps. First of all lets write down in the term of element-wise operations.

With a little bit of insight we may realize this is very close to the skew symmetric matrix of the squared

If we square it we get

Now we can see that it really looks like apart from the diagonal. The last step is to somehow turn the diagonal of the to the diagonal of This is quite easy. Since the vector has unit length we can just add one to the diagonal to get For example

So now we can write

which is

Using this identity in our equation we get

And finally we get the Rodriques formula

Next time I will show how the same formula is derived from angular velocity of a rigid object.

Fantastic proof. Took me a while to get through, but I got there in the end. Thanks for doing this!!!

Thanks for this! The pictures really help with visualizing things.

I understand almost all of it except for 2 things in the simplification part .

1.) For this part, vp=(v⋅n)n=(nTv)n=nTnv (converting the dot and cross products to multiplication)

How were you able to swap the order of (nTv)n to nTnv?

I thought matrix multiplication was non-commutative? (Since vectors are just matrices with one of its dimensions being 1)

It also appears differently in the next step:

u=vcosα+nnTv(1−cosα)+[n]×vsinα (nnTv != nTnv)

2.) For this part, nnT=[n]2×+I (Taking the identity of the outer product)

I'm not too clear on how this identity holds true.

I tried giving concrete values to n1=1, n2=2, and n3=3 of the vector n and I'm getting different results on the 2 sides of the equation.

Once again, thanks for this awesome explanation!

Hi skysoup,

Sorry for this late reply and BIG thanks for your comment and spotting my mistake. The (v⋅n)n is indeed nnTv and not nTnv.

Regarding the outer product identity I have update the article with the proof. The identity holds true only for normalized vector n which is probably why it didn't work for you. In the Matlab/Octave you can try this.

a=[1;2;3];

b=a/norm(a);

b*b'

b_skew = [ 0 -b(3) b(2) ; b(3) 0 -b(1) ; -b(2) b(1) 0];

b_skew^2 + eye(3)

You're welcome and thank you very much for the updated explanation. I finally fully understand it now!