Line Following Robot
Feb 2024
GOAL: Use a camera to autonomously navigate a maze by following a specific color line
SKILLS: CAD (OnShape), PID control, python programming, image processing, motor control, autonomous adjustment, wiring, low cost prototyping, laser cutting, use of single board computer (Raspberry Pi), design, collaboration
Summary
This robot uses a PiCam v3 to follow curved colored lines. It is designed to look like the standard kart in Mario Kart. You start by inputting what path of colors you want the robot to follow and the directions it needs to go (eg [red, blue, black, green] and [R, L, L, end]). Then, once you run the program, the robot should autonomously traverse this path.
This robot uses image processing techniques to recognize the lines. It also uses PID control to smoothly follow the lines, and to decide how much to turn at intersections to follow the next line
Video
given: ['blue', 'red', 'black'] and ['R', 'end']
given: ['blue', 'red', 'black'] and ['R', 'end']
given: ['red', 'blue', 'black'] and ['L', 'end']
Code without intersection modfication
Wiring
Code

Line Detection Code
First, the code captures an image with the camera and crops it to a size that we deemed appropriate based on the height of the camera.
Next, the image is converted to grayscale and blurred. This blurring gets rid of irregular edges and leaves only the important shapes. Next, a color threshold is applied that converts the image to binary.
Contours are created from the binary image, and if contours exist, the moment of the biggest contour is taken. The moment contains info like the area of the contour and its center of mass. cx and cy are assigned as the centroid coordinates from the moment.
Error Cases
The code gets an error value which is the center minus the current center of mass in the x direction. This value is positive if the robot is too far to the right, and negative if the robot is too far to the left. By subtracting the error multiplies by a proportional constant from the left motor and adding it to the right motor, the motor speeds will increase and decrease correctly to make the appropriate adjustment.
PID Control
Proportional Control
Proportional control gets error from the difference between the center (setpoint) and the x coordinate of the centroid. This value is then added or subtracted from a default duty cycle value so the motors change more dramatically when the error is larger.
Integral Control
Integral control addresses steady state error by summing the error over time. We implemented integral control by multiplying the error by the change in time and adding it to a running sum. We got change in time, dt, by using global current and previous time variables to get the change in time between each loop.
Derivative Control
Derivative control anticipates the future trend of the error by considering how fast the arror is changing. This dampens the response and reduces overshoot. We calculated the derivative of the error by finding the difference between the current and previous error and dividing by dt.
Intersection Code
in normal loop: process image with very wide threshold that can catch all the lines
if the contour area is greater than max_contour_area (maximum for the area to be from a single line), then two lines must be present
to reduce computational time, we only want to look do thresholding if the detecting line is actually next in the sequence, so assign next_threshMin and next_threshMax based on the next color in the color path array
call processIntersection with the original blurred image and the specific color threshold passed in. This function does thresholding and returns true if the area of the new threshold is above a minimum area to recognize a valid line.
processIntersection also calls get_slope which uses the point distribution of the contour area to calculate the linear fit of the shape
if processIntersection returned false, then the intersection was likely with a color that we don't care about, and the code moves on to operate as normal
if processIntersection returned true, then followNewLine is called
followNewLine uses abs((math.pi-math.atan(slope))) to find the different between the angle of the slope and a vertical line. This value is added to the default motor speed and passed into various functions depending on the current direction in the directions array.
if the error is large, the motor will spin faster and make a bigger adjustment over the set period of time that it spins for.
then it moved forward a bit more to make sure its off the old line and increments the index that keeps track of the color path and directions. The robot then continues as normal until the next intersection
if the intersection line was black and the direct was end, then the motors stop and the program ends
CAD
Fabrication
We wanted the car to look like the standard Mario cart, so we used cardboard and duct tape for the front and side pieces to keep the pieces light and also achieve a shiny appearance. The back thrusters and steering wheel were 3D printed. The front wheels are 3D printed wheels from a previous project with yellow duct tape added on to match the back lego wheels and the yellow on the wheels of the actual kart. The chassis body and the supports for the cardboard are laser cut birch wood. The camera mount is laser cut acrylic.