25

Video explaining for those who does not understand


THIS ANSWER IS NOT CORRECTLY ANSWERED PLEASE TRY TO ANSWER IT WITH ANOTHER SOLUTION (100 Bounty is out of date)

Same question but better explained

This questions was accepted as a correct but it is not at all, I tried it with my old device ZTE and it worked most of time, but now I have a Samsung Galazy A5 2016 and it doesn't work, neither on a LG G3.

The thing is trying using Accelerometer and some Sensors I have to be able to detect any of those two moviments that I made on the Video.

There are two moviments :

  • Smashing it (with a little bit of velocity)
  • Free fall

I let you to decide and convince me what's the better option and EASIER one to do, with better I mean that works on most of devices.

Community
  • 1
  • 1
Skizo-ozᴉʞS ツ
  • 19,464
  • 18
  • 81
  • 148
  • There's a good example of Accelerometer here: https://github.com/aporter/coursera-android/tree/master/Examples/SensorFilteredAccelerometer – Mark Jan 25 '16 at 16:49
  • I saw it, but it doesn't explain how to detect the "action down" event... – Skizo-ozᴉʞS ツ Jan 25 '16 at 16:50
  • According to the docs http://developer.android.com/guide/topics/sensors/sensors_motion.html the force going down 'z' is SensorEvent.values[2] - when I wrote a simple app for acelerometer easiest way way to output the figures verbose to the screen as your moving the device around. – Mark Jan 25 '16 at 16:55
  • But how to get that force I mean, if this Y increases negativitly it's the down event? with the app that I've created now, if I do this move the Y goes for example from 4 to 0 or -0 so I've to compare this? – Skizo-ozᴉʞS ツ Jan 25 '16 at 16:56
  • Sorry 'z' axis is up and down - this post will prove useful - http://stackoverflow.com/questions/4848490/android-how-to-approach-fall-detection-algorithm as I understand it if a phone is falling and it approaches terminal velocity (9.8ms) then the sensor should be near 0 value, faster than that (ie forced down) a negative value. – Mark Jan 25 '16 at 17:01
  • Yes, that's what I understand too, but ... how to compare it as code? – Skizo-ozᴉʞS ツ Jan 25 '16 at 17:38
  • You cannot do that with event.values[2] since this is the value for the z-axis. If the phone is held up in portrait mode then the down acceleration is the value for the y-axis instead, thus using accelerator value is device orientation dependent. Using gravity and set mDeviation to .5f I got the correct result every time. I have code for all these sensors which include stable compass and others. It has been a few years since, let me clean up the code and then publish it on Github in a few days. – Hoan Nguyen Jan 29 '16 at 00:54
  • Alright... Do you have tested on differents devices? I mean the problem that you thought(if the device doesnt have accelerator uses gravity, etc..) will it work? – Skizo-ozᴉʞS ツ Jan 29 '16 at 00:56
  • I tested on 2 devices both do not have TYPE_GRAVITY. In one device it work pretty well. In the other the mDeviation is two large so it does not detect moving down. You have to adjust mDeviation per device. – Hoan Nguyen Jan 29 '16 at 01:03
  • Thats what I mean, I didnt want to hardcorde nothing ia there any algorithm to get mdeviation? – Skizo-ozᴉʞS ツ Jan 29 '16 at 06:02
  • @HoanNguyen Did you get the way to get the mDeviation dynamically? I mean for each device get the mDeviation to get it works? – Skizo-ozᴉʞS ツ Jan 30 '16 at 11:36
  • I do not have TYPE_GRAVITY in my devices and using low pass filter the gravity norm depends on the device orientation. That is the gravity norm of a device laying flat and still is different than the gravity norm of a device held up and still. This should not be the case since the only force acting on the device is gravity. I will try the world z-linear acceleration to see if it will work better, that means I will need to also register for TYPE_MAGNETIC_FIELD. I will post to Github when it is done. – Hoan Nguyen Jan 30 '16 at 17:36
  • @Skizo do your device has TYPE_GRAVITY? if so does the gravity norm is different depending on device orientation? – Hoan Nguyen Jan 30 '16 at 17:37
  • @HoanNguyen Alright, thanks... thank you so much for your effort man.. :) I'm also trying to understand how to do it correctly – Skizo-ozᴉʞS ツ Jan 30 '16 at 17:38
  • How do I know if I have TYPE_GRAVITY? – Skizo-ozᴉʞS ツ Jan 30 '16 at 17:38
  • getDefaultSensor(Sensor.TYPE_GRAVITY) and see if it is not null – Hoan Nguyen Jan 30 '16 at 18:03
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/102093/discussion-between-skizo-and-hoan-nguyen). – Skizo-ozᴉʞS ツ Jan 30 '16 at 18:12
  • Can't understand anything from the video what you want to achieve. – Maveňツ Feb 02 '17 at 05:31
  • One of those events, smashing or free falling but always only moving down – Skizo-ozᴉʞS ツ Feb 02 '17 at 06:02
  • I recommend first having the user "calibrate" the device so that you can determine what the standard accelerometer readings are with the device laying down on it's back, then you'll have your at rest measurement. Then you can determine if that measurement falls below a threshold (approaches or passes 0), it's moving down and trigger that event. Adjust the threshold for sensitivity. – Dave S Feb 04 '17 at 01:16
  • I thought the same first user has to see if his accelerometer or other sensors are fine, and then do it but u don't know how to do this – Skizo-ozᴉʞS ツ Feb 04 '17 at 09:16
  • Please explain the issue..you want to catch the speed of device in downword motion? If it is more than 9.18 m/s2 then you can give alert to the user. – Maveňツ Feb 06 '17 at 05:43

2 Answers2

14

A stationary device will have an gravity value of +9.81, which corresponds to the acceleration of the device (0 m/s2 minus the force of gravity, which is -9.81 m/s2). Thus if the device is moving downward from stationary then the gravity will be less than 9.81. A free fall device will have gravity equals 0.

Below is how to determine if the device starts moving downward. It will not be able to determine whether the device is moving downward if the device is already moving downward with constant speed, since in this case there is no acceleration downward and the gravity norm should be around 9.81.

You need to use TYPE_GRAVITY. If the device does not have TYPE_GRAVITY, then low pass filter TYPE_ACCELEROMETER to get the gravity vector.

As above a stationary device will have a gravity vector with norm equal 9.81. However, this value will vary slightly with devices. Thus you need first to determine this stationary gravity norm. You can do this by register for TYPE_GRAVITY or TYPE_ACCELEROMETER and ask the user to lay the device flat and then press a button. Once the button is pressed the app will calculate the norm of the gravity in onSensorChanged.

private float mStationaryGravityNorm;
private float mDeviation = 0.01;
private float mCount;
private boolean mIsCalculatingStationGravityNorm = true;

Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener( {
    @Override
    public void onClick(View v) {
        // register sensor
    }
    });

@Override
public void onSensorChanged(SensorEvent event) {
// Will average out 100 gravity values.
if (mIsCalculatingStationGravityNorm) {
    if (mCount++ < 100) {
        mStationaryGravityNorm += Math.sqrt(event.values[0] * event.values[0] + event.values[1] * event.values[1] + event.values[2] * event.values[2]);
    } else {
        mStationaryGravityNorm /= 100;
        mIsCalculatingStationGravityNorm = false;
} else {
    float gravityNorm = Math.sqrt(event.values[0] * event.values[0] + event.values[1] * event.values[1] + event.values[2] * event.values[2]);
    if (gravityNorm < mStationaryGravityNorm - mDeviation) {
    // moving down
    }
}

PS For moving up an down you do want to calculate gravity. When the device is stationary, the gravity norm is approximately 9.81 (depending on device). Now if the device is moving down, there is an acceleration downward, thus the gravity norm will be less than 9.81 and if the device is moving up the gravity norm will be more than 9.81. So by comparing the gravity norm against this stationary gravity norm, you will know if the device moving up or down. This is independent of the device orientation. TYPE_GRAVITY will give better accuracy but if the device does not have this type then low pass filter TYPE_ACCELERATOR will give you the gravity vector.

Hoan Nguyen
  • 18,033
  • 3
  • 50
  • 54
  • 1
    @Skizo I was literally was doing testing .. I looked at the figures produced and deduced I could detect a shake in that manner, easily able to change based on requirements, I.e. moving down or up .. Also I use an alert to sound when the desired event occurs .. At the end of the day, it doesn't matter what code you use as long as you understand it and it works :) – Mark Jan 28 '16 at 21:11
  • @MarkKeen Yes, but I'd like to run this app in more than my device and make it works... – Skizo-ozᴉʞS ツ Jan 28 '16 at 21:38
-1

if you want to see if the device is in free fall, you should check if the normal is closer to zero. http://developer.android.com/guide/topics/sensors/sensors_motion.html

public void onSensorChanged(SensorEvent event) {
    double noraml = Math.sqrt(Math.pow(event.values[0].getX(),2)+
                    Math.pow(event.values[1].getY(),2)+
                    Math.pow(event.values[2].getZ(),2));
    if (normal < 0)
        return true;
    return false;

}