Определение силы давления при нажатии на акселерометр - PullRequest
13 голосов
/ 03 марта 2011

Вчера в презентации о новом Garageband для iPad 2 компания Apple продемонстрировала интересную функцию: определение давления крана с помощью акселерометра.(См. Раздел барабанов на странице Garageband .)

Мне интересно, как это должно работать, если iPad лежит на столе.Нет движения, нет измеримого ускорения, нет?

Ответы [ 8 ]

15 голосов
/ 22 марта 2011

Несколько хороших ответов.Вот некоторый рабочий код.Я реализовал это как подкласс UIGestureRecognizer, чтобы вы могли просто вставить его и прикрепить к UIView или UIButton.После срабатывания будет установлено «давление» с плавающей точкой между 0,0f и 2,0f.При желании вы можете установить минимальное и максимальное давление, необходимое для распознавания.Наслаждайтесь.

//
//  CPBPressureTouchGestureRecognizer.h
//  PressureSensitiveButton
//
//  Created by Anthony Picciano on 3/21/11.
//  Copyright 2011 Anthony Picciano. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions
//  are met:
//  1. Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in the
//     documentation and/or other materials provided with the distribution.
//  
//  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
//  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
//  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
//  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
//  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
//  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
//  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

#import <UIKit/UIKit.h>

#define CPBPressureNone         0.0f
#define CPBPressureLight        0.1f
#define CPBPressureMedium       0.3f
#define CPBPressureHard         0.8f
#define CPBPressureInfinite     2.0f

@interface CPBPressureTouchGestureRecognizer : UIGestureRecognizer <UIAccelerometerDelegate> {
    @public
    float pressure;
    float minimumPressureRequired;
    float maximumPressureRequired;

    @private
    float pressureValues[30];
    uint currentPressureValueIndex;
    uint setNextPressureValue;
}

@property (readonly, assign) float pressure;
@property (readwrite, assign) float minimumPressureRequired;
@property (readwrite, assign) float maximumPressureRequired;

@end


//
//  CPBPressureTouchGestureRecognizer.h
//  PressureSensitiveButton
//
//  Created by Anthony Picciano on 3/21/11.
//  Copyright 2011 Anthony Picciano. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions
//  are met:
//  1. Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in the
//     documentation and/or other materials provided with the distribution.
//  
//  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
//  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
//  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
//  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
//  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
//  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
//  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

#import <UIKit/UIGestureRecognizerSubclass.h>
#import "CPBPressureTouchGestureRecognizer.h"

#define kUpdateFrequency            60.0f
#define KNumberOfPressureSamples    3

@interface CPBPressureTouchGestureRecognizer (private)
- (void)setup;
@end

@implementation CPBPressureTouchGestureRecognizer
@synthesize pressure, minimumPressureRequired, maximumPressureRequired;

- (id)initWithTarget:(id)target action:(SEL)action {
    self = [super initWithTarget:target action:action];
    if (self != nil) {
       [self setup]; 
    }
    return self;
}

- (id)init {
    self = [super init];
    if (self != nil) {
        [self setup];
    }
    return self;
}

- (void)setup {
    minimumPressureRequired = CPBPressureNone;
    maximumPressureRequired = CPBPressureInfinite;
    pressure = CPBPressureNone;

    [[UIAccelerometer sharedAccelerometer] setUpdateInterval:1.0f / kUpdateFrequency];
    [[UIAccelerometer sharedAccelerometer] setDelegate:self];
}

#pragma -
#pragma UIAccelerometerDelegate methods

-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
    int sz = (sizeof pressureValues) / (sizeof pressureValues[0]);

    // set current pressure value
    pressureValues[currentPressureValueIndex%sz] = acceleration.z;

    if (setNextPressureValue > 0) {

        // calculate average pressure
        float total = 0.0f;
        for (int loop=0; loop<sz; loop++) total += pressureValues[loop]; 
        float average = total / sz;

        // start with most recent past pressure sample
        if (setNextPressureValue == KNumberOfPressureSamples) {
            float mostRecent = pressureValues[(currentPressureValueIndex-1)%sz];
            pressure = fabsf(average - mostRecent);
        }

        // caluculate pressure as difference between average and current acceleration
        float diff = fabsf(average - acceleration.z);
        if (pressure < diff) pressure = diff;
        setNextPressureValue--;

        if (setNextPressureValue == 0) {
            if (pressure >= minimumPressureRequired && pressure <= maximumPressureRequired)
                self.state = UIGestureRecognizerStateRecognized;
            else
                self.state = UIGestureRecognizerStateFailed;
        }
    }

    currentPressureValueIndex++;
}

#pragma -
#pragma UIGestureRecognizer subclass methods

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    setNextPressureValue = KNumberOfPressureSamples;
    self.state = UIGestureRecognizerStatePossible;
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    self.state = UIGestureRecognizerStateFailed;
}

- (void)reset {
    pressure = CPBPressureNone;
    setNextPressureValue = 0;
    currentPressureValueIndex = 0;
}

@end
4 голосов
/ 06 марта 2011

Ну просто сделайте этот эксперимент:

откройте с помощью XCode учебное приложение AccelerometerGraph, включенное в комплект XCode.Затем запустите приложение (фильтр высоких частот, лучше использовать адаптивную фильтрацию): вы увидите, как синяя линия меняется в зависимости от силы приложения.Конечно, на это влияет дрожание в таблице, которое добавляет шум к показателю, но вы все равно можете отфильтровать его, проверив данные акселерометра с событием касания.

Таким образом, такое обнаружение давления возможно с использованиемакселерометр.

4 голосов
/ 03 марта 2011

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

Или, пользовательский интерфейс Garage Band лучше, когда iPad стоит на Smart Cover.

1 голос
/ 06 августа 2011

Виггио24 прав. зондирование области пальца работает нормально. (У меня есть несколько постов здесь с тривиальной строкой кода, чтобы получить его). единственная проблема в том, что неясно, каковы будут последствия, если вы отправите его с включенным; мы предполагаем, что он просто не будет одобрен в лучшем случае.

1 голос
/ 03 марта 2011

Определение размера области касания? (Тяжелее нажатие, больший отпечаток пальца) Динамика крана?

Просто думаю.

0 голосов
/ 03 марта 2011

Попробуйте сами с помощью примера приложения AccelerometerGraph. Устройство и столешница имеют конечную жесткость, поэтому на графике вы можете увидеть маленькие блики.

ДОБАВЛЕНО:

Если вы самостоятельно скомпилируете образец графика Apple AccelerometerGraph из исходного кода, вы можете увеличить усиление по вертикальной оси и увидеть блики для меньших ускорений.

0 голосов
/ 03 марта 2011

Даже если SDK предоставляет нам только область касания, я полагаю, что аппаратное обеспечение экрана предоставляет операционной системе гораздо больше информации: количество точек касания (используется для определения области) и длительность касания.Вместе (и экспериментируя) они могут дать вам хорошую оценку приложенного давления.Было бы неплохо, если бы Apple выпустила эту эмпирическую оценку давления для разработчиков.

0 голосов
/ 03 марта 2011

Возможно, это из-за более чувствительного гироскопа? В сочетании с данными акселерометра, вероятно, достаточно просто определить даже небольшие изменения в движении. Просто догадка. Если нет чего-то, что они не говорят нам, что не будет первым.

...