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
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
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); ------------
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...
@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
@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
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.
@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
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
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
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
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
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
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
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
...>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
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.