Forum: Mikrocontroller und Digitale Elektronik Distance zwischen GPS Punkten


von Simon (Gast)


Lesenswert?

Distance zwischen GPS Punkten

Hi
Ich möchte die Distance zwischen 2 GPS punkten berechnen.
Der erste GPS Punkt ist fest und der zweite Punkt ist der Aktuelle 
Standort.
Die GPS Daten Auswertung funktioniert soweit aber irgendwie habe ich 
Probleme die Variable vom aktuellem Standort in die Formel zu bringen. 
Wenn ich zwei feste punkte angebe dann berechnet der µC mir das ohne 
Probleme.
Das ganze läuft auf einem Atmega128.


float distance;
uint32_t stringa;
uint32_t stringb;

stringa = GPRMC[3];    //GPS Koordinate N
stringb = GPRMC[5];    //GPS Koordinate E

void test(void)
{
distance = (111.324 * acos(sin(5341.1180) * sin(stringa) + 
cos(5341.1180) * cos(stringa) * cos(stringb - 683.3190)))/ 10;

lcd_float(distance);
}

Wenn ich das so Berechnen lasse steht im Display eine 0.
Hat jemand eine Idee wo der Fehler liegt?
Ich würde mich freuen wenn ihr mir helft.

Gruß Simon

von Ralli (Gast)


Lesenswert?

Ohne die Formeln oder die Sprachsyntax zu kontrollieren:

Argument (also das x) von sin(x) oder cos(x) muss üblicherweise
in Bogenmaß sein.
Selbst wenn Winkelgrad erlaubt ist, darf da nicht

sin(Längengrad*100 + Längenminuten.Längenminutenbruchteile)

stehen, solange ein sinnvolles Ergebnis erwartet wird.

Für die Breitengrade gilt das gleiche.
Sind denn die Ergebnisse für 2 feste Punkte überhaupt sinnvoll?

Schönen Gruß,
Ralli

von Tim R. (vref)


Lesenswert?

Aus meinem nmea2kml converter hier ein kleiner an deine Zwecke 
angepasster Schnipsel.
Wichtig ist vor allem, dass du Unterscheidungen zwischen westlicher und 
östlicher sowie südlicher und nördlicher Hemmisphäre vornimmst...

Mein Programm läuft nicht auf nem Microcontroller, daher hatte ich keine 
Not alles in double zu rechnen, mit float wird es aber vermutlich genau 
genug.


--------------
double d1, d2;
double lat_full, long_full;
double dx, dy;
double latitude, longitude;
double distance;


d1     = strtod(buf[3], NULL);
d2     = strtod(buf[5], NULL);

lat_full  = floor(d1  / 100.0);
long_full = floor(d2 / 100.0);

latitude  = lat_full + (d1 -  lat_full*100.0)/60.0;
longitude = long_full + (d2 - long_full*100.0)/60.0;

if (buf[4][0] == 'S') latitude  = -latitude;
if (buf[6][0] == 'W') longitude = -longitude;

dy = (latitude  - latitude_ref ) * 111314.4 ;                   // [m]
dx = (longitude - longitude_ref) * 111319.5 * cos(latitude * CONST_PI / 
180.0);     // [m]

distance = sqrt(dx*dx + dy*dy);
------------

von Tim R. (vref)


Lesenswert?

Achso, die Referenz-koordinaten latitude_ref und longitude_ref müssen 
natürlich ebenso - wie hier mit latitude und longitude gezeigt  - 
erstmal vom GPS-Koordinaten-Format in dezimal umgerechnet sein...

von Christoph (Gast)


Lesenswert?

@Simon

ich gehe mal davon aus, daß deine Referenzkoordinate die folgende ist:

Breitengrad: 5341.1180
Längengrad:  683.3190

Die Daten hast Du bestimmt aus einem NMEA-Datensatz. Die kannst Du 
allerdings nicht so einfach verwenden, jedenfalls nicht zum Rechnen. Du 
mußt die Breiten- und Längenangabe erst einmal in das Format Dezimalgrad 
umrechnen (siehe http://de.wikipedia.org/wiki/Breitengrad). Im Grunde 
kann eine Breitengrad- bzw. Längengradangabe in vier Formaten angegeben 
sein:

   1. Grad, Dezimalminuten: 66° 43,2′
   2. Dezimalgrad: 66,72°
   3. Grad, Minuten, Sekunden: 66° 43′ 13″
   4. Grad, Minuten, Dezimalsekunden: 66° 43′ 12,96″

Die Frage ist nun, welches Format in deinem GPS eingestellt ist? 
Abhängig davon mußt Du deine Referenzkoordinate in das 
Dezimalgrad-Format umrechnen. Und natürlich auch die aktuelle 
Koordinate, bevor es zur Entfernungsberechnung kommt.

Doch das ist nicht alles. Zusätzlich müssen die Gradangaben der Breiten- 
& Längengrade von Winkelmaß in Bogenmaß umgerechnet werden, weil die 
Funktionen sin, cos & acos die Werte im Bogenmaß erwarten.

Eine Frage hätte ich aber auch... wieso wird am Ende durch 10 dividiert?

Gruß
Christoph

von Christoph (Gast)


Lesenswert?

@Tim R.

Anmerkung: die Berechnung, die Du da durchführst, basiert auf einem 
rechtwinkligen Dreieck und ist relativ ungenau auf größere Entfernungen, 
weil die Erdkrümmung nicht beachtet wird. Die Berechnung, die Simon 
durchführen möchte basiert auf Orthodromen 
(http://de.wikipedia.org/wiki/Orthodrome) und ist genauer... dafür 
rechenintensiver.

Gruß
Christoph

von Tim R. (vref)


Lesenswert?

Das ist richtig.
In meinem Fall bekomme ich alle 1-5 Sek. vom GPS neue Koordinaten, und 
die Referenz ist immer die letzte Koordinate. Daher legt man selbst im 
Flugzeug max. ca. 1km in dieser Zeit zurück. Und in diesem Maßstab ist 
die Näherung auf eine Ebene ausreichend.

von Christoph (Gast)


Lesenswert?

@Tim R.
Da stimme ich Dir vollkommen zu... die Sache mit den Orthodromen ist 
zwar genauer, aber in den meisten Anwendungsfällen hat es etwas von 'mit 
Kanonen auf Spatzen schießen' ;)

Gruß
Christoph

von spess53 (Gast)


Lesenswert?

HI

In der Zeitschrift 'Toolbox' 1/2008 und 3-4/2008 sind Beiträge, die sich 
mit den Berechnungen rund um GPS, Koordinaten, Projektionen und 
Transformationen beschäftigen.

MfG Spess

von Detlef _. (detlef_a)


Lesenswert?

Die Entfernungberechnung zwischen zwei Koordinaten (GPS Koordinaten) auf 
einer Kugeloberfläche war schon öfters diskutiertes Thema:
Beitrag "Berechnung eines Kurses mit Koordinate"
Beitrag "GPS - MOUSE - MINI- NAVIGATOR (Assembler) ATmega8"

Gute Nacht
Detlef

von Simon (Gast)


Lesenswert?

Hi
Die Formel zum berechnen der Distance habe ich auf dieser Internetseite 
gefunden.
http://www.kompf.de/gps/distcalc.html

Ich habe die Formel gewählt weil ich ein möglich genaues Ergebnis 
erzielen wollte.

Und wenn ich mit 2 festen werten rechne also die beiden Variablen 
GPRMC[3] und GPRMC[5] durch GPS Koordinaten ersetzte bekomme ich auch 
ein richtiges Ergebnis raus. Deswegen verstehe ich nicht warum ich Daten 
noch umrechnen muss. Es kann aber auch nur Zufall gewesen sein das die 
Ergebnisse stimmten.

Die Referenzkoordinate
Breitengrad: 5341.1180
Längengrad:  683.3190
Habe ich auch aus einem Datensatz den ich mal aufgezeichnet habe.
Also mein GPS Empfänger liefert mir das auch in diesem Format.


@Tim R.
Dank. Wenn ich von der Arbeit wieder zuhause bin werde ich die Formel 
gleich mal ausprobieren.

@Christoph
Das durch 10 Teile ist unrelevant für die Formel. Es dient nachher nur 
zur besseren Ausgabe auf dem Display.

Gruß Simon

von Uwe N. (ulegan)


Lesenswert?

Das ist doch die übliche kompakte Darstellung im NMEA-Format.
Breitengrad: 5341.1180
Längengrad:  683.3190
bedeutet eigentlich 53° 41,1180' (vermutlich Nord, das ist das N im Feld 
davor) und 6° 83,3190' (wahrscheilich Ost, also E).
Aber bei der Länge liegt wohl ein Tippfehler vor, denn 83,319' machen 
keinen Sinn, die Minuten müssen kleiner 60 sein.
Nehmen wir mal an, dass sollte 53.3190 heissen dann ergibt sich auf 
ganze Grad umgerechnet 53,6853° Nord und 6,88865° Ost, das liegt vor 
Juist...

Zur Berechnung empfehle ich die Seite:
http://williams.best.vwh.net/avform.htm
Das Kapitel 'Distance between two points'.

Uwe

von Arno H. (arno_h)


Lesenswert?

Das sieht eher nach UTM-Koordinaten aus. Dann müsste noch eine Zone 
davor stehen, vermutlich 32.
Bist du sicher, auf dem Empfänger geografische Koordinatenausgabe 
eingestellt zu haben?
Dann  stünde auch ein "N" bei der Breite und ein "E" bei der 
Längenkoordinate dabei.

Arno

von Simon (Gast)


Lesenswert?

Hi
Ne es ist echt nur nen blöder Tippfehler da muss anstelle der 8 ne 1 
hin, aber trotzdem funktioniert das nicht mit der Berechnung.

Ne UTM ist das auch nicht.
Das währe schön wenn es UTM währe dann könnte ich mir das sparen die 
Daten nachher von GPS in UTM umzurechnen.

@ Uwe Nagel
Danke für den Tipp ich werd mir das mal angucken.

Gruß Simon

von Ronny (Gast)


Lesenswert?

Hallo,

möchte mal versuchen, einen sinnvollen Beitrag dazu zu leisten:

1. Abstand Breitengrade ist konstant -> Breitenminute = 1 Meile = 1.85km
2. Abstand Längengrade abhängig von Breitengrad :
                 Abstand_Längengrad = cos(Breitengrad)
3. für kurze Entfernungen Betrachtung in 2D-Ebene -> Dreieck
4. Datensätze müssen in Grad, Minute und Rest zerlegt werden
5. Ausgabe (z.B. 5341.1180N):
      54 Grad, 41 Minuten, 1180 (NICHT SEKUNDE!!!)
6. Differenzen für Breite und Länge bilden: Breitegrad2 - Breitegrad1, 
...
7. Mittels Satz des Pythagoras Entfernung berechnen:
                 E = sqrt(square(dB)+ square(dL))

mal als Code-Auszug:

   int BG1, BG2, BM1, BM2, BS1, BS2, LG1, LG2, LGM1, LM2, LS1, LS2;
   int ENTFERNUNG;
   double LAENGEN_ABSTAND, BREITE, LAENGE, MEILE = 1852.0;

   // zerlegen NMEA-Datensaetze in BG2, BM2, ...

   LAENGEN_ABSTAND = MEILE * 60.0 * cos(abs(BG2) * M_PI/180);
   BREITE = ((BG2 - BG1)  MEILE  60.0) +
            ((BM2 - BM1) * MEILE) +
            ((BS2 - BS1) * 0.006 * MEILE/60.0);
   LAENGE = ((LG2 - LG1) * LAENGEN_ABSTAND ) +
            ((LM2 - LM1) * LAENGEN_ABSTAND /60.0) +
            ((LS2 - LS1) * 0.006 * LAENGEN_ABSTAND /3600.0);
   ENTFERNUNG = (int)sqrt((square(BREITE) + square(LAENGE)));


viel Spass noch

von JUERGEN (Gast)


Lesenswert?

...>möchte mal versuchen, einen sinnvollen Beitrag dazu zu leisten:

>1. Abstand Breitengrade ist konstant -> Breitenminute = 1 Meile = 1.85km

Das ist ein weitverbreiteter Irrtum.
Der Abstand schwankt zwar nur gering, ist aber eben nicht konstant.
Je nach angestrebter Genauigkeit sollte man das schon beachten.

http://home.online.no/%7Esigurdhu/artimages/Latitude_1min.gif

juergen

von Jochen (Gast)


Lesenswert?

Hallo Simon,
von mir ist der eine tread der weiter oben genannt ist...

Du schreibst du wilst in UTM umrechnen hast du da irgendwelche 
Unterlagen wie das geht??

Bei welchem Verein bist du den der sowas nutzt Bund Feuerwehr KATs??

Jochen

von Simon (Gast)


Lesenswert?

Hi ich habe mal ein bisschen Rumexperimentiert.
Aber so das richtige war noch nicht dabei. Wenn ich eine Lösung gefunden 
habe werde ich sie hier präsentieren.

Ja später will ich in UTM umrechnen aber das dauert noch was.
Mein kleines Selbstbau Navi kommt ins Auto eingebaut.
Und die UTM Daten brauche ich um in einer Karte z.B die vom ADAC die 
Position zu bestimmen. Denn eine gute Straßenkarte mit den Längen und 
Breiten Graden hab ich noch nicht gefunden und wenn dann ist der Maßstab 
so groß das man nicht mehr genau weiß wo man ist.
Die Infos zum umrechnen hole ich mir aus einem Quellcode von der Seite 
http://home.hiwaay.net/~taylorc/toolbox/geography/geoutm.html
mal gucken ob ich das nachher auch noch hinbekomme.
Aber erstmal ist es interessant die Distance zwischen zwei GPS Punkten 
zu errechnen.
Gruß Simon

von Simon (Gast)


Lesenswert?

Nach langen rum experimentieren habe ich nun eine Lösung gefunden.
Leider ist sie nicht wirklich elegant, aber sie funktioniert.
Jetzt mach ich mich mal an die Optimierung.
Falls einer gute Ideen hat immer her damit :-)

void distance(void)
{
  double dist;
  double lat1;
  double lat2;
  double lon1;
  double lon2;

/*fest einprogrammierter Standort (z.B. zu hause) einfach die x durch 
die gewünschten Koordinaten ersetzten. Das Format muss Dezimalgrad 
sein.*/
  lat2 = xx.xxxx;
  lon2 = xxx.xxxx;

  double arraylat()
  {
    double summe;
    summe = 0;
    summe += (GPRMC[3][2]-0x30)*10000000;
    summe += (GPRMC[3][3]-0x30)*1000000;
    summe += (GPRMC[3][5]-0x30)*100000;
    summe += (GPRMC[3][6]-0x30)*10000;
    summe += (GPRMC[3][7]-0x30)*1000;
    summe += (GPRMC[3][8]-0x30)*100;
    return summe;
  }

  lat1 = arraylat()/6000000;

  if  (GPRMC[3][0] == 0x30)
  {
    lat1 += (GPRMC[3][1]-0x30)*10;
  }
  else
  {
    lat1 += (GPRMC[3][0]-0x30)*100;
    lat1 += (GPRMC[3][1]-0x30)*10;
  }

  double arraylon()
  {
    double summe;
    summe = 0;
    summe += (GPRMC[5][3]-0x30)*10000000;
    summe += (GPRMC[5][4]-0x30)*1000000;
    summe += (GPRMC[5][6]-0x30)*100000;
    summe += (GPRMC[5][7]-0x30)*10000;
    summe += (GPRMC[5][8]-0x30)*1000;
    summe += (GPRMC[5][9]-0x30)*100;
    return summe;
  }

  lon1 = arraylon()/6000000;

  if (GPRMC[5][0] == 0x30)
  {
    if (GPRMC[5][1] == 0x30)
    {
      lon1 += (GPRMC[5][2]-0x30)*10;
    }
    else
    {
      lon1 += (GPRMC[5][1]-0x30)*100;
      lon1 += (GPRMC[5][2]-0x30)*10;
    }
  }
  else
  {
    lon1 += (GPRMC[5][0]-0x30)*1000;
    lon1 += (GPRMC[5][1]-0x30)*100;
    lon1 += (GPRMC[5][2]-0x30)*10;
  }

  dist = 111.324 * acos(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * 
cos(lon2 - lon1));
  lcd_float(dist,1);
  lcd_str("km nach Hause");
}



Gruß Simon

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.