Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Kompass 2D (https://www.delphipraxis.net/183553-kompass-2d.html)

schand99 19. Jan 2015 14:32

Kompass 2D
 
Hallo,

versuche zur Zeit einen Kompass für mein Handy zu programmieren, dazu verwende ich die Heading X/Y/Z Werte des integrierten Magnetsensors. Leider habe ich aber große Schwierigkeiten den 3D-Vektor so auf das Handy-Display umzurechnen, dass dieser auch bei schräger Haltung des Gerätes noch nach Norden zeigt. Meine App funktioniert nur wenn das Smartphone schön flach auf dem Tisch liegt :pale:
Hätte jemand einen Tipp wie man das lösen könnte?

Danke,

Medium 19. Jan 2015 15:04

AW: Kompass 2D
 
Das sollte eigentlich erst dann ein Problem sein, wenn das Handy exakt senkrecht gehalten wird - bzw. so, dass der Vektor genau "durch" das Handy geht. Das lässt sich dann nicht mehr sinnvoll darstellen. Ansonsten musst du doch einfach nur den Vektor nehmen, und ihn in die XZ-Ebene projezieren (angenommen Nord=Z und X=Bildschirm-X), und ggf. noch auf eine fixe Länge skalieren fürs Zeichnen. Die Projektion ist da denkbar simpel: Einfach die Y-Komponente weg schmeissen, und Z dafür in den 2D Vektor einsetzen.

schand99 19. Jan 2015 15:19

AW: Kompass 2D
 
Wenn Du das so schreibst klingt das einfach, nur leider bekomme ich es nicht hin.

Den Quellcode für 2D hab ich hier im Forum gefunden und etwas angepasst. Muss aber leider einräumen dass ich es nicht schaffe das HeadinZ so einzubauen dass ein Pfeil am Display halbwegs brauchbar nach Norden zeigt.

procedure GetWinkel()
begin
if Kompass.Sensor.Started = True then
Begin
if (Kompass.Sensor.HeadingY > 0) then
Winkel := 90 - arcTan(Kompass.Sensor.HeadingX / Kompass.Sensor.HeadingY) * 180 / PI
else if (Kompass.Sensor.HeadingY < 0) then
Winkel := 270 - arcTan(Kompass.Sensor.HeadingX / Kompass.Sensor.HeadingY) * 180 / PI
else if (Kompass.Sensor.HeadingY = 0) and (Kompass.Sensor.HeadingX < 0) then
Winkel := 180
else if (Kompass.Sensor.HeadingY = 0) and (Kompass.Sensor.HeadingX > 0) then
Winkel := 0;
end;
Winkel:=Abs(Winkel-360);
End;

jfheins 19. Jan 2015 19:54

AW: Kompass 2D
 
Für sowas gibt es eigentlich die arctan2 Funktion.
Und zu dem Zeitpunkt, den du da hast, ist es bereits ein 2D-Vektor.

Möglicherweise ist auch der Kompasssensor nicht gut kalibriert, der kann sich durchaus "von selbst" verstellen und muss dann ggf. wieder kalibriert werden. Insbesondere wenn er mal an einem Magnetfeld war oder Eisenstücke in der Nähe sind.

Namenloser 19. Jan 2015 21:15

AW: Kompass 2D
 
Wie zeichnest du denn?

Ich würde empfehlen, mit Vektoren zu arbeiten und Winkel, wo es nur geht, komplett zu vermeiden. In Programmen mit Winkeln zu arbeiten ist immer sehr umständlich und außerdem langsam. Dazu kommen noch Probleme wie 360° = 0°. Meine wärmste Empfehlung: Lerne Vektorrechnung (Analytische Geometrie)! Kommt leider in der Schule viel zu kurz bzw. erst ziemlich spät. Aber mein Leben ist dadurch so viel einfacher geworden...

Um mal am Kompass-Beispiel zu zeigen: Ich nehme mal an, um den Zeiger zu zeichnen hast du irgendwo sowas stehen wie
Delphi-Quellcode:
LineTo(Mitte.X + cos(Winkel)*Nadellänge, Mitte.Y + sin(Winkel*Nadellänge)
. Das ist im Grunde von hinten durch die Brust ins Auge, weil du wahrscheinlich erst aus einem Vektor den Winkel gemacht hast, nur um dann den Winkel mit sin/cos wieder in einen Vektor zurückzuverwandeln.

Dabei braucht man den Winkel gar nicht. Sagen wir dein (2D-)Vektor heißt V und der zugehörige Winkel φ. Es gilt (immer): V.X = cos(φ) * Vektorlänge und V.Y = sin(φ) * Vektorlänge. Wenn du jetzt einen Vektor mit der Länge 1 haben willst, der in die gleiche Richtung zeigt, dann kannst du das ganz einfach, indem du die V.X und V.Y jeweils durch die Vektorlänge (Pythagoras: Länge = Sqrt(V.X² + V.Y²)) dividierst. Was kommt nun dabei raus? Klar: Ein neuer Vektor V’ mit V’.X = cos(φ) und V’.Y = sin(φ) (den Schritt nennt man übrigens auch normalisieren, und das Ergebnis ist ein sogenannter Einheitsvektor). Ja, und damit ist es jetzt ganz einfach, die Kompassnadel zu zeichnen:
Delphi-Quellcode:
LineTo(Mitte.X + V’.X*Nadellänge, Mitte.Y + V’.Y*Nadellänge
. Und wir haben kein einziges mal Sinus, Cosinus oder Arctan gebraucht. Deine ganze GetWinkel-Funktion wird überflüssig.

Jetzt gibt es natürlich noch ein kleines Problem: Der Vektor von deinem Sensor hat 3 Dimensionen. Du kannst aber leicht deinen gewünschten 2D-Vektor daraus berechnen, indem du eine der Komponenten X, Y oder Z einfach weglässt. Das hat Medium schon beschrieben.

schand99 20. Jan 2015 14:50

AW: Kompass 2D
 
Muss dem was "Namenloser" geschrieben hat zustimmen. Einen Vektor erst in einen Winkel umrechnen und nachher zum Zeichnen des Vektors dann wieder aus dem Winkel einen Vektor berechnen wäre tatsächlich ein unnötiger Umweg.
Leider benötige ich den Winkel für nachfolgende Berechnungen (Geocaching, möchte mir selbst eine App bauen die mir Richtung und Abstand zum Zielort anzeigt).
Aber dafür müsste ich es erstmal schaffen eine Kompassnadel zu zeichnen die auch halbwegs brauchbar nach Norden zeigt. Und da liegt das Problem, ich schaffe es nicht aus den Werten HeadingX, -Y und -Z eine brauchbare Kompassnadel zu zeichnen. Das simple Weglassen eines der Heading-Werte ist leider nicht die Lösung.
Die Heading-Werte ergeben zwar einen Vektor in der Einheit Tesla, allerdings blicke ich noch nicht genau durch wie die Werte zu interpretieren sind. Wie bereits geschrieben funktioniert der Kompass wenn das Smartphone flach auf dem Tisch liegt. Wird es aber um eine Achse leicht geneigt, dann stimmt die Richtung nicht mehr.
Es wäre naheliegend einfach HeadingZ zu ignorieren. Aber HeadingY eiert so seltsam rum dass mir so schön langsam die Lust am Basteln vergeht :evil:

Medium 20. Jan 2015 15:06

AW: Kompass 2D
 
Ohne das vor sich zu sehen, finde ich es gerade etwas schwierig sich genau vorzustellen was da wo wie schief laufen könnte. Hast du ggf. eine Möglichkeit, ein Video von der bisherigen Nadel auf deinem Handy zu machen, wie du es ein wenig bewegst? (So, dass man erkennen kann wie du es bewegst.) Auf Youtube oder so am besten.

Weisst du 100%ig welche der 3 Achsen Nord/Süd bezeichnet? Nicht, dass du genau diese mit Z weggelassen hast. Das würde das Herumeiern vielleicht erklären können. Und wenn alle Stricke reißen: Es gibt auch durchaus Handys, deren Magnetsensor nicht ganz so pralle ist. Hast du schon mal eine andere Kompass App probiert? Können die das besser mit deinem Handy?

Namenloser 20. Jan 2015 15:31

AW: Kompass 2D
 
Müsste eigentlich so funktionieren meiner Meinung nach. Könnte mir höchstens vorstellen, dass der Heading-Vektor entgegen unserer Annahme nicht relativ zum Display ist, sondern die Neigung des Displays schon herausgerechnet ist.

schand99 20. Jan 2015 15:51

AW: Kompass 2D
 
Hier ein mega Film: http://80.247.70.136/downloads/cmps.zip
Die App läuft auf einem Samsung Galaxy S3 mini (und ruckelt^^) genauso schräg wie auf einem Sony Xperia Z3 Compact.
Wäre für jeden Tipp dankbar.

Berechne jetzt so, die Variablen HeadX, -Y und -Z sind so deklariert dass sie auch in anderen Funktionen sichtbar sind.

procedure TStartup.Timer2Timer(Sender: TObject);
Var
Vek:Single;
begin
if Kompass.Sensor.Started = True then
Begin
HeadX := Kompass.Sensor.HeadingX;
HeadY := Kompass.Sensor.HeadingY;
HeadZ := Kompass.Sensor.HeadingZ;
Vek := Sqrt(Power(HeadX,2) + Power(HeadY,2));
HeadX:=HeadX/Vek;
HeadY:=HeadY/Vek;
end;
End;

Irre simpel da mit HeadX und HeadY gezeichnet wird, aber leider sehr stark lageabhängig und somit nutzlos.

Medium 20. Jan 2015 15:59

AW: Kompass 2D
 
Dem Video nach würde ich wirklich annehmen, dass Z die Nord/Süd-Achse ist. Zumindest wenn mich mein räumliches Vorstellungsvermögen (und das gedankliche de-projezieren :stupid:) nicht völlig verlassen hat. Probier doch einfach mal, was daraus wird wenn du Y oder X weg lässt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:40 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz