Linear acceleration direction to track up and down phone movements

I am trying to track the movement of the device only in the vertical direction, i.e. moving up and down. This should be independent of the orientation of the device. Things that I already know or have tried are these

  • Linear acceleration is set by the TYPE_LINEAR_ACCELERATION sensor, and the axes are the phone’s axes and therefore tracking any specific axes does not matter.

  • I tried applying transposition or inversion of the rotation vector (the inverse or transposed for the rotation vector are the same), and then I tried to track the z direction of the linear acceleration vector. It doesn't seem to help.

  • I am trying to make a point product with gravity values ​​(TYPE_GRAVITY) to get the direction of acceleration, but it seems to be error prone. Even when I move my device quickly, he says he is going down.

I will describe this method here

dotProduct = vectorA[0]*vectorB[0]+vectorA[1]*vectorB[1] + vectorA[2]*vectorB[2]; cosineVal = dotProduct/(|vectorA|*|vectorB|) if(cosineVal > 0 ) down else Up. 

What is the disadvantage of the method? Please help, I'm stuck on this for a while.

+8
android vector motion-detection android-sensors
source share
1 answer

As I see, in the third method you are trying to find the cos of the angle between two vectors (the gravity vector and the acceleration vector). And the idea is that the angle is approaching 180 degrees, you have movement, if the angle is close to 0 degrees, you have movement down. Cosine is a function that has a positive meaning when the angle is from -90 to 90 degrees. Therefore, when your cosineVal value cosineVal positive, it means that the phone is going down, and even if cosineVal is closer to 1 movement, it is straight down. So it's true the other way around. When the cosine is negative (from 90 degrees to 270), you have movement.

You can probably get vectors from Sensor.TYPE_ACCELEROMETER from https://developer.android.com/reference/android/hardware/SensorEvent.html#values there you have a gravity vector and an acceleration vector.
I made a code snippet below that you can try.

 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 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]; float scalarProduct = gravity[0] * linear_acceleration[0] + gravity[1] * linear_acceleration[1] + gravity[2] * linear_acceleration[2]; float gravityVectorLength = (float) Math.sqrt(gravity[0] * gravity[0] + gravity[1] * gravity[1] + gravity[2] * gravity[2]); float lianearAccVectorLength = (float) Math.sqrt(linear_acceleration[0] * linear_acceleration[0] + linear_acceleration[1] * linear_acceleration[1] + linear_acceleration[2] * linear_acceleration[2]); float cosVectorAngle = scalarProduct / (gravityVectorLength * lianearAccVectorLength); TextView tv = (TextView) findViewById(R.id.tv); if (lianearAccVectorLength > 2) {//increase to detect only bigger accelerations, decrease to make detection more sensitive but noisy if (cosVectorAngle > 0.5) { tv.setText("Down"); } else if (cosVectorAngle < -0.5) { tv.setText("Up"); } } } @Override public void onAccuracyChanged(Sensor sensor, int i) { } } 
+1
source share

All Articles