torsdag den 14. oktober 2010

Lab session 5: Line follower

Black white detection
The BlackWhiteSensor.java program has been used to evaluate the sensor readings over different dark and bright areas.
In the meassurements below we have observed that the values meassured depends on the color of the surface and the distance to the surface.

White paper readings in different distances:
60 – 5 mm
56 – 10 mm
50 – 20 mm
Black paper readings in different distances:
36 – 5 mm
34 – 10 mm
32 – 20 mm
Gray paper readings in different distances:
46 – 5 mm
44 – 10 mm
43 – 20 mm

Alishan train track readings in the distance of 10 mm:
White – 56
Border between black and white - 44
Black – 38

It seems like the sensor values are not symmetric. With a distance of 5 mm there is a bigger difference between gray and white (14) than gray and black (10). At the distance 20 mm the difference is inversed. The different between sensor readings gray and white is now 8 and gray and black 11. At the distance 10 mm measured at the Alishan track black has a higher value than on a pure black surface due to reflections from the white surroundings. One should think that symmetric readings should be optimal to make a motor controller for the line follower.
In use of sensor inputs for control of an actuator the number of values in the input scale is important in how accurate the mapping from inputs values to outputs values can be. If we have a fine grained scale (many values) we will be able to control the output actuator in smaller steps. If we as an example should use a proportional gain to map between input sensor values to an output motor power.To make a compromise between the above observations we have chosen the sensor distance to be 10 mm even though it isn't symmetric.

Line Follower with Calibration (PID)

First we tested the car following a line by using the LineFollowerCal.java program. The result is a car that is able to follow a straight black line but with a lot of oscillation.

Then we implemented the PID controller as described in [1] and started with setting the proportional gain Kp = 2. Based on the difference between gray and white = 12 when we multiply this value by Kp we get a maximum turn of 24 in power difference to the motor. The car was following the line more smoothly and precise.

PID calculation method:

public void pidCalculate(int lvalue) {
int turn;
int error;
float derivative = 0;

error = lvalue - offset;
integral = (integral*2)/3 + error;
derivative = error - lastError;
turn = (int)(Kp*error + Ki*integral + Kd*derivative);

powerA = limitPower(Tp + turn);
powerC = limitPower(Tp - turn);

lastError = error;
}

Main loop reading sensor and calling pidCalculate with the periodicity of ~10ms:

while (! Button.ESCAPE.isPressed()){
if (Button.ENTER.isPressed())
time = 0;
LightValue = sensor.light();
LCD.drawInt(LightValue,4,10,2);
LCD.drawInt(time,4,10,3);
LCD.refresh();
lineFollower.pidCalculate(LightValue);
Car.forward(powerA, powerC);
Thread.sleep(dT);
time++;
}

We managed to improve the line follower even better by adjusting the integral and derivative constants as described in [1]. First we used an execl sheet to automatically calculate the Kp, Ki and Kd based on a selected Kc.
We have measured the oscillation rate base on time and counting 10 robot oscillation turns. First we stated with a dT = 10 ms, but found it better using a sampling rate of 5 ms. The response time adjusting the PID and motor made a faster response. Especially when trying to make sharp turns following a black line.

1. Test
dt = 10ms
Kc = 2, dt = 10ms, pc = 800 ms (10 turns in ~8 sec)
Calculation of PID constants:

Kp = 0.6*Kc = 1.2
Ki = 2*Kp*dt/pc = 2*1.2*10/800 = 0.03
Kd = Kp * (pc/8*dt) = 1.2 (800/80) = 10




Results












Test1Test2Test3Test4Test5
dt10101055
kc24345
pc800600800700600
kp1.22.41.82.43
ki0.030.080.0450.0342860.05
kd1218184245

Complete source code to be found here: LineFollower

See video of PID controlled line follower here: PID controlled line follower

ColorSensor with Calibration
We decided to use the BlackWhiteSensor.java class [insert reference] as a base for our colour sensor application. This class is the one introduced in the first section. As it was previously mentioned, the class is using the lego NXT light sensor. One of the changes we introduced was to substitute the NXT light sensor and use the RCX equivalent since it has got high enough resolution to distinguish between several colours.

The main structure of the class is explained in the following lines.

The class is composed by three different types of attributes. The first one is an instance of the RCX light sensor class, that is provided by the Lejos API. This class will allow us to deal with the signals coming from the light sensor and to obtain the readings. The next attributes are integer variables that store the values corresponding to the black, white and green areas. Finally, the different thresholds that define the transitions between white, green and black are defined. The followed criteria to define those thresholds will be explained later.

private int greenBlackThreshold;
private int blackLightValue;
private int whiteLightValue;
private int greenLightValue;
private int whiteGreenThreshold;
private int greenBlackThreshold;

­­The main methods present at the class are the constructor, the read method and the calibration methods, and finally Boolean tests to detect whether the region is black, white or green.

The class constructor is creating an instance of the RCX light sensor class and defining that the sensor is going to be used in reflection mode.

public ColorSensor(SensorPort p)
{
rcsLs = new RCXLightSensor(p);
rcsLs.setFloodlight(true);
}

The calibrate method is executing blocking read operations in order to define the values that should be stored in the fields blackLightValue, whiteLightValue and greenLightValue. After those readings have been performed, the thresholds are defined by calculating the average value between two adjacent colours.

public void calibrate()
{
blackLightValue = read("black");
whiteLightValue = read("white");
greenLightValue = read("green");
greenBlackThreshold = (blackLightValue+greenLightValue)/2;
whiteGreenThreshold = (greenLightValue+whiteLightValue)/2;
}

Finally the Boolean test functions black, white and green are defined. Those functions test the conditions that must be fulfilled in order to identify one colour or another. Those conditions are defined by the thresholds, obtained from the readings performed in the calibration stage. In the following example it can be seen the example for the green detection function, that will return true in the case the detected colour is green.

public boolean green()
{
return(rcsLs.readValue() <> greenBlackThreshold);
}

[1] A PID Controller For Lego Mindstorms Robots.
[2] Caprani, Ole. BlackWhiteSensor.java

Ingen kommentarer:

Send en kommentar