CS 372 Artificial Intelligence

Robot Building Lab

Session 4

Exercises for this week

Program your robot to seek light while also avoiding obstacles. Implement your solution in the subsumption style. A simple example of how to do this in Interactive C is provided below.

Your robots will be tested in a series of progressively more difficult configurations. You must use the same Interactive C program for each situation.

 

Grading will be based on the overall functionality of your robot. Your robot should be able to pass the first three tests, but the last may be more difficult. The starting orientation of the robot will be arbitrary.

 

Sample Interactive C Program

/* Here is one possible way to implement a subsumption style 
   architecture in Interactive C.  This method is described
   in Mobile Robots by Jones and Flynn publised in 1993 by AK Peters.
 
   Each behavior has a pair of global variables associated with it: a 
   command and a flag.  When the flag is true, the command  represents the 
   action chosen by the behavior.  An arbitrator gives control to the highest 
   priority behavior whose flag  is true.
 
   In this simple example, there are three behaviors: cruise which 
   always wants to go forward, follow which turns towards light, and 
   escape which backs and turns away from obstacles.   Cruise has the 
   lowest priority and escape has the highest priority.
*/

#define Llight 2
#define Rlight 0
#define Lmotor 3
#define Rmotor 1
#define Lbump 9
#define Rbump 7

#define FORWARD 0
#define BACKWARD 1
#define TURNLEFT 2
#define TURNRIGHT 3
#define BACKthenLEFT 4
#define BACKthenRIGHT 5

int cruise_command;
int cruise_output_flag;
int follow_command;
int follow_output_flag;
int escape_command;
int escape_output_flag;
int motor_input;

/* The order in which the behavior results are checked
  determines the priority--first checked have low priority
  and last checked have high priority. */
void arbitrate() {
    while(1) {
        if (cruise_output_flag)
            motor_input = cruise_command;
        if (follow_output_flag)
            motor_input = follow_command;
        if (escape_output_flag)
            motor_input = escape_command;
    }
}

void motor_driver(){
    while (1) {
        if (motor_input == FORWARD) {
            printf("FORWARD\n");
            motor(Lmotor, 100);
            motor(Rmotor, 100);
        }
        else if (motor_input == BACKWARD) {
            printf("BACKWARD\n");
            motor(Lmotor, -100);
            motor(Rmotor, -100);
        }
        else if (motor_input == TURNLEFT) { 
            printf("TURNLEFT\n");
            motor(Lmotor, -100);
            motor(Rmotor, 100);
        }
        else if (motor_input == TURNRIGHT) {
            printf("TURNRIGHT\n");
            motor(Lmotor, 100);
            motor(Rmotor, -100);
        }
        else if (motor_input == BACKthenLEFT) {
            printf("BACKthenLEFT\n");
            motor(Lmotor, -100);
            motor(Rmotor, -100);
            sleep(.6);
            motor(Lmotor, -100);
            motor(Rmotor, 100);
            sleep(.4);
        }
        else if (motor_input == BACKthenRIGHT) {
            printf("BACKthenRIGHT\n");
            motor(Lmotor, -100);
            motor(Rmotor, -100);
            sleep(.6);
            motor(Lmotor, 100);
            motor(Rmotor, -100);
            sleep(.4);          
        }
        else {
            printf("MOTORS OFF\n");
            motor(Lmotor, 0);
            motor(Rmotor, 0);
        }
    }
}

void cruise() {
    while(1) {
        cruise_command = FORWARD;
        cruise_output_flag = 1;
    }
}

int abs(int value) {
    if (value >= 0)
        return(value);
    else return(-1*value);
}

void follow() {
    int Llightval, Rlightval;
    int delta, threshold;
    
    threshold = 13;
    while(1) {
        Llightval = analog(Llight);
        Rlightval = analog(Rlight);
        delta = Rlightval - Llightval;
        if (abs(delta) > threshold) {
            if (delta > 0)
                follow_command = TURNLEFT;
            else
                follow_command = TURNRIGHT;
            follow_output_flag = 1;
        }
        else
            follow_output_flag = 0;
    }
}

void escape() {
    int Lbumpval, Rbumpval;
    
    while (1) {
        Lbumpval = digital(Lbump);
        Rbumpval = digital(Rbump);
        if (Lbumpval && Rbumpval) {
            escape_command = BACKthenLEFT;
            escape_output_flag = 1;
        }
        else if (Lbumpval) {
            escape_command = BACKthenRIGHT;
            escape_output_flag = 1;
        }
        else if (Rbumpval) {
            escape_command = BACKthenLEFT;
            escape_output_flag = 1;
        }
        else
            escape_output_flag = 0;
    }
}

/* Initiate all the processes. */
void main() {
    start_process(motor_driver());
    start_process(cruise());
    start_process(follow());
    start_process(escape());
    start_process(arbitrate());
}

 

This is a sample of how to implement subsumption architectures. This behavior in itself does not implement all of the desired behaviors. However, you may implement it and observe the behavior to see how subsumption actually works. Also, before you implement, you should make use of defer() at the end of all the loops.That guarantees that the process exits at a place where one pass of decisions has been accounted for.


Back to CS372 Lab Pages | Back to CS372 Page