是否可以将矩阵的快速逆应用于纯旋转和平移矩阵的串联,例如M = T2*R1*T1*R1
?
如果我将旋转和平移存储在4x4齐次列顺序矩阵中,我可以说:
M1 = [ R1 t1 ] given by [ 1 t1 ] * [ R1 0 ]
[ 0 1 ] [ 0 1 ] [ 0 1 ]
和
inv(M1) = [inv(R1) inv(R1)*-t1 ] given by [ 1 -t1 ] * [ inv(R1) 0 ]
[ 0 1 ] [ 1 1 ] * [ 0 1 ]
由于R1只是旋转,我们知道inv(R1)=转置(R1)所以我们可以简单地说:
inv(M1) = [transp(R1) transp(R1)*-t1 ]
[ 0 1 ]
现在给出一些其他类似的旋转和平移矩阵M2,如果我们以MFinal = M2 * M1 = T2*R1*T1*R1
我们可以这么说吗
inv(MFinal) = [transp(MFinalRot) transp(MFinalRot)*-tfinal ]
[ 0 1 ]
其中MFinalRot是4x4矩阵的旋转部分?
此外,如果订单更加随意,例如MFinal2 = R3*T3 * T2*R2*T1*R1
,但仍然只是单独轮换和翻译,该怎么办?
答案 0 :(得分:1)
是的,如果您的4x4矩阵是纯旋转矩阵和平移矩阵的串联,您应该能够计算快速逆矩阵:
fast_inverse( [R1 t1] ) = [transpose(R1) transpose(R1)*(-t1)]
[0 1] [ 0 1 ]
这是因为3x3旋转矩阵(代码中的R1
)只是输入旋转矩阵的乘积,所以它本身应该是一个旋转矩阵,它的转置应该是它的反转。 / p>
如果你的任何连接矩阵都是缩放矩阵,或者底行不是[0 0 0 1]
,那么这不再是真的。
另请注意:实际上,如果将足够多的矩阵相乘,浮点误差可能会导致它们漂移"一些,因此它们可能不像新生的旋转矩阵那样接近正确的旋转矩阵。根据你如何使用它,这可能不是一个问题 - 但如果是,你可以重新正规化"它,如下所示:
orth(Vec3 a, Vec3 b): // return value orthogonal to b
return (a - (dot(a,b)/dot(b,b)) * b)
re_orthonormalize(Mat3x3 Rin):
Vec3 x = Rin.x;
Vec3 y = orth(Rin.y, x);
Vec3 z = orth(orth(Rin.z, x), y);
return Mat3x3(normalize(x),normalize(y),normalize(z))
只要您输入的距离太远,就应该为您提供正确的旋转矩阵。
要查看re_orthonormalize
代码的工作原理,请先将orth
输出的点积与其b
输入相加。因为点积是线性的,所以我们有:
dot(a - (dot(a,b)/dot(b,b)*b, b)
== dot(a,b) - (dot(a,b)/dot(b,b)) * dot(b,b)
== dot(a,b) - dot(a,b)
== 0
因此,如果a
和b
已基本正交,ortho(a,b)
会添加少量b
以确保点积确实为0
这意味着在re_orthonormalize
中,y
与x
完全正交。棘手的一点是确保z
与 x
和y
正交。这只有效,因为我们已经确保x
与y
完全正交,因此添加一点y
并不会阻止orth(Rin.z, x)
与x
正交$add_number = $twilio->account->incoming_phone_numbers->create(array(
"PhoneNumber" => $number,
"MessagingServiceSid" => "MG68f3...4b72", // Messaging Service ID on Twilio
));
。
答案 1 :(得分:0)
两个平方矩阵的乘积(P = AB)的倒数通常是Inv(B)* Inv(A)。轮换和翻译将通勤。通常,您必须按照应用顺序的相反方式展开操作。
在这种情况下,R1 * T1 * R2 * T2 = R1 * R2 * T1 * T2然后您可以计算连接的倒数,作为单个旋转和平移的组成的倒数。
所以是的,这对于纯粹的旋转和翻译来说是合理的。