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 -1
und 1
welche -1
Mittel 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 0
als Eingabe, dann habe ich die erforderliche als berechnet 0.4
. Danach wird sich das Auto zentrieren. 0.4
Ich 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.0f
und zurück 1.0f
. 1.0f
bedeutet, 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?