65

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

1)核心位置
使用CLLocationManagerDelegate方法的CLHeading locationManager:didUpdateHeading:。这类似于 Apple 的 Teslameter 示例应用程序。

2) 核心运动从's
使用。 CMMagneticFieldCMMotionManagermagnetometerData.magneticField

问题:
a) 两者有什么区别?我从两者中得到不同的价值观。我期待他们会返回相同的值。
当我从静止位置(面朝上放在桌子上)启动应用程序,然后将设备举到空中时,差异最为显着。
b) 如果有差异,我应该什么时候使用 Core Location 航向的磁场,什么时候应该使用 Core Motion 的磁场?

注意:我也不确定核心位置和核心运动的“磁场”是否指不同的磁场概念。
注意:对于这两种方法,我将强度计算为 (x^2 + y^2 + z^2) 的平方根。

4

4 回答 4

191

为了解决这个问题,我花了太多时间研究 Apple 文档。

获取磁力计数据的三种方式

1/ Core Motion框架
CMMotionManagers的CMMagnetometer

2/核心运动框架
CMDeviceMotion CMCalibratedMagneticField属性

3/核心位置框架
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

来自位置感知编程指南

获取与标题相关的事件

在包含磁力计的设备上运行的应用程序可以使用航向事件。磁力计测量从地球发出的附近磁场,并使用它们来确定设备的精确方向。尽管磁力计可能会受到局部磁场的影响,例如来自音频扬声器、电机和许多其他类型电子设备中的固定磁铁的磁场,但 Core Location 足够智能,可以过滤掉随设备移动的磁场。

以下是相关CLHeading的“原始”属性

@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/SE/W 罗盘读数(0 = 北,180 = 南等)。对于真航向,需要其他核心定位服务(地理定位)来获得磁与真北的偏差。

这是CLHeading头文件的一个片段

/*
 *  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);

CM磁力计

 *  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 Motion CM校准磁场

[表示] 地球磁场加上周围磁场,没有设备偏差

所以 - 根据文档 - 我们有:

1/ CMMagnetometer
来自磁力计的原始读数

2/ CMDeviceMotion (CMCalibratedMagneticField*) 磁场
磁力计读数针对设备偏差进行了校正(板载磁场)

3/ CLHeading [x|y|z]
磁力计读数针对设备偏差进行了校正,并经过过滤以消除局部外部磁场(通过设备移动检测到 - 如果磁场随设备移动,则忽略它;否则测量它)

测试理论

在此处输入图像描述

在 gitHub 上放了一个 Magnet-O-Meter 演示应用程序,它显示了其中一些差异。当应用程序运行并观察各种 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受本地外部场的影响更小。

你应该采取什么方法?根据我有限的测试,我建议……<br> 如果您想要一个罗盘读数
CLHeading 的magneticHeadingtrueHeading它将为您提供最准确和最稳定的罗盘读数。
如果您需要避免核心位置,
CMDeviceMotionCMCalibratedMagneticField似乎是下一个最理想的位置,尽管它的稳定性和准确性远不如magneticHeading.
如果您对局部磁场感兴趣,
CLHeading 的“原始”xy 和 z 属性似乎对局部磁场更敏感。
如果您想要包括板载磁场在内的所有数据
来自 CMMagnetometer 的原始磁力计数据。除非您准备进行大量过滤,否则使用它实际上没有多大意义,因为它受到设备本身产生的磁场的巨大影响。

于 2013-03-18T05:59:43.470 回答
1

此答案基于我对以下文档链接的解释

http://developer.apple.com/library/ios/#documentation/CoreLocation/Reference/CLHeading_Class/Reference/Reference.html#//apple_ref/doc/c_ref/CLHeading

http://developer.apple.com/library/ios/#documentation/CoreMotion/Reference/CMMagnetometerData_Class/Reference/Reference.html#//apple_ref/doc/c_ref/CMMagnetometerData

a) CLHeading 是“与设备跟踪的磁场线的偏差”,而磁力计Data.magneticField“是设备观察到的总磁场,等于地球的地磁场加上设备本身及其周围环境引入的偏置” .

因此 CLHeading 为您提供过滤值,参考框架是地球现有的磁场。而磁力计数据为您提供未经过滤的值,参考框架是设备。

b)如果您在想知道磁北或真北的位置做任何事情,我建议您使用 CLHeading。如果您想创建一个响应设备附近磁场的应用程序,或者您想要执行一些特定的传感器融合,可以尝试创建一个 AHRS,然后使用 CMMagneticField。

于 2013-03-17T12:39:56.147 回答
1

使用 CLHeading.[x|y|z] 值计算局部磁场强度时要记住的重要一点是 CLLocationManagerDelegate 方法

  • (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager

应设置为返回 YES。我发现如果关闭此校准警告,则永远不会校准磁力计读数,因此当设备的方向改变时,计算出的场强非常不稳定。

于 2013-08-11T13:55:59.637 回答
0

我认为磁力计Data.magneticField 它告诉您加速度,而不是位置(因此为什么您会得到从静止到移动的大值),而位置管理器则提供有关设备指向的方向的数据。

于 2013-03-15T12:15:20.817 回答