73 votes

Calculer le relèvement/le cap de la boussole vers un lieu dans Android

Je veux afficher une flèche à mon emplacement sur une vue de carte google qui affiche ma direction par rapport à un emplacement de destination (au lieu du nord).

a) J'ai calculé le nord en utilisant les valeurs des capteurs du magnétomètre et de l'accéléromètre. Je sais que c'est correct car cela correspond à la boussole utilisée sur la vue cartographique de Google.

b) J'ai calculé le relèvement initial entre ma position et la position de destination en utilisant myLocation.bearingTo(destLocation) ;

Il me manque la dernière étape ; à partir de ces deux valeurs (a & b), quelle formule dois-je utiliser pour obtenir la direction dans laquelle le téléphone pointe par rapport à l'emplacement de destination ?

J'apprécie toute aide pour un esprit dérangé !

0 votes

Vous pouvez consulter cet article de blog sur les capteurs et l'orientation de l'écran : Android-developers.blogspot.com/2010/09/

0 votes

Merci, j'ai déjà lu cet article. Malheureusement, il ne répond pas au problème posé dans la question.

2 votes

J'ai trouvé une solution ici qui m'a bien réussi stackoverflow.com/questions/7978618/

75voto

Damian Points 4588

Ok, j'ai trouvé une solution. Pour tous ceux qui essaient de faire ça, vous avez besoin.. :

a) cap : votre cap à partir du compas matériel. Il est exprimé en degrés à l'est de magnétique nord

b) le relèvement : le relèvement de votre emplacement à l'emplacement de destination. Il est exprimé en degrés à l'est de vrai nord.

myLocation.bearingTo(destLocation);

c) la déclinaison : la différence entre le nord géographique et le nord magnétique.

Le cap renvoyé par le magnétomètre + l'accéléromètre est exprimé en degrés à l'est du nord (magnétique) réel (-180 à +180). Vous devez donc obtenir la différence entre le nord et le nord magnétique pour votre emplacement. Cette différence est variable selon l'endroit où vous vous trouvez sur la terre. Vous pouvez l'obtenir en utilisant la classe GeomagneticField.

GeomagneticField geoField;

private final LocationListener locationListener = new LocationListener() {
   public void onLocationChanged(Location location) {
      geoField = new GeomagneticField(
         Double.valueOf(location.getLatitude()).floatValue(),
         Double.valueOf(location.getLongitude()).floatValue(),
         Double.valueOf(location.getAltitude()).floatValue(),
         System.currentTimeMillis()
      );
      ...
   }
}

Avec ces données, vous calculez l'angle de la flèche à dessiner sur votre carte pour indiquer votre orientation par rapport à votre objet de destination plutôt que par rapport au nord géographique.

Ajustez d'abord votre cap en fonction de la déclinaison :

heading += geoField.getDeclination();

Deuxièmement, vous devez décaler la direction dans laquelle le téléphone est orienté (cap) par rapport à la destination cible plutôt que le nord réel. C'est la partie qui m'a bloqué. La valeur du cap renvoyée par la boussole vous donne une valeur qui décrit où se trouve le nord magnétique (en degrés à l'est du nord géographique) par rapport à l'endroit où pointe le téléphone. Par exemple, si la valeur est -10, vous savez que le nord magnétique se trouve à 10 degrés sur votre gauche. Le relèvement vous donne l'angle de votre destination en degrés à l'est du nord vrai. Après avoir compensé la déclinaison, vous pouvez utiliser la formule ci-dessous pour obtenir le résultat souhaité :

heading = myBearing - (myBearing + heading); 

Vous devrez ensuite convertir les degrés à l'est du nord géographique (-180 à +180) en degrés normaux (0 à 360) :

Math.round(-heading / 360 + 180)

0 votes

Y a-t-il une faute de frappe dans votre ligne ? titre +- geoField.getDeclination() ; ou ce que vous voulez dire avec +- ? ?

2 votes

Lorsque vous dites "heading = myBearing - (myBearing + heading) ;", y a-t-il une erreur ? C'est comme si vous disiez "heading = heading".

7 votes

@Nikolas En fait, c'est comme si l'on disait que l'en-tête = -en-tête.

20voto

CookieMonssster Points 277

@Damian - L'idée est très bonne et je suis d'accord avec la réponse, mais quand j'ai utilisé votre code, j'avais des valeurs erronées, donc j'ai écrit ceci par moi-même (quelqu'un a dit la même chose dans vos commentaires). Compter le cap avec la déclinaison est bon, je pense, mais plus tard j'ai utilisé quelque chose comme ça :

heading = (bearing - heading) * -1;

au lieu du code de Damian :

heading = myBearing - (myBearing + heading); 

et en changeant -180 à 180 pour 0 à 360 :

      private float normalizeDegree(float value){
          if(value >= 0.0f && value <= 180.0f){
              return value;
          }else{
              return 180 + (180 + value);
          }

et ensuite quand vous voulez faire pivoter votre flèche, vous pouvez utiliser un code comme celui-ci :

      private void rotateArrow(float angle){

            Matrix matrix = new Matrix();
            arrowView.setScaleType(ScaleType.MATRIX);
            matrix.postRotate(angle, 100f, 100f);
            arrowView.setImageMatrix(matrix);
      }

donde arrowView est ImageView avec l'image de la flèche et les paramètres 100f dans postRotate est pivX et pivY).

J'espère que je vais aider quelqu'un.

0 votes

Je ne comprends pas pourquoi vous utilisez * -1 dans le calcul de la rubrique

6 votes

NormalizeDegree est inutilement complexe. Vous pouvez faire la même chose avec seulement return (value + 360) % 360

0 votes

" return 180 + (180 + value); "

2voto

Squonk Points 28943

Je ne suis pas un expert en lecture de cartes, en navigation, etc., mais les "directions" sont sûrement absolues et non relatives ou, en réalité, elles sont relatives au N ou au S qui sont eux-mêmes fixes/absolus.

Exemple : Supposons qu'une ligne imaginaire tracée entre vous et votre destination corresponde au SE "absolu" (un relèvement de 135 degrés par rapport au N magnétique). Supposons maintenant que votre téléphone pointe vers le NO - si vous tracez une ligne imaginaire entre un objet imaginaire à l'horizon et votre destination, elle passera par votre position et aura un angle de 180 degrés. Or, 180 degrés, dans le sens de la boussole, fait référence au S, mais la destination n'est pas "due S" à l'objet imaginaire pointé par votre téléphone et, de plus, si vous vous rendiez à ce point imaginaire, votre destination serait toujours au SE de l'endroit où vous vous êtes déplacé.

En réalité, la ligne à 180 degrés vous indique que la destination est "derrière vous" par rapport à la direction dans laquelle le téléphone (et probablement vous) est orienté.

Cela dit, si vous souhaitez calculer l'angle d'une ligne allant d'un point imaginaire à votre destination (en passant par votre emplacement) afin de dessiner un pointeur vers votre destination, il vous suffit de soustraire l'orientation (absolue) de la destination de l'orientation absolue de l'objet imaginaire et d'ignorer la négation (si elle est présente). Par exemple, NW - SE est 315 - 135 = 180, ce qui permet de dessiner le pointeur vers le bas de l'écran en indiquant "derrière vous".

EDITAR: Je me suis un peu trompé dans les maths... soustraire le plus petit des paliers du plus grand puis soustraire le résultat de 360 pour obtenir l'angle dans lequel dessiner le pointeur sur l'écran.

0 votes

Merci pour votre aide. J'ai réussi à résoudre le problème et j'ai produit la réponse ci-dessous pour toute personne rencontrant le même problème.

0 votes

Seulement 2 points contre les 37 que la réponse acceptée (incorrecte) a obtenu ? Oh bien, merci d'avoir posté Squonk, cela m'a beaucoup aidé.

1voto

Pedro Points 11

Si vous êtes sur le même fuseau horaire

Convertir le GPS en UTM

http://www.ibm.com/developerworks/java/library/j-coordconvert/ http://stackoverflow.com/questions/176137/java-convert-lat-lon-to-utm

Les coordonnées UTM permettent d'obtenir un simple X Y 2D

Calculez l'angle entre les deux positions UTM

http://forums.groundspeak.com/GC/index.php?showtopic=146917

Cela donne la direction comme si vous regardiez le nord.

Donc, quelle que soit la rotation liée au nord, il suffit de soustraire cet angle

Si les deux points ont un angle UTM de 45º et que vous êtes à 5º à l'est du nord, votre flèche pointera vers 40º du nord.

1voto

Mobistry Points 2902

Voici comment j'ai procédé :

Canvas g = new Canvas( compass );
Paint p = new Paint( Paint.ANTI_ALIAS_FLAG );

float rotation = display.getOrientation() * 90;

g.translate( -box.left, -box.top );
g.rotate( -bearing - rotation, box.exactCenterX(), box.exactCenterY() );
drawCompass( g, p );
drawNeedle( g, p );

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X