从欧拉旋转到四元数旋转

时间:2013-11-01 17:46:08

标签: c# rotation unity3d quaternions euler-angles

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

载体:

Leap.Vector normal = current.PalmNormal;
Leap.Vector pointer = current.Direction; 

有关详细信息,请参阅Leap Hand API:https://developer.leapmotion.com/documentation/Languages/CSharpandUnity/API/class_leap_1_1_hand.html

转换为Unity Vector3类:

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轴的θ_x度旋转,围绕y轴的θ_y度,以及围绕z轴的θ_z度)使用以下代码:

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;
}

然后将欧拉角转换为四元数并使用代码实现:

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)时,每个旋转轴都工作,我认为问题在于欧拉角转换为四元数的方式。我没有很好地理解四元数用于表示旋转的方式,但是我很困惑为什么围绕y轴改变旋转角度的值会改变围绕x轴的旋转角度。 / p>

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

轮换顺序是相关的,这可能是导致您混淆的原因。想象一下x轴上的一个点(1,0,0)。当我们现在围绕x轴旋转90°时,没有任何反应。然后我们围绕y轴旋转90°,这使得该点位于正z轴上。如果我们改变旋转顺序,该点将在y轴上结束。根据功能的实现方式,它们需要一定的旋转顺序才能获得预期的结果。

答案 1 :(得分:0)

这并不完美,但我的成绩非常好:

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是来自跳跃控制器的Hand实例,而marker是一个表示手旋转的简单矩形。

我得到了NaN,因此我将该组添加到0检查。

ATH

学家