RoboGolf

Over the 2003 summer, I had the pleasure of completing a two-week course on robotics at the UW. During those two weeks, I developed the following code:

// This program by Andrew Ferguson
// Copyright 2003 Andrew Ferguson
// The list below tells where the stuff should be plugged in
//Begin
int lt_bump = 7; //left bump sensor
int rt_bump = 8; //right bump sensor

int left_motor = 0; //left motor
int mill_motor = 1; //mill motor
int right_motor = 3; //right motor

int rear_bump = 9; //rear bump sensor

int alpha_pol = 0; //1st polarized light sensor
int beta_pol = 1; //2nd polarized light sensor, rotated 90 degrees

int lt_ir = 4; // first IR light sensor/emiter
int rt_ir = 3;// second IR light sensor/emiter
int break_beam_a = 15; //break beam sensor for detecting the balls
int break_beam_b = 14; //break beam sensor for detecting the balls

int rotation_left = 6; //left rotation sensor
int rotation_right = 5
; //right rotation sensor
//End

//The list below declares global variables, the varible does NOT need to be global, then do NOT put it here
//Begin
int foo_right = 0; // how many times bot has turned right
int foo_left = 0; // how many times bot has turned left

int last_turn = 0; // Which way the bot turned last; 0 = Left and 1 = Right

int lt_speed = 25; //how fast the left side is going
int rt_speed = 25; //how fast the right side is going

int ball_in_hopper = 1; //whether the a ball has been collected - 0 for no, 1 for yes

int pol_home = 1; //Which polorized light the sensor should look for/care about; possible values are 1 and -1

int sensor_value; //polarized sensor delta value

float system_time = seconds(); //time since epoch of system restart

float master_time = 0.; //This is the master start time, which is used to determine when it should start looking for home

int rt_cnt; //How many times the right rotation sensor has been hit
int lt_cnt; //How many times the left rotation sensor has been hit

int line_found; //This determines if the bot has detected the line for a given set of balls trying to be dropped...please no jokes

int in_motion = 1; //If the bot is in motion. This is normal set to 1 (i.e. Yes) until the game is over (180 seconds after boot), in which case the value is changed to 0 (no)
//End

void count_both (void) {
    int lt_previous_hole; //if the previous check on the left side was hole or not
    int rt_previous_hole; //if the previous check on the right side was a hole or not
    while(1) {
        if(lt_previous_hole == 0){ //the previous check was not a hole...
            if (analog(rotation_left) < 100){//... if the there is a hole now, then count that
                lt_cnt++; //counting the hole
                lt_previous_hole = 1; //setting the check to say there was a hole this time around
            }
        }
        else{
            if (analog(rotation_left) >= 100){ //if the previous check was a hole, then check to see if it's not a hole
                lt_cnt++;// counting the hole, or lack thereof
                lt_previous_hole = 0; //setting the check to say there was not a hole this time
            }
        }
        if(rt_previous_hole == 0){//the previous check was not a hole...
            if (analog(rotation_right) < 100){//... if the there is a hole now, then count that
                rt_cnt++;//counting the hole
                rt_previous_hole = 1;//setting the check to say there was a hole this time around
            }
        }
        else{
            if (analog(rotation_right) >= 100){//if the previous check was a hole, then check to see if it's not a hole
                rt_cnt++; //counting the hole, or lack thereof
                rt_previous_hole = 0; //setting the check to say there was not a hole this time
            }
        }
        defer();
    }
}

void stuck_master (void){
    int i;
    while(in_motion){
        lt_cnt = 0; //reset the left count to zero
        rt_cnt = 0; //reset the right count to zero
        sleep(2.0); //wait 2 seconds...now we have fresh count
        if ( (lt_cnt < 20) || (rt_cnt < 20) ) //if either the left or the right count is less then 10, then we just might be stuck
          {
            beep();
            stop();
            while ( (lt_cnt < 50) && (rt_cnt < 50) ){ //reverse for 20 counts
                lt_speed = -100;
                rt_speed = -100;             
                defer();
            }
            rt_speed = 25;
            lt_speed = 25;
          }
        defer();
    }
}

void go_home (void) //when time is up, try and find home!
{
    while(1) {
        while (seconds() <= 120.) { //if there are at least 2 minutes (120 seconds) left, we can go about our business
            defer();
            //beep();
        }
        while (seconds() <= 150. && (ball_in_hopper == 1) ) { //when there is a minute left, keep looking for balls
            defer();
            //beep();
        }       
        while (seconds() <= 150. && (ball_in_hopper == 0) ) { //when there is a minute left, start looking for the hole to drop of whatever balls we have...assuming we have balls
            ir_sense();
            //in_motion = 0;
            defer();
            //beep();
        }
        while (seconds() <180.) {  // when there are a 30 seconds left, start looking for the polarized light...note: there is no defer() or sleep(x.x) becuase this is a priority 1 process
            printf("Phoning Home\n");
            //in_motion = 0;
            beep();
            pol_sensor();
            defer();
        }
        while (seconds() > 180.) {  //when the game is over, shut down all motors and beep...how nice
            //printf("Shutting down\n");
            //beep();
            in_motion = 0;
            beeper_on();
            ao();
            defer();
        }
        defer();
    }
}

/*void ball (void){ //This checks to see if a ball is in the hopper or not
    while(1) {
        if (_raw_analog(break_beam) < 10)
          {
            ball_in_hopper = 0; // ball is NOT in hopper
        }
        else if (_raw_analog(break_beam) > 10) //ball IS in hopper
            {
              ball_in_hopper = 1;
              sleep(5.0);
          }
          sleep(.01);
    }
}
*/
void pol_sensor (void) // detects the polarization of the light source
{
    sensor_value = (_raw_analog(beta_pol) - _raw_analog(alpha_pol) ); // sets the delta value for the polarization
    lt_speed = 100; //full speed, left side
    rt_speed = 100; //full speed, right side
    if ( (sensor_value < -60) && (pol_home == 1 ) ){ //if the sensor value is less than 60 and the light is NOT home, turn around
        rt_speed = 100;
        lt_speed = -100;//lt_speed - 15;
    }
    if ( (sensor_value > -30) && (pol_home == -1) ){//if the sensor value is greater than -30 and the light is NOT home, turn around
        lt_speed = 100;
        rt_speed = -100;//rt_speed - 15;
    }
    sleep(.2);
    printf("%d\n", sensor_value);
}

void ir_sense(void) { //this tries to find the black line, which hopefully will lead to the hole. If not, the robot will turn around and go the other way, which HAS to lead to the black hole
    beep();
    printf("%d\n", line_found);
    while ( (analog(lt_ir) > 100) && (analog(rt_ir) > 100) ){ //if there are black lines under both the IR sensors :: this would happen if the robot approaced the line at a 90 degree angle
        lt_speed = 20;
        rt_speed = 20;
        //sleep(2.0);
        system_time = seconds();
        defer();
    }
    while( (analog(lt_ir) < 100) && (analog(rt_ir) < 100) && (line_found == 0) ){ //If there are no black lines and the line has NOT been found before
        lt_speed = 15;
        rt_speed = 25;
        defer();
    }
    while ( (analog(rt_ir) > 100) && (line_found == 0) ){ //if there is a black line under the right IR sensor and the line has not been found yet...
        rt_speed = 20;
        lt_speed = 20;//lt_speed - 15;
        system_time = seconds();
        line_found = 1;
        while(analog(lt_ir) < 100){ //...wait until the left IR sensor passes the line...
            defer();
        }
        while(analog(lt_ir) > 100){ //...then when it does hit the line, turn the other way
            rt_speed = -20;
            lt_speed = 20;
            sleep(1.5);
        }
        defer();
    }
    while ( (analog(lt_ir) > 100) && (line_found == 0) ){ //if there is a black line under the left IR sensor and the line has not been found yet...
        lt_speed = 20;
        rt_speed = 20;//rt_speed - 15;
        system_time = seconds();
        line_found = 1;
        while(analog(rt_ir) < 100){//...wait until the right IR sensor passes the line...
            defer();
        }
        while(analog(rt_ir) > 100){//...then when it does hit the line, turn the other way
            lt_speed = -20;
            rt_speed = 20;
            sleep(1.5);
        }
        defer();
    }
   
    while ( (analog(rt_ir) > 100) && (line_found == 1) && (analog(lt_ir) < 100) ){ //if the right IR sensor sees the black line, but the left one doesn't and the line has been found before, turn a bit the other way to get back on track
        rt_speed = 30;
        lt_speed = -10;//lt_speed - 15;
        system_time = seconds();
        defer();
    }
    while ( (analog(lt_ir) > 100) && (line_found == 1) && (analog(rt_ir) < 100) ){//if the left IR sensor sees the black line, but the right one doesn't and the line has been found before, turn a bit the other way to get back on track
        lt_speed = 30;
        rt_speed = -10;//rt_speed - 15;
        system_time = seconds();
        defer();
    }
    while( (analog(lt_ir) < 100) && (analog(rt_ir) < 100) && (line_found == 1) ) { // if both IR sensors don't see the black line :: this would happen if: A) The robot was on track or B) if the robot reached the end of the black line
        if( (seconds() - system_time) > 1.0) { // If more than 1 second has passed since the last course correction, start going in circles to try and reaquire the line
            lt_speed = -20;
            rt_speed = 20;
            while(analog(rt_ir)< 100) //while the right IR sensor doesn't seen the black line...
              {
                if( (seconds() - system_time) > 6.0) {//...and six seconds have passed, stop looking for the line...it's probably gone...
                    system_time = seconds();
                    break;
                }
                if (analog(lt_ir)> 100){//...or if the left line is seen, turn the other way :: the bot is really on track...just going straight
                    lt_speed = 20;
                    rt_speed = -20;
                    system_time = seconds();
                    while(analog(lt_ir)> 100){ //...wait while the left IR sensor is still on the black line...
                        defer();
                    }
                    while(analog(lt_ir)< 100) { //...when the left IR sensor gets off the back line...
                        if( (seconds() - system_time) > 4.) { //...wait until four seconds have passed and then break out
                            break;
                        }
                        defer();
                    }
                    break;
                }
                //system_time = seconds();
                break;
                defer();
            }
        }
        defer();
    }
}

void turn_left(void){ //turn the robot left
    //printf("Turning left:%d\n", foo_left);
    fd(left_motor);
    bk(right_motor);
    sleep(0.3);
    ao ();
    fd(mill_motor);
}

void turn_right(void){ //turn the robot right
    //printf("Turning right:%d\n", foo_right);
    bk(left_motor);
    fd(right_motor);
    sleep(0.3);
    ao ();
    fd(mill_motor);
}

void go_forward(void){ //make the robot go forward
    //printf("Going forward\n");
    motor(left_motor, lt_speed);
    motor(right_motor, rt_speed);
}

void go_backward(void){ //make the robot go backwards
    //printf("Going backwards\n");
    bk(left_motor);
    bk(right_motor);
    sleep (.5);
    ao ();
    fd(mill_motor);
}

void stop (void){ //make the robot stop
    //printf("Stopped\n");
    ao ();
    fd(mill_motor);
}

void main_movement (void) //main set of robot commands, pretty much just make sure it doesn't hit and thing and what to do if it does
{
    while (in_motion)
      {
        go_forward();
        //stuck_master(); //the ultimate in stuckness prevention!!
        /*while ( (digital(lt_bump) == 0) & (digital(rt_bump) == 0) )
          {
            //This section is commented out becuase it will be really hard for the robot get stuck on anything, esp. with the new physical collision avoidance system
            if( (seconds() - system_time) > 10.0)
              {
                stop();
                printf("10 second are up.  I'm going backwards");
                go_backward();
                printf("Turning %d\n", last_turn);
                if (last_turn == 1)
                  {
                    turn_right();
                    last_turn = 0;
                    system_time = seconds();
                }
                else{
                    turn_left();
                    last_turn = 1;
                    system_time = seconds();
                }
                go_forward();
                system_time = seconds();
            }
            defer();
        }
*/
        if ( (digital(lt_bump) == 1) ) //left turn
          {
            foo_left ++;
            stop();
            go_backward();
            if (foo_left%3 == 0)
              {
                turn_right();
                foo_right = 0;
                foo_left = 0;
            }
            else{
                turn_left();
            }
            last_turn = 0;
            system_time = seconds();
        }
        if ( (digital(rt_bump) == 1) ) //right turn
          {
            foo_right ++;
            stop();
            go_backward();
            if (foo_right%3 == 0)
              {
                turn_left();
                foo_right = 0;
                foo_left = 0;
            }
            else {
                turn_right();
                last_turn = 1;
                system_time = seconds();
            }
        }
        defer();
    }
}

void main() //Begin the main program
{
    printf("JCN v20.0 by Andrew and Mariah\n");
    //sleep(1.0);
    beep ();
    fd(mill_motor); //start the mill motor thingy
    start_process(main_movement() ); //start the main set of movements, including collision avoidance
    start_process(go_home() ); //start the master clock, and prepare to go home
    start_process(count_both() );
    start_process(stuck_master() );
   
    while (1)
      {
       
        line_found = 0;
        while ( (in_motion) && ( (digital(break_beam_a) == 0) || (digital(break_beam_b) == 0) )){
            //printf("%d - %d\n", digital(14), digital(15) );
            ir_sense(); //starts the black-line finding sub-routine
            sleep(.01);
        }
        printf("%d - %d\n", digital(14), digital(15) );
        //printf("Ball NOT in hopper\n");
        sleep(.01);
    }
}

I really like this part:
//stuck_master(); //the ultimate in stuckness prevention!!

Note: This was code that I originally had in a ‘Code’ page, but I’m moving it to a post now. This code is probably really old (years and years old). I enjoy laughing at myself and so should you.