Подтвердить что ты не робот

В iOS, в чем разница между значениями магнитного поля от базового расположения и базовых структур Core Motion?

У меня есть два способа получить магнитные поля (прочность, x, y и z) с помощью магнитометра устройства iOS.

1) Основное местоположение
Используется метод CLHeading из CLLocationManagerDelegate locationManager:didUpdateHeading:. Это похоже на пример приложения Apple Teslameter.

2) Основное движение
Используется CMMagneticField от CMMotionManager magnetometerData.magneticField.

Вопросы:
a) В чем разница между этими двумя? Я получаю разные значения от обоих. Я ожидал, что они вернут те же ценности.
Разница наиболее примечательна, когда я запускаю приложение из положения покоя (лицом вверх в таблице), а затем поднимаю устройство вверх в воздух.
б) Если есть разница, когда следует использовать магнитное поле из заголовка Core Location и когда я должен использовать магнитное поле от Core Motion?

Примечание. Я также не уверен, что "магнитное поле" Core Location и Core Motion относится к различным концепциям магнитного поля.
Примечание: Я вычислял силу как квадратный корень из (x ^ 2 + y ^ 2 + z ^ 2) для обоих подходов.

4b9b3361

Ответ 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]
Показания магнитометра были скорректированы с учетом смещения устройства и отфильтрованы для устранения локальных внешних магнитных полей (как обнаружено движением устройства - если поле движется вместе с устройством, игнорируйте его; в противном случае измерьте его)

Проверка теории

enter image description here

Я поместил демонстрационное приложение 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. В действительности нет особого смысла использовать это, если вы не готовы выполнять тонны фильтрации, так как на него сильно влияют магнитные поля, генерируемые самим устройством.

Ответ 2

этот ответ основан на моей интерпретации ссылок документации ниже

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 дает вам отфильтрованные значения с Frame of Reference, являющимся существующим магнитным полем земли. В то время как magnetometerData дает вам нефильтрованные значения с Структурой ссылки, являющейся устройством.

b) если вы делали что-либо с местоположением, где вы хотели знать, где магнитный или истинный север, я бы рекомендовал использовать CLHeading. Если вы хотите создать приложение, которое реагирует на магнитные поля в ближайших соседних устройствах или у вас возникли определенные слияния датчиков, которые вы хотели выполнить, попробуйте создать AHRS, а затем перейдите к CMMagneticField.

Ответ 3

Важно помнить при использовании значений CLHeading. [x | y | z] для расчета локальной напряженности магнитного поля заключается в том, что метод CLLocationManagerDelegate

  • (BOOL) locationManagerShouldDisplayHeadingCalibration: (диспетчер CLLocationManager *)

следует установить для возврата YES. Я обнаружил, что показания магнитометра никогда не откалиброваны, если это предупреждение о калибровке выключено и что в результате расчетная напряженность поля очень нестабильна при изменении ориентации устройства.

Ответ 4

Я думаю, что магнитометр Data.magneticField сообщает вам ускорение, а не позицию (следовательно, почему вы получаете большие значения, перемещающиеся из неподвижного состояния в движущиеся), тогда как диспетчер местоположений предоставляет данные о направлении, на которое указывает устройство.