2009-03-20 6 views
11

Dokunma hareketinin hızını tespit etmeye çalışıyorum ve her zaman beklediğim sonuçları alamıyorum. (Eklendi: Hız çok fazla artıyor) Bir şey yaparken ya da bunu yapmanın daha iyi bir yolunu önerdiğimi kimse fark edebilir mi?UITouch hareket hızı algılama


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ 
    self.previousTimestamp = event.timestamp; 
} 
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ 
    UITouch *touch = [touches anyObject]; 
    CGPoint location = [touch locationInView:self.view]; 
    CGPoint prevLocation = [touch previousLocationInView:self.view]; 
    CGFloat distanceFromPrevious = distanceBetweenPoints(location,prevLocation); 
    NSTimeInterval timeSincePrevious = event.timestamp - self.previousTimestamp; 
    CGFloat speed = distanceFromPrevious/timeSincePrevious; 
    self.previousTimestamp = event.timestamp; 
    NSLog(@"dist %f | time %f | speed %f",distanceFromPrevious, timeSincePrevious, speed); 

} 

cevap

10

Sen deneyebilirsiniz (sıfır touchesBegan distanceSinceStart ve timeSinceStart dışarı): Eğer dokunmatik (toplam mesafe/toplam süre) başladığından beri size ortalama hızı verecektir

distanceSinceStart = distanceSinceStart + distanceFromPrevious; 
timeSinceStart = timeSincestart + timeSincePrevious; 
speed = distanceSinceStart/timeSinceStart; 

.

Yoksa ortalama hareketli belki bir üstel, hız hareketli ortalamasını yapabilirdi: En son değerlere daha fazla ağırlık vermek istiyorsanız

const float lambda = 0.8f; // the closer to 1 the higher weight to the next touch 

newSpeed = (1.0 - lambda) * oldSpeed + lambda* (distanceFromPrevious/timeSincePrevious); 
oldSpeed = newSpeed; 

Sen 1 yakın değerlere lambda ayarlayabilirsiniz.

+0

Hey ... Bunu uygulamakta zorlanıyorum. Lambda fonksiyonu objektif-c'nin bir parçası mı? Bunu uygulamak için neye ihtiyacım var? tia – dizy

+2

Hayır ... Kendinizi belirlediğiniz bir sabit. 1'e yaklaştıkça, en yeni değere daha fazla ağırlık verirsiniz. N değerlerinin aritmetik ortalamasıyla karşılaştırın. Her yeni değer 1/n'lik bir ağırlık alır. Üstel için, lambda = 2/(n + 1) değerini ayarlayın; burada n, eşdeğer aritmetik değerdir. Böylece yeni değer 1/n yerine 2/(n + 1) ağırlığındadır ve daha sonra mevcut hareketli ortalama (1-lambda) = (n-1)/(n + 1) tarafından ölçeklendirilir ve ikisi de katma. Netleştirici? – Jim

3

Ana sorun, timeSincePrevioustimeSincePrevious çok küçük (birkaç milisaniye) olduğunda hız hesaplaması çok hatalı olacaktır. Bunu görmek için, timeSincePrevious'un 1 ms olduğunu varsayalım.

const float labmda = (timeSincePrevious>0.2? 1: timeSincePrevious/0.2); 

şudur: distanceFromPrevious 0 ve 1000 eğer distanceFromZero Ben lambda aşağıdaki önerdiğimiz değeri Bu nedenle 1.

ise Ardından hesaplanan hız 0 olur Yani, timeSincePrevious küçük olduğunda küçük bir lambda kullanıyoruz.

+0

Bu, uygun değişken bir örnekleme oranı filtresi kullanan tek cevaptır. Ve standart bir birinci derece düşük geçiş gibi yapmak için: k = ; a = exp (-dt/k); filtreliSpeed ​​= a * (dx/dt) + (1-a) * filtrelenmişSpeed; – kylefinn

1

Filtre önerisi iyi olabilir, ancak sorunu çözmüyor: zirve düzleştirilecek ancak kalıyor.

Dokunma olaylarını çıkış yaptıysanız, bu zirveler önceki zamanlardan (0.001215 ms) çok daha kısa bir zaman diliminde bir dokunuş gibi görünür;

 
distance = 17.269917, timeDelta = 0.016132, speed = 1070.504639 
distance = 15.206906, timeDelta = 0.017494, speed = 869.251709 
distance = 15.882380, timeDelta = 0.017583, speed = 903.297546 
distance = 14.983324, timeDelta = 0.030101, speed = 497.771088  //low peak 
distance = 15.435349, timeDelta = 0.001215, speed = 12703.991211 //high peak! 
distance = 15.882380, timeDelta = 0.017343, speed = 915.795898 
distance = 15.890248, timeDelta = 0.016302, speed = 974.742249 
distance = 16.560495, timeDelta = 0.016468, speed = 1005.606445 
distance = 16.101242, timeDelta = 0.017291, speed = 931.201050 

Ne yapmam son dokunuş olaylar arasındaki ortalama süresi delta hesaplamak ve anormal zaman delta (±% 30) ile bir dokunuş varsa, ben (önceki olayın hızını tutarak) hızını görmezden