Search code examples
androidandroid-sensorsmagnetometersensormanager

How to detect magnetic north / azimuth without Magnetometer


I'm working on an Android device which does not have a Magnetometer but has a Rotation Sensor (Gyro) and Gravity Sensor and GPS. I would like to determine True North / Azimuth from these sensors but can't figure out how. Without a Magnetometer, how do I determine the orientation of this device? Clearly somehow it knows where North is given the Maps app works just fine.


Solution

  • UPDATE:

    You can the Rotation Vector Sensor that seems perfect for your situation.

    private SensorManager mSensorManager;
    private Sensor mSensor;
    ...
    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
    

    The system of coordinates you want is as follows:

    • X is defined as the vector product Y x Z. It is tangential to the ground at the device's current location and points approximately East.
    • Y is tangential to the ground at the device's current location and points toward the geomagnetic North Pole.
    • Z points toward the sky and is perpendicular to the ground plane.

    enter image description here


    Android makes a lot of sensors available

    if you specifically wish to use the gyroscope (Sensor.TYPE_GYROSCOPE) you could do it like this (taken from the Google example):

    private SensorManager mSensorManager;
    private Sensor mSensor;
    ...
    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
    
    public void onSensorChanged(SensorEvent event) {
          //...
    }
    

    but you could try and check if you can use a higher level API that will leverage more than one sensor

    You should have a look at this simple example by JavaCodeGeeks where they leverage the default Sensor.TYPE_ORIENTATION to build an android compass

    Just a little more info on the Sensor.TYPE_ORIENTATION. According to Google you can still use device orientation, but by calling getOrientation() instead of acting directly over the sensor.

    Instead of using raw data from the orientation sensor, we recommend that you use the getRotationMatrix() method in conjunction with the getOrientation() method to compute orientation values, as shown in the following code sample. As part of this process, you can use the remapCoordinateSystem() method to translate the orientation values to your application's frame of reference.

    The bad news is that both getOrientation() and the old Sensor.TYPE_ORIENTATION rely at least partially on the magnetometer

    Hope this helps!