2012-02-13 7 views
2

J'ai besoin de calculer "facing" (peu importe si ce sera basé sur le vrai nord ou magnétique). Comme on peut le voir sur les appareils iOS, les objets CLHeading retournés par le CLLocationManager nous donnent à la fois le cap vrai et le cap magnétique par les propriétés correspondantes. En outre, nous pouvons très facilement voir, que ces valeurs sont liées au sommet de l'appareil (l'axe Y positif du système de coordonnées des appareils) ce qui n'est pas bon pour mes fins. Ce dont j'ai réellement besoin, c'est de calculer le parement lié à l'écran de l'appareil (axe Z) car je n'ai pas besoin de la boussole, mais d'un roi d'application AG. Le problème est lorsque vous faites pivoter l'appareil en mode paysage, vous obtenez des valeurs d'en-tête à gauche ou à droite de votre direction face à face, ce dont j'ai besoin à la fin. Comme je le sais, je peux obtenir les données "brutes" du magnétomètre (données en unités microtesla avec des valeurs de 128 à -128 pour chaque axe de l'appareil) ainsi que les données "brutes" du gyroscope (trois types: les anges Euler). , Matrice de rotation ou quaternion). Ce dont j'ai besoin est de savoir, quels calculs je dois appliquer à ceux pour obtenir la direction "face" au lieu de "titre"Calcul du nord basé sur le magnétomètre et le gyroscope

Répondre

4

Je l'ai fait il y a un certain temps et parce que je ne vois pas de réponses, j'ai décidé de mettre ma solution ici pour ceux qui va chercher réponse à la même question ...

_motionManager = [[CMMotionManager alloc]init]; 

    if (_motionManager.gyroAvailable) { 
     _motionManager.deviceMotionUpdateInterval = 1.0/20.0; 
     [_motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue] 
              withHandler:^(CMDeviceMotion *motion, NSError *error) 
     { 
      CMAcceleration gravity = motion.gravity; 
      CGPoint tiltVector = CGPointMake(-gravity.x, -gravity.y); 
      _tiltAngle = [self angleYAxisToVector:tiltVector]; 

      CLLocationDirection heaqding = [[SVSession sharedSession] heading].trueHeading; 
      double newHeading = fmod(heaqding + _tiltAngle, 360.0); 
      self.azimuth = degreesToRadian(newHeading); 

      [self updateLocations]; //this function updates my ui for the new heading 
     }]; 
    } else { 
     NSLog(@"No gyroscope on device."); 
     [_motionManager release],_motionManager = nil; 
    } 

Et voici quelques extraits supplémentaires qui peuvent aider à comprendre cet exemple:

-(double)angleYAxisToVector:(CGPoint)vector{ 
    double dX = vector.x; 
    double dY = vector.y; 

    if(dY == 0){ 
     if(dX > 0){ 
      return 0.0; 
     }else{ 
      if(dX < 0){ 
       return 180.0; 
      }else{ 
       return -1; 
      } 
     } 
    } 

    double beta = radiansToDegrees(atan(dX/dY)); 
    double angle; 
    if(dX > 0){ 
     if (dY < 0){ 
      angle = 180 + beta; 
     }else{ 
      angle = beta; 
     } 
    }else{ 
     if (dY < 0){ 
      angle = 180 + beta; 
     }else{ 
      angle = 360 + beta; 
     } 
    } 
    // NSLog(@"angle = %f, normalized = %f",beta,angle); 
    return angle; 
} 

#define degreesToRadian(x)    (M_PI * (x)/180.0) 
#define radiansToDegrees(x)    ((x) * 180.0/M_PI) 
#define degreesToRadians(x)    degreesToRadian(x) 
#define radiansToDegree(x)    radiansToDegrees(x) 

Bonne codage. ..

+0

qu'est ce que SVSession dans le code? je ne peux pas le trouver –

+0

Oh ... Vous ne le trouverez pas. C'est une partie de mes cours. J'ai l'habitude d'y stocker la dernière rubrique. – Ariel

+0

Ceci est incroyablement utile. Pour ceux qui trouvent cela, il se peut que ce code ne soit pas complètement clair, mais si vous cherchez à découvrir la manière dont l'appareil est orienté, quelle que soit l'orientation du paysage ou du portrait, c'est ce qu'il fera. – ratana

Questions connexes