0

我试图仅依靠设备的磁力计来获取设备的磁北偏角(以度为单位)。这是我写的代码,但我只是得到 0 度。我做错了什么?

CMMotionManager *motionManager;

motionManager = [[CMMotionManager alloc] init];

[motionManager startDeviceMotionUpdates];

CMDeviceMotion *deviceMotion;

deviceMotion = [[CMDeviceMotion alloc] init];

while(!self.stopButtonPressed)
{
    double x = motionManager.deviceMotion.magneticField.field.x;

    double y = motionManager.deviceMotion.magneticField.field.y;

    double degrees = asin(y/sqrt(pow(x, 2.0) + pow(y, 2.0))) * 180.0 / M_PI ;

    int degreesRounded = (int)degrees;

    NSLog(@"Degrees : %i", degreesRounded);
}
4

3 回答 3

0

上面的代码在哪个线程上运行?如果您在主线程上运行它,您可能不会随着时间的推移看到设备运动数据的更新。使用 NSTimer 或类似机制随时间对运动进行采样,因此主线程可以自由地做其他事情(例如来自核心运动子系统的服务请求)。

于 2012-07-29T18:11:52.397 回答
0

模拟器可能不会为这些方法返回正常值,因此您需要在真实设备上进行测试。

CLLocationManager方法didUpdateHeading:在模拟器上不起作用,所以你可能在这里遇到类似的事情。

编辑:

从文档:

“设备运动数据的最新样本。(只读)

@property(只读) CMDeviceMotion *deviceMotion

讨论 如果没有可用的设备运动数据,则此属性的值为 nil。在调用 startDeviceMotionUpdates 后接收设备运动数据的应用程序会定期检查此属性的值并处理设备运动数据。”

检查您的运动管理器的该属性是否为零。如果是,那么你会得到 0 的磁场属性。

编辑2:

而不是使用startDeviceMotionUpdates,你应该使用startMagnetometerUpdatesToQueue:。文档是这样说的:

“磁力计。设置磁力计UpdateInterval 属性以指定更新间隔。调用startMagnetometerUpdatesToQueue:withHandler: 方法,传递CMMagnetometerHandler 类型的块。磁场数据作为CMMagnetometerData 对象传递到块中。”

文档在这里

于 2012-07-29T18:05:27.357 回答
0

这是我在真实设备上测试的结果:

   CMMotionManager *myMotionManager= [[CMMotionManager alloc] init];
    myMotionManager.deviceMotionUpdateInterval = 1;
    [myMotionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXMagneticNorthZVertical  toQueue:[NSOperationQueue currentQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
        double x = myMotionManager.deviceMotion.magneticField.field.x;
        double y = myMotionManager.deviceMotion.magneticField.field.y;
        double z = myMotionManager.deviceMotion.magneticField.field.z;
        NSLog(@"Field.x= %f; Field.y = %f; Field.z= %f",x,y,z);
    }];
于 2014-06-24T06:14:55.503 回答