I needed to do this recently, so I broke down and decided to write routines for interconverting quaternions and rotation matrices.
I'll give the quaternion to rotation matrix routine first, since it's the shortest. I merely needed to modify my Rodrigues routine in this answer:
Needs["Quaternions`"];
quaternionToRotation[qq_] /; QuaternionQ[ToQuaternion[qq]] :=
Module[{q = ToQuaternion[qq], aim, r},
aim = AbsIJK[q]; r = Re[q];
If[aim == 0, Return[IdentityMatrix[3], Module]];
First[LinearAlgebra`Private`MatrixPolynomial[
{Prepend[2 aim {r, aim}/(r^2 + aim^2), 1]},
-LeviCivitaTensor[3, List].(Rest[List @@ q]/aim)]]]
(Use LinearAlgebra`MatrixPolynomial[]
in versions before 11.2.)
Now, for the more complicated direction of converting a rotation matrix to a quaternion. I will provide two methods I found in the literature. This first one is due to Markley, which is a modification of an earlier method due to Sheppard*:
rotationToQuaternion[m_?OrthogonalMatrixQ] := Module[{d, v, xm},
d = Diagonal[m];
v = {{m[[3, 2]] - m[[2, 3]], m[[1, 3]] - m[[3, 1]], m[[2, 1]] - m[[1, 2]]}};
xm = IdentityMatrix[4] +
DiagonalMatrix[{{1, 1, 1}, {1, -1, -1}, {-1, 1, -1}, {-1, -1, 1}}.d] +
ArrayFlatten[{{0, v}, {Transpose[v], 2 Symmetrize[m - DiagonalMatrix[d]]}}];
Sign[Apply[Quaternion, First[MaximalBy[xm, Norm]]]]]
The second method I present is due to Bar-Itzhack:
rotationToQuaternion2[m_?OrthogonalMatrixQ] := Module[{d, v, xm},
d = Diagonal[m];
v = {{m[[3, 2]] - m[[2, 3]], m[[1, 3]] - m[[3, 1]], m[[2, 1]] - m[[1, 2]]}};
xm = DiagonalMatrix[{{1, 1, 1}, {1, -1, -1}, {-1, 1, -1}, {-1, -1, 1}}.d] +
ArrayFlatten[{{0, v}, {Transpose[v], 2 Symmetrize[m - DiagonalMatrix[d]]}}];
Sign[Apply[Quaternion, First[Eigenvectors[xm, 1]]]]]
(The observant reader ought to notice the similarities in the two methods.)
At this juncture, let me remind the leader that a quaternion $\mathbf q$ and its negative correspond to the same rotation. If needed, one can modify the conversion routines so that a quaternion with positive real part is always returned.
Now, for tests:
BlockRandom[SeedRandom[42]; (* for reproducibility *)
tstq = Apply[Quaternion, Normalize[RandomVariate[NormalDistribution[], 4]]]];
Norm[rotationToQuaternion[quaternionToRotation[tstq]] + tstq]
1.54074*10^-32
Norm[rotationToQuaternion2[quaternionToRotation[tstq]] - tstq]
3.08149*10^-32
BlockRandom[SeedRandom[42]; (* for reproducibility *)
tst = Orthogonalize[# Det[#]] &[RandomVariate[NormalDistribution[], {3, 3}]]];
Norm[quaternionToRotation[rotationToQuaternion[tst]] - tst]
5.23541*10^-16
Norm[quaternionToRotation[rotationToQuaternion2[tst]] - tst]
2.37306*10^-16
* - altho it may not look it, the article by Sheppard is at the end of the PDF from that link.
Update 9/15/2019
An even faster and more accurate method due to Sarabandi, Perez-Gracia, and Thomas, based on the Cayley representation of the rotation matrix, can be very simply implemented in Mathematica:
rotationToQuaternionCayley[m_?OrthogonalMatrixQ] :=
With[{s = {{m[[3, 2]] - m[[2, 3]], m[[1, 3]] - m[[3, 1]], m[[2, 1]] - m[[1, 2]]},
{0, m[[2, 1]] + m[[1, 2]], m[[1, 3]] + m[[3, 1]]},
{0, 0, m[[3, 2]] + m[[2, 3]]}}},
Apply[Quaternion, Prepend[Sign[First[s]], 1]
Map[Norm, DiagonalMatrix[Prepend[NestList[RotateRight, {1, -1, -1}, 2],
{1, 1, 1}].Diagonal[m] + 1] +
((# + Transpose[#]) &[PadLeft[s, {-4, 4}]])]/4]]