Domanda

Voglio visualizzare una freccia mia posizione su una visione google map che visualizza la mia direzione rispetto ad un percorso di destinazione (invece del nord).

a) Ho calcolato nord utilizzando i valori dei sensori del magnetometro e accelerometro. So che questo è corretto perché si allinei con la bussola utilizzata sulla vista di Google Map.

b) ho calcolato il cuscinetto iniziale da mia posizione alla posizione di destinazione utilizzando myLocation.bearingTo (destLocation);

mi manca l'ultimo passo; da questi due valori (A e B) quale formula si usa per ottenere la direzione in cui il telefono è rivolto in relazione alla posizione di destinazione?

Apprezzo tutto l'aiuto per una mente addled!

È stato utile?

Soluzione

Ok ho capito questo. Per chiunque altro cercando di fare questo è necessario:

a) titolo: la direzione dalla bussola hardware. Questo è in gradi est di magnetico del Nord

b) del cuscinetto: il cuscinetto dalla posizione attuale alla posizione di destinazione. Questo è in gradi est di true del Nord.

myLocation.bearingTo(destLocation);

c) la declinazione: la differenza tra nord reale e nord magnetico

Il titolo che viene restituito dal magnetometro + accelermometer è in gradi est del Nord geografico (magnetico) (-180 a +180) quindi è necessario per ottenere la differenza tra nord e nord magnetico per la vostra posizione. Questa differenza è variabile a seconda di dove siete sulla terra. È possibile ottenere utilizzando 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()
      );
      ...
   }
}

Grazie a questi si calcola l'angolazione della freccia per disegnare sulla mappa per mostrare dove si trovano ad affrontare in relazione al proprio oggetto di destinazione, piuttosto che il nord geografico.

Per prima cosa regolare la direzione con la declinazione:

heading += geoField.getDeclination();

In secondo luogo, è necessario per compensare la direzione in cui il telefono si trova ad affrontare (intestazione) dal target di destinazione, piuttosto che il nord geografico. Questa è la parte che mi sono bloccato su. Il valore di prua ritornato dalla bussola ti dà un valore che descrive dove il nord magnetico è (in gradi est del Nord geografico) in relazione al punto in cui il telefono sta indicando. Così ad esempio, se il valore è -10 a sapere che il nord magnetico è di 10 gradi a sinistra. Il cuscinetto si dà l'angolo di destinazione in gradi est del Nord geografico. Così, dopo aver compensati per la declinazione è possibile utilizzare la formula seguente per ottenere il risultato desiderato:

heading = myBearing - (myBearing + heading); 

Potrai poi desidera convertire da gradi est del Nord geografico (-180 a +180) in gradi normali (da 0 a 360):

Math.round(-heading / 360 + 180)

Altri suggerimenti

@Damian - L'idea è molto buona e sono d'accordo con la risposta, ma quando ho usato il codice ho avuto valori sbagliati, così ho scritto questo sul mio (qualcuno ha detto lo stesso nei vostri commenti). intestazione conteggio con la declinazione è buono, credo, ma in seguito ho usato qualcosa di simile:

heading = (bearing - heading) * -1;

al posto del codice di Damian:

heading = myBearing - (myBearing + heading); 

e cambiando -180 a 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 desidera ruotare la freccia è possibile utilizzare il 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 foto freccia e 100F parametri postRotate è PivX e pivY).

spero di aiutare qualcuno.

In questo una freccia sul spettacoli bussola la direzione dalla posizione attuale alla Kaaba ( posizione di destinazione )

è possibile semplice utilizzo bearingTo in questo way.bearing a vi darà l'angolo direttamente dalla posizione attuale 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 vi darà un range da -180 a 180, che confondere le cose un po '. Avremo bisogno di convertire questo valore in un range da 0 a 360 per ottenere la corretta rotazione.

Questa è una tabella di ciò che vogliamo veramente, se paragonato a quello 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 implementa il SensorEventListener e le sue funzioni (onSensorChanged, onAcurracyChabge) e scrivere tutto il codice all'interno onSensorChanged

codice completo è qui per la direzione di Qibla bussola

 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;
}

codice XML è qui

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/flag_pakistan">
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/heading"
    android:textColor="@color/colorAccent"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="100dp"
    android:layout_marginTop="20dp"
    android:text="Heading: 0.0" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/heading"
android:scaleType="centerInside"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true">

<ImageView
    android:id="@+id/imageCompass"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:scaleType="centerInside"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true"
    android:src="@drawable/images_compass"/>

<ImageView
    android:id="@+id/needle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true"
    android:scaleType="centerInside"
    android:src="@drawable/arrow2"/>
</RelativeLayout>
</RelativeLayout>

Non sono un esperto in mappa-lettura / navigazione e così via, ma sicuramente 'direzioni' sono assoluti e non relativi o, in realtà, essi sono relative al N o S che a loro volta sono fissi / assoluto.

Esempio: Supponiamo una linea immaginaria tracciata fra te ei tuoi corrisponde destinazione con SE 'assoluto' (un cuscinetto di 135 ° rispetto alla N magnetica). Supponiamo ora che il telefono sia rivolta NW - se si disegna una linea immaginaria da un oggetto immaginario all'orizzonte verso la destinazione, passerà attraverso la vostra posizione e hanno un angolo di 180 gradi. Ora 180 gradi, nel senso di una bussola in realtà si riferisce a S, ma la destinazione non è 'dovuta S' dell'oggetto immaginario il telefono sta indicando e, inoltre, se hai viaggiato a quel punto immaginario, la destinazione sarebbe ancora a SE di dove è stato spostato a.

In realtà, la linea 180 gradi in realtà ti dice la destinazione è 'dietro di te' relativa al modo in cui il telefono (e presumibilmente voi) sta puntando.

Detto questo, tuttavia, se il calcolo del angolo di una linea dal punto immaginario verso la destinazione (passando per la vostra posizione), al fine di disegnare un puntatore verso la vostra destinazione è ciò che si vuole ... è sufficiente sottrarre il (assoluto ) di appoggio del destinazione dal cuscinetto assoluta dell'oggetto immaginario e ignorare una negazione (se presente). per esempio, NW - SE è 315 -. 135 = 180 in modo da disegnare il puntatore al punto nella parte inferiore dello schermo che indica 'dietro di te'

Modifica ho ottenuto la matematica leggermente sbagliato ... sottrarre il minore dei cuscinetti dal più grande quindi sottrarre il risultato da 360 a ottenere l'angolo in cui disegnare il puntatore sullo schermo.

Se siete sulla stessa fuso orario

Converti GPS per UTM

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

coordinate UTM farti un simples X Y 2D

Calcola l'angolo tra entrambe le posizioni UTM

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

Questo dà la direzione, come se si stesse guardando a nord

Quindi, qualunque cosa si ruota correlato non solo del Nord sottrarre questo angolo

Se sia punto hanno un angolo di 45 ° gradi UTM e si è 5º est di nord, la freccia punterà al 40º del nord

Ecco come ho fatto:

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 );

So che questo è un po 'vecchio, ma per il bene della gente come me da parte di Google, che non hanno trovato una risposta completa qui. Ecco alcuni estratti del mio app che mettono le frecce all'interno di un listview personalizzato ....

Location loc;   //Will hold lastknown location
Location wptLoc = new Location("");    // Waypoint location 
float dist = -1;
float bearing = 0;
float heading = 0;
float arrow_rotation = 0;

LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);

if(loc == null) {   //No recent GPS fix
    Criteria criteria = new Criteria();
    criteria.setAccuracy(Criteria.ACCURACY_FINE);
    criteria.setAltitudeRequired(false);
    criteria.setBearingRequired(true);
    criteria.setCostAllowed(true);
    criteria.setSpeedRequired(false);
    loc = lm.getLastKnownLocation(lm.getBestProvider(criteria, true));
}

if(loc != null) {
    wptLoc.setLongitude(cursor.getFloat(2));    //Cursor is from SimpleCursorAdapter
    wptLoc.setLatitude(cursor.getFloat(3));
    dist = loc.distanceTo(wptLoc);
    bearing = loc.bearingTo(wptLoc);    // -180 to 180
    heading = loc.getBearing();         // 0 to 360
    // *** Code to calculate where the arrow should point ***
    arrow_rotation = (360+((bearing + 360) % 360)-heading) % 360;
}

I pronto a scommettere che potrebbe essere semplificata, ma funziona! LastKnownLocation è stata utilizzata dal momento che questo codice è stato da nuovo SimpleCursorAdapter.ViewBinder ()

onLocationChanged contiene una chiamata a notifyDataSetChanged ();

codice anche da New SimpleCursorAdapter.ViewBinder () per impostare i colori di rotazione dell'immagine e listrow (applicati solo in un singolo columnIndex si badi bene) ...

LinearLayout ll = ((LinearLayout)view.getParent());
ll.setBackgroundColor(bc); 
int childcount = ll.getChildCount();
for (int i=0; i < childcount; i++){
    View v = ll.getChildAt(i);
    if(v instanceof TextView) ((TextView)v).setTextColor(fc);
    if(v instanceof ImageView) {
        ImageView img = (ImageView)v;
        img.setImageResource(R.drawable.ic_arrow);
        Matrix matrix = new Matrix();
        img.setScaleType(ScaleType.MATRIX);
        matrix.postRotate(arrow_rotation, img.getWidth()/2, img.getHeight()/2);
        img.setImageMatrix(matrix); 
}

Nel caso in cui vi state chiedendo che ho fatto via con i drammi dei sensori magnetici, non valeva la seccatura nel mio caso. Spero che qualcuno trova questo utile come faccio di solito quando Google mi porta a StackOverflow!

Ecco il codice per calcolare l'angolo tra due punti di appoggio:

public float CalculateBearingAngle(double lat1,double lon1, double lat2, double lon2){
    double Phi1 = Math.toRadians(lat1);
    double Phi2 = Math.toRadians(lat2);
    double DeltaLambda = Math.toRadians(lon2 - lon1);
    double Theta = atan2((sin(DeltaLambda)*cos(Phi2)),
        (cos(Phi1)*sin(Phi2) - sin(Phi1)*cos(Phi2)*cos(DeltaLambda)));
    return (float)Math.toDegrees(Theta);
}

di chiamata per la funzione:

float angle = CalculateBearingAngle(lat1, lon1, lat2, lon2);

Terminologia: La differenza tra il nord e il VERO Nord magnetico è noto come "variante" non declinazione. La differenza tra ciò che la vostra bussola legge e l'intestazione magnetica è conosciuto come "deviazione" e varia con voce. Una bussola identifica battente errori dispositivo e permette correzioni da applicare se il dispositivo è costruito in correzione. Una bussola magnetica avrà una carta di deviazione che descrive l'errore dispositivo su qualsiasi voce.

Declinazione: Un termine usato in Astro navigazione: declinazione è quali latitudine. Si riporta quanto lontano una stella è dall'equatore celeste. Per trovare la declinazione di una stella seguire un cerchio orario "giù dritta" dalla stella all'equatore celeste. L'angolo dalla stella all'equatore celeste lungo il cerchio ora è la declinazione della stella.

Sono in procinto di capire che fuori ora, ma sembra come se la matematica dipende da dove voi e la vostra destinazione è sulla terra, rispetto al vero e magnetico Nord. Ad esempio:

float thetaMeThem = 0.0;
if (myLocation.bearingTo(targetLocation) > myLocation.getBearing()){ 
     thetaMeThem = myLocation.bearingTo(targetLocation) - azimuth + declination;} 

Vedere Sensor.TYPE_ORIENTATION per azimut.

See getDeclination () per la declinazione

Questo presuppone la declinazione è negativo (ad ovest del Nord geografico) e theirBearing> yourBearing.

Se la declinazione è positivo e yourBearing> theirBearing un'altra opzione:

float thetaMeThem = 0.0;
if (myLocation.bearingTo(targetLocation) < myLocation.getBearing()){ 
     thetaMeThem = azimuth - (myLocation.bearingTo(targetLocation) - declination);} 

Non ho testato questo pienamente, ma a giocare con gli angoli su carta mi ha fatto qui.

Questo è il modo migliore per individuare Bearing da Località Oggetto su Google Map: ->

 float targetBearing=90;

      Location endingLocation=new Location("ending point"); 

      Location
       startingLocation=new Location("starting point");
       startingLocation.setLatitude(mGoogleMap.getCameraPosition().target.latitude);
       startingLocation.setLongitude(mGoogleMap.getCameraPosition().target.longitude);
       endingLocation.setLatitude(mLatLng.latitude);
       endingLocation.setLongitude(mLatLng.longitude);
      targetBearing =
       startingLocation.bearingTo(endingLocation);

La formula darà il cuscinetto utilizzando le coordinate del punto di partenza al punto finale vedi

Il seguente codice vi darà il cuscinetto (angolo tra 0-360)

private double bearing(Location startPoint, Location endPoint) {
    double longitude1 = startPoint.getLongitude();
    double latitude1 = Math.toRadians(startPoint.getLatitude());

    double longitude2 = endPoint.getLongitude();        
    double latitude2 = Math.toRadians(endPoint.getLatitude());

    double longDiff = Math.toRadians(longitude2 - longitude1);

    double y = Math.sin(longDiff) * Math.cos(latitude2);
    double x = Math.cos(latitude1) * Math.sin(latitude2) - Math.sin(latitude1) * Math.cos(latitude2) * Math.cos(longDiff);

    return Math.toDegrees(Math.atan2(y, x));

}

Questo funziona per me la speranza che funzionerà altri pure

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top