Belohnungsfunktion für q Lernen an einem Roboter


7

Ich habe einen 2-Rad-Differentialantriebsroboter, den ich mit pid für die Steuerung des niedrigen Füllstands verwende, um der Linie zu folgen. Ich habe q learning implementiert , das Samples für 16 Iterationen verwendet und diese dann verwendet, um die beste Position für die Linie zu bestimmen, damit das Auto von dort aus abbiegt. Dadurch kann die PID eingerichtet und schnell verfolgt werden. Meine Frage ist, wie ich eine Belohnungsfunktion einrichten kann, die die Leistung verbessert, dh dem q-Lernen ermöglicht, das Beste zu finden

Bearbeiten

Was es zu lernen versucht, ist Folgendes: Es hat 16 Eingaben, die die Zeilenpositionen für die letzten 15 Iterationen und diese Iteration enthalten. Linienposition zwischen -1und 1welche -1Mittel nur links meisten Sensor sieht die Zeile und 0 ist die Linie in der Mitte. Ich möchte, dass es eine Linienposition lernt, die, wenn es wieder dieser Eingabe zugewandt ist, diese Linienposition wie die Mitte einstellt und die Kurve entsprechend dieser Linienposition nimmt. Zum Beispiel ist ein Fehler erforderlich. Position - Linienposition. Nehmen wir also an, ich hätte 16 0als Eingabe, dann habe ich die erforderliche als berechnet 0.4. Danach wird sich das Auto zentrieren. 0.4Ich hoffe, das hilft :)

Du hast nach meinem Quellcode gefragt, den ich unten poste

void MainController::Control(void){

    float linePosition = sensors->ReadSensors();

    if(linePosition == -2.0f){       
      lost_line->FindLine(lastPos[1] - lastPos[0]);
    } 
    else{
        line_follower->Follow(linePosition);
        lastPos.push_back(linePosition);
        lastPos.erase(lastPos.begin());   
    }
}

Mein Sensorwert gibt einen Wert zwischen -1.0fund zurück 1.0f. 1.0fbedeutet, dass der äußere Sensor rechts nur die Linie ist. Ich habe 8 Sensoren.

void LineFollower::Follow(float LinePosition){

    float requiredPos = Qpredictor.Process(LinePosition,CurrentSpeed);
    float error = requiredPos - LinePosition;

    float ErrorDer = error -LastError;

    float diffSpeed = (KpTerm * error + (KdTerm * ErrorDer));

    float RightMotorSpeed = CurrentSpeed - diffSpeed;
    float LeftMotorSpeed = CurrentSpeed + diffSpeed;

    LastError = error;

    driver->Drive(LeftMotorSpeed,RightMotorSpeed);
}

Hier ist die Logik für den Wert für QPredictor (ich nenne den Lernteil so). Und schließlich QPredictor

float Memory[MemorySize][DataVectorLength] =
{
  {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
  {0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3},
  {0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6},
  {0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8},

  {0.000, 0.012, 0.050, 0.113, 0.200, 0.312, 0.450, 0.613, 0.800, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000},
  {0.000, 0.000, 0.012, 0.050, 0.113, 0.200, 0.312, 0.450, 0.613, 0.800, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000},
  {0.000, 0.000, 0.000, 0.012, 0.050, 0.113, 0.200, 0.312, 0.450, 0.613, 0.800, 1.000, 1.000, 1.000, 1.000, 1.000},
  {0.000, 0.000, 0.000, 0.000, 0.012, 0.050, 0.113, 0.200, 0.312, 0.450, 0.613, 0.800, 1.000, 1.000, 1.000, 1.000},
  {0.000, 0.000, 0.000, 0.000, 0.000, 0.012, 0.050, 0.113, 0.200, 0.312, 0.450, 0.613, 0.800, 1.000, 1.000, 1.000},
  {0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.012, 0.050, 0.113, 0.200, 0.312, 0.450, 0.613, 0.800, 1.000, 1.000},
  {0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.012, 0.050, 0.113, 0.200, 0.312, 0.450, 0.613, 0.800, 1.000},

  {0.000, 0.025, 0.100, 0.225, 0.400, 0.625, 0.900, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000},

  {0.000, 0.050, 0.200, 0.450, 0.800, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000},


  {0.000, 0.100, 0.400, 0.900, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000},
  {0.000, 0.000, 0.100, 0.400, 0.900, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000},
  {0.000, 0.000, 0.000, 0.100, 0.400, 0.900, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000},
  {0.000, 0.000, 0.000, 0.000, 0.100, 0.400, 0.900, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000},
  {0.000, 0.000, 0.000, 0.000, 0.000, 0.100, 0.400, 0.900, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000},
  {0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.100, 0.400, 0.900, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000},
  {0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.100, 0.400, 0.900, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000},
  {0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.100, 0.400, 0.900, 1.000, 1.000, 1.000, 1.000, 1.000},
  {0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.100, 0.400, 0.900, 1.000, 1.000, 1.000, 1.000},
  {0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.100, 0.400, 0.900, 1.000, 1.000, 1.000},
  {0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.100, 0.400, 0.900, 1.000, 1.000},
  {0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.100, 0.400, 0.900, 1.000}
};


QPredictor::QPredictor(){
    for(int i=0;i<MemorySize;i++){
        output[i]=0.0f;
        input[i]=0.0f;
    }

    state = 0;
    PrevState = 0;
}

float QPredictor::Process(float linePosition,float currentBaseSpeed){
    for(int i=1;i<DataVectorLength;i++){
        input[i] = input[i-1];
    }

    input[0] = m_abs(linePosition);

    int MinIndex = 0;
    float Distance = 10000.0f;

    float sum = 0.0f;

    for(int i=0;i<MemorySize;i++){
        sum = 0.0f;
        for(int j=0;j<DataVectorLength;j++){
            sum +=m_abs(input[j] - Memory[i][j]);
        }

        if(sum <= Distance){
            MinIndex = i;
            Distance = sum;     
       }
    }

    sum = 0.0f;
    for(int i=0;i<DataVectorLength;i++){
        sum += input[i];
    }

    float eta = 0.95f;

    output[MinIndex] = eta * output[MinIndex] + (1 - eta) * sum;

    return -m_sgn(linePosition) * output[MinIndex];
}


float QPredictor::rewardFunction(float *inputData,float currentBaseSpeed){
    float sum = 0.0f;

    for(int i=0;i<DataVectorLength;i++){
        sum += inputData[i];
    }

    sum /= DataVectorLength;

    return sum;
}

Ich habe jetzt nur einen durchschnittlichen Fehler und verwende derzeit kein Lernen, da es ohne Belohnungsfunktion nicht vollständig ist. Wie kann ich es an die Abmessungen meines Roboters anpassen?


1
Ich denke, Ihre Frage muss noch verbessert werden, bevor sie beantwortet werden kann. ZB was versuchst du zu lernen? Die PID-Parameter? Was ist Ihr Ziel für das endgültige Systemverhalten?
Jakob


Das Speicherarray speichert die vergangenen Erfahrungen des Roboters, nicht die Zukunft. Negative Belohnungen müssen gegeben werden, wenn alle Array-Elemente weiß sind. Bei einfachen Kurven funktioniert dies.
Manuel Rodriguez

Ja, das macht Sinn, aber was ist, wenn ich keine verlorene Linie habe, wie kann ich die Belohnung oder Bestrafung erhöhen oder verringern
Ege Keyvan

+1 für Versuch; Sie können eine einfache Webcam zur Validierung verwenden. Verwenden Sie eine einfache Überprüfung, um festzustellen, wie nahe Ihr Roboter an der Mitte der Linie liegt. Verwenden Sie das dann und fügen Sie Belohnungen (wie +1, was bedeutet, dass Sie jede Sekunde auf der Spur bleiben) und Strafen hinzu (wenn eines der Räder die Linie überquert; -50 für jede Sekunde).
Prasad Raghavendra

Antworten:


0

Die adaptive PID-Regelung basiert auf einem manuell codierten Algorithmus für die Zeilenverfolgung, der durch Verstärkungslernen modifiziert wird. Die Idee ist, dass in der PID-Funktion ein Parameter unbekannt ist (z. B. der Abstand von der Linie, der als Abweichung toleriert werden kann) und dieser Parameter während der Fahrt des Roboters im laufenden Betrieb berechnet wird. Die Belohnungen werden manuell von einem Bediener- Clicker-Training vergeben oder können in einer Schleife ermittelt werden. Der Roboter fährt einen Parcurs, die Zeit wird gemessen. Der Roboter fährt die Parcurs erneut und das Ziel ist es, die Zeit zu verkürzen.


Ich habe es gesehen, aber ich habe Kohonen-Karten und Q-Learning, dass ich Kohonen verwende, um den Eingabevektor zu gruppieren, und Q-Learning, um die Ausgabe zu bestimmen. Kann ich dieses System an mein System anpassen?
Ege Keyvan

Sicher, die selbstorganisierende Karte kann als assoziatives Gedächtnis verwendet werden (Q-KOHON, Claude F. Touzet).
Manuel Rodriguez

Schlagen Sie entsprechend der Eingabe vor, sollte das System die Parameter ändern?
Ege Keyvan

@EgeKeyvan: Bitte posten Sie Ihren Soucecode oder einen Screenshot von NXT-G GUI
Manuel Rodriguez

Ich habe es jetzt gepostet
Ege Keyvan

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.