Skip to content

Calcolare il rilevamento della bussola / la direzione verso la posizione in Android

Il nostro gruppo specializzato dopo alcuni giorni di lavoro e raccolta dati, abbiamo ottenuto i dati necessari, speriamo possano essere utili nel vostro progetto.

Soluzione:

Ok, ho risolto questo problema. Per chiunque altro stia cercando di farlo, è necessario:

a) direzione: la vostra direzione dalla bussola hardware. Questa è in gradi a est di magnetico nord

b) rilevamento: il rilevamento dalla propria posizione alla posizione di destinazione. È espresso in gradi a est di vero nord.

myLocation.bearingTo(destLocation);

c) declinazione: la differenza tra il nord vero e il nord magnetico.

La direzione restituita dal magnetometro + accelerometro è espressa in gradi a est del nord vero (magnetico) (da -180 a +180), quindi è necessario ottenere la differenza tra il nord e il nord magnetico per la propria posizione. Questa differenza varia a seconda della posizione sulla terra. Si può ottenere utilizzando 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()
      );
      ...
   }
}

Con questi dati si calcola l'angolo della freccia da disegnare sulla mappa per indicare dove ci si trova rispetto all'oggetto di destinazione piuttosto che al nord vero.

Per prima cosa si regola la rotta con la declinazione:

heading += geoField.getDeclination();

In secondo luogo, è necessario sfalsare la direzione in cui il telefono è rivolto (direzione) rispetto alla destinazione anziché al nord vero. Questa è la parte che mi ha bloccato. Il valore della direzione restituito dalla bussola fornisce un valore che descrive dove si trova il nord magnetico (in gradi a est del nord vero) rispetto al punto in cui è puntato il telefono. Quindi, ad esempio, se il valore è -10, si sa che il nord magnetico è 10 gradi a sinistra. Il rilevamento fornisce l'angolo di destinazione in gradi a est del nord vero. Quindi, dopo aver compensato la declinazione, è possibile utilizzare la formula seguente per ottenere il risultato desiderato:

heading = myBearing - (myBearing + heading); 

Si dovrà poi convertire i gradi a est del nord vero (da -180 a +180) in gradi normali (da 0 a 360):

Math.round(-heading / 360 + 180)

@Damian - L'idea è molto buona e sono d'accordo con la risposta, ma quando ho usato il tuo codice ho avuto valori sbagliati, quindi ho scritto questo per conto mio (qualcuno ha detto lo stesso nei tuoi commenti). Il conteggio della rotta con la declinazione è buono, credo, ma in seguito ho usato qualcosa di simile:

heading = (bearing - heading) * -1;

invece del codice di Damian:

heading = myBearing - (myBearing + heading); 

e cambiando -180 in 180 per 0-360:

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

e poi quando si vuole ruotare la freccia si può usare un codice come questo:

      private void rotateArrow(float angle){

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

dove arrowView è ImageView con l'immagine della freccia e i parametri 100f in postRotate sono pivX e pivY).

Spero di poter aiutare qualcuno.

In questo caso una freccia sulla bussola mostra la direzione dalla vostra posizione a Kaaba(posizione di destinazione)

Si può usare semplicemente bearingTo in questo modo.bearing to vi darà l'angolo diretto dalla vostra posizione alla posizione di destinazione

  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 fornirà un intervallo da -180 a 180, che confonderà un po' le cose. È necessario convertire questo valore in un intervallo da 0 a 360 per ottenere la rotazione corretta.

Questa è una tabella di ciò che vogliamo veramente, confrontata con ciò che bearingTo ci dà

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

quindi dobbiamo aggiungere questo codice dopo 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;
}

è necessario implementare SensorEventListener e le sue funzioni (onSensorChanged,onAcurracyChabge) e scrivere tutto il codice all'interno di onSensorChanged

Il codice completo è qui per la Direzione della bussola 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;
}

Il codice xml è qui











Non dimenticare di diffondere questa cronaca se ha risolto il tuo problema.



Utilizzate il nostro motore di ricerca

Ricerca
Generic filters

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.