I have 2 wheeled differential drive robot which I use pid for low level control to follow line. I implemented q learning which uses samples for 16 iterations then uses them to decide the best position to be on the line so car takes the turn from there. This allows PID to setup and smooth fast following. My question is how can I setup a reward function that improves the performance i.e. lets the q learning to find the best
Edit
What it tries to learn is this, it has 16 inputs which contains the line positions for the last 15 iterations and this iteration. Line position is between -1
and 1
which -1
means only left most sensor sees the line and 0 means the line is in the center. I want it to learn a line position that when it faces this input again it will set that line position like its the center and take the curve according to that line position. For example error is required position - line position so let say I had 16 0
as input then I calculated the required as 0.4
. So after that the car will center itself at 0.4
I hope this helps :)
You asked for my source code i post it below
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());
}
}
My Sensor reading returns a value between -1.0f
and 1.0f
. 1.0f
means Outer Sensor on the right is only the line. I have 8 sensors.
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);
}
Here is the logic for the value for QPredictor(I call the learning part as this). And Finally 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;
}
I now only have average Error and currently not using learning because it's not complete without reward function. How can I adjust it according to the dimensions of my Robot?