Forum: Compiler & IDEs C-Control PRO AVR32. Atan2 Funktion fehlt


von Olaf (Gast)


Lesenswert?

Hallo,

ich programmiere in CC-Basic mit der C-Controlpro IDE,
dort existiert leider die Funktion atan2 nicht (zur 
Kompasskursberechnung).

Ich würde diese Funktion gerne im Code mit Programmieren, werde aber aus 
der WIKI Beschreibung zur Atan2 Funktion nicht ganz schlau.

Kann mir jemand diese Funktion aufdröseln?
Gibt wohl 6 verschiedene Berechnungen je nach Wertigkeitvon X und Y.

Mit der Hoffnung auf ein wenig Hilfe
Olaf

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Welche Funktionen hast du denn als Ausgangsbasis verfügbar?

Im Wesentlichen besteht atan2 typischerweise aus einer Behandlung
der diversen Sonderfälle, gefolgt von einem Rückfall auf atan(y/x).

von Yalu X. (yalu) (Moderator)


Lesenswert?

Olaf schrieb:
> Kann mir jemand diese Funktion aufdröseln?

Was gibt es da aufzudröseln? Der Autor des Artikels hat das doch schon
getan.

> Gibt wohl 6 verschiedene Berechnungen je nach Wertigkeitvon X und Y.

Eben. Und genau diese musst du mittels einer IF-ELSEIF-ENDIF-Kette in
Basic umsetzen. Wo ist das Problem?

Hier ist per Pseudocode skizziert, wie atan2() in der AVR-Libc
implementiert ist:

avr-libc-2.0.0/libm/fplib/atan2.S:
1
...
2
/* float atan2 (float A, float B);  // A is y coord, B is x coord.
3
     The atan2() function calculates the arc tangent of the two variables
4
     A and B. It is similar to calculating the arc tangent of A/B, except
5
     that the signs of both arguments are used to determine the quadrant
6
     of the result. The atan2() function returns the result in radians,
7
     which is between -PI and PI (inclusive).
8
     
9
   Note:
10
     This implementation returns +0.0 in all four cases: +0/+0, +0/-0,
11
     -0/+0 and -0/-0.  Unlike x86 (GCC/Glibc).
12
13
   Algorithm:
14
  if (x == 0 && y == 0)    // A is y, B is x
15
      return 0
16
  if (x >= 0 && fabs(y) <= x)
17
      return atan(y/x)    // -Pi/4 .. +Pi/4
18
  if (y >= 0 && fabs(x) <= y)
19
      return Pi/2 - atan(x/y)  // +Pi/4 .. +3*Pi/4
20
  if (y <= 0 && fabs(x) <= fabs(y))
21
      return -Pi/2 - atan(x/y)  // -Pi/4 .. -3*Pi/4
22
  if (y >= 0)
23
      return Pi + atan(y/x)  // +3*Pi/4 .. Pi
24
  else
25
      return -Pi + atan(y/x)  // -3*Pi/4 .. -Pi
26
 */
27
...

Der eigentliche Programmcode ist in Assembler und hilft die vermutlich
nicht weiter.

von Olaf (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
vielen Dank.

Wenn ich avr-lib mit Wiki vergleiche
(soweit ich dazu in der Lage bin) fallen mir schon unterschiede auf:

aber ich versuche mal die Lib umzusetzen, sieht ja nicht so schwierig 
aus.
Falls die Ergebnisse nicht passen, wäre ich mal so frech meinen Code zu 
posten.

Danke
erst einmal

Auf die erste Frage: ich habe vom HMC5983 Die x,y,z Werte

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Olaf schrieb:
> Auf die erste Frage: ich habe vom HMC5983 Die x,y,z Werte

Sorry: die Frage bezog sich darauf, welche (trigonometrischen)
Funktionen deine Umgebung denn überhaupt bereitstellt.

Wenn du nicht nur kein atan2, sondern auch kein arctan überhaupt hast,
dann wird es natürlich drastisch aufwändiger.

von Olaf (Gast)


Lesenswert?

Hallo Jörg,
ja meine IDE arbeitet mit arctan (atan)

bekomme zur Zeit aber noch keine vernünftigen Werte.
Problem bei dem Code von Yalu ist,
dass bei mir die fabs Funktion Float ist, ich aber nur mit integer eine 
AND verknüpfung machen darf.......

sorry für so viel unwissen

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Olaf schrieb:
> dass bei mir die fabs Funktion Float ist, ich aber nur mit integer eine
> AND verknüpfung machen darf

Da steht ja auch "fabs(...) <Vergleichsoperator> <wasanderes>", und
das Resultat der Vergleichsoperation ist natürlich ein Boolescher
Wert.

von Olaf (Gast)


Lesenswert?

Hier nun mal mein Code:
Finde den Fehler :-)




If (datx = 0 And daty = 0) Then Kursrad = 0
     '___________________________________________________
     ElseIf (datx)>=0 And (fabs (daty)<= datx )Then
    Kursrad = atan(daty/datx)
    '________________________________________________________________

     ElseIf daty >=0 And (fabs(datx)<= daty)Then
      Kursrad = 1.5708 - atan(datx/daty)
     '______________________________________________________________

     ElseIf daty <=0 And (fabs(datx)<= fabs(daty)) Then
     Kursrad = -1.5708 - atan(datx/daty):
      '________________Fall 
4______________________________________________
      ElseIf daty>=0 Then Kursrad =3.1416 + atan(daty/datx):
      Else Kursrad = -3.1416 + atan(daty/datx)
      End If

von Olaf (Gast)


Lesenswert?

Olaf schrieb:
> Finde den Fehler :-)

Sollte nicht böse gemeint sein, sorry, aber ich bin schon am 
verzweifeln....

von Walter S. (avatar)


Lesenswert?

du könntest ja zumindest angeben wie sich der Fehler äußert

von Olaf (Gast)


Lesenswert?

Es scheint ein Teil der Formel nicht zu passen,
ich soll als Ergebniss Werte von - pi bis +pi bekommen.

Wenn ich mein Kompassmodul drehe bekomme ich in Teilkreisen von ca. 1/4 
Umdrehungen gute fließende Werte. dann bleibt das Ergebniss aber längere 
Zeit konstant. Obwohl meine Ausgangswerte x,y weiter verändern.

von Olaf (Gast)


Lesenswert?

DAs gleiche passiert übrigends auch wenn ich die Formel von Wiki (bild 
weiter oben) benutze

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Dann poste doch mal die Rohdaten zusammen mit deinem Ergebnis als
Tabelle (oder CSV-Datei).

von Olaf (Gast)


Lesenswert?

Hallo,
die Daten x,y, und TAN2 Ergebnis aus einer 360° Drehung (per Hand)
1
X= -38 Y= -156  ATAN2 Erg. :  1.815782
2
X= -38 Y= -156  ATAN2 Erg. :  1.815782
3
X= -38 Y= -156  ATAN2 Erg. :  1.815782
4
X= -33 Y= -108  ATAN2 Erg. :  1.892554
5
X= -33 Y= -108  ATAN2 Erg. :  1.892554
6
X= -33 Y= -108  ATAN2 Erg. :  1.892554
7
X= -33 Y= -108  ATAN2 Erg. :  1.892554
8
X= -249 Y= -392  ATAN2 Erg. :  2.356202
9
X= -249 Y= -392  ATAN2 Erg. :  2.356202
10
X= -249 Y= -392  ATAN2 Erg. :  2.356202
11
X= 2 Y= -593  ATAN2 Erg. :  1.567418
12
X= 2 Y= -593  ATAN2 Erg. :  1.567418
13
X= 2 Y= -593  ATAN2 Erg. :  1.567418
14
X= 2 Y= -593  ATAN2 Erg. :  1.567418
15
X= 215 Y= -558  ATAN2 Erg. :  1.107149
16
X= 215 Y= -558  ATAN2 Erg. :  1.107149
17
X= 215 Y= -558  ATAN2 Erg. :  1.107149
18
X= 215 Y= -558  ATAN2 Erg. :  1.107149
19
X= 390 Y= -365  ATAN2 Erg. :  0.000000
20
X= 390 Y= -365  ATAN2 Erg. :  0.000000
21
X= 390 Y= -365  ATAN2 Erg. :  0.000000
22
X= 441 Y= -111  ATAN2 Erg. :  0.000000
23
X= 441 Y= -111  ATAN2 Erg. :  0.000000
24
X= 441 Y= -111  ATAN2 Erg. :  0.000000
25
X= 441 Y= -111  ATAN2 Erg. :  0.000000
26
X= 311 Y= 93  ATAN2 Erg. :  0.000000
27
X= 311 Y= 93  ATAN2 Erg. :  0.000000
28
X= 311 Y= 93  ATAN2 Erg. :  0.000000
29
X= 311 Y= 93  ATAN2 Erg. :  0.000000
30
X= 95 Y= 176  ATAN2 Erg. :  1.570800
31
X= 95 Y= 176  ATAN2 Erg. :  1.570800
32
X= 95 Y= 176  ATAN2 Erg. :  1.570800
33
X= -40 Y= 147  ATAN2 Erg. :  1.570800
34
X= -40 Y= 147  ATAN2 Erg. :  1.570800
35
X= -40 Y= 147  ATAN2 Erg. :  1.570800
36
X= -40 Y= 147  ATAN2 Erg. :  1.570800
37
X= -218 Y= 85  ATAN2 Erg. :  2.677948
38
X= -218 Y= 85  ATAN2 Erg. :  2.677948
39
X= -218 Y= 85  ATAN2 Erg. :  2.677948
40
X= -218 Y= 85  ATAN2 Erg. :  2.677948
41
X= -283 Y= -37  ATAN2 Erg. :  2.999699
42
X= -283 Y= -37  ATAN2 Erg. :  2.999699
43
X= -283 Y= -37  ATAN2 Erg. :  2.999699
44
X= -283 Y= -37  ATAN2 Erg. :  2.999699
45
X= -235 Y= -315  ATAN2 Erg. :  2.356202
46
X= -235 Y= -315  ATAN2 Erg. :  2.356202
47
X= -235 Y= -315  ATAN2 Erg. :  2.356202
48
X= -173 Y= -246  ATAN2 Erg. :  2.356202
49
X= -173 Y= -246  ATAN2 Erg. :  2.356202
50
X= -173 Y= -246  ATAN2 Erg. :  2.356202

: Bearbeitet durch Moderator
von Yalu X. (yalu) (Moderator)


Lesenswert?

Olaf schrieb:
> die Daten x,y, und TAN2 Ergebnis aus einer 360° Drehung (per Hand)

Ich glaube, da laufen gleich mehrere Dinge schief:

1. Bei den Divisionen datx / daty bzw. daty / datx scheinen die
   Nachkommastellen abgeschnitten zu werden. Vermutlich sind beide
   Operanden Integer-Variablen, was dazu führt, dass auch das Ergebnis
   vom Typ Integer ist. Du müsstest mindestens einen der beiden
   Operanden in ein Single konvertieren, damit die Division ebenfalls
   Single ist und damit seine Nachkommastellen behält. Wie das geht,
   weiß ich nicht. Wenn dir nichts besseres einfällt, kannst du es mit

     1.0 * datx / daty

   versuchen, auch wenn das nicht sehr elegant ist.

2. Die Vergleiche, in denen die fabs-Funktion verwendet wird, scheinen
   so ausgeführt zu werden, also ob das fabs nicht vorhanden wäre. Statt

     fabs(datx) <= fabs(daty)

   wird also

     datx <= daty

   ausgewertet. Vielleicht hat fabs, das als Argument ein Single
   erwartet, ein Problem, wenn es stattdessen ein Integer bekommt.
   Eigentlich sollte der Wert in diesem Fall automatisch konvertiert
   werden, aber wer weiß ...

3. Schließlich scheint beim Ergebnis der gesamten Berechnugn das
   Vorzeichen verloren zu gehen, weswegen alle Ergebnisse nichtnegativ
   sind. Vielleicht wird der Wert richtig berechnet, und der Fehler
   geschieht erst bei der Ausgabe.

Wenn ich diese drei Probleme in einer anderen Programmiersprache
(Python) künstlich nachstelle, kommen tatsächlich exakt die von dir
aufgelisteten Ergebnisse heraus.

Falls du nicht weiterkommst, kannst du ja mal die an der Berechnung
beteiligten Operationen (Division, fabs, Vergleich, atan und die
Ausgabe) mit verschiedenen Operanden (Integer, Single, positiv und
negativ) einzeln testen,

- um zu sehen, und welchen Bedingungen die Fehler passieren, und

- um sicherzustellen, dass es sich dabei nicht um Compiler-Bugs handelt.

von olaf (Gast)


Lesenswert?

Danke für deine Mühe, ich werde deine Tipps die Tage mal versuchen 
umzusetzen.
Melde mich dann später nochmal.

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.