求解校准四元数 [英] Solving for calibration quaternion

查看:117
本文介绍了求解校准四元数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个需要旋转向量的 Android 应用.我想使用 TYPE_ROTATION_VECTOR 但在我的一些测试设备中,磁力计至少可以说表现不佳.相反,TYPE_GAME_ROTATION_VECTOR 提供了更平滑的数据(但我无法获得相对于地球的方向).我最终做的是在加载数据时运行两个虚拟传感器.我现在对两者都有一个平均四元数,称它们为 R (TYPE_ROTATION_VECTOR) 和 Rg (TYPE_GAME_ROTATION_VECTOR).

I'm writing an Android app that requires the rotation vector. I'd like to use the TYPE_ROTATION_VECTOR but in some of my test devices the magnetometer doesn't perform well to say the least. Instead, the TYPE_GAME_ROTATION_VECTOR provides much smoother data (but I can't get direction relative to the Earth). What I ended up doing is while my data is loading, I run both virtual sensors. I now have an average quaternion for both, call them R (TYPE_ROTATION_VECTOR) and Rg (TYPE_GAME_ROTATION_VECTOR).

校准结束后,我只运行 TYPE_GAME_ROTATION_VECTOR,但想针对北校正它.我认为我能做的是:R = Rg * C 其中 C 是我的校准和Rg 是低通滤波器后的新 TYPE_GAME_ROTATION_VECTOR 数据.我试过的:

Once calibration is over I only run the TYPE_GAME_ROTATION_VECTOR, but would like to correct it for North. What I think I can do is something like: R = Rg * C where C is my calibration and Rg is the new TYPE_GAME_ROTATION_VECTOR data after a low pass filter. What I tried:

1. R = Rg * C
2. R * R' = Rg * C * R'
3. U = Rg * C * R' // Here U is the unit quaternion
4. C * R' = Rg'    // This is because quaternion multiplication is associative
                   // Rg * (C * R') = U from line 3 therefore (C * R') must be
                   // equal to the conjugate of Rg
5. C = Rg' * R''   // I found this online somewhere (I hope this is right)
6. C = Rg' * R     // R'' is just R

现在我有了 C,我可以为 TYPE_GAME_ROTATION_VECTOR 取新值(在低通滤波器之后)乘以 C 并得到实际的旋转四元数 R 应该类似于 TYPE_ROTATION_VECTOR 提供的旋转四元数,并具有稳定的北.

Now that I have C, I can take new values (after low pass filter) for the TYPE_GAME_ROTATION_VECTOR multiply them by C and get the actual rotation quaternion R that should be similar to the one that would have been provided by the TYPE_ROTATION_VECTOR with a steady North.

这让我很接近,但它并不完全有效.我正在使用一个非常简单的 AR 之类的应用程序进行测试,该应用程序显示一个漂浮在屏幕上的项目(其位置由设备方向决定).如果我省略校准,角色会显示并完美跟踪,但它不会显示在我的北方(我现在将其固定在 (0, 1, 0) ).如果我取旋转向量,得到四元数,乘以校准常数,跟踪就会被抛弃:

This gets me pretty close, but it doesn't quite work. I'm testing using a very simple AR like app that shows an item (who's position is determined by the device orientation) floating on the screen. If I leave out the calibration the character shows up and tracks perfectly, but it doesn't show up North of me (I have it fixed at (0, 1, 0) for now). If I take the rotation vector, get the quaternion, multiply by the calibration constant, the tracking gets thrown off:

  1. 围绕 Y 轴旋转设备会正确地水平移动项目,但它也会添加一个垂直分量,其中沿正方向旋转(使用右手规则)将我的项目向上移动(屏幕上的负 Y).
  2. 围绕 X 轴旋转设备可以正确垂直移动项目,但也会添加一个水平分量,其中正向旋转(使用右手法则)将我的项目向右移动(屏幕上的正 X).
  3. 围绕 Z 轴旋转设备有效.

对不起,描述太长,我只想确保所有细节都在那里.问题摘要:我希望能够获得大致为北的旋转矩阵并避免使用磁力计.我试图通过取 TYPE_ROTATION_VECTORTYPE_GAME_ROTATION_VECTOR 之间的平均差异来做到这一点,并使用它来校准"来自 TYPE_GAME_ROTATION_VECTOR 的未来值,但是它不起作用.有谁知道我如何计算校准(或任何其他部分)可能有什么问题?

Sorry for the long description, I just want to make sure all the details are there. Summary of the question: I want to be able to get a rotation matrix that is roughly north and avoid using the magnetometer. I'm trying to do this by taking the average difference between TYPE_ROTATION_VECTOR and TYPE_GAME_ROTATION_VECTOR and using that to "calibrate" future values from the TYPE_GAME_ROTATION_VECTOR but it doesn't work. Does anyone know what the issue might be with how I'm calculating the calibration (or any other part of this)?

一些附加信息:

private float[] values = null
public void onSensorChanged(SensorEvent event) {
    values = lowPass(event.values.clone(), values);
    Quaternion rawQuaternion = Quaternion.fromRotationVector(values);
    Quaternion calibratedQuaternion = rawQuaternion.mult(calibration);
    float[] rotationMatrix = calibratedQuaternion.getRotationMatrix();

    float[] pos = new float[] { 0f, 1f, 0f, 1f };
    Matrix.multiplyMV(pos, 0, rotationMatrix, 0, pos, 0);
    Matrix.multiplyMV(pos, 0, matrixMVP, 0, pos, 0);
    // Screen position should be found at pos[0], -pos[1] on a [-1,1] scale
}

Quaternion fromRotationVector(float[] r) {
    float[] Q = new float[4];
    SensorManager.getQuaternionFromVector(Q, r);
    return new Quaternion(Q);
}

Quaternion mult(Quaternion q) {
    Quaternion qu = new Quaternion();
    qu.w = w*q.w - x*q.x - y*q.y - z*q.z;
    qu.x = w*q.x + x*q.w + y*q.z - z*q.y;
    qu.y = w*q.y + y*q.w + z*q.x - x*q.z;
    qu.z = w*q.z + z*q.w + x*q.y - y*q.x;
    return qu;
}

float[] getRotationMatrix() {
    float[] M = new float[16];
    float[] V = new float[] { x, y, z, w };
    SensorManager.getRotationMatrixFromVector(M, V);
    return M;
}

推荐答案

我遇到了同样的问题并做了一些研究并意识到问题出在哪里.因此,基本上,仅通过观察 IMU 的静止方向,您只需对齐坐标系的一个轴,即重力方向的垂直轴.这就是围绕 Z 轴旋转的原因.

I had the same issue and did some research and realized where the problem is. So basically, by only looking at a stationary orientation of the IMU, you only align one axis of the coordinate system which is the vertical axis in the direction of gravity. That's why you rotations around Z axis works fine.

要完成静态校准,您必须包括平面运动并找到运动的主向量,例如您的 X 轴.Y 轴遵循右手法则.

To complete your static calibrations, you have to include a planar motion and find the principal vectors of the motion which will be the, say, your X axis. Y axis follows the right-hand rule.

简单地,围绕全局 X 轴旋转 IMU,然后查看 IMU 的陀螺仪输出.陀螺仪的主要组件应该朝向 X 轴.第一步找到Z轴,第二步找到X轴后,可以通过两者的叉积找到Y轴.使用这些轴,为平移创建旋转矩阵或四元数.

Simply, rotate the IMU around the global X axis and look at the gyroscope outputs of your IMU. The principal component of your gyroscope should be towards the X axis. After finding the Z axis in the first step and X axis in the second step, you can find Y axis by the cross product of the two. Using these axes, create the rotation matrix or the quaternion for the translations.

这篇关于求解校准四元数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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