Thursday, November 18, 2010

Lab 18/11 - 2010

Dato: 18/11 - 2010
Varighed: 3 timer
Deltagere: Lasse, Esben og Toke

Dagens mål
I dag fokuserer vi lab sessionen på at undersøge leJOS NXJ behaviour-based kontrol program. Måden vi vil gøre det på er ved at kigge på den inkluderede testklasse BumberCar der ligger i samlples/BumberCar.
Til at gøre dette bruger vi vores NXJ robot hugo der til dagens session er bygget sådan her.


Dagens plan
- Testkørsel af BumberCar.java klassen samt analyse af Arbitrator.java klassen
- Udvidelse af BumberCar klassen med en ny behaviour Exit
- BESKRIV SIDSTE PUNKTER


Testkørsel af BumberCar.java klassen samt analyse af Arbitrator.java klassen
For at kunne arbejde med BumberCar klassen startede vi med at køre klassen i standard form på vores NXJ robot. Ud fra dette kunne vi observere at vores robot altid forsøger at køre ligefrem, indtil der skulle komme noget ind foran vores robot. Hvis robotten registrerer noget foran sig vil den forsøge at undgå dette ved at dreje væk fra den.
Ved at kigge på BumberCar koden kan vi udlede at den har en behaviour DetectWall, som er en subklasse af Behaviour, der står for denne undvigelse.
Uden at genfortælle hele strukturen som de bruger i deres behaviour kontrol så fungerer den ved at have implementeret en funktion takeControl() der returnerer true hvis har opdaget noget og gerne vil have kontrollen.

[CODESNIPPET]{
public boolean takeControl() {
return touch.isPressed() || sonar.getDistance();
}
Her vises implementation af takeControl(). touch og sonar er henholdsvis en TouchSensor og en UltrasonicSensor fra det leJOS NXJ API.

Ved at holde touch knappen nede vil takeControl returnere true hver gang Arbitrator.java tjekker for hvilken behaviour der skal være aktiv.

Mens vi kigger på Arbitrator.java så kan vi med det samme udlede at man starter fra den behaviour med højest prioritet og derfra arbejder sig nedad indtil man har fundet en behaviour der gerne vil have kontrol over robotten. Dette betyder altså at behvaiourer ikke vil få kaldt deres takeControl() funktion hvis der er en behaviour med højerer prioritet der returnerer true i takeControl().

[CODESNIPPET]{
_highestPriority = NONE;
for (int i = maxPriority; i >= 0; i--) {
if (_behavior[i].takeControl()) {
_highestPriority = i;
break;
}
}
int active = _active;// local copy: avoid out of bounds error in 134
if (active != NONE && _highestPriority > active) {
_behavior[active].suppress();
}
Ovenstående er et uddrag fra Arbitrator.java i metoden run(). Det viser hvordan man går igennem alle behaviours (behaviour er et array med alle behaviours) og spørger hver af dem om de gerne vil tage kontrol. Hvis metoden finder en behaviour der vil så breaker den og suppresser den behaviour der er aktiv.


Udvidelse af BumberCar klassen med en ny behaviour Escape
For at lære yderligere omkring Behaviours og hvordan de fungerer, prøvede vi som næste skridt at lave vores egen simple Behaviour og tilføje den til BumberCar.java. Vi kaldte denne behaviour for Escape

[CODESNIPPET]
class Escape implements Behavior{
public boolean takeControl() { return Button.ESCAPE.isPressed(); }
public void action() { System.exit(0); }
public void suppress() {}
}
Her ses vores simple behaviour der implementerer Behaviour og de metoder der følger med.

Denne behaviour blev tilføjet til vores behaviour liste som den sidste behaviour og dermed den behaviour med højest prioritet (Se inkluderede BumberCar.java fil for at se inkluderingen).

Ved testkørslen af dette opdagede vi noget uventet. Robotten slukkede ikke ned med det samme hvis man trykkede på NXJ robottens escape knap samtidig med at robotten var i gang med at udføre action funktionen i DetectWall behaviouren så blev man nødt til at holde knappen inde til dens action var færdig.

Hvis man kigger inde i DetectWall.action() så finder man følgende kode:
public void action() {
_suppress = false;
Motor.A.rotate(-180);// start Motor.A rotating backward
Motor.C.rotate(-360); // rotate C farther to make the turn
}
Denne kode kører to metode kald til motorerne med rotate. Ved at kigge leJOS NXJ API så kan man ved denne metode se de er blokkerende metoder hvilket forklarer hvorfor vi skal holde knappen inde.

Litteraturliste
BumberCar.java : STI TIL KLASSE
Arbitrator.java STI TIL KLASSE
Behaviour.java STI TIL KLASSE

Thursday, November 11, 2010

Lab 11/11-2010

Dato: 11/11
Varighed: 3 timer
Deltagere: Philip, Lasse, Toke og Esben

Dagens mål
At arbejde med navigation for lego NXT robotten. Først vil vi teste lejos.robotics.navigation.TachoPilot og måle hvor præcis denne er. Herefter vil vi implementere to-lags opførsel på robotten så den undgår kollisioner.

TachoPilot
En vigtig ting når det kommer til navigering via tacho counters, er at minimere friktionen samt at maksimere grebet med underlaget. Robotten blev programmeret til at køre i en geometrisk figur 10 gange (et kvadrat med sidelængde 30 cm).

TachoPilot tachoPilot = new TachoPilot(8.16f, 11.2f, Motor.C, Motor.B);
tachoPilot.setSpeed(100);
tachoPilot.forward();
for (int i = 0; i <>
for (int j = 0; j <>
tachoPilot.travel(30);
tachoPilot.rotate(90);
}
}

Vi satte vores rotationshastighed til 100 grader i sekundet på et hjul med en diameter på 81,6mm. Dette fik vores robots hjul til at skride ud, hvilket fik robotten til at tabe sin kurs og ikke følge den ønskede figur. Ved at reducere hastigheden fik vi maksimeret vejgrebet, hvilket er med til at minimere robottens drift[1].
Med en rotationshastighed på 30 grader i sekundet, noterede vi en afvigelse fra nulpunktet på ca. 1,5 cm pr kørt figur.

Robotten blev efterfølgende sat til at rotere 360 grader på stedet, og herefter rotere tilbage til udgangspunktet. Med den korrekte rotations hastighed (vi benyttede 10 grader i sekundet) roterede robotten kun lige over 300 grader, men roterede dog tilbage til næsten samme udgangspunkt, her med en afvigelse på et par grader. Dette virker mere som et problem med konfigurationen af robottens forskellige størrelser, end et problem med tacho counterne, da robotten netop roterer tilbage til det originale udgangspunkt korrekt. Ved at sætte afstanden mellem vores hjul op med yderligere 0,1cm kørte robotten næsten en fuld cirkel og roterede tilbage til sit udgangspunkt. Da der ikke var påsat en tusch til at tegne stien. må vi estimere på afvigelsen - vores estimat er 355 grader.

For at kunne stole på tacho counterne er det altså vigtigt at robottens konfiguration af diverse fysiske afstande er så korrekt som muligt samt at grebet mellem hjulene og overfladen maksimeres.


Navigation mens der undgås kollision

Målet for vores robot er at køre til et givent punkt og køre rundt om eventuelle forhindringer. Til dette definerede vi to behaviours, navigation behaviour og evasion behaviour, der blev hvor evasion opførslen undertrykker navigationen vha. supress mekanismen fra [2]

Navigation behaviour benytter SimpleNavigator og kører til et givent koordinat via funktionen goTo(x,y). Et problem vi opdagede da vi testede opførslen for sig selv, er at et kald til GetX() eller GetY() på en anden tråd, får det synkrone kald til goTo(x,y) til at afbryde og de indre værdier for x og y bliver forkerte. Et kald til goTo(100,0), som får robotten til at køre 1 meter ligeud, fik robotten til at køre i en halvcirkel da vi samtidig på hovedtråden pollede efter dens position og udskrev dette.

Evasion laget søger efter en forhindring, og hvis der findes en, undertrykkes navigationen, der drejes 90 grader og køres 20 cm, hvorefter navigationen igen overtager. Der gemmes ingen state og reagerer direkte på input.

while (true) {
while (sonicSensor.getDistance() > tooCloseThreshold) { //threshhold is 20cm
}
suppress();
rotate(90);
travel(20);
release();
}

Vi har observeret at robotten kan finde på at dreje med kun et hjul, hvor (ifølge dokumentationen) at SimpleNavigator blot drejer på stedet (robotten benytter differential drive). Den observerede opførsel kan være et resultat af udefineret opførsel hvis den synkrone metode goTo(x,y) bliver afbrudt. En mulighed her er at benytte den asynkrone version af goTo eller programmere vores egen navigation.

Der er enkelte fejl som nævnt ovenfor, der kunne forbedres, men generelt virker robotten fint, og kører korrekt hen til sit mål. Den lider af samme problemer som TachoPilot robotten, nemlig at den skyder lidt ved siden af, hvilket forværres drastisk hvis grebet med overfladen ikke er god nok.

[1] Brian Bagnall, MAXIMUM: LEGO NXT, Building Robots with Java Brains
[2] Rodney Brooks, MIT AI Memo 864, September 1985

Thursday, November 4, 2010

Lab 4/11-10

Vi har idag været:
Toke, Esben og Philip (Lasses søn var syg)

Vi har arbejdet fra 11 til 14

Vi vil idag undersøge begrebet behaviours inden for embedded systemer.

Opsætning
Vi starter med at hente SoundCar.java og overføre det til nxt'en. I programet er der 3 behavoiurs som kører simultant men supressor hinanden.

Test
Vi tester programmet med forskellige antal behaviours og de opfører sig som forventet, de supressor hinanden. Når der f.eks bliver spillet lyd stopper robotten altid med at køre, også selv om den er ved at avoide.

Daemon Tråde
Behaviour tråedene bliver sat som daemon threads, for at den virtuelle maskine skal lukke ned når SoundCar.java (som har kører i main tråden) lukker ned. Vi skal altså ikke vente på behaviourne når vi vil sukke programmet.

Counters vs Booleans til supression
Behaviour klassen bruger counters til at styre supression. Grunden til at bruge counters i stedet for en simpel boolean er at hvis man bruger booleans, så vil en behaviour når den releaser sin underbehaviour også release sit "barnebar". Det kan være det barnebarnets far med vilje allerede har supressed sit barn. Den supression vil så blive brudt. Med counters sker det ikke.
Det er vigtigt at forstå at behaviours altid kører og udregner, også selv om de er supressed.

Prioritet vs Heirarky
Forskellen på den kode vi kører med behaviours og den kode som Fred Martin kører er at Martin's kode bruger en central styrings algoritme til at bestemme hvilke tråd der skal køre. Vores tråde kører altid, selv om de ikke får lov til at give udput. For os er det trådenes heraki der bestemmer udput og ikke prioritet.

Lys behaviour
Vi laver en TowardLight behaviour, som skal styre robotten imod lys når det er meget stærkt.
For at få triggered vores behaviour laver vi en treshold for hvornår lys er for lyst til at ignorere.
Vi har sat TowardLight til at supresse de andre behavious, når den ser lyset går den efter det.