2011-03-03 115 views
12

昨天,在关于iPad 2新款Garageband的演示中,苹果公司演示了一个有趣的功能:使用加速度计检测敲击压力。 (请参阅Garageband page上的鼓部分。)使用加速度计的敲击压力强度检测

我想知道如果iPad在桌子上平放,应该如何工作。没有运动,没有可测量的加速度,不是?

+1

好问题。虽然考虑到我们可能没有看到新iPad中的任何一个,但似乎这将很难很明确地回答。 – 2011-03-03 10:39:49

回答

15

一些很好的答案。这是一些工作代码。我将它作为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 
+0

太好了,谢谢!目前无法进行测试,但是在完成测试时会这样做。 – 2011-03-22 17:23:56

+0

在你的回答中你用两个相同的文件命名:CPBPressureTouchGestureRecognizer.h你为什么这样做? – blacksheep 2011-06-03 09:05:09

+0

命名是一个错字。同样值得注意的是,这段代码只支持单个实例,因为它将自己设置为UIAccelerometer.delegate。我会很快发布一个更好的版本。 – picciano 2012-01-25 17:27:36

1

点击面积大小检测? (较硬的水龙头,较大的指纹) 水龙头动态?

只是在想。

+0

似乎并非如此。我用我的指甲仔细地尝试。绝对似乎是压力的数量。 – picciano 2011-03-21 19:40:09

0

也许是由于比较敏感陀螺仪?结合加速度计数据,确定运动的微小变化可能相当容易。只是一种预感。除非他们没有告诉我们什么,这不会是第一个。

4

我想象,铝制外壳和桌子不会阻止非常小的移动,并且传感器非常敏感。

或者,Garage Band的用户体验对于iPad站在智能封面上更好。

+0

也许,虽然iPhone 4的[加速度图](http://emberapp.com/futuretap/images/accelerometer)平躺在桌子上,同时用高压敲击并不会显示出任何峰值。正如@Cody所说,我们可能要等到我们看到真实的东西。 – 2011-03-03 11:36:50

0

即使SDK暴露给我们的触摸区域,我相信屏幕硬件正在向操作系统提供更多信息:触摸像素(用于区域检测)和触摸持续时间。一起(和试验)他们可以给你一个很好的施加压力的估计。 如果苹果向开发者发布这种经验性的压力估计,那将会很好。

+2

在基调中,他们专门表示他们正在使用加速度计。 – 2011-03-03 10:49:39

+0

感谢您的评论,你是对的。看到我的其他答案(我相信这是这篇文章的权威答案)。 – viggio24 2011-03-06 16:17:40

0

自己动手尝试使用AccelerometerGraph示例应用程序。该设备和桌面具有有限的硬度,因此您可能会在图表中看到小点。

新增:

如果您编译从自己的源代码苹果AccelerometerGraph图示例,您可以打开了在垂直轴上增益和看到的光点较小的加速度。

4

那么简单地做这个实验:

与XCode的包括在Xcode捆绑的AccelerometerGraph教程应用程序打开。 然后启动应用程序(高通滤波器,使用自适应滤波效果更好):您将看到根据应用程序强度改变的蓝线。当然,这受到表格抖动的影响,这会给测量增加噪音,但您仍然可以通过检查加速度计数据和触摸事件来对其进行过滤。

所以这种压力检测可以使用加速度计。

1

viggio24是对的。手指区域感应正常工作。 (我在这里有一些简单的代码行来获取它)。唯一的问题是,如果您启用它后会产生什么后果?我们认为它不会在最好的情况下获得批准。

+0

如何使用公共API访问轻敲的手指区域? – 2011-08-08 15:57:09

+2

float vf = 10.0; id valFloat = [thisTouch valueForKey:“pathMajorRadius”];如果(valFloat!= nil){vf = [valFloat floatValue]; } 它是这样做的......但它可能不公开;但这是无关的,因为它的作品。 ;-)我一直在乐器(录音,甚至在舞台上)使用它一年。您可能不得不为大众运送残缺版本,但我向您保证,有这方面的用处,它是完全不同的仪器类别,并且可以启用此功能。恕我直言,苹果是愚蠢的,因为没有做到这一点,以获得这个允许。 $ 100应用与$ 5。 – Rob 2011-08-09 19:36:33

+0

截至iOS8,这里有一个公共版本。阅读UITouch上的文档。 – Rob 2015-05-26 15:54:59