Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine the direction of a iPhone shake

I am using the accelerometer to scroll multiple subViews in a UIScrollVIew. I want the view (portrait orientation) to scroll to the right when the user flicks the iPhone to the right, and scroll to the left when the device is flicked to the left.

I thought I could do that just by noting positive or negative x acceleration values, but I see that the values are usually a mixture of positive and negative values. I have set the floor at 1.5g to eliminate non-shake movement, and am looking at the x values over the duration of .5 seconds.

I'm sure there is a trigonometrical method for determining the overall direction of a flick, and that you have to measure values over the duration of the flick motion. I'm also sure that someone has already figured this one out.

Any ideas out there?

Thanks

like image 562
Alpinista Avatar asked Dec 13 '22 03:12

Alpinista


1 Answers

I developed a solution which gives me better feedback than the proposed solution (only for left and right shake). The way I did it here is quite sensitive (recognizes a small shake), but sensitivity can be adapted by changing tresholdFirstMove and tresholdBackMove (increase for lower sensitivity)

In Swift : (in your viewController. And add "import CoreMotion")

var startedLeftTilt = false
var startedRightTilt = false
var dateLastShake = NSDate(timeIntervalSinceNow: -2)
var dateStartedTilt = NSDate(timeIntervalSinceNow: -2)
var motionManager = CMMotionManager()
let tresholdFirstMove = 3.0
let tresholdBackMove = 0.5

override func viewDidLoad() {
    // your code

    motionManager.gyroUpdateInterval = 0.01
}

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    motionManager.startGyroUpdatesToQueue(NSOperationQueue.currentQueue(), withHandler: { (gyroData, error) -> Void in
        self.handleGyroData(gyroData.rotationRate)
    })

}

private func handleGyroData(rotation: CMRotationRate) {

    if fabs(rotation.z) > tresholdFirstMove && fabs(dateLastShake.timeIntervalSinceNow) > 0.3
    {
        if !startedRightTilt && !startedLeftTilt
        {
            dateStartedTilt = NSDate()
            if (rotation.z > 0)
            {
                startedLeftTilt = true
                startedRightTilt = false
            }
            else
            {
                startedRightTilt = true
                startedLeftTilt = false
            }
        }
    }

    if fabs(dateStartedTilt.timeIntervalSinceNow) >= 0.3
    {
        startedRightTilt = false
        startedLeftTilt = false
    }
    else
    {
        if (fabs(rotation.z) > tresholdBackMove)
        {
            if startedLeftTilt && rotation.z < 0
            {
                dateLastShake = NSDate()
                startedRightTilt = false
                startedLeftTilt = false

                println("\\\n Shaked left\n/")
            }
            else if startedRightTilt && rotation.z > 0
            {
                dateLastShake = NSDate()
                startedRightTilt = false
                startedLeftTilt = false

                println("\\\n Shaked right\n/")
            }
        }
    }

}
like image 90
Jon - LBAB Avatar answered Dec 29 '22 10:12

Jon - LBAB