# EV3_Python Follow the line 

The following document describes programs written in Python for the Lego Mindstorm EV3. 
The purpose of the programs is to let a robot follow a given line on the floor. 
There are several possibilities for reaching this goal. In this document, two different approaches are described. 

## Used Hardware
<img align="right" src="Pictures/Proj1_RobotStructure.png" width="200">
The program was written for the LEGO EV3 Brick. It is the base of every Mindstorm EV3 robot. 
The built / used robot has two motors, one on each side, with two wheels each connected via a caterpillar track. 
But the program should work with all robots that have one driven wheel per side.

#### Motors

The used robot drives forward when the wheels turn counter-clockwise. `polarity = 'inversed'` If you use a robot with a clockwise direction of rotation, you need to change the settings in the program. `polarity = 'normal'` 
* **Left** Motor: Connected to output-port **A** 
* **Right** Motor: Connected to output-port **D** 
	
#### Sensors

To identify the line on the floor, two LEGO Color Sensors are used. The sensors are mounted on the front of the robot. 
* **Left** Color Sensor: Connected to input-port **2** 
* **Right** Color Sensor: Connected to input-port **4**

## Programs
As explained before, there are multiple possibilities to create a code that lets a robot follow a line. Therefore, there are two codes available to try out.

### Follow the line with color recognition
The first program uses the two color sensors to detect the color of the line. 
In the given code, the color is defined as black. `black: line_color = 1` 
If you use a different line-color, you may have to change the specification. 
Sometimes the color the sensor detects is not identical with what we see with our eyes. (e.g.: color of gray desk is detected as yellow)
To make sure you have the right input, you can use the program [Read sensor values](#read-sensor-values).

#### Description of the code
The robot drives forward as long as the color sensors do not detect the line (color). 
When one of the sensors detect the line, the motor stops on this side and the other motor drives faster. 
If both sensors detect the line, the robot stops and both LEDs of the EV3-brick will light up red. 
With this function you can create a finish line and the robot will follow the line as long as it has not reached it. 

The LEDs on the EV3 brick also show you the other current states. 
When the two sensors do not detect the line, both LEDs light up green. 
If one of the color sensors detects the line, the LED on this side will change the color to amber. The other side stays green.

Overview LED signals:
* **Both** LEDs = **green**: no color-sensor detected the line, the robot drives forward
* **Right** LED = **amber** and **Left** LED = **green**: the right color-sensor detected the line and the robot drives to the right
* **Left** LED = **amber** and **Right** LED = **green**: the left color-sensor detected the line and the robot drives to the left
* **Both** LEDs = **red**: both color-sensors detected the line, the robot stops

### Follow the line with intensity of reflected light
The second program is a bit more advanced and uses the intensity of the reflected light from the ground. 
As the color-sensor gets closer to the line, the reflection of the floor changes. 
So this means the sensor "detects" the line before it is completely over it.

To use this program, you need to know the maximal reflection-intensity of light of the floor and the minimal reflection-intensity of the line.
To get this values, you can use the [Read sensor values](#read-sensor-values) program. 
If you have the values, you can include them into the program: 

```
# Defined inputs for the given experiment / enviroment
Line = minimal value of the reflection-intensity of the line
Floor = maximum value of the reflection-intensity of the floor to which the line is attached
```

#### Description of the code
The rotating speed of the motors is directly dependent on the reflection of the light.
If one of the color sensors is near to the line, the motor on this side drives slower to make sure the color-sensor turns away from the line.

Calculation of speed-percentage: The two given values for the maximum and minimal intensity form limits of a range. 
The current measured reflections of the sensors are classified in this range and forms a percentage.
This percentage multiplied by the specified maximum driving speed value gives the actual speed percentage for the motor.

### Read sensor values 
<img align="right" src="Pictures/Proj1_Display_Read_sensor_value.png" width="200">

This program is used to find the needed values for the other two programs.
When you start the program, the intensity (value between 0 and 100) and color (value between 0 and 7) measured by the color-sensors are printed on the EV3 Brick every second. 
```
Right-Sensor:  Intensity = INTEGER(0-100)  Color = INTEGER(0-7)
Left-Sensor:  Intensity = INTEGER(0-100)  Color = INTEGER(0-7)
```
You should place the sensors over the line and over different areas of the floor. 
* For color recognition: Take the measured value of the color when placed the sensors on / over the line.  
* For intensity measuring: Pick the highest value of the intensity measured for the floor and the lowest value measured for the line.

## Problems and Improvements
Most of the problems depend on the input values / variables.
All the important inputs are defined in the code before the while-loop. 
Make sure you have chosen the right values for the inputs.

### Sharp curves
With both programs, the robot should be able to drive along every curve. If it happens, that the robot is not able to make the curve, you can improve the two programs. 
* For color recognition: You should try to vary the speed percentages of the motors (driving alone and both driving speed)
```
# Defined inputs for the given experiment / enviroment
line_color = 1 # Color of the given line is black 
speed_percent_alone = 60 # speed percentage when only one motor rotates (highest possible value 100%)
speed_percent_both = 30 # speed percentage when both motors rotate (should be less than speed_percent_alon
```
* For intensity measuring: You can vary the maximal speed percentage. It also can help to remeasure the reflected-intensities or increase the maximum value of the reflection from the floor for a wider range.
```
# Defined inputs for the given experiment / enviroment
Line = 2 # min. reflection meassured of line
Floor = 30 # max. reflection meassured of floor
max_speed_percent = 45 # maximum wanted speed percentage (highest possible value 100%)
```

### Robot drives backwards
As it is explained previously, the program is made for a robot that drives forward when the motors rotate counter-clockwise. 
If your robot drives backwards with the given code, change the polarity to normal. 
```
# The motor is initialized to run counter-clockwise (gegen den Uhrzeigersinn)
m_right.polarity  = 'inversed' # use 'normal' to initialize it to run clockwise (im Uhrzeigersinn)
m_left.polarity  = 'inversed'
``` 