tirsdag den 24. november 2009

Øvelse 10

Dato: 20. november 2009
Øvelsens varighed: 5 timer
Gruppemedlemmer: Annette, Samuel og Rasmus


Mål
I denne øvelse undersøges hvordan en behavior based arkitektur er blevet implementeret i subsumption API’en i leJOS NXJ. Specielt vil vi kigge på lejos.subsumption.Behavior interfacet og lejos.subsumption.Arbitrator klassen.

Baggrundsinfo
When most people start programming a robot, they think of the program flow as a series of if-thens, which is remeniscent of structured programming (Figur 1). This type of programming is very easy to get started in and hardly requires any thought or design beforehand. A programmer can just sit at the computer and start typing. The problem is, the code ends up as spaghetti code; all tangled up and difficult to expand. The behavior control model, in contrast, requires a little more planning before coding begins, but the payoff is that each behavior is nicely encapsulated within an easy to understand structure. This will theoretically make your code easier to understand by other programmers familiar with the behavior control model, but more importantly it becomes very easy to add or remove specific behaviors from the overall structure, without negative repercussions to the rest of the code. Let's examine how to do this in leJOS NXJ.
(Kilde: http://lejos.sourceforge.net/nxt/nxj/tutorial/Behaviors/BehaviorProgramming.htm)








Figur 1



Fremgangsmåde
BumperCar
1. Der monteres en touch sensor og ultralydssensor på bilen.

2. Der laves et nyt projekt ud fra BumperCar klassen.

3. Først undersøges hvad der sker når vi selv trykker touch sensoren ind og bliver ved med at holde den inde.

4. Nu skal koden til arbitratoren analyseres.

5. Der skal implementeres en tredje opførsel, Exit. Den skal reagere på tryk på ESCAPE knappen og gå ud af programmet. Den skal implementeres som den højeste prioritet og vi ser hvad der sker når ESCAPE knappen aktiveres.

6. Der laves en ny tråd som har til formål i et givent interval at aflæse den ultrasoniske sensor for at få en afstand. Værdien gemmes i en variabel som er tilgængelig i DetectWall.

7. DetectWall klassen ændres en smule så resultatet af at bilen kommer for tæt på en forhindring resulterer i at bilen først bakker i et sekund og efterfølgende drejer.

8. Undvigemanøvren skal kunne afbrydes og starte forfra igen hvis der detekteres en forhindring imens.



Resultater
Hele den færdige kode til alle øvelser kan ses under projektet Bumper.
1. Se billede af bilen i Figur 2.



Figur 2



2. Vi fandt BumperCar programmet i mappen samples/BumperCar som findes i LEJOS installationsbiblioteket.

3. Når touch sensoren trykkes ind sættes højre motor til at dreje 180 grader bagud og venstre motor sættes til at dreje 360 grader bagud. Det vil resultere i at den bakker mod højre for at undvige forhindringen.


4. I main oprettes to Behaviour instanser, b1 som er DriveForward og b2 som er DetectWall. De tilføjes til et array hvor den adfærd der ønskes lavest prioriteret står først i arrayet. DriveForward får lavest prioritet og DetectWall får næste prioritet. Efterfølgende oprettes en instans af Arbitrator med Behaviour arrayet og i Arbitratorens konstruktor oprettes en instans af Monitor klassen.

Arbitratoren har en start() metode, men den er ikke en tråd!! I start() metoden kaldes monitors start() metode og det er en tråd. Monitoren overvåger hvilken adfærd der skal have kontrollen. Det gøres ved at den går listen med behaviors igennem startende ved det højeste index, det vil sige adfærden med højeste prioritet. takeControl() kaldes på adfærden, her er det først DetectWall, som tester om touch sensoren er trykket ind eller ultralydssensoren er tættere end 25 cm fra en forhindring. Hvis der returneres false gås videre til index-1 hvilket betyder at DriveForward’s takeControl() kaldes og da den er i bunden af subsumption arkitekturen vil den altid gerne have kontrol og returnerer true.
Til sidst testes på om det er nødvendigt at undertrykke andre adfærd, hvilket det ikke er for DriveForward da det er den nederste, men hvis takeControl() på DetectWall havde returneret true skulle DriveForward adfærden undetrykkes.

5. Efter at have, implementeret exit() klassen, og lavet den til den Behavior med højst prioritet, afprøves den på robotten.
Første test, er at trykke på exit knappen, mens DriveForward opførslen er i gang. Programmet går lukket med det samme at exit knappen bliver trykket på, så der er ingen forsinkelse her. Næste test er at trykke exit, mens DetectWall opførslen er i gang. Det viser sig at der er forskel på hvornår man trykker. Hvis der trykkes mens hjulene drejer, sker der ofte ingenting. Hvis trykket lander lige i det hjulene stopper, når robotten de fleste gange at stoppe.

Efter at have rettet Sound.pause til 2000, afprøves exit metoden igen. Når touch sensoren trykkes ind første gang, går der et langt stykke tid før robotten begynder at bakke, som den skal i DetectWall. Dette skyldes at resten af programmet venter, mens Sound.pause(2000) bliver udført. Dette gør også at den ikke opdager et suppress kald mens den venter. Derfor er det nødvendigt at holde exit knappen inde, indtil den kommer til et sted i programmer, hvor dette bliver opdaget.
Hjulenes handlinger ser også ud til at blokere for andre handlinger, da der i versionen med de 20 ms pause, heller ikke blev opfattet et knaptryk på exit mens hjulene kørte. De 20 ms pause foregår inden hjulene bliver sat i gang, så det kan ikke være er overlap fra pausen.

6. Her brugte vi langt tid fordi vi havde problemer med at få implementeret tråden rigtigt. Den meldte ikke fejl under kompilering, men den ville ikke downloade programmet så det var meget vanskeligt at fejlfinde. Helt præcist hvad fejlen var lykkedes det ikke at finde ud af, for vi måtte prøve forfra med at implementere sensor klassen der nedarvede fra Thread.

Med den nye tråd implementeret, opfører robotten sig umiddelbart som den gjorde inden. Det der er forskellen på programmet som det var før, og som det er nu med tråden, er at programmet ikke bliver blokeret imens ultralyds sensoren læser.
Før var der en 20 millisekund pause, for at ultralydssensoren kunne nå at sende sin impuls ud, og få den ind igen. Denne pause gjorde at programmet ikke kunne modtage andet input i det tidsrum. Nu er alt håndtering af ultralyds sensoren lagt over i en tråd for sig, så hovedprogrammet kan køre frit imens.
Tidligere blev sleep kaldet sat op fra 20 til 2000 millisekunder, for at teste hvad der skete. Når touch sensoren blev aktiveret, eller afstanden var for lav, kunne man se, var at robotten først begyndt at bakke, efter de 2000 sekunder var gået. Samtidig kunne den ikke slukkes i tidsrummet.
Dette blev også afprøvet med den nye tråd. Her begyndte robotten med det samme at bakke, når Touch sensoren blev trykket på, men ikke ved ultralyds sensoren. Ved afstandsmålingen gik der omkring to sekunder før den reagerede, hvilket selvfølgelig skyldes at tråden venter i 2000 millisekunder mellem at den læser afstanden. Dog var det muligt at slukke robotten i disse to sekunders pause.
Sound.pause() er ikke det eneste der blokerer for slukning af robotten når den bakker. Når den bakker, sættes begge motoere til at dreje, men den første har "immidiate return" sat til True, hvilket den anden ikke har. Fordi det sidste motor kald ikke har immidiate return, blokere den stadig for resten af programmet til den er færdig.

7. Bilen sættes til først at bakke i et sekund inden den drejer ved at bruge Motors backward() metode og derefter kalde Thread.sleep() i 1000ms. Det betyder dog at det ikke umiddelbart er muligt at afbryde bagud kørslen hvis en forhindring detekteres imens så det er ikke den smarteste løsning. Vi har dog ikke tid til at gå mere ind i problemstilingen.

8. Som nævnt bruger vi Thread.sleep() metoden til at få bilen til at bakke i et sekund og derfor kan vi ikke bare afbryde og starte forfra midt i det hele.

Konklusion
Vi har undersøgt hvordan behavior og arbitrator fungerer. Der har specielt været fokus på at der ved specielle omstændigheder kan blokeres for en adfærd. Vi havde problemer med at implementere sensorlæsningen som en tråd, og det brugte vi lang tid på.

Referencer
Bumper, videreudvikling af BumperCar (Brian Bagnall and Lawrie Griffiths, modified by Roger Glassey)


Ingen kommentarer:

Send en kommentar

Faste læsere

Bidragydere