androidandroid-sensorssensor-fusion

Sensors required for LINEAR_ACCELERATION


Background : I am developing an app whose core functionality includes getting the Linear Acceleration values from an android phone, among others. I am also planning on providing Devices along with the app installations, as our target customers are mainly organizations, and the system is locally deployed, not through the store.

The dilemma : Now when choosing a device, what are the hardware sensors that are required in the device to obtain the LINEAR_ACCELERATION metric reliably?

On searching, I found out that LINEAR_ACCELERATION is a "fused" sensor that uses a combination of Hardware and/or software implementations to subtract the gravity factor from ACCELEROMETER readings.

I found this here :

TYPE_LINEAR_ACCELERATION, TYPE_GRAVITY, TYPE_ROTATION_VECTOR are "fused" sensors which return respectively the linear acceleration, gravity and rotation vector (a quaternion). It is not defined how these are implemented. On some devices they are implemented in h/w, on some devices they use the accelerometer + the magnetometer, on some other devices they use the gyro.

There is not much else info on this out there. So can someone please provide more info on this?

Thanks in advance.


Solution

  • After a lot of trial and error with various devices, I think I now have a rough idea:

    First, from this android-developers forum post :

    TYPE_LINEAR_ACCELERATION, TYPE_GRAVITY, TYPE_ROTATION_VECTOR are "fused" sensors which return respectively the linear acceleration, gravity and rotation vector (a quaternion). It is not defined how these are implemented. On some devices they are implemented in h/w, on some devices they use the accelerometer + the magnetometer, on some other devices they use the gyro.

    So there's that.

    Now what I found from trial and error was that devices with only an accelerometer do not provide the LINEAR_ACCELERATION sensor (there may be exceptions, some devices may still have the sensor, but none of the devices i tried had that).

    So to get the LINEAR_ACCELERATION sensor, you have to have at least a magnetometer or a gyro - which is very uncommon in smartphones below INR 8000 ($120).

    Now, not part of the question but how do you write your code to run on both these types of devices?

    Well, what I ended up doing was this :

    first, check whether the device has the sensor:

    Sensor linearAcceleration = sMgr.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION),
    
    if (linearAcceleration==null){
       hasLinearAccSensor = false;
    }
    else {
       hasLinearAccSensor = true;
    }
    

    If you have the sensor, then cool! but if you dont, then you can use the TYPE_ACCELEROMETER sensor and workout the Linear acceleration yourself. Something like this :

    public void processPseudoAcceleration(SensorEvent event)
    {
        // alpha is calculated as t / (t + dT)
        // with t, the low-pass filter's time-constant
        // and dT, the event delivery rate
    
        final float alpha = 0.8f;
    
        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];
    
        float linear_acceleration[] = {0,0,0};
    
        linear_acceleration[0] = event.values[0] - gravity[0];
        linear_acceleration[1] = event.values[1] - gravity[1];
        linear_acceleration[2] = event.values[2] - gravity[2];
    
        setAccValues(linear_acceleration[0],linear_acceleration[1],linear_acceleration[2]);
    }
    

    But note that in my test, I have found this function to be not as reliable as the actual sensor readings, but it will do for most applications.

    Hope someone finds this useful. Cheers.