Thursday, June 26, 2014

End Course Project Bonanza

Vi har i løbet af vores projekt valgt at samle alle vores End Course Project sessions i et enkelt Google Docs som kan findes her.

Alternativt kan de samlede sessions hentes soms PDF her.
Ydermere kan koden til vores balancerende robot findes her

Billedserie mht. konstruktionen kan findes her (comming asap)

Ønsker man ikke at følge fodnoterne til de to youtube film i vores Google Doc kan de også ses nedenfor: 







Wednesday, May 21, 2014

End Course Project Planning

Date: 8/5 2014
Duration of Exercise: 3 timer
Group Members Participating:
Henrik Jørgensen
Michael Schiønning
William Thorsen

Mål

Målet med denne øvelsesgang er, i enighed, at nå frem til had vores End Course Project skal være.

Plan

Planen for denne uge er:
  • Finde en række potentielle projekter
  • Udvælge hvilket projekt vi vil arbejde videre med 
  • Påbegynde blogindlæg

Fremgangsmåde

Efter en indledende diskussion nåede vi frem til tre kandidater til vores End Course Project

Robot Balancing On A Ball

Den første idé er en robot der kan balancere på en bold, samt holde balancen selvom der puffes let til enten bolden eller robotten. 

Hardware
  • 1 NXT unit 
  • 3 motorer til hjulene
  • 2 Hitechnic Gyro Sensors til at stabilisere robotten 
  • 1 bold til at balancere robotten på 
  • 3 omnidirektionelle hjul 
Software
  • Behaviour alt efter hvilken tilstand robotten er i (Altså, hvilke motorer der skal aktiveres for at robotten ikke falder ned fra bolden) 
  • PID til at kunne finjustere motorerne 
Den sværeste del af opgaven ville være at kunne kalibrere PID'erne til de tre motorer og derved sørge for at de reagerer korrekt når robottens balance forstyrres og derved korrigerer sin placering på bolden. 

Det endelige resultat vil derfor være en robot der kan balancere, uden assistance, på en bold og vil opretholde balancen selvom man skubber let til enten robotten eller bolden. 

WRO 2014

En robot der kan finde og scanne de ni solpaneler på banen. Såfremt robotten registrerer ogle defekte paneler skal de udskiftes med nye paneler fra et lager på banen. 

Hardware
  • 1 NXT unit
  • 3 Lyssensorer. To til at kunne følge banen (á la LineFollower) og en tredje til at registrere om de solpaneler robotten kører henover er defekte eller ej. 
  • 2 motorer til hjulene
  • 1 motor til en løftemekanisme, der skal bruges til at fragte de defekte paneler væk og erstattes med de nye fra et lager 
Software
  • Softwarearkitekturen til denne opgave er behaviour-based. Robotten checker alle solpanelerne og i det øjeblik den finder en defekt skifter vi opførsel og skal udskifte det givne panel. Efterfølgende fortsættes den oprindelige behaviour og vi checker de resterende solpaneler.
Det absolut sværeste ved denne opgave er at kunne designe en robot, der kan navigere banen uden at støde ind i solpanelerne, samt at designe selve navigeringen. Problemet ligger i, at vi ikke har en fritliggende linje, som vi let kan følge og at robotten skal være i stand til at kunne vende tilbage til det defekte panels plads med erstatningen. 

Til slutpræsentationen skal vi have en robot der som minimum kan scanne de ni paneler og bringe et defekt panel med sig tilbage til basen/lageret.    

Navigating LEGO Road Elements

Til denne opgave skal NXT'en først navigere en opsat bane og efterfølgende danne sig et "roadmap" så den kan find den korteste rute fra et punkt A til B på banen. 

Hardware
  • 1 NXT unit
  • Mindst 3 lyssensorer. Den første placeres centralt og kan via en LineFollower navigere banen. De resterende to sensorer placeres på hver sin side af robotten så vi kan registrere mulige fodgængerovergange. Gør vi dette skal det noteres at der er muligheder for dele af kortet vi ikke har besøgt og vi skal vende tilbage til det.
Software
  • Sekventiel softwarearkitektur med dynamisk tilgang
  • Første sekvens indebærer at robotten kører en rute á la LineFollower
  • Når robotten er vendt tilbage til sit udgangspunkt, checker vi om vi har passeret nogle fodgængerovergange, hvilket er lig med potentielle sving. NXT'en returnerer til det punkt og mapper den sidste del af banen
  • Til sidst er det "blot" et spørgsmål om at kunne udregne den korteste rute fra A til B og omsætte den udregning til en kørselsvejledning. 
Den sværeste del af opgaven ville først og fremmest være at kunne mappe banen og skelne imellem den grå og hvide farve på vejen når vi skal bearbejde fodgængerovergangene. 

Til slut skal robotten kunne mappe en hel bane og efterfølgende kunne finde frem til den korteste vej imellem to specifikke punkter på banen. 


Konklusion

Vi har valgt at arbejde med balancerobotten. Dette er fordi at det først og fremmest er en anderledes opgave i forhold til de to andre opgaver der omhandler pathfinding. Selve robotten er ikke det mest udspekulerede design og derved kan fokus hurtigt flyttes over til softwarearbejdet med kalibreringen. En anden god ting ved dette projekt er, at det hverken er bøvlet at teste eller sætte op til den endelige præsentation. Det eneste der er brug for er robotten samt en bold. 






Monday, May 5, 2014

Embedded Systems Lesson 10

Date: 1/5 2014
Duration of Exercise: 3½ time
Group Members Participating: 
Henrik Jørgensen
Michael Schiønning
William Thorsen

Mål

Målet med denne øvelsesgang er at gennemføre øvelserne til denne uges ugeseddel Motivation-Based Behavior Selection in Agents

Plan

Planen for denne uge er:

  • Bygge en robot til øvelserne
  • Udføre opgaverne på ugesedlen  
  • Påbegynde blogindlæg 

Fremgangsmåde

Til  BumperCar-opgaven skulle vi igen arbejde med leJOSs Arbitrator- og Behaviorklasser. Vi havde allerede fra sidste uge påbegyndt basen af robotten og kunne nu nøjes med at påmontere den ultrasoniske sensor og bumperen vha en touch-sensor. Nedenstående ses et billede af vores BumperCar.


Til øvelserne tog vi udgangspunkt i den udleverede BumperCar.java fil og skulle gøre os en række observationer omkring klassen og derved robottens opførsel. Til at starte med kørte vi et "dry" testrun og kunne konstatere at robotten kørte fremad indtil enten den ultrasoniske sensor registrerede en forhindring. Det samme gjaldt touch-sensoren. Al brugt kode kan findes til sidst i rapporten. 

Så snart en af de to sensorer blev aktiveret ville robotten aktivere behavior'en "DetectWall" og  stoppe, bakke og dreje en smule til den ene side før den fortsætter med at køre fremad igen. Vi satte et elastik rundt omkring vores bumper og derved blev DetectWall hele tiden aktiveret og robotten blev altså ved med at bakke og efterfølgende dreje ad nauseum. 

Adfærden Exit, som reagerer på Escape-knappen og kalder System.Exit(0), er implementeret som en klasse efter samme princip som DriveForward og DetectWall. Exit-adfærden er sat til sidst i adfærdslisten og derved får den den højeste prioritet. 


Efterfølgende prøvede vi at teste vores Escape-knap når robotten bevægede sig rundt. Så snart knappen trykkes stoppede programmet øjblikkeligt såfremt DriveForward havde prioritet. Var det tilfældet at DetectWall var under opsejling ville den først færdiggøre sin bakken og korrigering af ruten før robotten stoppede. 

I både DetectWall og DriveForward har vi metoden takeControl der kaldes i Arbitrator. Vi skulle finde ud af om, at DriveForward's takeControl metode også kaldes når vores triggering condition for DetectWall opfyldes. Som det fremgår ud fra kodestykket neden under fra Arbitrator klassen. Her kan vi set at den starter fra den højestre prioritet og checker hvorvidt takeControl() returnerer true. Er det ikke tilfældet checker vi den næsthøjeste prioritet osv. Dvs i vores tilfælde bliver takeControl() i DriveForward ikke kaldet, hvis DetectWalls takeControl() returnerer true
             maxPriority = -1; highest = -1;
          for (int i = 0; i < behavior.length; i++)
          {
           int priority = behavior[i].takeControl();
                 if (priority > maxPriority ) 
                 {
                    highest = i;
                    maxPriority = priority;
                 }
          }
Ydermere skulle DetectWall sættes til at bakke i 1 sec før den begyndte at dreje og efterfølgende bevæge sig fremad. Dette kan ses ud fra følgende kodestump 
    Motor.A.backward();
    Motor.C.backward();
    int now = (int)System.currentTimeMillis();
    while (!_suppressed && ((int)System.currentTimeMillis()< now + 1000))

Sumo-robot

Til sumorobotten gik vi ud fra den opgivene kode, hvor vi implementerede flere behaviors for at gøre robotten til en bedre sumorobot. Da vi kom ldit sent i gang med sumo-delen af opgaven (og derved ikke nåede at være med til selve konkurrencen) sad vi til sidst og biksede lidt med en rimelig simpel tilgang til sumorobotten. Derved har vi ikke en video eller et billede af robotten. Den er i bund og grund det samme skelet som vores BumperCar fra første del, tilsat en lyssenor foran og bagved samt et lidt større hjul på vores touch-sensor. 

Først ændrede vi en DetectWall klassen til i stedet for at bakke væk, når bumperen er trykket, så kører vi lige frem i små korte ryk. Denne behavior fik den højeste prioritet da tanken bag var at når bumperen var trykket så ville vi være lige foran en modstander og kunne forhåbentligt brute force modstanderen ud af ringen. 

Denærst monterede vi 2 lyssensorer, henholdsvis foran og bagved. Sensorerne  skulle bruges til at sørge for at vi ikke kørte eller bakker ud af banen . Her løb vi ind i et problem, hvor vi ikke kunne få bilen til at skifte prioritet mellem de klasser som håndterer lyssensoren. Vi tænkte at med samme prioritet 
(return 75;) ville de skifte imellem dem. Fx hvis en lyssensoren bagpå robotten registrerede et skift fra sort til hvid ville den køre frem for ikke at falde ned fra banen og derved tabe. Når den forreste sensor så registrerede et skift kunne den ikke tage prioritet, og visa versa.

Tanken var at vi videre hen måske ville bruge den ultrasoniske sensor  til at scanne efter en modstander. Anden ide var sætten endnu en bumper bagpå og så have bilen kører frem og tilbage, med små turns, indtil den fik et input på en bumper og så kører fuld kraft i den givne retning.

Den brugte kode kan findes her 

Konklusion

I denne uge har vi arbejdet videre med adfærdsbaseret arkitektur, som er implementeret i subsumption API'en af leJOS NXJ. Vi har lært at "motivation values" giver os en hurtigere reaktiong og derved et bedre resultat hvad vores behaviors angår. Dette kan f.eks. ses i forbindelse med, at når vores EXIT behavior aktiveres får vi en øjeblikkelig reaktion. 

Monday, April 28, 2014

Embedded Systems Lesson 9

Date: 29/4 2014
Duration of Exercise: 3 timer
Group Members Participating:
Henrik Jørgensen
Michael Schiønning
William Thorsen

Mål

Målet med denne øvelsesgang er at gennemføre øvelserne til denne uges ugeseddel Navigation and Map Building

Plan

Planen for denne uge er:
  • Bygge en robot til øvelserne
  • Udføre opgaverne på ugesedlen 
  • Påbegynde blogindlæg

Fremgangsmåde

Vi lagde ud med at bygge basen til en robot ved at genbruge vores design fra forrige uges opgave. Derefter testede vi, hvilke hjul der ville være bedst til eksperimentet.

Vi startede med at prøve de store flade hjul med mål 81.6 x 15, fordi vi gerne ville hæve robotten så vi kunne få et roterende hjul ind under. Dette gjorde dog at udførselen af TachoNavigator blev meget "stor" med hensyn til arealet robotten kørte.

Efter et par test for at sikre os at koden virkede skiftede vi til de mindre 56 x 26 hjul og gjorde selve ruten for robotten 5 gange mindre, hvilket gav et fint lille areal hvor robotten kørte. De mindre hjul gjorde også at robotten bevægede sig mere roligt og forekom at have mindre slip imellem dækkene og overfladen. Desuden var svingene ikke så voldsomme og kastede ikke robotten ud af kurs. Aligevel kunne vi ikke konsistent få den tilbage til udgangspositionen.
Vi fik dog robotten til at give det samme resultat som Blightbot og derved finde frem til den distance den skal køre.

Koden kan findes her

Dernæst skulle vi som Maja Mataric placerer en marker for enden af robotten så vi kunne tegne den rute som vi havde kørt. Her opstod et problem med designet;

Vi havde spændt boardmarkeren foran med elastikker og da vi kørte robotten begyndte den at ryste så vi fik lange rækker af prikker eller bare ingenting.

For at løse dette forsøgte vi at sætte et par extra elastikker på som kunne presse boardmarkeren ned på whiteboardet.
Dette gav flere problemer da boardmarkeren da løftede robotten en smule og dermed havde hjulene ikke god kontakt med underlaget og den drejede da helt ud af kurs. I stedet for at bruge tid på et justere designet valgte vi at gå videre og bygge en ny robot fra bunden af med byggeguiden fra uge 7, da samme robot skal bruges til næste uges opgave, Sumobryderen.

 


Ovenstående kørsel er et resultat af

LegacyNavigator robot = 
new LegacyNavigator(wheelDiameter, trackDiameter, Motor.B, Motor.C, true);
for(int i = 0; i < 10; i++) {
robot.goTo(40F, 0F);
robot.goTo(20F, 20F);
robot.goTo(20F, -10F);
robot.goTo(0F,  0F);
}

Improved navigation.

En måde til at undgå objekter foran robotten er ved at bruge den  ultrasoniske sensor. Sensoren skal køre i en tråd hele tiden ved siden af selve vores rutenavigation. Registrerer den ultrasoniske sensor et objekt som er i vejen skal en ny rute beregnes.


Posering

Fremgangsmåden i [2] kaldes dead reckoning og deres implementation beregnes en fejlmargin set udfra hvor meget et givent hjul har kørt i forhold til hvad det burde have kørt. Denne korrektion for fejl kan ses som en P kontrol.


Fremgangsmåden i [5] er at beregne motorkraften udfra en model og så undervejs korrigere for eventuelle afvigelser. Da [5] ikke akkumulerer fejl bør den være mere præcis.


Beregningerne foretages i [5] ved tidsinterval kontra [2] der beregner efter en given kørt distance. Så her burde [5] også være mere præcis, dog kun så længe at tidsintervallet er mindre end distance intervallet i [2].


Lejos egen algoritme er implementeret i OdometryPoseProvider.updatePose()
Her ses det at Lejos skelner imellem det at dreje og det at køre lige ud. Denne skarpe opdeling virker til at give plads til akkumulering af fejlmargin da det hele afhænger af den drejede vinkel, som er upræcis.

Konklusion

I denne uge har vi arbejdet med tacho counteren og erfaret, at selvom der kan forekomme afvigelser, specielt når vores robot svingede, er det rimeligt simpelt at kunne præcisere robottens bevægelser vha. manipulering af tacho counteren. Der vil dog over tid nærmest uundgåeligt akkumulere fejl den antagede og reelle placering ved brug af dead-reckoning. Upræcise tachocounters, slip i dækkene o.l. gør at selv den perfekte algoritme vil afvige over tid.

Monday, April 21, 2014

Embedded Systems Lesson 8

Date: 22/4 2014
Duration of Exercise: 9 timer
Group members participating:
Henrik Jørgensen
Michael Schiønning
William Thorsen

Mål

Målet med denne øvelsesgang er at gennemføre øvelsen til denne uges ugeseddel Robot Race, altså at bygge en robot der kan gennemføre Alishan banen.

Plan

Planen for denne uge er:
  • Bygge en robot der kan gennemføre banen
  • Programmere robotten så den kan gennemføre banen
  • Påbegynde blogindlæg
Fremgangsmetode
Design af robotten:

Vi så med det samme at udfordringen lå i svingene og at det nok største problem lå i at vide hvornår vi skulle dreje. Efter en del trial-and-error fandt vi et design der ved brug af to touch-sensorer kunne registrere når en bom monteret foran på robotten var enten oppe, midt eller nede. Med denne var planen at føle hvornår robotten skulle dreje et forud defineret sving og dermed helt undgå at følge linjen på plateauerne. Bommen kunne desuden bruges til at afskærme de to lysesensorer fra indtrængende sollys.

Dette bom-design var mere problematisk end forventet at føre ud i livet og krævede en del timers arbejde.
En del af problemet lå naturligvis i sammensætningen af klodser for at opnå en tilstrækkelig rigid robot.
Vi havde brugt Lego Digital Designer til det første design og her er det let at blive snydt da tingene bare sidder fast hvor de skal. Da vi så samlede den designede bil så vi at det hængte sammen, bogstavligt talt.

Et andet problem var at touch sensors ikke har samme (de)aktiveringspunkter, denne forskellighed i følsomhed havde vi ikke umiddelbart tænkt på og det kostede igen tid at finde "sweet spot" så bommen virkede efter hensigten.



Kommunikation med robotten:
Vores tidligere implementering af Bluetooth var meget begrænset og slet ikke gearet til at sende information både til og fra robotten. Vi måtte da bruge en del tid på at udvide vores BT framework, dette kompliceredes desværre af en HashMap implementation i Lejos som ikke virker korrekt og smed tilsyneladende uvedkommende NullPointer exceptions til højre og venstre.

Design af programmet:
Vi besluttede at bruge en subsumption arkitektur. Dog så vi en problematik i forhold til antallet af behaviors der unødigt havde prioritet i forskellige stages af gennemkørselen. En idé var derfor at ændre i listen af behaviors alt efter hvilken stage af Alishan vi var nået til.

Simpel inddeling af stages og tilhørende behaviors.


Med to lys-sensorer brugte vi to PIDControllers fra lejos.robotics pakken. Her brugte vi manipulated value (mv) fra højre(venstre) lyssensor til at sænke farten på venstre (højre) hjul.

 Grov skitse over brug af to lyssensorer ift. styring
af tildelt kraft til det enkelte hjul.
Denne fremgangsmåde til dobbelt PID styring synes at virke godt når vi alene skal følge en lige linje. Et problem vi dog mødte var at vi havde gearet hjulene i et forsøg på at sænke robottens tyngdepunkt. Denne gearing havde en del slør og lagt sammen med motorens egen slør oplevede vi problemer med justering at P,I og D værdier. For at fjerne gearingen måtte vi også bruge mindre hjul for at undgå at skulle lave ændringer på bommen og placering af lysesensorer. Begge dele hjalp meget på robottens evne til at følge linjen.



Koden kan findes her

Konklusion
Vi syntes selv at idéen i robotten grundlæggende er god; Bommen virkede umiddelbart efter hensigten og de to lys-sensorer var nok til at kunne følge linjen tilfredsstillende. Med mere tid på programmeringsdelen ville det bestemt være muligt at opnå en tilfredsstillende gennemkørsel.
Dette projekt har nok mest af alt lært os noget omkring KISS ift. LEGO technic og NXT sensorere. Jo færre bevægelige dele jo bedre.




Monday, April 7, 2014

Embedded Systems Lesson 7

Date: 3/4 2014
Duration of activity: 3 timer
Group members participating:
Henrik Jørgensen
Michael Schiønning
William Thorsen

Mål

Målet med denne øvelsesgang er at gennemføre øvelserne til denne uges ugeseddel Agents & behaviour selection in agents, subsumption architecture1

Plan

Planen for denne uge er:
  • Ombygge robotten til øvelserne
  • Udarbejde ugens øvelser 
  • Påbegynde blogindlæg

Resultat af øvelser

Opgave 1

Efter at have bygget den nye robot med en ultrasonisk sensor, en lyssensor samt en bumper, via to touch sensorer, startede vi den udleverede AvoidFigure9_3.java2 klasse. Måden den virker på er, at robotten hele tiden måler afstanden fra sensoren til et objekt, samtidigt med at den fortsat kører fremad.

Når sensoren opfanger en afstand, der er mindre end et givent threshold stopper robotten og den checker hvilken en af sine 2 målinger der er den største. Vi er ikke helt 100% sikker på hvad der menes her, men vi regner med at den højre afstandsværdi måles ud fra sensorens højre øje og vice versa for venstre.

Når de to værdier sammenlignes drejer robotten i den retning hvis "øje" har den største værdi og derved drejer vi uden om den givne forhindring. Vi rendte dog ind i et tilfælde, hvor vores robot ikke kunne finde ud af at rette op når den bevægede sig imod en mur. Hvis vinklen mellem muren og robotten er tilpas spids vil de målinger sensoren foretage sig ikke nå under klassens threshold og vi ender med nærmest at glide langs væggen uden at rette op.

Enten kunne man pille lidt ved klassens threshold og hæve det for at undgå situationer som dette. Det der nok er mest sandsynligt, men som vi ikke lige fik dobbeltchecket, er at da vi byggede robotten satte vi alle sensorene på. Altså betyder det at den ultrasoniske sensor ikke er placeret lige midt for robotten, men nærmere 1/4 af robottens bredde (jvf evt billedet fra opgavesiden1). Derved kan det muligvis gøre at hvis vi har en spids vinkel mellem robot og en væg på højre side af robotten kan målingerne på det højre øje være over vores threshold som en centreret sensor måske ville have reageret på.


I den anden del af opgaven var det blot et spørgsmål om at indsætte et ekstra check for at se om alle tre afstande (leftDistance, frontDistance og  rightDistance) er mindre end vores stopThreshold. Når det er tilfældet giver vi først lidt power til begge hjul så den bakker og derefter kun power til det ene af hjulene så vi kan vende.

Koden kan findes her3

Opgave 2

Programmet RobotFigure9_9.java4 implementerer nu yderligere to behaviours: nemlig Follow og Cruise samt en arbritarian mechanism. Efter at have downloadet programmet og overførte det, startede vi robotten. Fordi vi i første forsøg var ude i det lyse fællesrum var der ikke rigtigt en lyskilde for Follow behaviouren at skulle specifikt følge. I stedet for får Avoid prioritet og checker hvorvidt vi er ved at støde ind i noget. Er det ikke tilfældet får Follow nu prioriteten og checker om der er en lyskilde at følge. Ellers bevæger vi os blot fremad.

Slår vi både Follow og Avoid fra har vi blot en robot der kan kører fremad og intet andet. Aktiverer vi nu  Follow vil robotten aktivt søge imod en stærkere lyskilde, men skulle vi kolliderer med en mur har vi ingen mulighed for at rette op, da det er Avoids ansvar.

Opgave 3

Escape-funktionen5 bliver opbygget på samme måde som det udgivne eksempel i  Mobile Robots, Inspiration to Implementation,  samt de allerede opgivne Follow.java og Avoid.java
Efter et par justeringer virkede robotten efter hensigten og bumperen fungere nu og får prioritet når den bliver trykket uanset hvad der kommer ind af lys- eller længdesensoren6



Opgave 4

Vi nåede ikke at påmontere den tredje motor til lyssensoren.

Opgave 5


Arbiter og SharedCar virker grundlæggende på samme måde som foreslået i Mobile Robots, Inspiration to Implementation s. 306 7. I stedet for en hardcoded liste indsættes processer i et array, udfaldet af konflikter afgøres ved en prioritet ud fra indexeringen af dette array; Jo hørere indeks jo højere prioritet.

I Martin8 håndteres prioritetskonflikter mellem processer (flere med samme prioritet) ved først at finde højeste prioritet og så vælge den først fundne process med denne prioritet.


Konklusion


Denne gang har vi lært omkring brugen af forskellige behaviours og måden man kan væve dem sammen på via en arbritarian mechanism. Nemlig at man vægter hvilken opførsel der er vigtigst og derved ændrer robotten sin strategi Samtidig skal man dog, igen, være opmærksom på at specilt den soniske- og lyssensor kan være lidt tunge at danse med og måske ikke altid giver en de allerskarpeste målinger.





1 http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson7.dir/Lesson.html
http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson7.dir/Programs/AvoidFigure9_3.java
http://codetidy.com/8726/
http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson7.dir/Programs/RobotFigure9_9.java
http://codetidy.com/8728/
http://codetidy.com/8727/
http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson7.dir/11128_Mobile_Robots_Inspiration_to_Implementation-Flynn_and_Jones.pdf
Fred Martin, [4, page 214-218]

Tuesday, March 18, 2014

Embedded Systems Lesson 6

Date: 13/3 2014
Duration of activity: 3 timer
Group members participating:
Henrik Jørgensen
Michael Schiønning
William Thorsen

Mål

Målet med denne øvelsesgang er at gennemføre øvelserne til denne uges ugeseddel Embodied Agents1


Plan

Planen for denne uge er:
  • Bygge den NXT Braitenberg robotten udfra beskrivelsen i ugeseddelen.
  • Gennemgå ugens øvelser.


Resultat af øvelser 

Vi lagde ud med at bygge basis køretøjet udfra beskrivelsen og de to .lxf filer.

Vehicle 1


Ved brug af en lyssensor skulle vi implementere opførslen af det mest simple Braitenberg køretøj (Vehicle 1). Her forbindes en sensor "direkte" til motoren og genererer et signal proportionelt med sensorens input. Dvs. at jo stærkere lys sensoren opfanger, jo hurtigere kører motoren. For at opnå bedst mulig opløsning valgte vi at normalisere lydsensorens rå værdier til et motor interval. Da SoundSensor klassen ikke direkte understøtter rå værdier måtte vi tilgå disse direkte på SensorPort klassen.

SensorPort.S1.readRawValue();

Før dette virkede som forventet måtte porten dog klargøres for rå værdier:

// Manually setup sensorport for raw sound readings.
SensorPort.S1.setTypeAndMode(SensorConstants.TYPE_LIGHT_ACTIVE, SensorConstants.MODE_RAW);

Først normaliserede vi til intervallet [0; 100] hvor vi som forventet for exitatory forbindelsen imellem sensor og motor observerede at køretøjet, når det lys, bevægede sig fremad i en hastighed proportionel med lysstyrken. Omvendt gik det da vi ændrede forbindelsen til inhibitory, hvor hastigheden var omvendt proportionel med lysstyrken. Da kørte bilen med fuld styrke i mørke indtil den så lys.

Den dansende robot forsøgte vi at fremmane ved at normalisere fra det større rå interval [0; 1023] og ned til Car.forward() metodens interval [-100; 100] således

public int normalizeToRange(int light) {
    int output = 200 -((light - MAX_LIGHT) * 200) / (MIN_LIGHT - MAX_LIGHT);
 
    if(output > 100) output = 100;
    else if(output < -100) output = -100;
    return output;
}


MIN_LIGHT og MAX_LIGHT representerer minimum og maximum værdierne for de lysværdier vi forventer at få fra lyssensoren. Disse afhænger af sensoren og de lysforhold der er tilstede hvor denne arbejder.

At sætte musik til bilen vil få den til at danse, muligvis pga af de forskellige temposkift I sangen (NB: video er gået tabt I produktion )

Kode her2

Vehicle 2a og 2b

Vi monterede endnu en lyssensor foran, vinklet til hver sin side med 45 grader og forsøgte os med begge konfigurationer (2a og 2b). Styringen implementerede vi udfra Vehicle 1 og

I konfiguration 2a i exitatory tilstand observerede vi at robotten drejede væk fra lyset. I inhibitory tilstand søgte robotten imod lyset.

I konfiguration 2b observerede vi det omvendte af 2a; I exitatory tilstand drejede robotten imod lyset, jo kraftigere jo hurtigere. I inhibitory ville den ikke "se ind i lyset", den drejede væk.




main loop ( aner ikke om dette skal med? )
while (true) {
    int s4 = SensorPort.S1.readRawValue();
    int s1 = SensorPort.S4.readRawValue();

    // Update min/max light values
    if(s1 < MAX_LIGHT) MAX_LIGHT = s1;
    if(s4 < MAX_LIGHT) MAX_LIGHT = s4;
    if(s1 > MIN_LIGHT) MIN_LIGHT = s1;
    if(s4 > MIN_LIGHT) MIN_LIGHT = s4;

    average_s1 = alpha * s1 +(1-alpha) * average_s1;
    average_s4 = alpha * s4 +(1-alpha) * average_s4;

    LCD.drawString("Raw: " + s1 + ":" + s4, 0, 0);

    int s4n = s4 > average_s4 ? normalizeToRange(s4) : 0;
    int s1n = s1 > average_s1 ? normalizeToRange(s1) : 0;

    LCD.drawString("Norm: " + s1n +":" + s4n, 0, 1);

    Car.forward(s4n, s1n);
}



Opdatering af MIN_LIGHT og MAX_LIGHT over tid udførte vi i main loop
Vi observerede ingen udtalt ændring i robottens opførsel ved automatisk at opdatere værdierne af set MIN_LIGHT og MAX_LIGHT. 

Koden kan findes i fodnote 2. 

Vehicle 3

Denne nåede vi ikke at eksperimentere med.


Konklusion


I dennne uge har vi, med udgangspunkt i Braintenberg bygget to robotter med dertilhørende program på baggrund af Tom Deans noter. Lydsensoren blev brugt til vehicle 1, som havde en extiatory og en inhibitory metode. Dette samme var tilfælde for lyssensoren. Altså har vi en robot, der bevæger sig hurtigere desto højere en lyd den kan opfange fra omgivelserne.




















1 http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson6.dir/Lesson.html
2 https://docs.google.com/folderview?id=0B22Duz_kNMvWUk9ZS2NzYzRmZ2M&usp=docslist_api#

Tuesday, March 11, 2014

Embedded Systems Lesson 5

Date: 6/3 2014
Duration of activity: 3 timer
Group members participating:
Henrik Jørgensen
Michael Schiønning
William Thorsen

Mål

Målet med denne øvelsesgang er at gennemføre øvelserne til denne uges ugeseddel Communcation and Embedded Systems1

Plan

Planen for denne uge er:
  • Ombygge robotten til balanceøvelserne
  • Udarbejde ugens øvelser
  • Påbegynde blogindlæg  
Resultat af øvelser 

Opgave 1

I denne opgave har vi samlet vores robot efter Phillipe Hubains anvisning2 samt brugt Brian Bagnalls klasse Sejway.java3 til at få vores robot til at kunne balancere. Når det udleverede program startes skal robotten holdes i en oprejst balancerende tilstand. Når Enter trykkes endnu en gang afmåles og huskes det udgangspunkt robotten befinder sig i. Derefter kan den udregne størrelse af den fejl i de efterfølgende målinger og derefter hvor kraftigt den skal korrigere sin balance.


Opgave 2 

For lettere at kunne ændre på konstanterne når vi arbejder med balancering og PID fik vi sat en Bluetooth forbindelse op imellem vores NXT robot og en PC. Vi tog udgangspunkt i den udleverede klasse PCcarController.java4 og kunne ligeledes modificere klassen at styre vores parametere i robotten. Dette gøres ved først at justere de nødvendige text fields så vi har ki, kd, kp og scale. 



Ellers lå arbejdet i at ændre hvad rækkefølge output stream sender værdierne og selvfølgelig også sende de nytilføjede værdier, et eksempel er 

String kpText = kpField.getText();
float kpFloat = Float.parseFloat(kpText);
dos.writeFloat(kpFloat);
dos.flush();
Dette laver en string med hvad der er i tekstfeltet, parser det til en float (vi blev opfordret til at bruge floats)
derefter sende den nye floatværdi så vi kan flushe og gøre klar til næste.

Den endelige klasse kan ses her5

For at kunne kommunuikere med vores PCControllerBalance.java klasse tog vi den udleverede BTcontrolledCar.java og modificerede6 den til at inkludere en række handlers til at håndtere de PID-værdier vi sender via Bluetooth.

Denne BTcontrolledPID.java implementerede vi i den oprindelige Sejway.java6 klasse for så at kunne begynde vores balancejusteringer

Neden for ses vores balancerende robot efter de første PID justeringer er gjort via den trådløse forbindelse. Klippet blev optaget i et mørkt rum da det blev foreslået af Phillipe Hurbain, at et bedre resultat kunne opnås, hvis robotten tog sine målinger i et mørkt rum.





Opgave 3

Til den tredje opgave skulle vi prøve og erstatte lyssensoren med vores colour sensor fra sidste uge. Til at starte med satte vi colour sensoren på i samme højde som vores lyssensor, men ldet virkede som om, at sensoren først var i stand til at registrere noget før det var for sent og robotten var ved at vælte.

Da vi så flyttede sensoren tættere på jorden, lig med hvad vi gjorde de tidligere uger,  begyndte robotten at være i stand til at kunne balancere i meget kort tid. Vi erkendte derefter, at man højest sandsynligt skulle re-justere PID variablerne påny, da sensoren ikke reagerer helt på samme måde som lyssensoren. Da dette var sidst på dagen nåede vi ikke at justere særligt meget.

Opgave 4

Vi nåede ikke at tage hul på opgaven omkring brugen gyro-sensoren til at balancere med.

Konklusion 

I denne uge har vi arbejdet med, hvordan vi får vores NXT robot til at kunne balancere vha.  lys og farvesensoren. Endvidere har vi arbejdet med hvilke begrænsninger det medbringer. Skulle man følge Hurbains råd er det en nogle rimeligt specifikke krav der, muligtvis, skal opfyldes. F.eks. en ikke uniform overflade samt et mørkt rum osv. Vi har også lært, hvordan man etablerer en Bluetooth forbindelse mellem robot og PC, hvilket gør justeringer af en PID-controller uanmindeligt meget mindre molboagtigt. Vi har fået vores robot til at kunne balancere i en anelse længere  tid end den oprindeligt udleverede klasse, men ellers blev størstedelen af dagen brugt på at sætte Bluetooth-forbindelsen ordentligt op.



1 http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson5.dir/Lesson.html
2 http://www.philohome.com/nxtway/nxtway.htm
3 http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson5.dir/Sejway.java
4 http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson5.dir/PCcarController.java
5 https://docs.google.com/file/d/0B2MYdpHIaaatTEd1MXhxYk15c0E/edit
6 https://drive.google.com/folderview?id=0B22Duz_kNMvWOG9kYUU1b3FaZzQ&usp=gmail#

Tuesday, March 4, 2014

Embedded Systems Lesson 4

Date: 27/2 2014
Duration of activity: 3 timer
group members participating:
Henrik Jørgensen
Michael Schiønning
William Thorsen 


Mål


Målet med denne øvelsesgang er at gennemføre øvelserne til denne uges ugeseddel Sequential and reactive control strategies1

Plan

Planen for denne uge er: 


  • Påmontere robottens lyssensor 
  • Udarbejde ugens øvelser
  • Påbegynd blogindlæg 

Resultat af øvelser

Opgave 1

Til den første opgave skulle vi teste hvor godt det udleverede program BlackWhiteSensor.java2 var i stand til at afmåle forskellige lyse og mørke overflader. Måden hvorpå programmet virker på er, at via metoden calibrate tages der målinger over en hhv. hvid og sort overflade. Dette indstiller så standardværdien for sort og hvid. efter at have taget en hvid og en sort måling bliver grænseværdien mellem sort og hvid udreget som medianen mellem de to værdier. Altså har vi at blackWhiteThreshold =(blackLightValue + whiteLightValue)/2.

I stedet for at kaste os ud i et nyt program til at teste BlackWhiteSensor.java med tog vi blot LineFollowerCal.java,  som forklares i næste opgave. Selvom de værdier fra lyssensoren teoretisk set burde ligge fra 0-100 lå vores målinger fra 37-62. Et bud på hvorfor vi ikke kommer helt tæt på 0 og 100 kunne være at de afmålte overflader enten ikke var klare nok (i det hvide tilfælde) samt at lokalets naturlige lys kunne påvirke de sorte målinger.

Opgave 2

I denne opgave skulle vi arbejde med programmet LineFollowerCal.java3, som gør brug af calibrate metoden fra foregående program. Efter at metoden light får en måling fra sensoren sættes de til standardværdien for sort og hvid. Efterfølgende går LineFollowerCal ind i et loop, hvor der kontinuert tages prøver med lyssensoren samt kraft bliver tilført moteren alt efter om mplingen registrerer hvid eller sort.

Når programmet modtager en måling fra lyssensoren vurderes den til at være enten sort, hvis den er under den udregnede grænseværdi. Ellers er den hvid. I tilfædet af en sort registrering tilføjes kraft til robottens venstre motor og den drejer til højre. Registreres der en hvid måling i stedet tilføjes den højre motor samme kraft og vi drejer til venstre. Resultatet er at robotten er i stand til at følge en linje mellem en sort og en hvid overflade ved konstant oscillering.

Opgave 3


I denne opgave skulle vi lave en ColourSensor klasse (Her navngivetBGWSensor.java4) som ud over at kunne registrere sort og hvid også kunne se farven grøn. Dette blev lavet med at ganske enkelt viderudvikle den allerede udgivne BlackWhiteSensor.java. Vi havde allerede fundet ud af at hvid og sort henholdsvis ligger på over 60 og under 40. En scanning af et stykke grønt papir fortalte os at grøn var 49-51 afhænging af nuancen af grøn. Så vi lavede endnu et threshold imellem sort og hvid til programmet, som kunne printe ud hvis den kunne se en lysværdi som matchede grøn.


Opgave 4


Siden vi nu kan registre om en farve er grøn kan vi modificere den udleverede Linefollower5 program. 
Vi bruger vores new class så vi kan måle grønt. Vi udvider det tjek som skal se om robotten har krydset mellem den sorte og hvide side af linjen. I det ekstra tjek stopper robotten, hvis den ser en grøn farve. 

Vi fandt hurtigt ud af at robotten kunne finde på at registrere grøn når den kørte langs linjen i det øjeblik den skiftede fra den sorte til den hvide side. 

else if (sensor.green()) {
      if(seen > 50) {
      Car.stop(); // Must be green then
      LCD.drawString("GREEN!!", 0, 4);
      Thread.sleep(3000);
      seen = 0;

      break;

Som det ses oven for sørgede vi for at robotten først stoppede efter at den havde taget 50 målinger af grøn i træk ved hjælp af en counter. Ydermere bliver counteren sat til 0, såfremt en sort eller hvid måling foretages imellem de grønne. 


Opgave 5


Her skulle vi prøve at implementere en PID-controller6 som i uge 3

LineFollower.java kunne relativt let blive implementeret after at gense den gamle pseudokode7.


Kp = 1000                             
Ki = 100                              
Kd = 10000                            
offset = 45                           
Tp = 50 
integral = 0                          
lastError = 0                         
derivative = 0                        
Loop forever
   LightValue = read light sensor     
   error = LightValue - offset        
   integral = integral + error        
   derivative = error - lastError     
   Turn = Kp*error + Ki*integral + Kd*derivative  
 Turn = Turn/100                      
   powerA = Tp + Turn                 
   powerC = Tp - Turn                 
   MOTOR A direction=forward power=PowerA   
   MOTOR C direction=forward power=PowerC   
   lastError = error                  
end loop forever


Kalibreringen af PID er mangelfuld, men funktionsdygtig:
Vi lagde ud med at at sætte Ki = 0 og Kd = 0, dernest kalibrere Kp indtil bilen oscilerede omkring linjen. Herefter udregnede vi kI og kD (Ziegler–Nichols methoden) som foreslået i [7]. Dette resulterede dog i vilde udsving i den tildelte kraft til den enkelte motor. Vi kalibrerede da selv disse værdier ved trial and error indtil bilen kunne gennemføre banen.Der efterlades bestemt plads til forbedringer i kalibreringen.

Opgave 6


Vi fik udleveret en NXT Color Sensor og programmet ColourSensorSensor.java8. Dette brugte vi til at 
tjekke om vi kan se forskellige farver. Vi brugte de 3 farver vi har arbejdet med til denne lektion, altså Sort, Hvid og Grøn og vi fik disse resultater.


Hvid
Raw valueCalculated value
Rød650162
Grøn285150
Blå 530160
Light590155
Colour value: 6


Sort
Raw valueCalculated value
Rød600
Grøn600
Blå 600
Light600
Colour value: 7



Grøn
Raw valueCalculated value
Rød50060
Grøn53092
Blå 43542
Light50060
Colour value: 1



Sensoren kunne fint finde ud af hvad farve var hvad, men det var ret svært at gennemskue

hvordan det faktisk gjorde det.

Dernæst brugte vi vores "Stop at Green" kode til at teste om denne sensor også kan bruges

Resultatet var tilfredsstillende, dog havde sensoren det praktiske problem at den , ulig lyssensorem, skulle være meget tættere på at være vinkelret mellem selve sensoren og overfladen før den ville stoppe på det grønne felt.

Konklusion

I denne uge har vi monteret lyssensoren på vores robot og fået et indblik i, hvordan den fungerer. Dette er bl.a. gjort ved at teste forholdene mellem sort og hvid via målinger fra BlackWhiteSensor. Ved at bruge kaliberingen har vi kunnet påvirke robottens motorer  og været i stand til at få den  til at følge en linje imellem en sort og en hvid overflade. Ydermere har vi fået sensoren til at opfatte en tredje farve ved at ændre på grænseværdierne i programmet. Derved har det været muligt at kunne få robotten til at stoppe på et grønt felt efter at have fulgt linjen mellem hvid og sort.

Vi har også erfaret at siden sensoren registrerer lysværdier og ikke egentlige farver kræver det lidt ekstra benarbejde at sikre os at robotten kun stopper på det grønne felt og ikke tidligere i løbeta f en overgang mellem den hvide og sorte del af banen.

Derudover har vi lært, mere, om hvordan en PID-controller kan bruges til at mindste robottens oscillering samt udfordringerne med at finde ud af hvilke variabler der skal ændres og med hvor meget. Endeligt har vi stiftet bekendsskab med farvesensoren og erfaret at man skal tage højde for vinklen mellem den målte overflade og sensoren før vi kunne registrere den grønne farve.



1 http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson4.dir/Lesson.html
2 http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson4.dir/BlackWhiteSensor.java
3 http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson4.dir/LineFollowerCal.java
4 https://drive.google.com/?authuser=0#folders/0B22Duz_kNMvWTjByYlEtc2NHQjg
5 LineFollowerStop.java i linket https://drive.google.com/?authuser=0#folders/0B22Duz_kNMvWTjByYlEtc2NHQjg
6 https://docs.google.com/file/d/0B22Duz_kNMvWaHlKejIwY0hURUU/edit
7 http://www.inpharmix.com/jps/PID_Controller_For_Lego_Mindstorms_Robots.html
8 http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson4.dir/ColorSensorTest.java

Monday, February 24, 2014

Embedded Systems Lesson 3

Date: 20/2 2014
Duration of activity: 3 timer 
Group members participating: 
Henrik Jørgensen
Michael Schiønning 
William Thorsen 

Mål 


Målet med denne øvelsesgang er at gennemføre øvelserne til denne uges ugeseddel "Acting and Actuators[1]

Plan

Planen for denne uge er: 
  • Påmontere robottens lydsensor 
  • Udarbejde ugens øvelser. 
  • Påbegynd blogindlægget for denne uge med den forrige uges kritik i mente.
Resultat af øvelser 

Opgave 1 

Til den første øvelse skulle vi have monteret lydsensoren samt downloadet, compilet og kørt SonicSensorTest.java[2] til at teste vores sensor

Den nedenstående tabel viser de resultater vi har fået fra vores målinger. Til målingerne har vi gjort brug af et normalt klap samt en kontinuert tone[3] fra en af vores telefoner. Ideen med de to valg er, at klappets mønster indeholder et spring fra lav-amplitude til høj-amplitude (som vi senere ser i opgave 5). Tonen derimod bibeholder den samme amplitude (alle 10 timer...), hvilket giver os så konsistente målinger som muligt. 

cm050100
klap493211
beeeep925420

Som det fremgår af tabellen kan vi se at beep-tonen opfanges langt lettere ved de forskellige afstande. Dette kan være grundet at tonen, som førnævnt, er kontinuert, men samtidigt at klappets ampitude ikke er lige så stor som tonen og falder relativt hurtigt af i styrke. 

Alle målingerne er foretaget vinkelret på lydsensoren og afstanden er afmålt fra spidsen af sensorens "hovede".


Opgave 2

Til den anden opgave skulle vi igen gøre brug af DataLogger.java[4] fra sidste uge til at indsamle lyddata via det udleverede SoundSamling.java[5]. Grafen neden under er over beep-lyden da den som sagt var lettere at holde styr på grundet den konstante lyd. 


Opgave 3

I denne opgave skulle vi gøre brug af SoundCtrCar.java[6]. Programmet får robotten til gentagne gange at vente på en høj lyd. Ved første registrering bevæger den sig fremad, ved den anden registreting drejer den til højre. Den tredje gang vil den dreje til venstre og fjerde gang den registrerer en høj lyd stopper robotten.

Måden hvorpå programmet aflæser høje lyder er, at i metoden waitForLoudSound bliver der konstant taget prøver med lydsensoren indtil den modtager en prøve der ikke er mindre end det threshold (her sat til 90). Når en af de returnerede prøver er >= 90 returnerer funktionen, hvilket i dette tilfælde betyder at den har opfanget en høj lyd.  

Opgave 4

Programmet SoundCtrCar2.java[7] looper og vi skal få den til at stoppe efter et tryk på ene af vores tilgængelige knapper. Dette kan gøres ved at implemtere en buttonlistener som lytter på en input på en knap, I vores tilfælde escape og så når breaker ud af den igangværende løkke. 

Samt også lettest ved at hardcode escape til altid at breake ud af loops og terminere programmet.


Opgave 5

I denne opgave skulle vi forsøge at bruge Sivan Toledo[8] metode til at registrere klap på.

Vores endelige implementation afviger fra Toledo ved at være mindre rigid i kravene til et klap.
Vi benytter to sample-rækker, en til kort- og en til lang-tidshorisont. Størrelsesforholdet mellem medianen i de to rækker afgør da om vi tolker et klap. Opførelsen kan da reguleres ved at skrue på samplerate, samplesize og grænseværdien for tolkning af et klap.

En naiv implementation der fulgte Toledo vil være mere usikker.

...
if(soundLevel < 50) {
Thread.sleep(25);
soundLevel = sound.readValue();
if(soundLevel>85) {
Thread.sleep(250);
soundLevel = sound.readValue();
if(soundLevel<50) {
Sound.beep();
break;
}
}
}
...

I stedet for en flydende evaluering af den indkommende lyd låses tråden i mindst 275ms ved kraftige lyde længere end 25ms.
Implementationen i ClapBeep.java[9] var mere reagerende, dog kunne den få problemer ved længerevarende støj der øgede middel db for den længerevarende sample række.

Opgave 6

Til den sidste opgave skulle montere to sensorer på robotten og via de lyde den modtog skulle den altid bevæge sig imod høje lyde. For at få party robotten til at følge hvilken side lyden kom fra lavede vi et simpelt differensudtryk. Er differens 0 kør ligeud, er differens under eller over 0 så kør til den respektive side. Til dette har vi implementeret PartyBot.java[10].

Nedenfor ses en optagelse af vores PartyBot.java i funktion. Vi havde nogle enkelte problemer med at robotten kørte lige frem selvom lydkilden var placeret foran den ene sensor. Altså burde robotten ahve drejet enten til venstre eller højre. Vi regner stærkt med at dette er fordi den anden sensor formår at opfange lyden selvom den peger i en anden retning. Derfor sætter robotten sin differens til at være 0 og den kører lige frem. 

Ydermere oplevede vi at vores robot faktisk kunne opfange nogle af de lyde de andre grupper i lokalet gjorde brug af, hvilket resulterede i at robotten rørte på sig, inden vi havdde tændt for vores lydkilde. 




Konklusion

I denne uge har vi fået monteret robottens lydsensor og fået et indblik i, hvordan sensoren virker via denne uges opgaver. Dette indebærer bl.a. vores afstandsmålinger af klappe- og beep-lyden.Ydermere har vi lært at det er muligt at få robotten til at bevæge sig i bestemte retninger når den opfanger høje lyde via sin sensor. Dog har vi også erfaret at der kan være visse problemer med brugen af lyd. 

Nogle gange kan det være svært for sensoren at opfange lyde konsistent over længere afstande, som da vi forsøgte at bruge dataloggeren til at måle vores klap. Endvidere rendte vi ind i det førnævnte problem, at den ene sensor kunne opfange en lyd der var ment til anden sensor og derved skabe en hvis form for ravage 



1 http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson3.dir/Lesson.html
2 https://docs.google.com/file/d/0B22Duz_kNMvWWkxuVEx3cVhtN2c/edit
3 http://www.youtube.com/watch?v=GhhcpQI3iAs
4 http://legolab.cs.au.dk/DigitalControl.dir/NXT/src/DataLogger.java
5 http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson3.dir/SoundSampling.java
6 http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson3.dir/SoundCtrCar.java
7 https://docs.google.com/file/d/0B22Duz_kNMvWYnM3Mks1Uk1tZHM/edit
8 http://www.tau.ac.il/~stoledo/lego/ClapCounter/
9 https://docs.google.com/file/d/0B22Duz_kNMvWaFlISi02RUZWelU/edit
10 https://docs.google.com/file/d/0B2MYdpHIaaatRWhCYmNodVNjUVE/edit