Обнаружение силы нажатия при касании с помощью акселерометра

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

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


person Ortwin Gentz    schedule 03.03.2011    source источник
comment
Хороший вопрос. Хотя, учитывая, что, вероятно, никто из нас еще не видел ни одного из новых iPad, кажется, что на этот вопрос будет очень сложно ответить окончательно.   -  person Cody Gray    schedule 03.03.2011
comment
Это все еще актуально?   -  person Eric    schedule 26.11.2020


Ответы (8)


Несколько хороших ответов. Вот некоторый рабочий код. Я реализовал это как подкласс 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
person picciano    schedule 22.03.2011
comment
Большое спасибо! Не могу проверить это прямо сейчас, но сделаю это, когда доберусь до него. - person Ortwin Gentz; 22.03.2011
comment
в своем ответе вы называете два файла одинаковыми: CPBPressureTouchGestureRecognizer.h зачем вам это? - person blacksheep; 03.06.2011
comment
В названии была опечатка. Также следует отметить, что этот код в том виде, в каком он написан, поддерживает только один экземпляр, поскольку он устанавливает себя как UIAccelerometer.delegate. Скоро выложу улучшенную версию. - person picciano; 25.01.2012
comment
Смотрите лучшую, более новую версию здесь: /вопросы/8079580/ - person picciano; 25.01.2012
comment
Доступна ли обновленная версия этого кода (с использованием CoreMotion)? - person Vamshi Krishna; 03.10.2016

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

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

person mouviciel    schedule 03.03.2011
comment
Возможно, хотя график акселерометра iPhone 4, лежащего на столе во время постукивания с большим давлением не показывает скачков. Как упомянул @Cody, нам, вероятно, придется подождать, пока мы не увидим настоящую вещь. - person Ortwin Gentz; 03.03.2011

Ну просто проведите этот эксперимент:

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

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

person viggio24    schedule 06.03.2011

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

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

person Marcus Rohrmoser    schedule 03.03.2011
comment
Кажется, это не так. Я осторожно попробовал ногтем. Определенно кажется, что это величина давления. - person picciano; 21.03.2011

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

person Rob    schedule 06.08.2011
comment
Как бы вы получили доступ к области касания пальца с помощью общедоступного API? - person Ortwin Gentz; 08.08.2011
comment
поплавок vf = 10,0; id valFloat = [значение thisTouchForKey:pathMajorRadius]; if(valFloat != nil) { vf = [valFloat floatValue]; } это делается так... но это может быть не общедоступно; но это не имеет значения, потому что это работает. ;-) Использую на практике в инструментах (запись, да еще и на сцене) уже год. Возможно, вам придется выпускать урезанную версию для масс, но я обещаю вам, что для этого есть применение, в котором это совершенно другой класс инструментов с включенной функцией. ИМХО, Apple глупа, потому что не делает того, что нужно, чтобы разрешить это. Приложения за 100 долларов против 5 долларов. - person Rob; 09.08.2011
comment
начиная с iOS8 существует общедоступная версия этого. прочитайте документы на UITouch. - person Rob; 26.05.2015

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

person Christian Owens    schedule 03.03.2011

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

person viggio24    schedule 03.03.2011
comment
В основном докладе они прямо сказали, что используют акселерометр. - person Ortwin Gentz; 03.03.2011
comment
Спасибо за комментарий, вы правы. Смотрите мой другой ответ (я считаю, что это окончательный ответ на этот пост). - person viggio24; 06.03.2011

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

ДОБАВЛЕН:

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

person hotpaw2    schedule 03.03.2011