Différentes valeurs entre les capteurs TYPE_ACCELEROMETER / TYPE_MAGNETIC_FIELD et TYPE_ORIENTATION
Il y a 2 façons d'obtenir les 3 valeurs de rotation (azimut, de tangage, de roulis).
Est l'enregistrement d'un listener de type TYPE_ORIENTATION. C'est le moyen le plus facile et j'ai une bonne gamme de valeurs de chaque rotation, de la documentation dit:
azimut: [0, 359]
pitch: [-180, 180]
roll: [-90, 90]
L'autre, les plus précises et les plus complexes à comprendre la première fois que tu le vois. Android le recommande, si je veux l'utiliser, mais j'obtiens des valeurs différentes.
azimut: [-180, 180]. -180/180 est S, 0 i N, 90 E et -90 W.
pitch: [-90, 90]. À 90 à 90, est -90 -90, 0 est 0, mais -180/180 (couché avec l'écran vers le bas) est de 0.
roll: [-180, 180].
Je devrais obtenir les mêmes valeurs, mais avec des décimales, droit?
J'ai le code suivant:
aValues = new float[3];
mValues = new float[3];
sensorListener = new SensorEventListener (){
public void onSensorChanged (SensorEvent event){
switch (event.sensor.getType ()){
case Sensor.TYPE_ACCELEROMETER:
aValues = event.values.clone ();
break;
case Sensor.TYPE_MAGNETIC_FIELD:
mValues = event.values.clone ();
break;
}
float[] R = new float[16];
float[] orientationValues = new float[3];
SensorManager.getRotationMatrix (R, null, aValues, mValues);
SensorManager.getOrientation (R, orientationValues);
orientationValues[0] = (float)Math.toDegrees (orientationValues[0]);
orientationValues[1] = (float)Math.toDegrees (orientationValues[1]);
orientationValues[2] = (float)Math.toDegrees (orientationValues[2]);
azimuthText.setText ("azimuth: " + orientationValues[0]);
pitchText.setText ("pitch: " + orientationValues[1]);
rollText.setText ("roll: " + orientationValues[2]);
}
public void onAccuracyChanged (Sensor sensor, int accuracy){}
};
S'il vous plaît aider. C'est très frustrant.
Dois-je traiter avec ces valeurs, ou je fais quelque chose de mal?
Grâce.
source d'informationauteur Gabriel Llamas
Vous devez vous connecter pour publier un commentaire.
Je sais que je suis en train de jouer thread nécromancien ici, mais j'ai travaillé sur ce genre de choses beaucoup ces derniers temps, alors j'ai pensé que je jetterais dans mes 2 cents.
L'appareil ne contient pas de boussole ou inclinomètres, de sorte qu'il n'est pas à la mesure de l'azimut, de la hauteur, ou rouler directement. (Nous appelons ces angles d'Euler, BTW). Au lieu de cela, il utilise les accéléromètres et magnétomètres, lesquelles produisent des 3-l'espace XYZ vecteurs. Ceux-ci sont utilisés pour calculer l'azimut, etc. des valeurs.
Vecteurs sont dans le dispositif de coordonnées de l'espace:
Les coordonnées du monde Y ont fait face au nord, X face à l'est, et Z vers le haut:
Ainsi, un dispositif de "neutre" de l'orientation est couché à plat sur le dos, sur une table, avec le haut de l'appareil, face au nord.
L'accéléromètre produit d'un vecteur dans la direction verticale. Le magnétomètre produit d'un vecteur dans le "nord" de la direction. (Notez que dans l'hémisphère nord, ce qui tend à point à la baisse en raison immersion magnétique.)
L'accéléromètre vecteur et un magnétomètre vectoriel peut être combiné mathématiquement par SensorManager.getRotationMatrix() qui renvoie une matrice de 3x3 qui va de la carte des vecteurs de coordonnées de périphérique pour les coordonnées du monde ou vice-versa. Pour un appareil dans la position neutre, cette fonction retourne la matrice identité.
Cette matrice ne varie pas avec l'orientation de l'écran. Cela signifie que votre application doit être conscient de l'orientation et de compenser en conséquence.
SensorManager.getOrientation() prend la matrice de transformation et calcule l'azimut, le tangage et le roulis des valeurs. Elles sont prises par rapport à un appareil dans la position neutre.
Je n'ai aucune idée de ce qu'est la différence entre l'appel de cette fonction, ainsi que l'utilisation TYPE_ORIENTATION capteur, sauf que la fonction vous permet de manipuler la matrice.
Si l'appareil est incliné vers le haut à 90° ou à proximité, puis l'utilisation des angles d'Euler tombe à l'eau. C'est un cas dégénéré mathématiquement. Dans ce domaine, la façon dont l'appareil est-il censé savoir si vous êtes à la modification de l'azimut ou rouleau?
La fonction SensorManager.remapCoordinateSystem() peut être utilisée pour manipuler la matrice de transformation pour compenser ce que vous savez à propos de l'orientation de l'appareil. Cependant, mon expérience montre que cela ne couvre pas tous les cas, même pas certains de la commune. Par exemple, si vous voulez reconfigurer pour un appareil tenu verticalement (par exemple, pour prendre une photo de), vous devez multiplier la matrice de transformation par cette matrice:
avant d'appeler getOrientation(), et ce n'est pas l'une de l'orientation reconfigurations ne que remapCoordinateSystem() prend en charge [à quelqu'un s'il vous plaît corrigez-moi si j'ai oublié quelque chose ici].
OK, donc cela a été un long-winded façon de dire que si vous utilisez l'orientation, soit à partir de la TYPE_ORIENTATION capteur ou de getOrientation(), vous êtes probablement de faire le mal. Le seul moment où vous fait voulez les angles d'Euler est à une orientation de l'affichage des informations dans un format convivial, annoter une photo, de lecteur de vol de l'instrument d'affichage, ou quelque chose de similaire.
Si vous voulez effectuer des calculs liés à l'orientation de l'écran, vous êtes presque certainement mieux à l'aide de la matrice de transformation et de travail avec XYZ vecteurs.
De travail en tant que consultant, à chaque fois que quelqu'un vient à moi avec un problème impliquant des angles d'Euler, de sauvegarder et de leur demander ce qu'ils vraiment essayons de faire, et ensuite trouver un moyen de le faire avec des vecteurs au lieu.
À la recherche de retour à votre question initiale, getOrientation() doit retourner trois valeurs dans [-180 180] [-90 90] et [-180 180] (après la conversion de radians). Dans la pratique, nous pensons à l'azimut comme des nombres dans [0 360), si vous devez simplement ajouter 360 pour les nombres négatifs que vous recevez. Votre code est correct comme l'a écrit. Il serait utile si je savais exactement ce que les résultats que vous attendez et ce que vous aviez à la place.
Édité pour ajouter: Un couple de plus de pensées. Les versions modernes de Android utiliser quelque chose appelé "capteur de fusion", ce qui signifie essentiellement que toutes les entrées disponibles -- acceleromter, magnétomètre, gyroscope-sont combinées dans une mathématique de la boîte noire (généralement un filtre de Kalman, mais dépend d'un fournisseur). Tous les différents capteurs -- l'accélération, le champ magnétique, les gyroscopes, de la gravité, accélération linéaire, et l'orientation-sont prises sous la forme de résultats à partir de cette boîte noire.
Chaque fois que possible, vous devriez utiliser TYPE_GRAVITY plutôt que TYPE_ACCELEROMETER comme l'entrée de getRotationMatrix().
Je suis peut-être le tir dans le noir ici, mais si je comprends votre question correctement, vous vous demandez pourquoi vous obtenez
[-179..179]
au lieu de[0..360]
?Noter que
-180
est le même que+180
et le même que180 + N*360
oùN
est un nombre entier (integer).En d'autres termes, si vous voulez obtenir les mêmes nombres que avec capteur d'orientation, vous pouvez le faire:
Cela vous donnera les valeurs de la
[0..360]
gamme que vous vouliez.Il vous manque une critique de calcul dans vos calculs.
Le remapCoordinateSystem appel afer vous faire un getRotationMatrix.
L'ajouter à votre code et tout ira bien.
Vous pouvez en lire plus à ce sujet ici.