Question

I'm trying to detect when the user moves their phone down, and when they move it back up. The phone only movies up and down (there is no side to side motion)

I'm logging the acceleration data, but it's always negative, even when I move back up. Why is this?

[_motionManager startAccelerometerUpdatesToQueue:[[NSOperationQueue alloc] init]
                                     withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
                                         dispatch_async(dispatch_get_main_queue(), ^{
                                             [self performSelectorOnMainThread:@selector(update:) withObject:accelerometerData waitUntilDone:NO];
                                         });

-Update:

- (void)update:(CMAccelerometerData *)accelData {
      NSLog(@"acceldata.z %f",accelData.acceleration.z);
}

Sample Data

2014-03-14 02:24:02.973 myApp[16294:60b] acceldata.z -0.863266
2014-03-14 02:24:02.993 myApp[16294:60b] acceldata.z -0.855530
2014-03-14 02:24:03.004 myApp[16294:60b] acceldata.z -0.853592
2014-03-14 02:24:03.024 myApp[16294:60b] acceldata.z -0.793396
2014-03-14 02:24:03.043 myApp[16294:60b] acceldata.z -0.774567
2014-03-14 02:24:03.053 myApp[16294:60b] acceldata.z -0.749664
2014-03-14 02:24:03.072 myApp[16294:60b] acceldata.z -0.716141
2014-03-14 02:24:03.082 myApp[16294:60b] acceldata.z -0.733749
2014-03-14 02:24:03.102 myApp[16294:60b] acceldata.z -0.752518
Était-ce utile?

La solution

The problem is that gravity is an acceleration, and it never stops. (Actually I guess that is a good thing.) Your user motion is "hidden" in the combination of user acceleration (muscle-based motion) and gravity. That is because you are using raw accelerometer data. That is kind of a silly thing to do.

You can roughly filter out gravity with a high-pass filter. Apple has plenty of example code showing how to do that.

However, it would be much more sensible to use CMDeviceMotion (startDeviceMotionUpdatesUsingReferenceFrame:), which gives you a userAcceleration property which has already performed this filtering far more accurately, and with less latency, than you could possibly do it.

Autres conseils

The acceleration data returned by iOS is "normalized" where a value of 1.0 represents equivalence with earth's gravity. That is, a phone laid face-up on a table will consistently return "Z" values of right around -1.0 (you never end up with a static value; it's constantly varying slightly, even when the phone is completely at rest).

The acceleration.z value in your CMAccelerometerData object represents the axis running perpendicular to the front/back of the phone.

Based on your data (values of -0.86 to -0.71), you are moving the phone's screen toward the center of the earth. It's hard to tell exactly what's going on without the X and Y axis values. Basically, a value of -0.8 indicates that the z-axis is accelerating toward the center of the earth at 0.2 * 9.8m/s/s.

If you want positive values, flip the phone screen-down. Alternatively, you can "drop" the phone, making its downward acceleration exceed the acceleration by earth's gravity.

You should actually use all 3 values to determine the vector of acceleration in case the phone isn't perfectly perpendicular to the earth's gravity.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top