Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly calculate linear acceleration using AcceleroMeter in Android

To my utmost surprise, in Android 4.0+ they decided to remove LINEAR ACCELERATION sensor from available software sensors and put it inside a hardware sensor, the gyroscope that is rarely available in regular phones. I don't know why they did it, but imagine my surprise when I delivered the software that was tested on a cheap 2.3 phone, and on 2 months old phone it shows Unable to instantiate linear acceleration sensor. Why have they done it?

To save my skin, I checked if an Accelerometer is available in the phone, and it does. Based on this article, I should be able to calculate linear acceleration using the data from accelerometer. I checked the code and I see a variable that has no declaration available.

public void onSensorChanged(SensorEvent event){
  // In this example, alpha is calculated as t / (t + dT),
  // where t is the low-pass filter's time-constant and
  // dT is the event delivery rate.

  final float alpha = 0.8;
  float[] gravity=new float[]{0.0f,0.0f,0.0f}; //should it be here???

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

  // Remove the gravity contribution with the high-pass filter.
  linear_acceleration[0] = event.values[0] - gravity[0];
  linear_acceleration[1] = event.values[1] - gravity[1];
  linear_acceleration[2] = event.values[2] - gravity[2];
}

What does the gravity array contain in the first run? Should I add it like

float[] gravity=new float[]{0.0f,0.0f,0.0f};

?

Or should it contain real gravity data that is available via the Gravity sensor (also not available in regular devices)?

Does the calculation result proper linear acceleration data? Is it possible to calculate just by substracting a number from the incoming sensor data?

like image 420
Nestor Avatar asked Jan 05 '14 15:01

Nestor


People also ask

Can accelerometer measure linear acceleration?

1. Accelerometer sensors measure the difference between any linear acceleration in the accelerometer's reference frame and the earth's gravitational field vector.

How do you calculate acceleration from an accelerometer?

An accelerometer actually measures normal force or restoring force which we equate to acceleration using the formula, F=ma.

How does a linear accelerometer work?

The linear accelerometer measures the acceleration applied to the sensor built-in into the device, excluding the force of gravity, in m/s². For example, you could use this sensor to see how fast your car is going. The linear acceleration sensor always has an offset, which you need to remove.

What is accelerometer How do you use accelerometer in mobile devices?

The accelerometer is an in-built comment of a smartphone to measure its acceleration. It tracks the different motion like shaking, tilting, swinging, and rotating and accordingly change the orientation of your app. To calculate and detect the motion, the accelerometer uses the value of XYZ.


1 Answers

Actually what is done in that docs provided code snippet is that they take data from accelerometer(which contains both gravity and linear acceleration) and filter it. So how it basically works, we take raw data and assume that gravity vector is something constant and cannot change very quickly, opposite to linear acceleration, which changes really fast. So let's say if we take 80% of past counted gravity vector and add 20% of raw data we filter fast linear acceleration peaks and get gravity vector. If we remove gravity vector from raw data we get linear acceleration without gravity. Google for exponential filter for more information. Here you can play with it http://copterpilot.ru/custom-app/exponential/. So you can easily initialize your global gravity array of floats with zeros and wait a little for filtered data. Here is code snippet

public class MainActivity extends AppCompatActivity implements SensorEventListener {
private float[] gravity = new float[3];
private float[] linear_acceleration = new float[3];

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    SensorManager mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    Sensor mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}

@Override
public void onSensorChanged(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];

    linear_acceleration[0] = event.values[0] - gravity[0];
    linear_acceleration[1] = event.values[1] - gravity[1];
    linear_acceleration[2] = event.values[2] - gravity[2];
}  
}
like image 100
thekekc Avatar answered Sep 30 '22 02:09

thekekc