gpt4 book ai didi

Android getOrientation 方位角在手机倾斜时被污染

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:27:41 27 4
gpt4 key购买 nike

我遇到了一个非常烦人的问题,AR View 就像一个指南针。因此,当我纵向握住手机(这样屏幕就指向我的脸)时,我会调用 remapCoordinateSystem纵向握住时音高为0。然后方位角(罗盘功能)是完美的,但是一旦我倾斜手机,方位角就会被破坏,如果我向前弯曲,方位角会增加,如果我向后弯曲,它会减小。

我使用 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);

如您所见,这里没有魔法。当 gravitymeterValues 和 magnetometerValues 准备好使用时,我调用这段代码。

我的问题是,当我倾斜手机时,如何防止方位角变得疯狂?

我查看了 Google Play 商店中的一款免费应用 Compass,它并没有解决这个问题,但我希望有解决方案。

我想到了 2 个解决方案:

  1. 让 AR View 仅在非常受限的俯仰角下工作,现在我有类似 pitch >= -5 && pitch <= 30 的东西.如果未填满,则会向用户显示一个屏幕,要求他/她将手机旋转为纵向。

  2. 以某种方式使用俯仰角来抑制方位角,虽然这似乎是一个非常针对特定设备的解决方案,但我当然愿意接受建议。

我还可以补充一点,我已经花了几个小时来寻找合适的解决方案,但我没有找到比 2) 此处更好的解决方案。

提前致谢!

最佳答案

完整代码见https://github.com/hoananguyen/dsensor
保留历史并取平均值,我不知道俯仰和横滚的正确解释,所以以下代码仅适用于方位角。

类(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;
}

关于Android getOrientation 方位角在手机倾斜时被污染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17979238/

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