Ø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)
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.
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.
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.
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)