【发布时间】:2019-10-22 13:01:26
【问题描述】:
我有一个旋转,我想将它分解成一系列围绕 3 个正交任意轴的旋转。这有点像欧拉分解的推广,其中旋转不围绕 X、Y 和 Z 轴进行
我试图找到一个封闭形式的解决方案,但没有成功,所以我生成了一个数值解决方案,该解决方案基于最小化我想要的旋转与代表 3 个角度的 3 个轴旋转的 3 个四元数的乘积之间的差异未知数。 'SimplexMinimize' 只是代码的抽象,用于找到最小化错误的 3 个角度。
double GSUtil::ThreeAxisDecomposition(const Quaternion &target, const Vector &ax1, const Vector &ax2, const Vector &ax3, double *ang1, double *ang2, double *ang3)
{
DataContainer data = {target, ax1, ax2, ax3};
VaraiablesContainer variables = {ang1, ang2, ang3};
error = SimplexMinimize(ThreeAxisDecompositionError, data, variables);
}
double GSUtil::ThreeAxisDecompositionError(const Quaternion &target, const Vector &ax1, const Vector &ax2, const Vector &ax3, double ang1, double ang2, double ang3)
{
Quaternion product = MakeQFromAxisAngle(ax3, ang3) * MakeQFromAxisAngle(ax2, ang2) * MakeQFromAxisAngle(ax1, ang1);
// now we need a distance metric between product and target. I could just calculate the angle between them:
// theta = acos(2?q1,q2?^2-1) where ?q1,q2? is the inner product (n1n2 + x1x2+ y1y2 + z1z2)
// but there are other quantities that will do a similar job in less time
// 1-(q1,q2)^2 should be faster to calculate and is 0 when they are identical and 1 when they are 180 degrees apart
double innerProduct = target.n * product.n + target.v.x * product.v.x + target.v.x * product.v.x + target.v.x * product.v.x;
double error = 1 - innerProduct * innerProduct;
return error;
}
它有效(我认为)但显然它很慢。我的感觉是应该有一个封闭形式的解决方案。至少该函数应该有一个渐变,这样我就可以使用更快的优化器。
【问题讨论】:
-
代码中有一个小错误:innerProduct = target.n * product.n + target.v.x * product.v.x + target.v.y * product.v.y + target.v.z * product.v.z
-
你试过我的解决方案了吗?我很确定它会比迭代优化更快。
-
是的,您的解决方案要快得多。我特别怀疑当值接近 90 度时,欧拉角的行为非常奇怪。
标签: rotation geometry euler-angles