根據旋轉前後的向量值求旋轉矩陣

根據旋轉前後的向量值求旋轉矩陣

如果已知旋轉前後的一向量的變化,那麼該如何求這個旋轉矩陣呢?本篇結合Rodrigues' rotation formula,介紹一下該旋轉矩陣的求法。

1.旋轉角度

已知旋轉前向量爲P, 旋轉後變爲Q。由點積定義可知:

image可推出P,Q之間的夾角爲:

image

2. 旋轉軸

由1中可知,旋轉角所在的平面爲有P和Q所構成的平面,那麼旋轉軸必垂直該平面。

假定旋轉前向量爲a(a1, a2, a3), 旋轉後向量爲b(b1, b2, b3)。由叉乘定義得:

image

所以旋轉軸c(c1, c2, c3)爲:

image

3.  羅德里格旋轉公式(Rodrigues' rotation formula)

3.1 公式

已知單位向量Inline3 , 將它旋轉θ角。由羅德里格旋轉公式,可知對應的旋轉矩陣Inline5 :

image

其中I是3x3的單位矩陣,

omega^~ 是叉乘中的反對稱矩陣r:

NumberedEquation1

3.2 公式證明

假設在座標系(x, y, z)中,向量v=ax+by+cz,v繞z軸逆時針旋轉θ角後得到新的向量v’。

img1

根據2維(x,y)面上的旋轉公式可得:

image

推出:

image已知:

image將上式帶入v’的公式:

image  將cz替換掉,可得:

image

將上式中的叉乘表示爲反對稱矩陣得:

image

另外:

image

最終可以推出:

image

上式即爲羅德里格旋轉公式。

 

4. 求旋轉矩陣

根據旋轉前後的兩個向量值,使用上面的方法,先求出旋轉角度和旋轉軸,然後用羅德里格旋轉公式即可求出對應的旋轉矩陣。

C#的實現代碼如下:

複製代碼
void Calculation(double[] vectorBefore, double[] vectorAfter)
{
    double[] rotationAxis;
    double rotationAngle;
    double[,] rotationMatrix;
    rotationAxis = CrossProduct(vectorBefore, vectorAfter);
    rotationAngle = Math.Acos(DotProduct(vectorBefore, vectorAfter) / Normalize(vectorBefore) / Normalize(vectorAfter));
    rotationMatrix = RotationMatrix(rotationAngle, rotationAxis);
}

double[] CrossProduct(double[] a, double[] b)
{
    double[] c = new double[3];

    c[0] = a[1] * b[2] - a[2] * b[1];
    c[1] = a[2] * b[0] - a[0] * b[2];
    c[2] = a[0] * b[1] - a[1] * b[0];

    return c;
}

double DotProduct(double[] a, double[] b)
{
    double result;
    result = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];

    return result;
}

double Normalize(double[] v)
{
    double result;

    result = Math.Sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);

    return result;
}

double[,] RotationMatrix(double angle, double[] u)
{
    double norm = Normalize(u);
    double[,] rotatinMatrix = new double[3,3];
    
    u[0] = u[0] / norm;
    u[1] = u[1] / norm;
    u[2] = u[2] / norm;

    rotatinMatrix[0, 0] = Math.Cos(angle) + u[0] * u[0] * (1 - Math.Cos(angle));
    rotatinMatrix[0, 1] = u[0] * u[1] * (1 - Math.Cos(angle) - u[2] * Math.Sin(angle));
    rotatinMatrix[0, 2] = u[1] * Math.Sin(angle) + u[0] * u[2] * (1 - Math.Cos(angle));

    rotatinMatrix[1, 0] = u[2] * Math.Sin(angle) + u[0] * u[1] * (1 - Math.Cos(angle));
    rotatinMatrix[1, 1] = Math.Cos(angle) + u[1] * u[1] * (1 - Math.Cos(angle));
    rotatinMatrix[1, 2] = -u[0] * Math.Sin(angle) + u[1] * u[2] * (1 - Math.Cos(angle));
      
    rotatinMatrix[2, 0] = -u[1] * Math.Sin(angle) + u[0] * u[2] * (1 - Math.Cos(angle));
    rotatinMatrix[2, 1] = u[0] * Math.Sin(angle) + u[1] * u[2] * (1 - Math.Cos(angle));
    rotatinMatrix[2, 2] = Math.Cos(angle) + u[2] * u[2] * (1 - Math.Cos(angle));

    return rotatinMatrix;
}
複製代碼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章