Android Getorientation Azimuth Gets Polluted When Phone Is Tilted

Android getOrientation Azimuth gets polluted when phone is tilted

For complete code see https://github.com/hoananguyen/dsensor

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.

Class members

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

How to make azimuth and degree less shaky in Android

Solution is to apply (LPF) Low Pass Filter. It's smooth and working perfectly now.
I found the solution here: Low Pass Filter

How to get phone heading for augmented reality?

Both your code and the solution you found are wrong if by "phone facing" you means the opposite direction of the device z-coordinate. For augmented reality, you just call

remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);

independent of the device orientation. Then the azimuth in the call to getOrientation() gives the direction of the phone facing with respect to Magnetic North.

These 2 calls amount to projection of the device z-coordinate to the XY plane of the world coordinates and then calculate the direction of the resulting vector.

Android Sensor Upright Rotation

From the code above the parameters gravity and geomagnetic in mSensorManager.getRotationMatrix(rotationMatrix, I, gravity, geomagnetic); are probably zero array and thus your accy is always zero

Android trouble getting compass direction

You should use TYPE_GRAVITY instead of TYPE_ACCELEROMETER else you should low pass filter TYPE_ACCELEROMETER. Your problem lies mainly in

mGravity = sensorEvent.values;

and

mGeomagnetic = sensorEvent.values;

Since sensorEvent is a local variable and either mGravity or mGeomagnetic points to this value, either of these can be anything by the next time onSensorChanged is called. It should be

mGravity = sensorEvent.values.clone();

and

mGeomagnetic = sensorEvent.values.clone();

You can look at my answer at Android getOrientation Azimuth gets polluted when phone is tilted



Related Topics



Leave a reply



Submit