torsdag den 4. november 2010

lab note 8

Attendances: Carsten, Dan
Duration: 11:30 - 13:15

Goal

The main goal is to experiment with defining multiple behaviors and
defining how they work together

Plan

We experiment with the SoundCar.java program which have 3 behaviors:
drives randomly, avoids obstacles and plays sounds. The plan consist
of:



  • Understanding the LCD output.


  • Analysing the behavior of our robot.


  • Understanding how priority of behaviors are implemented.


  • Include the light follower behavior from last week.

Robot

We added a distance sonic sensor to our robot from lab 7. The robot
now have 2 distance sensors and 1 sonic sensor.


Understanding the LCD output

0/1: in Random drive mode everything is 0. When the robot is backing
up (avoiding) the drive is 1. When the sound is playing, both drive and
avoid are 0. This fits with the code that a thread has a 1 if its
engine use is suppressed and 0 if that thread can access the motors.

s/f/b: stop/forward/back. Indicates what a thread commands the motors
to do (go forward/back or stop). When drive have f and avoid have
b the robot is going backwards.

Analysing the behavior of our robot

With only the drive thread it is just driving forward randomly. With
the avoid and sound active it is inactive unless something is put in
front of it (then it avoids). It can be seen that it will stop in the
middle of an avoid if the sound is played.

Understanding how priority of behaviors are implemented

Daemon

One reason to use daemon thread is because the program stops when only
daemon threads remain (so in this case we don't need to stop the 3
threads). Daemon threads are a service running in the background,
Setting these threads(behaviors) as daemons signify they are services
and not directly part of the program (they are just always running in
the background).

Priority

The suppressCount integer signify how many higher-priority threads
have wanted access to the motor (by calling suppress()).


When the robot is avoiding it calls suppress() (which sets
drive.suppressCount to 1), then does its avoidance, then calls
release() (which sets drive.suppressCount to 0).

If in the middle of an avoidance the sound is played, sound calls
suppress() which sets avoid.suppressCount to 1 and drive.suppressCount
to 2, then when sound releases avoid.suppressCount is set to 0 and
drive.suppressCount to 1 (which means avoid now have access to the
motors and drive still does not have access).

Include the light follower behavior from last week

Our light follower from lab 7 used motors directly, but for the
suppress priority to work it needs to use Car, so we started by
modifying that.

We insert the light follower thread above the drive but below the
avoid in the hierarchy. This results in the robot driving randomly
when there is no light source of significant intensity (above the
average of the last couple of seconds). The robot will spend most of
its time driving around after the light because the robot will
usually start up again when the average stabilizes. If the robot gets
too close to an obstacle the avoid thread takes over and tries to
avoid. While playing a sound the robot will still stop moving.

The Final implementation of the lightfollower class look like this:
(The important parts are highlighted with bold.)
import lejos.nxt.Button;
import lejos.nxt.LCD;
import lejos.nxt.MotorPort;
import lejos.nxt.SensorPort;
import lejos.nxt.addon.RCXLightSensor;

public class LightFollower extends Behavior{

private int MAXLIGHT;
private int MINLIGHT;

RCXLightSensor lightSensorLeft = new RCXLightSensor(SensorPort.S3);
RCXLightSensor lightSensorRight = new RCXLightSensor(SensorPort.S2);
MotorPort leftMotor = MotorPort.C;
MotorPort rightMotor= MotorPort.B;

private final int forward = 1,
backward = 2,
stop = 3;

int averageLeft = 0,averageRight = 0;

final int BETA = 25;

public LightFollower(String name, int LCDrow, Behavior b){
super(name,LCDrow,b);
}

public void run()
{
MAXLIGHT = 0;
MINLIGHT = 1000;
while(! Button.ESCAPE.isPressed()){
int normalizedLightLeft = normalize(lightSensorLeft.getNormalizedLightValue());
int normalizedLightRight = normalize(lightSensorRight.getNormalizedLightValue());
averageLeft = average(averageLeft,normalizedLightLeft);
averageRight = average(averageRight,normalizedLightRight);
int powerToLeft = 0;
int powerToRight = 0;
if(normalizedLightLeft > averageLeft){
powerToLeft = normalizedLightLeft;
}
if(normalizedLightRight > averageRight){
powerToRight = normalizedLightRight;
}
suppress();
forward(powerToLeft,powerToRight);
delay(100);
stop();

release();
}
}

int normalize(int light){
if (light > MAXLIGHT)
MAXLIGHT = light;
if (light < minlight =" light;" minlight ="=" output =" 100" output =" 0;"> 100)
output = 100;
LCD.drawString("output is: " + output, 0, 7);
return output;
}

int average(int formerAverage, int light){
int output = formerAverage + (BETA*(light - formerAverage))/100;
return output;
}
}

The robot behaves mostly like the one from last week except for
avoiding stuff. The sound part is played every few seconds. The random
drive thread is not noticeable active, this is likely because the
light follower is only inactive when waiting for the average light
level to level out.

Results

We have analyzed and understood the SoundCar.java program. And we
have learned how to implement different behaviors with different
priorities using threads.

Ingen kommentarer:

Send en kommentar