2010-10-01 26 views
2

Je dois écrire une application boussole dans Android. La seule chose que l'utilisateur voit sur l'écran est un cube avec un mur rouge qui doit pointer vers le nord. Ce ne est pas important. Ce qui est important, c'est que je doive faire pivoter ce cube en fonction de la rotation de l'appareil lui-même afin que le mur rouge continue de pointer vers le nord, peu importe la façon dont le téléphone est tenu. Mon code est simple et direct:Convertir les valeurs de Sensor.TYPE_ORIENTATION en angles d'Euler?

@Override 
public void onSensorChanged(SensorEvent event) { 
    synchronized (this) { 
     switch (event.sensor.getType()){ 
     case Sensor.TYPE_ACCELEROMETER: 
      direction = event.values[2]; 
      break; 
     case Sensor.TYPE_ORIENTATION: 
      if (direction < 0) { 
       angleX = event.values[1]; 
       angleY = -event.values[2]; 
       angleZ = event.values[0]; 
      } else { 
       angleX = -event.values[1]; 
       angleY = -event.values[2]; 
       angleZ = event.values[0]; 
      } 
      break; 
     } 
    } 
} 

J'ai ajouté cette variable de direction supplémentaire qui stocke simplement si l'écran du téléphone est orienté vers le bas ou vers le haut. Je ne sais pas si j'en ai besoin mais il semble y avoir des bugs. J'utilise le SensorSimulator pour android mais quand mon curseur de pitch va dans l'intervalle [-90, 90] les autres variables se mélangent. C'est comme s'ils obtenaient un 180 offset. Mais je ne peux pas détecter quand je suis dans cet intervalle parce que la gamme de la hauteur est de -90 à 90, donc je peux déplacer ce curseur de gauche à écrire et je serai toujours dans cet intervalle.

Tout était juste pour vous montrer jusqu'où mon code a progressé. Je ne dis pas comment ce problème devrait être résolu parce que je vais probablement me retrouver dans une impasse. Vous voyez, j'ai essayé d'écrire cette application pendant 3 jours maintenant, et vous pouvez imaginer à quel point mon patron est énervé. J'ai lu toutes sortes de tutoriels et essayé toutes les formules que je pouvais trouver ou penser. Alors s'il vous plaît aidez-moi. Tout ce que j'ai à faire est de savoir comment faire pivoter mon cube, dont les angles de rotation sont EULER ANGLES en degrés.

Répondre

3

Voici un code que j'ai écrit pour faire quelque chose de très similaire, se souciant seulement de la rotation de l'appareil dans le sens du rouleau. J'espère que cela aide! Il utilise simplement les valeurs de l'accéléromètre pour déterminer la hauteur, pas besoin d'obtenir l'orientation de la vue.

public void onSensorChanged(SensorEvent event) { 
    float x = -1 * event.values[0]/SensorManager.GRAVITY_EARTH; 
    float y = -1 * event.values[1]/SensorManager.GRAVITY_EARTH; 
    float z = -1 * event.values[2]/SensorManager.GRAVITY_EARTH; 

    float signedRawRoll = (float) (Math.atan2(x, y) * 180/Math.PI); 
    float unsignedRawRoll = Math.abs(signedRawRoll); 
    float rollSign = signedRawRoll/unsignedRawRoll; 
    float rawPitch = Math.abs(z * 180); 

    // Use a basic low-pass filter to only keep the gravity in the accelerometer values for the X and Y axes 
    // adjust the filter weight based on pitch, as roll is harder to define as pitch approaches 180. 
    float filterWeight = rawPitch > 165 ? 0.85f : 0.7f; 
    float newUnsignedRoll = filterWeight * Math.abs(this.roll) + (1 - filterWeight) * unsignedRawRoll; 
    this.roll = rollSign * newUnsignedRoll; 
    if (Float.isInfinite(this.roll) || Float.isNaN(this.roll)) { 
     this.roll = 0; 
    } 
    this.pitch = filterWeight * this.pitch + (1 - filterWeight) * rawPitch; 
    for (IAngleListener listener : listeners) { 
     listener.deviceRollAndPitch(this.roll, this.pitch); 
    } 
}