www.mikrocontroller.net

Forum: Compiler & IDEs "echter" double mit AVR-GCC


Autor: Andreas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe ein Funktion zur Berechnung der Wegstrecke zwischen 2 
GPS-Koordinaten geschrieben. Diese verwendet double-Datentypen. Da GCC 
aber anscheinend keinen echten double verwendet, habe ich Probleme mit 
der Genauigkeit von "nur" 6 Stellen.
Wenn die Koordinaten eng beisammen sind, ergibt sich bereits ein relativ 
großer Fehler. Beim Aufaddieren der Abstände zwischen den einzelnen 
Koordinaten ergibt sich folglich ein erheblicher Fehler (Bsp. 300 
Koordinaten, Länge am PC errechnet: 750m, Länge am AVR berechnet: 
312m!!!).

Gibt es eine Möglichkeit, die Genauigkeit im GCC zu erhöhen oder hat 
jemand eine optimierte Formel zur Berechnung der Differenz?
Ich verwende folgende Formel:

d = 2 * asin(sqrt((sin((lat1 - lat2) / 2)) ^ 2 + cos(lat1) * cos(lat2) * 
(sin((lon1 - lon2) / 2)) ^ 2))

Das Ergebnis ist die Länge in nautischen Meilen.

Danke für eure Hilfe.

mfg
Andreas

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Diese Formel ist bezüglich der Rundungsfehler schon optimiert. Da hängt 
es eher an der internen Implementation der trigonometrischen Funktionen 
im AVR-GCC.

Was spricht dagegen, die Gesamtstrecke nicht als Summe der einzelnen 
Teilstrecken, sondern als Entfernung Startpunkt-Zielpunkt zu berechnen?

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
^^ Bin beim obigen Post aus einem mir jetzt nicht mehr einleuchtenden 
Grund davon ausgegangen, daß du eine "gerade" Strecke zurücklegst...

Autor: Andreas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Oliver,

genau das ist das Problem. Bei einer geraden Strecke würde der Fehler 
erträglich sein, aber durch das Aufaddieren entsteht ein relativ großer 
Fehler. Bin gerade auf der Suche nach Fixed-Point-Berechnungen für 
sin/cos/asin.

mfg
Andreas

Autor: Philipp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist jetzt nur eine Idee ohne zu wissen ob es hier was bringt, aber 
vielleicht sollte man sich die Taylor Reihen der einzelnen Funktionen 
mal ansehen und gucken ob man die Formel dann noch etwas vereinfachen 
kann.

Gruß Philipp

Autor: Andreas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Philipp,

danke für den Tipp. Bin gerade dabei, dass ich sin/cos für Fixed-Point 
implementiere. +, -, *, / und abs() habe ich schon.

mfg
Andreas

Autor: Philipp Co (ba4_philipp)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fein :) Kannst du uns dann auch an den Ergebnissen teilhaben lassen? 
Habe auch noch vor mit dem GPS Kram rumzuspielen.

Gruß Philipp

Autor: Andreas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

hab jetzt ziemlich viel Zeit investiert, um eine höhere Genauigkeit zu 
erreichen. Leider ohne Erfolg. Ich habe in FixedPoint (8.24) 
sin/cos/sqrt implementiert, aber trotzdem reicht die Genauigkeit nicht 
für die Berechnung kleiner Wegstrecken aus. Bei einer Distanz von 
mehreren km ist es kein Problem. Ist der Abstand aber kleiner 10m, so 
kommt bei den Berechnungen immer 0 raus.
Wenn man zu Fuß unterwegs ist, wird man pro Sekunde (GPS-Daten kommen 
1x/s) nicht viel Meter zurücklegen. Somit habe ich als Summe der 
Wegstrecke immer 0.

Jetzt ist die Frage, ob ein anderer Compiler double precision 
unterstützt. Vielleich IAR oder so?

Hat da jemand Erfahrung damit?

mfg
Andreas

Autor: Michael Wilhelm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
IAR hat einen extra Schalter für 64 bit Double. Hab aber damit noch 
nicht gearbeitet.

MW

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den GCC selbst auf 64-bit-double zu bringen, ist sicher auch gar kein
großer Akt.  Allerdings müsste sich eben jemand hinsetzen und eine
libm.a für 64 bit FP bauen.

Autor: Reiner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Bei einer Distanz von mehreren km ist es kein Problem. Ist der Abstand 
aber kleiner 10m, so kommt bei den Berechnungen immer 0 raus."

Was benutzt Du denn für ein GPS.  Normalerweise liegt der 
Positionsfehler bei GPS im günstigsten Fall bei 15m, kann aber leicht 
auch mal bis >50m hochgehen.  Differential-GPS geht runter bis 1-3m 
erfordert aber einen zusätzlichen terrestrischen Empfangskanal.

Wo liegt also das Problem mit Abständen von 10m?

R.

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
15-50 m? Da hast du aber einen sehr schlechten Empfänger. Beim SIRF III 
sieht der Fehler unter guten Empfangsbedingungen ungefähr so aus:
http://www.pocketnavigation.de/pictures/article/3483_1.jpeg

Autor: Andreas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Reiner: das merkt man auch, wenn der Empfänger am selben Ort liegt, 
aber lt. Koordinaten die Position sehr stark abweicht (hatte schon ca. 
50m bei schlechterem Empfang!).

Laut Rückrechnung ergibt sich bei einer Differenz von 1m eine Änderung 
der Longitude von 0,00000952". Da ich aber nur 0,0001" Auflösung habe, 
habe ich sowieso ein Problem...

mfg
Andreas

Autor: Francesco Na (franceso-)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
8.24 kannst du nur nutzen, wenn du die 360 Grad in 256 umrechnest, inkl.
den Nachkommastellen. Dies kann unter umstaenden die Berechnungen sehr
beschleunigen. Ich habe das mit fixed-point mal gemacht, mit einer 
multiplication sowie ein paar shifts/additionen, fuer die Rundungen.
Grundsaetzlich habe ich damals 16.16 Float genommen, auch weil ich
sin usw. im bereich von 0-1 hatte (16bit table lookup+interpolation).
Habe aber auch ein Scaling gemacht, aber das war Applikationsspezifisch.

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Jetzt ist die Frage, ob ein anderer Compiler double precision
> unterstützt. Vielleich IAR oder so?

Der macht das problemlos und rechnet sehr schnell.

> Allerdings müsste sich eben jemand hinsetzen und eine
> libm.a für 64 bit FP bauen.

Das macht bekanntlich niemand, da 'float' in 'Fachkreisen' immer wieder 
schlechtgeredet wird und 'double' sowieso niemand braucht.
GPS ist nun mal ne Anwendung, wo man sich nicht mehr um 'double' 
herummogeln kann.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael wrote:

>> Allerdings müsste sich eben jemand hinsetzen und eine
>> libm.a für 64 bit FP bauen.

> Das macht bekanntlich niemand, da 'float' in 'Fachkreisen' immer wieder
> schlechtgeredet wird und 'double' sowieso niemand braucht.

Quark.  Es gibt hinreichend viele Requests dafür, nur keinen, der sich
bislang der Aufgabe hätte annehmen wollen.

Autor: Francesco Na (franceso-)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wiso nimmst du nicht FP, auch 64bit FP wird von GCC unterstützt.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> auch 64bit FP wird von GCC unterstützt.

Auf einem AVR?
Das wär ja ganz was Neues.

(Wenn FP Floating Point heissen soll)

Autor: Francesco Na (franceso-)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, fixed point,

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie sieht hier die Unterstützung aus?
Datentypen + Operationen
Das wäre äusserst nützlich, wenn man da keine
externen Libraries brauchen würde.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab ich auch noch nie davon gehört. Irgendwo auf meiner Platte rotiert 
aber noch ein angefangenes Fixedpoint-Klassentemplate für avr-g++ mit 
per Template-Argument wählbarer Anzahl an Vor- und Nachkommabits. Gips 
aber keine trigonometrischen Funktionen für, und die Klasse ist auch 
weder fertig, noch getestet. Muss ich mal bei Gelegenheit dran 
weiterbasteln.

Autor: Andreas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Francesco Na: wo finde ich diese Module? Wenn das implementiert wäre, 
wäre das sehr hilfreich.

Danke für die Infos.

mfg
Andreas

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Quark.  Es gibt hinreichend viele Requests dafür, nur keinen, der sich
> bislang der Aufgabe hätte annehmen wollen.

Das ist ja auch kein Wunder. Wenn hier (Forum) ein Problem auftritt, das 
sich einfachst mit 'float' lösen ließe, wird gleich geschrieen, daß man 
das nicht machen darf, weil es viel zu langsam sei, .....
Man nehme gefälligst 'int' und schlimmstenfalls 'long' und skaliere bis 
zum Abwinken.
Das ist keine Motivation für irgendeinen , die Grundrechenarten als 
'double' zu implementieren. Für sin(), cos(), usw. gib es ja die 
entsprechenden Routinen in C, mit recht effizienten Reihen.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael wrote:

> Das ist keine Motivation für irgendeinen , die Grundrechenarten als
> 'double' zu implementieren. Für sin(), cos(), usw. gib es ja die
> entsprechenden Routinen in C, mit recht effizienten Reihen.

Eben um die Implementierung dieser Routinen ging es mir aber.  Die
gibt es nicht ,,in C'', sondern die müsste jemand für avr-libc's
Mathematikbibliothek in 64 bit implementieren.  Andernfalls wäre das
mögliche GCC-Feature ziemlich sinnfrei.  Die Implementierung des
GCC-Features trau ich mir beinahe zu (ist letztlich ein Mischmasch
zwischen 64-bit int und 32-bit float), aber eine effiziente Reihe für
den AVR zu entwickeln ist jenseits dessen, was ich aus dem Handgelenk
schüttele.  (Die GCC-Implementierung bietet natürlich auch noch
genügend Brot in den Details, man will schließlich wohl am Ende einen
Schalter -mdouble32 haben analog zu -mint8.)

Diejenigen, die potenziell in der Lage sind, obiges zu erledigen,
werden sich kaum vom gelegentlichen Gequake ,,double nimmt man einfach
nicht'' abhalten lassen.  Eher von der fehlenden Zeit, das anzugehen.

Autor: Michael (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@Jörg

Ist es dies, was Du bräuchtest ?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Naja, letztlich sollte es schon für den AVR optimiert sein.  Wenn
ich mir das so angucke fürchte ich, dass das ein ziemlicher Klopper
wird.  Ich häng dir mal zum Vergleich die jetzige Implementierung
von atan2() der libm aus der avr-libc an.

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klopper hin, Klopper her. Die uralte Routine habe ich auf die Schnelle 
gefunden. Bei anderen GNU-Quellen hatte ich auch mehr C-Quellen für 
trigon.+andere Funktionen gefunden, allerdings nicht mehr aktuell auf 
der Platte verfügbar. Das wird sich alles wiederfinden lassen.

Um sich nicht gleich Knüppel zwischen die Beine zu werfen, würde ich 
vorschlagen, je nach Compiler-Schalter entweder nur 32bit oder nur 64bit 
rechnen zu lassen: gleiche Größe für 'float' und 'double'.
Ferner wird man einen Prozessor mit wohl 32k Flash benötigen. Wenn ich 
meine Mega128-Programme ansehe, da ist Platz im Flash noch und nöcher. 
Und wenn ein sin() vielleicht 2-3ms dauert, wer es braucht, kann damit 
leben. Kopfrechnen dauert länger.


Dazu bräuchte man
1. die Grundrechenarten einschließlich Rundung und Vergleichsoperationen
2. eine Compilerversion, die alle float/double mit 64bit verarbeitet.
3. eine libm64.a, die die notwendigen Funktionen zur Verfügung stellt.

Punkt 1 müßte in Assembler erledigt werden, da hiervon die 
Verarbeitungsgeschwindigkeit maßgeblich abhängt. Die Routinen sollten 
rekursiv und reentrant verwendbar sein.
Punkt 2 müßte in der Compilerquelle angepaßt werden.
Punkt 3 müßte die C-Quellen für alle Funktionen durchnudeln und eine lib 
erzeugen.

Gretchenfrage: wer macht Punkt 1 ?

Autor: Andreas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für eure interessanten Ideen. Ich habe versucht, die Berechnung 
mit FixedPoint (64 Bit) zu lösen. Doch das scheitert an mehreren 
Punkten:

1. ich bräuchte für *, / einen 128 Bit Datentyp, oder aufwändige 
Schiebeoperationen
2. die Implementierung in C ist extrem (!!) speicherintensiv. Ein 
ATmega32 reicht hier bei weitem nicht aus. Implementierung in Assembler 
ist mir zu mühsam.
3. Kosten für anderen Compiler sind zu hoch

Deshalb werde ich einfach einen anderen Controller einsetzen, dessen 
Compiler einen echten double unterstützt (Renesas M16C). Den haben wir 
im Haus und kostet somit nichts.

mfg
Andreas

Autor: Detlef _a (detlef_a)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Wegen Numerikproblemen den Mikrocontroller wechseln? Bißchen 
zweifelhaft, die Strategie.

Du machst in Deiner Formel asin(sqrt(sin . Ich nehme an, daß das 
numerisch ungünstig ist. In
Beitrag "Re: GPS - MOUSE - MINI- NAVIGATOR (Assembler) ATmega8" habe ich mal nen 
Excelsheet gepostet, dessen Berechnungsmethode vielleicht numerisch 
günstiger ist.

Michaels atan2.c und Jörgs atan2.s sind nicht fair vergleichbar, weil in 
atan2.c der atan selbst mitberechnet wird, atan.c selbst ist ne 
Vorverarbeitung, welche den atan selbst als Funktion nur aufruft.

Für die Freunde des atan2: angehängt ne C-Routine, die aus 2 short 
Real/imag einen short mit Cordic nen Winkel macht. Genau wie sau und hat 
für meine Zwecke immer gelangt.

Cheers
Detlef

Autor: Andreas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Detlef,

danke für die Infos. Der Wechsel des Controllers ist kein Problem, da 
ich noch in der Evaluierungsphase bin und Librarys (RS232, etc.) für 
beide Controller habe. Mal schauen, ob nach der Machbarkeitsstudie ein 
Go für das Projekt rauskommt...

mfg
Andreas

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.