9

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.

1
  • If you got your answer, can you please share the code? May 16, 2015 at 17:55

2 Answers 2

20

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.

5
  • 2
    +1 for a really great answer. Also, on #1... As a runner I can tell you, 1/5 second per step is an IMPOSSIBLY fast cadence. Really fast turn-over is about 190 bpm, which is a little over 3 footfalls per second. That's good for OP's purposes, because the grosser the resolution you're looking at, the more jitter you can screen out. I also really like the moving average suggestion, because the impact you hit the ground with varies with your running style, the quality of your form, your body composition, your speed, and other factors. A magic number is never going to really work there.
    – Dan Ray
    Nov 29, 2011 at 13:11
  • Thanks Licks & Dan. So What would you suggest setUpdateInterval value instead of 0.2 ? Can you also suggest how to make threshold variable ?
    – Tariq
    Nov 30, 2011 at 4:39
  • The update interval of 0.2 is probably good, at least for starters. To make the threshold variable you'd probably keep the moving average of prior accelerometer values (separate averages for x, y, and z) and use maybe 2x or 3x the moving average as the threshold.
    – Hot Licks
    Nov 30, 2011 at 4:45
  • It might help to generate some graphs of the movement, to see what the values usually are when it goes wrong and when it goes right. Even better to generate graphs with multiple different people.
    – Aberrant
    Dec 1, 2011 at 8:39
  • If not graphs, at least a regular NSLog of events, showing the input values, thresholds, and other calculated values. Use a graphic flag (eg, **) to indicate values that are "important", such as accel measurements that indicate a stride. (And, of course, somehow #ifdef the NSLogs, so you can turn them off in production.)
    – Hot Licks
    Dec 1, 2011 at 12:24
0
        var motionManager = CMMotionManager()
        motionManager.deviceMotionUpdateInterval = 0.1
        motionManager.startDeviceMotionUpdatesToQueue(NSOperationQueue.currentQueue(), withHandler:{
            deviceManager, error in

            var accelerationThreshold:Double = 1;
            var userAcceleration:CMAcceleration = deviceManager.userAcceleration;
            if(fabs(userAcceleration.x) > accelerationThreshold) || (fabs(userAcceleration.y) > accelerationThreshold) || (fabs(userAcceleration.z) > accelerationThreshold)
            {
                println("LowPassFilterSignal")
            }
        })

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.