Hangjun (Jerry) LiuRobert BettuzziDaniel WangwxyLuna
Published

High way lane switch + obstacle avoidance autonomous robot

The robot imitates a vehicle on the highway through changing lanes, producing a honking noise, and avoiding obstacles with infrared sensors.

IntermediateProtip359
High way lane switch + obstacle avoidance autonomous robot

Things used in this project

Hardware components

Texas Instruments LM386 Low voltage Audio Power Amplifier
×1
Texas Instruments Mini-speaker
×1
Sharp GP2Y0A21YK0F Analog Distance Sensor 10-80cm
3 of these sensors used to detect the front, left, and right distance between the robot car and obstacles
×1
USB Camera
×1
Raspberry Pi 4 Model B
Raspberry Pi 4 Model B
×1
Sharp GP2Y0A21YK0F Analog Distance Sensor 10-80cm
×3
LAUNCHXL-F28379D C2000 Delfino LaunchPad
Texas Instruments LAUNCHXL-F28379D C2000 Delfino LaunchPad
×1

Software apps and online services

OpenCV
OpenCV
Code Composer Studio
Texas Instruments Code Composer Studio

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
3D Printer (generic)
3D Printer (generic)

Story

Read more

Schematics

Side view of robot car

An overview of the robot car, showing how the camera and the infrared sensors are mounted.

Code

RasberryPi Code

C/C++
Code that programmed the RasberryPi to recognize lines on the robot's path and output a legal flag to the main code that determines which direction the robot should go to avoid obstacles.
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/highgui.hpp>
#include <math.h>
#include <sys/select.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>

#include <time.h>
#include <memory>
using namespace cv;

extern "C"
{
#include "serial_dev.h"
}

using namespace cv;
using namespace std;

union float_char
{
    float val[1];
    char bytes[4];
};

#define SHOW_IMAGE 
char SERFILE[] = "/dev/ttyAMA1";
#define SERIALBUFFSIZE 1024
float cx; //position of the center(in percentage)
float cy; //position of the center(in percentage)
char to_send;
char received[] = "O";
int frame_count = 0;
int max_index=0;
float x,y;
float size = 0;
std::vector<cv::KeyPoint> keypoints;
int charsread = 0;

// line recognition flag
int left_banned = 0;
int right_banned = 0;
int legal_flag = 0;
char crossing_flag[] = "N";
int line_reached = 0;
char send[] = "O";
union float_char received_f28;
/*
 * setup_serial()
 *   sets the serial port up at 115200 baud
 */
void setup_serial()
{
    sd_setup(SERFILE); //starts non-blocking
    sd_ioflush();
}

/////////////// Color Detection //////////////////////
char asterisk[] = "*";
char exclamation[] = "!";

int main()
{
    printf("Initializing serial port driver %s...\n", "/dev/ttyAMA1");
    setup_serial();
    printf("...OK\n");

    //sd_set_blocking();
    printf(".\n");
    sd_ioflush();

    printf("Starting\n");
    VideoCapture cap(0);
    cap.set(CAP_PROP_FRAME_WIDTH,160);//Setting the width of the video//
    cap.set(CAP_PROP_FRAME_HEIGHT,120);//Setting the height of the video//
    Mat img;
    //below value selected with trackbar
    int hmin = 0, smin = 104, vmin = 240;
    int hmax = 179, smax = 255, vmax = 255;

    // //create trackbar to select values, hue max is 179, saturation and value are 255
#ifdef SHOW_IMAGE
    namedWindow("Trackbars", (640, 200));
    createTrackbar("Hue Min", "Trackbars", &hmin, 179);
    createTrackbar("Hue Max", "Trackbars", &hmax, 179);
    createTrackbar("Sat Min", "Trackbars", &smin, 255);
    createTrackbar("Sat Max", "Trackbars", &smax, 255);
    createTrackbar("Val Min", "Trackbars", &vmin, 255);
    createTrackbar("Val Max", "Trackbars", &vmax, 255);
#endif

	cv::SimpleBlobDetector::Params params;
	params.minDistBetweenBlobs = 40.0f;
	params.filterByInertia = false;
	params.filterByConvexity = false;
	params.filterByColor = false;
	params.filterByCircularity = false;
	params.filterByArea = true;
	params.minArea = 10.0f;
	params.maxArea = 50000.0f;
    Mat frame, frame_HSV, frame_threshold, frame_key;
    Ptr<SimpleBlobDetector> blob_detector = SimpleBlobDetector::create(params);
    while (true)
    {
        frame_count++;
		//printf("Framecount = %d\n");
        cap >> frame;
        if (frame.empty())
        {
            break;
        }
        // Convert from BGR to HSV colorspace
        cvtColor(frame, frame_HSV, COLOR_BGR2HSV);
        // // Detect the object based on HSV Range Values
        Scalar lower(hmin, smin, vmin); //set lower bound
        Scalar upper(hmax, smax, vmax); //set upper bound
        inRange(frame_HSV, lower, upper, frame_threshold);
        blob_detector->detect(frame_threshold, keypoints);
#ifdef SHOW_IMAGE
        drawKeypoints(frame,keypoints,frame_key,Scalar::all(-1),DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
#endif
       for (int i=0; i<keypoints.size(); i++){
            x = keypoints[i].pt.x; 
            y = keypoints[i].pt.y;
            size = keypoints[i].size;
            // check x<60 -> left or x >60 -> right 
            
            if (x > 60){
            // check solid line or dashed line for right
                // size > 30 -> solid line
                if (size > 30){
                    right_banned = 1;
                }
                else {
                    right_banned = 0;
                }
            }
            else{
                    // check solid line or dashed line for right
                    // size > 30 -> solid line
                if (size > 30){
                    left_banned = 1;
                }
                else{
                    left_banned = 0;
                }
            }
            
            
            if (size > keypoints[max_index].size) {
                    max_index = i;
            }
            printf("keypoints %d ,x %.3f, y %.3f, size %f \n",keypoints.size(),x,y,size);

            }
        printf("left %d, right %d ",left_banned,right_banned);
        // determine legal state flag
        if ((left_banned == 0) && (right_banned == 1)){
            legal_flag = 1; // only left passing is allowed
        }
        else if ((left_banned == 1) && (right_banned == 0)){
            legal_flag = 2; // only right passing is allowed
        }
        else if ((left_banned == 1) && (right_banned == 1)){
            legal_flag = 3; // no passing allowed
        }
        else if ((left_banned == 0) && (right_banned == 0)){
            legal_flag = 1; // all passing allowed, but default to pass on the left
        }
        printf("legal flag = %d \n", legal_flag);
        
        
        // send legal_flag to red board
        sd_write(asterisk);
        sd_write(asterisk);
        if (legal_flag == 1){
            send[0] = 'A'; 
        }
        else if (legal_flag == 2){
           send[0] = 'B'; 
        }
        else if (legal_flag == 3){
           send[0] = 'C';  
        }
        else if (legal_flag == 4){
           send[0] = 'D';  
        }
        sd_write(send);
        //usleep(5000);
        // sd_write(exclamation);
        // sd_write(exclamation);
        // usleep(5000);
        // // read from red board for current crossing status
        // charsread = sd_readn(received.bytes,4);
        // if (charsread != 1) {
        //     while(sd_readn(received.bytes,4) > 0) {}
        // } else {
		//     printf("value1 = %.3f \n",received.val[0]);

        // }
		// // crossing_flag[0] = 'J';
        // if (crossing_flag[0] == 'X') {
        //     printf("received x");
        // }if (crossing_flag[0] == 'Z') {
        //     printf("received z");
        // }
		// printf("crossing flag = %d\n",received[0]);
			

        
        // Show the frames
#ifdef SHOW_IMAGE
        // imshow("image", frame);
        imshow("mask", frame_threshold);
        imshow("mark", frame_key);
#endif
        waitKey(1);
        char key = (char)waitKey(30);
        frame_count++;
        //if (frame_count >= 8) {
        //     break;
        //}
        //break;
        if (key == 'q' || key == 27)
        {
            break;
        }
    }
    return 0;
}

Main Code of Final Project

C/C++
The code containing the initial setups for the ADC channel, PWM signal, as well as other functions used in this project. It also contains the code that implement the state machines for obstacle avoidance and playing various tones, and the control algorithms.
No preview (download only).

Credits

Hangjun (Jerry) Liu

Hangjun (Jerry) Liu

3 projects • 2 followers
Master of Science student as UC San Diego studying mechanical engineering
Robert Bettuzzi

Robert Bettuzzi

0 projects • 1 follower
Daniel Wang

Daniel Wang

1 project • 1 follower
wxyLuna

wxyLuna

1 project • 1 follower
Thanks to Texas Instrument, Yixiao Liu, and Dan Block.

Comments