Rotation Matrix Time Derivatives
Problem Setup
For a point \(x_0 \in\mathbb R^4\), the rotation is a transformation defined as
where \(R(\Delta t) \in SO(3)\).
Then, through the transformation through time \(t\) will create a trajectory. We come up with the velocity of \(x\) as
So that the velocity is the time derivative of the rotation matrix.
Angular Velocity
Without loss of generality, assume \(x\) is rotated along the rotation with the axis of rotation \(\vec a\in\mathbb R^3\). Therefore, \(x\) is travel in a circle.
Let \(\dot\theta\) be the change in angle.
Let \(v: \mathbb R\rightarrow \mathbb R^3\) be the velocity of \(x\), decompose \(v(t) = a(t)d(t)\) where \(a\) is the magnitude and \(d\) is the direction.
Since we are rotating around \(\vec a\), i.e. the plane that contains the circle is orthogonal to \(\vec a\). Hence \(d\perp \vec a\).
In addition, a rotation is orthogonal matrix so that \(v\perp x\), since \(\vec a,v,x\) are mutually orthogonal, we can uniquely determine \(d\) from
Then, consider the magnitude \(a\), let \(y = x + \Delta tv\). The angle formed by \(y\) and \(x\) is \(\dot\theta \Delta t\). So that we can have
Therefore, we can have
so that
and then
Therefore, we obtain the angular velocity \(\omega\), which includes the velocity of angle and the rotation direction.
Rotation Matrix
Since cross product can be written into cross matrix form as matrix multiplication, $v=\omega\times x $ can then be understood as
which is a linear ODE, and has analytical solution
where \(\exp(M)\) is the matrix exponential.
Matrix Exponential
For an invertible matrix \(A\in\mathbb R^{n\times n}\). the matrix exponential \(\exp(A)\) is given as
Where \(A=V\Lambda A^{-1}\) is the Eigen decomposition. However, as we did the decomposition, it is not very efficient.
For our problem, since \([\omega]_{\times}\) is a cross product matrix, hence \(3\times 3\) skew-symmetric, we can use Rodrigues' Rotation Formula. First, we can break \(\omega t\) into the axis of rotation and angle of rotation, as \(\vec a\) and \(\theta\)
then Rodrigues' Rotation Formula gives
Relationship between R and w
Note that we have \(\dot x(t) = \dot R(t)x_0\) and the equation above gives \(\dot x(t) = [\omega]_\times x\), therefore, we have found the relation that
General Equation
Consider the explicit equation with a fixed \(t_0\)
and its time derivative is
Note that from the derivations above, since \(R(t_0)x_0\) is a fixed point, \(v\) is just the time derivative of rotation at time \(t_0\) so that
Another form of this equation is
then this form gives that \(v\) is linear in \(\omega\).
Source code
import plotly.express as px
import plotly.graph_objects as go
import numpy as np
def rodrigues(k, v, theta):
k /= np.linalg.norm(k)
cross = np.cross(k, v)
cos = np.cos(theta)[:, None]
sin = np.sin(theta)[:, None]
dot = np.dot(k, v)
v_p = np.tile(v, (len(theta), 1))
k_p = np.tile(k, (len(theta), 1))
return v_p * cos + sin * cross + dot * k_p * (1-cos)
def plot(output_file):
axis = np.random.random(3)
axis /= np.linalg.norm(axis)
vector = np.random.random(3)
angle = np.linspace(0, 2 *np.pi, 100)
dt = 0.2
points = rodrigues(axis, vector, angle)
alpha = vector.dot(axis) / np.linalg.norm(axis) * axis
d = np.cross(axis, vector) / np.linalg.norm(vector)
derivative = vector + dt * d
trajectory = go.Scatter3d(x=points[:, 0], y=points[:, 1], z=points[:, 2],
mode="lines", name="x trajectory")
plot_axis = go.Scatter3d(x=[0, axis[0]],y=[0, axis[1]],z=[0, axis[2]],
name="a_vec")
plot_vector = go.Scatter3d(x=[0, vector[0]],y=[0, vector[1]],z=[0, vector[2]],
name="x")
plot_normal = go.Scatter3d(x=[alpha[0], vector[0]], y=[alpha[1], vector[1]], z=[alpha[2], vector[2]],
name="trajectory normal", mode="lines", line=dict(dash="dot"))
plot_y = go.Scatter3d(x=[vector[0], derivative[0], 0], y=[vector[1], derivative[1], 0], z=[vector[2], derivative[2], 0],
name="y")
fig = go.Figure(data=[trajectory, plot_axis, plot_vector, plot_normal, plot_y])
fig.update_layout(margin=dict(l=0, r=0, b=0, t=0),
scene_aspectmode='cube',
legend=dict(x=0, y=0))
with open(output_file, "w") as f:
f.write(fig.to_json())
output_file = "../assets/rotation.json"
plot(output_file)