【问题标题】:In iOS, what is the difference between the Magnetic Field values from the Core Location and Core Motion frameworks?在 iOS 中,Core Location 和 Core Motion 框架中的磁场值有什么区别?
【发布时间】:2013-03-01 02:40:31
【问题描述】:

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

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

2) 核心运动
使用CMMagneticField 来自CMMotionManagermagnetometerData.magneticField

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

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

【问题讨论】:

  • 您是否在使用CLHeadingmagneticHeading 属性?
  • @ThomasW 不,先生,我正在使用 CLHeading 的 x、y 和 z。

标签: ios core-location core-motion magnetometer


【解决方案1】:

为了解决这个问题,我花了太多时间研究 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 的 magneticHeadingtrueHeading 将为您提供最准确和最稳定的指南针读数。
如果您需要避开核心位置
CMDeviceMotion 的 CMCalibratedMagneticField 似乎是下一个最理想的,尽管比 magneticHeading 的稳定性和准确度要低得多。
如果您对局部磁场感兴趣
CLHeading 的“原始”x y 和 z 属性似乎对局部磁场更敏感。
如果您想要包括板载磁场在内的所有数据
来自 CMMagnetometer 的原始磁力计数据。除非您准备进行大量过滤,否则使用它实际上没有多大意义,因为它受到设备本身产生的磁场的巨大影响。

【讨论】:

  • 如果 CMAttitudeReferenceFrameXMagneticNorthZVertical 更改为 CMAttitudeReferenceFrameXTrueNorthZVertical,值会有所不同吗?如果是,您为什么选择 CMAttitudeReferenceFrameXMagneticNorthZVertical?
  • @MiuMiu,它不会有任何区别,因为参考框架只影响 CMAttitude(滚动、俯仰、偏航等)——我没有在这个演示中使用。
  • 感谢您的回答。由于我对局部磁场感兴趣,我将继续使用 CLHeading 的原始 x、y 和 z 值。
  • @foundry,我想您在表格的第二列将绿色和蓝色的十字混合在一起,因为绿色是 CLHeading.[x|y|z] 并且不受局部磁场干扰的影响
  • @AlexSmirnov - 我刚刚检查了我的代码,绿色肯定是 CLHeading。在理论上,这个不应该受到本地磁场的影响。但只需在运行应用程序时尝试在设备周围挥动磁铁即可。绿色有反应,蓝色没有。这也让我感到惊讶(长回复的原因之一)。
【解决方案2】:

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

  • (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager

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

【讨论】:

    【解决方案3】:

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

    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。

    【讨论】:

    • 1) 何时应针对磁场使用 CLHeading?我从您的回答中了解到,您对 CLHeading 的使用是关于方向,而不是磁场强度。还是它是唯一合理的用途? 2)你能不能告诉我为什么Apple在Tesmater示例应用程序中使用CLHeading而不是Core Motion的CMMagneticField?
    • @MiuMiu,请参阅我的回答 - CLHeading 确实测量场强,并且根据我的测试 - 这与有关此问题的文档相矛盾 - CLHeading 的 x|y|z 测量对本地外部磁最敏感场,因此将是通用磁场探测器的最佳候选者。
    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-03
      • 2019-04-22
      • 2016-03-14
      • 2019-07-13
      • 1970-01-01
      • 2010-12-25
      • 1970-01-01
      • 2020-08-10
      相关资源
      最近更新 更多