- Labornetzteil AliExpress         
Seite 6 von 7 ErsteErste ... 4567 LetzteLetzte
Ergebnis 51 bis 60 von 63

Thema: 1 Maussensor, Drehung berechnen

  1. #51
    Benutzer Stammmitglied
    Registriert seit
    07.10.2007
    Beiträge
    58
    Anzeige

    LiFePo4 Akku selber bauen - Video
    Ich habs geschafft: \/
    Jetzt habe ich einen funktionierenden Code zur berechnung der Drehung mit Hilfe von mare_crisiums Dokumentationen und .xls erstellt:
    (Falls ihr Verbesserungsvorschläge habt, bitte melden)
    Dazu sind 2 Funktionen nötig:
    -Eine zum Initialisieren der Variablen, welche beim Start des Roboters aufgerufen wird
    -Eine, welche immer nach einer kurzen Drehung die aktuelle Position auswertet.

    Also hier der Code (einfach in eine Header File kopieren und im Programm includieren)
    ACHTUNG: Die defines müssen an euren Maussensor angepasst werden. Zur näheren Beschreibung und zur Berechnung siehe in der Dokumentation von mare_crisium weiter vorn im Thread.
    Code:
    /*
    ###################################################
    27.09.08 - TurnAlgorithm.h
    ---------------------------------------------------
    Header File welche diverse Funktionen zum Berechnen
    der Drehung beinhaltet
    
    ###################################################
    */
    
    #include <stdlib.h>
    #include <math.h>
    
    //PI mit 2 multipliziert (= 360°)
    #define PI_DOUBLE 6.283185307179586476925286766559
    
    //PI mit 2 dividiert (= 90°)
    #define PI_HALF 1.5707963267948966192313216916398
    
    // Benötigte Variablen zur Berechnung
    #define TURN_ALGO_ALPHA 0.0336681 //Benötigter Wert zum Umrechnen von Ticks in mm
    #define TURN_ALGO_DIST 62.6 //Abstand zwischen Maussensor-Messpunkt und Roboter-Mittelpunkt in mm
    #define TURN_ALGO_MOUSE_ANGLE -1.62187951 //Fehlausrichtungswinkel der x-Richtung der Maus zur Längsachse des Roboters im Bogenmaß
    #define TURN_ALGO_COS_MOUSE_ANGLE -0.05106097 //cos(TURN_ALGO_MOUSE_ANGLE)
    #define TURN_ALGO_SIN_MOUSE_ANGLE -0.99869554 //sin(TURN_ALGO_MOUSE_ANGLE)
    
    /**
      * Initialisiert die Variablen, welche benötigt werden, um die Drehung zu berechnen
      * @param CurrX Beinhaltet die aktuelle X-Position des Sensors
      * @param CurrY Beinhaltet die aktuelle X-Position des Sensors
      * @param LastX Pointer auf die Variable mit der letzten X-Koordinate (übergabe an Funktion TurnAlgo_update)
      * @param LastY Pointer auf die Variable mit der letzten Y-Koordinate (übergabe an Funktion TurnAlgo_update)
      * @param Last_e_p_norm_x Pointer auf die Variable mit dem letzten Wert von e_p (normiert) x (übergabe an Funktion TurnAlgo_update)
      * @param Last_e_p_norm_y Pointer auf die Variable mit dem letzten Wert von e_p (normiert) x (übergabe an Funktion TurnAlgo_update)
      * @param Last_e_q_norm_x Pointer auf die Variable mit dem letzten Wert von e_q (normiert) x (übergabe an Funktion TurnAlgo_update)
      * @param Last_e_q_norm_y Pointer auf die Variable mit dem letzten Wert von e_q (normiert) y (übergabe an Funktion TurnAlgo_update)
      * @param turnAngle Pointer auf die Variable welche den Winkel beinhalten wird (übergabe an Funktion TurnAlgo_update)
      *
      */
    
    void TurnAlgo_init(int CurrX, int CurrY, int *LastX, int *LastY, double *Last_e_p_norm_x, double *Last_e_p_norm_y, double *Last_e_q_norm_x, double *Last_e_q_norm_y, double *turnAngle)
    {
        *LastX = CurrX;
        *LastY = CurrY;
        *Last_e_p_norm_x = 1.0;
        *Last_e_p_norm_y = 0.0;
        *Last_e_q_norm_x = 0.0;
        *Last_e_q_norm_y = 0.0;
        *turnAngle = 0.0;
    }
    
    /**
      * Wird nach jeder kurzen Drehung aufgerufen, um den neuen Winkel zu berechnen
      * @param CurrX Beinhaltet die aktuelle X-Position des Sensors
      * @param CurrY Beinhaltet die aktuelle X-Position des Sensors
      * @param LastX Pointer auf die Variable mit der letzten X-Koordinate (übergabe an Funktion TurnAlgo_update)
      * @param LastY Pointer auf die Variable mit der letzten Y-Koordinate (übergabe an Funktion TurnAlgo_update)
      * @param Last_e_p_norm_x Pointer auf die Variable mit dem letzten Wert von e_p (normiert) x (übergabe an Funktion TurnAlgo_update)
      * @param Last_e_p_norm_y Pointer auf die Variable mit dem letzten Wert von e_p (normiert) x (übergabe an Funktion TurnAlgo_update)
      * @param Last_e_q_norm_x Pointer auf die Variable mit dem letzten Wert von e_q (normiert) x (übergabe an Funktion TurnAlgo_update)
      * @param Last_e_q_norm_y Pointer auf die Variable mit dem letzten Wert von e_q (normiert) y (übergabe an Funktion TurnAlgo_update)
      * @param turnAngle Pointer auf die Variable welche den Winkel beinhalten wird (übergabe an Funktion TurnAlgo_update)
      *
      */
    void TurnAlgo_update(int CurrX, int CurrY, int *LastX, int *LastY, double *Last_e_p_norm_x, double *Last_e_p_norm_y, double *Last_e_q_norm_x, double *Last_e_q_norm_y, double *turnAngle)
    {
        double delta_x = (CurrX - (*LastX)) * (double)TURN_ALGO_ALPHA; //Delta X in mm
        double delta_y = (CurrY - (*LastY)) * (double)TURN_ALGO_ALPHA; //Delta Y in mm
        double delta_y_norm = delta_x * (double)TURN_ALGO_SIN_MOUSE_ANGLE + delta_y * (double)TURN_ALGO_COS_MOUSE_ANGLE; //Delta Y in mm mit berücksichtigung der Fehlausrichtung
        double delta_angle = delta_y_norm / (double)TURN_ALGO_DIST;
        
        double e_p_not_norm_x = (*Last_e_p_norm_x) + delta_angle * (*Last_e_q_norm_x); //e_p (nicht normiert) x
        double e_p_not_norm_y = (*Last_e_p_norm_y) + delta_angle * (*Last_e_q_norm_y); //e_p (nicht normiert) y
        double e_p_not_norm_sum = sqrt(pow(e_p_not_norm_x,2) + pow(e_p_not_norm_y,2)); //Betrag von e_p (nicht normiert)
        
        double curr_e_p_norm_x = e_p_not_norm_x/e_p_not_norm_sum;
        double curr_e_p_norm_y = e_p_not_norm_y/e_p_not_norm_sum;
        
        *LastX = CurrX;
        *LastY = CurrY;
        *Last_e_p_norm_x = curr_e_p_norm_x;
        *Last_e_p_norm_y = curr_e_p_norm_y;
        *Last_e_q_norm_x = e_p_not_norm_y * (-1);
        *Last_e_q_norm_y = e_p_not_norm_x;
        
        *turnAngle = atan2(curr_e_p_norm_y, curr_e_p_norm_x) * (-1); //Winkel im bereich von [-179,179]
        if (*turnAngle < 0)
            *turnAngle = PI_DOUBLE + *turnAngle;
        
    }
    Ich habe das alles so realisiert, dass der Drehfunktion die Variablen der Vorherigen dreh-berechnung als Pointer übergeben werden.

    In der TurnRobot funktion kann ich einfach einen Winkel übergeben, zu dem hingedreht werden soll, also nicht, um wieviel gedreht wird. Würde man der Funktion zu umschreiben, dass man übergibt, um wie viel gedreht wird, dann wäre die Fehlerwahrscheinlichkeit sehr viel höher.
    Man kann auch mal einfach Geradeaus fahren, und danach Drehen. Die absolute Winkelangabe sollte dann trozdem funktionieren.

    Ein Aufruf könnte dann wie folgt aussehen
    Code:
    int TurnAlgo_LastX;
    int TurnAlgo_LastY;
    double TurnAlgo_Last_e_p_norm_x;
    double TurnAlgo_Last_e_p_norm_y;
    double TurnAlgo_Last_e_q_norm_x;
    double TurnAlgo_Last_e_q_norm_y;
    double TurnAlgo_currAngle;
    
    //  -------------- Main-Funktion --------------
    int main(void)
    {
        /*###Initialisierungsphase###*/
        // ... eigene Initialisierungen
    
        TurnAlgo_init(0, 0, &TurnAlgo_LastX, &TurnAlgo_LastY, &TurnAlgo_Last_e_p_norm_x, &TurnAlgo_Last_e_p_norm_y, &TurnAlgo_Last_e_q_norm_x, &TurnAlgo_Last_e_q_norm_y, &currAngle);
    
        while(1)
        {
            //Hauptschleife
        }
    }
    
    
    /**
      *Dreht den Roboter zum angegebenen Winkel
      * @param degree Grad, auf die gedreht werden soll
      */
    void turnRobot(int endDegree)
    {
        int  startPos_X, startPos_Y;
        pan_getPos(&startPos_X, &startPos_Y);
        
        TurnAlgo_update(startPos_X, startPos_Y, &TurnAlgo_LastX, &TurnAlgo_LastY, &TurnAlgo_Last_e_p_norm_x, &TurnAlgo_Last_e_p_norm_y, &TurnAlgo_Last_e_q_norm_x, &TurnAlgo_Last_e_q_norm_y, &TurnAlgo_currAngle);
        
        double startAngle = TurnAlgo_currAngle;
            
        double endAngle = (M_PI * endDegree) / 180.0;
        
        //Winkel in Bereich von 0 bis 360° (= PI_DOUBLE) umrechnen
        while (endAngle >= PI_DOUBLE)
            endAngle -= PI_DOUBLE;
        while (endAngle <0)
            endAngle += PI_DOUBLE;
        
        
        
        double diff = endAngle - TurnAlgo_currAngle;
    
        
        //Gibt an, ob sich der Roboter gegen den Uhrzeiger (mathematischer Drehsinn) = 0 oder mit dem Urhzeiger = 1 dreht
        int turnDirection = 0;
        
        //Überprüfung, ob Differenz mehr als 180° (= PI), wenn ja, andere Drehrichtung verwenden, da dort der Weg kürzer ist.
        if (diff > M_PI)
        {
            turnDirection = 1;
            diff -=PI_DOUBLE;
        }
        else if (diff < M_PI*(-1))
        {
            turnDirection = 0;
            diff +=PI_DOUBLE;
        }
        else if (diff > 0)
            turnDirection = 0;
        else if (diff < 0)
            turnDirection = 1;
        else
        {
            return; //Nothing to do
        }
        
        
        int speedL;
        int speedR;
        
        if (turnDirection == 0) //Drehrichtung = 0
        {
            speedL = -245;
            speedR = 255;
        }
        else if (turnDirection == 1) //Drehrichtung = 1
        {
            speedL = 255;
            speedR = -245;
        }
    
        int  newPos_X, newPos_Y;
    
    
        //Schleife wird auch innerhalb unterbrochen, sobald der endAngle erreicht ist
        while (startAngle!=endAngle)
        {
            moveRobot(speedL, speedR, 3);
            pan_getPos(&newPos_X, &newPos_Y);
            
            TurnAlgo_update(newPos_X, newPos_Y, &TurnAlgo_LastX, &TurnAlgo_LastY, &TurnAlgo_Last_e_p_norm_x, &TurnAlgo_Last_e_p_norm_y, &TurnAlgo_Last_e_q_norm_x, &TurnAlgo_Last_e_q_norm_y, &TurnAlgo_currAngle);
            
        
            if (TurnAlgo_currAngle == endAngle)
                break;
            if (turnDirection == 0)
            {
                if ((startAngle < endAngle) && (TurnAlgo_currAngle >= endAngle))
                    break;                                                        //Beim startWinkel 170° abziehen, da es vorkommen kann, dass der TurnAlgo_currAngle den Winkel 259° anstatt 0° hat und dann unterbrochen werden würde 
                else if ((startAngle > endAngle) && (TurnAlgo_currAngle >= endAngle) && (TurnAlgo_currAngle < startAngle - 2.9670597283903602807702743064306)) //Bereich liegt über dem 4. und 1. Quartal
                    break;
            }
            else if (turnDirection == 1)
            {
                if ((startAngle > endAngle) && ((TurnAlgo_currAngle <= endAngle) || (TurnAlgo_currAngle > endAngle + M_PI)))
                    break;                                                        //Beim startWinkel 170° addieren, da es vorkommen kann, dass der TurnAlgo_currAngle den Winkel 1° anstatt 0° hat und dann unterbrochen werden würde 
                else if ((startAngle < endAngle) && (TurnAlgo_currAngle <= endAngle) && (TurnAlgo_currAngle > startAngle + 2.9670597283903602807702743064306)) //Bereich liegt über dem 4. und 1. Quartal
                    break;
            }
            
        }
    }
    Danke an alle die mitgeholfen haben.

    Edit: Code verbessert




    Edit 2 (Dez. 2014): PDF von mare_crisium zur Berechnung erneut hochgeladen: (siehe post #62):
    https://www.roboternetz.de/community...l=1#post609113
    Geändert von PRobot (03.12.2014 um 20:09 Uhr)

  2. #52
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    PRobot,

    prima ! Beim Durchsehen des Algorithmus (mit beschränkten C-Kenntnissen) ist mir nur aufgefallen, dass Du e_q_norm_y mit 0.0 initialisierst; der Startwert muss aber 1.0 sein.

    Auf die Variablen e_q_norm_x und e_q_norm_y kannst Du ganz verzichten, wenn Du schreibst

    double e_p_not_norm_x = (*Last_e_p_norm_x) - delta_angle*(*Last_e_p_norm_y)
    double e_p_not_norm_y = (*Last_e_p_norm_y) + delta_angle*(*Last_e_p_norm_x)

    Das ist eine mögliche, aber keine notwendige Vereinfachung des Programms.

    Freut mich, dass Du's hingekriegt hast. Berichte 'mal über die Testfahrten!

    Ciao,

    mare_crisium

    Edit: Fehler in Formel für e_p_not_norm_y korrigiert: Zeiger (*Last_e_p_norm_x) durch Zeiger (*Last_e_p_norm_y) ersetzt (Danke, für den Hinweis, SternThaler !

  3. #53
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018
    Guten Morgen zusammen.

    @mare_crisium
    e_q_norm_y mit 0.0 oder 1.0 initialisieren?
    Ich kann diese Variablen nicht finden? Meinst du die Variable Last_e_q_norm_y, die in der Funktion TurnAlgo_init() auf 0.0 gesetzt wird?

    Falls dein Vorschlag mit der Vereinfachung oben im Programm von PRobot schon enthalten ist, dann ist dort ein Unterschied zu deinem Vorschlag:
    Du mare_crisium schreibst:
    double e_p_not_norm_x = (*Last_e_p_norm_x) - delta_angle*(*Last_e_p_norm_y)
    Gefunden bei PRobot habe ich:
    double e_p_not_norm_x = (*Last_e_p_norm_x) + delta_angle * (*Last_e_q_norm_x)

    Und auch bei "double e_p_not_norm_y = ..." finde ich einen Unterschied.

    Ansonsten kann ich der Mathematik (leider) nicht mehr folgen.
    Nur bei deinen im letzten Post angegeben Excel-Diagramme bekomme ich in den Kopf, dass es sich um wunderbare Halbkreise handelt . Jubel, habt ihr gut gemacht.

    Lasst euch bloß nicht von meinem Geschreibsel stören. Wahrscheinlich ist das sowieso nicht relevant.
    Gruß Sternthaler
    Lieber Asuro programieren als arbeiten gehen.

  4. #54
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    62
    Beiträge
    5.799
    Blog-Einträge
    8
    Lasst euch bloß nicht von meinem Geschreibsel stören.
    Ist doch immer wieder nett etwas von dir zu lesen :)
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  5. #55
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    Einen schönen Sonntagmorgen!
    @ SternThaler,

    Ihr habt zwar noch Oktoberfest, aber deshalb musst Du Deine Mathekenntnisse nicht gleich unter die Moass stellen!

    Deine erste Anmerkung ist richtig: Ich meine "Last_e_q_norm_y".

    Der zweite Unterschied, den Du bemerkt hast, ist genau die Vereinfachung, die ich vorschlagen wollte: e_q_norm_x ist gleich (-1)*e_p_norm_y und e_q_norm_y ist e_p_norm_x. Erinnerst Du Dich: Das ist der Trick, mit dem man einen Vektor um +90° drehen kann . PRobot hat den Vorschlag noch nicht eingearbeitet.

    Zitat Zitat von Sternthaler
    Ansonsten kann ich der Mathematik (leider) nicht mehr folgen.
    Na, damit Du wieder Mut schöpfst, hänge eine neue Version des Algorithmus an, in der ich versucht habe, die Sache mit ein paar zusätzlichen Zeichnungen verständlicher zu machen.

    @ radbruch:
    Gönn' doch dem armen Haifisch auch mal ein Erfolgserlebnis!!

    Ciao,

    mare_crisium

    Edit: Anhang gelöscht wg. Upload-Quota

  6. #56
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    13.07.2004
    Ort
    bei Stuttgart
    Alter
    42
    Beiträge
    760
    hoi,
    also beim letzten bild stimmt irgendwas net ganz. sonst hab ich des ganze net wirklich durchgelesen. aber da es funktioniert scheint es au zu stimmen
    mfg jeffrey

  7. #57
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    jeffrey,

    danke für den Hinweis. Hab's ausgebessert.

    mare_crisium

  8. #58
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018
    Hai zusammen. (Wenn er denn mal was zu futtern bekommt? Ha, ha, ha.)

    @radbruch: Lass bitte, bitte den armen Smilie leben. Für den Hai spende ich mal ne Makrele.
    Und hier kann man sehen, dass die Beiden Freunde sind (so passiert auch der Makrele nix.): http://www.taucher.net/edb/Embudu_Vi...Atoll_b63.html
    (ca. 1/4 der Seite scrollen)

    Jetzt weiß ich wenigstens, warum ich dem Ganzen wohl nicht folgen konnte.
    Liegt vor allem nicht am Oktoberfest, da ich etwas weiter nördlich, recht dicht beim Liborifest, zu finden bin. Wir trinken hier Bier nicht im Moass, sondern in Massen . Und am Samstag war es aber mal wieder Wein mit Freunden.


    Mathe, und 90°-Drehung:
    Gut, dass du mare_crisium, noch mal deinen Koppelnavigations-Algorithmus mitschickst. Ich bin mir recht sicher, dass es sich bei deinem Vorschlag um die Formel (2.7) handeln müsste.
    Dann aber sollte doch die Berechnung bei deinem Vorschlag zum Ermitteln von e_p_not_norm_y mit:
    double e_p_not_norm_y = (*Last_e_p_norm_y) + delta_angle*(*Last_e_p_norm_x)
    erfolgen? Oder etwas doch nicht?
    Seht ihr nun warum ich lieber auf die Wiesen gehen sollte? Ich kann nämlich nur bei euch nachlesen was ihr so tolles macht, es aber nicht selber nachrechnen, so dass am Ende eben nur merkwürdige Hinweise kommen können. Die gebe ich euch natürlich auch dann in Moassen, selbst wenn ihr nicht danach fragt .

    Einen ruhigen, erfolgreichen Wochenbeginn wünscht euch
    Sternthaler
    Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken fischf_rwaterworld.jpg  
    Lieber Asuro programieren als arbeiten gehen.

  9. #59
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    Guten Morgen, zusammen!

    @Tierfreund SternThaler:
    hast recht: Es ist Formel (2.7) und den Fehler im alten Posting habe ich korrigiert.

    Wohnst Du wirklich in der Nähe von London? (London Interbank Borrowing Rate - Fest???)

    Ciao,

    mare_crisium

  10. #60
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018
    Na, wer ist denn noch alles wach?

    @LustigeIdeen-mare_crisium
    Ne, ab übermorgen nicht mehr. Nachdem ich einen Teil der letzten Überweisung einer Deu.Bank (KxW, oder so ähnlich) aus u s a habe umleiten können, werde ich nun auf so eine kleine Insel umziehen. Dort kann man hervorragend Fische und Smilies beobachten

    Nun aber erst einmal ein: Gute Nacht
    Sternthaler
    Lieber Asuro programieren als arbeiten gehen.

Seite 6 von 7 ErsteErste ... 4567 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen