fredag den 30. marts 2012

TeddyClimber, session 2


Plan

1. Byg en robot som bruger gearede motorer.
2. Vi skal have finpudset kommunikationen imellem pc og robot.

3. Begynd på at skrive kode til robotten.

Resultater

1.
Vi er nået en konstruktion hvor vi har den ønskede høje fart.







2.
Vi har stadig en masse problemer med vores kommunikation imellem robot og computer, hvor der bliver sendt/modtaget forkert værdier på robotten.


3.
Vi har skrevet en kalibreringsmetode til de 3 sensorer. Derudover har vi skrevet lidt struktural kode til main-loopet. Ideen er at vi finder ud af hvilken state vi er i, og så udfører vi handlinger der passer til den state.

TeddyClimber, session 1


Torsdag 22. marts
Deltagere: Mikkel, Jesper, Bjarke og Troels

Opgave

Vi skal bygge en robot der kan finde op af følgende bakkebane:
Man skal nå op til toppen og tilbage til start hurtigst. Da det er en konkurrence, skal vi vinde.

Plan

1. Vi skal lave et GUI program på computeren som kan tilkobles bilen, hvis vi ønsker at kunne ændre værdier og modtage værdier over bluetooth imens bilen kører.
2. Vi skal beslutte hvordan vi opdager at vi kommer til svingene og hvordan vi foretager et sving hurtigst muligt.
3. Vi skal kunne håndtere de tre forskellige farver: sort, hvid, grøn (mål).
4. Vi skal også have fundet en bilkonstruktion der kan køre hurtigst muligt.

Resultater

1.
Vi har arbejdet på at tilpasse vores kommunikation imellem robot og pc til de behov vi har. Her har vi valgt at

2.
Vi har overvejet tre muligheder.
En mulighed er en ultralydssensor, der fanger hvornår man kører på bakke og hvornår man kører på plateauerne. Her skal vi så i logikken holde styr på de forskellige områder af banen vi er på.
En anden mulighed er at bruge lyssensorer. Her har vi overvejet to setups.
Her er ideen at vi følger den sorte streg med den nederst sensor i begge setups. I den venstre kigger vi så efter et hvidt område foran den nederst sensor og derved fange at vi er ved et sving. Den højre mulighed er at vi har to lyssensorer, der måler på hver side af midten efter sorte streger. Fordelen ved dette setup at vi ved i hvilken retning vi skal dreje.
Vi ser nogle problemer med at bruge ultralydsensoren. Der er forskel på om man kører nedad eller opad.
Vi er begyndt at overveje et nyt setup hvor vi har en lyssensor på hver side af den sorte streg og en længere fremme for at opdage hvornår vi kommer til plateauerne.
Her er vi begyndt at overveje om vi behøver mere end de to nederste sensorer. Vi har besluttet at prøve at få dette til at virke. Det vil sige følgende sensorsetup:
For at dette kan virke skal vi sikre at vi kommer i nogle bestemte states, hvor vi ved hvad vi skal gøre for at komme videre til næste state.
Vi har bygget følgende robot:
[Billeder 2 3]
3.

4.
Vi har overvejet om vi skal have 2 eller 3 motorer.

Post day-1

Vi har implementeret store dele af programstrukturen, således at vi har en GUI der kan sende og modtage data via hhv en sender og modtager klasse. Det hele er styret af MainHandler klassen, der opretter klasserne og binder dem sammen.
UML diagram følger.

Forslag til design - billede og pseudo kode. Hvert tal på billedet svarer til en kommentar (// x) i pseudo koden
 

public class PseudoClimber{

public Motor leftMotor;
public Motor rightMotor;

public Sensor rightLight;
public Sensor leftLight;
public Sensor middleSensor;

public Robot() {

//Go

//1
while(something) {

//2
if(black(rightLight.value)) {
//turn right
}
else if(white(rightLight.value)) {
//turn left
}

//Omvendt for leftLight!

//3
if(white(middleSensor.value)) {
//turn right //fine tune hvordan
}
}

//4
//Find linje igen

while(something) {
//5
if(black(rightLight.value)) {
//turn right
}
else if(white(rightLight.value)) {
//turn left
}

//Omvendt for leftLight!

//6
if(white(middleSensor.value)) {
//turn left //fine tune hvordan
}
}

//7
//find linje igen

while(something) {
if(black(rightLight.value)) {
//turn right
}
else if(white(rightLight.value)) {
//turn left
}

//8
if(black(rightLight.value) && black(leftLight.value) && black middleLight.value) {
//180 degree turn
}

//Samme procedure som ovenfor når vi skal ned igen!
}
public boolean black(int i) {
}
public boolean white(int i) {
}
}


Konklusioner
Vi har fået lavet en masse overvejelser og vil bringe det videre til næste gang vi arbejder på Robotten. Derudover har vi fået kommunikationen imellem robot og computer til at køre.

torsdag den 29. marts 2012

NXT Programming, Lesson 7


Varighed: 2 Timer
Deltagere: Mikkel, Jesper & Troels

Plan

Vi følger vejledningen [1].
1. Monter ultralydssensor på en lego robot bil.
2. Få overført programmet [2].
3. Observer robotten opførsler og find ud af hvad der starter dem
4. Observer LCD displayet og fortolk resultaterne.
5. Undersøg java-programmet og find ud af hvordan triggering conditions er implementeret for hver af de forskellige klasser, og hvordan opførslerne er implementeret. Prøv at køre kun med den første opførsel og derefter kun med de 2 første opførsler aktive.
6. Forklar hvorfor Behavior klassen har kaldet this.setDeamon(true) i constructoren.
7. Forklar betydningen af SuppressCount og sammenlign SoundCar med Fred Martins arbiter [3].
8. Tilføj en behavior (“Drive toward light”) til SoundCar.


Resultater

1 og 2.
Vi har monteret ultralydssensoren foran på den bil vi havde til at ligge og overført programmet uden problemer.


3.
Den kører fremad hvis der ikke er noget foran den i forskellige periodelængder. Nogle gange drejer den lidt. Det tyder på at den kører noget tilfældigt på begge hjul og i tilfældige længder.
Hvis der er noget foran den bakker den og drejer til venstre. Den spiller et musikstykke med et fast mellemrum. Musikstykket er forskelligt for hver gang det spiller.


4.
Følgende er et billede af displayet.
Drive, Avoid, Play er navnene på de forskellige opførsler. Næste kolonne (der er fyldt med 0er) viser om en behaviour er subsumed af en anden behaviour (1 betyder subsumed). Næste kollone består kun af et tal udfor Avoid. Dette er måleresultatet fra ultralydssensoren, når den kommer under 20 bliver Avoid aktiveret. Næste kollone i så der s/b/f ud for de forskellige opførsler. s betyder at den er klar, f betyder fremad, b betyder bagud.


5.
Alle klasser extender Behavior (som extender Thread). Behavior modellerer ideen om at en behavior kan subsume underliggende behaviors. En behavior kan kun udføre actions hvis den ikke er suppressed. Her har vi også opdaget at “s” på displayet betød stoppet og ikke klar. RandomDrive har ingen triggering condition. RandomDrive kører med tilfældig power (mellem 50-100) på de to motorer. Derefter venter den et sted ml. 1,5 og 2,5 sekunder. Derefter gentager den ovenstående. Behavioren starter med at kalde suppress() der “undertrykker” underliggende behaviors og derefter udfører den sin action og så kalder den release(), der fjerner undertrykkelsen (Men da den ikke har nogen underliggende behavior, sker der ikke noget ved disse kald). AvoidFront har en triggering condition på en måling under 20 fra ultralydssensoren (Dette implementeres med en while loop). Så kalder den suppress(), der undertrykker RandomDrive, og derefter kører den tilbage med 70 på begge motorer i 1 s. og så kører den fremad med 80 på højre hjul i 0,8 s. Så stopper den og venter i 0,5 s. Herefter kaldes release(). PlaySound spiller en sang af tilfældig længde (dog mindst 5 * 100 ms). Den sætter for hver gang de parametre der bliver brugt til at generere lydene (vol, osv.). PlaySound har en triggering condition som er at den skal køre hver 10 s.


6.
At behaviorne er sat som deamon threads betyder at hovedtråden afslutter, bliver deamon threads også lukket [4].


7.
SuppressCount bliver talt op når en ovenstående behavior suppresser en behavior. Den bliver talt ned igen når den ovenstående behavior releaser igen. En behavior kan kun køre hvis dens suppressCount er 0. Tallet fortæller altså hvor mange behaviors der undertrykken den givne behavior.
I SoundCar er hver behavior autonomt som agerer i et hierarki, hvor de øverste bestemmer over dem under dem. I modsætning hertil står Fred Martins arbiter system [3], hvor der er en central enheder der vælger hvilke processer der skal køre udfra prioriteter.


8.
Triggering Condition for “Drive toward light” skal være at der bliver målt lysværdier over en bestemt grænse (60), som så trigger at robotten kører fremad i retning af den lyssensor derfra hvor lyset kommer fra. Den skal ligge over RandomDrive og under Avoid, idet det er vigtigere at bevæge sig imod lyset end at køre tilfældigt og vigtigere at undgå forhindringer end at følge lyset. Musikken er selvfølgelig vigtigst. Vi har implementeret behavioren i den følgende java-klasser [5]. Vores forventning er at robotten bliver domineret af PlaySound og AvoidFront, og at den dominerer RandomDrive.

Som det kan ses i videoen er dette tilfældet. Den trigger først når dioden på kameraet lyser på en sensor.


Konklusioner
Vi nåede i mål med opgaverne.


Referencer
[1]: http://www.legolab.daimi.au.dk/DigitalControl.dir/NXT/Lesson7.dir/Lesson.html
[2]: http://www.legolab.daimi.au.dk/DigitalControl.dir/NXT/Lesson7.dir/
[3]: Fred G. Martin, Robotic Explorations: A Hands-on Introduction to Engineering, Prentice Hall, 2001, s. 214-18
[4]: http://journals.ecs.soton.ac.uk/java/tutorial/java/threads/daemon.html
[5]: http://dl.dropbox.com/u/357278/Lego/Week7/LightSense.java og http://dl.dropbox.com/u/357278/Lego/Week7/SoundCar.java

torsdag den 8. marts 2012

NXT Programmering, Lesson 6

Varighed: 3,5 Timer
Deltagere: Mikkel, Jesper, Troels & Bjarke


Status på Bluetooth forbindelse
Bluetooth forbindelse mellem PC og NXT brick inspireret fra koden fra PCCarController [1] og BTControlledCar [2] fungerer fint. Vi kan sende parametre frem og tilbage mellem PC og NXT.  Der er et problem i forhold til at at afbryde bilen, som diskuteret til forelæsningen. Vi har tænkt os at ændre i programmet på bilen så vi i stedet benytter available metoden til at tjekke om streamen indeholder noget inden vi kalder readInt().
 public int available() throws IOException
Returns the number of bytes that can be read (or skipped over) from this input stream without blocking by the next caller of a method for this input stream. The next caller might be the same thread or or another thread.
Pt. har vi fået bluetooth forbindelse til at fungere på to computere. Én ubuntu 32-bit maskine samt én windows 7 maskine med 32-bit java og 32-bit eclipse.


Formål

Lesson 6: http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson6.dir/Lesson.html
I denne lektion vil vi bygge og programmere Braitenberg robotter. Dvs. robotter med reactive control hvor der er en direkte forbindelse fra lys -eller lydsensorerne til motorerne på robotten.


Plan
1. Først bygges køretøj nr. 1 der kører fremad når den registrerer høje lyde. Programmet på NXT’en normaliserer den registrerede lyd så motoren får en værdi mellem 50 og 100 baseret på hvad lydsensoren måler. Ved højere lyde gives der mere kraft.
 

2. Vi ændrer i programmet så vi i stedet benytter en inhibitory connection imellem lyd og kraft. Dvs. robotten kører med fuld kraft, men når der registreres lyd trækkes den registrerede lyd fra kraften.
 

3. Vi ombygger robotten til en “five-minute bot” efter byggeinstruktioner fra nxtprograms.com [3].
 

4. Vi tilføjer to lyssensorer til robotten så vi kan lave Braitenberg robotterne 2a og 2b, som vist nedenfor. De registrerede værdier for lyssensorerne normaliseres, som tidligere og gives som input til hjulene. Robotten kan så køre mod lyset eller væk fra lyset alt efter hvordan lyssensorerne kobles til NXT brikken.
 

5. Vi vil placere en lyskilde på bilen og sætte den sammen med en eller flere andre robottor for at se hvordan de reagerer.
 

6. Omskriv vores program der styrer robotten, således at den opsamler N samples og anvender gennemsnittet til at bestemme hastigheden på motorerne.
 
7. Byg en Braitenberg robot 3



Resultater
1. Først lavede vi en minimal implementation, hvor vi på displayed vi fik vist den registrerede værdi fra lyssensoren. Vi fik de forventede værdier mellem 0 og 100 fra readValue() metoden. Vi lavede en minimums hastighed for motoren på 50 baseret på vores tidligere erfaringer med hvor meget kraft der skulle til for at drive hjulene.
Vores normalisering af den indlæste værdi fra lydsensoren gik i første omgang ud på at dividere den indlæste værdi med 2. Ved at lægge dette resultat sammen med minimum speed fik vi en værdi mellem 50 og 100 for motoren. Bilen kørte som forventet bortset fra at vi var kommet til at sætte motoren omvendt på. Altså kørte bilen baglæns..
Som foreslået i opgaven [4] lavede vi også en version hvor normaliseringen i stedet lavede en mapping til kraft mellem -100 og 100. Vi tolkede negative tal som ‘bakgear’ [5]. Resultatet blev at bilen bakkede medmindre den registrerede høje lyde. I så fald kørte den fremad som før.


For at reagere i lidt længere tid på det input indsatte vi et Thread.sleep(500) i slutningen af vores while loop. Dette fungerede ikke så godt, idet den ikke får reageret på alle høje lyde.En løsning kunne være opsamle flere værdier og tage gennemsnittet.


2. Det virkede som forventet. Implementationen trækker den registrerede lydværdi/2 fra default power på 100.  Robotten havde således en default power og når den registrerede lyd kørte den langsommere eller stoppede helt [6].


4. Robotten kørte som forventet. Robot 2b styrede mod lyset som vist på videoen. Hvis vi byttede om på hvilke porte lyssensorerne var tilsluttet styrede den væk fra lyset, som 2a [7].

Vi indførte også inhibitor kontrol så robotten kørte fremad indtil den registrerede en lyskilde. Hvis vi placerede en lyskilde imellem de to sensorer stoppede således robotten helt [8].


5. Vi har derefter tilsluttet dioder foran på, så vi kan se hvordan to robotter reagerer overfor hinanden. Vi har tilsluttet dioden til MotorPort.C og tænder den ved at kalde controlMotor(100, MotorPort.FORWARD). 
Robotterne kørte imod hinanden. Men vi havde ikke nogle ordentlige MIN og MAX værdier for motorkraften, så vores robot kørte langsommere.
Vi kunne konstatere at vores robot kunne finde ud af det mørklagte køkken ved at køre efter lyset.


6. I stedet for at opsamle N værdier har vi valgt at følge Estimate-formlen fra bunden af noten om Braitenbergs “Vehicles” [9]:

Dette gør at vi slipper for at tage gennemsnittet over en masse læste værdier og i stedet lader den nye værdi afhænge af den tidligere værdi. Her er beta et tal imellem 0 og 1, som fortæller hvor meget vægt den nye værdi skal have i forhold til den tidligere værdi.
For at kunne observere at robotten ændrer hastigheden over flere værdier, har vi valgt at tilføje et Thread.sleep(100) [10]. Med dette delay var det tydeligt at det tog lidt tid for robotten at accellerere op til den nye hastighed.
Konklusioner
Vi fandt efter punkt 5 i dagsordenen ud af, at vi kunne hente raw value via metoden readNormalizedValue() fra sensoren. 
public int readNormalizedValue()
Get the normalized light reading

Returns:
the raw light level
Det ville have givet en større spændvidde af værdier i stedet for getValue der blot giver en procentværdi mellem 0 og 100. Der er også den forskel at getValue på en SoundSensor giver en procent værdi på DB værdierne af målingerne. Dette gør at koden formentlig opfører sig anderledes end hvis vi havde brugt raw-værdierne.
Tiden løb fra os og vi nåede ikke at prøve os frem med punkt 7 i planen.


Referencer
[1] http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson5.dir/PCcarController.java
[2] http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson5.dir/BTcontrolledCar.java
[3] http://www.nxtprograms.com/five_minute_bot/steps.html
[4] http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson6.dir/Lesson.html
[5] http://dl.dropbox.com/u/609402/V1.0/PPControl.java
[6] http://dl.dropbox.com/u/609402/V1.1/PPControl.java
[7] http://dl.dropbox.com/u/357278/Lego/ExpandedPPControl/V1.0/EPPControl.java
[8] http://dl.dropbox.com/u/357278/Lego/ExpandedPPControl/V1.1/EPPControl.java
[9] http://www.cs.brown.edu/people/tld/courses/cs148/01/vehicles/vehicles.htm
[10] http://dl.dropbox.com/u/357278/Lego/CollectPPControl/V1.0/CPPControl.java

torsdag den 1. marts 2012

NXT Programmering, Lesson 5

NXT Programmering, Lesson 5

Varighed: 4 Timer
Deltagere: Mikkel, Jesper, Troels & Bjarke


FORMÅL

I denne lektion vil vi lave en såkaldt Segway robot. Dvs. en robot på to hjul der kan holde balancen. Dette gøres ved hjælp af NXT Lyssensoren. Den måler løbende afstanden til jorden og via resultaterne fra sensoren bestemmes om robotten skal køre fremad eller bagud. For nemt og hurtigt at kunne kalibrere konstanterne i PID kontrollen på vores segway-robot vil vi etablere en forbindelse mellem robotten og vores PC. Dette gør vi ved at modificere java-programmerne [2] der blev linket til i øvelsesvejledningen for denne uge [1] der kører på henholdsvis robotten og vores PC. 

PLAN

1. Først bygges robotten efter instruktionerne fra http://www.philohome.com/nxtway/bi_nxtway.htm.
2. Så tester vi sejway koden fra http://www.variantpress.com/books/maximum-lego-nxt.
3. Vi tester om vi kan få PCcarController og BTControlledCar [2] til at kommunikere via bluetooth.
4. Vi kombinerer sejway koden med BTControlledCar og kalibrerer vores bil ‘on-the-fly’ via en modificeret version af PCcarController fra pc’en.


RESULTATER
1. Instruktionerne var ikke så nøjagtige som vi kunne have ønsket os, men det lykkedes os at få bygget en rimelig fornuftig segway robot.



2. Noget af koden fra http://www.variantpress.com/books/maximum-lego-nxt var deprecated, så den krævede nogle ændringer. Specifikt ændrede vi i koden så vi benyttede Motorport klassen i stedet for Motor klassen. Herefter overførte vi programmet til robotten. Robotten kørte som den skulle, men der var for megen kraft på, hvilket resulterede i at den hurtigt væltede.



Vi konkluderede at der krævedes kalibrering af konstanterne for at få den til at virke og gav os derfor til at arbejde på forbindelsen mellem BTControlledCar og PCCarController, så vi kunne ændre konstanterne løbende.

3. Vi gennemførte dette som en del af 4 i stedet for at gøre det som et seperat punkt.

4. Vi kom til at gå direkte igang med punkt 4 i stedet for at gå igang med punkt 3. Det betød at vi ikke havde fundet ordentligt ud af hvordan vi kommunikerede via bluetooth. Dette gjorde at vi brugte en del kræfter på finde fejl i programmet der egentligt skyldes at vi ikke havde fået etableret en ordentlig forbindelse. Vi fandt ud af at få udskrevet NXT enhedens BT adresse. 
Her brugte vi Bluetooth.getLocalAddress() [3].

Vi har lavet en tråd til at modtage nye værdier til robotten over bluetooth. Dette gør vi fordi kaldene til at få værdierne over bluetooth er blocking. Med denne opsætning kan vi ændre værdier imens robotten kører. Vi har lavet et opsætningsskridt hvor man skal etablere forbindelse før robotten går igang med at prøve at balancere. Vi havde et stort problem med at få afsluttet vores tråd når robotten stopper. Problemet er, at tråden er låst i de blocking calls til at læse fra bluetooth streamen. Her bruger vi .interrupt() til at afbryde trådens udførsel. Dette virker dog ikke korrekt og vi har ikke fået en ordentlig måde at få afbrudt tråden (hvilket gjorde at vi blev nød til afkoble batteriet). 

Vi har ikke formået at få robotten til at balancere i mere end 2-3 sekunder. Det virker til at den kompenserer for lidt, for sent. Når den kommer ud over en vis grænse kan den ikke justere og vælter. Det endelige resultat kan ses i [4].

KONKLUSIONER

Vi har ikke fulgt vores plan ordentligt og kom derfor til at spilde noget tid undervejs. Robotten kom ikke til at balancere, formentlig fordi vi ikke kunne få konstanterne til at passe.


REFERENCER
1. http://www.legolab.daimi.au.dk/DigitalControl.dir/NXT/Lesson5.dir/Lesson.html
2. http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson5.dir/PCcarController.java og
    http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson5.dir/BTcontrolledCar.java
3. http://lejos.sourceforge.net/nxt/nxj/api/index.html
4. http://dl.dropbox.com/u/357278/Lego/TeddyWay/TeddyWay.java og http://dl.dropbox.com/u/357278/Lego/PCcarController/PCcarController.java