2009-03-20 10 views
11

Próbuję wykryć prędkość ruchu dotyku i nie zawsze uzyskuję oczekiwane rezultaty. (dodane: zbyt szybkie skoki) Czy ktokolwiek może zauważyć, jeśli robię coś ciekawego lub sugeruję lepszy sposób na zrobienie tego?Wykrywanie prędkości ruchu UITouch


- (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); 

} 

Odpowiedz

10

Można spróbować (zero out distanceSinceStart i timeSinceStart w touchesBegan):

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

który daje średnią prędkość od rozpoczęcia dotyku (całkowity dystans/całkowity czas).

Albo można zrobić ruchomą średnią prędkością, może wykładnicza średnia ruchoma:

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; 

można dostosować do wartości lambda blisko 1, jeśli chcesz dać większą wagę do ostatnich wartości.

+0

Hej ... mam problem z zaimplementowaniem tego. Czy funkcja lambda jest częścią obiektywu-c? Czego potrzebuję do jego wdrożenia? tia – dizy

+2

Nie ... jest to stała, którą sam określasz. Im bliżej 1, tym więcej wagi umieszczasz na najnowszej wartości. Porównaj ze średnią arytmetyczną z n wartości. Każda nowa wartość ma wagę 1/n. Dla wykładniczej, ustaw lambdę = 2/(n + 1) gdzie n jest równoważną wartością arytmetyczną. Tak więc nowa wartość jest ważona 2/(n + 1) zamiast 1/n, a następnie istniejąca średnia ruchoma jest zmniejszana o (1-lambda) = (n-1)/(n + 1), a dwie są dodany. Czyściej? – Jim

3

Głównym problemem jest to, że obliczenie prędkości będzie bardzo trudne: niedokładne, gdy timeSincePrevious jest bardzo małe (kilka milisekund). Aby to zobaczyć, załóżmy, że timeSincePrevious to 1ms. Następnie oblicza prędkość będzie wynosić 0, jeśli distanceFromPrevious wynosi 0, a 1000 jeśli distanceFromZero to 1.

Z tego powodu proponuję następującą wartość lambda:

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

to powiedzmy, używamy małej lambdy, gdy timeSincePrevious jest mała.

+0

Jest to jedyna odpowiedź przy użyciu odpowiedniego filtru zmiennej częstotliwości próbkowania. I zrobić to jak standardowe dolnoprzepustowe pierwszego rzędu: k = ; a = exp (-dt/k); przefiltrowana prędkość = a * (dx/dt) + (1-a) * przefiltrowana prędkość obrotowa; – kylefinn

1

Sugestia filtra może być w porządku, ale nie rozwiązuje problemu: szczyt zostanie wygładzony, ale pozostanie.

Jeśli wylogowałeś się z wydarzeń dotykowych, te szczyty będą wyglądać jak dotyk z bardzo małą różnicą czasu od poprzedniej (0.001215 ms), poprzedzoną dotknięciem z dużą różnicą czasu.

 
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 

Co mogę zrobić, to obliczyć średni czas delta pomiędzy ostatnich zdarzeń dotykowych, a jeśli nie jest dotykowy delta nienormalny czasu (± 30%), ignoruję jego prędkość (utrzymując prędkość poprzednim przypadku)

Powiązane problemy