Thursday, September 30, 2010

Lab 05 - Line Follower with Calibration

Dato: 30/9 2010
Varighed: 11-14
Deltagere: Daniel, Leni, Martin A og Martin N
1. Formål
2. Øvelsegennemgang
Billede af LEGO 9797 Line Follower with Calibration car:
Del 1 - Black White Detection
Denne del opgaver går ud at danne os nogle erfaringer med at anvende lys sensoren, ved at bruge BlackWhiteSensor.java programmet.
Programmet anvender readCalue() på sensoren denne værdi er den normaliserede værdi som tager den rå værdi og omregner den til et tal mellem 0 og 100, hvor hvid ligger mellem 55 - 65 og sort omkring 35. Som man kan se er dette et meget lille spektrum vi her arbejder i og andre farver ville være meget svære at finde frem til.
BlackWhiteSensor koden fungerer ved at man kalibrere sensoren ved først at læse sort ind og derefter hvid herefter ligges disse to værdier sammen og middel værdien bliver den som bestemmer om det er sort eller hvid robotten ser, denne metode fungerer ok hvis motoren ikke accelerer alt for meget så robotten kommer for langt væk fra linjen.
  • Black value: 357
  • White value: 550
  • Green value: 370-400
De tre værdier ovenfor viser resultaterne fra aflæsning af lys sensoren med metoden getNormalisedValue() som returnere de rå værdier fra lys sensoren, dette giver en bedre opløsning af sensorens aflæsninger dette havde i spørgsmålet omkring sort og hvid programmet ingen betydning da robotten alligevel delte spektrumnet i to dele tolkede alt som enten sort eller hvidt.
Men når programmet skal udvides til at finde flere farver ville et større spektrum gøre det nemmere at skelne mellem de enkelte farver.

Del 2 - Line Follower with Calibration
Video af, hvordan Line Follower with Calibration kørte:
I denne del brugte vi koden fra BlackWhiteSensor som udgangspunkt for at se om robotten var i stand til at anvende givne program til at følge linjen. og her viser problemstillingen nævnt ovenfor sig hurtigt i form af hvis robotten kommer for langt væk fra den sorte linje er den tabt og køre i ring altså robotten reagerer kun på farve ændringer.

Næste forsøg var så bruge regulering til at få robotten til bedre at kunne følge linjen og denne opgave blev gjort til vores aflevering 6 og robot kapløbet så for mere information omkring dette kig på afleveringen til opg. 6.

Del 3 - ColorSensor with Calibration

Med udgangspunkt i BlackWhiteSensor var opgaven her at udvide koden til at kunne kende forskel på mere end sort og hvidt. For at gøre dette skulle algoritmen omkring de to målte værdier og bare tage middelværdien af disse udskiftes.

Første forsøg var at tage udgangspunkt i målinger foretaget i del 1. og derefter bruge lidt af den samme tankegang som sort hvid metoden, nemlig ved at inddele spektrumnet i en sort hvid og grøn zone hvor alle værdier over grøn betraktes som hvid alt under grøn som sort og derefter alt i zonen som grøn.

Problemet her er at grøns værdi ikke ligger særligt langt væk fra sort og derfor kan det være meget svært at få robotten til at skelne mellem sort og grønt, dette gjorde at robotten en gang i mellem mens den kørte lavede nogle stop sekvenser i overgangsfasen mellem hvid og sort da disse overgange er flydende sker der nemlig det at på de rigtige tidspunkter vil blandingen af den sorte og hvide halvdel på banen ville blive til grøn og derfor signalerer stop til robotten.

For at gøre det sværere for robotten at læse værdien grøn mens den køre på banen blev der lavet først en cirkulær buffer hvor de aflæste værdier blev gemt og derefter midlet for at se om denne værdi var grøn og så reagerer på dette, men det samme problem var stadig til stede da en middel værdi ikke ændre på det faktum at der er tale om et flydende værdigrundlag fra sensoren og at en middelværdi bare ville kunne give flere områder hvor værdien grøn ville kunne blive fortolket af robotten.

det næste forsøg tog også udgangspunkt i en cirkulær buffer hvor der i stedet for en middel værdi blev forsøgt at huske på de sidste 5 værdier og så opstille en regel om at de sidste 5 værdier skulle være grønne før at det blev tolket som en grøn kommando. dette havde en delvis effekt robotten stoppede med at lave tilfældige stop kommandoer mens den kørte, fordi en tilfældig grøn værdi ikke længere ville blive tolket som stop kommando, men problemet nu var at 5 værdier i grøn zone var meget afhængig af om solen var bag en sky eller om skidt kom ind foran sensoren, og dette gjorde det meget tilfældig om robotten fik tolket rigtigt mens den var i den grønne zone.
Del 4 - Line Follower that stops in a Cole Zone
forsøget her blev ikke til en kørende robot da opgave 6 tog lidt over og resultatet kan ses i denne opgave.

Men i stedet lavede vi her en række test hvor vi i displayet skrev hvilken zone robotten kunne se via sensoren og dette blev brugt til at forsøge de ovennævnte metoder til at genkende den grønne farve i forhold til de sorte og hvide farver.

Et forsøg vi ikke fik nået at lave var at dedikere en sensorer til kun at kigge efter grøn ved at placerer en sensor løftet op i luften i forhold til de sort hvide sensor ville man kunne hæve det grønne spektrum op midt i mellem sort og hvid man ville kunne bruge aflæsninger over tid (e.g cirkulær buffer ) samt lave et større spekter for sensoren at tolke grønt i og give robotten en meget mere stabilt grundlag til at genkende grøn.
3. Konklusion

Opgaven var et godt grundlag til opg. 6 og blev også til grundlaget for den kode vi lavede til den opgave. der blev ligeledes gjort en masse erfaringer med anvendelsen af lys sensoren, dels omkring præcision og dels omkring problemstilligner omkring tolkning af sensorenes værdier.
4. Referencer

Lab 04 - Self-balancing robots



Dato: 16/9 2010
Varighed: 11-16
Deltagere: Daniel, Leni, Martin A og Martin N

1. Formål
Formålet med denne øvelse var at bygge en LEGO SegWay, dvs. en selv balancerende robot. Der findes tre sensor opsætninger som kan anvendes til en sådan robot:
  • En traditionel lyssensor
  • Et accelerometer
  • Et gyrometer
Ved at anvende enten et accelerometer eller et gyrometer er det muligt at få det mest stabile respons og derigennem en robot hvis evne til at opretholde sin egen balance er forøget i forhold til kun at benytte en lyssensor.
Denne øvelse har imidlertid til opgave at give et indblik i hvorledes et selvregulerende system kan fungerer, hvortil en lyssensor vælges for at simplificerer opgaven.

2. Øvelsesgennemgang
Den selvbalancerende robot blev opbygget ud fra et design af Philippe Hurbain's NXTway, som er en portering af Steve Hassenplug's Legway fra RCX til NXT.


Et billede af den færdige robot kan ses herunder:


Selve reguleringen af robotten foregår igennem en PID regulator hvor kildekoden bygger på elementer fra Brian Bagnall's bog "Maximum Lego NXTBuilding Robots with Java Brains".


Den færdige robot fungerer ved at programmet startes, hvorefter robottens balance position findes. Når dette punkt er fundet, trykkes ENTER knappen ned for at definerer et offset.
Proportional regulatoren måler herefter de konstante ændringer som opstår ved at robottens motor med små ryk får den til at bevæge sig frem og tilbage. Den aktuelle værdi trækkes fra balance offsettet, og udgører sammen med Kp (proportional konstanten) P vægten i PID regulatoren.


De øvrige regulerings elementer vil ikke blive forklaret i dette afsnit, istedet er det muligt at se en video af hvordan den ovenfor byggede robot holder balancen:


Det er tydeligt at robotten har svært ved at holde balancen, hvor det faktum at robottens balance punkt ikke befinder sig ved 90grader har en stor del af skylden. Ligeledes blev det observeret at når balance punktet skulle indstilles, så var det svært at justerer det 100% korrekt da trykket på ENTER fik robotten til at rykke sig en smule.


Løsning af balance problem - SegWay Rider
Der var i gruppen enighed om at såfremt man justerede Kp, Ki og Kd så burde det være muligt at opnå et mere stabilt respons. Men istedet for at spilde en masse ressourcer på en LEGO model som efter vores opfattelse var "dårlig", valgte vi at opbygge en ny model. Grundlaget herfor var at vi ønskede en robot hvis naturlige balance punkt var placeret ved 90grader for at opnå en mere stabil robot.


En LEGO model af en reel Segway PT designet af Dave Parker blev brugt som grundmodel til vores SegWay Rider. Informationer samt bygge instruktioner kan findes på følgende side:
http://nxtprograms.com/segway/index.html


Selve koden til at få denne robot til at balancerer var bygget til LEGO's egen udviklingsplatform, men vi vurderede at den eksisterende PID regulator ville kunne justeres til at fungerer med denne LEGO model istedet.
Et billede af SegWay Rider kan ses herunder:


Fordelen ved denne model er at dens naturlige balance punkt befinder sig i en vinkel på 90grader, samt at den har sin vægt placeret "højt" over hjulene, hvorved den får et meget mere stabilt tyngdepunkt.


For at undgå at skulle benytte ENTER til at kalibrerer et balance punkt, blev denne robot designet således at man har 4 sekunder fra programmet startes til at finde balance punktet. Herefter samples den aktuelle værdi fra lyssensoren og benyttes som offset for alle fremtidige målinger. Dette viste sig at gøre det meget nemmere at gentage balance indstillingen med større præcision end før, da man kun skulle fokuserer på at opretholde robotten i dens naturlige balance punkt.
Koden til at foretage denne kalibrering kan ses herunder:

public void getBalancePos() throws Exception {
// turn up system volume to ensure user hears the beeps
Sound.setVolume(75);


// wait for 4 seconds before determining balance position (offset)
int timeOut = 3;
while (timeOut != 0) {
Sound.beep();
Thread.sleep(1000);
timeOut--;
}
// SegWay Rider must be balanced when we reach 0!!
offset = ls.readRawValue();
Sound.beepSequenceUp();
}

Selve reguleringen af SegWay Rider bygger på den tidligere omtalte PID regulator, hvor præcisionen af de forskellige målinger og del resultater blev forøget ved at anvende float istedet for int.


Herunder vil P, I og D leddene blive gennemgået for at forklare hvorledes disse udregnes:

float pError = avgValue - offset;

if (pError < 0)
pError = pError * 1.8F;

integralError = ((integralError + pError) * 2)/3;

float derivError = pError - prevError;
prevError = pError;

float PIDValue = KP * pError + KI * integralError + KD * derivError;

Først findes proportional fejlen som den aktuelle måling minus det fastsatte balance offset. Derefter afgøres det hvorvidt fejlen er negativ (svarende til at robotten tilter bagud). Er det tilfældet så justeres proportional fejlen med en faktor 1,8 for at kompenserer for den mindre mængde lys som sensoren kan se i forhold til et fremad tilt.
Integrations fejlen findes som summationen af alle tidligere fejl vægtet med 2/3, for at sikrer at de første målinger vil påvirke denne summation mindre og mindre som tiden går. Hvis denne skalering ikke anvendes vil værdierne løbe løbsk og få robotten til at oscillerer ud af kontrol.
Differential fejlen findes som den aktuelle proportional fejl minus den forrige fejl.


Disse tre led som samlet udgører PID regulatoren summeres efter deres individuelle konstanter er blevet ganget på, som det også fremgår af den sidste kodelinie ovenfor.


Forbedringer af stabiliteten
For at forbedrer stabiliteten af robotten var det nødvendigt at se på udsvingene i input værdierne til lyssensoren. Et plot af sensor målinger kan ses herunder for en NXT 2.0 farve lyssensor:

Målingerne er foretaget vha. den tidligere benyttede datalogger fra øvelse 3 på proportional fejlen. Plottet illusterer et udsving mellem +/- 20grader i forhold til robottens balance punkt. Det ses tydeligt at der er mange små skift i de målte værdier, men at kurve formen eller passer overens med det forventede. Endvidere er det værd at observerer at sample værdierne mellem 500-2500 begynder at bevæge sig mod nul selvom robotten stadig bevæger sig fremad.

Altså kan det konkluderes at såfremt robotten får et udsving på mere end ca. 10grader i fremadgåede retning, så vil målingerne ikke afspejle den reele retning. Det er derfor vigtigt at PID regulatoren fungerer hurtigt nok til at kunne udgå udsving større end +/- 10grader for at opretholde et stabilt respons.


De små udsving kan fjernes ved at lave en midling af de foregående samples, et såkaldt moving average filtrering. Efter nærmere test, kunne det konkluderes at det kun var muligt at midle over de 2 sidst målte samples for at robotten ikke kom ud over den ovenfor beskrevede +/- 10graders begræsning (grundet den højere sampletid).
Et plot af proportional fejlen for et 2. ordens moving average filtreret sensor input kan ses herunder:

Det ses udfra plottet at de små udsving tydeligt blevet fjernet, hvorfor det blev valgt at benytte denne midlede sample værdi. Koden til realisering af MA(2) filteret kan ses herunder:

public float MAFilter(float value) {
// update the delayline top->bottom and add new sensor value
delayline[0] = delayline[1];
delayline[1] = value;

// return the calculated average
return (delayline[0]+delayline[1])/2;
}

Hvor delayline er et array indeholdende 2 pladser som begge er initialiseret til 0.


Plot af henholdsvis: proportional, integration og differential fejlene for robotten under balance kan ses herunder, sammen med et plot af den samlede PID regulator værdi:

De indivudelle konstanter Kp, Ki og Kd blev justeret, således at proportional og diffential fejlene ville få mest indflydelse på PID regulator værdien.

Til at styre motorens retning blev følgende kode benyttet:
if (PIDValue > 100)
PIDValue = 100;
if (PIDValue < -100)
PIDValue = -100;

int normPower = (int)(45 + (Math.abs(PIDValue) * 55) / 100);
Motor.B.setPower(normPower);
Motor.C.setPower(normPower);

if (PIDValue > 0) {
Motor.B.forward();
Motor.C.forward();
} else {
Motor.B.backward();
Motor.C.backward();
}

Variablen normPower styrer kraften til de to motorer B og C (disse blev valgt da de sad på samme H bro hvorved de udsættes for de samme delays og derfor skulle reagerer på samme tid). normPower er normalizeret således at PID regulator værdien (som er begrænset til værdier mellem +/- 100) højst vil bedrage med 55% af motor kraften, mens de resterende 45% svarer til den kraft som motorerne konstant udsættes for selvom robotten er i perfekt balance. Det var nødvendigt at sætte den minimale motor kraft så højt for at få motorerne til at reagerer kraftigt nok til at kunne opretholde sit balance punkt.


Herunder kan en video af hvor effektivt den nye SegWay Rider kørte:


Det var muligt at få robotten til at balancerer i 2 minutter inden videoen blev startet, samt 3 minutter efter. Den væltede først da Martin gik ind foran lampen som oplyste gulvet hvorved lysniveauet ændrer sig så meget at det fastsatte offset ikke længere var aktuelt.

3. Konklusion
Det lykkedes at få lavet en LEGO model (SegWay Rider) med et stabilt respons ved at benytte en lyssensor.


Konklusionen på effektiviteten af denne type balancerende robot er at det er rigtig svært at få indstillet balance punktet korrekt, hvis det blot er en smule skævt eller hvis sampleværdien springer i det øjeblik offsettet udmåles vil robotten bevæge sig ud af balance.
Det er ligeledes meget svært at lave en robot som vil virke på alle typer overflader, samt er det ikke muligt (som beskrevet ovenfor) at ændrer alt for meget på miljøet omkring robotten mens den balancerer (dvs. lys, underlag etc.) uden at den ikke vælter.


Såfremt man ønskede at lave en mere effektiv balancerende robot, vil det være mere praktisk at anvende et gyro meter, og så evt. en lyssensor hvis man ønsker at få robotten til at følge en linie.


4. Kildekode
Link til kildekoden for SegWay Rider kan hentes her!

Tuesday, September 21, 2010

Lab 03 - Clap Controlled Car

Dato: 16/9 2010
Varighed: 11-16
Deltagere: Daniel, Leni, Martin A og Martin N

1. Formål
Formålet med denne øvelse var at opnå erfaring med lyd sensoren, hvorledes den fungerer samt danne et overblik over dens begrænsninger.

2. Øvelsesgennemgang
Del 1 - Test af lyd sensor
Først blev lyd sensoren monteret på LEGO model 9797 ifølge vejledningen. Hvorefter et test program blev skrevet på baggrund af SonicSensorTest.java som var udleveret ved forrige øvelse.

Billede af LEGO 9797 bilen kan ses herunder:



SoundSensorTest.java instansierer et objekt af klassen SoundSensor, hvorefter amplituden af det opfangede lyd signal vises på LCD displayet.

SoundSensor ss = new SoundSensor(SensorPort.S2, true);
LCD.drawString("Sound Level (dBa): ", 0, 0);

while (! Button.ESCAPE.isPressed()) {
LCD.drawInt(ss.readValue(), 3, 0, 1);
Thread.sleep(300);
}

SoundSensor klassen kræver at der angives hvorvidt der ønskes at måle i dB_A eller dB_B, med henholdsvis true eller false.


Test
For at kunne teste amplitude karakteristikken af lyd sensoren blev der udført to tests:
#1 - Lydsensoren blev placeret i forskellige afstande til en lydkilde, hvis volumen var sat til et fast niveau.
#2 - Lydsensoren blev placeret i en fast afstand til lydkilden, hvorefter volumen af lydkilden blev justeret.

Til test #1 blev en PC benyttet med programmet SineGen installeret. SineGen blev benyttet til at udsende en 1kHz sinus tone med en amplitude på -10dB (i forhold til det maksimale lydniveau på PC’en).
Denne amplitude blev valgt for at undgå at lyden fra PC’ens højtalere blev forvrænget, hvilket var tilfældet ved højere niveauer.

Resultaterne fra disse tests kan ses af nedenstående oversigt:

Variable afstand, fast volumen på -10dB:
  • 135 cm : 16 dB
  • 120 cm : 51 dB
  • 105 cm : 48 dB
  • 90 cm : 70 dB
  • 75 cm : 47 dB
  • 60 cm : 45 dB
  • 45 cm : 93 dB
  • 30 cm : 91 dB

Variable volumen, fast afstand på 45 cm:
  • -10 dB(PC) : 93 dB(lejOS)
  • -13 dB(PC) : 73 dB(lejOS)
  • -16 dB(PC) : 52 dB(lejOS)
  • -19 dB(PC) : 42 dB(lejOS)
  • -22 dB(PC) : 27 dB(lejOS)
  • -25 dB(PC) : 20 dB(lejOS)
  • -28 dB(PC) : 13 dB(lejOS)
  • -31 dB(PC) : 9 dB(lejOS)
  • -34 dB(PC) : 6 dB(lejOS)
  • -37 dB(PC) : 4 dB(lejOS)
  • -40 db(PC) : 3 dB(lejOS)
Resultaterne fra test #1 var meget varierende, og det er praktisk umuligt at fortælle noget om lyd sensorens karakteristik ud fra disse målinger. Det eneste det er muligt at konkludere ud fra disse målinger er at der ikke er en lineær sammenhæng mellem opfangede amplitude og afstand til lydkilden.

Resultaterne fra test #2 derimod viser en klar sammenhæng mellem opfangede volumen i en fast afstand til lydkilden. Det er svært at konkludere på hvorvidt målingerne der er foretaget reelt er korrekte, da vi ikke var nogen oplysninger om hvilken reference sensoren benytter.

Nedenfor kan ses en graf som viser målingerne fra test #2:



Hvis vi antager at den returnerede værdi fra sensoren er dB(spl) (sound pressure level), med en dB(A) karakteristik (dvs. outputtet er vægtet således at der opnås en approksimation af det menneskelige øres reelle respons), ser vi en klar afvigelse i forhold til det forventede.
Amplituden af baggrundstøjen er blevet målt til 2dB, hvilket er 38dB lavere end hvad man reelt vil kunne forvente i forhold til en dB(spl) måling hvor en måling på 40dB svarer til et meget stille rum, mens 30dB svarer til en måling foretaget i et lyddødt rum.

En forklaring på denne afvigelse, kan være at målingerne som præsenteres er justeret med et fast offset for at opnå et bedre dynamikområde. Dette ville være en logisk forklaring, hvis ikke det var fordi at det maksimale lydniveau der kunne måles var omkring 93dB, hvor 255dB burde have været det maksimalt opnåelige.
Altså kan vi ikke konkludere yderligere fra vores tests hvad angår lydmålingens reference, andet end at der er en tilnærmelsesvis lineær sammenhæng mellem opfanget amplitude i en fast afstand (variabel volumen). Mens der ved tilfældet med en variable afstand (fast volumen) er en ulineær sammenhæng.

Del 2 - Datalogger
Til denne del af øvelsen benyttede vi lyd sensoren som en datalogger for at kunne overføre målinger til evt. senere behandling på en PC.

Koden til dataloggeren var givet ved øvelsens start.

Herunder ses et plot af det opsamlede data fra lyd sensoren:
Det opsamlede data består af en sekvens af henholdsvis 1 og 2 klap. Dette blev valgt for at analysere, hvorledes indhyldningskurven for et klap ser ud, hvilket benyttes til løsning af del 4).

Del 3 - Sound Controlled Car
Lydsensoren udlæser lydniveauer mellem på værdier mellem 2 og 93.
For at kunne kontrollere bilen ved hjælp af høje lyde, aflæser vi lydsensoren som i opgave 1, og sammenligner denne værdi med vores soundThreshold, som er den øvre værdi vi definerer som lydniveauet der skal til at foresage et retningsskift.

Som vist i del opgave 1 i koden læser vi en værdi fra sensoren og sammenligner denne værdi med vores soundThreshold som er den øvre værdi vi definerer som niveauet der skal til et ændrings skift. Altså vil høje lyde være værdier over soundThreshold værdien.

-- TODO Martin Bitte Koden Einsetzen --

Video af, hvordan Sound Controlled Car kørte:



Opgaven her er at anvende ButtonListener interfacet til at gøre det muligt at lukke sound Controlled car programmet i de indre løkker og ikke kun fra main løkken.
For at gøre dette har vi oprettet en klasse som implementerer buttonListener. I klassen kalder vi system.Exit(0) som lukker programmet.
I vores main kalder vi Button.addButtonListener() med vores objekt som parameter, hvilket gør, at vi på et vilkårligt tidspunkt ved tryk på knappen får afviklet vores luknings funktion i listener objektet.

-- TODO more code plz --

Video af hvordan Sound Controlled Car kørte samt stop ved brug af ESCAPE knappen:


Del 4 - Clap Controlled Car
Den sidste del af øvelsen, bestod i at få bilen til at kunne detektere et eller flere klap, og adskille disse lyde fra andre høje lyde, fx en blender der tændes, eller et højt pift.

Derfor skal vi have lavet en model af, hvordan lydsensoren opfatter et klap.
De data der ligger til grund for denne model blev opsamlet i øvelse 2 ovenfor.

Som det ses på grafen, er det karakteristiske ved et klap, at der er en meget kort stigetid i begyndelsen (1-2 samples ved en samplerate på 100 Hz), efterfulgt af et langsomt aftagende forløb.

For at kunne finde de lydsekvenser der har disse egenskaber, gemmer vi løbende samples fra lydsensoren i en cirkulær buffer på 15 samples (TODO er det 15 i den endelige kode?).
For hver ny sample tjekkes det om den ældste sample i bufferen er over vores valgte tærskelværdi (clapPeakThreshold), og hvis det er tilfældet undersøges de resterende samples, for at se om falder ned under vores nedre tærskel værdi (clapQuietThreshold).

Hvis signalet opfylder begge disse betingelser har vi detekteret et klap, og vi starter nu en counter der tæller ned fra 1 sekund, for at se om der kommer flere klap efter hinanden.
Hver gang et nyt klap detekteres nulstilles tælleren.

Når tælleren på et tidspunkt løber ud, returnerer programmet til hovedløkken, som bestemmer hvilken vej bilen skal køre, alt efter hvor mange klap der er blevet detekteret.
Et klap får bilen til at køre fremad, mens 2 eller flere klap får den til at køre baglæns.

Video af hvordan Clap Controlled Car kørte:



Kildekoden der implementerer klap detektionen kan findes her: (TODO indsæt link til sunrise)

Konklusion
Vi fik undersøgt NXT lydsensorens virkemåde, og konstateret at den er meget upålidelig til at detektere afstand fra en lydgiver.
Det lykkedes at få optaget en indhyldningskurve for hhv 1 og 2 klap, få overført disse data til en PC, og plottet kurven.
Derefter lykkedes det at detektere om en lyd var over en vis styrke, og ændre bilens omdrejningsretning på hver gang denne værdi overskrides.

Endeligt lykkedes det for projektgruppen at få modelleret et klap, baseret på opsamlede data, og implementere en detektering af dette klap på NXT platformen, hvor efter LEGO bilen kunne styres ved at klappe et bestemt antal gange inden for 1 sekund af hinanden.

Referencer
http://www.tau.ac.il/~stoledo/lego/ClapCounter/

Thursday, September 9, 2010

Lab 02 - Wall Hugger

Dato: 9/9 2010
Varighed: 11-14
Deltagere: Daniel, Leni, Martin A og Martin N

1. Formål
Formålet med denne øvelse var at opnå erfaring med ultralyds sensoren og dennes begrænsninger.

2. Øvelsesgennemgang
Del 1 – Test af ultralyds sensor
Først blev ultralyds sensoren monteret på LEGO model 9797 i følge vejledningen. Herefter blev SonicSensorTest.java programmet kompileret og overført til NXT bricken.

Billede af LEGO 9797 bilen kan ses herunder:



Programmet kører i et while loop hvor der med et givet interval måles en afstand. Afstanden til et objekt opmåles ved at den dedikerede ultralyds sensor udsende en pulse (et såkaldt ping), herefter lytter sensoren efter pulsens echo (reflektion).
Den tid det tager for pulsen at løbe fra sensoren ud til objektet og tilbage igen kaldes "time of flight". Den målte tid omsættes direkte i den dedikerede ultralyds sensor til en afstand i cm, hvorefter den udregnede afstand sendes til NXT bricken via I2C bussen.

Til test af ultralyds sensoren blev LEGO bilen placeret med en given afstand til en væg. Herefter blev bilen rykket længere og længere væk fra væggen og evt. "døde huller", samt maksimal rækkevide noteret. Der blev udført tests med to forskellige sampling rates på henholdsvis 10ms og 300ms. Disse blev valgt for at observerer hvorvidt evt. genudsendte pulser (ved 10ms) ville kunne forstyrre målingerne væsentligt.

Tests
1. sample rate - 10ms
Der blev observeret en jævn udmåling af afstanden til væggen i intervallerne 17-163cm og 202-233cm. Dog opstod der et dødt område i intervallet 163-202cm.
For at verificerer at dette ikke var grundet repeterende pulser som forstyrrede opmålingen (hvad enten der er tale om reflektioner fra andre vægge eller væggen selv), blev testen foretaget igen ved en sample rate på 300ms

2. sample rate - 300ms
Her blev de samme målinger observeret som ved en sample rate på 10ms.

Altså kan vi ud fra de målinger vi har foretaget konkluderer at puls frekvensen må være væsentlig højere end 100Hz (hvilket også er forventet at ligge i omegnen af 50-100kHz).

3. test op ny væg - sample rate 300ms
Vi prøvede at udfører samme test på en anden væg hvor der var større afstand til andre vægge/hjørner. Denne test viste sammenlignelige resultater, uden de store variationer.

4. test udendørs - sample rate 300ms
Ved udendørs testen var det ikke muligt at måle en afstand på større end 133cm, herefter viste den målte afstand blot 255.

Test resultater:
10 ms samplerate
  • 233 (NXT) : 232,1 cm
  • 202 (NXT) : 198,1 cm
  • Dødzone (255 NXT) : 198 - 163 cm
  • 163 (NXT) : 163 cm
  • 120 (NXT) : 119,8 cm
  • 17 (NXT) : 17 cm
300 ms samplerate
  • 163 (NXT) : 161 cm
  • Dødzone (255 NXT) : 160 - 129 cm
  • 133 (NXT) : 128,7 cm
  • 17 (NXT) : 15 cm
Disse resultater viser en klar sammenhæng mellem jo lavere samplerate (jo længere tid der er mellem samples) jo større afvigelse er der mellem den reelle og den målte afstand.

Del 2 - Tracker
Tracker programmet blev overført og afviklet på NXT bricken, hvorefter det blev observeret hvorledes LEGO bilen opførte sig.

LEGO bilen blev placeret i en afstand af ½m fra væggen, hvorefter programmet blev afviklet, herefter begyndte bilen at køre fremad, men sænkede farten jo tættere på væggen bilen kom. Da bilen var nået en fast afstand fra væggen begyndte den at kører frem og tilbage for at opretholde denne afstand.

Programmet må altså benytte ultralyds sensoren til at opmåle afstanden til et objekt, og derefter forsøge at opretholde en fastsat afstand fra dette objekt ved at køre frem og tilbage.
Derved kan vi konkluderer at programmet må udregne et error signal som baserer sig på den målte afstand i forhold til en ønsket afstand.

Hvis vi betragter programmet fra et mere regulerings mæssigt syn kan dette oversættes til at der er implementeret en P-regulatering (propertional), hvor fejlen (error signalet) sammen en gain faktor afgører hastigheden som bilen kører med.
Hastigheden vil altid være mindst 60% og adderes til outputtet fra P-reguleringen, hvilket er årsagen til at bilen kører hurtigere jo længere væk fra væggen bilen befinder sig.
Er outputtet fra P-reguleringen positiv er det nødvendigt for bilen at køre fremad og vice versa.

Del 3 - Wall Hugger
Sidste del af øvelsen bestod i at få robotten til at køre langs en mur i en fast bestemt astand.

For at gøre det muligt skulle robottens hoved modificeres, således at ultralydssensoren pegede i en 45 graders vinkel mod muren.
Resultatet af denne modifikation kan ses på billedet herunder:



Reguleringen af robottens afstand blev implementeret med en simpel proportional regulator, der bestemte forskellen mellem den ønskede afstand (sat til 40cm) og den faktiske afstand fra muren. Herefter blev denne afstand multipliceret med en gain faktor på 2,5, og endelig trukket fra motorkraften på den motor der sidder på den side som robotten skal dreje til.

Denne reguleringsmetode giver den mest jævne kørsel, i forhold til en on/off regulering, og sikrer at robotten kører med størst mulig fart langs muren.

Herunder ses implementeringen af propertional regulatoren:

if ( distance != noObject )
{
error = distance - desiredDistance;
if ( error > 0 )
{
powerR = (int)(100 - error*gain);
powerL = 100;
}
else
{
powerL = (int)(100 + error*gain);
powerR = 100;
}
else
{
powerL = 100;
powerR = 60;
}
Car.forward(powerL, powerR);


Video af hvordan Wall Hugger kørte:




3. Konklusion
Generelt set lykkedes alle de opstillede test, og de fejl vi stødte på undervejs blev rettet.

4. Referencer
http://lejos.sourceforge.net/index.php
http://www.philohome.com/wallfollower/wallfollower.htm

Lab 01 - Line Follower

Dato: 2/9-2010
Varighed: 11-14
Deltagere: Daniel, Leni, Martin A og Martin N

1. Formål
Formålet med denne øvelse var at opnå erfaring med installation og opsætning af leJOS.

Herudover at give deltagerne et indblik i hvorledes et simpelt reguleringssystem fungerer, ved at uploade og afvikle Java applikationen LineFollower.java på den opbyggede Lego NXT model.

2. Øvelsesgennemgang
Del 1 - leJOS installation og opsætning
Først blev driveren fra LEGO’s hjemmeside downloadet og installeret for at kunne kommunikere med NXT bricken.
Herefter foregik installationen af leJOS version 0.85 samt JDK version 1.6 update 20-21 foregik uden der opstod nogle problemer. Følgende tutorial blev fulgt:
http://lejos.sourceforge.net/nxt/nxj/tutorial/Preliminaries/GettingStartedWindows.htm

Efter fuldendt installation blev NXT bricken flashed med leJOS firmwaren. Her opstod et problem, da driveren til Lego Mindstorm Firmware Update Mode ikke var indeholdt i den driver fil som var blevet hentet fra LEGO’s hjemmeside. I stedet blev NXT bricken detekteret som et GPS Tracker Cam.
For at løse dette problem blev LEGO Mindstorms NXT 2.0 suiten installeret, hvorefter leJOS firmware flash af NXT bricken foregik uden yderligere problemer.

Til at teste om leJOS firmwaren var blevet installeret korrekt på NXT bricken, blev sample programmet "View" kompileret og uploadet til bricken. Dette foregik via en command promt med følgende kommandoer:

nxjc View.java

nxj –r View

Sample programmet blev både kompileret og afviklet som forventet på NXT bricken.

Del 2 - Upload og afvikling af LineFollower program
Efter at have opbygget LEGO modellen til 9797 LEGO car ud fra samlevejledningen, var det muligt at afprøve funktionaliteten i NetBeans plugin’et.
NetBeans installationen foregik uden problemer, og det samme gjorde installationen af NetBeans plugin’et vha. følgende vejledning:
http://lejos.sourceforge.net/nxt/nxj/tutorial/Preliminaries/UsingNetbeans.htm

Et projekt blev oprettet i NetBeans, hvorefter LineFollower.java koden blev hentet ind. Da vi forsøgte at kompilere projektet via NetBeans opstod der dog det problem, at kompileren ikke kunne finde leJOS.nxt pakken. Dette blev løst ved at åbne projekt options og under ”Java Source Classpath” fjerne den relative URL til leJOS classes.jar og erstatte den med en URL til en kopi af classes.jar, som blev overført til projektmappen.

Herefter forsøgte vi igen at kompilere projektet vha. build.xml filen med kommandoen ”uploadandrun”. Igen opstod der et problem af samme type som ovenstående.
Det viste sig at build.properties filen som lå i roden af projektmappen indeholdt en forkert reference til NXJ_HOME mappen:
nxj.home=..snapshot

I stedet for at hente den environmental variable som var sat, var der i stedet indsat stien: ”../snapshot”. Dette blev rette til:
nxj.home=${env.NXJ_HOME}

Herefter kunne NetBeans kompilere programmet korrekt og uploade det til NXT bricken.

Herunder findes et billede af den opbyggede LEGO 9797 car:




Del 3 – Test af LineFollower program
Efter afvikling af LineFollower programmet blev lysniveauet målt for følgende tilfælde:
  • På bordet: 53
  • I fri luft (1m over bordet): 42
  • Sort banedel: 32
  • Hvid banedel: 55

Ud fra de målte værdier kunne vi konkluderer at programmet burde fungere med den allerede fastsatte blackWhiteThreshold på 43, der er midt mellem sensorens værdi for den sorte og hvide farve.

Banetesten var en succes, LEGO bilen kørte hele banen igennem, kørte rundt omkring den blå overflade for enden og kørte tilbage af banestrækning igen.
En video af, hvordan banetestene så ud, kan ses ved at trykke her:



Del 4 – Måling af lysniveau for andre farver
Lysniveauet blev målt for følgende farver:
  • Hvid:55
  • Gul: 47
  • Lyserød: 45
  • Rød: 44
  • Grå: 44
  • Blå: 43
  • Lilla: 41
  • Mørkeblå: 38
  • Sort: 32
Det lys som sendes ud af lysdioden er rødt lys, dvs. at for at opnå en maksimal sensor udlæsning skal den overflade som reflekterer lys ind på sensoren, reflektere mest muligt af dette røde lys. Derfor burde en rød overflade med den samme lød som lysdioden give den samme sensor udlæsning som en hvid overfalde, da de begge (teoretisk) reflekterer det røde lys fuldstændigt.
En overflade med en anden farve vil give en sensor udlæsning, der afhænger af hvor meget af den røde farve der reflekteres fra overfladen.

Del 5 – Måling af lysniveauer uden rød lys
Alle de tidligere målte farver blev målt igen, men uden at tænde for det røde lys. Dette resulterer i en måling af, hvor godt det naturlige lys' refleksion kan måles af sensoren.
Målingerne blev som følger:
  • Hvid:42
  • Gul: 48
  • Lyserød: 41
  • Rød: 44
  • Grå: 43
  • Blå: 44
  • Lilla: 40
  • Mørkeblå: 37
  • Sort: 24
Der ses ud fra målingerne at der ikke er stor forskel på disse målinger og de oprindelige for alle andre farver end sort og hvid.
Ud fra dette kan vi konkludere at sensorens responsivitet må være afstemt efter lysdioden, således at den er mest følsom overfor den samme røde farve som lysdioden udsender.

Da lysniveauet for hvid er faldet til 42, vil det være nødvendigt at justere variablen blackWhiteThreshold til en lavere værdi, for at få LEGO bilen til at gennemføre banetesten korrekt uden at have lysdioden tændt.
Denne nye værdi som valgt til 33, da den værdi ligger lige mellem de målte værdier for sort og hvid.
Ændringen af variablen blackWhiteThreshold fungerede efter hensigten.

Del 6 – Ændring af samplerate
Her skulle det undersøges, hvilken indflydelse en evt. ændring af sampleraten ville have på LEGO bilen evne til at fuldføre en banetest.

Sampleraten var oprindeligt sat til 10ms, og det skulle efterfølgende forsøges med en ændring til henholdsvis: 50ms, 100ms, og 1000ms.
Først blev gennemløbet med en samplerate på 10ms observeret, hvorfra det kunne konkluderes at banetesten blev gennemført som forventet med små udsving til højre/venstre ved overgangen mellem banens sorte og hvide dele. Det blev også observeret at motorerne ikke virkede til at kunne følge med til en ændring med 10ms, hvilket resulterede i et større udsving end man kunne have forventet med den lave samplerate.
Dette skyldes at motorerne ikke reagerer øjeblikkeligt på en ændring i spænding, da inertimomentet i hjul og motoranker er med til at opretholde rotationen.

Konsekvensen af at ændre samplerate til en lavere værdi end motorernes responstid er, at jo længere tid der går imellem hver sample, jo større sving fra side til side vil bilen tage, da der går længere tid inden den "opdager" at den skal ændre retning.

Ved meget lave samplerates når bilen slet ikke at sample lyset når den er over den sorte linie, og ender derfor med at dreje rundt om sig selv, indtil det tilfældigvis passer med at er samples på det tidspunkt hvor den er over den sorte streg, hvorefter bilen vil begynde at dreje den anden vej rundt om sig selv.

Ved en test med sample rate på 500 ms drejede LEGO bilen så meget væk fra stregen at den ikke kunne finde tilbage igen. Endvidere kunne den heller ikke finde stregen igen efter at være drejet en hel omgang rundt, grundet det tidligere nævnte dilemma med at sample på det korrekte tidspunkt.


Banetestene for den ændrede sample tid kan ses her:

100ms


500ms



Del 7 – LCD.drawString test
I denne del opgave skulle vi forsøge at anvende string direkte i kaldet LCD.DrawString() for at se på hukommelses forbruget i NXT’en.
Ved at kalde Runtime.getRuntime().freeMemory() og udskrive resultatet fra denne funktion på NXT'ens display vil vi kunne se hukommelsesforbruget i NXT’en.
Kodestumpen der kører systemets kontrol loop og udskrivning på LCD displayet ser således ud:

final String left = "Turn left ";
final String right= "Turn right";
while (! Button.ESCAPE.isPressed()) {
if (light.readValue() > blackWhiteThreshold) {
// On white, turn right

LCD.drawString(right, 0, 1);
MotorPort.B.controlMotor(0,stop);
MotorPort.C.controlMotor(power, forward);
} else {
// On black, turn left

LCD.drawString(left, 0, 1);
MotorPort.B.controlMotor(power, forward);
MotorPort.C.controlMotor(0,stop);
}
LCD.drawString(String.valueOf(Runtime.getRuntime().freeMemory()) , 0, 4);
LCD.drawInt(light.readValue(), 3, 9, 0);
Thread.sleep(10);
}

Når vi bruger string right og left variablerne forventer vi, at NXT enheden bruger mindre hukommelse end ved at kalde direkte med strenge.
Grundlaget for dette er, at vi i variablerne bruger final string prefix som gør, at strengen kun bliver allokeret en gang og derefter sendes der en reference med til denne hukommelse når disse strenge skal sendes til en funktion.
Altså ville vi forvente at den frie hukommelsen ikke ville falde efter første gennemløb af kontrol loopet.
I testen viste det sig dog at den frie hukommelse stadig falder, dog ikke med konstant hastighed. Dette kunne skyldes, at vi kalder runtime.getRuntime().freememory() funktionen som allokerer plads til resultatet fra kaldet og dermed står for det fald vi ser på displayet.

3. Konklusion
Generelt set lykkedes alle de opstillede test, og de fejl vi stødte på undervejs blev rettet.

Herudover lavede vi nogle observationer under testene, hvor vi kunne konstatere, at LEGO bilen bremsede engang imellem i omkring et sekund, hvor det ikke rigtig virkede som om den lavede noget.
Efter at have udført del 8, kunne vi se en sammenhæng mellem at antallet af fri hukommelse næsten altid var lav mens dette skete. Vores første tanke var derfor at dette kunne skyldes at Garbage Collectoren var i gang, og af en eller anden grund fik den ene af motorerne til at stoppe under sin afvikling.
For at komme nærmere en løsning, valgte vi at forsøge og udskifte den ene motor. Det resulterede i at fejlen forsvandt hvorved det kan konkluderes at den ene motor havde en defekt. Vi kunne samtidig observerer at den nye motor havde et væsentlig højere omdrejningstal. Altså er det muligt at den defekte motor kan have været overbelastet og derfor midlertidig slukkede når den blev hårdt belastet.

4. Referencer
http://lejos.sourceforge.net/index.php
http://lejos.sourceforge.net/nxt/nxj/tutorial/index.htm
http://lejos.sourceforge.net/nxt/nxj/tutorial/Preliminaries/GettingStartedWindows.htm
http://lejos.sourceforge.net/nxt/nxj/tutorial/Preliminaries/CompileAndRun.htm
http://lejos.sourceforge.net/nxt/nxj/tutorial/Preliminaries/UsingNetbeans.htm