为了解决这个问题,我花了太多时间研究 Apple 文档。
获取磁力计数据的三种方式
1/Core Motion framework
CMMotionManagers 的CMMagnetometer 类
2/核心运动框架
CMDeviceMotionCMCalibratedMagneticField属性
3 / Core Location framework
CLLocationManager的CLHeading
1/ 提供来自磁力计的“原始”数据。
2/ 和 3/ 返回“派生”数据。两种情况下的数字相似(尽管不完全相同)。
Core Motion的CMMagnetometer和CMCalibratedMagneticField的区别
1/ 和 2/ - 均来自 Core Motion 框架 - 不同之处如下:
CMDeviceMotion 类参考
@property(readonly, nonatomic) CMCalibratedMagneticField magneticField
讨论
此属性返回的 CMCalibratedMagneticField 为您提供了设备附近的总磁场,没有设备偏差。与 CMMagnetometer 类的磁场属性不同,这些值反映了地球磁场加上周围磁场,减去设备偏差。
CMMagnetometer 为我们提供原始数据,CMCalibratedMagneticField 是调整后的数据。
Core Motion 的 CMCalibratedMagneticField 和 Core Location 的 CLHeading 的区别
文档并没有立即明确 2/ 和 3/ 之间的区别,但它们确实生成了不同的数字,所以让我们进行一些挖掘......
核心定位框架
CLHeading
来自Location Awareness Programming Guide
获取与标题相关的事件
标题事件适用于在包含磁力计的设备上运行的应用。磁力计测量从地球发出的附近磁场,并使用它们来确定设备的精确方向。尽管磁力计可能会受到局部磁场的影响,例如来自音频扬声器、电机和许多其他类型电子设备中的固定磁铁的磁场,但 Core Location 足够智能,可以过滤掉随设备移动的磁场。
这里是相关的CLHeading'raw'属性
@property(readonly, nonatomic) CLHeadingComponentValue x
@property(readonly, nonatomic) CLHeadingComponentValue y
@property(readonly, nonatomic) CLHeadingComponentValue z
[x|y|z] 轴的地磁数据(以微特斯拉计)。 (只读)
该值表示与设备跟踪的磁力线的 [x|y|z] 轴偏差。
(旧版本的文档添加:)此属性报告的值被标准化为 -128 到 +128 的范围。
我不清楚如何将微特斯拉测量值“标准化”(压缩?剪裁?)到 +/-128 的范围内,并且仍然代表它声称要测量的单位。也许这就是从文档中删除该句子的原因。 iPad mini 上的单位似乎符合这种范围,但 iPhone4S 的 CMMagnetometer 读数范围更大,例如 200-500。
API 显然希望您使用派生属性:
@property(readonly, nonatomic) CLLocationDirection magneticHeading
@property(readonly, nonatomic) CLLocationDirection trueHeading
以度为单位提供稳定的 N/S E/W 罗盘读数(0 = 北,180 = 南等)。对于真航向,需要其他核心定位服务(地理定位)来获得磁与真北的偏差。
这是来自CLHeading 头文件的sn-p
/*
* 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.
核心运动框架
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
这是保存向量的结构。
CMDeviceMotion的校准磁场和CMMagnetometer的未校准版本是一样的:
/* 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.
这里暗示了 2/ 和 3/ 之间的区别:
核心位置CLHeading
表示由轴分量值 x、y 和 z 构造的指向磁北的向量
Core Location 足够智能,可以过滤掉随设备移动的字段
核心运动CMCalibratedMagneticField
[表示]地球磁场加上周围的磁场,没有设备偏差
所以 - 根据文档 - 我们有:
1/ CMMagnetometer
磁力计的原始读数
2/ CMDeviceMotion (CMCalibratedMagneticField*) 磁场
针对设备偏差(板载磁场)校正的磁力计读数
3/ CLHeading [x|y|z]
磁力计读数针对设备偏差进行校正并过滤以消除局部外部磁场(通过设备移动检测到 - 如果磁场随设备移动,则忽略它;否则测量它)
检验理论
我放了一个Magnet-O-Meter demo app on gitHub,它显示了其中一些差异。当应用程序运行并观察各种 API 的反应时,在您的设备周围挥动磁铁非常有启发性:
CMMagnetometer 对任何东西都没有太大反应,除非你拉近稀土磁铁。机载磁场似乎比局部外部磁场或地球磁场重要得多。在我的 iPhone 4S 上,它始终指向设备的左下角;在 iPad mini 上,它通常指向右上角。
CLHeading.[x|y|z] 对本地外部场最脆弱(响应),无论是相对于设备移动还是静止。
(CMDevice)CMCalibratedMagneticField 在面对变化的外部场时是最稳定的,但在其他方面跟踪它的核心位置对应物CLHeading。[x|y|z] 漂亮密切。
CLHeading.magneticHeading - Apple 推荐的磁罗盘读数 - 比其中任何一个都稳定得多。它使用来自其他传感器的数据来稳定磁力计数据。但是你没有得到 x,y,z 的原始分解
influenced by
onboard fields local external fields earth's field
yellow X X X
green _ X X
blue _ _ X
red _ _ X
黄色 CMMagnetometer
绿色 CLHeading.[x|y|z]
蓝色 CMCalibratedMagneticField
红色 CLHeading.magneticHeading
这似乎与文档相矛盾,文档表明 CLHeading.[x|y|z] 应该比 CMCalibratedMagneticField 受本地外部场的影响更小。 p>
你应该采取什么方法?根据我有限的测试,我建议……
如果您想要指南针读数
CLHeading 的 magneticHeading 和 trueHeading 将为您提供最准确和最稳定的指南针读数。
如果您需要避开核心位置
CMDeviceMotion 的 CMCalibratedMagneticField 似乎是下一个最理想的,尽管比 magneticHeading 的稳定性和准确度要低得多。
如果您对局部磁场感兴趣
CLHeading 的“原始”x y 和 z 属性似乎对局部磁场更敏感。
如果您想要包括板载磁场在内的所有数据
来自 CMMagnetometer 的原始磁力计数据。除非您准备进行大量过滤,否则使用它实际上没有多大意义,因为它受到设备本身产生的磁场的巨大影响。