2009-03-20 6 views
11

나는 터치 움직임의 속도를 감지하려고 노력하고 있으며 나는 항상 기대했던 결과를 얻지 못하고 있습니다. (추가 : 속도가 너무 빠르다) 내가 펑키 한 뭔가를하고 있거나 더 나은 방법을 제안한다면 누구나 찾아 볼 수 있습니까?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); 

} 

답변

10

당신은 시도해 볼 수도 있습니다 (제로 touchesBegan에서 distanceSinceStart 및 timeSinceStart 아웃) : 사용자가 터치 (총 거리/총 시간)을 시작한 이후 당신에게 평균 속도를 줄 것이다

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

.

가 아니면 이동 평균 아마도 지수, 속도의 이동 평균을 할 수있는 : 당신은 최근 값에 더 많은 가중치를 부여 할 경우

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; 

당신은 1에 가까운 값으로 람다을 조정할 수 있습니다.

+0

안녕하세요 ...이 문제를 구현하는 데 문제가 있습니다. 람다 함수는 objective-c의 일부입니까? 구현하려면 무엇이 필요합니까? tia – dizy

+2

아니 ... 당신이 지정하는 상수입니다. 1에 가까울수록 최신 값에 더 많은 가중치를 부여합니다. n 값의 산술 평균과 비교하십시오. 각각의 새로운 값은 1/n의 가중치를가집니다. 지수의 경우 lambda = 2/(n + 1)을 설정합니다. 여기서 n은 상응하는 산술 값입니다. 따라서 새로운 값은 1/n 대신 2/(n + 1)의 가중치를 적용한 다음 기존 이동 평균을 (1-λ) = (n-1)/(n + 1) 덧붙였다. 클리어어요? – Jim

3

주된 문제는 timeSincePrevious이 매우 작 으면 (몇 밀리 초) 속도 계산이 매우 일 확률이 매우 낮습니다. 이를 확인하기 위해 timeSincePrevious이 1ms라고 가정 해 봅시다.

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

이고 다음 distanceFromPrevious는 0, 1000 경우 distanceFromZero는 I 람다의 다음 값을 제안이 때문에 1

이면 계산 속도가 0이 될 것 예를 들어 timeSincePrevious이 작 으면 작은 람다를 사용합니다.

+0

이것은 올바른 가변 샘플 속도 필터를 사용하는 유일한 대답입니다. 표준 1 차 저역 통과와 같이하려면 : k = <응답 시간>; a = exp (-dt/k); filteredSpeed ​​= a * (dx/dt) + (1-a) * filteredSpeed; – kylefinn

1

필터 제안은 괜찮지 만 문제가 해결되지는 않습니다. 최고점은 부드럽게 나오지만 그대로 유지됩니다.

터치 이벤트를 로그 아웃 한 경우이 피크는 이전 시간 (0.001215ms)에서 매우 작은 시간 델타를 가진 터치처럼 보이고 큰 시간 델타가 터치됩니다.

 
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 

은 내가하는 일은 최근의 터치 이벤트 사이의 평균 시간 델타를 계산하고, 비정상적인 시간 델타 (± 30 %)와 터치가 있다면, 나는 (이전 이벤트의 속도를 유지)의 속도를 무시

관련 문제