torsdag den 18. november 2010

Week 9 in LEGO lab

Date: 4. November

Duration of activity: 3 hours
Groups members participating: Heine Stokholm, Michael Vilhelmsen and Mads Møller Jensen

Dagens opgaver:
  • Byg NXT robotten om, så den kan fungere som BumperCar med koden givet fra lejos NXT distributionen i samples/BumperCar
  • Lav eksperimenter med BumperCar
BumperCar
Vi har ombygget vores robot som følger:

Vi har beholdt robotten fra uge 8 og påsat en tryksensor, så robotten kan "føle" at den kører ind i noget.
Herefter har vi uploaded programmet fra tutorialen til robotten med følgende resultat:


Eksperimenter med BumperCar
  • Hvad sker der når tryksensoren holdes i bund?
Når tryksensoren holdes i bund, kræver DetectWall opførslen hele tiden motoradgangen, og robotten forsætter med hele tiden at lave afvigelsesmanøvren.
  •  Både DriveForward og DetectWall har takeControl metoden. Undersøg i Arbitrator koden om Driveforwards takeControl metode, når DetectWall ønkser kontrollen.
I Arbitrator har vi et loop, som kører alle Behaviors igennem. Når loopet finder den Behavior med højest prioritet, som returnerer true ved takeControl, ved den at det er denne Behavior som skal afvikles. Derfor afbrydes loopet, når en sådan Behavior er fundet. Dette betyder at resten af de Behaviors med lavere prioritet ikke bliver kaldt. I BumperCar tilfældet betyder det at DriveForwards takeControl metode IKKE bliver kaldt, når DetectWalls takeControl metode returnerer true. 
  • Implementer end tredje opførsel,  Exit, med højeste prioritet. 
Vi har implementeret en Exit opførsel med højeste prioritet. Dette betyder, at hvis Exit knappen er nede, vil programmet afbrydes, i stedet for at køre fremad, eller afvige. Hvis vi øgede Sound.pause(20) til Sound.pause(2000), ville det ikke være muligt at afbryde robotten i 2 sekunder, hver gang Arbitratoren skal tjekke om DetectWall vil have adgang til motorene. Dvs. vi kan ikke afbryde i bestemte steder i loopet.
  • For at undgå ventetiden i loopet, få den ultrasoniske sensor til at tage prøver hver 20 msek og gemme værdien i en variabel, så takeControl metoden, blot kan tjekke denne værdi.
Vi har valgt at implementere en tråd, som hver 20 msek opdaterer en variable med den senest målte værdi. Fra DetectWall's takeControl metode kigger vi nu bare på den variabel som tråden opdaterer. På den måde undgår vi ventetid i loopet i Arbitration klassen. Vi prøvede at sætte måleintervallet op til 2 sek, og det betød at vi kun kunne afvige hver andet sekund (fordi det kun var der, at vi fik nye målinger). Til gengæld kan vi hele tiden afbryde, modsat før hvor vi var hæmmet af ventetiden i loopet. 
  • Lad DetectWall få robotten til at køre baglæns 1 sekund før den normale afvigelsesmanøvre sker. Implementer at DetectWall kan afbrydes(og køres forfra), hvis den efter det ene sekund stadig kan se forhindringen.
Dette er gjort.Vi har implementeret dette ved hjælp af en ekstra tråd. Tråden indeholder den afvigende opførsel. Hvis tryksensoren så rammes igen, interruptes tråd, og en ny tråd af samme slags kaldes og startes. På den måde kan robotten blive ved med at afvige hvis den bliver ved med at se forhindringer.

Koden for BumperCar efter alle implementationer på nær sidste opgave kan ses her

Koden for BumperCar efter den sidste implementation kan ses her

onsdag den 10. november 2010

Week 8 in LEGO lab

Date: 4. November

Duration of activity: 3 hours
Groups members participating: Heine Stokholm, Michael Vilhelmsen and Mads Møller Jensen

Dagens opgaver:
Thor kørte rundt, og stoppede med jævne mellemrum. Efter ca. 10 sekunder spillede han en lille lyd, og derefter fortsatte han med at køre tilfældigt rundt.
  • Look at the LCD and try to interprete the output
Vi ser 3 linjer:
Drive, Avoid og Play.
Ud for dem alle er et tal der enten er 0 eller 1. Dette tal er 1 når denne behaviour bliver suppresed. Derudover er der et lille bogstav bagved dem alle (enten f, b eller s). Desuden er der et tal fra 0-255 ud for Avoid (afstanden som sensoren måler).
Vi ser at når Avoid suppreser Drive bliver 0'et ud for Drive sat til 1. På samme måde ser vi at når Play suppreser Drive og Avoid bliver begge deres 0'er sat til 1.
  • Look into the three classes and try to identify how the triggering condition is implemented in each of the classes and how the actions for each behavior is implemented
PlaySounds har en while-true løkke. I løkken sleeper den i 10 sek. Når den ikke sleeper, kalder den suppress, og spiller en lille melodi og kalder derefter release. Triggering condition er altså at de 10 sek. er gået - Action er at spille en melodi.

AvoidFront har en while-true løkke. I løkken looper den i en while-løkke så længe den afstand sensoren måler er større end tooCloseThreshold. Så længe afstanden er større måler den en nye afstand og skriver den gamle ud på displayet. Når afstanden pludselig er mindre end threshold suppreser den, og bakker, drejer og til sidst releaser den.
Triggering condition er altså at den målte afstand er mindre end threshold - Action er at bakke og dreje lidt.

Drive har en while-true løkke. I løkken vælges en tilfældig retning og der køres i denne retning, derefter delayes der i et tilfældigt stykke tid. Drive starter med at suppresse og releaser når den er færdig.
Triggering condition er faktisk ingenting; så længe den ikke suppresses kører Thor hele tiden tilfældigt rundt.
Action er at køre i en tilfældig retning
  • Try to watch the car with only the first thread active and then with only the two first threads active to observe the behaviors more clearly.
Vi mente godt at vi kunne forestille os hvordan Thor ville opføre sig hvis vi kun havde en eller to af trådene aktive. I stedet mente vi at det var tydeligere at se hvordan Avoid suppresser Drive og Play suppresser begge dele, hvis Thor hele tiden kører rundt. Derfor fjernede vi det tilfældige delay i Drive, og så opførslen. Videoen her viser resultatet.
  • What is the purpose of making these threads daemon threads as done in the constructor of the Behavior class
Da en daemon-tråd holder op med at eksistere når de tråde den skal servicere terminerer, giver det mening at lade de 3 behaviours være daemon-tråde, da de ikke giver mening at eksistere for sig selv.



Week 7 in LEGO lab

Date: 28. October
Duration of activity: 3 hours
Groups members participating: Heine Stokholm og Mads Møller Jensen




Dagens opgaver:

  • Brug Tom Dean's noter til at implementere Braitenbergs "Vehicle 1", "Vehicle 2a" og "Vehicle 2b
  • Lav en ændring i programmet, så MIN_LIGHT og MAX_LIGHT bestemmes af N samples og altså ikke af alle samples, som robotten har set i sin levetid.
  • Implementer Vehicle 2 (a eller b) med to "threads of control" i stedet for én (Èn for hver forbindelse mellem sensor og motor).
Vehicle 1:
Vi byggede Vehicle 1:


Vehicle 1 er en robot som (i dette tilfælde) har en mikrofon og fremdriften i motorene bestemmes af det lydniveau, som mikrofonen opfanger. Idéen er at robotten skal køre hen i mod en lydkilde, men dette bliver aldrig tilfældet, da robotten ikke har nogen anelse om, hvor lydkilden befinder sig, men kun hvad et givent lydniveau er, der hvor robotten befinder sig.
Først implementerede vi bare, motorene reagerede på lyd, så robotten kørte bare den opfangede en svag lyd.
Det resulterede i at robotten kørte af sig selv p.g.a. den støj som motoren udsender. 




Derfor implementerede vi jvf. Tom Deans note "Braitenberg's Vehicles", en håndtering af baggrundsstøj. Dette gjorde vi vha. et estimat. Vi kunne have valgt at kigge på alle hørte værdier, og beregne gennemsnittet, men over tid er dette en dårlig løsning.
Derfor brugte vi estimatløsningen, hvor det kun er nødvendigt at gemme den sidste estimatværdi, for at beregne den næste.
Som Java kode ser det således ud.


double estimate = 0;
double beta = 0.2
...
estimate = estimate + beta*(volume-estimate);

Dette virkede og robotten stoppede med at reagere på baggrundstøj og dens egen motor.





Hele koden for Vehicle 1 ses her


Vehicle 2:
Vi byggede Vehicle 2:


Vehicle 2 har modsat Vehicle 1 to sensorer (i dette tilfælde lyssensorer). Motorkraften på de to motorer bestemmes så af de lysværdier, sensorerne opfanger. Der findes to forskellige udgaver af Vehicle 2:
a) Her reagerer højre motor på værdierne fra højre lyssensor, og på samme måde i venstre side. Det betyder, at robotten vil køre væk fra en lyskilde.
b) Her reagerer højre motor på værdierne fra venstre lyssensor, og omvendte. Det betyder at robotten vil køre hen imod en lyskilde.


For at få det til at virke med to sensorer ændrede vi en lille smule i koden fra Vehicle 1:


lightL = lightLeft.readNormalizedValue();
lightR = lightRight.readNormalizedValue();
...
estimateR = estimateR + beta*(volume-estimateR);
estimateL = estimateL + beta*(volume-estimateL);
...
Car.forward(normalized(lightR), normalized(lightL));


Det gav følgende resultat:


Herefter implementerede vi MIN_LIGHT og MAX_LIGHT variablene, så den normaliserede værdi (den værdi som motorene skal køre med) passer til det miljø som robotten befinder sig i. Den måler en maksimal lysværdi og en minimal lysværdi, så den reagerer optimalt i de omgivelser den er i. 
Dette gav følgende resultat:
[VIDEO]


Koden kan ses [link]


Miljøændring
I Tom Dean's noter bliver MIN_LIGHT og MAX_LIGHT værdierne kun reguleret, når en henholdsvis mindre og større værdi opfanges. Dette er dog ikke helt hensigtsmæssigt, da lysomgivelserne skifter, eksempelvis når vi går fra dag til nat. Derfor har vi brug for at rekalibrere disse værdier efter N tid eller N indsamlet data. Dette forsøgte vi at implementere med følgende resultat:
[VIDEO]


Koden kan ses [link]


To tråde
Til sidst prøvede vi at lave to "threads of control" i stedet for en. 
Det gav følgende resultat:
[VIDEO]


Koden kan ses [link]