math - Android getOrientation Azimuth gets polluted when phone is tilted -
i'm having annoying problem ar view acting compass. when hold phone in portrait (so screen pointing face), call remapcoordinatesystem
pitch 0 when holding portrait. azimuth (compass functionality) perfect, tilt phone azimuth gets ruined, if bend forward azimuth increases , if bend backwards decreases.
i use 2 sensors readings, sensor.type_magnetic_field
, sensor.type_gravity
.
i use lowpassfilter pretty basic, it's implemented alpha constant , used directly on read values sensors.
here 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);
as see there no magic here. call piece of code when gravitymetervalues , magnetometervalues ready used.
my question how stop azimuth going crazy when tilt phone?
i checked free app on google play store, compass , hasn't solved problem, hope there solution.
i have 2 solutions in mind:
make ar view work in constrainted pitch angles, right have
pitch >= -5 && pitch <= 30
. if isn't fullfilled user shown screen asks him/her rotate phone portrait.somehow use pitch suppress azimuth, seems pretty device-specific solution though, of course i'm open suggestions.
i can add i've been searching couple of hours decent solution , haven't found has given me better solutions 2) here.
thanks in advance!
for complete code see https://github.com/hoananguyen/dsensor
keep history , average out, not know correct interpretation of pitch , roll following code azimuth only.
class members
private list<float[]> mrothist = new arraylist<float[]>(); private int mrothistindex; // change value azimuth stable , fit requirement private int mhistorymaxlength = 40; float[] mgravity; float[] mmagnetic; float[] mrotationmatrix = new float[9]; // direction of camera, valid if device tilted // @ 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 degree of tilt device independent of orientation (portrait or landscape) // if less 25 or more 155 degrees device 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 undefined, need clear history clearrothist(); mfacing = float.nan; } else { setrothist(); // mfacing = azimuth 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]; (float[] value : values) { (int = 0; < 9; i++) { result[i] += value[i]; } } (int = 0; < 9; i++) { result[i] = result[i] / values.size(); } return result; }
Comments
Post a Comment