torsdag den 17. december 2009

Projektaktivitet 3

Projektaktivitet 3



Dato: 17. december 2009
Varighed: 7 timer
Deltagere: Annette, Rasmus og Samuel



Mål

GyroSensorkoden er klar til at blive brugt i forbindelse med at robotten skal holdes oprejst, så der skal laves et projekt hvor der kan reguleres ud fra værdier fra GyroSensorkoden. Dette skal efterfølgende kombinereres med bluetoothkoden, hvor regulering og bluetooth hver bliver en selvstændig tråd. Arbejdet med at få robotten til at balancere påbegyndes muligvis.



Baggrundsinfo
PID er et lukket sløjfe reguleringssystem. PID controlleren beregner en fejlværdi mellem den målte værdi (procesvariablen) og en ønsket værdi (set point) og ud fra det prøver den at regulere. Se yderligere om PID regulering her: PID regulering.




Fremgangsmåde


Segway med gyrosensorkoden

Udgangspunktet for at få robotten til at balancere bliver klassen Segway fra øvelse 4 [3.1]. Segway er den klasse som håndterer selve PID reguleringen. Den blev brugt i forsøg på at få robotten til at balancere vha. lyssensorer, så den skrives om til at bruge GyroSensor klassen i stedet for.


Segway klassen arver fra Thread Klassen og i constructoren til Segway oprettes en instans af GyroSensor klassen. En anden metode i Segway er getBalancePos() som sørger for at kalibrere offset ved at kalde calibrateOffset() metoden på GyroSensor. Efterfølgende aflæses setPoint vinklen som er udgangspunkt for reguleringen af robotten. run() metoden indeholder koden til reguleringen, som vil være på baggrund af værdier fra GyroSensor klassens getAngle() metode.


Reguleringen vil blive beskrevet senere. Derudover består projektet af DataLogger klassen så vi har mulighed for at analysere opsamlet data under arbejdet med PID kontrollen. Testen udføres fra BalanceTest klassen.


Bluetoothdelen

SegWayPCGUI klassen, viser et grafisk interface på PC'en, hvor der kan skrives værdier ind for P, I og D, som kan sendes individuelt. Den opretter forbindelse til NXT enhedens BluetoothThread klasse (som skal være startet først). Værdierne der bliver sendt fra PC'en er 4 cifrede, så der laves en omregning i BluetoothThread klassen, der kan indstilles individuelt for P, I eller D, alt efter hvor store eller små tal der skal bruges.

Når der modtages en værdi i BluetoothThread, kalder den den passende set-metode i SegWay klassen, så værdierne kan bruges. Værdierne starter alle på 0, når enheden startes. Kraften til motoren i SegWay, er normaliseret mellem 55 og 100, hvilket vil sige at den bevæger sig selvom P, I og D er 0. Derfor sættes en if sætning ind, der sætter motor power til 0, hvis P er 0. Så begynder robotten først at køre, når den får en P værdi tilsendt.



Resultater


Segway med gyrosensorkoden

Det har ikke voldt problemer at implementere PID reguleringskoden fra øvelse 4 i en test med vores egen GyroSensor klasse og DataLogger klassen.



Bluetooth delen


Arbejdet med undersøgelserne af gyroskopet er foregået vha. USB kablet på en anden NXTenhed end den der er brugt til arbejdet med Bluetooth kommunikationen. Det viser sig nu at der er problemer med Bluetooth kommunikationen på NXT’en hvor gyroskopet er blevet undersøgt, så vi har besluttet at bruge den, hvor vi ved Bluetooth virker.

Her viser det sig dog at der sker noget interessant med driften, for den er her langt mindre selvom vi kun skifter NXT og ikke selve sensoren. En anden ting der også undrer os er at offset er ændret fra før 596 til nu ca. 591. Så vidt vi har kunnet forstå skyldes drift hardwaren i selve sensoren, men denne opdagelse tyder på at også hardwaren i NXT'en har indflydelse.


Vi har ikke tid til at undersøge dette nærmere, men vi har en formodning om at det kan være A/D konverteren eller måske batteriniveauet der spiller ind.

Den samlede kode med GyroSensor, regulering og Bluetooth kan ses i [3.2] Samlet kode.


Konklusion


Samlingen af koden er gået fint, så vi er nu klar til at finde værdier for PID reguleringen. Bluetooth kommunikationen er implementeret så vi kan sende værdier til robotten. Det gør det nemmere fordi vi så ikke skal ændre i koden, compile og downloade til robotten, hver gang vi ændrer en af P, I, D værdierne.


Vores oplevelse med at det har betydning hvilken NXT der bruges og ikke kun hvilken sensor der bruges undrer os stadigvæk, men vi har valgt at lade det ligge.


I næste projektaktivitet skal interfacet på PC'en bruges til at tune PID konstanterne.


Referencer
[3.1] Øvelse 4: Øvelse 4.
[3.2] Samlet kode: Endelig-Kode

onsdag den 16. december 2009

PID regulering

PID Algoritmen og Lukket-sløjfe-styring




Lukket-sløjfe-styring og feedback



Lukket-sløjfe-styring eller automatisk styring, er en kontrol teknik som er baseret på såkaldt negativ tilbagekobling ( feedback).

Et velkendt eksempel på ukontrolleret, positiv feedback findes hos elektronisk udstyr, der kan begynde at hyle. Det sker i højttalersystemet, hvis lyden fra højttaleren når mikrofonen, hvor den bliver forstærket af systemet og returnerer dertil med endnu større styrke. Ved et enkelt gennemløb af sløjfen er denne virkning ikke til at høre, men den bliver alvorlig, når signalet passerer gennem systemet igen og igen.

Lukket-sløjfe-styring består grundlæggende af 3 elementer, Controller, system (plant) og Sensor, som konstant prøver at give et ønsket system output ud fra en givet reference.



Figur 1

Sensoren måler system output (også kaldet procesvariablen) og fejlen (Measured error) beregnes ved at trække den målte værdi fra referencen (negativ feedback). Controlleren beregner så et nyt system output som sendes til systemet, som så reagerer på det og loopet begynder forfra.


PID regulering
I vores projekt bruger vi en PID (proportional–integral–derivative) regulerings algoritme til at styre vores lukkede sløjfe, dvs. som controller (se figur 1). PID regulering er en form for kontrolalgoritme der er meget udbredt inden for industrien og som benyttes lukket-sløjfe-styringer. PID-algoritmen er baseret på 3 parametre, proportional (Kp), integral (Ki) og differential (Kd).


Figur 2

PID algoritmen ser ud som vist på figur 2. I forhold til figur 1 svarer "input" til "system input" og "error" til "measured error".

fredag den 11. december 2009

Projektaktivitet 2

Projektaktivitet 2



Dato: 11. december 2009
Varighed: 7 timer
Deltagere: Annette, Rasmus og Samuel



Mål

Færdiggøre undersøgelser af gyroskopet og lave et grafisk program til PC'en, der kan sende parametre til NXT enheden løbende over Bluetooth.



Fremgangsmåde
GUI program til Bluetooth kommunikation.

Da problemerne med kommunikation mellem PC og NXT blev løst i sidste projektaktivitet, er det nu kun nødvendigt at bestemme formatet af kommunikationen og lave den grafiske brugergrænseflade.



Undersøgelse af gyroskop
Gyrosensor
Til undersøgelserne af gyroskopet laves et LeJOS NXJ projekt som indeholder tre klasser, en testklasse, en GyroSensor klasse og en DataLogger klasse. Testklassen varierer afhængigt af om vi ønsker at læse fx vinkelhastighed eller vinkel, DataLogger klassen er skrevet af Ole Caprani, og opretter en .txt fil, hvortil man kan skrive integers.



GyroSensor klassen
Lejos har en GyroSensor klasse under lejos.nxt.addon som i constructoren tilknytter en medsendt port til sensoren, og i hvilken mode den skal fungere. Når sensoren holdes fast i en stilling returnerer den værdier der i vores tilfælde ligger på omkring 596, det er sensorens offset og kan sættes i GyroSensor klassen.
readValue() metoden i GyroSensor klassen læser den rå værdi fra porten (A/D converteren) med ADSensorport.readRawValue() metoden og som tidligere beskrevet returneres en værdi fra sensoren der svarer til grader/sekund. I readValue() metoden fratrækkes offset værdien så vinklen har nul som udgangspunkt.



getAngle metoden
Det er dog ikke vinkelhastigheden vi har brug for til vores projekt hvor robotten selv skal kunne balancere. Her har vi brug for en angivelse af position i stedet for. Derfor må vi tilføje en metode getAngle() der returnerer vinklen beregnet ud fra vinkelhastigheden. Beregningen udføres som vist i Figur 2.1.

Figur 2.1



Implementationen er som vist i Figur 2.2. Det er nødvendigt at kende tiden, så derfor kaldes metoden System.currentTimeMillis() som returnerer tiden i millisekunder siden NXT'en blev startet. Derefter beregnes dt som er den nye tid minus den gamle og efterfølgende beregnes den nuværende vinkel ud fra den gamle vinkel, sensorværdien og dt.

Figur 2.2



Nu er vi klar til at lave nogle forskellige undersøgelser, som først vil dreje sig om at finde ud af hvordan sensoren måler vinklen, og efterfølgende vil det dreje sig om drift, som vi ved er et problem med sensoren.


Undersøgelse 1: Vinkel

Den første undersøgelse skal vise om sensoren fungerer, som beskrevet af HiTechnic og om den tilføjede metode getAngle() returnerer vinklen som den skal. Det gælder altså her om at få en fornemmelse af hvordan sensoren fungerer. Offset angives i koden til at være 596.


Undersøgelse 2: Vinkelhastighed
Vinkelhastigheden undersøges, ved at bruge GyroSensor klassen med offset sat til 0. Sensoren fastgøres i en opstilling som vist på Figur 2.3 så den ikke bevæger sig. Værdierne fra sensoren burde så være stabile, men vil sandsynligvis stå at skifte lidt (drift).

Figur 2.3


Værdierne fra sensoren opsamles i en datafil der efterfølgende overføres til en PC og undersøges i Mathcad.


Undersøgelse 3: Vinkel
For at undersøge vinklen sættes offset til 596 da det er ca. der NXT’ens offset ligger. Det er den samme opstilling der bruges for at holde sensoren stille. Her bruges vores egen getAngle() metode til at returnere vinklen og igen burde værdierne være stabile fordi sensoren ikke bevæger sig. Værdierne opsamles også her i en datafil der undersøges i Mathcad.


Undersøgelse 4: Kompensation for drift
Da det ikke er et dyrt gyroskop må vi forvente at der kan forekomme drift. Det kommer til udtryk ved at der returneres en vinkelhastighed fra A/D konverteren selvom sensoren ikke bevæger sig. Offset ændrer sig altså en smule, som vi også så i undersøgelse 2. For at finde et nøjagtigt offset har vi derfor lavet en kalibreringsmetode, i klassen gyroSensor, som kaldes for at kalibrere offset. Metoden kalder readRawValue() metoden et antal gange og tager et gennemsnit af det antal samples den tager. For at få et mere nøjagtigt resultat bruger vi double-præcision.


Beregningen af offsettet sker ved at vi tager 50000 samples og tager gennemsnittet af disse samples. Dette gøres reelt to gange i træk.



Til at finde ud af om kompensationen har den ønskede virkning bruges den samme opstilling som i de to foregående undersøgelser. Ved hjælp af getAngle() metoden hentes værdier for vinklen som skrives til en datafil. Forventningen er så at driften vil være stærkt reduceret i forhold til de tidligere målinger.



Resultater


GUI program til Bluetooth kommunikation.
Overførsel af data:
Kommunikationen mellem PC og bluetooth enhed, foregår ved at der bliver sendt en stream af data. Der kan sendes bytes, Integers, Chars og andre typer, men der kan kun læses én ad gangen hos modtageren. Samtidig kan der kun sendes via én stream ad gangen, så alt data skal overføres via denne ene stream.
Da der skal sendes 3 forskellige parametre på vilkårlige tidspunkter, skal det besluttes hvordan disse data skal sendes og opfattes. Værdierne der skal modtages, skal i sidste ende være doubles, altså kommatal, som NXT'en bruger som parametre i sin PID kontrol. Der kan ikke sendes doubles over streamen, da der kun kan læses "enkelte tegn" i den anden ende.

For at kunne kende forskel på de forskellige parametre der sendes, sendes data som chars. Hvis der skal sendes en P parameter, sendes der et lille p, efterfulgt af de tal der er parametren: "p001". Dette betyder at der sendes 4 chars, for at få et tal på 3 tegn.



For at forstå de tegn der sendes over streamen, skal modtageren laves rigtigt. Da der i et tidligere SegWay projekt blev brugt PID regulering, med double værdier, bruges denne type også her. I det tidligere projekt, havde parametrene 2 decimaler, hvilket er grunden til at der i dette program sendes 3 chars.
Når Nxt programmet modtager de 4 chars fra PC programmet, tjekker den det første tegn og ser om det er et p, i eller d. Hvis ikke det er en af de tre, prøver den det næste tegn.
Hvis det er et af de tre tegn, sætter den de næste 3 chars i streamen, sammen til en string. Denne string bliver omfortolket til en integer. Denne integer bliver så lavet om til en double, og kommaet rykkes 2 pladser til venstre. For eksempel bliver strengen 001 til tallet 1 og strengen 101 til tallet 101. Derefter ganges dette tal med 0.01, så det i stedet bliver til et kommatal som følgende eksempler: (String - Int - Double)
(001 - 1 - 0.01)
, (101 - 101 - 1.01) og (021 - 21- 0.21).
Fordi der tjekkes på om det første tegn er p, i eller d, gemmes dette tal i den respektive variabel, som programmet så bruger til PID regulering.




Den grafiske brugergrænseflade:
Interfacet der skal bruges til at sende PID parametrene til NXT'en er ikke særligt kompleks. Der er 3 knapper, med tilsværende tekstfelter hvori tallene der skal sendes, skrives ind. Der laves også et større tekstområde, hvor der udskrives feedback på, om der sker fejl og om parametrene faktisk bliver sendt.



Den grafiske del er lavet ud fra et simpelt eksempel om JButtons i java, som er tilpasset til ovenstående formål. Derefter bliver der oprettet en instans af det program der står for kommunikationen med bluetooth enheden, "BTconnector" (som er indeholdt i samme fil). Hver gang der trykkes på en knap, tager programmet strengen i det tilhørende tekstfelt (og sætter hhv. p, i eller d foran) og sender videre til BTconnectoren. Derefter sendes strengen over den oprettede bluetooth forbindelse, som BTconnector sørger for at oprette.



Undersøgelse af gyroskop
Undersøgelse 1: Vinkel
Når sensoren holdes i en fast lodret position returneres en vinkel på 0 grader og når den vippes med uret returneres en positiv værdi for vinklen og mod uret en negativ værdi for vinklen. Selve udlæsningerne af vinklen ser også ud til at passe godt med det forventede, hvis udgangspunktet er at sensoren er i lodret position og den bliver roteret med uret til vandret position (efter øjemål) udlæses en værdi på 45 grader. Hvis man roterer videre med uret til lodret på hovedet udlæses 90 grader. Tilsvarende ser udlæsningerne ud til at passe hvis den roteres mod uret


Undersøgelse 2: Vinkelhastighed
Der er opsamlet værdier for vinkelhastigheden for sensoren når den er stationær og værdierne er plottet ind i grafer der kan ses i [2.1]. Der er lavet målinger over tre gange og de viser alle at vinkelhastigheden varierer mellem 694 og 696 og ved enkelte målinger helt ned til 593 og op til 598. Målingerne viser altså at der returneres en vinkelhastighed selvom sensoren er fikseret og derfor ikke bevæger sig. Testkoden kan ses under [2.2] VelocityDriftTest projektet.


Undersøgelse 3: Vinkel
Der er opsamlet værdier for vinklen af sensoren når sensoren er stationær og værdierne er plottet ind i grafer i [2.1]. Også her er der lavet målinger tre gange og de viser at ved et offset på 296, sker driften i negativ retning. Det er varierende hvor hurtigt det går, men det er en ret voldsom drift. Testkoden kan ses under [2.3] AngleDriftTest projektet.



Undersøgelse 4: Kompensation for drift
Der er lavet tre målinger på vinklen når der kompenseres for drift, en grafisk fremstilling kan ses i Mathcad dokumentet i [2.1]. Med offset kalibreret til 596.032426458401 fås en negativ drift, på to grader i løbet af lidt mere end 20000 samples hvilket er en stor forbedring hvis man sammenligner med målingerne hvor der ikke kompenseres.
Med offset kalibreret til 595.99829648078 fås en positiv drift på to grader i løbet af lidt mindre end 20000 samples. Den sidste kalibrering er på 595.976274831896 og giver en positiv drift på seks grader i løbet af lidt mindre end 20000 samples, men det er også en noget lavere offset værdi så det er forventet. Det rigtige offset må ligge mellem 596.032426458401 og 595.99829648078, da det ene giver negativ drift og det andet giver positiv drift. Testkoden kan ses under [2.4] DriftCompensation projektet.




Konklusion

Undersøgelserne af gyroskopet er afsluttet. Der er ret voldsom drift, men der kan kompenseres for det i en sådan grad, at vi håber at det ikke bliver et problem i det videre arbejde.


Vi synes vi har et godt udgangspunkt til at få robotten til at balancere nu hvor vi kan beregne en vinkel ud fra den målte vinkelhastighed fra sensoren og vi kan sende værdier vha. Bluetooth mellem en PC og NXT'en.


I projektaktivitet 3 skal GyroSensor klassen og bluetooth klassen kombineres i et program og vi begynder muligvis at kigge på PID reguleringen.



Referencer
Java eksempel GUI er bygget over:
ButtonDemo.java
BTconnector uden GUI:
BTconnector.java
Samlet GUI program: SegWayPcGUI.java (Indeholder også BTconnector)
BT klient program på Nxt:
BluetoothUnit.java
[2.1] Drift Test: Drift.pdf
[2.2] VelocityDrift projektet: VelocityDrift.rar
[2.3] AngleDrift projektet: AngleDrift.rar
[2.4] DriftCompensation projektet: DriftCompensation.rar

torsdag den 3. december 2009

Projektaktivitet 1

Projektaktivitet 1




Dato: 4. december 2009
Varighed: 7 timer
Deltagere: Annette, Rasmus og Samuel


Mål
At undersøge gyroskopet og få bluetooth kommunikation til at fungere mellem PC og NXT.


Fremgangsmåde

Bluetooth kommunikationen
En af de første ting der skulle laves i projektet, var at få kommunikation mellem PC og NXT til at virke. Det skal bruges i flere sammenhænge, blandt andet til at opdatere parametre til PID regulering løbende. Derfor blev der afprøvet programmer fra tidligere studerendes projekter.

Undersøgelse af gyroskop
Med baggrund i materialet fra NXT om gyrosensoren laves undersøgelser af hvordan den fungerer. Dette indebærer blandt andet:

• Hvilke værdier fås fra porten?
• Hvor stor er nøjagtigheden?
• Drift.
• Hvordan skal softwaren tilpasses?

Resultater

Bluetooth kommunikationen
Problemer

Compile: Det første problem var at finde ud af hvordan programmerne skulle compiles. Modtagerprogrammet der skulle kører på NXT’en gav sig selv, da det bare skulle køre som normalt. Programmet på PC’en var der dog tvivl om.
Efter at have søgt på nettet og set hvad andre tidligere grupper havde gjort, var konklusionen at den skulle compiles som et almindelig java program, dog med en classpath til pccomm.jar filen i lejos mappen.
Dette virkede dog ikke, da compileren stadigvæk ikke kunne forstå syntaksen for bluetooth kommunikation i javafilen. Flere søgninger på nettet viste andre jar filer der skulle med, og i stedet for at skrive dem hver gang noget skulle compiles, blev de skrevet ind i miljøvariablerne i windows:

CLASSPATH
C:\Program Files\leJOS NXJ\pccomms\lib\pccomm.jar;C:\Program Files\leJOS NXJ\pccomms\3rdparty\libbluecove.jar; bluecove-gpl.jar

Dette gjorde at filen blev compilet uden fejl, men det viste sig senere at det ikke var en permanent løsning. (Se Kørsel på PC nedenfor).

Kørsel på PC: Efter det var lykkedes at få compilet filerne rigtigt, var næste problem at få kørt PC programmet. Da PC filen skulle compiles som et normal java program (Compile delen), var det også logisk at den skulle køres på denne måde. Problemet var dog, at der kom en ”noClassDefFoundError”, der sagde at filen ikke blev fundet.

C:\Program Files\leJOS NXJ\pcsamples\BTSend>java BTSend
Exception in thread "main" java.lang.NoClassDefFoundError: BTSend
Caused by: java.lang.ClassNotFoundException: BTSend
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
Could not find the main class: BTSend. Program will exit.

Dette blev løst ved at tilføje stien til den mappe hvor filen lå, til classpathen:
java -classpath "C:\Program Files\leJOS NXJ\pcsamples\BTSend" BTSend

Dette løste problemet, og programmet udskrev den første linje som den skulle, inden den gik i gang med Bluetooth forbindelsen. Her kom den næste fejl dog:

C:\Program Files\leJOS NXJ\pcsamples\BTSend>java -classpath "C:\Program Files\le
JOS NXJ\pcsamples\BTSend" BTSend
Exception in thread "main" java.lang.NoClassDefFoundError: lejos/pc/comm/NXTConnector at BTSend.main(BTSend.java:27)
Caused by: java.lang.ClassNotFoundException: lejos.pc.comm.NXTConnector
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
... 1 more

Dette blev efterfulgt af en lang serie af søgninger på nettet, som ikke umiddelbart gav resultat. Dog var der nogle der benyttede kommandoerne nxjpcc til at compile de programmer der skulle bruges på PC’en med, og nxjpc til at køre dem. Hvis man bruger windows, kommer disse kommandoer fra to .bat filer som ligger i leJOS NXJ\bin. Disse filer følger ikke med i lejos 0.8, som vi bruger eller tidligere versioner, men i 8.5. Disse filer blev hentet ind og afprøvet.
Nxjpcc virkede fint og compilede, men der kom stadig fejl efter nxjpc. Da disse bat filer selv opsætter classpath og andet der skal bruges, var det ikke længere nødvendigt selv at have defineret classpath. Den classpath der var blevet sat under computerens miljøvariabler, blev slettet, da der var mistanke om at den var skyld i fejlen. Ganske rigtigt. Da miljøvariablen CLASSPATH blev slettet, og kommandoen nxjpc BTSend blev kørt, kom følgende output:

C:\Program Files\leJOS NXJ\pcsamples\BTSend>nxjpc BTSend
BlueCove version 2.1.0 on winsock
Failed to connect to any NXT *
BlueCove stack shutdown completed

* Det skal bemærkes, at der ikke var nogle enheder at forbinde til, så det var helt rigtigt at den ikke kunne få forbindelse.

Konklusion - ”Det gode råd”
Hvis andre windowsbrugere har problemer med at compile og køre Bluetooth programmer til kommunikation mellem PC og NXT, er der en simpel løsning til Lejos 0.8 og tidligere:
Lad være med selv at sætte classpaths!

Hvis der benyttes Lejos 8.0 eller ældre, mangler der kun 2 filer, nxjpcc.bat og nxjc.bat, som skal ligge under …\leJOS NXJ\bin.
Når disse filer er lagt ind, lukkes alle cmd vinduer der skal benytte filerne (ellers er det ikke sikkert at de finder filerne) og de åbnes igen.
Derefter bruges kommandoen nxjpcc til at compile PC filerne, og nxjpc til at køre dem.

Undersøgelse af gyrosensoren

Der skal udføres videre undersøgelser af gyrosensoren, så det hele vil blive beskrevet samlet i projektaktivitet 2.

Konklusion
Efter stort besvær kom bluetooth kommunikationen mellem PC og NXT til at virke. I næste projektaktivitet skal det gøres færdigt med et interface og der skal laves en protokol til at sende dataværdierne. De første undersøgelser af gyrosensoren blev også påbegyndt og vil fortsætte i projektaktivitet 2.

Referencer
Download af nxjpcc og nxjpc filerne: Nxj-pc-compile.rar
Kildekode til Bluetooth Sample fra Lejos: BTSend
Tidligere studerendes projekt: Marvin

Øvelse 11

End course project

Dato: 3. december 2009
Varighed: 4 timer
Deltagere: Annette, Rasmus og Samuel


Mål
At beskrive forskellige end course projects vi synes kunne være interessante og vælge det vi har lyst til at lave.

Plan
Vi vil starte med at kigge på listen over forslag til projekter og tilføje vores egne forslag. Efterfølgende vælger vi de mest interessante ud som vi diskuterer og overvejer forskellige løsningsmodeller til i gruppen. Når vi har nogle gode udgangspunkter vil vi tage en snak med Ole Caprani og derefter vælge ud fra den feed back vi får.


Projektoplæg/valg

Segway på Alishan Train Track

Formål:
Formålet med projektet er at bygge en robot der balancerer på to hjul. Den skal kunne køre op og ned ad Alishan train track banen som vi brugte i lektion 6 til robot race. Dette indebærer først og fremmest at få den til balancere – både når den står på et vandret underlag, men også når den skal køre op og ned ad bakke. Desuden skal vælges en metode for at få den til at blive på banen og den skal kunne dreje og vende.

Problemstillinger:
- At få robotten til at balancere - både på vandret underlag og på skråt underlag. Her er der mulighed for at bruge fx gyroskop eller tiltmåler.
- Navigation på banen. Her er der mulighed for fx at bruge lyssensorer, kompas eller tachocounter.

Hardware:
- NXT
- 2 motorer
- Gyroskop
- Tiltmåler
- Lyssensorer
- Kompas
- Tachocounter (i motor)

First LEGO league

Formål:
Formålet med dette projekt er at gennemføre First LEGO Legue banen for 2009 med 400 points hvilket svare til maksimum point. Desuden er det et mål at undgå en sekventiel tilgang til problemet.

Problemstillinger:
- Det er en svær bane med mange forskellige forhindringer. Dette gør det svært hvis ikke man laver en sekventiel styring af robotten.

Hardware:
- NXT
- 2 motorer
- Kompas
- Ultralydssensor

Cave Res-Q

Formål:
Fere robotter navigerer igennem en ”hule”, labyrint eller bane. De skal kortlægge omgivelserne/ruten og på samme tid lokalisere personer og sende informationerne tilbage til en PC, så det bliver plottet ind på et kort. De skal snakke sammen så de dækker så stort et område som muligt, men stadigvæk ikke bliver væk fra hinanden.

Problemstillinger:
- Kortlægning af område.
- Identifikationen af en person.
- Kommunikation.
- Undgå at robotterne klumper sig sammen, men samtidig operere som en flok der kan dække et større område. Dette skal gøres ved kommunikation robotterne imellem.

Hardware:
- NXT
- 2 motorer
- Tachocounter (i motor)
- Kompas
- Bluetooth kommunikation
- Ultralydssensor

Valg
Det er tre gode projekter hver med sine spændende elementer. Vi har valgt at lave projektet med en Segway på Alishan train track banen fordi vi gerne ville vende tilbage til en Segway og det giver nogle interessante udfordringer at få den til at køre på banen fordi det kræver at den også kan holde sig oprejst på skrå overflader og det kræver at den ikke bare kan stå stille og holde sig oprejst, men at den kan navigere rundt.

Yderligere om Segway på Alishan train track
Vi har taget et valg allerede nu med hensyn til hvordan robotten skal balancere. I første omgang vil vi undersøge gyroskopet for det skulle være nok til at få robotten til at balancere og vi har det til rådighed.
For at få et overblik over hvad hvilke opgaver der er i dette projekt ses nedenfor en liste som skal danne udgangspunkt for arbejdsforløbet. Efterhånden som vi bliver klogere på hvad der kræves vil listen blive opdateret.

- Bygge robot.
- Undersøge hvordan gyroskopet virker.
- Undersøge og vælge reguleringsteknik.
- Lave et interface fra PC så det er nemt at ændre parametre i reguleringen.
- Få robotten til at balancere.
- Få robotten til køre frem mens den balancerer.
- Få robotten til at dreje mens den balancerer.
- Få robotten til at balancere mens den kører op ad bakke.
- Få robotten til at balancere mens den kører ned ad bakke.
- Undersøge hvilke muligheder der er for at navigere på banen (streg, tachocounter, kompas) og vælge.


Konklusion
Vi har valgt projektet Segway på Alishan train track fordi det bliver et spændende projekt med nogle gode problemstillinger. De to alternative projekter er beskrevet og det valgte projekt er beskrevet i yderligere detaljer så vi har et første overblik over arbejdsopgaverne og ved hvad vi skal gå i gang med først. Den første projektaktivitet skal være at bygge robotten og undersøge gyroskopet.

tirsdag den 24. november 2009

Øvelse 10

Dato: 20. november 2009
Øvelsens varighed: 5 timer
Gruppemedlemmer: Annette, Samuel og Rasmus


Mål
I denne øvelse undersøges hvordan en behavior based arkitektur er blevet implementeret i subsumption API’en i leJOS NXJ. Specielt vil vi kigge på lejos.subsumption.Behavior interfacet og lejos.subsumption.Arbitrator klassen.

Baggrundsinfo
When most people start programming a robot, they think of the program flow as a series of if-thens, which is remeniscent of structured programming (Figur 1). This type of programming is very easy to get started in and hardly requires any thought or design beforehand. A programmer can just sit at the computer and start typing. The problem is, the code ends up as spaghetti code; all tangled up and difficult to expand. The behavior control model, in contrast, requires a little more planning before coding begins, but the payoff is that each behavior is nicely encapsulated within an easy to understand structure. This will theoretically make your code easier to understand by other programmers familiar with the behavior control model, but more importantly it becomes very easy to add or remove specific behaviors from the overall structure, without negative repercussions to the rest of the code. Let's examine how to do this in leJOS NXJ.
(Kilde: http://lejos.sourceforge.net/nxt/nxj/tutorial/Behaviors/BehaviorProgramming.htm)








Figur 1



Fremgangsmåde
BumperCar
1. Der monteres en touch sensor og ultralydssensor på bilen.

2. Der laves et nyt projekt ud fra BumperCar klassen.

3. Først undersøges hvad der sker når vi selv trykker touch sensoren ind og bliver ved med at holde den inde.

4. Nu skal koden til arbitratoren analyseres.

5. Der skal implementeres en tredje opførsel, Exit. Den skal reagere på tryk på ESCAPE knappen og gå ud af programmet. Den skal implementeres som den højeste prioritet og vi ser hvad der sker når ESCAPE knappen aktiveres.

6. Der laves en ny tråd som har til formål i et givent interval at aflæse den ultrasoniske sensor for at få en afstand. Værdien gemmes i en variabel som er tilgængelig i DetectWall.

7. DetectWall klassen ændres en smule så resultatet af at bilen kommer for tæt på en forhindring resulterer i at bilen først bakker i et sekund og efterfølgende drejer.

8. Undvigemanøvren skal kunne afbrydes og starte forfra igen hvis der detekteres en forhindring imens.



Resultater
Hele den færdige kode til alle øvelser kan ses under projektet Bumper.
1. Se billede af bilen i Figur 2.



Figur 2



2. Vi fandt BumperCar programmet i mappen samples/BumperCar som findes i LEJOS installationsbiblioteket.

3. Når touch sensoren trykkes ind sættes højre motor til at dreje 180 grader bagud og venstre motor sættes til at dreje 360 grader bagud. Det vil resultere i at den bakker mod højre for at undvige forhindringen.


4. I main oprettes to Behaviour instanser, b1 som er DriveForward og b2 som er DetectWall. De tilføjes til et array hvor den adfærd der ønskes lavest prioriteret står først i arrayet. DriveForward får lavest prioritet og DetectWall får næste prioritet. Efterfølgende oprettes en instans af Arbitrator med Behaviour arrayet og i Arbitratorens konstruktor oprettes en instans af Monitor klassen.

Arbitratoren har en start() metode, men den er ikke en tråd!! I start() metoden kaldes monitors start() metode og det er en tråd. Monitoren overvåger hvilken adfærd der skal have kontrollen. Det gøres ved at den går listen med behaviors igennem startende ved det højeste index, det vil sige adfærden med højeste prioritet. takeControl() kaldes på adfærden, her er det først DetectWall, som tester om touch sensoren er trykket ind eller ultralydssensoren er tættere end 25 cm fra en forhindring. Hvis der returneres false gås videre til index-1 hvilket betyder at DriveForward’s takeControl() kaldes og da den er i bunden af subsumption arkitekturen vil den altid gerne have kontrol og returnerer true.
Til sidst testes på om det er nødvendigt at undertrykke andre adfærd, hvilket det ikke er for DriveForward da det er den nederste, men hvis takeControl() på DetectWall havde returneret true skulle DriveForward adfærden undetrykkes.

5. Efter at have, implementeret exit() klassen, og lavet den til den Behavior med højst prioritet, afprøves den på robotten.
Første test, er at trykke på exit knappen, mens DriveForward opførslen er i gang. Programmet går lukket med det samme at exit knappen bliver trykket på, så der er ingen forsinkelse her. Næste test er at trykke exit, mens DetectWall opførslen er i gang. Det viser sig at der er forskel på hvornår man trykker. Hvis der trykkes mens hjulene drejer, sker der ofte ingenting. Hvis trykket lander lige i det hjulene stopper, når robotten de fleste gange at stoppe.

Efter at have rettet Sound.pause til 2000, afprøves exit metoden igen. Når touch sensoren trykkes ind første gang, går der et langt stykke tid før robotten begynder at bakke, som den skal i DetectWall. Dette skyldes at resten af programmet venter, mens Sound.pause(2000) bliver udført. Dette gør også at den ikke opdager et suppress kald mens den venter. Derfor er det nødvendigt at holde exit knappen inde, indtil den kommer til et sted i programmer, hvor dette bliver opdaget.
Hjulenes handlinger ser også ud til at blokere for andre handlinger, da der i versionen med de 20 ms pause, heller ikke blev opfattet et knaptryk på exit mens hjulene kørte. De 20 ms pause foregår inden hjulene bliver sat i gang, så det kan ikke være er overlap fra pausen.

6. Her brugte vi langt tid fordi vi havde problemer med at få implementeret tråden rigtigt. Den meldte ikke fejl under kompilering, men den ville ikke downloade programmet så det var meget vanskeligt at fejlfinde. Helt præcist hvad fejlen var lykkedes det ikke at finde ud af, for vi måtte prøve forfra med at implementere sensor klassen der nedarvede fra Thread.

Med den nye tråd implementeret, opfører robotten sig umiddelbart som den gjorde inden. Det der er forskellen på programmet som det var før, og som det er nu med tråden, er at programmet ikke bliver blokeret imens ultralyds sensoren læser.
Før var der en 20 millisekund pause, for at ultralydssensoren kunne nå at sende sin impuls ud, og få den ind igen. Denne pause gjorde at programmet ikke kunne modtage andet input i det tidsrum. Nu er alt håndtering af ultralyds sensoren lagt over i en tråd for sig, så hovedprogrammet kan køre frit imens.
Tidligere blev sleep kaldet sat op fra 20 til 2000 millisekunder, for at teste hvad der skete. Når touch sensoren blev aktiveret, eller afstanden var for lav, kunne man se, var at robotten først begyndt at bakke, efter de 2000 sekunder var gået. Samtidig kunne den ikke slukkes i tidsrummet.
Dette blev også afprøvet med den nye tråd. Her begyndte robotten med det samme at bakke, når Touch sensoren blev trykket på, men ikke ved ultralyds sensoren. Ved afstandsmålingen gik der omkring to sekunder før den reagerede, hvilket selvfølgelig skyldes at tråden venter i 2000 millisekunder mellem at den læser afstanden. Dog var det muligt at slukke robotten i disse to sekunders pause.
Sound.pause() er ikke det eneste der blokerer for slukning af robotten når den bakker. Når den bakker, sættes begge motoere til at dreje, men den første har "immidiate return" sat til True, hvilket den anden ikke har. Fordi det sidste motor kald ikke har immidiate return, blokere den stadig for resten af programmet til den er færdig.

7. Bilen sættes til først at bakke i et sekund inden den drejer ved at bruge Motors backward() metode og derefter kalde Thread.sleep() i 1000ms. Det betyder dog at det ikke umiddelbart er muligt at afbryde bagud kørslen hvis en forhindring detekteres imens så det er ikke den smarteste løsning. Vi har dog ikke tid til at gå mere ind i problemstilingen.

8. Som nævnt bruger vi Thread.sleep() metoden til at få bilen til at bakke i et sekund og derfor kan vi ikke bare afbryde og starte forfra midt i det hele.

Konklusion
Vi har undersøgt hvordan behavior og arbitrator fungerer. Der har specielt været fokus på at der ved specielle omstændigheder kan blokeres for en adfærd. Vi havde problemer med at implementere sensorlæsningen som en tråd, og det brugte vi lang tid på.

Referencer
Bumper, videreudvikling af BumperCar (Brian Bagnall and Lawrie Griffiths, modified by Roger Glassey)


torsdag den 19. november 2009

Øvelse 9


Dato: 13. november 2009


Øvelsens varighed: 3 timer


Gruppemedlemmer: Annette, Samuel og Rasmus


Mål

I denne øvelse skal vi undersøge tacho counteren af NXT motoren for at holde styr på positionen og retningen af en LEGO bil. Bilen skal være differential styret, dvs. de to motorer bruges uafhængigt til at drive og styre bilen. Desuden laves en undersøgelse af et kompas monteret på bilen. Hvornår er præcisionen størst.


Baggrundsinfo

Bilen i denne øvelse skal kunne dreje rundt på stedet. Dette opnås ved at sætte forward power på det ene hjul og backward power på det andet hjul.

Fremgangsmåde

Opgave 1: Præcision ved kørsel.
Den første øvelse handler om hvor præcist bilen kan vende tilbage til det samme sted og dermed hvor præcis tacho counteren er.


1. Montering
For at tilpasse bilen til denne øvelse monteres en tusch bag på, så den kan tegne på et white board ved undersøgelserne.


2. Navigation
I den første undersøgelse sætter vi bilen til at køre med default hastighed som er bestemt til at være 17cm/s (fundet ved udlæsning på display). Tacho counteren undersøges ved at programmere bilen til at køre 40 cm fremad (travel(40)) og efterfølgende kan vi se hvor langt bilen har kørt ved at måle længden af den tegnede streg.


3. Navigation
I denne undersøgelse sættes bilen til at køre i en lige linje fremad i 40 cm og efterfølgende dreje 180 grader om sig selv og igen køre 40cm. Dermed burde bilen ende samme sted som den startede.


4. Navigation
Nu sættes bilen til at køre i en firkant. Dette gøres ved at programmere den til at køre skiftevis 40 cm frem og drejer 90 grader til venstre indtil den skulle være tilbage ved udgangspunktet. Koden til disse undersøgelser kan ses i http://www.daimi.au.dk/~u071252/DL/Practice9/TravelTest.java.




Opgave 2: Undvige objekter.

  1. Robotten tilpasses ved at fjerne unødvendige tilbygninger, og sætte øge afstanden mellem hjulene. Dette gør at den har nemmere ved at bevæge sig. Ultralyds sensoren monteres, så robotten kan opdage de objekter den skal undgå.


  1. Øvelsen går ud på at få robotten til at undgå objekter og navigere via TachoPilot klassen. Robotten skal derfor kører tilfældigt rundt, og undgå objekter der kommer i vejen for den. Til dette bruger vi subsumtion arkitekturen fra øvelse 8.


Opgave 3: Navigation med kompas.


  1. Der monteres et kompas på robotten.


  2. Robotten skal navigere med kompasset, så præcisionen kan observeres. Til at starte med bruges TravelTest klassen fra opgave 1. Den eneste forskel er at der benyttes CompasPilot i stedet for TachoPilot.


  3. Da der i første forsøg ikke var indstillet på hjul størrelse og afstand, kalibreres dette. Derefter afprøves robottens præcision, i forhold til robotten uden kompas.


  4. Magnetisk Påvirkning
    For at se hvordan magnetisme påvirker kompasset, laves nogle ekstra tests med magnet og den kompas styrede robot.




Resultater


Opgave 1:



  1. På figur 1 herunder ses bilen med tuschen monteret.


Figur 1


  1. Tacho counteren er ret præcis. Når bilen sættes til at køre 40 cm kører den 40cm, se figur 2.


Figur 2

Under skrivning af den første testkode fandt vi ud af at klasserne der er vist i eksemplerne ikke virker eller er deprecated så vi endte med i stedet for at bruge TachoPilot klassen.

Der opstod også en smule forvirring angående F’et når man opretter en ny TachoPilot: Pilot pilot = new TachoPilot(5.6F, 20.0F, Motor.C, Motor.B, true);. Først troede vi at det betød at det var målesystemet hvor man bruger feet, så vi skulle finde ud af hvordan man angiver målene i cm. Vi fandt ud af at F betyder float, og at der ikke skulle skrives enheder på. Så længe man sørger for at bruge de samme enheder til alt hvad man angiver er det i stedet for et forhold som bliver beregnet.


3. Den er ikke så præcis når den skal dreje. Det ses på figur 3. Strækningen på de 40 cm passer igen som vi så under 2., men det går galt når den skal dreje de 180 grader om sig selv. Den kører ca. 20 grader for langt og ender altså et stykke fra udgangspunktet når den vender tilbage.

Figur 3

Problemerne skyldes blandt andet at tavlen er meget glat. Som en mulig løsning sættes et sæt ekstra hjul på og det hjalp lidt. Den skrider ikke så meget på underlaget når den skal dreje nu. Noget andet der har indflydelse er hvor hjulene er placeret, selvom man angiver afstanden mellem hjulene i koden, kan man ved at ændre på hjulenes placering få mere eller mindre fejl når bilen drejer om sig selv. Blandt andet oplevede vi at vi kunne få mindre fejl ved ikke at angive den korrekte afstand mellem hjulene.

4. Når bilen kører i en firkant spiller problemerne med underlaget selvfølgelig også ind. Derfor bliver det heller ikke en særlig lige firkant og bilen stopper et helt forkert sted i forhold til udgangspunktet, men her summeres fejlen også op da firkanten kræver at bilen drejer 90 grader tre gange, se figur 3. Dette problem med drift beskriver Brian Bagnall også.


Bare for at prøve det, satte vi bilen på gulvet uden tuschen for at se hvordan den så klarede firkanten. Det så meget bedre ud så den største fejlkilde kan altså tilskrives underlaget.

Opgave 2:




  1. På billedet herunder ses robotten med ultralyds sensoren. Desuden har vi også monteret compass sensoren, som først bruges i den 3. opgave.


Figur 4



  1. Opgaven virker umiddelbart nem, men Pilot klassen har en anderledes opførsel end de metoder der tidligere er brugt. Når robotten er sat til at udføre en handling via Pilot klassen, kan den ikke umiddelbart sættes til at gøre andet. Dette løste
    For at indføre subsumption anvendtes SoundCar programmet fra en tidligere øvelse. Koden blev passet til, så det ikke var Car der styrede robottens bevægelser, men TachoPilot. RandomDrive klassen blev også rettet til, så den brugte de rigtige metoder.

  1. Steer() i stedet for Turn()
    Et at de store problemer, var turn() metoden i TachoPilot. Denne virkede i programmet til første del af øvelsen, men i dette program var den et problem. Når metoden blev kaldt med det antal grader den skulle dreje rundt om sig selv, begyndte den i stedet bare at køre ligeud. Det var ikke muligt at finde årsagen til at metoden ikke virkede, så i stedet anvendes Steer() metoden fra TachoPilot. Denne virkede efter hensigten.

  2. Avoid Objects
    AvoidFront klassen fra SoundCar projektet anvendes til at få robotten til at undvige objekter. Denne fungerer ligesom i SoundCar, dog med TachoPilot metoder i stedet for Car klassens metoder.


Opgave 3:


  1. På filmen ses robotten kører i en firkant vha. kompas sensoren.


  2. Det første forsøg var helt uden justering af hjul afstand eller diameter. Alligevel blev robotten afprøvet på et vandret whiteboard, med en tush montere på robotten. Robotten var sat til at kører i en firkant, og det var overraskende så præcist det blev.


  3. Præcisionen var ikke betydeligt anderledes med lidt ændrede værdier for hjul diameter og afstand. Dette kan skyldes at robotten selv korrigerer, alt efter graderne kompasset viser, og ikke hvor meget Tacho tælleren viser. Hvis underlaget er glat, som det er på et whiteboard, vil hjulene dreje rundt uden at komme så langt som de burde.

    En af de muligt kilder til afvigelse for kompas navigationen, kan være at den giver for meget fart når den drejer, og derfor bliver skubbet lidt længere væk end den regner med. Det set i hvert fald sådan ud, når den kører.


  4. Det er muligt at strømkabler i kabelbakkerne kunne påvirke kompas sensoren en smule. vi prøvede at flytte whiteboardet lidt rundt i lokalet, men det var ikke muligt at afgøre. I hvertfald er det ikke meget den bliver påvirket.
    Vi prøvede også at påvirke sensoren vha. magneten i en visker til whiteboardet. Det gik selvfølgelig helt galt hvis vi påvirkede sensoren under calibreringen. På billedet herunder ses hvordan det gik da vi prøvede at lade den kører calibreringen uforstyret og så påvirkede den under kørslen. Vi har ikke lavet nogle målinger på hvilken afstand der skal til for at den bliver påvirket.

Figur 5




Konklusion

Tachocounteren fungerede fint når bilen skulle køre lige ud, men der var store problemer når den skulle dreje hvilket for en stor del kunne tilskrives underlaget. Den fejl i rotationen som vi så når den skulle køre lige frem og derefter dreje 180 grader blev summeret op når bilen skulle køre i en firkant. Dette var også de resultater Brian Bagnall nåede frem til.


Forskel mellem kompas sensoren og den almindelige sensor, er at kompas sensoren selv kan kompencere, hvis robotten kommer fysisk ud af kurs. Tacho counteren kan kun navigere efter de udregninger den har, fra hvor mange omdrejninger hjulene har taget. Hvis dette af en eller anden grund er forkert (Hjulene glider, noget sidder fast osv.) opdager den det ikke.

Kompas sensoren derimod, måler efter hvilken retning robotten befinder sig i, og er derfor ikke påvirket af robottens fysik på samme måde. Dokumentationen for denne klasse, er meget begrænset og det er derfor svært at finde ud af præcis hvordan det virker. Da konstroktoren også tager parametre for hjulene, må man gå ud fra at afstand er målt via Tacho tællerne, da kompasset kun kender retningen. Heldigvis er Tacho tællerne temmelig gode til at måle afstanden, og unøjagtighederne opstår oftest ved rotation.



Referencer

torsdag den 12. november 2009

Øvelse 8

Dato: 6. november 2009
Øvelsens varighed: 3 timer
Gruppemedlemmer: Annette, Samuel og Rasmus

Mål
Sidste øvelse handlede om Braitenbergs vehicles der kunne køre mod en kilde eller væk fra en kilde (lys, lyd). De havde alle kun én behavior. Denne øvelse handler om at en agent kan have flere synlige opførsler og hvilken opførsel der skal vælges på hvilket tidspunkt.

Baggrundsinfo
Subsumption architecture is a reactive robot architecture heavily associated with behavior-based robotics. The term was introduced by Rodney Brooks and colleagues in 1986.
A subsumption architecture is a way of decomposing complicated intelligent behaviour into many "simple" behaviour modules, which are in turn organized into layers. Each layer implements a particular goal of the agent, and higher layers are increasingly abstract. Each layer's goal subsumes that of the underlying layers, e.g. the decision to move forward by the eat-food layer takes into account the decision of the lowest obstacle-avoidance layer. As opposed to more traditional AI approaches subsumption architecture uses a bottom-up design.
For example, a robot's lowest layer could be "avoid an object", on top of it would be the layer "wander around", which in turn lies under "explore the world". Each of these horizontal layers access all of the sensor data and generate actions for the actuators — the main caveat is that separate tasks can suppress (or overrule) inputs or inhibit outputs. This way, the lowest layers can work like fast-adapting mechanisms (e.g. reflexes), while the higher layers work to achieve the overall goal. Feedback is given mainly through the environment.
The basic principles of implementing a subsumption architecture are:
1. Divide your problem into basic competencies ordered simple to more complex. Designate a level for each basic competency.
2. Further subdivide each level into multiple simple components which interact through shared variables. Limit the sharing of variables among levels to avoid incomprehensible code.
3. Implement each module as a separate light-weight thread. You might think of setting the priorities for these threads so that modules in a given level have the same priority.
4. Implement suppression and inhibition as one or more separate "arbitration" processes that serve to control access to shared variables. You might want to control access using semaphores.

Fremgangsmåde
1. Robotten
Der bygges en ultralydssensor på robotten.

2. SoundCar program
SoundCar.java programmet bruges sammen med klasserne AvoidFront.java, Behavior.java, Car.java, PlaySounds.java og RandomDrive.java. Projektet downloades til robotten og opførslen observeres.

3. Concurrent tråde
De tre forskellige opførsler; drive, avoid og play er implementeret som tre forskellige tråde. Koden til de tre opførsler undersøges og sammenlignes med hvad vi har observeret i det foregående.

4. Behavior suppression



Figur 1 - Kilde http://people.csail.mit.edu/brooks/papers/AIM-864.pdf

Hver af klasserne til de tre opførsler bygger på suppression, se Figur 1. De højere niveauer undertrykker de lavere niveauer. En lignende figur laves for vores program ud fra hvad vi har observeret og samtidig beskrives koden. Hele projektet kan ses i http://www.daimi.au.dk/~u071252/DL/Practice8/SoundCar.rar.

5. Drive towards light
I sidste øvelse skrev vi til sidst FollowLight projektet om til et flertrådet program. Til denne del af øvelsen bruges FollowLight klassen, så robotten får en ekstra opførsel, det vil sige et ekstra niveau. Udover instanser af de tre andre opførsler oprettes nu en instans af FollowLight og den bliver gjort aktiv som niveau 2, se Figur 2. Det nuværende projekt ændres ved at føje FollowLight klassen til projektet og lave nogle enkelte tilpasninger fx er det ikke direkte Car klassens forward og backward metoder der skal bruges, men Behavior klassens.


Figur 2

Forventningen til robottens kørsel er, at vi ikke vil se den tilfældige kørsel på må og få som vi hidtil har set, men i stedet en målrettet kørsel efter lys. Avoid og PlaySound er stadigvæk de højeste niveauer, så hvis den er ved at køre ind i noget vil den undgå det i stedet for at blive ved med at køre mod lyset og PlaySound vil stadigvæk sørge for at den stopper op hver tiende sekund og spiller et lille nummer. Hele projektet kan ses i http://www.daimi.au.dk/~u071252/DL/Practice8/SoundCarMedLys.rar.



Resultater
1. Robotten
Med ultralydssensoren ser robotten ud som vist i Figur 3.




Figur 3

2. Robottens opførsel
Robotten kører tilfældigt rundt. Den kører og holder stille – kører og holder stille i intervaller af ca. 3 sekunder. Strækningerne den kører er forskellige.
Ca. hvert tiende sekund spiller den en lyd. Længden af lyden der bliver spillet er forskellig.
Hvis der er en forhindring foran ultralydssensoren bakker den en smule og drejer lidt så den måske kommer fri af forhindringen.

Displayvisninger




Den første kolonne angiver hvilke opførsler der er undertrykt når en given opførsel udføres. Ved drive er ingen af opførslerne undertrykt. Når bilen er ved at undgå en forhindring er opførslen drive undertrykt. Når den spiller er både drive og avoid undertrykte.
Den anden kolonne angiver afstanden som ultralydssensoren måler så længe avoid ikke er undertrykt.
Den sidste kolonne angiver hvilken vej motorerne kører. Når bilen skal køre tilfældigt rundt skifter den mellem at køre frem og stoppe og det vises på displayet med f og s ved drive. Når bilen skal avoide er drive undertrykt og der vises s (stop) ud for drive. Ved avoid kører den først tilbage (b) og derefter drejer den lidt ved at køre tilbage på venstre hjul (b) og fremad på højre hjul (f). Når den spiller er både drive og avoid undertrykte og bilen holder stille så der står s ud for drive og avoid.

3. Concurrent tråde
RandomDrive
Random drive opførslen er styret vha. tid. Når robotten får besked om at den skal køre fremad gør den det i et tidsinterval der er givet med et kald til Math.random() der bruges til delay. Power til motorerne er også tilfældigt givet med random(). Delayet mellem fremadkørsel og stop er også tilfældigt med random(). Stop udføres også i et tidsinterval givet ved et tilfældigt delay. Vi havde observeret denne opførsel som mere kontrolleret, med kørslen fremad og tilbage i de samme intervaller hver gang, men det har været tilfældigt at random() funktionen har returneret værdier der har ligget så tæt på hinanden at vi ikke har kunnet skelne.

Avoid
Avoid aktiveres når en forhindring er mindre end tyve centimeter fra robotten, det er altså styret af en ekstern påvirkning. Reaktionen på dette er at robotten bakker i 1 sekund og efterfølgende drejer til venstre ved at sætte power på højre motor. Det var også denne opførsel vi observerede under testen.

PlaySounds
PlaySounds sker i et fast interval af ti sekunder. Hvorimod intervallet lyden bliver spillet i varierer ved kald til random() metoden, der bruges i delay().

4. Behavior suppression
Vores observationer af robotten under de tidligere tests gør det muligt at lave en figur der viser specifikt hvad de forskellige niveauer er i robotten. Drive er nederst og undertrykkes hvis det er nødvendigt at lave en avoid manøvre og playsound er øverst og undertrykker både avoid og drive opførslerne.


Figur 4

KodenI SoundCar klassen oprettes én instans af klasserne RandomDrive, AvoidFront og PlaySounds, som alle nedarver fra klassen Behavior. Ved oprettelsen sendes en instans af den klasse, der ligger ét niveau under og som derfor skal undertrykkes, med som argument.

rd = new RandomDrive("Drive",1, null);
af = new AvoidFront ("Avoid",2,rd);
ps = new PlaySounds ("Play ",3,af);

Bemærk at instansen, rd, får en null-pointer med som argument. Det skyldes at RandomDrive klassen i dette tilfælde repræsenterer det nederste niveau i suppress-mekanismen. Når en instans af de forskellige opførsler, som klasserne repræsenterer, skal undertrykke de underliggende instanser, sker det igennem et kald til metoden suppress.

public synchronized void suppress() {
if ( subsumedBehavior != null ) {
subsumedBehavior.suppressCountIncrement();
subsumedBehavior.suppress();
}
}

Suppress metoden kalder suppressCountIncrement() metoden for den instans af behavior-klassen som ligger ét niveau under. Samtidig kaldes dens suppress-metode som undertrykker dens underlæggende instans, og sådan fortsættes indtil vi når bunden af niveauet. I vores tilfælde ligger rd (RandomDrive) nederst i hirakiet, og derfor er dens instans af subsumedBehavior sat lig med null. Derfor blokerer den ikke nogle underlæggende instanser pga. if-sætningen.

Behavior-klassen implementerer også sine egne forward og backward metoder som kalder forward og backward metoderne fra Car-klassen. Behavior-klassens implementering sørger for at Car-klassens metoder kun kan kaldes hvis den kaldende instans ikke er undertrykt.

5. Drive towards light
Testen foregår i et mørkt rum med døren stående åben, men robotten søger i første omgang ikke mod lyset men mod mørket. Det gjorde dog at vi fik testet avoid opførslen, fordi den så var ved at køre ind i en væg, og avoid bryder fint ind og undertrykker FollowLight, så den ikke kolliderer med væggen.

At den kørte mod mørke i stedet for lys skyldes at venstre sensor styrede venstre motor og højre sensor højre motor og det er forkert når den skal køre mod lyset. Da det var ændret kørte den mod døråbningen og blev undervejs afbrudt hver tiende sekund af en gang musik.
Vi observerede at der var et problem hvis den kom for tæt på en grå kopimaskine i rummet fordi den fra den afstand er lysere. Ved at der kom dagslys ind gennem døren kan man sige at der var en aktiv lyskilde og det var den vi gerne vi finde og derfor er det ikke ønskeligt at den finder den lyseste overflade. Det lys sensoren registrerer, er lysrefleksionen fra kopimaskinen.

Konklusion
Øvelsen har gjort teorien fra sidste undervisningstime mere konkret. Vi har nu selv prøvet at stille en model op for robottens opførsler og tilføje en opførsel og implementere den. Først var det et eksisterende program der blev afprøvet på robotten og vi kunne nogenlunde skelne dens opførsel og bestemme hvad der aktiverede de forskellige opførsler. Til sidst tilføjede vi en ny opførsel ved at bestemme hvor i arkitekturen den skulle ligge og bagefter implementere den i testprogrammet. Dette lykkedes også som forventet.

Referencer
1. Kilder til Baggrundsinfo:
Robot Architectures by Thomas Dean.
http://www.cs.brown.edu/people/tld/courses/cs148/02/architectures.html

Wikipedia Subsumption architecturehttp://en.wikipedia.org/wiki/Subsumption_architecture

2. Kilde til arkitektur: http://people.csail.mit.edu/brooks/papers/AIM-864.pdf.

3. SoundCar projektet af Ole Caprani: http://www.daimi.au.dk/~u071252/DL/Practice8/SoundCar.rar.

4. SoundCarMedLys projektet SoundCarprojektet videreudviklet af gruppen: http://www.daimi.au.dk/~u071252/DL/Practice8/SoundCarMedLys.rar.

torsdag den 5. november 2009

Øvelse 7

Dato: 30. oktober 2009
Øvelsens varighed: 3 timer
Gruppemedlemmer: Annette, Samuel og Rasmus


Mål
Målet for denne øvelse er at bruge NXT til at bygge og programmere tre Braitenberg køretøjer og derved få en bedre forståelse af hvordan de virker.

Baggrundsinfo
Valentino Braitenberg's Vehicles
Braitenberg's vehicles consist of the simplest sort of wheeled robots in which sensors that are sensitive to different stimuli are wired directly to motors that drive the wheels. In these models, we assume that the sensor generates a signal that is proportional to the stimulus. In the simplest vehicle (see Vehicle 1 below) we imagine a sensor sensitive to light and assume that the more light that falls on face the sensor the faster the motor turns. The wire running from the sensor to the motor is labeled positive (+) indicating that sensor stimulates the motor to turn. Things become more interesting when we have multiple sensors and multiple motors.

(Fra: http://www.cs.brown.edu/people/tld/courses/cs148/02/introduction.html )


Fremgangsmåde
1. Vehicle 1
Det første køretøj som ses i Figur 1 er udstyret med en sensor og en motor. Jo større værdi der detekteres af sensoren desto hurtigere kører motoren.


Figur 1 - Braitenbergs vehicle 1

Dette princip bruges til at afprøve vores egen udgave af Braitenbergs vehicle 1. Den kan ses i Figur 2. I stedet for en lyssensor har den en lydsensor, så den vil køre hurtigere jo højere lyden er, i den retning lyden kommer fra. Da det vil være vanskeligt for bilen at undgå at vælte har den to hjul styret af to motorer, men hver motor får tilført samme power beregnet ud fra sensorværdien.


Figur 2 - Vores vehicle 1

Reguleringen af hastigheden er proportional med styrken som lydsensoren opfanger. Den læste værdi for lyden konverteres til en værdi for power til begge motorer og bilen kører lige fremad. Konverteringen foregår vha. en constant som ses beregnet i Figur 3. De indkommende sensorværdier ligger mellem 0 og 100 og det skal passes ind i intervallet mellem maksimum power og minimum power som ligger mellem 60 og 100. 60 er valgt så de bilen kører fremad ved lav hastighed selvom der ikke laves høje lyde. Desuden ganges med 100 for at forblive i integers.


Figur 3 - Beregning af constant


Convert() metoden som ses i Figur 4 har lydværdien som parameter og her bruges constant værdien beskrevet ovenfor til at konvertere lydværdien. For at kompensere for faktoren i constant divideres med 100. Derudover sørger if sætningerne for at vi holder os imellem de 0 og 100 i motorkraft i tilælde af at lyden bliver så den overskrider eller kommer under grænserne for hvad der kan sendes ud på motorerne.



Figur 4 - convert() metoden


Til sidst er tilbage at bruge værdien konverteret fra en værdi for lyden til en værdi for motor power og sende den til motorerne. Car klassen fra de tidligere øvelser bruges igen som den er. Som det ses bruger vi metoden backward og det skyldes at motorene sidder omvendt af hvad de gør, på den robot Car klassen er lavet til.


Figur 5 - Bilen styres vha. den målte lydstyrke

Test
Testen udføres ved at sætte bilen på gulvet. Når programmet startes vil den begynde at køre langsomt fremad. Forventningen er at den vil speede kraftigt op når vi klapper eller råber. Hele koden til vehicle 1 projektet kan findes her: http://www.daimi.au.dk/~u071252/DL/Practice7/SoundSpeedCar.java

2. Vehicle 2a
Vehicle 2a har som det ses på Figur 6 to sensorer. Størrelsen af den målte værdi fra den venstre sensor bruges til at beregne hvor meget power der skal til venstre motor og størrelsen af den målte værdi fra den højre sensor bruges til at beregne hvor meget power der skal til højre motor.

Figur 6 - Braitenbergs vehicle 2a

Vores udgave af dette køretøj følger dette princip, men da der kun er en lydsensor til rådighed bruges her lyssensorer. Bilen er vist i Figur 7 og den har venstre lydsensor der peger ca. 45 grader mod venstre og den højre lydsensor der peger ca. 45 grader mod højre.


Figur 7 - Vores vehicle 2a

I koden til vehicle 2a er der en konstant som bruges i convert() metoden. Denne metode er fuldstændig ligesom ved vehicle 1 og konstanten er beregnet på samme måde. Forskellen ligger i while loopen der udføres indtil escape knappen aktiveres. Den ser ud som vist i Figur 8 for vehicle 2a.

Figur 8 - Regulering af power til de to motorer

Værdierne fra de to sensorer aflæses og konverteres til en værdi til motorerne. Jo større lysstyrke desto større værdi til motorerne. Hvis der sendes størst power til venstre motor fordi lyset har størst intensitet her vil det resultere i at bilen drejer mod højre, det vil sige væk fra lyskilden. Den samlede kode til vehicle 2a projektet findes her: http://www.daimi.au.dk/~u071252/DL/Practice7/Vehicle2.java

Test
Testen består i at stille bilen på gulvet og påvirke den med lys fra en af siderne og forventningen er at bilen kører den modsatte vej.

3. Vehicle 2b

Vehicle 2b har ligesom vehicle 2a to sensorer og varierer også power til motoren ud fra værdierne fra sensorerne, men her går venstre sensor til højre motor og højre sensor til venstre motor. Ændringen fra vehicle 2a foregår udelukkende i koden så der henvises igen til Figur 7.


Figur 9 - Braitenbergs vehicle 2b


Den eneste forskel i koden kan ses i Figur 10, hvor power til venstre motor før blev beregnet ud fra sensor 1’s værdi beregnes den nu ud fra sensor 2’s værdi. Den samlede kode til vehicle 2b kan findes her: http://www.daimi.au.dk/~u071252/DL/Practice7/Vehicle3.java



Figur 10 - Kode til vehicle 2b

Test
Nu vil en stor sensorværdi fra venstre sensor resultere i mere power til højre motor og at bilen derfor drejer mod venstre. Forventningen til testen er derfor at vehicle 3 nu vil køre mod døråbningen, når den startes i et mørkt rum.

4. Flere tråde

På nuværende tidspunkt sker al udførsel i programmet fra main tråden. Venstre sensor aflæses og der beregnes en værdi til motoren og højre sensor aflæses og der beregnes en værdi til motoren, efterfølgende outputtes værdierne til de to motorer. Det kunne være interessant at se om det har nogen indflydelse hvis aflæsning af sensorværdierne og den efterfølgende beregning og styring af den tilhørende motor deles op i tråde. Det vil sige de nævnte aktiviteter skal foregå i en klasse der arver fra Thread() og der oprettes en tråd til hver sensor.

Nu vil thread scheduleren sørge for at tildele hver tråd udførselstid og spørgsmålet er om disse skift vil få indflydelse på hvordan bilen opfører sig. Forventningen er at det ikke vil have nogen betydning fordi skiftene sker så hurtigt og vores lyskilde er permanent. Derimod kunne der muligvis blive problemer i tilfælde af at der sker et lysglimt som er så kort at det sker lige i den timeslice hvor tråden til den anden sensor der vender væk er aktiv og så vil den reagere på lysglimtet i stedet for. Her er det dog nok ikke trådenes time slicing der er det største problem, men måske i lige så høj grad det interval som sensorerne kan opdatere deres værdier i.

Test
Programmet til vehicle 2b skrives om så det der lå i while loopen nu sker i en ’SensorThread’. Der oprettes en left SensorThread og en right SensorThread. Hvor Car.java klassen tidligere har kunnet bruges direkte har det været nødvendigt at lave en separat metode til at styre venstre motor og en til at styre højre motor, da kontrollen sker i forskellige time slices. Forventningen er stadigvæk at bilen vil køre mod døråbningen i et mørkt rum. Koden til dette projekt kan ses i http://www.daimi.au.dk/~u071252/DL/Practice7/V3/SensorThread.java http://www.daimi.au.dk/~u071252/DL/Practice7/V3/Vehicle3.java.

Resultater
1. Vehicle 1
Testen er udført som beskrevet ovenfor og som forventet speeder bilen kraftigt op når der laves høje lyde som klap eller tramp i gulvet. Dette kan ses her: http://www.youtube.com/watch?v=3Ro79z-tLsY

2. Vehicle 2a
Testen er udført i et mørkt lokale uden vinduer med døren stående åben og ganske som forventet kører bilen væk fra døren og altså væk fra lyskilden.

3. Vehicle 2b
Testen er igen udført i et mørkt lokale uden vinduer med døren stående åben. Som forventet kører bilen mod døråbningen og altså imod lyskilden. Dette kan ses her: http://www.youtube.com/watch?v=rk6ttAPf7DI

4. Flere tråde
Som ventet kørte bilen uden problemer mod døråbningen i det mørke rum så det har ikke ændret noget at lave det flertrådet.

Konklusion
Der blev lavet tre biler med egenskaber som Braitenbergs Vehicles 1, 2a og 2b. Vehicle 1 speedede op når den detekterede høje lyde proportionalt med værdien for lyden. 2a kørte i den modsatte retning af lys og 2b kørte i retningen af lys.
Derudover blev det undersøgt om det har nogen indvirkning på bilens opførsel når udførsel af programmet ikke sker i main tråden, men der laves en tråd til hver sensor som også sørger for at sætte en værdi for power til motoren. Der er ikke nogen synlig forskel på opførslen og det var heller ikke forventet.

Referencer
1. Opgaveoplægget: http://www.legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson7.dir/Lesson.html
2. Braitenberg Vehicles intro: http://www.cs.brown.edu/people/tld/courses/cs148/02/introduction.html
3. Vehicle1 kode: http://www.daimi.au.dk/~u071252/DL/Practice7/SoundSpeedCar.java
4. Vehicle2 kode: http://www.daimi.au.dk/~u071252/DL/Practice7/Vehicle2.java
5. Vehicle3 kode: http://www.daimi.au.dk/~u071252/DL/Practice7/Vehicle3.java
6. Vehicle3thread kode: http://www.daimi.au.dk/~u071252/DL/Practice7/V3/SensorThread.java http://www.daimi.au.dk/~u071252/DL/Practice7/V3/Vehicle3.java
7. Vehicle1 film: http://www.youtube.com/watch?v=3Ro79z-tLsY
8. Vehicle2b film: http://www.youtube.com/watch?v=rk6ttAPf7DI

Faste læsere

Bidragydere