2013-11-23 3 views
19

iPhoneの画面だけでなく、どこでも可能なタップを検出しようとしています。これは可能であることを示すlinkです。加速度計でiPhoneのどこでもハードタップを検出

基本的には、電話がポケットに入っている間にユーザーがiPhoneで3回タップするとアラートを送信します。 私が達成したのは、私は3つのタップを検出することができますが、私はまた、これらのケースでも誤ったアラートを取得します。 1)ユーザーの歩行、2)携帯電話の振り回し、3)走っている場合。ユーザーがiPhoneを3回叩いたかどうかを確認する必要があります。

ここに私のコードです。

- (void)accelerometer:(UIAccelerometer *)accelerometer 
     didAccelerate:(UIAcceleration *)acceleration 
{ 
    if (handModeOn == NO) 
    { 
     if(pocketFlag == NO) 
      return; 
    } 

    float accelZ = 0.0; 
    float accelX = 0.0; 
    float accelY = 0.0; 

    accelX = (acceleration.x * kFilteringFactor) + (accelX * (1.0 - kFilteringFactor)); 
    accelY = (acceleration.y * kFilteringFactor) + (accelY * (1.0 - kFilteringFactor)); 
    accelZ = (acceleration.z * kFilteringFactor) + (accelZ * (1.0 - kFilteringFactor)); 

     self.z.text = [NSString stringWithFormat:@"%0.1f", -accelZ]; 

     if((-accelZ >= [senstivity floatValue] && timerFlag) || (-accelZ <= -[senstivity floatValue] && timerFlag)|| (-accelX >= [senstivity floatValue] && timerFlag) || (-accelX <= -[senstivity floatValue] && timerFlag) || (-accelY >= [senstivity floatValue] && timerFlag) || (-accelY <= -[senstivity floatValue] && timerFlag)) 
     { 
      timerFlag = false; 
      addValueFlag = true; 
      timer = [NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:@selector(timerTick:) userInfo:nil repeats:YES]; 
     } 

     if(addValueFlag) 
     { 
      if (self.xSwitch.on) 
      { 
       NSLog(@"X sWitch is on"); 
       [self.accArray addObject:[NSNumber numberWithFloat:-accelX]]; 
      } 
      if (self.ySwitch.on) 
      { 
       NSLog(@"Y Switch is on"); 
       [self.accArray addObject:[NSNumber numberWithFloat:-accelY]]; 
      } 
      if (self.zSwitch.on) 
      { 
       NSLog(@"Z Switch is on"); 
       [self.accArray addObject:[NSNumber numberWithFloat:-accelZ]]; 
      } 

     } 
    //} 
} 

- (void)timerTick:(NSTimer *)timer1 
{ 
    [timer1 invalidate]; 
    addValueFlag = false; 
    int count = 0; 

    for(int i = 0; i < self.accArray.count; i++) 
    { 
     if(([[self.accArray objectAtIndex:i] floatValue] >= [senstivity floatValue]) || ([[self.accArray objectAtIndex:i] floatValue] <= -[senstivity floatValue])) 
     { 
      count++; 
      [self playAlarm:@"beep-1" FileType:@"mp3"]; 
     } 

     if(count >= 3) 
     { 
      [self playAlarm:@"06_Alarm___Auto___Rapid_Beeping_1" FileType:@"caf"]; 
      [self showAlert]; 
      timerFlag = true; 
      [self.accArray removeAllObjects]; 
      return; 
     } 
    } 
    [self.accArray removeAllObjects]; 
    timerFlag = true; 
} 

ご協力いただきますようお願い申し上げます。

ありがとう

+0

これはまさに私が探しているものです!あなたは解決策を見つけましたか? – Jonovono

+0

@sajooこれまでこれまでの解決策を見つけましたか?これについて話したいですか?私のメールは私のプロフィールにあるはずです。がんばろう! – Jonovono

+0

@Jonovonoはい、私はそれを達成しました。私は自分のシステムに戻ったときに私のソリューションを投稿しようとします。あなたが私と話をしたいのであれば、私のメールIDはここにあります。 [email protected]。 – sajjoo

答えて

0

これは私がそれを達成した方法です。

- (void)accelerometer:(UIAccelerometer *)accelerometer 
     didAccelerate:(UIAcceleration *)acceleration 
{ 
    if (pause) 
    { 
     return; 
    } 
    if (handModeOn == NO) 
    { 
     if(pocketFlag == NO) 
      return; 
    } 

// float accelZ = 0.0; 
// float accelX = 0.0; 
// float accelY = 0.0; 

    rollingX = (acceleration.x * kFilteringFactor) + (rollingX * (1.0 - kFilteringFactor)); 
    rollingY = (acceleration.y * kFilteringFactor) + (rollingY * (1.0 - kFilteringFactor)); 
    rollingZ = (acceleration.z * kFilteringFactor) + (rollingZ * (1.0 - kFilteringFactor)); 

    float accelX = acceleration.x - rollingX; 
    float accelY = acceleration.y - rollingY; 
    float accelZ = acceleration.z - rollingZ; 

    if((-accelZ >= [senstivity floatValue] && timerFlag) || (-accelZ <= -[senstivity floatValue] && timerFlag)|| (-accelX >= [senstivity floatValue] && timerFlag) || (-accelX <= -[senstivity floatValue] && timerFlag) || (-accelY >= [senstivity floatValue] && timerFlag) || (-accelY <= -[senstivity floatValue] && timerFlag)) 
    { 
     timerFlag = false; 
     addValueFlag = true; 
     timer = [NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:@selector(timerTick:) userInfo:nil repeats:YES]; 
    } 

    if(addValueFlag) 
    { 
     [self.accArray addObject:[NSNumber numberWithFloat:-accelX]]; 
     [self.accArray addObject:[NSNumber numberWithFloat:-accelY]]; 
     [self.accArray addObject:[NSNumber numberWithFloat:-accelZ]]; 
    } 
} 
+0

そのコードの説明を以下に示します。 自分の設定で感度設定を追加しました。ここでユーザーは加速度センサーの感度を設定できます。だから私は値がその感受性と等しいかそれ以上のものを得る。私は1.5秒間タイマーを開始し、その後1.5秒間に他の値をチェックします。私のタイマーが終わったら、アレイの加速度計の値が、今度は感度以上になります。次にtimerTickメソッドでは、3から4の値が必要な配列にあるかどうかを配列から調べます。ハードタップが検出されたアラート方式を起動します。 – sajjoo

11

加速度計のデータにハイパスフィルタを適用する必要があります。それはあなたに信号の鋭いタップを与えるだけです。

「UIAccelerometerハイパスフィルター」でクイック検索を行い、いくつかヒットしました。最も簡単なコードは、加速度計入力のローリング平均をとり、その平均値を瞬時値から減算して突然の変化を検出します。間違いなくもっと洗練された方法もあります。

シャープなタップを認識するコードを作成したら、行内に3つのシャープなタップを検出するコードを作成する必要があります。

-10

は、このコードを試してみてください。

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] 
                initWithTarget:self action:@selector(handleLongPress:)]; 
     longPress.minimumPressDuration = 2; //seconds 
     //longPress.delegate = self; 
     [myButton addGestureRecognizer:longPress]; 
+2

あなたは元の質問と問題を全く読んでいないのですか?それはどうすればその可能な解決策になりますか? – holex

3

これは、すべての加速度計データのストリームからタップをフィルタリングして行うには、別の答えによって示唆されているように、です。インパルス状のタップは、適切なフィルタからの応答が閾値より高いときに検出される特徴的なスペクトログラム(周波数の組み合わせ)を有する。

これはiPhone上で非常に一般的な操作であり、私はそのようhere

としてあなたは公式ドキュメントを見てお勧めします私がリンクされているサンプルコードは、次の2つの重要な事柄を与える:ハイパスフィルタのための公式のコード例をと加速度計データをグラフ表示するサンプルアプリケーションです。これにより、タップ、ステップ、ジャンプを視覚化して、フィルタが誤って応答する理由をよりよく理解することができます。

さらに、インターネットはフィルタ設計に関する膨大な文献です。非常に高品質のフィルタを作成する必要がある場合は、文献を参照する必要があります。私はしかし、適切な2次フィルタで十分だろうと思う。

@implementation HighpassFilter 

- (id)initWithSampleRate:(double)rate cutoffFrequency:(double)freq 
{ 
    self = [super init]; 

    if (self != nil) 
    { 
     double dt = 1.0/rate; 
     double RC = 1.0/freq; 
     filterConstant = RC/(dt + RC); 
    } 

    return self;  
} 

- (void)addAcceleration:(UIAcceleration *)accel 
{ 
    double alpha = filterConstant; 

    if (adaptive) 
    { 
     double d = Clamp(fabs(Norm(x, y, z) - Norm(accel.x, accel.y, accel.z))/kAccelerometerMinStep - 1.0, 0.0, 1.0); 
     alpha = d * filterConstant/kAccelerometerNoiseAttenuation + (1.0 - d) * filterConstant; 
    } 

    x = alpha * (x + accel.x - lastX); 
    y = alpha * (y + accel.y - lastY); 
    z = alpha * (z + accel.z - lastZ); 

    lastX = accel.x; 
    lastY = accel.y; 
    lastZ = accel.z; 
} 

- (NSString *)name 
{ 
    return adaptive ? @"Adaptive Highpass Filter" : @"Highpass Filter"; 
} 

@end 

重要なことに、このフィルタは加速度の大きさのみがフィルタリングされるため、方向に依存しません。これは、応答を正常に見せるためには不可欠です。さもなければ、ユーザーは、sweetspotを見つけるために異なる角度からタップする必要があるように感じるかもしれません。

このタスクが難しくて厄介なことが判明した場合は、データを(WAVファイルなどで)キャプチャし、一般的なシグナルアナライザプログラムのいずれかを使用して、間違っている。 Baudline

関連する問題