在iOS中,Core Location和Core Motion框架的磁场值有什么区别? [英] In iOS, what is the difference between the Magnetic Field values from the Core Location and Core Motion frameworks?

查看:135
本文介绍了在iOS中,Core Location和Core Motion框架的磁场值有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两种方法可以使用iOS设备的磁力计获得磁场(强度,x,y和z)。



1)核心位置

使用来自的CLHeading CLLocationManagerDelegate 方法的LocationManager:didUpdateHeading:。这类似于Apple的Teslameter示例应用程序。



2)Core Motion

使用 CMMagneticField 来自 CMMotionManager 's magnetometerData.magneticField



问题:

a)两者有什么区别?我从两者中得到了不同的价值观。我期待他们将返回相同的值。

当我从静止位置(面朝上的桌子)启动应用程序时,差异最为显着,然后将设备提升到空中。

b)如果存在差异,何时应使用Core Location标题中的磁场,何时使用Core Motion的磁场?



注意:我也不确定Core Location和Core Motion的磁场是否涉及不同的磁场概念。

注意:我计算强度为(x ^的平方根) 2 + y ^ 2 + z ^ 2)两种方法。

解决方案

为了揭开这一点,我花了一点点钱时间挖掘Apple文档。



获取磁力计数据有三种方法



1 / ,它显示了一些差异。当应用程序运行并观察各种API的反应时,在设备周围挥动磁铁是非常有启发性的:



CMMagnetometer 没有反应除非你近距离拉稀土磁铁,否则什么都有。机载磁场似乎比局部外场或地球磁场更重要。在我的iPhone 4S上,它始终指向设备的左下角;在iPad mini上它通常指向右上角。



CLHeading。[x | y | z] 是最脆弱的(响应)到本地外部字段,无论是相对于设备移动还是静态。



(CMDevice) CMCalibratedMagneticField 在面对不同的外部字段时是最稳定的,但在其他方面跟踪它的核心位置对应 CLHeading。 [x | y | z] 非常接近。



CLHeading.magneticHeading - Apple对磁罗盘阅读的建议 - 比任何这些都要稳定得多。它使用来自其他传感器的数据来稳定磁力计数据。但是你没有得到x,y,z的原始细分

 
板载字段本地外部字段的影响地球场
黄色XXX
绿色_XX
蓝色_ _ X
红色_ _ X

黄色 CMMagnetometer

green CLHeading。[x | y | z]

blue CMCalibratedMagneticField

red CLHeading.magneticHeading



这似乎与文档相矛盾,这表明 CLHeading。[x | y | z] 应该比 CMCalibratedMagneticField 更少受本地外部字段的影响。



<你应该采取什么方法?基于我的有限测试,我建议...

如果你想要指南针阅读

CLHeading的 magneticHeading trueHeading 将为您提供最准确,最稳定的指南针读数。

如果您需要避免核心位置

CMDeviceMotion的 CMCalibratedMagneticField 似乎是下一个最理想的,虽然比 magneticHeading 。$
如果您对局部磁场感兴趣

CLHeading的'原始'xy和z属性似乎对局部磁场更敏感。< br>
如果您想要所有数据,包括板载磁场

来自CMMagnetometer的原始磁力计数据。除非你准备进行大量的过滤,否则使用它的确没有什么意义,因为它受到设备本身产生的磁场的巨大影响。


I have two ways of getting the magnetic fields (strength, x, y, and z) using the iOS device's magnetometer.

1) Core Location
Used the CLHeading from CLLocationManagerDelegate method locationManager:didUpdateHeading:. This is similar to Apple's Teslameter sample app.

2) Core Motion
Used CMMagneticField from CMMotionManager's magnetometerData.magneticField.

Questions:
a) What is the difference between the two? I am getting different values from both. I was expecting that they will return the same values.
The difference is most notable when I start the app from a resting position (face up in a table), and then lift the device up in to the air.
b) If there is a difference, when should I use the magnetic field from Core Location heading, and when should I use the magnetic field from Core Motion?

Note: I also am not sure if the "magnetic field" of Core Location and Core Motion refer to different magnetic field concepts.
Note: I computed strength as the square root of (x^2 + y^2 + z^2) for both approaches.

解决方案

To unravel this I've spent a bit too much time digging through the Apple docs.

There are three ways of obtaining magnetometer data

1/ Core Motion framework
CMMotionManagers's CMMagnetometer class

2/ Core Motion framework
CMDeviceMotion CMCalibratedMagneticField property

3 / Core Location framework
CLLocationManager's CLHeading

1/ supplies 'raw' data from the magnetometer.
2/ and 3/ return 'derived' data. The numbers in both cases are similar (though not exactly the same).

Difference between Core Motion's CMMagnetometer and CMCalibratedMagneticField

1/ and 2/ - both from the Core Motion framework - differ as follows:

CMDeviceMotion Class Reference

@property(readonly, nonatomic) CMCalibratedMagneticField magneticField

Discussion
The CMCalibratedMagneticField returned by this property gives you the total magnetic field in the device’s vicinity without device bias. Unlike the magneticField property of the CMMagnetometer class, these values reflect the earth’s magnetic field plus surrounding fields, minus device bias.

CMMagnetometer gives us raw data, CMCalibratedMagneticField is adjusted data.

Difference between Core Motion's CMCalibratedMagneticField and Core Location's CLHeading

The docs are not immediately clear on the difference between 2/ and 3/, but they do generate different numbers so let's do some digging….

Core Location framework
CLHeading

From Location Awareness Programming Guide

Getting Heading-Related Events

Heading events are available to apps running on a device that contains a magnetometer. A magnetometer measures nearby magnetic fields emanating from the Earth and uses them to determine the precise orientation of the device. Although a magnetometer can be affected by local magnetic fields, such as those emanating from fixed magnets found in audio speakers, motors, and many other types of electronic devices, Core Location is smart enough to filter out fields that move with the device.

Here are the relevant CLHeading 'raw' properties

@property(readonly, nonatomic) CLHeadingComponentValue x
@property(readonly, nonatomic) CLHeadingComponentValue y
@property(readonly, nonatomic) CLHeadingComponentValue z

The geomagnetic data (measured in microteslas) for the [x|y|z]-axis. (read-only)
This value represents the [x|y|z]-axis deviation from the magnetic field lines being tracked by the device. (older versions of the docs add:) The value reported by this property is normalized to the range -128 to +128.

I am not clear how a microtesla measurement can be 'normalized' (compressed? clipped?) to a range of +/-128 and still represent the unit it claims to measure. Perhaps that's why the sentence was removed from the docs. The units on an iPad mini do seem to conform to this kind of range, but the iPhone4S gives CMMagnetometer readings in higher ranges, eg 200-500.

The API clearly expects you to use the derived properties:

@property(readonly, nonatomic) CLLocationDirection magneticHeading
@property(readonly, nonatomic) CLLocationDirection trueHeading

which give stable N/S E/W compass readings in degrees (0 = North, 180 = South etc). For the true heading, other Core Location services are required (geolocation) to obtain the deviation of magnetic from true north.

Here is a snippet from the CLHeading header file

/*
 *  CLHeading
 *  
 *  Discussion:
 *    Represents a vector pointing to magnetic North constructed from 
 *    axis component values x, y, and z. An accuracy of the heading 
 *    calculation is also provided along with timestamp information.
 *  
 *  x|y|z
 *  Discussion:
 *    Returns a raw value for the geomagnetism measured in the [x|y|z]-axis.

Core Motion framework
CMDeviceMotion CMCalibratedMagneticField

/*
 *  magneticField
 *  
 *  Discussion:
 *          Returns the magnetic field vector with respect to the device for devices with a magnetometer.
 *          Note that this is the total magnetic field in the device's vicinity without device
 *          bias (Earth's magnetic field plus surrounding fields, without device bias),
 *          unlike CMMagnetometerData magneticField.
 */
@property(readonly, nonatomic) CMCalibratedMagneticField magneticField NS_AVAILABLE(NA,5_0);

CMMagnetometer

 *  magneticField
 *  
 *  Discussion:
 *    Returns the magnetic field measured by the magnetometer. Note
 *        that this is the total magnetic field observed by the device which
 *        is equal to the Earth's geomagnetic field plus bias introduced
 *        from the device itself and its surroundings.
 */
@property(readonly, nonatomic) CMMagneticField magneticField;  

CMMagneticField
This is the struct that holds the vector.
It's the same for CMDeviceMotion's calibrated magnetic field and CMMagnetometer's uncalibrated version:

/*  CMMagneticField - used in 
 *  CMDeviceMotion.magneticField.field
 *  CMMagnetometerData.magneticField
 *  
 *  Discussion:
 *    A structure containing 3-axis magnetometer data.
 *
 *  Fields:
 *    x:
 *      X-axis magnetic field in microteslas.
 *    y:
 *      Y-axis magnetic field in microteslas.
 *    z:
 *      Z-axis magnetic field in microteslas.


The difference between 2/ and 3/ are hinted at here:

Core Location CLHeading

Represents a vector pointing to magnetic North constructed from axis component values x, y, and z

Core Location is smart enough to filter out fields that move with the device

Core Motion CMCalibratedMagneticField

[represents] Earth's magnetic field plus surrounding fields, without device bias

So - according to the docs - we have:

1/ CMMagnetometer
Raw readings from the magnetometer

2/ CMDeviceMotion (CMCalibratedMagneticField*) magneticField
Magnetometer readings corrected for device bias (onboard magnetic fields)

3/ CLHeading [x|y|z]
Magnetometer readings corrected for device bias and filtered to eliminate local external magnetic fields (as detected by device movement - if the field moves with the device, ignore it; otherwise measure it)

Testing the theory

I have put a Magnet-O-Meter demo app on gitHub which displays some of these differences. It's quite revealing to wave a magnet around your device when the app is running and watching how the various APIs react:

CMMagnetometer doesn't react much to anything unless you pull a rare earth magnet up close. The onboard magnetic fields seem far more significant than local external fields or the earth's magnetic field. On my iPhone 4S it consistently points to the bottom left of the device; on the iPad mini it points usually to the top right.

CLHeading.[x|y|z] is the most vulnerable (responsive) to local external fields, whether moving or static relative to the device.

(CMDevice)CMCalibratedMagneticField is the most steady in the face of varying external fields, but otherwise tracks it's Core Location counterpart CLHeading.[x|y|z] pretty closely.

CLHeading.magneticHeading - Apple's recommendation for magnetic compass reading - is far more stable than any of these. It is using data from the other sensors to stabilise the magnetometer data. But you don't get a raw breakdown of x,y,z

             influenced by
             onboard fields    local external fields   earth's field
yellow               X                   X                 X
green                _                   X                 X
blue                 _                   _                 X
red                  _                   _                 X           

yellow CMMagnetometer
green CLHeading.[x|y|z]
blue CMCalibratedMagneticField
red CLHeading.magneticHeading

This does seem to contradict the docs, which suggest that CLHeading.[x|y|z] should be less influenced by local external fields than CMCalibratedMagneticField.

What approach should you take? Based on my limited testing, I would suggest…
If you want a compass reading
CLHeading's magneticHeading and trueHeading will give you the most accurate and most stable compass reading.
If you need to avoid Core Location
CMDeviceMotion's CMCalibratedMagneticField seems to be the next most desirable, although considerably less stable and accurate than magneticHeading.
If you are interested in local magnetic fields
CLHeading's 'raw' x y and z properties seem to be more sensitive to local magnetic fields.
If you want all of the data including onboard magnetic fields
Raw magnetometer data from CMMagnetometer. There is really not much point using this unless you are prepared to do tons of filtering, as it is hugely influenced by magnetic fields generated on the device itself.

这篇关于在iOS中,Core Location和Core Motion框架的磁场值有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆