I want to implement the Inverse Rodrigues Rotation Formula (also known as Log map from SO(3) to so(3)), in double precision code (MATLAB is fine for the example) preferably as a 3-parameter vector with the unit direction vector scaled by the magnitude of rotation.
The analytical form is (from Wikipedia):
$\theta = \arccos\left( \frac{\mathrm{trace}(R) - 1}{2} \right)$
and then use it to find the normalised axis:
$\omega = \frac{1}{2 \sin(\theta)} \begin{bmatrix} R(3,2)-R(2,3) \\ R(1,3)-R(3,1) \\ R(2,1)-R(1,2) \end{bmatrix}$
which can then be used to find the scaled axis of rotation $\rho = \theta \omega$
Of course, $\sin(\theta)$ will cause the denominator to approach zero, which is undefined. The rotation vector $\rho$ at zero rotation is $\rho = \begin{bmatrix}0 & 0 & 0\end{bmatrix}^T$. Furthermore, it will also be undefined at $n\pi$, though we may assign the rotation to be the desired sign ($\pm\pi$)
The naive implementation is to have if() statements for floating point values close to $n\pi$ rotations, but surely there is a better way than some dirty hacks around the singularities... right?
EDIT:
At rotations near zero, empirically, the following works well:
if (trace(R) > (3 - small_number))
inverse_sinc = 1 + (1.0 / 6.0) * theta_2 + ...
(7.0 / 360.0) * theta_4 +
(31.0 / 15120.0) * theta_6;
rho = 0.5 * inverse_sinc * r;
end
where $\theta$ (and powers thereof), and $\mathbf{r} = \begin{bmatrix} R(3,2)-R(2,3) \\ R(1,3)-R(3,1) \\ R(2,1)-R(1,2) \end{bmatrix}$ are pre-calculated, and inverse_sinc (i.e. x/sin(x))is calculated from the Taylor series. This is accurate to better than 10^-11 in each axis when unit tested across a range of values (0, eps, 10^-12 through to 10^-3 and negative values for each across all three axes).
A good solution for $\theta = \pi$ still eludes me...