是否可以创建允许360度旋转的四元数扭曲解决方案



我最近读到了关于四元数的文章,想知道是否有可能创建一个系统,让你创建一个不会在+/-180翻转并允许360度扭曲的扭曲系统?

我所做的每一个测试都会回到计算两个向量之间的角度,这个角度总是在0到180之间。

如果你不确定我到底在寻找什么,那么Jorn Harald Paulsen的这段视频应该会很清楚,我想用四元数来做,但我不确定他用的是什么方法。

我在Felix Joleanes的网站上读过他关于防止翻转的文章,他有一个专门介绍扭曲设置的部分,但它更像是一个瞄准/注视约束,这种设置不适用于为多个关节分配扭曲。这也取决于对欧拉角使用一些技巧/技巧,我宁愿避免使用四元数。

四元数

q = cos(t/2) + (u_x i + u_y j + u_z k) sin(t/2)

将角度平滑映射到旋转。在360度时,q=-1,但当将四元数映射到旋转时,这并不重要;旋转只是身份,正是你想要的。旋转中没有"翻转"。所以我不明白问题出在哪里。。。

四元数表示"方向",即空间中的角度位置。但它不能将360度的"旋转"表示为方向随时间的变化。

如果要表示围绕固定轴的角运动(旋转),可以使用"轴角度"表示https://en.wikipedia.org/wiki/Axis%E2%80%93angle_representation

或"指数映射"https://en.wikipedia.org/wiki/Rotation_group_SO(3) #指数映射

如果你的旋转轴适合框架轴,那么你可以使用"欧拉天使"

所有这些表示都可以转换为四元数或旋转矩阵。

我最近在我们的项目中开发了一种扭曲提取算法。我只是描述一下,然后你决定它是否是你需要的。

假设我们有一个臂,它的两端被称为E1E2,它们的方向用四元数描述。当E2围绕臂方向旋转角度r时,我们期望E1旋转f*r

让我们看看为什么会发生翻转(假设本例中为f = 0.5)。在某个时刻,E2可能已经旋转了170度,这意味着E1旋转了85度。

然后,我们继续将E2旋转20度,因为f为0.5,我们预计E1旋转10度,结果是旋转95度。但四元数不能表示E2的190度旋转,它告诉我们E2实际上旋转了-170度,所以E1最终以-85度旋转结束。与以前的85度旋转相比,这是一次翻转。

显然,只有当你有一个"参考角度"时,翻转才会发生。在我们的例子中,"参考角"是85度。我们没有办法阻止四元数给出-170度的结果,但利用参考角度的信息可以修复翻转。

在我们将-170乘以0.5之前,我们应该检查E1的当前旋转角度,这是参考角度,85度。除以0.5,我们会在最后一帧中知道,E2旋转了170度。然后我们将n*360度加到-170上,使其尽可能接近170。这个过程可以用C++中的CCD_ 19来完成。

float FindClosestEquavilentAngle (float angle, float reference)
{
    int cycle = 0;
    remquo(reference - angle, 360, &cycle);
    return angle + 360 * cycle;
}

此函数可将-170度转换为190度。现在我们可以将190乘以0.5,并将结果应用于E1

这对我来说是有效的。

如果你想用四元数而不是角度来表示你的旋转,那么你总是会遇到问题。这里有一个简单的例子:假设你在时钟显示10时开始编写程序,在时钟显示12时完成。你什么时候完成一半?大多数人说11点,但如果你从晚上10点开始,到中午12点结束,当时钟显示5点时,你已经完成了一半(马拉松14小时训练7小时)。

关键是,从给定的数据中无法判断哪个答案是正确的。同样,没有一种通用的方法可以正确地插值半个旋转,或三分之一旋转,或其他什么。

如果你想要一个只有四元数的解决方案,我建议"外推"而不是插值角度。也就是说,将控制元素设置为旋转或移动最少的元素,然后让所有其他元素都是表示最小旋转的四元数的倍数。因此,如果q是最小的扭曲,最靠近手臂的窝,q^2旋转两倍,q^3旋转三倍,依此类推。

最新更新