Android - detect downward acceleration, in particular an elevator

I want to be able to detect a situation where the phone is accelerating with respect to the ground (which probably means that a gravity sensor should be used here as well).

I've read a lot about this topic in Android docs, high and low pass filters and other posts, and now I have a sample code that speeds up the X, Y and Z axes after removing 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, linear_acceleration

it is supposedly acceleration along the X, Y, Z axis without gravity.

This is all good, but the problem is obviously that it depends on how the user holds the phone, for example, in an elevator - if he holds it level, parallel to the ground - it will change Z axis

, if he holds it straight - it Y axis

will change, etc. ...

So, for example, if the user holds the phone diagonally, the acceleration will be "split" between the other axis, and some mathematical work will be required to calculate the actual acceleration given where the gravitational direction is in that direction.

Correct me if I'm wrong?

Is there a reliable way to detect downward acceleration (toward the ground)? perhaps using other sensors like a gyroscope?

Speaking of type TYPE_LINEAR_ACCELERATION

, I read this answer saying that its actually not very accurate.

+1


source to share


2 answers


Use some basic physics. Acceleration is a vector. The magnitude of the vector v is always (vv) ^ 5 or the square root of the dot product. Or in simpler terms (x ^ 2 + y ^ 2 + z ^ 2) ^ 5. This will tell you about acceleration, but not if it is pointing towards or off the ground.

If you need to know if it is coming to or from the ground, you can combine that with the SensorManager.getOrientation data. You may have to do this before they enter the elevator, although the orientation code uses gravity as one of its inputs, so if you try to use it in an elevator it might be messed up. You will need to check this.



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

0


source


I also wanted to just measure the vertical movement. This is how I did it and it worked for me. First post on this site and I have no idea how to format it correctly.

Use two different sensors for Android: Type_linear_Acceleration and Type_Gravity

Linear acceleration will give you acceleration on the X, Y and Z axis of the phone, and Gravity will do the same, but only for gravity. You know that the sum of the gravity values โ€‹โ€‹should = 9.8, but this will be split between the X, Y and Z coordinates depending on the orientation of the phone.

I won't go into the math too much, but the following will give you vertical acceleration without gravity. If you want to understand this, then do a little work on some values, as if the phone was held vertically and then horizontally, it works even if the phone is tilted.



vertical acceleration = (LinearAccelX * GravityX / 9.8) + (LinearAccelY * GravityY / 9.8) + (LinearAccelZ * GravityZ / 9.8).

See code below (unnecessary parts removed):

{public class MainActivity extends AppCompatActivity implements SensorEventListener {

SensorManager sm;
Sensor linearaccelerometer;
Sensor gravity;
double Yaccel;
double Xaccel;
double Zaccel;
double gravityY;
double gravityX;
double gravityZ;
double verticalAccel;

    sm = (SensorManager) getSystemService(SENSOR_SERVICE);
    linearaccelerometer = sm.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
    gravity = sm.getDefaultSensor(Sensor.TYPE_GRAVITY);

    sm.registerListener(this, linearaccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
    sm.registerListener(this, gravity, SensorManager.SENSOR_DELAY_NORMAL);
}

public void onSensorChanged(SensorEvent event) {

    Sensor sensor = event.sensor;

    if (sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION) {
        Xaccel = (double) event.values[0];
        Yaccel = (double) event.values[1];
        Zaccel = (double) event.values[2];
    }

    if (sensor.getType() == Sensor.TYPE_GRAVITY) {
        gravityX = (double) event.values[0];
        gravityY = (double) event.values[1];
        gravityZ = (double) event.values[2];
    }

    verticalAccel = (Xaccel * gravityX / 9.8) + (Yaccel * gravityY / 9.8) +  (Zaccel *gravityZ /9.8);

}

      

+1


source







All Articles