Varighed: 3
Deltagere: Nick, JC og Allan
Formål med øvelsen
Dagens øvelse går ud på at lave en robot som, for en udefrakommende observatør, ser ud til at have mere end en type opførsel. Dette er i kontrast til lab 7 hvor robotterne kun havde en type opførsel.
Planen for øvelsen
Planen for i dag er følgende:
- Bygge Lego car 9797 med en ultrasonic sensor.
- Afprøvning af programmet SoundCar.java.
- Hvad siger LCD displayet når SoundCar.java køres?
- Analyse af koden bag SoundCar, hvilke typer opførsler har robotten? Evt. video af de forskellige opførsler, dvs. hvor kun en opførsel er aktiveret af gangen.
- Hvordan virker Behavior.java? Hvordan kontrollere den hvilken opførsel som har adgang til motorerne på et givent tidspunkt?
- Behavior.java er baseret på Rodney Brooks subsumption architecture, hvordan er denne i forhold til Fred Martin, [4, page 214-218]?
- Modificer SoundCar.java ved at tilføje en ekstra opførsel: "Kør i mod lys".
Forventede resultater
Det forventes at robotten vil være mere uforudsigelig jo flere opførsler den har at forholde sig til.
Det forventes at robotten vil være mere uforudsigelig jo flere opførsler den har at forholde sig til.
Afprøvning af programmet SoundCar.java
Ved kørsel af SoundCar ser displayed ud som følger:

Her repræsentere Drive, Avoid og Play de tre forskellige simple opførsler robotten kan have, som tilsammen giver den mere avancerede opførsel.
Drive køre tilfældigt rundt og har i denne kode laveste prioritet, hvilket vil resultere i at det er robottens standard opførsel som udføres så snart ingen tråde er undertrykte. [AIMEMO]
Robotten kører play hvert 10 sekund, hvilket har top prioritet. Det at Play har top prioritet betyder at hvis der ikke var 10 sekunders ventetid ville den spille lyden hele tiden, da denne har højere prioritet end de to andre (Drive og Avoid har et 1 tal, mens Play har 0).
Avoid har en prioritet som ligger under Play og over Drive, hvilket betyder den kan undertrykke Drive og blive undertrykt af Play.
Den sidste række på diplayet repræsentere motor kald, dvs. forward (f), backward (b) og stop (s).
Behavior.java
Behavior extender thread og har en run metode, som kører uafhængigt af de andre tråde på VM'en. Hver Behavior har en Behavior feltvariable som indeholde den Behavior som den er højere end i hierakiet. Den nederst Behavior indeholder ingen, så den kan ikke suppresse andre.
Når en Behavior mener at den skal udføre sin opførelse, suppresser den de Behaviors der er under den, ved at kalde suppresse, som suppresser dens egen Behavior som er under den, som suppresser den under den osv... Når den er færdig med den opførelse den skulle, kan den sende en release ud og derved give plads til de andre Behaviors.
Hvilken Behavior der kommer til afhænger af VM'ens styring af tråde, men da vi antager at det er en fair fordeling, vil alle tråde komme til.
På denne måde kan vi bygge et hieraki op af opførelser der kan overtrumfe hinanden. Da metoderne suppresse og release er synchronized, bliver alle suppressed og released samtidig.
Om en Behavior er suppressed afhænger af en counter frem for en boolean. Dette skyldes at Behavior der er i gang med sin egen udførelse, kan blive suppressed og lige efter release Behaviors under den. Det laveste niveau ville da ikke vide at en Behavior længere oppe end dens egen parent var i gang og ville da tro at den måtte udføre opgaver. Med en counter skal alle over den have kaldt release for at den kan komme til.
Behavior extender thread og har en run metode, som kører uafhængigt af de andre tråde på VM'en. Hver Behavior har en Behavior feltvariable som indeholde den Behavior som den er højere end i hierakiet. Den nederst Behavior indeholder ingen, så den kan ikke suppresse andre.
Når en Behavior mener at den skal udføre sin opførelse, suppresser den de Behaviors der er under den, ved at kalde suppresse, som suppresser dens egen Behavior som er under den, som suppresser den under den osv... Når den er færdig med den opførelse den skulle, kan den sende en release ud og derved give plads til de andre Behaviors.
Hvilken Behavior der kommer til afhænger af VM'ens styring af tråde, men da vi antager at det er en fair fordeling, vil alle tråde komme til.
På denne måde kan vi bygge et hieraki op af opførelser der kan overtrumfe hinanden. Da metoderne suppresse og release er synchronized, bliver alle suppressed og released samtidig.
Om en Behavior er suppressed afhænger af en counter frem for en boolean. Dette skyldes at Behavior der er i gang med sin egen udførelse, kan blive suppressed og lige efter release Behaviors under den. Det laveste niveau ville da ikke vide at en Behavior længere oppe end dens egen parent var i gang og ville da tro at den måtte udføre opgaver. Med en counter skal alle over den have kaldt release for at den kan komme til.
Behavior.java er baseret på Rodney Brooks subsumption architecture, hvordan er denne i forhold til Fred Martin, [4, page 214-218]
Fred Martin beskriver en form for hjemmelavet schedulerings algoritme som kan bruges i systemer som ikke understøtter threading, hvilket er relevant for nogle embedded systemer. NXT'en understøtter threading og derfor ville det ikke være relevant at benytte Fred Martins løsning.
Den helt store forskel er dog at der ikke er tale om tråde, hvilket vil sige koden altid vil køre færdig og aldrig vil blive afbrudt, hvilket kan lade sig gøre når tråde benyttes.
Kør i mod lys
SoundCar er blevet modificeret så den kører mod lyset, ved at tilføje en ekstra opførsel fra lab7. Dette gøres ved at oprette en tråd ved at nedarve fra Behavior og implementere run metoden.
public class LightDrive extends BehaviorYderligere er SoundCar's main metode modificeret så den starter den nye behavior:
{
public LightDrive( String name, int LCDrow, Behavior b)
{
super(name, LCDrow, b);
}
public void run()
{
float maxRight = -1;
float minRight = -1;
float maxLeft = -1;
float minLeft = -1;
float powerR;
float powerL;
LightSensor lsRight;
LightSensor lsLeft;
lsRight = new LightSensor(SensorPort.S2);
lsRight.setFloodlight(false);
lsLeft = new LightSensor(SensorPort.S3);
lsLeft.setFloodlight(false);
while (true)
{
suppress();
float lsRightValue = lsRight.readValue();
float lsLeftValue = lsLeft.readValue();
if(maxRight == -1) {
maxRight = lsRightValue;
minRight = lsRightValue;
maxLeft = lsLeftValue;
minLeft = lsLeftValue;
} else {
if(maxRight < maxright =" lsRightValue;" maxleft =" lsLeftValue;"> lsRightValue) minRight = lsRightValue;
if(minLeft > lsLeftValue) minLeft = lsLeftValue;
}
powerR = -1;
powerL = -1;
if(lsRightValue == minRight) powerR = 0;
else if (lsRightValue == maxRight) powerR = 100;
if(lsLeftValue == minLeft) powerL = 0;
else if (lsLeftValue == maxLeft) powerL = 100;
if(powerR == -1) powerR = ((lsRightValue - minRight)/(maxRight-minRight))*100;
if(powerL == -1) powerL = ((lsLeftValue - minLeft)/(maxLeft-minLeft))*100;
forward((int) powerL, (int) powerR);
release();
}
}
}
Vi har valgt at lave sådan at robotten kun følger lys og undgår forhindringer, da dette er nemmere at teste.
public class SoundCar
{
public static void main(String [] args)
{
AvoidFront af;
// PlaySounds ps;
LightDrive ld;
LCD.drawString("Sound Car",0,0);
LCD.refresh();
//rd = new RandomDrive("Drive",1, null);
//ps = new PlaySounds ("Play ",3,af);
ld = new LightDrive("Light", 1, null);
af = new AvoidFront ("Avoid",2,ld);
//rd.start();
af.start();
//ps.start();
ld.start();
while (! Button.ESCAPE.isPressed())
{
// rd.reportState();
af.reportState();
// ps.reportState();
ld.reportState();
}
LCD.clear();
LCD.drawString("Program stopped",0,0);
LCD.refresh();
}
}
Ingen kommentarer:
Send en kommentar