Search code examples
objective-caccelerometergyroscope

Detect when an iphone has been bumped


I want to be able to detect if an iphone has been bumped into something...would it be best to listen to the gyroscope / accelerometer and judge how fast its moved or if its moved and stopped suddenly.

In fact how would I judge if the device has moved then stopped suddenly?

This answer is great but in reverse iOS: Accurately determining energy of a bump from accelerometer output - it smooths out the movement, if anything I want to detect a sharp movement.

Also are both the Gyroscope and Accelerometer available for 3GS ?

UPDATED WITH CODE

From the Apple doc http://developer.apple.com/library/iOS/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/MotionEvents/MotionEvents.html#//apple_ref/doc/uid/TP40009541-CH4-SW26

Isolating Instantaneous Motion from Acceleration Data If you are using accelerometer data to detect just the instant motion of a device, you need to be able to isolate sudden changes in movement from the constant effect of gravity. You can do that with a high-pass filter.

Listing 4-6 shows a simplified high-pass filter computation. The acceleration values from the previous event are stored in the accelX, accelY, and accelZ member variables of the class. This example computes the low-pass filter value and then subtracts it from the current value to obtain just the instantaneous component of motion.

Listing 4-6 Getting the instantaneous portion of movement from accelerometer data

define kFilteringFactor 0.1

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
    // Subtract the low-pass value from the current value to get a simplified high-pass filter
    accelX = acceleration.x - ( (acceleration.x * kFilteringFactor) + (accelX * (1.0 - kFilteringFactor)) );
    accelY = acceleration.y - ( (acceleration.y * kFilteringFactor) + (accelY * (1.0 - kFilteringFactor)) );
    accelZ = acceleration.z - ( (acceleration.z * kFilteringFactor) + (accelZ * (1.0 - kFilteringFactor)) );

   // Use the acceleration data.
}

How would I then 'Use the acceleration data' to work out if an instantaneous motion is detected?


Solution

  • I used this code:

    #define kUpdateFrequency    100.0
    #define kFilteringFactor    0.1
    float accelZ;
    int spikeZCount = 0; 
    
    [[UIAccelerometer sharedAccelerometer] setUpdateInterval:1.0 / kUpdateFrequency];
        [[UIAccelerometer sharedAccelerometer] setDelegate:self];
    
    - (void) accelerometer: (UIAccelerometer *) accelerometer didAccelerate: (UIAcceleration *) acceleration 
    {
        accelZ = acceleration.z - ( (acceleration.z * kFilteringFactor) + (accelZ * (1.0 - kFilteringFactor)) );
    
        if (accelZ > 0.0f)
        {
            if (spikeZCount > 9)
            {
                //  NSLog(@"SPIKE!");
                [[UIAccelerometer sharedAccelerometer] setDelegate:nil];
    
                [self isBumped];
            }
            else
            {
                spikeZCount++;
                //  NSLog(@"spikeZCount %i",spikeZCount);
            }
        }
        else
        {
            // NSLog(@"spikeZCount Reset");
            spikeZCount = 0;
        }
    }