当我查看Google之前的纸板sdk(decompiled one on Github)时,function提取了rodrigues' rotation matrix个旋转轴和角度here。数学很简单,并详细解释。
令我感到困惑的是,撰写此https://stackoverflow.com/a/26839190/1309710的作者将计算分为三种情况(cosθ> sqrt(1/2);cosθ< -sqrt(1/2); -sqrt( 1/2)≤cosθ≤sqrt(1/2))。但实际上除了θ= 0
的情况外,通常可以应用第一种情况任何人都可以弄明白为什么作者这样做了?是关于准确性还是性能?或者有什么致命的我错过了
答案 0 :(得分:0)
罗德里格斯的公式是
R = I + sin(th)*K + (1-cos(th))*K²
其中K
是反对称矩阵,在问题中实现了k=(kx,ky,kz)
(k=n
)的叉积。对于它的正方形,也有公式K²=k*k^T-I
,因此另一种形式是
R = cos(th)*I+sin(th)*K+(1-cos(th))*(k*k^T).
对于接近asin
或acos
的参数,角度范围的细分可以解决+1
和-1
的通常限制。这可以通过计算所有情况来避免
angle = Math.atan2(sinAngleAbs, cosAngle);
( Esp。因为在大多数实现中,使用了身份asin(x)=atan2(x,sqrt(1-x*x))
和acos(x)=atan2(sqrt(1-x*x),x)
,因为x86 FPU提供FPATAN
作为唯一的反向触发功能。)
取消错误的一个来源是计算R
,
(R-R^T)/2 = sin(th)*K
非对角条目的格式为
R(1,2)=-sin(th)*kz + (1-cos(th))*kx*ky
=2*sin(th/2)*( -cos(th/2)*kz + sin(th/2)*kx*ky ), …
如果sin(th)
很小且cos(th)
接近-1
,即角度th
接近pi
,在这种情况下, sin(th)*kz
对kx*ky
较小,因此此组件R-R^T
中的取消错误发生。并且类似地,如果任何其他组件在其他组件之一中很小。这就是为什么在这种情况下的条目更好地从
(R+R^T)/2 = I + (1-cos(th))*K²
= cos(th)*I + (1-cos(th))*(k*k^T)
在(1-cos(th))*k*k^T
中选择具有最大乘数的列kx,ky,kz
。