安卓坐标系转换之二:旋转角(欧拉角)

欧拉角是按照既定的顺序,如依次绕z,y,x分别旋转一个固定角度,使用roll,yaw ,pitch分别表示物体绕,x,y,z的旋转角度,可以完成一个坐标系转换成另一个坐标系。
但是在安卓中,这里的角度定义有所不同,原文如下:

Note: This definition is different from yaw, pitch and roll used in aviation where the X axis is along the long side of the plane (tail to nose).
也就是说,X轴与航空系统所定义的不同。安卓里的X轴是短边。

具体如下图:

注: 图中旋转方向只是示意方向,不是指定的正方向!!!

当手机坐标系与地球坐标系重合时,三个角度都为0。

  • Azimuth:绕z轴旋转,磁北与y轴的夹角,顺时针增大,0到359度。
  • Pitch:绕x轴旋转的角度,即手机上下旋转,y轴往z轴方向为正。-180到180度。
  • Roll:绕y轴旋转的角度, 即手机的左右旋转,顺时针为正,-90到90度。

看一下getgetOrientation()方法,求出手机坐标系相对于世界坐标系三个轴的旋转角。

 public static float[] getOrientation(float[] R, float[] values) {
        /*
         * 4x4 (length=16) case:
         *   /  R[ 0]   R[ 1]   R[ 2]   0  \
         *   |  R[ 4]   R[ 5]   R[ 6]   0  |
         *   |  R[ 8]   R[ 9]   R[10]   0  |
         *   \      0       0       0   1  /
         *
         * 3x3 (length=9) case://上篇文章讲到的旋转矩阵
         *   /  R[ 0]   R[ 1]   R[ 2]  \
         *   |  R[ 3]   R[ 4]   R[ 5]  |
         *   \  R[ 6]   R[ 7]   R[ 8]  /
         *
         */
        if (R.length == 9) {
            values[0] = (float) Math.atan2(R[1], R[4]);//azimuth
            values[1] = (float) Math.asin(-R[7]);//pitch
            values[2] = (float) Math.atan2(-R[6], R[8]);//roll
        } else {
            values[0] = (float) Math.atan2(R[1], R[5]);
            values[1] = (float) Math.asin(-R[9]);
            values[2] = (float) Math.atan2(-R[8], R[10]);
        }
        return values;
    }

这里三个角的计算不大好理解,我画几个示意图大致讲一下我的看法。
还望大家一起讨论。
首先复习一下上一节R矩阵的内容:

R[0] = Hx;     R[1] = Hy;     R[2] = Hz;//【地球坐标系】X方向,指东
R[3] = Mx;     R[4] = My;     R[5] = Mz;//【地球坐标系】Y方向,指北
R[6] = Ax;     R[7] = Ay;     R[8] = Az;//【地球坐标系】Z反方向,向下

首先看azimuth,代码如下:

 values[0] = (float) Math.atan2(R[1], R[4]);

也就是arctan2(Hy,My)。 Hy是【地球坐标系】指向东的单位向量在【手机坐标系】Y轴上的分量。
同样地,My是【地球坐标系】指向北的单位向量在【手机坐标系】Y轴上的分量。
azimuth是绕z轴旋转,磁北与y轴的夹角,顺时针增大,0到359度。这里用了atan2函数,因为atan只可以表示 90o90o − 90 o 到 90 o ,atan2可以表示 180o180o − 180 o 到 180 o 。具体详细的区别可以看这里。
示意图如下:

pitch的代码如下:

values[1] = (float) Math.asin(-R[7]);

也就是arcsin(-Ay).Ay是【地球坐标系】指向下(重力)的单位向量在【手机坐标系】Y轴上的分量。示意图如下:

roll的代码如下:

 values[2] = (float) Math.atan2(-R[6], R[8]);

也就是arctan2(-Ax,Az).Ax【地球坐标系】指向下(重力)的单位向量在【手机坐标系】x轴上的分量。Az是【地球坐标系】指向下(重力)的单位向量在【手机坐标系】z轴上z的分量。
示意图如下:

这里需要指出的是,这个图的俯视方向是沿着y轴的正方向,所以本来是顺时针为正,这里是逆时针为负,所以也要加负号。

你可能感兴趣的:(Research)