Dans iOS, quelle est la différence entre les valeurs du champ magnétique des frameworks Core Location et Core Motion?

J'ai deux façons d'get les champs magnétiques (force, x, y et z) en utilisant le magnétomètre de l'appareil iOS.

1) Emplacement principal
Utilisation de la méthode CLHeading from CLLocationManagerDelegate locationManager:didUpdateHeading: Ceci est similaire à l'exemple d'application Teslameter d'Apple.

2) Motion de base
CMMagneticField de CMMotionManager 's CMMotionManager .

Des questions:
a) Quelle est la différence entre les deux? Je reçois des valeurs différentes des deux. Je m'attendais à ce qu'ils reviennent les mêmes valeurs.
La différence est la plus notable lorsque je démarre l'application à partir d'une position de repos (face vers le haut dans une table), puis soulevez l'appareil dans l'air.
b) S'il y a une différence, quand devrais-je utiliser le champ magnétique à partir de l'en-tête Emplacement principal, et quand devrais-je utiliser le champ magnétique de Core Motion?

Remarque: Je ne suis pas sûr non plus si le "champ magnétique" de Core Location et Core Motion fait reference à différents concepts de champs magnétiques.
Note: J'ai calculé la force comme la racine carrée de (x ^ 2 + y ^ 2 + z ^ 2) pour les deux approches.

Pour démêler cela, j'ai passé un peu trop de time à fouiller dans les documents Apple.

Il y a trois façons d'get des données de magnétomètre

1 / Cadre de base du mouvement
La class CMMagnetometer de CMMagnetometer

2 / Cadre de base du mouvement
Propriété CMDeviceMotion CMCalibratedMagneticField

3 / Cadre de base de localization
CLLocationManager CLHeading

1 / fournit des données «brutes» du magnétomètre.
2 / et 3 / renvoie des données «dérivées». Les numbers dans les deux cas sont similaires (mais pas exactement les mêmes).

Différence entre CMMagnetometer de Core Motion et CMCalibratedMagneticField

1 / et 2 / – tous deux du cadre de la motion de base – diffèrent comme suit:

Référence de la class CMDeviceMotion

 @property(readonly, nonatomic) CMCalibratedMagneticField magneticField 

Discussion
Le CMCalibratedMagneticField returnné par cette propriété vous donne le champ magnétique total dans le voisinage de l'appareil sans biais de l'appareil. Contrairement à la propriété magneticField de la class CMMagnetometer, ces valeurs reflètent le champ magnétique de la Terre plus les champs environnants, less le biais de l'appareil.

CMMagnetometer nous donne des données brutes, CMCalibratedMagneticField est des données ajustées.

Différence entre CMCalibratedMagneticField de Core Motion et CLHeading de Core Location

Les docs ne sont pas immédiatement clair sur la différence entre 2 / et 3 /, mais ils génèrent des nombres différents alors faisons quelques searchs …

Cadre de base de localization
CLHeading

À partir du Guide de programmation Awareness

Obtention d'events liés à la rubrique

Les events de rubrique sont disponibles pour les applications exécutées sur un appareil qui contient un magnétomètre. Un magnétomètre mesure les champs magnétiques environnants émanant de la Terre et les utilise pour déterminer l'orientation précise de l'appareil. Bien qu'un magnétomètre puisse être affecté par des champs magnétiques locaux, tels que ceux provenant d'aimants fixes présents dans les haut-parleurs, les moteurs et de nombreux autres types d'appareils électroniques, Core Location est assez intelligent pour filterr les champs qui se déplacent avec l'appareil.

Voici les CLHeading «premières» de CLHeading

 @property(readonly, nonatomic) CLHeadingComponentValue x @property(readonly, nonatomic) CLHeadingComponentValue y @property(readonly, nonatomic) CLHeadingComponentValue z 

Les données géomagnétiques (mesurées en microteslas) pour l'axe [x | y | z]. (lecture seulement)
Cette valeur représente l'écart [x | y | z] -axis des lignes de champ magnétique suivies par l'appareil. (les anciennes versions des docs ajoutent 🙂 La valeur signalée par cette propriété est normalisée entre -128 et +128.

Je ne comprends pas comment une mesure microtesla peut être «normalisée» (comprimée? Écrêtée?) À une plage de +/- 128 et représenter toujours l'unité qu'elle prétend mesurer. C'est peut-être pourquoi la phrase a été retirée des docs. Les unités sur un iPad mini semblent se conformer à ce type de gamme, mais l'iPhone4S donne des lectures CMMagnetometer dans des gammes plus élevées, par exemple 200-500.

L'API s'attend clairement à ce que vous utilisiez les propriétés dérivées:

 @property(readonly, nonatomic) CLLocationDirection magneticHeading @property(readonly, nonatomic) CLLocationDirection trueHeading 

qui donne des lectures de boussole N / SE / W stables en degrés (0 = Nord, 180 = Sud, etc.). Pour le vrai cap, d'autres services de localization de base sont nécessaires (geolocation) pour get l'écart de la direction magnétique par rapport au nord géographique.

Voici un extrait du file d'en-tête 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. 

Core Motion framework
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
C'est la structure qui contient le vector.
Il en est de même pour le champ magnétique calibré de CMMagnetometer et la version non calibrée de 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. 

La différence entre 2 / et 3 / est indiquée ici:

Emplacement principal CLHeading

Représente un vector pointant sur le nord magnétique construit à partir des valeurs des composantes d'axe x, y et z

L'location principal est assez intelligent pour filterr les champs qui se déplacent avec l'appareil

Core Motion CMCalibratedMagneticField

[représente] le champ magnétique terrestre plus les champs environnants , sans biais de l'appareil

Donc – selon les docs – nous avons:

1 / CMMagnetometer
Lectures brutes du magnétomètre

2 / CMDeviceMotion (CMCalibratedMagneticField *) magneticField
Les lectures du magnétomètre ont été corrigées pour la polarisation de l'appareil (champs magnétiques embarqués)

3 / CLHeading [x | y | z]
Les lectures du magnétomètre ont été corrigées pour le biais de l'appareil et filtrées pour éliminer les champs magnétiques externes locaux (détectés par le mouvement de l'appareil – si le champ se déplace avec l'appareil, ignorez-le, sinon mesurez-le)

Tester la théorie

entrez la description de l'image ici

J'ai mis une application de démonstration Magnet-O-Meter sur gitHub qui affiche certaines de ces différences. Il est assez révélateur d'agiter un aimant autour de votre appareil lorsque l'application fonctionne et de voir comment les différentes API réagissent:

CMMagnetometer ne réagit à rien à less de tirer un aimant de terre rare de près. Les champs magnétiques embarqués semblent beaucoup plus importants que les champs externes locaux ou le champ magnétique terrestre. Sur mon iPhone 4S, il pointe constamment vers le bas à gauche de l'appareil; sur l'iPad mini, il pointe généralement vers le haut à droite.

CLHeading. [X | y | z] est le plus vulnérable (sensible) aux champs externes locaux, qu'ils soient mobiles ou statiques par rapport au périphérique.

(CMDevice) CMCalibratedMagneticField est le plus stable face à la variation des champs externes, mais il suit de très près son homologue du Core Location CLHeading. [X | y | z] .

CLHeading.magneticHeading – la recommandation d'Apple pour la lecture de boussole magnétique – est beaucoup plus stable que l'un de ceux-ci. Il utilise datatables des autres capteurs pour stabiliser datatables du magnétomètre. Mais vous n'obtenez pas une ventilation brute de x, y, z

  influenced by onboard fields local external fields earth's field yellow XXX green _ XX blue _ _ X red _ _ X 

CMMagnetometer jaune
CLHeading vert . [x | y | z]
CMCalibratedMagneticField bleu
CLHeading.magneticHeading rouge

Cela semble contredire les docs, qui suggèrent que CLHeading. [X | y | z] devrait être less influencé par les champs externes locaux que CMCalibratedMagneticField .

Quelle approche devriez-vous prendre? Basé sur mes tests limités, je suggérerais …
Si vous voulez une lecture de boussole
Les fonctions magneticHeading et trueHeading vous donneront la lecture de la boussole la plus précise et la plus stable.
Si vous devez éviter Core Location
Le CMCalibratedMagneticField de CMCalibratedMagneticField semble être le deuxième plus souhaitable, bien que considérablement less stable et précis que magneticHeading .
Si vous êtes intéressé par les champs magnétiques locaux
Les propriétés xy et z «crues» de CLHeading semblent être plus sensibles aux champs magnétiques locaux.
Si vous voulez toutes datatables, y compris les champs magnétiques embarqués
Données magnétomésortingques brutes de CMMagnetometer. Il n'y a vraiment pas grand chose à utiliser à less que vous soyez prêt à faire des tonnes de filtrage, car il est énormément influencé par les champs magnétiques générés sur l'appareil lui-même.

cette réponse est basée sur mon interprétation des liens de documentation ci-dessous

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 est " déviation des lignes de champ magnétique suivies par le dispositif" tandis que magnetometerData.magneticField "est le champ magnétique total observé par le dispositif qui est égal au champ géomagnétique de la Terre plus le biais introduit par le dispositif lui-même et ses environs" .

Ainsi CLHeading vous donne des valeurs filtrées avec le cadre de reference étant le champ magnétique existant de la terre. Alors que magnétomètreData vous donne des valeurs non filtrées avec le cadre de reference étant l'appareil.

b) Si vous faisiez quelque chose avec l'endroit où vous vouliez savoir où est le nord magnétique ou vrai, je reorderais d'utiliser CLHeading. Si vous vouliez créer une application qui répond aux champs magnétiques dans les environs immédiats des appareils ou si vous aviez une fusion de capteur spécifique que vous vouliez effectuer, essayez peut-être de créer un AHRS par exemple, puis allez avec CMMagneticField.

Une chose importante à retenir lors de l'utilisation des valeurs CLHeading. [X | y | z] pour calculer l'intensité du champ magnétique local est que la méthode CLLocationManagerDelegate

  • (BOOL) locationManagerShouldDisplayHeadingCalibration: gestionnaire (CLLocationManager *)

devrait être réglé pour returnner YES. J'ai constaté que les lectures du magnétomètre ne sont jamais calibrées si cet avertissement d'étalonnage est désactivé, et qu'en conséquence, l'intensité de champ calculée est très instable lorsque l'orientation de l'appareil est modifiée.

Je pense que le magnétomètreData.magneticField vous indique l'accélération, pas la position (d'où la grande valeur qui passe d'immobile à mobile), alors que le gestionnaire de localization fournit des données sur la direction vers laquelle pointe le périphérique.