获得从Android的陀螺仪四元数? [英] Get quaternion from Android gyroscope?

查看:2617
本文介绍了获得从Android的陀螺仪四元数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

官方的开发文档建议获得四元数的下列方式从3D旋转速率矢量(WX,WY,WZ)

The official development documentation suggests the following way of obtaining the quaternion from the 3D rotation rate vector (wx, wy, wz).

// Create a constant to convert nanoseconds to seconds.
private static final float NS2S = 1.0f / 1000000000.0f;
private final float[] deltaRotationVector = new float[4]();
private float timestamp;

public void onSensorChanged(SensorEvent event) {
  // This timestep's delta rotation to be multiplied by the current rotation
  // after computing it from the gyro sample data.
  if (timestamp != 0) {
    final float dT = (event.timestamp - timestamp) * NS2S;
    // Axis of the rotation sample, not normalized yet.
    float axisX = event.values[0];
    float axisY = event.values[1];
    float axisZ = event.values[2];

    // Calculate the angular speed of the sample
    float omegaMagnitude = sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ);

    // Normalize the rotation vector if it's big enough to get the axis
    // (that is, EPSILON should represent your maximum allowable margin of error)
    if (omegaMagnitude > EPSILON) {
      axisX /= omegaMagnitude;
      axisY /= omegaMagnitude;
      axisZ /= omegaMagnitude;
    }

    // Integrate around this axis with the angular speed by the timestep
    // in order to get a delta rotation from this sample over the timestep
    // We will convert this axis-angle representation of the delta rotation
    // into a quaternion before turning it into the rotation matrix.
    float thetaOverTwo = omegaMagnitude * dT / 2.0f;
    float sinThetaOverTwo = sin(thetaOverTwo);
    float cosThetaOverTwo = cos(thetaOverTwo);
    deltaRotationVector[0] = sinThetaOverTwo * axisX;
    deltaRotationVector[1] = sinThetaOverTwo * axisY;
    deltaRotationVector[2] = sinThetaOverTwo * axisZ;
    deltaRotationVector[3] = cosThetaOverTwo;
  }
  timestamp = event.timestamp;
  float[] deltaRotationMatrix = new float[9];
  SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector);
    // User code should concatenate the delta rotation we computed with the current rotation
    // in order to get the updated rotation.
    // rotationCurrent = rotationCurrent * deltaRotationMatrix;
   }
}

我的问题是:

这是很从加速的情况下,其中使用加速度的随着计算合成加速度不同的3轴是有道理的。

It is quite different from the acceleration case, where computing the resultant acceleration using the accelerations ALONG the 3 axes makes sense.

我真的很困惑,为什么得到的转速也可以与子旋转速度的周围的3轴计算。这是没有道理给我。

I am really confused why the resultant rotation rate can also be computed with the sub-rotation rates AROUND the 3 axes. It does not make sense to me.

为什么这个方法 - 寻找综合轮换率幅度 - 甚至工作

Why would this method - finding the composite rotation rate magnitude - even work?

推荐答案

由于你的标题并没有真正符合您的问题,我想回答的,尽我所能。

Since your title does not really match your questions, I'm trying to answer as much as I can.

陀螺仪不给一个绝对的方向(如<一个href="http://developer.android.com/guide/topics/sensors/sensors_motion.html#sensors-motion-rotate">ROTATION_VECTOR)但围绕这些轴线他们在建造时,仅旋转速度'旋转'周围,这是由于陀螺仪想象一下下面的建筑。金色的是旋转的,并且由于物理法律它并不想改变其旋转。现在,您可以旋转的框架和测量这些转动。

Gyroscopes don't give an absolute orientation (as the ROTATION_VECTOR) but only rotational velocities around those axis they are built to 'rotate' around. This is due to the design and construction of a gyroscope. Imagine the construction below. The golden thing is rotating and due to the laws of physics it does not want to change its rotation. Now you can rotate the frame and measure these rotations.

现在,如果你想获得的东西从陀螺仪的当前旋转状态,你将不得不开始通过最初的旋转,称之为 Q0 不断增加该陀螺仪绕轴线测量到它的微小旋转的差异: Q1 = Q0 + gyro0 Q2 = Q1 + gyro1 ...

Now if you want to obtain something as the 'current rotational state' from the Gyroscope, you will have to start with an initial rotation, call it q0 and constantly add those tiny little rotational differences that the gyroscope is measuring around the axis to it: q1 = q0 + gyro0, q2 = q1 + gyro1, ...

在换句话说:陀螺​​仪给你它已经绕三建轴旋转的差异,这样你就不会创作的绝对值,但小三角洲

In other words: The Gyroscope gives you the difference it has rotated around the three constructed axis, so you are not composing absolute values but small deltas.

现在,这是非常笼统,留下了几个问题待解:

Now this is very general and leaves a couple of questions unanswered:

  1. 在哪里可以得到从初始位置?答:有一个在旋转矢量传感器 - 您可以使用从那里得到的四元数作为初始化
  2. 如何'之'q和陀螺仪?

根据旋转的目前重新presentation:如果您使用的是旋转矩阵,一个简单的矩阵乘法应该做的工作,如在意见建议(注意,这个矩阵乘法实现效率不高!)

Depending on the current representation of a rotation: If you use a rotation matrix, a simple matrix multiplication should do the job, as suggested in the comments (note that this matrix-multiplication implementation is not efficient!):

/**
 * Performs naiv n^3 matrix multiplication and returns C = A * B
 * 
 * @param A Matrix in the array form (e.g. 3x3 => 9 values)
 * @param B Matrix in the array form (e.g. 3x3 => 9 values)
 * @return A * B
 */
public float[] naivMatrixMultiply(float[] B, float[] A) {
    int mA, nA, mB, nB;
    mA = nA = (int) Math.sqrt(A.length);
    mB = nB = (int) Math.sqrt(B.length);

    if (nA != mB)
        throw new RuntimeException("Illegal matrix dimensions.");

    float[] C = new float[mA * nB];
    for (int i = 0; i < mA; i++)
        for (int j = 0; j < nB; j++)
            for (int k = 0; k < nA; k++)
                C[i + nA * j] += (A[i + nA * k] * B[k + nB * j]);
    return C;
}

要使用此方法,假设 mRotationMatrix 保持当前的状态,这两条线做的工作:

To use this method, imagine that mRotationMatrix holds the current state, these two lines do the job:

SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector);
mRotationMatrix = naivMatrixMultiply(mRotationMatrix, deltaRotationMatrix);
// Apply rotation matrix in OpenGL
gl.glMultMatrixf(mRotationMatrix, 0);

如果您选择使用四元数,再想象一下 mQuaternion 包含当前状态:

If you chose to use Quaternions, imagine again that mQuaternion contains the current state:

// Perform Quaternion multiplication
mQuaternion.multiplyByQuat(deltaRotationVector);
// Apply Quaternion in OpenGL
gl.glRotatef((float) (2.0f * Math.acos(mQuaternion.getW()) * 180.0f / Math.PI),mQuaternion.getX(),mQuaternion.getY(), mQuaternion.getZ());

四元数乘法描述在这里 - 方程(23)。请确保你正确运用乘法,因为它是不可交换的!

Quaternion multiplication is described here - equation (23). Make sure, you apply the multiplication correctly, since it is not commutative!

如果你想简单地知道你的设备的旋转(我想这是你最终想要的)我强烈建议ROTATION_VECTOR感应。而另一方面陀螺仪都相当precise用于测量转速,有一个非常良好的动态响应,但漂移受苦,不给你一个绝对方位(磁北或根据重力)。

If you want to simply know rotation of your device (I assume this is what you ultimately want) I strongly recommend the ROTATION_VECTOR-Sensor. On the other hand Gyroscopes are quite precise for measuring rotational velocity and have a very good dynamic response, but suffer from drift and don't give you an absolute orientation (to magnetic north or according to gravity).

更新:如果你想看到一个完整的例子,你可以下载源 - code一个简单的demo-app <​​/A> href="https://bitbucket.org/apacha/sensor-fusion-demo">https://bitbucket.org/apacha/sensor-fusion-demo.

UPDATE: If you want to see a full example, you can download the source-code for a simple demo-app from https://bitbucket.org/apacha/sensor-fusion-demo.

这篇关于获得从Android的陀螺仪四元数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆