Follow Line
- Carlos Caminero
- 13 oct 2020
- 3 Min. de lectura
Actualizado: 1 dic 2020
In this project we will use a Formula 1 car that will travel the entire race circuit, guided only by a line (red / orange) painted on the road. For this, we have used a racing circuit in the gazebo simulator and we have programmed our algorithm on a python program that handles ROS topics in an abstract and underlying way

The goal of this practice is to implement a reactive system by a PID controller that allows us to act on the control of the vehicle in the best possible way to follow the line, and thus, we can avoid going off the road, losing sight of the line, gaining linear and angular speed, etc.
But the first problem of all, you have to filter the color line of the road.
We will use Opencv and we will do the following:
1. Convert the camera image from RGB to HSV, because the HSV scale is easier to use for filtering and we can adapt well to saturation and brightness levels
2. Mask. we will take a range of value (lower, higher) to filter the red line of the road and obtain a mask (black / white image where white is our objective). To help us obtain the correct values, we can create a GUI apart that allows us to filter the line using moving sliders. And so we get this result:

3. Mixing the images. We made this contribution late (after recording the videos), but it is a way to better perceive how well the image has been filtered. For that, we have used cv2.bitwise_and(...) that works like an "and" function bit by bit.
4. Following the line. The method that we have used, has been looking for the medium point of the contour of a section of horizon. For that we have cut the original image in half and we have filtered the red line again . Then we have used "moments" of Opencv library (see documentation cv2.moments) to obtain the centroid of the cropped image. The moments are configured under the following equation:

If we use m00 we will obtain the numbers of pixeles that are 1 ( white color), since "array(x, y)" will only give values 1 or 0. If we use m10 we will obtain the sum of the coordinates x of the pixels that whose values are 1. Therefore, if we divide m10 / m00 we will obtain the x coordinate of the centroid. In the same way we will do for the y coordinate of the centroid (m01 / m00). Once the x and y points have been obtained we have drawn them in the original image (camera image)
We have programmed the filter in such a way that we can see the centroid and its distance with the vertical central axis and the contour of the line section using "cv2.drawContours (...)". Our goal is to make that distance ~0 pixels

Once this is done, we have to implement a PID controller that allows us to follow the line in the best possible way (stability) and quickly. In my case, I used P, D, and I.
To do this, we have created a GUI with opencv methods (cv2.namedWindow(...), cv2.createTrackbar(...) and cv2.getTrackbarPos(...)) that allows us to adjust the Kp, Kd, Ki and maximum velocity parameters through observation and comfort :)

To adjust the PID controller I did the following steps:
- 1. I modified the Kp constant (from P controller). With this, the error decreased but the oscillation of the system increased.
- 2. I modified the Kd constant (from D controller). With this, I generated a quick response using the derivative of the error and got less oscilations.
- 3. I modified the Ki constants (from I controller). With this, I got a behavior that anticipated the future, and if the error accumulated a lot, the car knew where to turn.
But if it was piling up too much, the turning response could be so abrupt that the car would roll out of line. Therefore, if the error for the integral component was negative, it would reset the integral component to avoid overshooting
Here is my first video.
After the first video, I improved it, with the following improvements:
Recognize lines and curves. Starting from a maximum speed, if the error was very very small, the linear speed does not vary much but if the error is very large, the linear speed will be reduced considerably. it's proportional to the error, so that I have used a P controller.
Look even more towards the horizon. In this way we can anticipate curves. To do this, we had to make the cropped image smaller
Resetting new values for Kp, Kd, Ki to adapt them to the new maximum speed.

And this is the result: my best score (35 seconds in Simulation Time).
EXTRA CIRCUITS
Currently, I am using my formula 1 in others circuits to test our proyect
For now, we have tested my formula 1 in Montmeló Circuit and this is the result:
Montreal y Nurburgring soon...
Comments