Arkustangens



  • Hallo zusammen,
    ich möchte den arctan aus einem Sinus- und einem Cosinus-Wert bestimmen, dazu übergebe ich an eine Funktion die zuvor berechneten Werte áus einer Sinus- und Cosinus-Funktion.

    arctan= tan^-1 --> arctan= (sin/cos)-1 --> arctan= cos/sin

    float atan(float alpha)
    {
    float arctan;
    arctan = ((cosF(alpha)) / (sinF(alpha)));
    return arctan;
    }

    Ich habe mir die Werte über einen großen Bereich in ein .txt-File geschrieben und musste leider feststellen, dass nur Murks bei der berechnung entsteht.
    Hat jemand einen Tipp für mich?
    Ich hoffe ich konnte genug Informationen liefern.
    Danke im voraus



  • Die Funktionen aus C99 heißen sinf/cosf und nicht sinF/cosF.
    Nehme einen Debugger zu Hilfe bevor du die Daten in eine Datei schreibst.
    Außerdem gibt es bereits die C89-Funktion atan, welche den arctan liefert.
    Mit C99 gibt es die float/long double Variante davon:

    #include <math.h>
    double atan(double x);
    float atanf(float x);
    long double atanl(long double x);
    


  • MrChipsy schrieb:

    arctan= tan^-1 --> arctan= (sin/cos)-1 --> arctan= cos/sin

    Das ist vollkommen falsch. Das 1^{-1} steht hier für die Umkehrfunktion, nicht für den Kehrwert. Der Kehrwert des Tangens ist der Cotangens, das ist etwas vollkommen anderes als der Arcustangens.



  • Meine Funktionen heißen so, ich habe nicht die aus C99 verwendet.

    Stimmt, das ist der Cotangens.
    Wie berechne ich den Arcustangens aus nem Sinus und nem Cosinus?
    Ich darf leider keine Taylor-Reihe oder die math.h benutzen.
    Im Netz gibt es eine Näherungsformel. Diese kann ich allerdings auch nicht benutzen, da ich keine Wurzeln und Potenzen bilden darf.



  • Was darfst du denn überhaupt? Und was willst du überhaupt machen? Was hast du gegeben und was ist gesucht?

    Du schreibst z.B. «dazu übergebe ich an eine Funktion die zuvor berechneten Werte áus einer Sinus- und Cosinus-Funktion.» Woraus sind die Werte denn berechnet? Normalerweise wäre das ja der Winkel, also der Arcustangens, wodurch sich das Problem in Luft auflösen würde.



  • Suchst du evtl. nach CORDIC



  • Es ist folgendermaßen:
    Ich habe 16 Zwischenwerte mit Hilfe der Sinusfunktion aus der math.h in einer Initfunktion berechnet und in einer Tabelle gespeichert. Diese Zwischenwerte decken den Sinus im Bereich von 0 bis PI/2 ab.
    Mit diesen konnte ich nun die Restwerte des Sinus und durch eine Addition um PI/2 auch den Cosinus berechnen.
    Liegt jetzt ein Winkel an(wird von einem Doppelintegrator übergeben) , wird so die aktuelle Position bestimmt.
    Mit den Werten für Sinus und Cosinus muss nun der Arcustangens gebildet werden.

    --Doppelintegrator-----
    |
    -------- |----------
    | |
    Sin Cos
    | |
    ----Arcustangens----
    |

    Wichtig ist nur, dass ich keine Funktion der math.h und keine Reihenentwicklung nutze(ausserhalb der Init).



  • Na Super, das Bild hat sich leider verschoben.

    ---Doppelintegrator-->Sin/Cos--->Arcustan


  • Mod

    MrChipsy schrieb:

    Wichtig ist nur, dass ich keine Funktion der math.h und keine Reihenentwicklung nutze(ausserhalb der Init).

    Und was ist mit der Integraldefinition des Arcustangens? Das wäre streng genommen keine Reihenentwicklung. Ansonsten hätte ich noch arctan(x)=arcsin(xx2+1)\arctan(x) = \arcsin\left(\frac {x}{\sqrt{x^2+1}}\right) zu bieten. Dafür müsstest du deine Sinustabelle umkehren. Aber die Wurzel ist natürlich ein ganz neues Problem.

    Ansonsten klingt das nach Anfängerunsinn: Was immer du mit dem Arcustangens willst, du brauchst zwischendurch sicher nicht den Sinus und Cosinus des Winkels, sondern kannst das was du willst direkt aus dem Winkel berechnen.



  • Der Arkustangens IST der Winkel.
    (ggf. nach einer Bereichsanpassung auf (π2,π2)(-\frac{\pi}{2},\frac{\pi}{2}))

    Aus Sinus und Cosinus kannst du höchstens den Tangens oder Cotangens errechnen.



  • MrChipsy schrieb:

    Na Super, das Bild hat sich leider verschoben.

    Dagegen gibt es die Code oder cpp Tags (Text markieren und einen der Buttons unter den 🙂 😃 😉 😞 :p drücken)

    Kommst du an den Wert ran, der in den Doppelintegrator rein geht?

    Und brauchst du nicht eigentlich den atan2 ?



  • wenn der den winkel schon hat und nen sinus und nen cosinus berechnen kann, dann braucht er den arctan nicht, denn dann hat er den winkel schon.
    siehe post von bashar



  • merk0r schrieb:

    wenn der den winkel schon hat und nen sinus und nen cosinus berechnen kann, dann braucht er den arctan nicht, denn dann hat er den winkel schon.

    Ach



  • Ich komme leider nicht an den Eingangswert des Doppelintegrators ran.
    Der Ausgangswert des Doppelintegrators läuft zum einen in den Sinus Cosinus Generator, zum anderen auch in einen Quantisierer.
    Aus der Addition des quantisierten Wertes und dem ATAN Wert vom Sinus Consinus Generator soll dann wieder der Winkel entstehen.

    Achso und der Satz mit dem Anfängerunsinn:
    Ja, ich bin Anfänger und das ist die Aufgabe die mir gegeben wurde um C zu lernen.


  • Mod

    Und was ist mit den schon genannten CORDIC oder der Integraldefinition? Technisch gesehen sind das keine Reihenentwicklungen (Reihenentwicklungen sind sowieso etwas für die Theorie und nicht sehr selten praxistauglich). Vielleicht kann man sich auch ein passendes Newtonverfahren ausdenken. Für die Wurzel beim integral kannst du auf jeden Fall ein Newtonverfahren nehmen, 2-3 Iterationen reichen meistens. Aber guck dir zuerst einmal CORDIC an. Oder wenn dir das zu schwer ist, mach einen weiteren Lookup-Table mit Interpolation (aber großartig anders ist CORDIC auch nicht). Oder wenn du es gerne optimiert haben möchtest, dann guck dir mal das hier an:
    http://www.electronics.dit.ie/staff/aschwarzbacher/research/ecs99.pdf



  • MrChipsy schrieb:

    Ich komme leider nicht an den Eingangswert des Doppelintegrators ran.

    Das wäre ja auch die Winkelbeschleunigung, non? Du brauchst den Ausgangswert des Doppelintegrators.



  • Ich habe nochmal mit meinem Betreuer gesprochen und jetzt kann ich den CORDIC benutzen. Ich soll damit allerdings dann ATAN2(oder ARCTAN2) bestimmen.



  • MrChipsy schrieb:

    Ich habe nochmal mit meinem Betreuer gesprochen und jetzt kann ich den CORDIC benutzen. Ich soll damit allerdings dann ATAN2(oder ARCTAN2) bestimmen.

    Ist ja auch sinnvoller. Mit dem atan bekommst du ja nur den halben Kreis.
    Beachte aber auch die Reihenfolge der Parameter von der Funktion (atan2) aus der Standardbibliothek.
    Du solltest es nicht anders machen.



  • Ich muss das ganze erst einmal verstehen, weiss noch nicht so richtig wie ich den Cordic-Alg. umsetzen soll. Das ist fürn Neuling ein wenig heavy.



  • Ich habe einen vorhandenen Cordic-Alg implementiert und auf meine Vorgaben hin abgeändert, allerdings liefert dieser mir nur falsche Werte. Sieht jemand einen Fehler?

    float i_atan2(int x,int y) {
    
    	float result;    
        int k=0,xh=0,yh=0,winkel=0;
        int lmax = (0x1FFFFFFF); 
    
        // die Eingangswerte begrenzen
        while ( x>lmax || (-x)>lmax || y>lmax || (-y)>lmax ) {
          x = x >> 1 ;
    	  y = y >> 1; 
        }
    
        // initalisierung
      if(y>=0)
      {
        xh = y;
        yh = -x;
        winkel = -i_atantab[0];
      }
      else
      {
        xh = -y;
        yh = x;
        winkel = i_atantab[0];
      }
        x = xh;
        y = yh;
    
        // iteration maximum: i<31
        for (int i=0;i<15;i++) {
          if(y>=0)
          {
            winkel -= i_atantab[i];
            xh = x +( y >> k );
            yh = y -( x >> k );
          }
          else
          {
            winkel += i_atantab[i];
            xh = x -( y >> k );
            yh = y +( x >> k );
          }
          x = xh;
          y = yh;
          k = k+1;
        }
    
      result=(float)(-winkel);
    
      return (result);
     }
    

    Float als Rückgabewert war Vorgabe, weshalb ich am Ende den Winkel noch caste. Die Eingangswerte x und y sind die Werte aus meinem Sinus Cosinus Generator.


Anmelden zum Antworten