Как определить направление встряхивания iPhone - PullRequest
4 голосов
/ 19 июня 2009

Я использую акселерометр для прокрутки нескольких подвидов в UIScrollVIew. Я хочу, чтобы вид (книжная ориентация) прокручивался вправо, когда пользователь щелкает iPhone вправо, и прокручивал влево, когда устройство переворачивалось влево.

Я думал, что смогу сделать это, просто отметив положительные или отрицательные значения ускорения х, но я вижу, что значения обычно представляют собой смесь положительных и отрицательных значений. Я установил пол в 1.5g, чтобы устранить движение без дрожания, и смотрю на значения x в течение 0,5 секунд.

Я уверен, что существует тригонометрический метод для определения общего направления движения, и что вы должны измерять значения по продолжительности движения движения. Я также уверен, что кто-то уже понял это.

Есть идеи?

Спасибо

Ответы [ 2 ]

7 голосов
/ 13 марта 2015

Я разработал решение, которое дает мне лучшую обратную связь, чем предлагаемое решение (только для левого и правого встряхивания). То, как я это сделал здесь, довольно чувствительно (распознает небольшое дрожание), но чувствительность можно адаптировать, изменив tresholdFirstMove и tresholdBackMove (увеличение для более низкой чувствительности)

В Свифте: (в вашем viewController. И добавьте "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/")
            }
        }
    }

}
5 голосов
/ 19 июня 2009

ОК, разработано решение. Когда я обнаруживаю колебательное движение (ускорение больше 1,5 на оси x), я запускаю таймер и устанавливаю BOOL в значение true. Пока BOOL верна, я добавляю значения ускорения. Когда таймер истекает, я прекращаю добавлять значения ускорения и определяю направление встряхивания по знаку полного ускорения.


- (void)accelerometer:(UIAccelerometer *)acel didAccelerate:(UIAcceleration *)aceler {

    if (fabsf(aceler.x) > 1.5)
    {
        shake = YES;
        NSTimeInterval myInterval = .75;
        [NSTimer scheduledTimerWithTimeInterval:myInterval target:self selector:@selector(endShake) userInfo:nil repeats:NO];
        return;
    }

    if(shake)
    {
        totalG += aceler.x;
    }
}

- (void) endShake {
    shake = NO;
    int direction;
    if (totalG isLessThan 0) direction = 1;
    if(totalG isGreaterThan 0) direction = -1;
    [self changePageByShake:direction];
    totalG = 0;
}

Примечание: я не смог заставить символы <и> правильно отформатировать в кодовом блоке выше, поэтому я заменил isLessThan и isGreaterThan на символы.

...