Forum: Compiler & IDEs Umrechnung GPS Koordinaten


von Peter (Gast)


Lesenswert?

Habe GPS Koordinaten in folgender Form in einem Array...

Grad und Dezimalminuten (GMM): 41 24.2028, 2 10.4418
z.B. gps_data[0]=4 gps_data[1]=1 gps_data[2]=2 usw...

Zum Umrechnen in Dezimalgrad (GGG): 41.40338, 2.17403
muss man ja jetzt z.B. 24.2028 / 60 + 41 rechnen.

Wie komme ich jetzt von obigen Array zu
z.B. einem Wert wie dann 41.40338 in C?

von Markus F. (mfro)


Lesenswert?

Peter schrieb:
> Wie komme ich jetzt von obigen Array zu
> z.B. einem Wert wie dann 41.40338 in C?

Auf welcher Hardware (AVR, PC, kariertes Papier, ...)?

von Jochen S. (jochen_s)


Lesenswert?

Hallo Peter,

im ersten Schritt muss um den "ZEICHEN" rechnen zu können aus dem Array 
jeweils eine Zahl gemacht werden. Dazu verwendet man im Allgemeinen den 
Ascii-Code des Zeichens und zieht dann Ascii 0 (das Zeichen Null) ab.

Hierbei kann Du schon auf Vor- und Nachkommastellen achten.

also die gps_data[0]=4 als Ziffer mit 10 multiplizieren und dann die 1 
als Ziffer addieren.
Wenn es flexibel sein soo, muss due vorher im Array die Längen ermitteln 
um zu wissen wie viele Stellen vor dem Komma stehen.

Bei den Dezimalminuten geht das vom Prinzip her genauso, allerdings 
kommt hier noch deine /60 hinzu, dies ist aber kein großen Thema mehr, 
wenn es erst mal Zahlen sind.
Wenn Du die Ausgabe als Kommazahl haben möchtest, denk dran einen 
Datentyp zu verwenden der das kann.

Double , float


Hoffe ich konnte dir helfen. Meld dich einfach...

von Peter (Gast)


Lesenswert?

Auf einem AVR...

von Peter (Gast)


Lesenswert?

@Jochen
Ah OK, ich dachte das geht irgendwie einfacher.
Ja ich möchte ein float am Ende haben.

von Markus F. (mfro)


Lesenswert?

Peter schrieb:
> @Jochen
> Ah OK, ich dachte das geht irgendwie einfacher.
> Ja ich möchte ein float am Ende haben.

Ich bin nicht sicher, ob Du das willst. Ich nehme an, die Daten kommen 
als Datenstrom an, mit dem Du irgendwie mithalten musst?

Wenn Du die Umrechnung von Bogenminuten in Dezimalminuten als float 
machst, dürfte das auf dem AVR ein wenig (möglicherweise ein wenig zu 
lange) dauern.

Da ist es wahrscheinlich günstiger, die Vor- und Nachkommastellen 
separat als Fixpunktzahl zu behandeln, so daß Du nur mit Ganzzahlen 
rechnen mußt.

von Peter (Gast)


Lesenswert?

@Markus
Das Ganze ist Zeitunkritisch.
Generiere aus den GPS Koordinaten
nur einen Google Maps Link der dann per SMS
versendet wird.

von npn (Gast)


Lesenswert?

Markus F. schrieb:
> Wenn Du die Umrechnung von Bogenminuten in Dezimalminuten als float
> machst, dürfte das auf dem AVR ein wenig (möglicherweise ein wenig zu
> lange) dauern.

Wenn die Daten von einem GPS-Empfänger kommen, dann kommen sie in der 
Regel in einem Abstand von einer Sekunde. Ich denke, in einer Sekunde 
schafft der AVR schon zwei oder drei Fließkomma-Operationen :-))

von Markus F. (mfro)


Lesenswert?

Peter schrieb:
> @Markus
> Das Ganze ist Zeitunkritisch.
> Generiere aus den GPS Koordinaten
> nur einen Google Maps Link der dann per SMS
> versendet wird.

Dann kannst Du's so machen wie von Jochen oben beschrieben.

Oder, wenn Du genügend Platz hast, mit sscanf() aus der AVR-libc. Das 
erspart dir, die float-Parserei von Hand zu machen.

von Jochen S. (jochen_s)


Lesenswert?

Hallo Peter,

so schlimm ist es  nicht.

Peter schrieb:
> Habe GPS Koordinaten in folgender Form in einem Array...
>
> Grad und Dezimalminuten (GMM): 41 24.2028, 2 10.4418
> z.B. gps_data[0]=4 gps_data[1]=1 gps_data[2]=2 usw...
>
> Zum Umrechnen in Dezimalgrad (GGG): 41.40338, 2.17403
> muss man ja jetzt z.B. 24.2028 / 60 + 41 rechnen.
>
> Wie komme ich jetzt von obigen Array zu
> z.B. einem Wert wie dann 41.40338 in C?

Deine Darstellung des Arrays passt leider nicht ganz mit dem zusammen, 
was Du darüber geschrieben hast. In  gps_data[2] müsste nach der obiger 
Schreibweise ein Leerzeichen sein?


hier was Q&D zum spielen: (läuft auf PC in  DEVcc)
1
#include <cstdlib>
2
#include <iostream>
3
4
using namespace std;
5
6
int main(int argc, char *argv[])
7
{
8
    int Zehner_vorkomma;
9
    int einer_vorkomma;
10
    int vorkomma;
11
    float nachkomma_1;
12
    float nachkomma_2;
13
    float nachkomma_3;
14
    float nachkomma_4;
15
    float nachkomma_5;
16
    float nachkomma_6;
17
    float nachkomma;
18
    float Koordinate;
19
    char Data[8];
20
    Data[0]='4';
21
    Data[1]='1';
22
    Data[2]='2';
23
    Data[3]='4';
24
    Data[4]='2';
25
    Data[5]='0';
26
    Data[6]='2';
27
    Data[7]='8';
28
29
30
  
31
Zehner_vorkomma=Data[0]-'0';
32
einer_vorkomma=Data[1]-'0';
33
vorkomma=Zehner_vorkomma*10+einer_vorkomma;
34
printf ("vorkomma %d",vorkomma);
35
printf (" \n" );   
36
37
nachkomma_1=Data[2]-'0';
38
nachkomma_2=Data[3]-'0';
39
nachkomma_3=Data[4]-'0';
40
nachkomma_4=Data[5]-'0';
41
nachkomma_5=Data[6]-'0';
42
nachkomma_6=Data[7]-'0';
43
nachkomma=nachkomma_1*100000+nachkomma_2*10000+nachkomma_3*1000+nachkomma_4*100+nachkomma_5*10+nachkomma_6;
44
nachkomma=nachkomma/60/100000;
45
printf ("nachkomma %f",nachkomma);
46
printf (" \n" );    
47
Koordinate=(double)vorkomma+(double)nachkomma;    
48
printf ("Koordinate %f \n",Koordinate);
49
    
50
    system("PAUSE");
51
    return EXIT_SUCCESS;
52
}

von Peter (Gast)


Lesenswert?

Hallo Jochen danke für Dein Beispiel!
Das mit dem Array war nur ein Beispiel um klarzumachen was ich meine.
Der GPS Empfänger bringt an der Stelle kein Leerzeichen.

Aber da es ein ATMega2560 ist, hab ich genügend platz und ich werde
es dann mal mit sscanf probieren wie Markus vorgeschlagen hat.

Gruß und Danke an euch
Peter

von Peter (Gast)


Lesenswert?

Habe es jetzt mit ATOI und ATOF gemacht...
1
                    degree_lat_array[0]=gps_latitude[1];
2
                    degree_lat_array[1]=gps_latitude[2];
3
                    degree_lat=atoi(degree_lat_array);
4
                    
5
                    minutes_lat[0]= gps_latitude[3];
6
                    minutes_lat[1]= gps_latitude[4];
7
                    minutes_lat[2]= gps_latitude[5];
8
                    minutes_lat[3]= gps_latitude[6];
9
                    minutes_lat[4]= gps_latitude[7];
10
                    minutes_lat[5]= gps_latitude[8];
11
                    minutes_lat[6]= gps_latitude[9];
12
                    minutes_lat[7]= gps_latitude[10];    
13
                    minute_lat = atof(minutes_lat);
14
                    minute_lat = minute_lat / 60;
15
                    lat = degree_lat + minute_lat;
16
                    //printf( "Wert des Strings: %f\n", lat);
17
                    
18
                    degree_lon_array[0]=gps_longitude[1];
19
                    degree_lon_array[1]=gps_longitude[2];
20
                    degree_lon_array[2]=gps_longitude[3];
21
                    degree_lon=atoi(degree_lon_array);
22
                    
23
                    minutes_lon[0]= gps_longitude[4];
24
                    minutes_lon[1]= gps_longitude[5];
25
                    minutes_lon[2]= gps_longitude[6];
26
                    minutes_lon[3]= gps_longitude[7];
27
                    minutes_lon[4]= gps_longitude[8];
28
                    minutes_lon[5]= gps_longitude[9];
29
                    minutes_lon[6]= gps_longitude[10];
30
                    minutes_lon[7]= gps_longitude[11];    
31
                    minute_lon = atof(minutes_lon);
32
                    minute_lon = minute_lon / 60;
33
                    lon = degree_lon + minute_lon;
34
                    //printf( "Wert des Strings: %f\n", lon);

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:
> Habe es jetzt mit ATOI und ATOF gemacht...

zeig mal, wie du deine Arrays deklariert hast. Denn im Code hast du die 
C-String Terminierung nicht gemacht.

Man sieht auch recht oft, dass die Leute für derartige Konvertierungen 
jeweils verschiedene Arrays für die Strings benutzen. Wozu? DU kannst 
alle Konvertierungen über ein und dasselbe Array abwickeln, da du je die 
jeweiligen Teilstrings nach der Überführung in echte Zahlen nicht mehr 
brauchst.
Auch wenn du genug Speicher hast, verprassen brauchst du den deswegen 
auch nicht sinnlos.

von Markus F. (mfro)


Lesenswert?

Peter schrieb:
> Habe es jetzt mit ATOI und ATOF gemacht...
>

Das geht einfacher (ohne die Zwischenspeicherung):
1
sscanf(&gps_latitude[1], "%2d", &degree_lat);
2
sscanf(&gps_latitude[3], "%8f", &minute_lat);
3
minute_lat /= 60;
4
lat = degree_lat + minute_lat;
5
6
sscanf(&gps_longitude[1], "%2d", &degree_lon);
7
sscanf(&gps_longitude[3], "%8f", &minute_lon);
8
minute_lon /= 60;
9
lon = degree_lon + minute_lon;

sscanf() kann mit der Angabe einer Feldbreite direkt aus dem String 
lesen.

Der Code ist ungetestet, nur mal "aus der Hüfte" hingeschrieben, aber 
ich denke, so (oder ganz ähnlich) müsste es funktionieren.

Die sscanf() float-Version kriegst Du mit

-Wl,-u,vfscanf -lscanf_flt -lm

als Compileroption.

von Vlad T. (vlad_tepesch)


Lesenswert?

Ich bin gerade in einer ähnlichen Situation, in der ich auf einem µC mit 
GPS-Daten arbeiten möchte. 64bit-floats werden nicht unterstützt.

Nach nachrechnen, stellt sich heraus, dass von float die Genauigkeit 
nicht ausreicht.
Zum speichern vielleicht gerade so (am Äquator ~37cm pro digit).
Aber sobald gerechnet wird...

von Detlef _. (detlef_a)


Lesenswert?

hier gibts' funktionierende 64Bit float Routinen:

Beitrag "64 Bit float Emulator in C, IEEE754 compatibel"

Cheers
Detlef

von Jürgen S. (jurs)


Lesenswert?

Detlef _a schrieb:
> hier gibts' funktionierende 64Bit float Routinen:
>
> Beitrag "64 Bit float Emulator in C, IEEE754 compatibel"

Im allgemeinen ist es beim Rechnen mit GPS-Koordinaten gar nicht 
notwendig, mit so hoher Genauigkeit zu rechnen, um trotzdem ausreichend 
genaue Ergebnisse zu bekommen.

Sondern eigentlich braucht man nur geeignete Algorithmen zu verwenden.

Zum Beispiel für sehr kleine Abstände auf der Erdoberfläche den Abstand 
nicht per Kugelgeometrie und Winkelfunktionen ausrechnen, sondern 
stattdessen kleine Abstände als ebene Dreiecke mit euklidische Geometrie 
rechnen.

Dazu rechnet man sich im ersten Schritt beispielsweise aus, wieviele 
Meter ein millionstel Grad entspricht. Zum Beispiel am Äquator:
40070 km / 360° = 111,3 km
Entsprechend ist 1 Millionstel Grad:
111,3 * 1000 m / 1000000 = 0,1113 m

Und wenn man dann die GPS-Koordinaten nicht als Gleitkommazahlen 
vorliegen hat, sondern als long Ganzzahlen in Millionstel Längengrad, 
dann ist die Differenz zwischen Längengrad
10000004  (10,000004°) und
10000007  (10,000007°) am Äquator exakt
--------
       3 Millionstel Grad a 0,1113m = 0,3339 m

Bei Koordinaten, die sich in Längen- und Breitengrad unterscheiden, 
rechnet man den (kleinen) Abstand über den Pythagoras.

Im Endeffekt ist es dann nur Aufgabe zu entscheiden, wo man die Grenze 
zwischen "kleine GPS-Abstände" und "große GPS-Abstände" berechnen legt 
um zu entscheiden, ob man seinen gesuchten Abstandswert am besten per 
sphärischer oder per euklidischer Geometrie ausrechnet, um den relativen 
Fehler gering zu halten.

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.