2017-04-25 111 views
0

我有一個四元數表示一個對象(黃色方框和球體)的方向。我想知道是否有可能將該四元數分解爲其他四元數,從而讓我們旋轉每個局部座標軸(X,Y和Z)。拆分四元數到軸旋轉

Due to I do not have enough reputation to post images directly, I have to put just the link of the image

我一直在做,直至現在越來越歐拉代表,並與它的工作,但它不是我的具體情況正確的解決方案:

給定兩個點(藍框),我想限制我的物體的方向,以便它不能指出灰色的平面,即使我的四元數顯示器離開那架飛機。
我想分解(分解)四元數,因爲當我的對象達到平面的極限(例如右)時,我想讓它停留在那裏(在該組件中),然後旋轉我的對象在垂直分量,使用新分割的四元數之一。

我正在與Unity合作。

我希望這是可以理解我的問題:)

+0

將'四元數旋轉= Quaternion.Euler(新的Vector3(transform.eulerAngles.x,0,0)) ;'適用? –

+0

感謝@Peh的版本。 謝謝瑞安,但我想避免歐拉角,因爲原來的四元數來自外部IMU,並限制歐拉角的方向我有一些麻煩 – javinair

+0

[Quaternion.eulerAngles](https://docs.unity3d.com /ScriptReference/Quaternion-eulerAngles.html)是一件事,但我懷疑這就是你已經在使用。我知道'wxyz'的價值根本無濟於事,因爲它們不完整。我能想到的最好的方法是在兩個藍色框中計算一個歐拉'AngleTo()'(你必須寫這個方法),並檢查它的X和Y分量都大於0(或者小於)。 – Draco18s

回答

0

我以前和我有統一的知識,如果對象是在IMU數據作爲四元數讀取與IMU的工作,那麼你就不會遇到gimbo鎖問題。因此,您確實可以創建對象旋轉的引用並將其轉換爲euler天使,然後在將其應用到對象之前轉換回Quaternion。

但是,如果你只是想限制旋轉,我會做這樣的事情:

//the last rotation was pointed at the grey zone. 
private Quaternion prevAllowedRotation; 

void FixedUpdate(){ 
    if(!isValidRotation()){ 
     this.transform.rotation = prevAllowedRotation; 
    }else{ 
     this.transform.lookAt(lockToArea()); 
    } 
} 


private bool isValidRotation(){ 
    //I chose forward based on the image, find the direction that works for you 
    Ray ray = new Ray(this.transform.position, this.transform.forward); 
    RaycastHit hit; 
    if(Physics.Raycast(ray, out hit, 10f){ 
     if(hit.transform.tag == "wall"){ 
      return true; 
     } 
    } 
    return false; 
} 


private Vector3 lockToArea(Gameobject grey){ 
    Vector3 center = grey.transform.position; 
    //figure out how to get the position of the facing direction on the same plane as the grey area. 
    Vector3 pointerPosition = getPointerPosition(); 
    RaycastHit hit; 
    if(Physics.Linecast(pointerPosition, center, hit)){ 
     return hit.point; 
    } 
    return Vector3.zero; 

} 

private Vector3 getPointerOnPlane(){ 
    Ray ray = new Ray(this.transform.position, this.transform.forward); 
    // you need to figure out how to dyanmically get the distance so that the ray lands on the same plane as the vector 
    float distance = 0; 
    return ray.GetPoint(distance);  
} 

這將鎖定其旋轉僅在灰色的立方體被人指指點點。這應該對你有很大的幫助,你只需要知道IMU數據讀入的位置,並且與灰色立方體的中心在同一平面上。

+0

感謝@丹爲您回答。這與我所期望的非常接近,但我想要更進一步。我的旋轉限於灰色區域的面積,但是現在的問題是當我的立方體指向飛機(原始旋轉的意思)時,它卡在飛機的一側。例如,如果我將立方體從飛機的右側移出並垂直移動,它仍會卡在最後允許的位置,而不是沿着右邊緣上下移動。是否容易到達?再次感謝。 – javinair

+0

@javinair看看我所做的最新修改,我沒有足夠的時間去完成getPointerOnPlane的最後一步,但如果你弄清楚了,那麼你就完全想要什麼。我在重新閱讀您的問題後進行了這些修改。我也很高興它的工作,因爲我無法測試它的XD。 –

0

這是一種獲得y軸局部旋轉的方法。可以修改該功能以獲取x或z軸。

/// <summary> isolate the y-Component of a rotation </summary> 
private Quaternion yRotation(Quaternion q) 
{ 
    float theta = Mathf.Atan2(q.y, q.w); 

    // quaternion representing rotation about the y axis 
    return new Quaternion(0, Mathf.Sin(theta), 0, Mathf.Cos(theta)); 
} 

可以通過轉換成歐拉驗證結果在Unity檢查員:

public float yLocal; 
void Update() 
{ 
    yLocal = yRotation(this.transform.rotation).eulerAngles.y; 
}