我最近一直在阅读有关四元数的信息,并想知道是否有可能创建一个系统,允许您创建一个不会在+/- 180处翻转并允许360度扭曲的扭曲系统?
我所做的每一项测试都会继续计算两个向量之间的角度,它总是会给出0到180之间的角度。
如果您不确定我正在寻找什么,那么来自Jorn-Harald Paulsen的视频应该清楚,我想用四元数来做,但我不确定他使用的是什么方法。
我在他的网站上看过关于防止翻转的Felix Joleanes'文章,他有一个专门用于扭曲设置的部分,但它更像是一个目标/外观约束,这个设置不适用于分配扭曲用于多个关节。它还取决于使用欧拉角的一些技巧/黑客,我宁愿避免使用四元数。
答案 0 :(得分:1)
四元数
q = cos(t/2) + (u_x i + u_y j + u_z k) sin(t/2)
给出角度到旋转的平滑映射。在360度时,你有q = -1,但是当你将四元数映射到旋转时无关紧要;轮换只是身份,正是你想要的。旋转中没有“翻转”。所以我不明白问题是什么......
答案 1 :(得分:0)
四元数代表“方向”,即空间中的角度位置。但它不能代表360度“旋转”作为时间变化的方向。
如果要表示关于固定轴的角度运动(旋转),可以使用“轴角度”表示https://en.wikipedia.org/wiki/Axis%E2%80%93angle_representation
或“指数地图” https://en.wikipedia.org/wiki/Rotation_group_SO(3)#Exponential_map
如果您的旋转轴适合于框架轴,则可以使用“Euler angels”
所有这些表示都可以转换为四元数或旋转矩阵。
答案 2 :(得分:0)
我最近在我们的项目中开发了一种扭曲提取算法。我只是描述它,你决定它是否是你需要的。
假设我们有一个手臂,其两端称为E1
和E2
,其方向以四元数形式描述。当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 ++中的remquo
来完成此过程。
float FindClosestEquavilentAngle (float angle, float reference)
{
int cycle = 0;
remquo(reference - angle, 360, &cycle);
return angle + 360 * cycle;
}
此功能可将-170度转换为190度。现在我们可以将190乘以0.5,并将结果应用于E1
。
这适用于我的情况。
答案 3 :(得分:0)
如果您想使用四元数而不是角度来表示旋转,那么您将始终遇到遇到的问题。这是一个简单的例子:假设你在时钟显示10时开始处理你的程序,并在时钟显示12时结束。你什么时候中途完成?大多数人说11,但如果你从晚上10点开始到中午12点结束,当时钟显示5(7小时通过马拉松14小时)时,你就完成了一半。
关键是,没有办法告诉哪个是给定数据的正确答案。同样,没有通用的方法可以正确插值半个旋转,或旋转的三分之一,或其他任何方式。
如果您想要一个仅限四元数的解决方案,我建议"推断"而不是插值角度。也就是说,将控制元素设置为最少转动或移动的元素,然后让所有其他元素为表示最小旋转的四元数的倍数。因此,如果q
是最小的扭曲,最接近手臂的插座,q^2
旋转两倍,q^3
旋转三次,依此类推。