Hallo zusammen, ich entwicklte gerade aus Spass ein kleines GPS-Gerät bestehend aus einer seriellen GPS-Maus, einem ATmega-Board, einem Display & einer Matrixtastatur. Das ganze in C. Anzeige der GPS-Daten nach div. Kriterien klappt ohne Probleme. Jetzt wollte ich dem ganzen auch eine Waypoint-Navigation spendieren & befasse mich gerade mit der Entfernungsberechnung zwischen zwei Orten (je mit Länge/Breite angegeben). Dafür gibt es eine Formel, die die kürzeste Strecke zwischen zwei Punkten auf der Kugeloberfläche ausrechnet. Im folgenden seien: pLat = Breitenangabe Ort 1 pLong = Längenangabe Ort 1 pLat2 = Breitenangabe Ort 2 pLong2 = Längenangabe Ort 2 Das Ergebnis der Formel (1) w = sin(pLat)*sin(pLat2) + cos(pLat)*cos(pLat2)*cos(pLong2-pLong) eingesetzt in Formel (2) alpha = arccos(w) berechnet den Winkel zwischen der Geraden, die durch den Kugelmittelpunkt zum Ort 1 und der Geraden, die durch den Kugelmitelpunkt zum Ort 2 geht. alpha (wenn ich vorher schon mit dem Bogenmaß gerechnet habe) multipliziert mit dem Äquatorradius (Formel (2)) gibt dann die kürzeste Entfenung zwischen den zwei Orten auf der (erdgroßen) Kugeloberfläche. Das Problem ist nur, dass ich hier mit sin, cos & acos rechnen muß & das ganze auf dem ATmegaX wegen Dauer & Speicher wohl nicht zu empfehlen ist. Oder ist das nicht so wild? Oft wird davon gesprochen eine Tabelle mit Sinus-Werten anzulegen. Habe ich gemacht & zwar in 0,25° Schritten von 0-90°. Wenn ich die Berechnung (oder sollte ich lieber sagen den Lookup) von sin & cos über diese Tabelle laufen lasse, dann ist das Endergebnis der Berechnung äußerst ungenau. Bei der Entfernung fast Faktor 2! Das ganze wird deshalb so ungenau, weil das Ergebnis von Formel (1) ein Wert zw. (-1)-1 ist. Und wenn z. B. statt 0.99943 am Ende nur 0.9972 rauskommt, dann liefert das ganze eingesetzt in Formel (2) schon ziemlich unterschiedliche Werte. Damit ist die Entfernungsberechnung schon gescheitert :( Hat jemand eine Idee, wie man das Problem elegant lösen kann? Feinere Auflösung der Sinus-Tabelle (Nachteil: sehr viele Einträge). Interpolieren zwischen zwei Werten aus der Sinus-Tabelle. DOch die sin-, cos- & acos-Funktionen nutzen? Im voraus schon mal Danke... Christoph
eine Loesung habe ich nicht, aber in der Codesammlung gibt es einen langen Thread ueber eine GPS Software auf AVR.
Wie hast du die Sin/Cos Tabelle implementiert? Mit Float/Double? Vorschlag: Nimm doch int oder long. Also ohne Kommaanteil. Dann geht zum Beispiel die Tabelle nicht von -1 bis +1 sondern zB von -1000 bis +1000. Alles nur eine Sache der Skalierung am Ende deiner Rechnung.
Spar dir das mit den Tabellen, rechne erst mal in Fließkomma mit den trigonometrischen Funktionen die der Compiler bereitstellt. Sollte sich herausstellen dass das zu langsam ist (was ich bei den langsamen Aktualisierungsraten von GPS bezweifle), kannst du immer noch optimieren.
@Simon das Problem ist nicht, dass die Werte zw. -1 & 1 sind, sondern dass ich in meiner Tabelle nur diskrete sin-Werte für die Winkel 0, 0.25, 0.5 ... 90 habe. Wenn ich dann z. B. den sin-Wert für Winkel 44.8 haben will, dann kann ich bei der Einfachmethode aus der Tabelle den sin-Wert für Winkel 44.75 oder Winkel 45 nehmen. Beide sin-Werte sind verglichen mit dem tatsächlich berechneten sin-Wert ziemlich ungenau. Und wenn ich dann noch mit mehreren solcher ungenauer Werte weiterrechne (siehe Formel (1) z. B. Multiplikation), dann ist das Endergebnis sehr ungenau. Also, das Problem ist NICHT float/double, sondern die diskreten Werte, die mir die Tabelle bietet. Gruss Christoph
Du könntest linear interpolieren. Oder du könntest dir den ganzen Ärger erst einmal komplett sparen. Ein paar Sinus-Berechnungen pro Sekunde macht der AVR mit links.
wie wärs mit interpolation der tabellen-werte für die dazwischenliegenden werte?
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.