2012-05-21 7 views
10

En un prototipo de iOS utilizo una combinación de CMDeviceMotion.deviceMotion.yaw y CLHeading.trueHeading para hacer que el encabezado estable de la brújula sea sensible y preciso. Esto funciona bien cuando el iPhone se mantiene plano, donde tengo una flecha gráfica que apunta a un título de brújula estable.CMDeviceMotion yaw valores inestables cuando iPhone es vertical

El problema aparece cuando el iPhone se mantiene vertical en el modo de retrato. UIDeviceOrientation cambia constantemente de UIDeviceOrientationFaceDown a UIDeviceOrientationFaceUp y viceversa. Esto hace que el valor de guiñada salte hacia adelante y hacia atrás +/- 180 grados en función de pequeños cambios del tono. ¿Es posible bloquear el dispositivo con una orientación que proporcione un valor estable de orientación, predecir el cambio sin fallas o calcular la giroscopía (o rodar en esta orientación) de otras maneras?

Este pobre tipo tiene el mismo problema, sin respuestas. Doble puntos posibles personas! :) https://stackoverflow.com/questions/10470938/euler-angle-yaw-not-working-when-iphone-orientation-changes

Respuesta

13

Estaba buscando una respuesta a este problema. Me rompió un poco el corazón ver que publicaste esto hace más de un año, pero pensé que quizás tú u otra persona podrían beneficiarse de la solución.

El problema es gimbal lock. Cuando el tono es de aproximadamente 90 grados, la guiñada y el balanceo coinciden y el giroscopio pierde un grado de libertad. Los cuaterniones son una forma de evitar el bloqueo cardánico, pero sinceramente no me apetecía. En cambio, noté que la guiñada y el balanceo coinciden y se pueden sumar para resolver el problema (suponiendo que solo te importe la guiñada).

SOLUCIÓN:

float yawDegrees = currentAttitude.yaw * (180.0/M_PI); 
    float pitchDegrees = currentAttitude.pitch * (180.0/M_PI); 
    float rollDegrees = currentAttitude.roll * (180.0/M_PI); 

    double rotationDegrees; 
    if(rollDegrees < 0 && yawDegrees < 0) // This is the condition where simply 
              // summing yawDegrees with rollDegrees 
              // wouldn't work. 
              // Suppose yaw = -177 and pitch = -165. 
              // rotationDegrees would then be -342, 
              // making your rotation angle jump all 
              // the way around the circle. 
    { 
     rotationDegrees = 360 - (-1 * (yawDegrees + rollDegrees)); 
    } 
    else 
    { 
     rotationDegrees = yawDegrees + rollDegrees; 
    } 

    // Use rotationDegrees with range 0 - 360 to do whatever you want. 

espero que esto ayude a alguien más!

+0

¡Simplemente lo hizo, GRACIAS MUCHO !!!! –

+0

@ blkph19 ¿puede mirar mi respuesta? No pude ajustar todo el código en la sección de comentarios. – Deveram

1

Si alguien está interesado en la aplicación en iOS Swift se da el código de abajo:

let queue = NSOperationQueue() 
    motionManager.startDeviceMotionUpdatesToQueue(queue) { 
     [weak self] (data: CMDeviceMotion!, error: NSError!) in 
    var yawDegrees: Double = self!.motionManager.deviceMotion.attitude.yaw * (180.0/M_PI) 
     var pitchDegrees: Double = self!.motionManager.deviceMotion.attitude.pitch * (180.0/M_PI) 
     var rollDegrees: Double = self!.motionManager.deviceMotion.attitude.roll * (180.0/M_PI) 


     if(rollDegrees < 0 && yawDegrees < 0){ 
      self!.rotationDegrees = 360 - (-1 * (yawDegrees + rollDegrees)) 
     } 
     else { 
      self!.rotationDegrees = yawDegrees + rollDegrees 
     } 
    } 

Sin embargo estoy teniendo algunos problemas y espero @ blkhp19 me puede ayudar con esto porque en algunos puntos los ángulos van en valores negativos que luego estropean todo el cálculo y no puedo entender cuál es el problema.

Cuestiones relacionadas