... | ... | @@ -24,22 +24,52 @@ First, you should mount the sensor on the LEGO 9797 car as described in LEGO Min |
|
|
|
|
|
#### Execution ####
|
|
|
First, we rebuilt the robot to utilize a light sensor. Our initial construction can be seen in Figure 1.
|
|
|
Secondly, we programmed an application which used the *BlackWhiteSensor.java* <<<<<<indsæt reference til koden her >>>>>> class to classify colors as either white or black. This application can be seen <<<<<indsæt kode eller reference til git med kode>>>>>>. We used this application to analyse the effectiveness of application calibration.
|
|
|
Secondly, we programmed an application which used the *BlackWhiteSensor.java* \[2\] class to classify colors as either white or black. This application can be seen in Code 1. We used this application to analyse the effectiveness of application calibration.
|
|
|
|
|
|
```Java
|
|
|
public class BWSensorTest
|
|
|
{
|
|
|
private static String black = "Black";
|
|
|
private static String white = "White";
|
|
|
private static String unknown = "?????";
|
|
|
public static String getColor(BlackWhiteSensor sensor) {
|
|
|
if (sensor.black()) return black;
|
|
|
if (sensor.white()) return white;
|
|
|
return unknown;
|
|
|
}
|
|
|
public static void main(String [] args) throws Exception
|
|
|
{
|
|
|
BlackWhiteSensor blackWhiteSensor = new BlackWhiteSensor(SensorPort.S1);
|
|
|
blackWhiteSensor.calibrate();
|
|
|
Thread.sleep(2000);
|
|
|
LCD.clear();
|
|
|
LCD.drawString("Color: ", 0, 0);
|
|
|
while (!Button.ESCAPE.isDown())
|
|
|
{
|
|
|
LCD.drawString(getColor(blackWhiteSensor), 0, 1);
|
|
|
Thread.sleep(100);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
*Code 1 : BlackWhiteSensor test class*
|
|
|
|
|
|
<img src="https://gitlab.au.dk/martinwp/LegoGroup2/raw/develop/lesson-04/images/sensor_location_high.jpg" alt="Figure 1" width="200px" />
|
|
|
*Figure 1 : The initial construction of the robot, Note hight of sensor location*
|
|
|
|
|
|
The *BlackWhiteSensor.java* class prints light values to the display as a percentage <<<<indsæt reference til hvor dette er kendt fra >>>>>. We noted these in table <<<<<table ref >>>>>.
|
|
|
The *BlackWhiteSensor.java* \[2\] class prints light values to the display as a percentage. We noted these in Table 1.
|
|
|
|
|
|
**White** | **Black**
|
|
|
--- | ---
|
|
|
51 | 33
|
|
|
---------- | ----------
|
|
|
51% | 33%
|
|
|
*Table 1 : Light percentages from BlackWhiteSensor test*
|
|
|
|
|
|
We noticed that the application was very effective at classifying the differences between black and white. It does this by calculating the median between the black and white readings and setting this value as the threshold between the two colors.
|
|
|
Because of this, it was interesting to test the sensor on a greyscale. Starting at white, we moved the robot (and thus the sensor) towards black until the classification changed. This happened around the middle of the scale which makes sense. The exact point at which the application changed from white to black can be seen in Figure 2.
|
|
|
Because of this, it was interesting to test the sensor on a greyscale. Starting at white, we moved the robot manually (and thus the sensor) towards black until the classification changed. The classification was printed on the display, and the threshold was printed as ?. This happened around the middle of the scale which makes sense. The exact point at which the application changed from white to black can be seen in Figure 2.
|
|
|
|
|
|
<img src="https://gitlab.au.dk/martinwp/LegoGroup2/raw/develop/lesson-04/images/sensor_black_white.jpg" alt="Figure 2" width="200px" />
|
|
|
*Figure 2 : Messuring the *
|
|
|
*Figure 2 : Measuring the exact point of classification between black and white. The robot was moved manually and the classification was printed to the display*
|
|
|
|
|
|
### Line Follower with Calibration ###
|
|
|
|
... | ... | @@ -48,9 +78,9 @@ As an application of the BlackWhiteSensor try the program *LineFollowerCal.java* |
|
|
|
|
|
#### Execution ####
|
|
|
|
|
|
We installed the *LineFollowerCal.java* <<<<<<ref!!!>>>>> application on the robot. Initially, we had some issues making the robot follow a black line. We found that this issue was fixable by holding the robot on top of the black line a bit before allowing the robot to drive and by placing it exactly on the black line instead of close to the black/white edge.
|
|
|
We installed the *LineFollowerCal.java* \[3\] application on the robot. Initially, we had some issues making the robot follow a black line. We found that this issue was fixable by holding the robot on top of the black line a bit before allowing the robot to drive and by placing it exactly on the black line instead of close to the black/white edge.
|
|
|
|
|
|
After taking this approach, the robot ran as expected and followed the line. The movement was however a bit jagged due to the reactive nature of the application, which will be covered in depth in section <<<indsæt ref til sektion om PID line follower>>>>.
|
|
|
After taking this approach, the robot ran as expected and followed the line. The movement was however a bit jagged due to the reactive nature of the application, which will be covered in depth in the section *PID Line Follower*.
|
|
|
|
|
|
### ThreeColorSensor with Calibration ###
|
|
|
|
... | ... | @@ -59,19 +89,56 @@ Use the idea and structure of the BlackWhiteSensor to program a class ThreeColor |
|
|
|
|
|
#### Execution ####
|
|
|
|
|
|
We extended the behaviour of *BlackWhiteSensor.java* to calibrate for green as well as the black and white. In this application, thresholds between black-green and green-white were used instead of black-white. This happened under assumption that any color would always have a value between absolute white and absolute black, meaning that ambient light would have no difference. The extended application then defines green as any value between the two thresholds (non-inclusive) and uses this to classify colors. This behaviour worked in our current environment, but given different ambient light, the read values might be lower, minimising differences between thresholds.
|
|
|
We extended the behaviour of *BlackWhiteSensor.java* \[2\] to calibrate for green as well as the black and white. In this application, thresholds between black-green and green-white were used instead of black-white. This happened under assumption that any color would always have a value between absolute white and absolute black, meaning that ambient light would have no difference. The extended application then defines green as any value between the two thresholds (non-inclusive) and uses this to classify colors. This behaviour worked in our current environment, but given different ambient light, the read values might be lower, minimizing differences between thresholds.
|
|
|
|
|
|
We installed the program on the robot and started classifying black, white and green. The green color was dark green and was thus very close to black for the light sensor.
|
|
|
We installed the program on the robot and started classifying black, white and green. The green color was dark green and was thus very close to black for the light sensor as can be seen in Table 2.
|
|
|
|
|
|
**White** | **Black** | **Green**
|
|
|
--- | --- | ---
|
|
|
---------- | --------- | ----------
|
|
|
51% | 33% | 37%
|
|
|
|
|
|
A final observation is that the light value class uses percentages to define the amount of light<<<<<indsæt ref!!!!>>>>>>. This value is returned as an integer, which means that any value will be rounded down.
|
|
|
As many colors lie in the value space between 30% and 50%, this functionality reduces the effectiveness of classifications. An option would have been to instead use the raw values which percentages are calculated from, as these have values between 0 and 1023<<<<<<REF>>>>>>.
|
|
|
|
|
|
The extended application can be seen <<<<<<indsæt ref til kode FOR BEGGE FILER, eller indsæt kode>>>>>>.
|
|
|
|
|
|
*Table 2 : Light percentages from ThreeColorSensor test*
|
|
|
|
|
|
A final observation is that the light value class uses percentages to define the amount of light. This value is returned as an integer, which means that any value will be rounded down.
|
|
|
As many colors lie in the value space between 30% and 50%, this functionality reduces the effectiveness of classifications. An option would have been to instead use the raw values which percentages are calculated from, as these have values between 0 and 1023.
|
|
|
|
|
|
The extended application can be seen in Code 2.
|
|
|
|
|
|
```Java
|
|
|
public class TCSensorTest
|
|
|
{
|
|
|
private static String black = "Black";
|
|
|
private static String white = "White";
|
|
|
private static String green = "Green";
|
|
|
private static String unknown = "?????";
|
|
|
static void displayColor(String name, int raw, int calibrated, int line)
|
|
|
{
|
|
|
LCD.drawString(name, 0, line);
|
|
|
LCD.drawInt(raw, 5, 6, line);
|
|
|
LCD.drawInt(calibrated, 5, 11, line);
|
|
|
}
|
|
|
public static String getColor(ThreeColorSensor sensor) {
|
|
|
if (sensor.black()) return black;
|
|
|
if (sensor.white()) return white;
|
|
|
if (sensor.green()) return green;
|
|
|
return unknown;
|
|
|
}
|
|
|
public static void main(String [] args) throws Exception
|
|
|
{
|
|
|
ThreeColorSensor treeeColorSensor = new ThreeColorSensor(SensorPort.S1);
|
|
|
treeeColorSensor.calibrate();
|
|
|
Thread.sleep(2000);
|
|
|
LCD.clear();
|
|
|
LCD.drawString("Color: ", 0, 0);
|
|
|
while (!Button.ESCAPE.isDown())
|
|
|
{
|
|
|
LCD.drawString(getColor(treeeColorSensor), 0, 1);
|
|
|
Thread.sleep(100);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
*Code 2 : ThreeColorSensor test class*
|
|
|
|
|
|
### Line Follower that stops in a Goal Zone ###
|
|
|
|
... | ... | @@ -82,29 +149,82 @@ Use the ThreeColorSensor to make a line follower that stops in a green goal zone |
|
|
This exercise combines the previous two exercises to both follow a black line on white background and register the color green as an event causing the robot to stop.
|
|
|
|
|
|
##### Programming the application #####
|
|
|
We need to program an application which follows a black line on white background on stops immediately when seeing green. We built this application simply by combining the *ThreeColorSensor.java* <<<<ref>>>> class from the previous exercise with the *LineFollowerCal.java* <<<<ref>>>> class. We also added behaviour to stop the robot on button press. The final application can be seen in <<<<ref>>>>.
|
|
|
We need to program an application which follows a black line on white background on stops immediately when seeing green. We built this application simply by combining the *ThreeColorSensor.java* \[4\] class from the previous exercise with the *LineFollowerCal.java* \[3\] class. We also added behaviour to stop the robot on button press. The final application can be seen in Code 3.
|
|
|
|
|
|
```Java
|
|
|
public class LineFollowerCalGoal
|
|
|
{
|
|
|
public static void main (String[] aArg)
|
|
|
throws Exception
|
|
|
{
|
|
|
final int power = 70;
|
|
|
final int low_power = 20;
|
|
|
final int needReadings = 100;
|
|
|
int readings = 0;
|
|
|
ThreeColorSensor sensor = new ThreeColorSensor(SensorPort.S1);
|
|
|
sensor.calibrate();
|
|
|
Button.waitForAnyPress();
|
|
|
LCD.clear();
|
|
|
LCD.drawString("Light: ", 0, 2);
|
|
|
while (! Button.ESCAPE.isDown())
|
|
|
{
|
|
|
LCD.drawInt(sensor.light(),4,10,2);
|
|
|
LCD.refresh();
|
|
|
if ( sensor.black() ) {
|
|
|
readings = 0;
|
|
|
Car.forward(power, 0);
|
|
|
}
|
|
|
else if ( sensor.white()) {
|
|
|
readings = 0;
|
|
|
Car.forward(0, power);
|
|
|
}
|
|
|
else if ( sensor.green() ) {
|
|
|
readings++;
|
|
|
if (readings >= needReadings) {
|
|
|
Car.stop();
|
|
|
}
|
|
|
Car.forward(0, low_power); // Move as white but less
|
|
|
}
|
|
|
Thread.sleep(15);
|
|
|
}
|
|
|
Car.stop();
|
|
|
LCD.clear();
|
|
|
LCD.drawString("Program stopped", 0, 0);
|
|
|
Thread.sleep(2000);
|
|
|
LCD.refresh();
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
*Code 3 : Line Follower with Goal*
|
|
|
|
|
|
##### Creating the track #####
|
|
|
We started off by finding a circular track with a black line on white background. On this track, we placed a light green post it note to indicate the goal zone. An interesting observation here is that the light green color is different to the dark green color which was used in previous exercises. This causes the sensor to register different readings.
|
|
|

|
|
|
We started off by finding a circular track with a black line on white background. On this track, we placed a light green post-it note to indicate the goal zone, as seen in Figure 3. An interesting observation here is that the light green color is different to the dark green color which was used in previous exercises. This causes the sensor to register different readings.
|
|
|
|
|
|
<img src="https://gitlab.au.dk/martinwp/LegoGroup2/raw/develop/lesson-04/images/sensor_green.jpg" alt="Figure 3" width="200px" />
|
|
|
*Figure 3 : The green goal zone*
|
|
|
|
|
|
##### Changing the sensor height #####
|
|
|
We made some readings with this light green color and found the results seen in table <<<table ref >>>>>.
|
|
|
We made some readings with this light green color and found the results seen in Table 3.
|
|
|
|
|
|
**White** | **Black** | **Dark green** | **Light green**
|
|
|
--- | --- | --- | ---
|
|
|
---------- | --------- | -------------- | ----------------
|
|
|
47% | 31% | 37% | 40%
|
|
|
*Table 3 : Light percentages from goal zone, and the initial readings*
|
|
|
|
|
|
Using these readings as calibration, we tried to run our application. This caused the robot to immediately stop on the white/black line without seeing green. We edited our application a bit to still show the read light value after stopping the robot. This revealed to us that the light value registered on the black/white line is around 41%, which is close to the middle of the zone where the application classifies the color as green.
|
|
|
|
|
|
To fix this issue, we tried different heights for the light sensor, choosing the exact height in which we reached a maximum light value for white background. The new build can be seen in <<<ref til billede herunder>>>.
|
|
|

|
|
|
To fix this issue, we tried different heights for the light sensor, choosing the exact height in which we reached a maximum light value for white background. The new configuration can be seen in Figure 4.
|
|
|
|
|
|
<img src="https://gitlab.au.dk/martinwp/LegoGroup2/raw/develop/lesson-04/images/sensor_location_low.jpg" alt="Figure 4" width="200px" />
|
|
|
*Figure 4 : Position of the light sensor, changed to be closer to surface*
|
|
|
|
|
|
By lowering the sensor to a height of a few millimeters, the sensor showed the values in table <<<ref til tabel>>>.
|
|
|
By lowering the sensor to a height of a few millimeters, the sensor showed the values in Table 4.
|
|
|
|
|
|
**White** | **Black** | **Dark green** | **Light green**
|
|
|
--- | --- | --- | ---
|
|
|
---------- | --------- | -------------- | ----------------
|
|
|
52% | 31% | 40% | 45%
|
|
|
*Table 4 : Light percentages from new sensor position closer to surface*
|
|
|
|
|
|
We immediately tried the application again with these values, and managed to have the robot follow the black line closely and stop its movement when sensing green.
|
|
|
|
... | ... | @@ -113,7 +233,7 @@ A final observation relating to this application is that the robot stopped immed |
|
|
### PID Line Follower ###
|
|
|
|
|
|
#### Description ####
|
|
|
It is possible to make a line follower with just one light sensor that follows the line more smoothly and drive faster if a PID regulator is used \[2\]. Try this.
|
|
|
It is possible to make a line follower with just one light sensor that follows the line more smoothly and drive faster if a PID regulator is used \[PID\]. Try this.
|
|
|
|
|
|
#### Execution ####
|
|
|
In this exercise, we follow the description of a PID implementation given in the exercise sources<<<<<ref>>>>>. We refer to this article for the theoretical reasoning for building a PID algorithm.
|
... | ... | @@ -135,7 +255,7 @@ By integrating from an amount of previous samples, the application can classify |
|
|
As we didn't have any solution of how to set the values in our application for proportional (Kp), integral (Ki), differential (Kd) and base motor power (Tp), we experimented with the values until we had a solution where the robot both drove with a somewhat fast speed and where the movement was fluid on straight lines as well as during turns.
|
|
|
|
|
|

|
|
|
*Figure X: The video shows the robot fluidly driving around a circular track following a black line on white surface.
|
|
|
*Figure X: The video shows the robot fluidly driving around a circular track following a black line on white surface.*
|
|
|
|
|
|
|
|
|
### Color Sensor ###
|
... | ... | @@ -201,9 +321,18 @@ While a simple program fitted with an advanced sensor can fulfil some goals, mor |
|
|
|
|
|
\[1\] : [Lesson Plan](http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson4.dir/Lesson.html)
|
|
|
|
|
|
\[2\] : [A PID Controller For Lego Mindstorms Robots](http://www.inpharmix.com/jps/PID_Controller_For_Lego_Mindstorms_Robots.html)
|
|
|
\[2\] : [BlackWhiteSensor.java](https://gitlab.au.dk/martinwp/LegoGroup2/raw/develop/lesson-04/exercise-01/BlackWhiteSensor.java)
|
|
|
|
|
|
\[3\] : [LineFollowerCal](https://gitlab.au.dk/martinwp/LegoGroup2/raw/develop/lesson-04/exercise-02/LineFollowerCal.java)
|
|
|
|
|
|
\[4\] : [ThreeColorSensor](https://gitlab.au.dk/martinwp/LegoGroup2/raw/develop/lesson-04/exercise-03/ThreeColorSensor.java)
|
|
|
|
|
|
\[PID\] : [A PID Controller For Lego Mindstorms Robots](http://www.inpharmix.com/jps/PID_Controller_For_Lego_Mindstorms_Robots.html)
|
|
|
|
|
|
<!--
|
|
|
STYLE FOR REF:
|
|
|
\[number\] : [name](link)
|
|
|
|
|
|
STYLE FOR IMAGE:
|
|
|
<img src="" alt="Figure X" width="200px" />
|
|
|
*Figure X : This is a caption for Figure X*
|
... | ... | |