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.
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 setsdrive.suppressCount
to 1), then does its avoidance, then callsrelease()
(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 anddrive.suppressCount
to 1 (which means avoid now have access to themotors 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.
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