Search code examples
androidaccelerometerandroid-sensorshardware-acceleration

android - detect downward acceleration, specifically an elevator


I want to be able to detect a situation where the phone has an acceleration towards the ground (probably means that the Gravity sensor has to be used here also).

I have read a lot about this topic in the Android docs, about High and Low pass filters and other posts, and right now what I have is a code sample that gets the acceleration in the X, Y and Z axis after stripping the gravity:

if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {

        final float alpha = (float) 0.8;

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

        linear_acceleration[0] = event.values[0] - gravity[0];
        linear_acceleration[1] = event.values[1] - gravity[1];
        linear_acceleration[2] = event.values[2] - gravity[2];  
}

So, the linear_acceleration is supposedly the acceleration in the X, Y, Z axis without the gravity.

This is all nice, but the problem obviously is that is depends on how the user holds the phone, for example, in the elevator - if he holds it flat, parallel to the ground - the Z axis will change, if he holds it up straight - the Y axis will change , etc.

So, for example, if the user holds the phone diagonally, the acceleration will be "divided" between the different axes, and some sort of math work, considering where the gravity direction is, will be needed to calculate the actual acceleration in that direction.

Correct me if I am wrong?

Is there a reliable way to detect the downward (towards the earth) acceleration? maybe using other sensors like Gyroscope?

BTW - about the TYPE_LINEAR_ACCELERATION type, I read this answer, saying that its actually not very accurate.


Solution

  • Use some basic physics. Acceleration is a vector. The magnitude of a vector v is always equal to (v.v)^.5, or the square root of the dot product. Or in simpler terms (x^2+y^2+z^2)^.5. That will tell you the amount of acceleration, but not if its towards or away from the earth.

    If you need to know if its going towards or away from earth- you can combine that with data from SensorManager.getOrientation. You may need to do that before they enter the elevator though- the orientation code uses gravity as one of its inputs, so it may be screwed up if you try to use it in an elevator. You'd need to test it out.

    If you need to break it down to acceleration in terms of earth x, y, and z axes- simple geometry. Take the angle from the orientation result, and use trig properties to convert axes. If you don't know the formulas you need to read up on trig a bit or you'll get them wrong even if I tell them to you.