How to count steps using an Accelerometer?

Tariq picture Tariq · Nov 29, 2011 · Viewed 20.4k times · Source

I have to develop the same functionality as of this Pedometer App

I have observed this Pedometer app in very high detail.

It's not a perfect pedometer app. For example, if you stay/sit at one place and shake your hand, it also detects steps counts and distance.

Ignore this ideal and gravity behavior, because in the instructions of this app it's already been mentioned that you should tie up your iPhone or you should place it in your pocket to count steps. This way, I have found this app working very well, it detects almost all steps.

My problem is: I have developed one sample according to the above logic, but it's not working up to that level. For example, sometimes it detects 2-3 steps at the same time. And sometimes it works fine.

My code:

In viewDidLoad:

[[UIAccelerometer sharedAccelerometer] setUpdateInterval:0.2] 

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
    const float violence = 1.2;
    static BOOL beenhere;
    BOOL shake = FALSE;
    if (beenhere) return;
    beenhere = TRUE;
    if (acceleration.x > violence || acceleration.x < (-1* violence))
       shake = TRUE;
    if (acceleration.y > violence || acceleration.y < (-1* violence))
       shake = TRUE;
    if (acceleration.z > violence || acceleration.z < (-1* violence))
       shake = TRUE;
    if (shake) {
       steps=steps+1;
     }
  beenhere = false;
}

What am I doing wrong? I am not able to determine the threshold. If I make it high, it won't detect minor steps. If I make it small, it registers 3-4 steps simultaneously.

Is there any other implementation required to do this, or some tweaks in this code?

I have seen all other similar Stack Overflow links. Nothing I have found performs up to this level.

Please help.

Answer

Hot Licks picture Hot Licks · Nov 29, 2011

Been counting snores, not steps, but have some of the same issues. No actual answers, but some suggestions:

  1. Require a time interval between steps. Yes, someone can be walking slowly or jogging, but even at the fastest there is a time interval of maybe 1/5 second between steps. If "impacts" appear more rapid than that they're likely just from rebound/rattling.
  2. Rather than your fixed threshold (violence) employ a variable threshold, based on a moving average of previous events.
  3. Consider keeping separate x, y, and z thresholds, based on the assumption that the phone will not, over a short period of time, change orientation.
  4. Rather than just ignoring events stronger than a certain level, consider ignoring those outside a range, with limits specified by two thresholds (one perhaps a fraction of the other).
  5. Consider what happens when you walk -- there is a forward/backward acceleration of the body that is quite rhythmic, along with a "shock" as the foot strikes the ground. It may be best to attempt to ignore the shock (a fairly short-term signal) and instead look for the rhythmic forward/backward motion.

Another suggestion

Testing this beast "live" would be impossible. (I can imagine you trying to jog along while holding the laptop in front of you, trying to get the debugger console to focus.) What you should do is first rig your app to make some recordings (ie, write files) containing the raw measurements, then re-rig your app (#ifdefs would be handy here) to be able to "play back" those measurements so that you can step through the app with the debugger and observe its behavior.