5
$\begingroup$

I'm a programmer working on an advanced C++ 3D mathematics library.

Now, things have been going well, in fact, basically everything about the library has been fully implemented, but one final bit of code still alludes me: finding the axis of rotation for a pure rotation matrix when said matrix is also symmetric.

I've got a nice bit of math going when it comes to non-symmetric matrices

Given a non-symmetric 3x3 pure rotation matrix [M]

M = { { a, b, c },
      { d, e, f },
      { g, h, i } }

det(M) = 1

M * T(M) = T(M) * M = I

M =/= T(M)

an eigenvector [u] which sits along the axis of rotation can be found 

u = { h - f,
      c - g,
      d - b }

such that its normal is axis of rotation [r] of the matrix

r = u / |u|

but this math breaks the moment you give it a symmetric matrix, as the 'h - f', 'c - g', and 'd - b' portions will all resolve to zero, which obviously isn't the normal vector I want.

Now, I do understand linear algebra, but only a little bit. I've been researching this problem for a few days now, and while there are resources that talk about this, most of them either don't address the problem I'm having, or explain it in a way that my scrub brain simply can't keep up with.

They tell me to do things like 'diagonalize M and solve for u', but I've not a clue what that actually entails doing, let alone in a generalized way, let alone (even more) teaching my C++ library to do it in a generalized way given any symmetric pure rotation matrix.

So ya, that's my plight. Hoping that one of y'all could help bail me out on this one and show me how to solve this problem. :D

Btw, again, this is needed for writing code, so if your answer could be written in a way that addresses that need and also the fact that I'm a linear algebra noobie, that would be awesome.

Thanks in advance!

$\endgroup$
  • 1
    $\begingroup$ “Diagonalize $M$ and solve for $u$” isn’t particularly helpful since most rotation matrices aren’t diagonalizable over the reals in the first place. Since the rotation axis is fixed, any vector on it is an eigenvector with eigenvalue $1$, so what you can do is compute a null vector of $M-I$, which will always work. However, the above method and the method in my answer are more efficient and likely more numerically stable. $\endgroup$ – amd Nov 19 '19 at 18:38
5
$\begingroup$

If the matrix is symmetric, then $M^TM=M^2=I$, so it’s a 180-degree rotation about some axis. The method you’re using is known to fail for this angle, as you’ve discovered. (Indeed, among the conditions in the gray block in your question is $M\ne M^T$.) Essentially, it examines the skew-symmetric part of $M$, which is $\sin\theta$ times the “cross-product matrix” of the rotation axis. This unfortunately vanishes when $\theta=\pi$.

This question and this one describe a different method that uses the symmetric part of $M$ instead: Compute $$T = M+M^T-(\operatorname{tr}(M)-1)I.$$ Any nonzero row or column of this matrix is a vector parallel to the rotation axis.


Addendum (2019.11.19): As you noted, “diagonalize $M$ and solve for $u$” isn’t particularly helpful advice: most rotation matrices aren’t diagonalizable over the reals in the first place. The rotation axis is fixed by the rotation, though, so what you can do for any rotation matrix is compute the eigenspace of $1$, i.e., find a null vector of $M-I$. However, the method in your question and the above method are more efficient. Because of roundoff and other computational errors, in practice computing a null vector of a matrix is done by computing its SVD and taking the singular vector that corresponds to the least singular value.

| cite | improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ I suspect that this method will be better numerically when the matrix is nearly symmetrical and the rotation is nearly $180$-degrees because then the differences between off diagonal elements will me small and perhaps numerically unstable. $\endgroup$ – Ethan Bolker Nov 18 '19 at 21:40
  • $\begingroup$ Cool, awesome answer mate, thank you. Once question though, how do I actually get the eigenvector from the matrix? Do I take the main diagonal as a vector? I've written up a little thing to test the math, and it is giving me a vary clean looking matrix, but I'm not quite sure how I'm to interpret it. $\endgroup$ – Tirous Nov 18 '19 at 21:46
  • 1
    $\begingroup$ @Tirous As I wrote, any nonzero row or column of $T$ is parallel to the rotation axis, i.e., is an eigenvector of $M$ with eigenvalue $1$. You need to find a nonzero entry of $T$ and extract that row or column of $T$. $\endgroup$ – amd Nov 18 '19 at 21:49
  • $\begingroup$ Lol, of course you did. I'm an idiot. Thanks, friend, this is been a huge help. $\endgroup$ – Tirous Nov 18 '19 at 22:01
  • 2
    $\begingroup$ This method works for any angle, but your original method is a lot faster. Following @EthanBolker’s hunch, a possibility is to switch to this alternate method when $\operatorname{tr}(M)$ is near $-1$, which means that $\theta$ is near $\pi$ and the matrix is nearly symmetric. $\endgroup$ – amd Nov 18 '19 at 22:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.