gpt4 book ai didi

android - 从 Android 陀螺仪获取四元数?

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:51:25 26 4
gpt4 key购买 nike

The official development documentation建议使用以下方法从 3D 旋转速率向量 (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 个轴的加速度计算合成加速度是有意义的。

我真的很困惑,为什么合成的旋转速率也可以用 AROUND 3 个轴的子旋转速率来计算。这对我来说没有意义。

为什么这种方法 - 找到复合旋转速率幅度 - 甚至会奏效?

最佳答案

由于你的标题与你的问题不太相符,我尽量回答。

陀螺仪不提供绝对方向(如 ROTATION_VECTOR ),但仅提供围绕它们“旋转”的那些轴的旋转速度。这是由于 gyroscope 的设计和构造所致.想象一下下面的结构。金色的东西在旋转,由于 laws of physics它不想改变它的旋转。现在您可以旋转框架并测量这些旋转。

Illustration of a Gyroscope

现在,如果您想从陀螺仪中获取“当前旋转状态”,则必须从初始旋转开始,将其称为 q0 并不断添加那些微小的旋转差异陀螺仪围绕它的轴进行测量:q1 = q0 + gyro0, q2 = q1 + gyro1, ...

换句话说:陀螺仪为您提供了它围绕三个构造轴旋转的差异,因此您不是在构成绝对值,而是在构成小的增量。

现在这是非常笼统的,还有几个问题没有得到解答:

  1. 我从哪里获得初始职位?答案:看看旋转矢量传感器——您可以使用从那里获得的四元数作为初始化
  2. 如何“求和”q 和陀螺仪?

根据旋转的当前表示:如果您使用旋转矩阵,一个简单的矩阵乘法应该可以完成这项工作,如评论中所建议的(请注意,这种矩阵乘法实现效率不高!):

/**
* 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 保存当前状态,这两行代码完成此工作:

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

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

// 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());

描述了四元数乘法here - equation (23) .确保正确应用乘法,因为它不可交换!

如果您只想知道设备的旋转(我想这就是您最终想要的),我强烈推荐 ROTATION_VECTOR-Sensor。另一方面,陀螺仪在测量旋转速度方面非常精确,并且具有非常好的动态响应,但会出现漂移并且不会为您提供绝对方向(磁北或重力方向)。

更新:如果您想查看完整示例,可以下载一个简单的源代码 demo-app来自 https://bitbucket.org/apacha/sensor-fusion-demo .

关于android - 从 Android 陀螺仪获取四元数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18587262/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com