我有一个非常恼人的问题,像一个指南针AR视图。所以,当我拿着手机在纵向(使画面指着我的脸),然后我叫 remapCoordinateSystem
的间距为0时,持有其肖像。然后方位角(指南针功能)是完美的,但只要我倾斜手机的方位被毁了,如果我向前弯曲方位增加,如果我向后弯曲则减。
I'm having a really annoying problem with a AR view acting like a compass. So when I hold the phone in portrait (so that the screen is pointing to my face), then I call the remapCoordinateSystem
that the pitch is 0 when holding it portrait. Then the azimuth (compass functionality) is perfect, but as soon as I tilt the phone the azimuth gets ruined, if I bend forward the azimuth increases and if I bend backwards it decreases.
我用2个传感器,以获取读数, Sensor.TYPE_MAGNETIC_FIELD
和 Sensor.TYPE_GRAVITY
。
I use 2 sensors to get the readings, Sensor.TYPE_MAGNETIC_FIELD
and Sensor.TYPE_GRAVITY
.
我用的lowpassfilter是pretty的基础,它的实施与字母的常数,直接从传感器上使用的读值。
I use a lowpassfilter which is pretty basic, it's implemented with an alpha constant and is used directly on the read values from the sensors.
下面是我的code:
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);
正如你看到的也没有神奇的在这里。我称这片code当gravitymeterValues和magnetometerValues是随时可以使用。
As you see there is no magic here. I call this piece of code when the gravitymeterValues and the magnetometerValues are ready to be used.
我的问题是如何阻止方位角从快要疯了,当我倾斜手机?
My question is how do I stop the azimuth from going crazy when I tilt the phone?
我检查了谷歌一个免费的应用程序Play商店,北斗的到现在也没有解决这个问题,但我希望有一个解决方案。
I checked a free app on the Google Play Store, Compass and it hasn't solved this problem, but I hope there is a solution.
我心目中2解决方案:
请在AR视图只能在非常constrainted俯仰角,现在我有这样的事情间距&GT; = -5安培;&安培;间距&LT; = 30
。如果这不是fullfilled显示给用户,询问他的画面/她的旋转手机的画像。
Make the AR view only work in very constrainted pitch angles, right now I have something like pitch >= -5 && pitch <= 30
. If this isn't fullfilled the user is shown a screen that asks him/her to rotate the phone to portrait.
不知怎么用球场上燮preSS的方位,这似乎是一个pretty的设备,具体的解决方案,虽然,但当然我开放的建议。
Somehow use the pitch to suppress the azimuth, this seems like a pretty device-specific solution though, but of course I'm open for suggestions.
我还可以补充一点,我一直在寻找了几个小时,一个体面的解决办法,我还没有发现任何给我任何超过2更好的解决方案)在这里。
I can also add that I've been searching for a couple of hours for a decent solution and I haven't found any that has given me any better solutions than 2) here.
在此先感谢!
请一个历史平均出来,我不知道俯仰和横滚的正确跨pretation所以下面code是方位角只
Keep a history and average out, I do not know the correct interpretation of pitch and roll so the following code is for azimuth only
类成员
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
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;
}