首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从欧拉旋转到四元数旋转的转换

从欧拉旋转到四元数旋转的转换
EN

Stack Overflow用户
提问于 2013-11-02 01:46:08
回答 2查看 3.1K关注 0票数 2

我正在使用Leap Motion设备来获取有关我的手的位置和方向的有用数据。目前,我在编码的方向部分遇到了问题。Leap API只有用于逐帧旋转的代码,但是,它还提供了法线向量(垂直于手掌)和指针向量(从手掌向外指向手指的方向)。这两个矢量是垂直的。

向量:

代码语言:javascript
复制
Leap.Vector normal = current.PalmNormal;
Leap.Vector pointer = current.Direction; 

更多信息可以在Leap上找到:https://developer.leapmotion.com/documentation/Languages/CSharpandUnity/API/class_leap_1_1_hand.html

正在转换为Unity Vector3类:

代码语言:javascript
复制
Vector3 normalU = new Vector3();
normalU.x = normal.x;
normalU.y = normal.y;
normalU.z = normal.z;
Vector3 pointerU = new Vector3();
pointerU.x = pointer.x;
pointerU.y = pointer.y;
pointerU.z = pointer.z;

我使用这些向量来计算我的手的欧拉角方向(围绕x轴旋转theta_x度,围绕y轴旋转theta_y度,围绕z轴旋转theta_z度):

代码语言:javascript
复制
float rXn = Mathf.Atan (normalU.y/normalU.z);
rXn *= (180f/Mathf.PI);
if ((normalU.y < 0 && normalU.z < 0) || (normalU.y > 0 && normalU.z < 0))
{
    rXn += 180f;
}
float rZn = Mathf.Atan (normalU.y/normalU.x);
rZn *= (180f/Mathf.PI);
if ((normalU.y < 0 && normal.x > 0) || (normalU.y > 0 && normalU.x > 0))
{
    rZn += 180f;
}
float rYn = Mathf.Atan (pointerU.x/pointerU.z);
rYn *= (180f/Mathf.PI);
if ((pointerU.x > 0 && pointerU.z > 0) || (pointerU.x < 0 && pointerU.z > 0))
{
    rYn += 180f;
}

然后将Euler角度转换为四元数并使用以下代码实现:

代码语言:javascript
复制
Quaternion rotation = Quaternion.Euler (-rZn+90, -rYn, rXn+90);
rigidbody.MoveRotation (rotation);

有关Unity Quaternion类的更多信息可以在这里找到:http://docs.unity3d.com/Documentation/ScriptReference/Quaternion.html

在我编写代码时,我单独测试了每个旋转轴,注释掉了其他轴(将它们设置为0),它们工作正常。然而,当我同时实现所有这三种方法时,围绕单个轴的旋转行为发生了变化,这让我感到困惑。为什么包括对y轴旋转的识别会改变x轴旋转的方式?

当其他旋转轴被注释掉(并设置为0)时,每个旋转轴都起作用,我认为问题出在Euler角度转换为四元数的方式。我对四元数表示旋转的方式不是很了解,但是我很困惑,为什么改变绕y轴的旋转角的值会改变绕x轴的旋转角。

谢谢你的帮助。

EN

回答 2

Stack Overflow用户

发布于 2013-11-02 05:24:55

旋转的顺序是相关的,这可能是导致您困惑的原因。想象x轴上(1,0,0)处的一个点。当我们现在绕x轴旋转90°时,什么也没有发生。然后我们绕y轴旋转90°,这使得点位于正z轴上。如果我们改变旋转的顺序,这个点将在y轴上结束。根据您的函数的实现方式,它们需要一定的旋转顺序才能获得预期的结果。

票数 2
EN

Stack Overflow用户

发布于 2013-11-02 08:25:53

它并不完美,但我使用以下命令获得了相当好的结果:

代码语言:javascript
复制
private void UpdateHandNormal( Hand hand, Transform marker )
{

    float y = Mathf.Atan( hand.Direction.x / hand.Direction.z );
    if( float.IsNaN( y ) ) y = 0;
    marker.localRotation = new Quaternion( hand.PalmNormal.z, -y, hand.PalmNormal.x, 1 ) ;  

}

其中hand是leap控制器中的Hand实例,标记是表示手旋转的简单矩形。

我正在获取y的NaN,所以我将集合添加到0检查。

路径

J.

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19732300

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档