... | ... | @@ -25,9 +25,9 @@ Vores plan er at følge instruktionerne for Lab session 9 [1]. Indledningsvist, |
|
|
|
|
|
### BumperCar
|
|
|
|
|
|
BumperCar programmet er et eksempel på et behavior-based control program fra leJOS NXJ. Programmet består af to slags behaviors: DriveForward og DetectWall, der begge implementere interfacet Behavior samt benytter en instans af klassen Arbitrator til at styre hvornår hvilken behaviors får kontrol.
|
|
|
BumperCar programmet er et eksempel på et behavior-based control program fra leJOS NXJ. Programmet består af to slags behaviors: DriveForward og DetectWall, der begge implementere interfacet Behavior samt benytter en instans af klassen Arbitrator til at styre hvornår hvilken behavior får kontrol.
|
|
|
|
|
|
*Billede 1: BumperCar - sumobryderbase påmonteret med bumper og ultrasonisk sensor*
|
|
|
*Billede 1: BumperCar - sumobryderbase påmonteret med bumper og ultralydssensor*
|
|
|
|
|
|
![IMG_0402](http://gitlab.au.dk/uploads/group-5/group-5-lesson-9/f26dc8708d/IMG_0402.JPG)
|
|
|
|
... | ... | @@ -43,7 +43,7 @@ Video 1 [13] ovenfor viser at når tryksensoren holdes inde bakker begge robotte |
|
|
|
|
|
#### Exit behavior
|
|
|
|
|
|
For at gøre robotten i stand til at stoppe midt i et program, implementerede vi en tredje behavior, Exit, som har den højeste prioritet. Målet hermed er at hvis der trykkes på ESCAPE-knappen mens en anden behavior er aktiv, tager Escape-behavioren kontrol og kalder System.Exit(0) for at stoppe programmet. Video 2 [14] demonstrerer dennem Escape-behavior.
|
|
|
For at gøre robotten i stand til at stoppe midt i et program, implementerede vi en tredje behavior, Exit, som har den højeste prioritet. Meningen hermed er at hvis der trykkes på ESCAPE-knappen mens en anden behavior er aktiv, tager Escape-behavioren kontrol og kalder System.Exit(0) for at stoppe programmet. Video 2 [14] demonstrerer Escape-behavioren.
|
|
|
|
|
|
*Video 2: Demonstration af Escape-behavior*
|
|
|
|
... | ... | @@ -85,12 +85,13 @@ for (int i = maxPriority; i >= 0; i--) { |
|
|
}
|
|
|
}
|
|
|
```
|
|
|
Metoden takeControl() for DriveForward behavioren bliver ikke kaldt, da behavior arrayet er sorteret i stigende rækkefølge (mht. prioritet) og gennemløbet af arrayet er aftagende. Dette betyder at hvis en behavior placeret sidst i arrayet returnerer true i sit takeControl()-kald, stoppes gennemløbet og denne behavior får kontrol, hvorved behaviors placeret forrest i arrayet ignoreres.
|
|
|
|
|
|
Her kan det ses at takeControl() metoden for DriveForward behavioren ikke bliver kaldt, da behavior arrayet er sorteret i stigende rækkefølge (mht. prioritet) og gennemløbet af arrayet er aftagende. Dette betyder at hvis en behavior placeret sidst i arrayet returnerer true i sit takeControl()-kald, stoppes gennemløbet og denne behavior får kontrol, hvorved behaviors placeret forrest i arrayet ignoreres.
|
|
|
|
|
|
|
|
|
#### Undgå delay i takeControl-metoden
|
|
|
|
|
|
DetectWall-behaviorens takeControl()-metode indeholder et kald til ultralydssensorens getDistance() metode. GetDistance() metoden er blokerende, hvilket ikke er hensigtsmæssigt i takeControl() metoden, fordi det hæmmer arbitorens evne til at vælge mellem behaviors. Vi kan overkomme dette langsomme kald, ved at implementere en lokal tråd i DetectWall-behavioren. Denne tråd kalder hvert 20. msek getDistance() metoden på ultralydssensoren, og gemmer en sensorværdien (afstanden) i variablen _is_within_wall_range. Denne værdi kan dermed hurtigt tilgås fra takeControl()-metoden. Den implementerede lokale tråd kan ses i Java-kode 3, mens den nye takeControl-metode kan ses i Java-kode 4 nedenfor.
|
|
|
DetectWall-behaviorens takeControl()-metode indeholder et kald til ultralydssensor getDistance() metode. getDistance() metoden er blokerende, hvilket ikke er hensigtsmæssigt i takeControl() metoden, fordi det hæmmer arbitorens evne til at vælge mellem behaviors. Vi kan overkomme dette langsomme kald, ved at implementere en lokal tråd i DetectWall-behavioren. Denne tråd kalder hvert 20. msek getDistance() metoden på ultralydssensoren, og gemmer en sensorværdien (afstanden) i variablen _is_within_wall_range. Denne værdi kan dermed hurtigt tilgås fra takeControl()-metoden. Den implementerede lokale tråd kan ses i Java-kode 3, mens den nye takeControl-metode kan ses i Java-kode 4 nedenfor.
|
|
|
|
|
|
*Java-kode 3: Lokal metode i DetectWall*
|
|
|
|
... | ... | @@ -116,6 +117,7 @@ public boolean takeControl() { |
|
|
return touch.isPressed() || _is_within_wall_range;
|
|
|
}
|
|
|
```
|
|
|
|
|
|
Bemærk at der er synkroniseringsproblemer med ovenstående kode (en variabel der bliver læst og skrevet af forskellige tråde), men i praksis har det ikke den store betydning.
|
|
|
|
|
|
#### DetectWall-implementation med bakning (1 sekund)
|
... | ... | @@ -147,7 +149,7 @@ public void action() { |
|
|
|
|
|
#### DetectWall-implementation med afbrydelse
|
|
|
|
|
|
Hvis tryksensoren registrerer et tryk *imens* bilen er i gang med at dreje (DetectWall-behavioren er allerede aktiv), reagerer bilen ikke, medmindre der er implementeret mulighed for en interruption af DetectWall-behavioren.
|
|
|
Hvis tryksensoren registrerer et tryk *imens* bilen er i gang med at dreje (mens DetectWall-behavioren er allerede aktiv), reagerer bilen ikke, medmindre der er implementeret mulighed for en interruption af DetectWall-behavioren.
|
|
|
|
|
|
Nedenstående Java-kode 6 viser vores implementation af DetectWall’s action()-metode, således at bilen kan afbrydes mens den er i gang med at dreje.
|
|
|
|
... | ... | @@ -183,11 +185,13 @@ Nedenstående video 3 [15] viser en demonstration af denne opførsel. |
|
|
|
|
|
[![image alt text](https://img.youtube.com/vi/7Ie5lJAXUIE/0.jpg)](https://www.youtube.com/watch?v=7Ie5lJAXUIE)
|
|
|
|
|
|
I videoen ser vi, hvordan en testperson rækker hånden ind foran afstandssensoren, imens bilen er i gang med at dreje. Bilen reagerer på dette ved at bakke yderligere 1 sekund, idet DriveForward’s action() bliver undertrykt og DetectWall’s action() bliver kaldt.
|
|
|
I videoen ser vi, hvordan en testperson rækker hånden ind foran ultralydssensoren, imens bilen er i gang med at dreje. Bilen reagerer på dette ved at bakke yderligere 1 sekund, idet DriveForward’s action() bliver undertrykt og DetectWall’s action() bliver kaldt.
|
|
|
|
|
|
|
|
|
#### A Behavior-based Control Program for the Sumo Wrestler Robot
|
|
|
|
|
|
Efter indledende undersøgelser af arkitekturen bag behavior-based control er vores næste mål at konstruere og programmere vores egen LEGO sumobryderrobot.
|
|
|
|
|
|
Reglerne for sumo-brydningen er som følger:
|
|
|
|
|
|
* Robottens basekonstruktion skal være den samme som Express bot består af. Se “base car with extensions” [2].
|
... | ... | @@ -200,7 +204,7 @@ Reglerne for sumo-brydningen er som følger: |
|
|
|
|
|
* Efter tryk på start-knappen skal robotten vente 3 sekunder inden den begynder at køre.
|
|
|
|
|
|
Efter indledende undersøgelser af arkitekturen bag behavior-based control er vores næste mål at konstruere og programmere vores egen LEGO sumobryderrobot. Vi ønsker at programmere vores robot efter behavior-based control paradigmet [3], som det beskrives af Jones et al. Vi benytter Behavior.java [6], Arbitrator.java [7] and BumperCar.java [8] som inspiration til at implementere en behavior-based arkitektur. På trods af at disse klasser understøtter “flydende prioriteter” eller “motivation factors” er alle vores prioriteter enten en høj værdi (hvis den vil have kontrol) eller 0 (hvis den ikke vil have kontrol). Nedenstående figur viser det arkitektur-netværk, som vi har til intention at konstruere og programmere vores sumobryderrobot ud fra.
|
|
|
Vi ønsker at programmere vores robot efter behavior-based control paradigmet [3], som det beskrives af Jones et al. Vi benytter Behavior.java [6], Arbitrator.java [7] and BumperCar.java [8] som inspiration til at implementere en behavior-based arkitektur. På trods af at disse klasser understøtter “flydende prioriteter” eller “motivation factors” er alle vores prioriteter enten en høj værdi (hvis den vil have kontrol) eller 0 (hvis den ikke vil have kontrol). Nedenstående figur viser det arkitektur-netværk, som vi har til intention at konstruere og programmere vores sumobryderrobot ud fra.
|
|
|
|
|
|
|
|
|
*Figur 2: Arkitektur-netværk for vores sumobryder robot.*
|
... | ... | @@ -221,9 +225,9 @@ I de følgende delmåls-afsnit beskrives den løbende konstruktion og programmer |
|
|
|
|
|
Den første behavior vi ønskede at implementere var AvoidEdge, hvorfor Roaming-behavioren (køre frem) også var nødvendig at implementere. Hensigten med AvoidEdge er at sørge for at robotten holder sig inden for banen, hvilket i sidste ende er vores højeste prioritet i en sumobryderkamp. Hvis en af robottens lyssensorer derfor registrerer den hvide kant på banen, ønsker vi at robotten bakker og drejer for at undgå at kører ud over kanten (se figur 2).
|
|
|
|
|
|
Som beskrevet i reglerne består vores sumobryder robot af Express bot basen, som ses i [2]. Derudover påsatte vi to lyssensorer. Vores hidtidige sumobryderrobot kan ses af billede 2 nedenfor.
|
|
|
Som beskrevet i reglerne består vores sumobryder robot af Express bot basen, som ses i [2]. På denne basis platform påsatte vi to lyssensorer, en foran og en bagpå for at registrer om bilen bevæger sig udover kanten. Vores sumobryderrobot med lyssensorer kan ses af billede 2 nedenfor.
|
|
|
|
|
|
*Billede 2: Express-bot base med to lyssensor foran og bagpå.*
|
|
|
*Billede 2: Express-bot base med lyssensor foran og bagpå.*
|
|
|
|
|
|
![IMG_0428.JPG ](http://gitlab.au.dk/uploads/group-5/group-5-lesson-9/57614d9d2b/IMG_0428.JPG_.JPG)
|
|
|
|
... | ... | @@ -278,9 +282,10 @@ Video 4 [16] nedenfor demonstrerer den grundlæggende AvoidEdge behavior. |
|
|
|
|
|
[![image alt text](https://img.youtube.com/vi/XCGIMv6Vldc/0.jpg)](https://www.youtube.com/watch?v=XCGIMv6Vldc)
|
|
|
|
|
|
|
|
|
### Delmål: Implementere FindEnemy.
|
|
|
|
|
|
Den næste Behavior vi implementerede var FindEnemy. Vi ønskede som udgangspunkt at denne Behavior skulle afhænge af input fra en enkelt ultralydssensor. Dette input skulle benyttes til at detektere hvor modstanderrobotten befinder sig og, dernæst nærme sig modstanderen. Da selve bilen godt kunne ende med at bruge meget tid på at køre rundt for at finde modstander-robotten, valgte vi at placere ultralydssensoren på en motor, således at ultralydssensoren kunne drejes imens robotten var i bevægelse. Robotten ville derfor kunne afsøge flere vinkler uden at selve robotten behøvede at dreje. Nedenstående billede 3 viser hvordan vores sumobryderrobot så ud efter vi har påsat en ultralydssensor på en motor, således at ultralydssensoren kan rotere imens robotten er i bevægelse.
|
|
|
Den næste Behavior vi implementerede var FindEnemy. Vi ønskede som udgangspunkt at denne Behavior skulle afhænge af input fra en enkelt ultralydssensor. Dette input skulle benyttes til at detektere hvor modstanderrobotten befinder sig og, dernæst få robotten til at nærme sig modstanderen. Da selve bilen godt kunne ende med at bruge meget tid på at køre rundt for at finde modstander-robotten, valgte vi at placere ultralydssensoren på en motor, således at ultralydssensoren kunne drejes imens robotten var i bevægelse. Robotten ville derfor kunne afsøge flere vinkler uden at selve robotten behøvede at dreje. Nedenstående billede 3 viser hvordan vores sumobryderrobot så ud efter vi har påsat en ultralydssensor på en motor, således at ultralydssensoren kan rotere imens robotten er i bevægelse.
|
|
|
|
|
|
*Billede 3: Sumobryder robot med afstandssensor påsat på motor.*
|
|
|
|
... | ... | @@ -290,9 +295,9 @@ Den næste Behavior vi implementerede var FindEnemy. Vi ønskede som udgangspunk |
|
|
|
|
|
[![image alt text](https://img.youtube.com/vi/2u-6_E8zmvs/0.jpg)](https://www.youtube.com/watch?v=2u-6_E8zmvs)
|
|
|
|
|
|
Vi måtte indse at konstruktionen med den roterende afstandssensor var sværere at implementere end først antaget. Video 5 [17] ovenfor viser hvorledes sensoren er utilregnelig og måler korte afstande på trods af der ingenting er på banen. Vi vurdere årsagen hertil er at ultralydssensoren havde en tendens til at slingre når den stoppede, hvilket i princippet kan gøre det svært for ultralydssensoren at modtage den reflekterede lyd. Selvom det formentlig ville være muligt at løse dette problem, ved at vente førend en måling foretages, vurdere vi at vi mister fordelen ved denne løsning (hastighed), hvis vi indsætter et sådan delay. Vi forsøgte os derfor i stedet med en anden type konstruktion. Denne konstruktion består af to statisk monteret ultralydssensorer, modsat den roterende konstruktion. Billede 4 nedenfor viser denne konstruktion. Bemærk: Vi har nu en motor port i overskud til f.eks. at lave noget aggressivt.
|
|
|
Vi måtte indse at konstruktionen med den roterende afstandssensor var sværere at implementere end først antaget. Video 5 [17] ovenfor viser hvorledes sensoren er utilregnelig og måler korte afstande på trods af der ingenting er på banen. Vi vurdere årsagen hertil er at ultralydssensoren havde en tendens til at slingre når den stoppede, hvilket i princippet kan gøre det svært for ultralydssensoren at modtage den reflekterede lyd. Selvom det formentlig ville være muligt at løse dette problem, ved at vente førend en måling foretages, vurdere vi at vi mister fordelen ved denne løsning (hastighed), hvis vi indsætter et sådan delay. Vi forsøgte os derfor i stedet med en anden type konstruktion. Denne konstruktion består af to statisk monteret ultralydssensorer, modsat den roterende konstruktion. Billede 4 nedenfor viser denne konstruktion. Bemærk: Fordelen ved dette er også at vi har en motor port i overskud til f.eks. at lave noget aggressivt.
|
|
|
|
|
|
*Billede 4: Sumobryder robot med to statiske afstandssensorer.*
|
|
|
*Billede 4: Sumobryder robot med to statiske ultralydssensorer.*
|
|
|
|
|
|
![IMG_0441](http://gitlab.au.dk/uploads/group-5/group-5-lesson-9/ffb41c6b9b/IMG_0441.JPG)
|
|
|
|
... | ... | @@ -389,7 +394,7 @@ public void action() { |
|
|
|
|
|
### Delmål: AttackEnemy-behavior
|
|
|
|
|
|
Den sidste behavior vi ønskede at implementere var AttackEnemy. Med denne Behavior ønskede vi at få robotten til at angribe fjenden, lige så snart fjenden var indenfor en bestemt rækkevidde. Vi ønskede at robotten skulle angribe ved at skubbe aggressivt til modstanderen, som vi havde set en professionel sumobryderrobot benyttede i [10]. Da vi dermed skulle benytte os af en lineært direktionel kraft, lod vi os yderligere inspirere af stempel-mekanismen på et tog. Vi fandt yderligere inspiration i en lego-konstruktion, der gjorde brug af denne mekanisme [11]. Udover at være krævende at konstruere i sig selv, var det en stor udfordring for os at inkorporere denne opførsel fysisk i vores robot uden at overskride hverken de dimensionelle eller de vægtmæssige grænser. Nedenstående billede viser, hvordan det lykkedes os at konstruere vores robot, således vores sidste Behavior kunne implementeres. Billede 5 nedenfor viser dermed også, hvordan vores sumobryder robot endeligt kom til at se ud, da den nu indeholder at vores ønskede behaviors.
|
|
|
Den sidste behavior vi ønskede at implementere var AttackEnemy. Med denne Behavior ønskede vi at få robotten til at angribe fjenden, lige så snart fjenden er indenfor en bestemt rækkevidde. Vi ønskede at robotten skulle angribe ved at skubbe aggressivt til modstanderen, som vi havde set en professionel sumobryderrobot benyttede i [10]. Vores konstruktion er yderligere inspireret af stempel-mekanismen på et tog og en anden lego-konstruktion, der gjorde brug af en lignende mekanisme [11]. Pga. de plads- og vægtmæssige begræsningerne på robotten (30 cm x 30 cm x 30 cm, >1 kg) var det besværligt at konstruere denne mekanisme, men det lykkes os efter et par iterationer at holde os indenfor grænserne. Nedenstående billede (5) viser vores sumobryder robot med det bevægelige skjold foran - dette er også vores endelige konstruktion.
|
|
|
|
|
|
*Billede 5: Sumobryder robot med stempel-mekanisme*
|
|
|
|
... | ... | @@ -420,7 +425,7 @@ public int takeControl() { |
|
|
}
|
|
|
```
|
|
|
|
|
|
Dermed tager AttackEnemy kontrol, når ultralydssensorerne detekterer en modstander under 30 cm væk, og aktivere dens action, hvilken er at køre fremad med fuld motorkraft, samtidig med at stemplet kører på fuld kraft. Nedenstående video er en demonstration af stemplets funktionalitet, som er en del af AttackEnemy-behavioren. Derudover implementerede vi et delay som betyder at stempelmekanismen holder en pause på 3 sekunder inden stempelmekanismen begynder igen. Dermed kunne vi sikre at robotten var istand til at angribe modstanderen over flere omgange, i stedet for at “låse sig fast” i angrebsbevægelsen. Denne taktik er inspireret at den spartanske krigstaktik, hvor forsvaret gradvist rykker deres skjold frem, og dermed presser fjenden bagud gennem korte intensive bevægelser [12]. Nedenstående video 6 [18] demonstrerer AttackEnemy behavioren.
|
|
|
Dermed tager AttackEnemy kontrol, når ultralydssensorerne detekterer en modstander under 30 cm væk, og aktivere dens action, hvilken er at køre fremad med fuld motorkraft, samtidig med at stemplet kører på fuld kraft. Nedenstående video er en demonstration af stemplets funktionalitet, som er en del af AttackEnemy-behavioren. Derudover implementerede vi et delay som betyder at stempelmekanismen holder en pause på 3 sekunder inden stempelmekanismen begynder igen. Dermed forsøger vi at sikre at robotten er i stand til at angribe modstanderen over flere omgange, i stedet for at “låse sig fast” i angrebsbevægelsen. Denne taktik er inspireret at den spartanske krigstaktik, hvor forsvaret gradvist rykker deres skjold frem, og dermed presser fjenden bagud gennem korte intensive bevægelser [12]. Nedenstående video 6 [18] demonstrerer AttackEnemy behavioren.
|
|
|
|
|
|
|
|
|
*Video 6: Demonstration af AttackEnemy behavior*
|
... | ... | @@ -440,6 +445,7 @@ Som det fremgår af billede 6 overholder vores sumobryderrobot kravet om at samt |
|
|
|
|
|
Slutteligt, som det ses af billede 7 overholder vores robot også kravet om at veje mindre end 1000 g. Vores robot endte med at veje hele 999 g (men altså stadig mindre end 1000 g).
|
|
|
|
|
|
|
|
|
#### Fights with our sumo robot
|
|
|
|
|
|
For at afprøve vores sumobryderrobots evne til at sumobryde undertog vi en række kampe med andre sumobryderrobotter.
|
... | ... | @@ -489,10 +495,8 @@ I videoerne ovenfor (Video 7 [19], Video 9 [21]) taber vi, umiddelbart fordi vi |
|
|
## Conclusion
|
|
|
Vi har med de indledende undersøgelser fået en bedre forståelse for, hvorledes behavior-based control kan implementeres og bruges til at styre en LEGO robot, samt hvilke elementer man skal tage sig i agt for. I disse undersøgelser arbejde vi bl.a. med at undgå at foretage blokerende kald i arbiteren, såsom med f.eks. ultralydssensorens getDistance(). Derudover tog vi et nærmere kig på, hvorledes behaviors kan undertrykkes og genstartes.
|
|
|
|
|
|
Herefter konstruerede og programmerede vi vores egen sumobryderrobot med behavior control til at kæmpe mod andre sumobryderrobotter. Vores sumobryder robot har 5 forskellige behaviors, som er til hhv. for at være i bevægelse (Roam), lave tilfældige retningsskift (TurnAround), undgå kanterne af banen (AvoidEdge), finde fjenden (FindEnemy) og angribe fjenden (AttackEnemy). AttackEnemy gør brug af 2 motorer til at bevæge en plade frem og tilbage for at skubbe fjenden væk. Efter finjustering af robottens AvoidEdge behavior var robotten i stand til at vinde flere gange over andre robotter.
|
|
|
|
|
|
Herefter konstruerede og programmerede vi vores egen sumobryderrobot med behavior control til at kæmpe mod andre sumobryderrobotter. Vores sumobryder robot har 5 forskellige behaviors, som er til hhv. for at være i bevægelse (Roam), lave tilfældige retningsskift (TurnAround), undgå kanterne af banen (AvoidEdge), finde fjenden (FindEnemy) og angribe fjenden (AttackEnemy). AttackEnemy gør brug af 2 motorer til at bevæge en plade frem og tilbage for at skubbe fjenden væk. Efter finjustering af robottens AvoidEdge behavior var robotten i stand til at vinde adskillige gange over andre robotter.
|
|
|
|
|
|
Herefter konstrueret og programmerede vi vores egen sumobryderrobot til at kæmpe mod andre sumobryderroboter. Ige
|
|
|
|
|
|
## References
|
|
|
|
... | ... | |