Android getOrientation倾斜手机时,方位angular会受到污染

AR视图像一个指南针一样,真的很烦人。 所以当我拿着手机的肖像(使屏幕指向我的脸),然后我把它remapCoordinateSystem ,当它拿着肖像时,音调是0。 然后,方位angular(指南针function)是完美的,但只要我倾斜手机的方位angular被破坏,如果我弯曲的方位angular增加,如果我向后弯曲减less。

我使用2个传感器来读取Sensor.TYPE_MAGNETIC_FIELDSensor.TYPE_GRAVITY

我使用了一个非常基本的低通滤波器,它使用一个alpha常量来实现,并直接用于传感器的读取值。

这是我的代码:

 float[] rotationMatrix = new float[9]; SensorManager.getRotationMatrix(rotationMatrix, null, gravitymeterValues, magnetometerValues); float[] remappedRotationMatrix = new float[9]; SensorManager.remapCoordinateSystem(rotationMatrix, SensorManager.AXIS_X, SensorManager.AXIS_Z, remappedRotationMatrix); float results[] = new float[3]; SensorManager.getOrientation(remappedRotationMatrix, results); float azimuth = (float) (results[0] * 180 / Math.PI); if (azimuth < 0) { azimuth += 360; } float pitch = (float) (results[1] * 180 / Math.PI); float roll = (float) (results[2] * 180 / Math.PI); 

如你所见,这里没有魔法。 当重力计值和磁力计值准备好使用时,我把这段代码称为。

我的问题是,当我倾斜手机时,如何阻止方位发疯?

我在Google Play商店, Compass上查了一个免费的应用程序,并没有解决这个问题,但我希望有一个解决scheme。

我有两个解决scheme:

  1. 使AR视图只能在非常约束的俯仰angular度下工作,现在我有类似pitch >= -5 && pitch <= 30 。 如果未填满,则向用户显示一个屏幕,要求他/她将手机旋转至肖像。

  2. 不知何故,用这种方式压制方位angular,这看起来像是一个非常漂亮的设备特定的解决scheme,但当然我也乐意提供build议。

我还可以补充说,我一直在寻找一个体面的解决scheme几个小时,我还没有find任何比这里给了我更好的解决scheme。

提前致谢!

Solutions Collecting From Web of "Android getOrientation倾斜手机时,方位angular会受到污染"

有关完整的代码,请参阅https://github.com/hoananguyen/dsensor
保持一个历史和平均,我不知道正确的解释,俯仰和滚动,所以下面的代码是只为方位angular。

class级成员

 private List<float[]> mRotHist = new ArrayList<float[]>(); private int mRotHistIndex; // Change the value so that the azimuth is stable and fit your requirement private int mHistoryMaxLength = 40; float[] mGravity; float[] mMagnetic; float[] mRotationMatrix = new float[9]; // the direction of the back camera, only valid if the device is tilted up by // at least 25 degrees. private float mFacing = Float.NAN; public static final float TWENTY_FIVE_DEGREE_IN_RADIAN = 0.436332313f; public static final float ONE_FIFTY_FIVE_DEGREE_IN_RADIAN = 2.7052603f; 

onSensorChanged

 @Override public void onSensorChanged(SensorEvent event) { if (event.sensor.getType() == Sensor.TYPE_GRAVITY) { mGravity = event.values.clone(); } else { mMagnetic = event.values.clone(); } if (mGravity != null && mMagnetic != null) { if (SensorManager.getRotationMatrix(mRotationMatrix, null, mGravity, mMagnetic)) { // inclination is the degree of tilt by the device independent of orientation (portrait or landscape) // if less than 25 or more than 155 degrees the device is considered lying flat float inclination = (float) Math.acos(mRotationMatrix[8]); if (inclination < TWENTY_FIVE_DEGREE_IN_RADIAN || inclination > ONE_FIFTY_FIVE_DEGREE_IN_RADIAN) { // mFacing is undefined, so we need to clear the history clearRotHist(); mFacing = Float.NaN; } else { setRotHist(); // mFacing = azimuth is in radian mFacing = findFacing(); } } } } private void clearRotHist() { if (DEBUG) {Log.d(TAG, "clearRotHist()");} mRotHist.clear(); mRotHistIndex = 0; } private void setRotHist() { if (DEBUG) {Log.d(TAG, "setRotHist()");} float[] hist = mRotationMatrix.clone(); if (mRotHist.size() == mHistoryMaxLength) { mRotHist.remove(mRotHistIndex); } mRotHist.add(mRotHistIndex++, hist); mRotHistIndex %= mHistoryMaxLength; } private float findFacing() { if (DEBUG) {Log.d(TAG, "findFacing()");} float[] averageRotHist = average(mRotHist); return (float) Math.atan2(-averageRotHist[2], -averageRotHist[5]); } public float[] average(List<float[]> values) { float[] result = new float[9]; for (float[] value : values) { for (int i = 0; i < 9; i++) { result[i] += value[i]; } } for (int i = 0; i < 9; i++) { result[i] = result[i] / values.size(); } return result; }