How can I get the magnetic field vector, independent of the device rotation? How can I get the magnetic field vector, independent of the device rotation? android android

How can I get the magnetic field vector, independent of the device rotation?


Do this

private static final int TEST_GRAV = Sensor.TYPE_ACCELEROMETER;private static final int TEST_MAG = Sensor.TYPE_MAGNETIC_FIELD;private final float alpha = (float) 0.8;private float gravity[] = new float[3];private float magnetic[] = new float[3];public void onSensorChanged(SensorEvent event) {    Sensor sensor = event.sensor;    if (sensor.getType() == TEST_GRAV) {            // Isolate the force of gravity with the low-pass filter.              gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];              gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];              gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];    } else if (sensor.getType() == TEST_MAG) {            magnetic[0] = event.values[0];            magnetic[1] = event.values[1];            magnetic[2] = event.values[2];            float[] R = new float[9];            float[] I = new float[9];            SensorManager.getRotationMatrix(R, I, gravity, magnetic);            float [] A_D = event.values.clone();            float [] A_W = new float[3];            A_W[0] = R[0] * A_D[0] + R[1] * A_D[1] + R[2] * A_D[2];            A_W[1] = R[3] * A_D[0] + R[4] * A_D[1] + R[5] * A_D[2];            A_W[2] = R[6] * A_D[0] + R[7] * A_D[1] + R[8] * A_D[2];            Log.d("Field","\nX :"+A_W[0]+"\nY :"+A_W[1]+"\nZ :"+A_W[2]);        }    }


Solution :

Possibility 1 :

MAGNETIC_FIELD is very unstable regarding rotation you could not relate on just some math to convert landscape and portrait values, the main reason is the hardware use different captors for different axises then when rotate occur you use a different hardware captor the value will never be the same, on some hi end device it will be the same but not on most devices.

if you want something to rely on and compatible on many devices you need to forget calculating the MAGNETIC_FIELD with rotation, but just force the orientation with your application. Force "portrait" orientation mode

Possibility 2 :

You talked about "magnetic fingerprint" of a location. if it's only about identifying a location without GPS you have plenty of other informations to work with. first "Wifi SSIDs" then "Mobile Networks Cells" also "Connected Wifi" etc. if this interest you i could give you code for it.

Possibility 3 :

If you absolutely need to calculate MAGNETIC_FIELD for your location, and don't want to force rotation... you could catch both value landscape and portrait instead of calculating them. then when you compare just compare to both values.

Also if you are looking to locate place where you have magnet or hight magnetic location you could work with a hi tolerance percentage just to detect if a magnet is present or so,

Note :

If you stick with the math don't forget that the function will be different on almost every device...don't hesitate to give more infos about your question i'll be pleased to adapt my answer ;)


to get the strength of the magnetic field, you have to get the x,y,z values of the magnetic field (from Sensor.TYPE_MAGNETIC_FIELD), and apply the following formula:

double magnetic_field_strength = Math.sqrt( (Xvalue*Xvalue) + (Yvalue*Yvalue) + (Zvalue*Zvalue) );

magnetic_field_strength is expressed in microtesla (µT)
It could be noted that the average magnetic field strength of the Earth is 50 µT, according to this website.


So a possible code would be:

private SensorEventListener sensorEventListener = new SensorEventListener() {       @Override    public void onSensorChanged(SensorEvent event) {        switch (event.sensor.getType()) {        case Sensor.TYPE_MAGNETIC_FIELD:                                    magnetic_field_strength = Math.sqrt((event.values[0]*event.values[0])+(event.values[1]*event.values[1])+(event.values[2]*event.values[2]));            break;                              default:             return;        }                    }}