18

I'm writing an application and my aim is to detect when a user is walking. I'm using a Kalman filter like this:

float kFilteringFactor=0.6f;

        gravity[0] = (accelerometer_values[0] * kFilteringFactor) + (gravity[0] * (1.0f - kFilteringFactor));
        gravity[1] = (accelerometer_values[1] * kFilteringFactor) + (gravity[1] * (1.0f - kFilteringFactor));
        gravity[2] = (accelerometer_values[2] * kFilteringFactor) + (gravity[2] * (1.0f - kFilteringFactor));

        linear_acceleration[0] = (accelerometer_values[0] - gravity[0]);
        linear_acceleration[1] = (accelerometer_values[1] - gravity[1]);
        linear_acceleration[2] = (accelerometer_values[2] - gravity[2]);

        float magnitude = 0.0f;
        magnitude = (float)Math.sqrt(linear_acceleration[0]*linear_acceleration[0]+linear_acceleration[1]*linear_acceleration[1]+linear_acceleration[2]*linear_acceleration[2]);
        magnitude = Math.abs(magnitude);
if(magnitude>0.2)
  //walking

The array gravity[] is initialized with 0s.

I can detect when a user is walking or not (looking at the value of the magnitude of the acceleration vector), but my problem is that when a user is not walking and he moves the phones, it seems that he is walking.

Am I using the right filter?

Is it right to watch only the magnitude of the vector or have I to look at the single values ??

Jav_Rock
  • 21,011
  • 18
  • 115
  • 164
havanakoda
  • 183
  • 1
  • 1
  • 7
  • Are you considering the acceleration of the movement forward, or just the 'up and down'? – gnclmorais Feb 14 '11 at 15:41
  • I'm considering up and down and rotation of the phones. When a user is not walking he is allowed to do these kind of movement; but I don't want that these will be detected as walking. – havanakoda Feb 14 '11 at 15:48
  • Is the user holding the phone in their hand and walking, or putting it in their pocket and walking? – jcwenger Mar 16 '11 at 12:18
  • the user is holding his phone in his hands – havanakoda Apr 04 '11 at 11:25
  • Can you try using camera to detect movement in place of accelerometer, as you said the user shall be holding the phone in their hand while using your app/ game! – APZ Jun 13 '12 at 13:59
  • I encourage users to look at my answer, which gives an overview of the APIs Google offers to detect a range of different activities. – Dick Lucas Jul 16 '15 at 15:26
  • QQ: Does accelerometer_values[0] means x axis ; accelerometer_values[1] means y axis and accelerometer_values[2] means z axis – Dev.K. Jul 25 '17 at 01:33

5 Answers5

23

Google provides an API for this called DetectedActivity that can be obtained using the ActivityRecognitionApi. Those docs can be accessed here and here.

DetectedActivity has the method public int getType() to get the current activity of the user and also public int getConfidence() which returns a value from 0 to 100. The higher the value returned by getConfidence(), the more certain the API is that the user is performing the returned activity.

Here is a constant summary of what is returned by getType():

  • int IN_VEHICLE The device is in a vehicle, such as a car.
  • int ON_BICYCLE The device is on a bicycle.
  • int ON_FOOT The device is on a user who is walking or running.
  • int RUNNING The device is on a user who is running.
  • int STILL The device is still (not moving).
  • int TILTING The device angle relative to gravity changed significantly.
  • int UNKNOWN Unable to detect the current activity.
  • int WALKING The device is on a user who is walking.
Dick Lucas
  • 10,721
  • 9
  • 44
  • 71
  • That's awesome! Do you know if there's a google API that would allow you to do more or less the same stuff through javascript? – PrintlnParams Feb 06 '18 at 09:31
  • @PrintlnParams No. These APIs are only available for Android and Google does not currently develop javascript APIs for Android. – Dick Lucas Feb 06 '18 at 19:14
5

My first intuition would be to run an FFT analysis on the sensor history, and see what frequencies have high magnitudes when walking.

It's essentially seeing what walking "sounds like", treating the accelerometer sensor inputs like a microphone and seeing the frequencies that are loud when walking (in other words, at what frequency is the biggest acceleration happening).

I'd guess you'd be looking for a high magnitude at some low frequency (like footstep rate) or maybe something else. It would be interesting to see the data.

My guess is you run the FFT and look for the magnitude at some frequency to be greater than some threshold, or the difference between magnitudes of two of the frequencies is more than some amount. Again, the actual data would determine how you attempt to detect it.

doug65536
  • 6,014
  • 2
  • 37
  • 51
4

For walking detection I use the derivative applied to the smoothed signal from accelerometer. When the derivative is greater than threshold value I can suggest that it was a step. But I guess that it's not best practise, furthermore it only works when the phone is placed in a pants pocket.

The following code was used in this app https://play.google.com/store/apps/details?id=com.tartakynov.robotnoise

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER){
            return;
        }
        final float z = smooth(event.values[2]); // scalar kalman filter                               
        if (Math.abs(z - mLastZ) > LEG_THRSHOLD_AMPLITUDE)
        {
            mInactivityCount = 0;
            int currentActivity = (z > mLastZ) ? LEG_MOVEMENT_FORWARD : LEG_MOVEMENT_BACKWARD;                  
            if (currentActivity != mLastActivity){
                mLastActivity = currentActivity;
                notifyListeners(currentActivity);
            }                   
        } else {
            if (mInactivityCount > LEG_THRSHOLD_INACTIVITY) {
                if (mLastActivity != LEG_MOVEMENT_NONE){
                    mLastActivity = LEG_MOVEMENT_NONE;
                    notifyListeners(LEG_MOVEMENT_NONE);                                 
                }
            } else {
                mInactivityCount++;
            }
        }
        mLastZ = z;
    }
tartakynov
  • 2,408
  • 2
  • 24
  • 22
  • 2
    Instead of using just the Z acceleration, you should probably use the vector length: Math.sqrt(pow(x,2) + pow(y,2) + (z,2)) - 9.8. This way you will get the summed acceleration of all 3 directions and will not be dependent on the position/rotation in space of the device. – Nikolay Tsenkov Aug 08 '13 at 08:39
  • 1
    Can you add source of smooth function? – Guy Fawkes Apr 04 '14 at 16:45
  • 2
    https://github.com/tartakynov/robowalk/blob/master/src/com/tartakynov/robotnoise/leg/LegMovementDetector.java – tartakynov Apr 07 '14 at 09:45
0

EDIT: I don't think it's accurate enough since when walking normally the average acceleration would be near 0. The most you could do measuring acceleration is detect when someone starts walking or stops (But as you said, it's difficult to filter it from the device moved by someone standing at one place)

So... what I wrote earlier, probably wouldn't work anyway:

You can "predict" whether the user is moving by discarding when the user is not moving (obvious), And first two options coming to my mind are:
Check whether the phone is "hidden", using proximity and light sensor (optional). This method is less accurate but easier.
Controlling the continuity of the movement, if the phone is moving for more than... 10 seconds and the movement is not despicable, then you consider he is walking. I know is not perfet either, but it's difficult wihout using any kind of positioning, by the way... why don't you just use LocationManager?

mdelolmo
  • 6,277
  • 3
  • 38
  • 58
  • I can't use LocationManager because I want to stop getting location update when the user is not walking. The user will use my game/application looking at the phone. But is it right to use accelerometer to detect walking ? – havanakoda Feb 14 '11 at 16:39
  • @havanakoda , Now that I think deeply, its accuracy is really low, cause when you're walking, you barely accelerate, so the accelerometer would get pretty low values. I don't know if it's worthy to try. – mdelolmo Feb 14 '11 at 16:59
  • 2
    Humans bob up and down, and the shock of footstep impacts shoot through your body. Even when the phone is damped by being in the person's hand, I would be surprised if you didn't get a reasonably recognizable signal out of it. – doug65536 Jan 03 '13 at 18:51
  • What @doug65536 said. And also if you restart your accelerometer circuit it will detect a speed increase as opposed to keeping it on all the time because it has to re-measure your current vector and assume previous vector is nil. – nurettin May 31 '16 at 09:08
0

Try detecting the up and down oscillations, the fore and aft oscillations and the frequency of each and make sure they stay aligned within bounds on average, because you would detect walking and specifically that person's gait style which should remain relatively constant for several steps at once to qualify as moving. As long as the last 3 oscillations line up within reason then conclude walking is occurring as long as this also is true:-

You measure horizontal acceleration and update a velocity value with it. Velocity will drift with time, but you need to keep a moving average of velocity smoothed over the time of a step, and as long as it doesn't drift more than say half of walking speed per 3 oscillations then it's walking but only if it initially rose to walking speed within a short time ie half a second or 2 oscillations perhaps.
All of that should just about cover it. Of course, a little ai would help make things simpler or just as complex but amazingly accurate if you considered all of these as inputs to a NN. Ie preprocessing.