I have a 4x4 matrix with translation, rotation, and scaling components, but no shear or other transformations. How do I find its inverse? I'm using the Eigen library in c++.
Asked
Active
Viewed 5,621 times
1 Answers
3
This is tricky to get right, since the operations need to be performed in the correct order:
template<class Derived>
Matrix4f AffineInverse(const Eigen::MatrixBase<Derived>& mat)
{
Matrix3f RotSclInv = (
mat.block<3, 3>(0, 0).array().rowwise()
/ mat.block<3, 3>(0, 0).colwise().squaredNorm().array() //scaling
).transpose(); //rotation
return (Matrix4f(4,4) << RotSclInv
, -RotSclInv * mat.block<3, 1>(0, 3) //translation
, 0, 0, 0, 1).finished();
}
As this answer states, the inverse of the top left 3x3 block can be calculated separately:
inv ([ A b ]) = [inv(A) -inv(A)*b]
([ 0 1 ]) [ 0 1 ]
The key insight for the top left block is that the scaling and rotation is equal to a orthogonal (rotation) matrix Q
times a diagonal (scaling) matrix D
: Q*D
. To invert it, do some linear algebra:
inv(Q*D)
= transp(transp(inv(Q*D)))
= transp(inv(transp(Q*D)))
= transp(inv(transp(D)*transp(Q)))
(see this proof), and since D
is diagonal and Q
is orthogonal,
= transp(inv(D*inv(Q)))
= transp(Q*inv(D))).
Q*inv(D)
is easy to find: Since in Q*D
each column is a column of Q
(which is a unit vector) times an entry of D
(which is a scalar), it is enough to divide each column by the square of its norm. This is what the first three lines of the function do.
Written out fully in linear algebra form:
inv ([ Q*D b ]) = [transp(Q*inv(D)) -transp(Q*inv(D))*b]
([ 0 1 ]) [ 0 1 ]

Dan
- 12,409
- 3
- 50
- 87
-
can you explain how do you get from transp(transp(inv(Q*D))) to transp(inv(transp(Q*D))) ? i understand transp(X) = inv(X) if X is orthonormal matrix which only applies for the rotation matrix but not for scale rotation matrix. – bysreg Jul 25 '17 at 05:56
-
@bysreg That identity is actually true for any invertible matrix. See [the proof here.](https://math.stackexchange.com/questions/340233/transpose-of-inverse-vs-inverse-of-transpose) – Dan Jul 27 '17 at 11:31
-
thanks. the link proves transp(inv(M)) = inv(transp(M)). but, just to be clear, the transp(X) = inv(X) only works for orthogonal (not only orthonormal, which i mentioned in the previous comment). but yea, that proof answer my question – bysreg Jul 30 '17 at 01:38
-
What is the reason this cannot be represented as an Eigen Transform which has an `inverse()` method? – oarfish May 19 '20 at 07:38