四元数“常规旋转”在转换为轴角时给出奇怪的值

时间:2011-11-22 10:54:27

标签: java rotation angle quaternions

我的自定义Quaternion实现似乎存在问题。 Download My quaternion implementation in Java

当我想要这个片段时,为了看到四元数角度演变,在Main()方法中:

    Quaternion currentRotation = Quaternion.buildIdentityQuaternion();
    Quaternion constantRotation = Quaternion.buildFromAxisAngle(10, 0,1,0);

    while(true){
        float angle = currentRotation.toAxisAngle()[0];
        System.out.println(angle);
        currentRotation = constantRotation.mulInLeftOf(currentRotation);
    }

我得到了以下结果:

0.0
9.99997
19.999975
29.999979
39.99998
49.999977
59.999977
69.99998
79.99997
89.99997
99.99997
109.99997
119.99997
129.99997
139.99997
149.99997
159.99997
169.99997
179.99997
189.99998
199.99998
209.99998
219.99998
230.0
240.0
250.00002
260.00003
270.00003
280.00003
290.00006
300.0001
310.00012
320.00015
330.00024
340.00037
350.00082
360.0
350.00012
340.0001
330.0001
320.0001
310.00006
300.00006
290.00006

那么为什么角度值首先变为360度然后逐渐减小到0度呢?虽然我在Quaternion#toAxisAngle()方法中用公式2 * Acos(Quaternion.w)计算了角度?也许实现并不坏,所以如何计算角度,使其返回0,10,...,350,360,0,10,......,350,360,0,10等等? / p>

最后,有没有办法计算真实角度?那个角度跨越了值:0,10,20,30,......,360,0,10,20 ......?


然而,我设法在JOGL程序中使用它来定期旋转简单的6色立方体,只需每次计算四元数乘法并在结果四元数上调用toMatrix()方法。有什么用(不要注意JOGL的具体实现细节):

  // The OpenGL functionnalities of my program
  MyJOGLEventListener implements GLEventListener {

       Quaternion myCurrentRotation = Quaternion.buildIdentityQuaternion() // w=1, x=0, y=0, z=0
       Quaternion constantRotation = Quaternion.buildFromAxisAngle(0.02f, 0,1,0) // angle = 0.02 degrees, x=0, y=1, z=0

       GLUgl2 glu = new GLUgl2();

       public void display(GLAutoDrawable drawable) {
            GL2 gl = drawable.getGL().getGL2();
            gl.glClear(/* OMITTED : color buffer and depth buffer*/);
            gl.glLoadIdentiy();

            glu.gluLookAt(/* OMITTED */);

            /// the three most relevent lines ///////////////////////////////////
            gl.glMultMatrix(myCurrentRotation.toMatrix(), 0);

            MyCubeDrawer.drawCube(gl);

            myCurrentRotation = constantRotation.mulInLeftOf(myCurrentRotation);
            //////////////////////////////////////////////////////////////////////

      }

     // OMITED : in init(GLAutoDrawable) method, I set up depth buffer
     // OMITED : the reshape(GLAutoDrawable drawable, int x, int y, int width, int height) sets the viewport and projection
 }

此致

1 个答案:

答案 0 :(得分:4)

我怀疑你的四元数实现没问题。使用四元数传递360度时,它会反转旋转轴。因此,首先,您的四元数表示正 y 轴周围的正旋转;但是,一旦你穿过360度,它就会开始代表 y 轴周围的正向旋转。

所以你得到的角度仍然是正确的。零的旋转通常表示为[1 0 0 0]。绕 y 轴旋转180度将表示为[0 0 1 0]。然后旋转360度(显然相当于0的旋转)出现[-1 0 0 0]。再旋转180度会给你[0 0 -1 0]这是四元数的一般属性。它们是2倍多余的。如果否定四元数的所有分量,则相当于围绕翻转轴旋转相反方向以获得相同的结果。

要获得您想要的内容,您只需检查四元数的 y 组件即可。如果它小于零,则从360减去计算的旋转,以便将轴翻转回正值。