Saltar al contenido

Calcular el rumbo / rumbo de la brújula a la ubicación en Android

Hola, descubrimos la respuesta a lo que necesitas, desplázate y la verás aquí.

Solución:

Ok, me di cuenta de esto. Para cualquier otra persona que intente hacer esto, necesita:

a) rumbo: tu rumbo de la brújula de hardware. Esto es en grados al este de magnético norte

b) rumbo: el rumbo desde su ubicación hasta la ubicación de destino. Esto es en grados al este de cierto norte.

myLocation.bearingTo(destLocation);

c) declinación: la diferencia entre el norte verdadero y el norte magnético

El rumbo que devuelve el magnetómetro + acelermómetro está en grados al este del norte (magnético) verdadero (-180 a +180), por lo que debe obtener la diferencia entre el norte y el norte magnético para su ubicación. Esta diferencia es variable dependiendo de dónde se encuentre en la tierra. Puede obtenerlo usando la clase 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()
      );
      ...
   

Armado con estos, calcula el ángulo de la flecha para dibujar en su mapa para mostrar hacia dónde se enfrenta en relación con su objeto de destino en lugar del norte verdadero.

Primero ajuste su rumbo con la declinación:

heading += geoField.getDeclination();

En segundo lugar, debe compensar la dirección en la que el teléfono mira (rumbo) desde el destino objetivo en lugar del norte verdadero. Esta es la parte en la que me quedé atascado. El valor de rumbo devuelto por la brújula le da un valor que describe dónde está el norte magnético (en grados al este del norte verdadero) en relación con el lugar hacia donde apunta el teléfono. Entonces, por ejemplo, si el valor es -10, sabrá que el norte magnético está 10 grados a su izquierda. El rumbo le da el ángulo de su destino en grados al este del norte verdadero. Entonces, después de haber compensado la declinación, puede usar la fórmula a continuación para obtener el resultado deseado:

heading = myBearing - (myBearing + heading); 

Luego, querrá convertir de grados al este del norte verdadero (-180 a +180) a grados normales (0 a 360):

Math.round(-heading / 360 + 180)

@Damian: la idea es muy buena y estoy de acuerdo con la respuesta, pero cuando usé su código tenía valores incorrectos, así que escribí esto por mi cuenta (alguien dijo lo mismo en sus comentarios). Contar el rumbo con la declinación es bueno, creo, pero luego usé algo así:

heading = (bearing - heading) * -1;

en lugar del código de Damian:

heading = myBearing - (myBearing + heading); 

y cambiando -180 a 180 de 0 a 360:

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

y luego, cuando desee rotar la flecha, puede usar un código como este:

      private void rotateArrow(float angle)

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

dónde arrowView es ImageView con imagen de flecha y parámetros 100f en postRotate es pivX y pivY).

Espero ayudar a alguien.

En este, una flecha en la brújula muestra la dirección desde su ubicación hasta Kaaba(ubicación de destino)

puede usar simplemente BearingTo de esta manera. Bearing le dará el ángulo directo desde su ubicación hasta la ubicación de destino

  Location userLoc=new Location("service Provider");
    //get longitudeM Latitude and altitude of current location with gps class and  set in userLoc
    userLoc.setLongitude(longitude); 
    userLoc.setLatitude(latitude);
    userLoc.setAltitude(altitude);

   Location destinationLoc = new Location("service Provider");
  destinationLoc.setLatitude(21.422487); //kaaba latitude setting
  destinationLoc.setLongitude(39.826206); //kaaba longitude setting
  float bearTo=userLoc.bearingTo(destinationLoc);

BearingTo le dará un rango de -180 a 180, lo que confundirá un poco las cosas. Necesitaremos convertir este valor en un rango de 0 a 360 para obtener la rotación correcta.

Esta es una tabla de lo que realmente queremos, comparado con lo que Bear To nos da

+-----------+--------------+
| bearingTo | Real bearing |
+-----------+--------------+
| 0         | 0            |
+-----------+--------------+
| 90        | 90           |
+-----------+--------------+
| 180       | 180          |
+-----------+--------------+
| -90       | 270          |
+-----------+--------------+
| -135      | 225          |
+-----------+--------------+
| -180      | 180          |
+-----------+--------------+

así que tenemos que agregar este código después de bearTo

// If the bearTo is smaller than 0, add 360 to get the rotation clockwise.

  if (bearTo < 0) 
    bearTo = bearTo + 360;
    //bearTo = -100 + 360  = 260;

debe implementar SensorEventListener y sus funciones (onSensorChanged, onAcurracyChabge) y escribir todo el código dentro de onSensorChanged

El código completo está aquí para la dirección de la brújula Qibla

 public class QiblaDirectionCompass extends Service implements SensorEventListener{
 public static ImageView image,arrow;

// record the compass picture angle turned
private float currentDegree = 0f;
private float currentDegreeNeedle = 0f;
Context context;
Location userLoc=new Location("service Provider");
// device sensor manager
private static SensorManager mSensorManager ;
private Sensor sensor;
public static TextView tvHeading;
   public QiblaDirectionCompass(Context context, ImageView compass, ImageView needle,TextView heading, double longi,double lati,double alti ) {

    image = compass;
    arrow = needle;


    // TextView that will tell the user what degree is he heading
    tvHeading = heading;
    userLoc.setLongitude(longi);
    userLoc.setLatitude(lati);
    userLoc.setAltitude(alti);

  mSensorManager =  (SensorManager) context.getSystemService(SENSOR_SERVICE);
    sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
    if(sensor!=null) 
        // for the system's orientation sensor registered listeners
        mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);//SensorManager.SENSOR_DELAY_Fastest
    else
        Toast.makeText(context,"Not Supported", Toast.LENGTH_SHORT).show();
    
    // initialize your android device sensor capabilities
this.context =context;
@Override
public void onCreate() 
    // TODO Auto-generated method stub
    Toast.makeText(context, "Started", Toast.LENGTH_SHORT).show();
    mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME); //SensorManager.SENSOR_DELAY_Fastest
    super.onCreate();


@Override
public void onDestroy() 
    mSensorManager.unregisterListener(this);
Toast.makeText(context, "Destroy", Toast.LENGTH_SHORT).show();

    super.onDestroy();


@Override
public void onSensorChanged(SensorEvent sensorEvent) 


Location destinationLoc = new Location("service Provider");

destinationLoc.setLatitude(21.422487); //kaaba latitude setting
destinationLoc.setLongitude(39.826206); //kaaba longitude setting
float bearTo=userLoc.bearingTo(destinationLoc);

  //bearTo = The angle from true north to the destination location from the point we're your currently standing.(asal image k N se destination taak angle )

  //head = The angle that you've rotated your phone from true north. (jaise image lagi hai wo true north per hai ab phone jitne rotate yani jitna image ka n change hai us ka angle hai ye)



GeomagneticField geoField = new GeomagneticField( Double.valueOf( userLoc.getLatitude() ).floatValue(), Double
        .valueOf( userLoc.getLongitude() ).floatValue(),
        Double.valueOf( userLoc.getAltitude() ).floatValue(),
        System.currentTimeMillis() );
head -= geoField.getDeclination(); // converts magnetic north into true north

if (bearTo < 0) 
    bearTo = bearTo + 360;
    //bearTo = -100 + 360  = 260;


//This is where we choose to point it
float direction = bearTo - head;

// If the direction is smaller than 0, add 360 to get the rotation clockwise.
if (direction < 0) 
    direction = direction + 360;

 tvHeading.setText("Heading: " + Float.toString(degree) + " degrees" );

RotateAnimation raQibla = new RotateAnimation(currentDegreeNeedle, direction, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
raQibla.setDuration(210);
raQibla.setFillAfter(true);

arrow.startAnimation(raQibla);

currentDegreeNeedle = direction;

// create a rotation animation (reverse turn degree degrees)
RotateAnimation ra = new RotateAnimation(currentDegree, -degree, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

// how long the animation will take place
ra.setDuration(210);


// set the animation after the end of the reservation status
ra.setFillAfter(true);

// Start the animation
image.startAnimation(ra);

currentDegree = -degree;

@Override
public void onAccuracyChanged(Sensor sensor, int i) 


@Nullable
@Override
public IBinder onBind(Intent intent) 
    return null;

el código xml está aquí











Te mostramos las reseñas y valoraciones de los lectores

Si te animas, puedes dejar un post acerca de qué le añadirías a este artículo.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *