Forum: Mikrocontroller und Digitale Elektronik Problem mit der berechnung von sin/cos/acos


von Lukas H. (lukasrau)


Lesenswert?

Ich habe folgendes Problem:

Entwicklungsumgebung Keil uVision 3

Ich möchte gerne die entfernung von 2 GPS Positionen berechnen wenn ich 
die folgende Formel mit meinem Taschenrechner berechne (auf RAD 
eingestellt) bekomme ich das richtige ergebnis wenn ich das ganze aber 
mit dem Debugger von Keil durchgehe steht am ende folgendes Ergebnis im
Speicher: -1.#INF es sollte aber 1.593(mit Taschenrechner berechnet) 
drinstehen hier ist der code:


// initialisierung aus der Struktur im main
GPRMCDaten.dezimalLaengengrad   = 8.41321;
GPRMCDaten.dezimalLaengengrad2   = 8.42182;
GPRMCDaten.dezimalBreitengrad   = 49.9917;
GPRMCDaten.dezimalBreitengrad2   = 50.0049;
//


float   lat1,lat2,lon1,lon2;
float  distanz;
float   pi = 3.14159265;


lat1 = 2.0*pi*(ptrStrukt->dezimalBreitengrad/360.0);
lat2 = 2.0*pi*(ptrStrukt->dezimalBreitengrad2/360.0);
lon1 = 2.0*pi*(ptrStrukt->dezimalLaengengrad/360.0);
lon2 = 2.0*pi*(ptrStrukt->dezimalLaengengrad2/360.0);

distanz = 6378.388 * acos(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) 
* cos(lon2 - lon1));


fals jeamnd ne idee hat wäre ich für eine Antwort sehr dankbar

von Purzel H. (hacky)


Lesenswert?

Wieviele signifikante Stellen hat float ? Was geschieht bei acos 
(1+0.0001) oder so ?

von Karl H. (kbuchegg)


Lesenswert?

Lukas Honsell schrieb:

> distanz = 6378.388 * acos(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2)
> * cos(lon2 - lon1));
>
>
> fals jeamnd ne idee hat wäre ich für eine Antwort sehr dankbar

Nimm mal die Formel auseinander, lass dir die einzelnen Terme getrennt 
ausrechnen und dann vergleiche die Zwischenwerte mit denen, die du vom 
Taschenrechner bekommst.

von Klaus W. (mfgkw)


Lesenswert?

Mit 8-Byte-doubles gerechnet sieht es erstmal vernünftig aus
(ich komme mit meinem double-Taschenrechner auf 1.593417 (km?)).

Aber selbst wenn er durch Kniffe das Problem soweit löst, sehe
ich ein ganz anderes (das mit dem obigen Rundungsfehler eng verwandt
ist):
Er versucht ja offenbar, eine relativ kleine Entfernung auf der
Erdoberfläche aus den Koordinaten zu berechnen.
D.h. er versucht, aus einem Wert sehr nahe bei 1.000 über den
acos den Winkel zu bestimmen. Leider ändert sich der cos
bei kleinen Winkeln kaum, dementsprechend ungenau ist die
umgekehrte Rechnung über den acos zum Winkel.

Mein Vorschlag: entweder eine Gleichung hinfummeln, die
den asin verwendet (das ist bei kleinen Winkeln viel genauer,
da der sin hier praktisch linear verläuft),
oder gleich einsehen, daß es kleine Winkel sind und damit die
Erdkrümmung wumpe ist und einfach die Länge des Geradenstücks
zwischen den beiden Punkten nehmen.
Das ist wesentlich genauer als mit 6 Dezimalstellen bei float
über den acos zu gehen.

Das könnte so aussehen, daß man aus den Koordinaten den
Abstand in N-S-Richtung berechnet sowie den in O-W-Richtung,
und daraus über Pythagoras die Länge der Strecke.

PS: der Winkel um den es hier geht, ist in rad 0.000249 bzw.
0.014313°.
Ich gehe jede Wette ein, daß mein GPS-Tracker die Formel von
Lukas nicht verwendet.

von Klaus W. (mfgkw)


Lesenswert?

PPS: schneller geht es mit Pathagoras auch, weil man nur für die 
O-W-Richtung einmal eine Winkelfunktion braucht (oder eine Tabelle
für lineare Interpolation, da harmloser Verlauf), sowie etwas
Quadrieren und eine Wurzel.

von Karl H. (kbuchegg)


Lesenswert?

Klaus Wachtler schrieb:

> oder gleich einsehen, daß es kleine Winkel sind und damit die
> Erdkrümmung wumpe ist und einfach die Länge des Geradenstücks
> zwischen den beiden Punkten nehmen.
> Das ist wesentlich genauer als mit 6 Dezimalstellen bei float
> über den acos zu gehen.
>
> Das könnte so aussehen, daß man aus den Koordinaten den
> Abstand in N-S-Richtung berechnet sowie den in O-W-Richtung,
> und daraus über Pythagoras die Länge der Strecke.

Genau so würde ich das auch machen.
Denn:
  Was interessiert mich die Distanz auf einer Kugel zwischen
  Oberammerhofen und Bad-Nirgendwo?

Die reale Distanz ist sowieso eine andere, weil die Erde nun mal keine 
glatt polierte Billiardkugel ist, sondern Berge und Täler hat.

Anstatt da lang auf einer Kugel rumzurechnen, kann ich genausogut 
annehmen, dass in hinreichender Näherung die Erde in 50km Umkreis eine 
ebene Fläche ist. Der Fehler wird dadurch auch nicht größer sein.

von eProfi (Gast)


Lesenswert?

1.
#include<math.h>  ?
2.
evtl. muss eine float-library dazugelinkt werden.
3.
Wegen Rechengenauigkeit: steht eine double-library zur Verfügung?

von Purzel H. (hacky)


Lesenswert?

Ein Sinus kann um Null mit der Identitaet approximiert werden, und ein 
Cosinus mit 1-x^2, oder aehnlich, siehe Taylor

von Klaus W. (mfgkw)


Lesenswert?

A...aha Soooo. schrieb:
> 1-x^2

eben, und 1-x^2 ist bei kleinen x ziemlich genau 1.0.
Genau da steckt das Problem.
Der cos ist da einfach waagrecht.

von Lukas H. (lukasrau)


Lesenswert?

Danke schon einmal für die vielen Antworten das mit dem geringen abstand 
und die berechnung mit dem pytagoras weis ich auch schon es gibt ja drei 
berechnungsmethoden einmal die mit dem pytagoras dann die 
berechnungsformel mit der kugeloberfläche und die Formel für eine 
Ellipsoide das Problem ist dass ich mit meinem GPS gerät 
unterschiedliche Abstände berechnen will und so wäre mir die 
Kugelberechnung etwas lieber mir ist nun aufgefallen dass mein 
Taschenrechner nicht runded der compiler dagegen rundet bei zB 0.9999984 
schon auf 1 gibt es eine möglichkeit das zu unterbinden wenn nicht dann 
wäre noch die möglichkeit mit einer groben vorberechnung des Abstands 
der zwei Punkte zu errechnen und dann zu entscheiden ob ich die 
Pytagoras Formel oder die Kugelformel zur berechnung nehme

von Purzel H. (hacky)


Lesenswert?

Ja, eine Rundung kann man unterbinden duch mehr Stellen. Dh geh mal von 
Float-32bit auf float-64bit.

von Karl H. (kbuchegg)


Lesenswert?

Lukas Honsell schrieb:

> Taschenrechner nicht runded der compiler dagegen rundet bei zB 0.9999984
> schon auf 1

das tut er nicht.
Aber du darfst bei 5 bis 6 signifikanten Stellen keine Wunder erwarten. 
Du hast die Genauigkeit einfach nicht.
Dein Taschenrechner rechnet auf 10, 12, 15 Stellen genau, dein µC aber 
nur auf ca 6.

Signifikante Stellen!
Das heist bei der Zahl  876.387
sind diese 6 Stellen aufgebraucht, alles dahinter ist nur noch 
'gelogen'. Und das 'Problem' wird schlimmer, je komplexer die 
Berechnungen werden.

Wenn man zu 1000.00 die Zahl 0.0001 addieren will, dann hat man einfach 
nicht die dazu nötige Stellenzahl. Das ist bei einer Addition nicht 
weiter schlimm. Willst du aber 10000 mal die 0.0001 addieren, dann ist 
das Ergebnis danach immer noch 1000.00 obwohl dein Taschenrechner ganz 
was andres raus bringt.

von Klaus W. (mfgkw)


Lesenswert?

Lukas Honsell schrieb:
> Danke schon einmal für die vielen Antworten das mit dem geringen abstand
> und die berechnung mit dem pytagoras weis ich auch schon es gibt ja drei
> berechnungsmethoden einmal die mit dem pytagoras dann die
> berechnungsformel mit der kugeloberfläche und die Formel für eine
> Ellipsoide das Problem ist dass ich mit meinem GPS gerät
> unterschiedliche Abstände berechnen will und so wäre mir die
> Kugelberechnung etwas lieber mir ist nun aufgefallen dass mein
> Taschenrechner nicht runded der compiler dagegen rundet bei zB 0.9999984
> schon auf 1 gibt es eine möglichkeit das zu unterbinden wenn nicht dann
> wäre noch die möglichkeit mit einer groben vorberechnung des Abstands
> der zwei Punkte zu errechnen und dann zu entscheiden ob ich die
> Pytagoras Formel oder die Kugelformel zur berechnung nehme

Nein, dein Problem ist, daß du keine Sätze schreiben kannst.
Das kann man doch nicht lesen, ohne daß sich die Fußnägel ablösen!

von Lukas H. (lukasrau)


Lesenswert?

@ Klaus Wachtler ich werde mich in Zukunft bemühen :D

Das heist es wäre besser erst eine grobe vorberechnung der Distanz 
vorzunehmen und dann eine Methode auszuwählen (Pytagoras oder Kugel).

Bei kleinen Entfernungen den Pyt und bei den grösseren Entfernungen die 
Kugelberechnung.

Ist das mit den 6 Signifikanten Stellen beim uController immer so oder 
(hardwarebezogen) oder lässt sich das durch die Software erweitern.

von Klaus W. (mfgkw)


Lesenswert?

Lukas Honsell schrieb:
> Bei kleinen Entfernungen den Pyt und bei den grösseren Entfernungen die
> Kugelberechnung.

Das hört sich sinnvoll an.

Lukas Honsell schrieb:
> Ist das mit den 6 Signifikanten Stellen beim uController immer so oder
> (hardwarebezogen) oder lässt sich das durch die Software erweitern.

Je nach Controller gibt es meist sowieso keine Gleitkommarechnung
in Hardware, also ist es nur eine SW-Frage.

Beim AVR bspw. gibt es in der glibc erstmal nur float (genau
genommen gibt es auch double, aber das ist dasselbe).
Mit zusätzlichen Libs kann man auch mit 64 Bit rechnen.

Das Problem dabei ist, daß die Rechenzeit drastisch ansteigt.
Schon mit 32 Bit kann man kaum noch einen Blumentopf gewinnen,
64-Bit-Rechnungen mit noch ein paar Winkelfunktionen wirst
du nicht mehr im msec-Takt machen wollen, falls wir von wenigen
MHz Takt reden.

Bei geschickterer Rechnung mit float leben zu können, wird dir
mehr helfen.
Wenn du nicht gerade asin(etwa 1) rechnen willst oder ähnliches,
sind 6 Stellen gar nicht so verkehrt.

von Jobst M. (jobstens-de)


Lesenswert?

Nimm Pythagoras.

Funktioniert im Nahbereich wesentlich genauer und auch die Entfernung 
Hannover - Mallorca stimmt noch einigermassen gut.

Nur wenn Du damit Polarexpeditionen vor hast, gibt es damit Probleme.

Wenn Du Interesse an 8051-asm-code hast, sag bescheid!


Gruß

Jobst

von Martin O. (ossi-2)


Lesenswert?


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.