Ответ 1
Чтобы разгадать это, я потратил слишком много времени, копаясь в документах Apple.
Есть три способа получения данных магнитометра
1/Core Motion Framework
CMMotionManager CMMagnetometer
класс
2/Core Motion Framework
Свойство CMCalibratedMagneticField
3/Базовая структура местоположения
CLLocationManager CLHeading
1/предоставляет "необработанные" данные с магнитометра.
2/и 3 /вернуть "производные" данные. Числа в обоих случаях одинаковы (хотя и не совсем одинаковы).
Разница между Core Motion CMMagnetometer и CMCalibratedMagneticField
1/и 2 / - оба из каркаса Core Motion - отличаются следующим:
Описание класса CMDeviceMotion
@property(readonly, nonatomic) CMCalibratedMagneticField magneticField
обсуждение
Поле CMCalibratedMagneticField, возвращаемое этим свойством, дает полное магнитное поле в окрестности устройства без смещения устройства. В отличие от свойства MagneticField класса CMMagnetometer, эти значения отражают магнитное поле Земли плюс окружающие поля минус смещение устройства.
CMMagnetometer дает нам необработанные данные, CMCalibratedMagneticField - откорректированные данные.
Разница между Core Motion CMCalibratedMagneticField и расположением ядра 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] -axis. (Только для чтения)
Это значение представляет отклонение [x | y | z] -axis от линий магнитного поля, отслеживаемых устройством. (более старые версии документации добавляют :) Значение, сообщаемое этим свойством, нормализуется в диапазоне от -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.
Базовая структура Motion
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 vicinity without device
* bias (Earth 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 geomagnetic field plus bias introduced
* from the device itself and its surroundings.
*/
@property(readonly, nonatomic) CMMagneticField magneticField;
CMMagneticField
Это структура, которая содержит вектор. CMDeviceMotion
же самое для калиброванного магнитного поля CMMagnetometer
некалиброванной версии 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 CMCalibratedMagneticField
[представляет] магнитное поле Земли плюс окружающие поля, без смещения устройства
Итак, согласно документам, мы имеем:
1/CMМагнетометр
Необработанные показания магнитометра
2/CMDeviceMotion (CMCalibratedMagneticField *) магнитное поле
Показания магнитометра с поправкой на смещение устройства (бортовые магнитные поля)
3/CLHeading [x | y | z]
Показания магнитометра были скорректированы с учетом смещения устройства и отфильтрованы для устранения локальных внешних магнитных полей (как обнаружено движением устройства - если поле движется вместе с устройством, игнорируйте его; в противном случае измерьте его)
Проверка теории
Я поместил демонстрационное приложение Magnet-O-Meter на gitHub, которое отображает некоторые из этих различий. Это довольно показательно, когда вы работаете с приложением и наблюдаете, как реагируют различные API:
CMMagnetometer не реагирует ни на что, если вы не притянете к себе редкоземельный магнит. Бортовые магнитные поля кажутся гораздо более значительными, чем локальные внешние поля или магнитное поле Земли. На моем iPhone 4S он постоянно указывает на левую нижнюю часть устройства; на iPad mini он обычно указывает вверху справа.
CLHeading. [X | y | z] является наиболее уязвимым (реагирующим) на локальные внешние поля, движущиеся или статические по отношению к устройству.
(CMDevice) CMCalibratedMagneticField является наиболее устойчивым в условиях изменяющихся внешних полей, но в остальном отслеживает его аналог Core Location CLHeading. [X | y | z] довольно близко.
CLHeading.magnHeading - рекомендация Apple по считыванию магнитных компасов - гораздо более стабильна, чем любая из них. Он использует данные других датчиков для стабилизации данных магнитометра. Но вы не получите грубую разбивку по x, y, z
influenced by
onboard fields local external fields earth field
yellow X X X
green _ X X
blue _ _ X
red _ _ X
желтый CMMagnetometer
зеленый CLHeading. [x | y | z]
синий CMCalibratedMagneticField
красный CLHeading.magnHeading
Это, кажется, противоречит документам, которые предполагают, что CLHeading. [X | y | z] должен быть менее подвержен влиянию локальных внешних полей, чем CMCalibratedMagneticField.
Какой подход вы должны выбрать? На основании моего ограниченного тестирования я бы предложил...
Если вы хотите, чтобы чтение компаса
CLHeading magneticHeading
и trueHeading
даст вам наиболее точные и наиболее стабильных показаний компаса.
Если вам нужно избежать Core Location
CMDeviceMotion CMCalibratedMagneticField
похоже, является следующим наиболее желательным, хотя и значительно менее стабильным и точным, чем magneticHeading
.
Если вы заинтересованы в локальных магнитных полях
CLHeading "необработанные" свойства xy и z кажутся более чувствительными к локальным магнитным полям.
Если вам нужны все данные, включая бортовые магнитные поля
Необработанные данные магнитометра из CMMagnetometer. В действительности нет особого смысла использовать это, если вы не готовы выполнять тонны фильтрации, так как на него сильно влияют магнитные поля, генерируемые самим устройством.