LegoLab09

Denne blog bruges af Kim Munk Petersen (20063667), Andreas Koefoed-Hansen (20062154) og Tim Rasmussen (20061947) som dagbog i forbindelse med kurset Embedded Systems/Legolab på Århus Universitet.

onsdag den 27. januar 2010

Projekt - Endelig konklusion

Dato:
26-01-2010

Antal timer:
3 timer

Deltagende personer:
Kim Munk Petersen, Andreas Koefoed-Hansen og Tim Rasmussen

Opsummering:
I starten af projektforløbet lavede vi en liste af prioriteter over hvad vi ville nå. Vi har forsøgt at følge listen som en slags arbejdsplan igennem hele projektperioden. Listen er som følgende:
  1. Balancere vha. PID kontroller.
  2. Køre frem og tilbage evt. styret via Bluetooth.
  3. Dreje
  4. Follow the line
  5. Undgå objekter.
  6. Navigation vha. kompas.
Det første punkt viste sig at tage en del længere tid end forventet og vi havde en del problemer med at få noget brugbart information fra sensoren pga. drift [1]. Efter en del søgen på nettet for at finde en løsning fandt vi frem til et projekt der mindende om vores. Steven Witzand havde som en del af hans speciale bygget en GELway robot der kunne balancere vha. en gyroskopsensor[2]. Ved at bruge noget af hans kode fik vi robotten til at balancere nogenlunde og efter en del ændringer i koden blev resultatet tilfredsstillende. En af de ting vi ændrede på var værdierne på PID controlleren der bliver brugt til at få robotten til at balancere, det viste sig dog at vi ikke kunne indstille parameterene bedre end de forvejen var [3].

Næste punkt var at få Bluetooth kommunikation op at køre. Det viste sig ikke at være det store problem da Kim tidligere i kurset havde arbejdet med dette [4]. Et at de mindre problemer vi havde med Bluetooth var at den ene NXT-brick ikke kunne kommunikere med computeren. Kim havde heldigvis en anden, fra hans tidligere gruppe, som vi vidste virkede[5]. Inputs til robotten bliver sat og læst vha. en bitmask således at der kan sendes flere input af gangen, fx kør frem + drej til højre. Bluetooth kontrollen blev implementeret som en behavior som bygger på en subsumption struktur der blandt anden kan håndtere prioriteter af behaviors.

Det tredje punkt var at få robotten til at dreje. Dette var ikke det store problem da det bare handlede om at give mindre power til motoren i den retning man ville.

Punkt 4 og 5 blev byttet om så vi først implementerede en AvoidFront behavior[5] og derefter en LineFollower behavior[6]. Det viste sig ikke at være det store problem og det var ret let at implementere disse som behaviors da vi havde nogle erfaringer med disse i forbindelse med øvelser tidligere i kurset[7][8].

Det sidste punkt med navigation vha. et kompas, fik vi ikke tid til at implementere. Det at gøre det muligt for Legwayen at navigere vha. et kompas er i sig selv et helt projekt. Vi ved fra da vi selv arbejde med kompas og fra gruppen der har arbejdet med det hvor svært det har været at få robotten til at vide hvor den er. Derfor var dette mål også meget urealistisk.

Linket herunder peger på en side med videoer der viser hvad vores Legway er i stand til. De blev alle filmet dagen inden præsentationen.
http://www.cs.au.dk/~tiras/filer/LEGO/embed.html

Udbytte:
I forbindelse med projektforløbet har vi arbejdet med mange af de teknikker blev gennemgået i løbet af kurset.
Blandt andet fik vi brugt et løbende gennemsnit til at hele tiden at re-kalibrere offsettet i gyroskopklassen.
I forbindelse med at robotten skulle kunne balancere fik vi også et bedre indblink i hvordan en PID controller virker. Vi havde dog tidligere arbejdet lidt med denne da vi skulle lave en robot der kunne balancere vha. en lyssensor. I løbet af dette projekt vi fik mere mulighed for at gå  mere i dybden med PID controlleren.
Efter at robotten balancerede og vi ville udbygge funktionaliteten fik vi gjort brug af en behavior-based arkitektur da vi arbejde med leJOS subsumption framework. Dette var lige til da vi også tidligere i kurset havde arbejdet med denne type arkitektur.
En sidste ting er at vi har fået nogle erfaringer med kommunikation vha. Bluetooth. Selvom der var lidt problemer i starten lærte vi af dem og fik rettet dem samtidigt med at vi lærte mere om hvordan kommunikation foregår.

Perspektivering:
Hvad ville vi ændre eller udbygge med hvis vi havde haft mere tid til projektet, eller skulle arbejde på et lignende projekt i fremtiden?.

Størstedelen af vores overvejelser i løbet af projektet har omhandlet hvordan vi kunne komme driften på gyrosensoren til livs. Efter at vi indså at der var meget drift, overvejede vi om vi skulle benytte andre typer sensorer som fx en tiltsensor/accelerometer. En kombination af tilt -og gyrosensorer (sensor fusion) kunne nok havde været en god løsning da dette er måden hvorpå en Segway håndtere driften fra gyrosensorerne[9][10].
En anden ting der kunne været afprøvet var at sætte to gyrosensorer på robotten der monteret modsat af hinanden. Ideen er at sensorerne muligvis ville drifte hver sin vej og at man derved kunne finde en gennemsnitsværdi der lå tæt på den reelle værdi.

Som beskrevet tidligere har vi fra starten af benyttet dele af koden fra en BalanceController der er fundet på nettet. En af de ting vi ville prioritere hørt i en anden sammenhæng ville være at bygge denne fra bunden af og selv lave de beregninger der indgår, som fx vægtningen af sensorinput.

Konklusion
Fra starten af projektforløbet, opstillede vi en række mål vi ønskede for projektet. Et enkelt af disse mål
var meget optimistisk og blev derfor heller ikke en del af projektet. Ud over det ene mål, er alle mål blevet opfyldt. Grunden til at vi nåede alle vores mål skyldes det kode vi fandt på nettet[11]. Lige som den anden gruppe der også arbejdede med Legway, så har vi også haft lige så store problemer med at løse problemet omkring gyroskopsensorens drift. Vi var så heldige at vi fandt noget kode på nettet der bygger på et tidligere års Lego projekt. Efter at have arbejdet ud fra den fundne kode og gjort brug af nogle af de samme principper valgte vi at anvende dele af den fundne kode. Grunden til dette var en prioritetssag. Enten valgte vi at arbejde videre med drift problemet eller også valgte vi at gøre brug af noget kode og dermed få robotten til at balancere så vi kunne arbejde videre med at nå vores mål. Vi har arbejdet meget bevist på hele tiden at se om vi kunne lave vores egen kode, hvilket resultere i at vi kun bruger koden til at styre motorerne, principperne til at få Legwayen til at køre frem og tilbage samt de beregnede værdier til PID controlleren. Alt funktionalitet rundt om har vi selv udviklet. Ligeledes har vi modificeret og tilføjet nye ændringer til deres kode. Vi gør brug af deres balancecontroller, men i teorien kunne vi lige så godt have lavet vores egen og bruge deres værdier, eftersom vi allerede har lavet vores egen tidligere i kurset. For ikke at bruge unødig tid på noget der egentligt ikke giver nogen ændring, valgte vi blot at bruge deres.

Som tidligere nævnt så har det været et prioritets spørgsmål hvor vi skulle vælge at bruge vores tid og vi er glade for det valg vi tog. Det har givet os muligheder for at stifte bekendtskab med og overveje forskellige former for styring af behavior, Bluetooth og PID controller. Hvis vi havde haft længere tid til projektet, så ville vores først prioritet være at lave vores egen balancecontroller og motorcontroller, således vi ikke gjorde brug af andet end vores egent kode.

Referencer:
  1. Projekt Blog 1: http://legolab09.blogspot.com/2009/12/projekt-uge-1.htm
  2. Projekt Blog 2: http://legolab09.blogspot.com/2009/12/projekt-2.html
  3. Projekt Blog 3: http://legolab09.blogspot.com/2010/01/projekt-2.html
  4. Kim og Martins blog: http://gayalsfaboulousrobots.blogspot.com/2009/10/robot-race.html
  5. Projekt Blog 4: http://legolab09.blogspot.com/2010/01/projekt-4.html
  6. Projekt Blog 7: http://legolab09.blogspot.com/2010/01/projekt-7.html
  7. NXT Programming, Lesson 8, http://legolab.daimi.au.dk/DigitalControl.dir/NXT/Lesson8.dir/Lesson.html
  8. NXT Programming, Lesson 9, # http://legolab.daimi.au.dk/DigitalControl.dir/NXT/Lesson9.dir/Lesson.html
  9. http://findit-fixit.sensorsmag.com/archive/index.php/t-839.html
  10. http://www3.ntu.edu.sg/home/mffyap/web/docs/Selfbalancingscooter.pdf
  11. The Java source code for the GELway, http://gelway.googlecode.com/files/GELway%20Java%20Code.rar

onsdag den 20. januar 2010

Projekt - 7

Dato:
20-01-2010

Antal timer brugt:
4 timer

Deltagende personer:
Kim Munk Petersen, Andreas Koefoed-Hansen og Tim Rasmussen

Målet:
  • Implementere LineFollower
  • Rette blogindlæg
Planen:
Vi vil i dag forsøge at tilføje en ny behavior til Legwayen. Som beskrevet i de tidligere blogindlæg, bruger vi leJOS' subsumption framework hvilket gør det nemt at tilføje nye behaviors. Den nye behavior vi vil tilføje er en Line-follower således at vores Legway bliver i stand til at følge linjen på gulvet i Legolab, ligesom ved øvelsesgang 1 [1] og 4 [2].
Herefter vil vi rette de hidtil skrevne blogindlæg samt uddybe mangelfulde forklaringer mm.

Processen:
Vi mener at Legwayen har mulighed for at følge linjen på gulvet i Legolab idet vi ved at den er i stand til at balancere, køre ligeud og dreje uden problemer. Et mindre problem kan være at den for at holde balancen kører lidt frem og tilbage hvilket kan forsage at den kommer til at køre for langt frem i et skarpt sving og dermed kommer uden for banen. Dette problem er mindre udtalt ved lave hastigheder og vi starter derfor med at implementere en funktion der gør os i stand til at styre farten af Legwayen. I øjeblikket er farten ved ligeudkørsel hardcoded ind i programmet og det er altså denne vi vil have flyttet ud i en variabel så den kan ændres. Herved opnår vi også en mere generisk løsning der gør det let at implementere en analog styring af Legwayen, selvom vi ikke har planer om at implementere dette. Legwayens acceleration er bestemt af en eksponentialfunktion som forklaret i forrige blogindlæg, og metoden setMaxSpeed sætter derfor den maksimalt opnåelige fart ved henholdsvis kørsel frem og tilbage ifølge to parametre der gives med.

public void setMaxSpeed(double maxFowradSpeed, double maxBackwardSpeed) {
  this.maxForwardSpeed = maxFowradSpeed;
  this.maxBackwardSpeed = maxBackwardSpeed;
}


De to fields maxForwardSpeed og maxBackwardSpeed bruges nu i metoden runDriveState på følgende måde:

if (driveState == CtrlParam.FORWARDS)
  setTiltAngle(maxForwardSpeed - maxForwardSpeed * Math.exp(-damp));
else if (driveState == CtrlParam.BACKWARDS)
  setTiltAngle(-maxBackwardSpeed + maxBackwardSpeed * Math.exp(-damp));

Efterhånden som det andet led i kaldet til setTiltAngle går mod nul, sættes tilt-vinklen til maxForwadSpeed hvis Legwayen kører fremad og -maxBackwardSpeed hvis den bakker.

Efter vi implementerede setMaxSpeed-metoden i CtrlParam-klassen, flyttede vi også konstanterne STATIONARY, FORWARDS og BACKWARDS samt metoden runDriveState() fra BalanceController til CtrlParam idet vi ikke mener at det er BalanceControllerens ansvarsområde at få Legwayen til at køre frem og tilbage, men derimod blot at holde balancen.

Opførslen til at følge linjen er implementeret i klassen FollowLine der implementerer Behavior. Vi har valgt at den skal ligge lavest i behavior-hierarkiet, dvs. have den mindste prioritet. Den skal ikke ligge over AvoidFront idet der godt kan være en forhinding på en bane. Her giver det så god mening at Legwayen vender om og kører den anden vej. Den skal heller ikke ligge over BTDriver idet det er svært at detektere hvornår den er på en bane med en sort linje den kan følge, og dermed supresse Bluetooth-forbindensen. Nedenstående diagram viser Legwayens aktuelle behavior-hierarki.





I øjeblikket bruger Legwayen to ud af de fire sensorporte som NXT'en stiller til rådighed. De to sidste sensorporte kan derfor bruges til lyssensorer. Ved at bruge to lyssensorer i modsætning til én, får vi ikke en bang-bang controller [3], som er karakteriseret ved to tilstande, men derimod en controller med fire tilstande. Disse fire tilstande udgøres af mulige farvekombinationer som de to lyssensorer kan se, dvs. hvid/hvid, sort/sort, sort/hvid og hvid/sort. Ulempen ved at bruge en enkelt lyssensor er at robotten hele tiden skal holde sig på den ene side af linjen. Den har ingen mulighed for at opdage det hvis den ved et uheld krydser linjen, idet sensoren går fra sort til hvid uanset hvilken side af linjen den havner på, og kan derfor ikke finde tilbage til linjen igen. Ved at bruge to lyssensorer ved robotten til hver en tid på hvilken side af den sorte streg den befinder sig ved at se på hvilken sensor der sidst så den sorte linje. Da Legwayen er ustabil af natur hvorved den let kan komme til at krydse linjen, besluttede vi fra begyndelsen at bruge to lyssensorer.

Der er flere måder at lave styringen på. Vi lavede den således at robotten altid kører langsomt fremad og så korrigerer retningen ved at bremse hjulet der sidder i den retning den ønsker at dreje til. Skemaet herunder forklarer hvad robotten skal gøre alt efter hvilken af de fire førnævnte tilstande den er i.




Til at starte med placerede vi lyssensorerne mellem hjulene under robottens tyngdepunkt som vist på billedet herunder. Vi placerede dem således at de sidder på hver deres side af linjen, men stadig så tæt som muligt for at robotten hurtigst muligt registrerer når den kører skævt ift. linjen.




Da vi testede denne konfiguration viste det sig at robotten ikke var i stand til at følge linjen på gulvet. Den kørte meget fra side til side, nogle gange så meget at den vendte en halv omgang og begyndte at følge linjen i den forkerte retning. Problemet løste vi ved at flytte lyssensorerne længere frem. Herved får robotten mere feedback når den drejer idet sensorerne bevæger sig mere. Et eksempel herpå kan ses på nedestående illustration hvor lyssensorerne er placeret midt under robotten på den øverste serie af billeder hvorimod de er rykket lidt fremad på den nederste serie af billeder. Billederne illustrerer robotten og banen set oppefra, og hvad der sker når robotten kommer til et sving med henholdsvis den ene og den anden placering af lyssensorerne. Der er ingen forskel på de to tilfælde når robotten kører parallelt med stregen, men i sving har robotten nemmere ved at navigere når sensorerne sidder fremme idet den hurtigere finder den rigtige retning og ikke kommer helt på tværs af stregen som den ellers ville gøre (vist på øverste højre billede).




Vores eneste bekymring ved at placere lyssensorerne et stykke foran robotten er at de under acceleration løftes fra underlaget idet robotten tilter bagud, hvilket kan gøre at de muligvis ikke kan "se" farven på underlaget. Omvendt kan de under deceleration komme til at røre underlaget hvilket kan få robotten til at "snuble". Det første tilfælde viste sig ikke at være et problem i praksis og det andet tilfælde var kun et problem når Legwayen kører op af en stejl skråning. Dette problem ville givetvis kunne løses ved at rykke sensorerne en smule længere ind under robotten, og evt. ved at sætte en begrænsning i programmet på hvor skarpt robotten må dreje, for at undgå at den kommer helt på tværs af linjen. Dette når vi desværre ikke at eksperimentere med inden præsentation i morgen.

I det følgende beskriver vi kort implementeringen af opførslen. Idet FollowLine implementerer Behavior, har den metoderne action(), takeControl() og suppress(). TakeControl-metode returnerer altid true således at den bliver aktiv hvis ingen anden behavior ønsker kontrollen, hvilket giver god mening idet den har lavest prioritet. Suppress-metoden sætter en boolean isSuppresed til true. Denne bruges i action-metoden til at afgøre hvornår den skal stoppe med at følge linjen. Så snart Legwayen kommer for tæt på en mur eller der oprettes forbindelse til den via Bluetooth, vil henholdsvis AvoidFront eller LegwayDriver få arbitratoren til at supresse FollowLine og dermed sætte isSuppressed-flaget hvorefter den stopper sin action-metode så den opførsel der suppressede den kan blive afviklet. I starten af action-metoden tændes lyssensorernes floodlight og de slukkes lige inden action-metoden returnerer. Herved kan vi se på robotten om FollowLine-opførslen er aktiv eller ej.

Idet det egentlig mål med robotten var at få den til at balancere, kan man mene det er dumt at den afvikler FollowLine-opførslen pr. default, antaget af kriterierne for højere-prioritets opførsler ikke er opfyldt hvilket de typisk ikke er når robotten stares. Af den grund udvidede vi FollowLine-opførslen med en boolean isEnabled som angiver om den må udføres eller ej. Denne boolean starter med værdien false og kan kun sættes til true via PC-programmet der også bruges til at styre Legwayen. Det betyder at robotten ikke har nogen opførsel der ønsker kontrollen lige efter den er startet op hvorfor den blot står og balancerer. På samme måde gjorde vi det også muligt at aktivere og deaktivere AvoidFront-opførslen via Bluetooth så erfarne "chauffører" ikke risikerer at robotten pludseligt overtager styringen. Herunder ses et snapshot af det nye PC-program til styring af Legwayen. Desuden udskrives bitmasken nu også i tekstfeltet i midten således at vi kan kontrollere at de rigtige kommandoer bliver afsendt til Legwayen.




Afslutningsvis navngav og flyttede vi nogle "magiske" konstanter, som før var hardcoded ind i Legway'ens program, op i toppen af deres respektive klasse. Et eksempel herpå er konstanten der afgør hvornår Legwayen er væltet. Denne er nu defineret i BalanceController som følgende, således at koden bliver mere overskuelig og let kan justeres hvis vi skulle få brug for det.
private static final int FALL_ERROR = 8000; // constant for determining when Legway has fallen
Afrunding:
Projektforløbet er nu ved at være slut og vi når derfor ikke at implementere flere features på vores Legway. For at give et overblik over vores endelige softwarearkitektur, har vi lavet et UML-diagram som vist herunder. For at gøre det simpelt, har vi ikke inkluderet leJOS-klasser og interfaces såsom Behavior, Arbitrator, Motor og diverse sensorer. Derudover har vi kun skrevet de væsentligste metoder og fields i klasserne. Vi har illustreret hvilke klasser der ligger på NXT'en og hvilken der ligger på PC'en der bruges til at styre Legwayen via Bluetooth.

Mange af klasserne vist i UML-diagrammet er beskrevet i de forgående blogindlæg. Nogle af klasserne er dog ikke beskrevet, hvilket vi derfor kort gør i det følgende. Klassen Legway på NXT'en er hovedklassen forstået på den måde at den indeholder main-metoden som er programmets entry point. Den starter BalanceControlleren og tilføjer behaviors til arbitratoren som herefter også startes. Klassen Car implementerer nogle metoder der kan bruges til at få robotten til at køre frem/tilbage, dreje og stoppe. CtrlParam indeholder kontrolparametre der angiver robottens kinetiske tilstand, såsom drive-state, damp og motor-offsets.

Konklusion:

Det lykkedes os at få implementeret en ny behavior til Legwayen således at den nu er i stand til at følge en linje. Selvom vi som nævnt tidligere har implementeret samme opførsel ved to af øvelsesgangene, var det lidt sværere denne gang fordi vi skulle tage højde for Legwayens ustabilitet. Ved at få den til at køre langsomt minimerede vi ustabiliteten og ved at bruge to lyssensorer sørgede vi for at den kan finde tilbage til linjen hvis den kommer til at krydse den.
Efter præsentationen i morgen begynder vi at lave den endelige konklusion på projektet. 


Referencer:
  1. NXT Programming, Lesson 1, http://www.legolab.daimi.au.dk/DigitalControl.dir/NXT/Lesson1.dir/Lesson.html
  2. NXT Programming, Lesson 4, http://www.legolab.daimi.au.dk/DigitalControl.dir/NXT/Lesson4.dir/Lesson.html
  3. Bang-bang control, http://en.wikipedia.org/wiki/Bang-bang_control

mandag den 18. januar 2010

Projekt - 6

Dato:
18-01-2010

Antal timer brugt:
8 timer

Deltagende personer:
Kim Munk Petersen, Andreas Koefoed-Hansen og Tim Rasmussen

Målet:
  1. Ryde op i koden
  2. Udbedre ujævn kørsel
    1. Vil fjerne sinus kode.
    2. Modificere PID værdierne
    3. Regulere speed til motorerne bedre

Planen:
Vi vil starte med at få ryddet op i koden, således alt det kode vi ikke gør brug af bliver fjernet. Samtidig vil vi gennemgå koden for at se om der er ting der kan laves smartere. En af de ting der har irriteret os en smule når vi har kørt rundt med Legwayen er at dens hastighed svinger op og ned. Vi har en idé om at det er setPower() i MotorController der er skyld i at hastigheden svinger, eftersom den lægger en sinus værdi til hastigheden. Vi vil derfor for at fjerne den ujævne kørsel, prøve at fjerne koden der modificerer motorPower med en sinus værdi. Vi kunne forstille os at fjernelsen af sinus værdierne, kan medvirke at robotten bliver mere ustabil og vi derfor er nødt til at se på værdierne anvendt i PID Controllren. Derfor vil vi gennemføre endnu en test af disse og ændre på PID controllerens værdier så de kommer til at passe.

Processen:
Efter at have ændret rigtigt meget i koden, var der efterhånden opstået en hel del kode som vi ikke længere gjorde brug af. Et eksempel på noget kode der skulle fjerens, er måden hvornår bluetooth forbindelsen oprettes. Dette blev før gjort ved at der blev lavet en
BTConnection conn = Bluetooth.waitForConnection();
direkte i main metoden, hvorefter conn blev sendt videre til BTCommandReader. Det objekt af BTCommandReader blev herefter send videre til BTDriver sammen med ctrlParam. Efter at vi har ændret vores BTDriver til at håndtere hele opsætningen af Bluetooth i forbindelse med BTCommandReaderen, var der en helt del kode i main metoden der skulle fjernes. Dette kode fik vi fjernet sammen med alt andet død kode.

Legwayens kørsel er meget ujævn når den kører frem eller tilbage. Den starter med accelerere op til en vis hastighed hvorefter den decelererer indtil robotten kommer nær tilstand hvorefter den igen accelerer. Eftersom hastigheden svinger meget lignende en sinus kurve, var vores ide at grunden til den svingende hastighed skyldes den sinus værdi der lægges til motorhastigheden i setPower metoden.

Næste mål med at fjerne sinus-koden var ligetil. Vi udkommenterede koden der er placeret i MotorController klassen og compilede og uploade ændringerne. Resultatet af dette var at når Legwayen skulle stå stille og balancere, overshootede den mere en før og bevægede sig derved mere frem og tilbage. Ligeledes medførte ændringer ikke nogen forbedringer på den ujævne hastighed når vi kørte Legwayen frem og tilbage.
Vi prøvede også at ændre på nogle af de kontanter der bliver brugt i forbindelse med sinus-reguleringen:
private final double sin_speed = 0.1;
private final double sin_amp = 20.0; 

Dette gav ikke noget bedre resultat og vi besluttede os for at gå tilbage til den originale kode.

For at komme med et nyt bud på årsagen til den ujævne kørsel så vi på hvordan Legwayen håndterer frem og tilbage kommandoer. Når Legwayen bevæger sig frem eller tilbage sker det er det ved at give BalanceController klassen en tiltAngle der lægges til den angle der bliver hentet fra GyroscopeSensor klassen hvorved Legwayen "tror" den er ude af balance og derved vil prøve at korrigere for dette. Dette bliver gjort ved at ændre på den CtrlParam der bliver giver med til BalanceControllerens contructor.

CtrlParam har metoder til at sætte forskellige variabler som damp og driveState. Damp variablen bestemmer hvor hurtigt robotten skal accelerer mens driveState kan enten være stationary, forward eller backward. TiltAngle bliver beregnet ud fra de to variabler ved følgende formel
tiltAngle = maxForwardSpeed - maxForwardSpeed * Math.exp(-damp));
tiltAngle bliver beregnet hver gang runDriveState() metoden bliver kaldt og efter den er beregnet bliver damp talt lidt op.

Grafen herunder viser hvordan tiltAngle bliver sat efterhånden som damp bliver talt op.




Som det ses fra grafen giver dette en blød ændring i tiltAngle over tid. Dette gøres for at Legwayen skal kunne holde balancen under accelerationen. Hvad er så grundet til at Legwayen stopper op efter den har kørt et stykke tid? Ud fra grafen ses det at tiltAngle forbliver den samme efter accelerationen, så ret intuitivt skulle robotten blive ved med at køre frem med samme hastighed. Grunden til at dette ikke er tilfældet, er at integral ledet i PID controlleren[1]. Efter noget tid vil error-værdien bliver normaliseret da integral ledet gør at robotten "vænner" sig til den nye tilt.

Vi prøvede at ændre den måde hvorpå tiltAngle beregnes, således tiltAnglen nu kun afhang af damp værdien. Dette betød at tiltAnglen blev talt så hurtigt op at Legwayen accelererede eller decelererede så hurtigt at at den væltede. Grunden til at den vælter skyldes at integral ledet i PID controlleren ikke kan følge med til at kompensere for den store tiltAngle og derved vælter robotten når tiltAngle bliver for stor.Vi kunne have lavet et loft for hvor meget tiltAngle må tælles op, men ved at gøre dette vil vi blot være tilbage til udgangspunktet hvor hastigheden svinger op og ned. 

Vi ændrede derfor på hvor meget damp blev talt op hver gang og med den måde at bregne tiltAngle på nåede vi frem til en optimale værdi på 0.07. Efter at have fundet frem til denne værdi, står robotten stadig og overshooter mere end den gjorde ved den oprindelige måde at beregne tiltAngle på. Grunden til dette skal findes i at den accelerere hurtigt op og derved kommer over balancepunktet hvorfor den skal til at køre modsat vej for at kompensere for dette. Vi forsøgte at løse problemet med at den overshooter ved at skrue ned for ki variablen, så integralet ikke betød så meget i error-beregningen, men uden held.

Selv om vi nu have løst problemet med hastigheden, så valgte vi alligevel at vende tilbage til den anden måde at beregne tiltAngle på. Grunden til dette skyldes at Legwayens balanceringsevne. Den overshooter simpelthen for meget og det lykkes os ikke at finde nye værdier til PID controlleren der kunne kompensere for den overshoot der sker.

Vi ændrede PID controllerens parametre tilbage til de originale da det gav den bedste balance evne.

En ting vi gjorde der hjalp på kørslen var at udskifte den ene motor på Legwayen. Førhen kørte Legwayen skævt fordi den ene motor ikke var så kraftig som den anden. Efter denne ændring fik vi en bedre balance og den blev lettere at styre. Vi kunne også have kompenceret for den svage motor i koden, men jo kraftigere motorerne er, jo mere kraft har Legwayen til rådighed hvilket giver mulighed for bedre balanceevne.

Konklusion:
Vi fandt ud af at vores første tanke om at det var setPower() metoden der tilføjede en sinus værdi til hastigheden ikke var skyld i Legwayens svingende hastighed. Vi fandt frem til at svingningerne i stedet skyldes måden hvorpå tiltAngle blev beregnet i runDriveState samt den måde hvorpå PID controller prøver at kompensere for tiltAnglen. Vi prøve at ændre på den måde hvorpå runDriveState beregner tiltAnglen, således den nu kun afhænger af damp. Dette hjalp på problemet med den svingende hastighed, men gav i stedet nye problemer i form af for hurtig acceleration eller for høj hastighed. Begge tilfælde gjorde at Legwayen væltede. Vi prøve derfor at ændre på ki, for at se om vægtning af int_error (integralet af error) have en betydning for svingningerne. Det viste sig at dette gjorde Legwayen så ustabil at vi ikke rigtig kunne konkludere noget på dette.

Vi vil måske senere få tid til at arbejde videre på dette problem, men vores næste mål vil være at få udvidet funktionaliteten ved at tilføje en ny behavior i form af en LineFollower.


Referencer:
  1. PID Control.Chapter 5, pp. 179-190 of Fred G. Martin, Robotic Explorations: A Hands-on Introduction to Engineering, Prentice Hall, 2001. 

søndag den 17. januar 2010

Projekt - 5

Dato:
17-01-2010

Antal timer brugt:
10 timer

Deltagende personer:
Kim Munk Petersen, Andreas Koefoed-Hansen og Tim Rasmussen

Målet:
  1. Sørge for at motorene slukker når den vælter.
  2. Rette forskellige fejl og optimere koden.
  3. Tilføje connect- og disconnet-knap til vores Bluetoothcontroller på computeren.
  4. Tilføje understøttelse på Legwayen af flere samtidige tastetryk.
  5. Få robotten til at undgå objekter vha. en ultralydssensor.
Planen:
Vi starter med at få Legwayen til at slukke motorene når den ikke længere har mulighed for at rette op igen. Dette kunne f.eks. være når Legwayen er ned uden 45 grader, dette er selvfølgelig noget der skal afprøves for at finde den rigtige vinkel, således den ikke slukker motorene under kørsel med Legwayen. Der er forskellige fejl kode der skal rettes. F.eks. at newCommand bliver sat i BTCommandReader, men først bliver brugt i BTDriver. Dette betyder at BTCommandReader pga. et delay kan nå at opdatere variablen igen og derved mistes en kommando. Dette skal rettes til at BTDriver der holder styr på at der er modtaget en ny kommando. Ligeledes er der forskellige optimeringen der kan laves på koden. Når dette problem er løst, er planen at tilføje en ekstra behavior til Legwayen, således den bakker væk fra en objekt hvis den kommer for tæt på. Denne behavior har højre prioritet end vores BTDriver, og vi har derfor det simple behavior-hierarki  vist herunder.

 


Processen:
En af de ting vi har irriteret os over i forbindelse med at teste Legwayen, er at motorerne går helt amok når den vælter. Grunden til at motorerne får så meget power, skyldes at gyroskopet registrerer at Legwayen er væltet eller tilter meget og derfor forsøger PID controlleren at rette op den op igen. Hvis den er så langt nede at den ikke kan rettes op igen, så er det bedre at slukke for motorerne i stedet for at forsøge at rette op. Det store spørgsmål er nu bare, hvornår Legwayen ikke længere skal forsøge at rette sig selv op?

Vi forsøgte at løse dette problem ved at gøre brug af den vinkel gyroskopet måler vha. gyro.getAngle(). Det første forsøg gik ud på at hvis Legwayen havde tiltet mere en 70 grader skulle motorene slukkes. Dette gjorde vi ved følgende kode:
private static boolean testUpright(double Psi) {
    if (Math.abs(Psi) < 70)
        return true;
    motors.stop();
    ...
}
Så længe den numeriske værdi af vinklen er under de 70 grader, så fortsætter PID controlleren med at styre motorenes hastighed, men med det sammen vinklen kommer op over det 70, slukkes motorene. Hældningen på de 70 viste sig at være for højt, eftersom motorerne ikke altid blev slukket når Legwayen væltede. Derfor ændrede vi værdien til 60, men her havde vi stadig tilfælde hvor motorene ikke slukkede når den væltede. Vi ændrede derfor værdien til 50, hvilket heller ikke var en god værdi. Problemet var nu ikke at motorene ikke slukkede, men i stedet at de slukkede for hurtigt. Selv om Legwayen kørte som den skulle, så kunne gyroskopet pludseligt returnere en værdi højere end 50 og derved slukkede motorene. En måde vi kunne løse dette på var ved at lave et filter, hvorved værdier der lå langt fra tidligere værdier bliver sorteret fra. På den måde vil enkelte høje værdier være blevet sorteret fra og vi have undgået at den væltede. Vi valgte i stedet at træffe beslutninger på baggrund af det output (power), der bliver beregnet  i PID controlleren vha. formelen:
pw = error * Kp + deriv_error * Kd + int_error * Ki;
Efter at have lavet en del tests fandt vi frem til at den optimale værdi var 8000. Så når outputtet når op over de 8000 slukkes motorerne. En bivirkning ved denne løsning er at robotten rent faktisk også slukker motorerne hvis man løfter den fra overfladen. Denne bivirkning mener vi imidlertid er positiv idet det for Legwayen er unødvendigt at forsøge at korrigere for en tiltning hvis den hjul ikke rører jorden. I forbindelse med at vi fik løst problemet med motorene, kiggede vi også på muligheden for at rejse Legwayen op igen uden at genstarte NXT'en. Dette krævede nogle ændringer på tilgangen til de variabler vi skulle ændre på, samt tilføjelser til nogle metoder. Men ud over ændringerne i koden, var det rimeligt simpelt at løse problemet. Vi tilføjede funktionen til vores testUpright() metode som ses her:
private static boolean testUpright(double power) {
    if (Math.abs(power) < 8000)
        return true;
  
    motors.stop();
    motors.reset();
    File medicFile = new File("medic.wav");
    if(medicFile.canRead())
        Sound.playSample(medicFile);
    while (!Button.ENTER.isPressed()) {
        delay(10);
    }
    int_error = 0;
    prev_error = 0;
    gyro.reset();
    ctrl.resetTiltAngle();
    return false;
}
Det vigtigste er at huske at nulstille de rigtige værdier. Dem vi fandt ud af at vi skulle nulstille var motorens TachoCounter, gyroskopets vinkel, PID controllerens forskellige error værdier og vores TiltAngle. Da disse værdier var nulstillet, kunne vi starte balanceringen igen ved at trykke på enter knappen på NXT'en.

Efter at have løst problemet med motorene, begyndte vi at rette fejl og optimere koden. En af de større fejl vi rettede var at det var BTCommandReader der afgjorde om der var modtaget en ny kommando, men pga. et delay mellem BTCommandReader og BTDriver, der begge kører på NXT'en, kunne der gå kommandoer tabt. Derfor ændrede vi det til at det var BTDriver selv der stod for at bestemme om der var forskel på den nye og den forrige kommando. Ved at rette dette opstod der så et nyt problem. Problemet lå i at vi nu ikke længere kunne holde en knap nede på tastaturer eller trykke flere gange hurtigt. Grunden til dette ligger i at hvis vi f.eks. trykkede forward, så kører Legwayen fremad i 100 millisekunder, hvorefter den venter på en ny kommando. Hvis den nye kommando er den samme som den tidligere så sker der ikke noget, men eftersom vi altid sender en stop kommando når en knap slippes så burde den være klar til at modtage en ny forward kommando, men pga. det delay der er kan denne kommando gå tabt. Problemet løste vi ved at lave det sådan at den kører frem af indtil den modtager en ny kommando. Dette viste sig at være en god løsning.

En anden af de vigtige ændringer vi har lavet er at tilføje en buttonListener[1] til main metoden, således ligegyldig hvornår man trykker på ESCAPE knappen, så lukkes programmet.
Button.ESCAPE.addButtonListener(new ButtonListener() {
    public void buttonPressed(Button b) {
        Sound.buzz();
        System.exit(0);
    }
    public void buttonReleased(Button b) { }
});
Inden vi lavede denne ændring have vi placeret flere while-loops i koden for at kontrollere om der bliver trykke på ESCAPE knappen. Ved at bruge en ButtonListener kan vi nøjes med en enkelt listener. Vi havde dog et lille problem med at få vores ButtonListener til at virker, men dette skyldes at vi havde placeret den nederst i main metoden og derved aldrig blev afviklet. Grunden til at koden ikke blev afviklet skyldes at når Arbitratioren startes, så blokerer den koder der kommer efter. Vi flyttede derfor registreringen af vores ButtonListener op i starten af main metoden, hvorefter problemet var løst.

Ud over at have rette disse fejl, har vi været i gang med at rydde op og optimere koden. Dette betyder at metoder vi ikke længere gør brug af er fjernet, mens andre metoder har fået lidt mere arbejde. Ligeledes har vi fået tilføjet en connect og disconnet knapper i vores bluetooth controller på computeren, således det nu er muligt undervejs at disconnecte forbindelsen til NXT og derefter igen bruge connet til at oprette den igen. Det har været et irritationsmoment for os at vi hele tiden skulle til at lukke og starte programmet for igen at oprette forbindelse. Et snapshot af det opdaterede program med de to knapper ses herunder.



De to knapper var ikke svære at tilføje, men de gav lidt problemer idet tryk derpå flytter fokus fra det tekstfelt hvortil en keyEvent-listener er påhæftet. Det betyder at tastetryk ikke fanges når man har trykket på en af knapperne, medmindre man husker at trykke på tekstfeltet igen. En hurtig løsning var også at tilføje keyEvent-listener'en til begge knapper. Det viste sig ikke at virke idet vi disabler connect-knappen når man har connected og disconnect-knappen når man har disconnected, idet det ikke giver mening at oprette forbindelse hvis den allerede er forbundet, eller afbryde en forbindelse der er afbrudt. Grunden til at det ikke virker er at en disabled knap ikke er i stand til at fange key-events. Vi løste problemet ved programmatisk at ændre fokus tilbage til tekstfeltet efter man har trykket på en knap.

Vi regnede med at Legwayen ville blive nemmere at styre hvis man fx kan holde pil op og pil til højre nede på én gang og derved få den til at køre fremad mens den drejer svagt til højre. Som beskrevet i forrige indlæg kan vores PC-program der sender kommandoer til Legwayen via Bluetooth signalere at flere taster holdes nede. Vi udvidede derfor BTDriver-klassen til også at understøtte dette ved at ændre tilt-vinklen på præcis samme måde som når robotten kører frem eller tilbage og så lave et offset på en af de to motorerer således at den bremses ift. den anden hvilket resulterer i at Legwayen drejer svagt. Det virkede som forventet og Legwayen blev noget nemmere at styre præcist med denne funktionalitet tilføjet.

Vi fik den idé at robotten også skulle kunne dytte når man på en Bluetooth-forbundet computer trykker på space. Der er ingen praktisk årsag hertil, men vi synes bare at det kunne være sjovt og det ville samtidig give os erfaring med Sound-klassen. Det krævede blot at vi tilføjede en key til keyEvent-listeneren i PC-programmet, lavede en værdi i bitmasken hertil og en fortolkning af den nye bitmaske i BTDriver-klassen. Vi havde ingen tidligere erfaring med at afspille lyd på NXT-brick'en, men det viste sig at være utrolig let. NXT'en kan afspille lyd som simple toner og som forskellige instrumenter, men kan også afspille wav-filer. Vi valgte at implementere lyden via en lydfil idet det giver den mest naturlige lyd og let kan skiftes. Det eneste man skal gøre for at afspille en wav-fil er at oprette et fil-objekt der peger på lyd-filen, kontrollere at filen kan læses, dvs. findes, og så sende den med som parameter til en metode i Sound-klassen som vist herunder:
File hornFile = new File("horn.wav");
if(hornFile.canRead())
    Sound.playSample(hornFile);

Det er i princippet ikke nødvendigt at kontrollere om filen findes, men idet man kan komme til at slette den eller der kan opstå en fejl i flash-hukommelsen, gør vi det alligevel for at få vores Legway så robust som muligt. Ligeledes kan en afbrudt Bluetooth-forbindelse som beskrevet ikke få Legwayen til at gå ned. Denne tankegang understøttes af  Pattie Maes [2] der postulerer at behavior-based agenter skal være robuste og kunne overleve selvom fejl opstår.

Vi prøvede med forskellige lydfiler og erfarede at man bliver nødt til at have lidt stilhed efter selve lyden i filen idet NXT'en af ukendte årsager ikke afspiller de sidste ca. 0.3 sekunder af lydfilen.

Efter at have fundet ud af hvor simpelt det var at arbjede med lyd på NXT'en, besluttede vi at tilføje lyde der indikerer når robotten er væltet og når en Bluetoothforbindelse til en computer oprettes og afbrydes. Når Legwayen vælter afspiller den et råb om hjælp, mere præcist "Medic". Når en Bluetoothforbindelse oprettes og lukkes, afspilles pre-definerede lydsekvenser vha. metoderne Sound.sequence() og Sound.sequendeUp().

En anden ny tilføjelse til Legwayen en ekstra behavior[3]. Denne behavior går ud på at hvis robotten kommer for tæt på et objekt, så bakker den væk og drejer ca. 180 grader hvorefter den igen er klar til at modtage kommandoer. Måde vi har lavet det på er at vi har oprettet en by behavior kaldet AvoidFront som indeholder de metoder en behavior skal have.
public AvoidFront(CtrlParam ctrl) {
    sonic = new UltrasonicSensor(SensorPort.S2);
    car = new Car(ctrl);
}
Behavioer'en gør brug af en ultralydsensor til at bestemme standen, og når afstanden er mindre end 25 cm tager den kontrol. Dette er som tidligere beskrevet Arbitratoren der sørger for at give den behavior med højest prioritet, retten til motorerne. I vores tilfælde har vi to forskellige behaviors: Styring via. Bluetooth og AvoidFront. Vi vælger at give AvoidFront den højeste prioritet, eftersom det ikke vil give meget mening at have en behavior der skal sørge for at Legwayen ikke kører ind et objekt og samtidigt kan blokeres af en anden behavior hvor man kan kører Legwayen ind i objektet. Dette giver vores prioritetsliste:
Behavior[] bArray = { b1, b2 };
hvor b1 er Bluetooth styring og b2 er AvoidFront. Action-metoden i AvoidFront, som er den der udføres når behavoiren har kontrol, starter med at stoppe robotten. Når Legwayen er stoppet, får den ordre på at køre baglæns i 500 millisekunder, hvorefter den igen stoppet. Når Legwayen igen er stoppet giver vi den en left kommando i 2 sekunder, hvilket sørger for at Legwayen roterer ca. 180 grader. Denne tid skal man nødt til at forsøge sig frem til, indtil man få et fornuftigt resultat. Når vi har roteret, kalder vi igen stop. Grunden til at vi bruger stop-kommandoen imellem hver bevægelseskommando, skyldes at vi dermed sikrer os at robotten står stille inden vi giver den en ny kommando. Dette giver en mere stabil kørsel.

For at indikere at den nye behavior AvoidFront træder i kraft, afspilles også en lyd her. Efter at have tilføjet denne lyd, opdagede vi at Legwayen var blevet mere interaktiv og langt mere livagtig end tidligere. Man føler næsten at den har sin egen personlighed når man hører den sige noget. Dette forstærkes helt sikkert også af dens fysiske konstruktion hvor ultralydsensoren ligner et hoved med to øjne.

Legway'en har omkring 160KB flash hukommelse tilgængelig når vi har formateret den. Med alle vores lyde og vores program uploaded, er der kun ca. 5KB ledig. Når vi forsøger at uploade en opdateret version af vores Legway-program, fejler den pga. pladsmangel, selvom der altså er plads. Løsningen hertil er at slette det oprindelige program inden det nye uploades.

Konklusion:
Vi har denne gang fået løst flere fejl der har været til irritation undervejs. Fejlene er blevet rettet og koden gjort mere overskuelig. I sidste blogindlæg beskrev vi hvordan vi ønskede at tilføje en connect og disconnet knap til vores Bluetooth controller på computeren. Dette er lykkes os dog med lidt besvær, eftersom fokus blev flyttet når man trykkede på knapperne. Problemet blev løst og programmet fungerer nu efter hensigten.

Endnu en tilføjelse til vores Legway er vores AvoidFront behavior, som sikrer at Legwayen ikke kører ind i objekter. Denne behavior var utroligt let at implementere når der blev gjort brug af behavior interfacet og voldte derfor ikke de store problemer. Koden virkede derfor også næsten efter hensigterne under første test, men nogle af de tider der bestemmer hvor meget der skal bakkes og drejes var en smule forkert og måtte justeres.

Vores mål herfra er at få ryddet mere op i koden og evt. få fjernet brugen af sinus hastigheder mht. robottens kørsel. Dette betyder at vi igen skal igennem processen med at finde frem til nogle PID controller værdier. Grunden til at vi godt kunne tænke os at fjerne sinus kurven fra hastigheden er at når man kører med Legwayen så accelererer den op hvorefter hastigheden dæmpes. Dette kunne være rart at man kunne holde en mere konstant fart, men dette kan komme til at påvirke Legwayens balanceringsevne. Ud over dette er målet at få gennemgået vores blogindlæg og rettet evt. fejl og mangler, forberede præsentationen samt skrevet den endelige konklusion.


Referencer:
  1. leJOS Threads, Listeners and Events tutorial, http://lejos.sourceforge.net/nxt/nxj/tutorial/ListenersAndEvents/Listeners_Events.htm
  2. P. MaesModeling Adaptive Autonomous Agents,
    Artificial Life Journal, C. Langton, ed., Vol. 1, No. 1 & 2, MIT Press, 1994.
  3. Sequential and reactive control strategies, Chapter 5, pp.190-233 of Fred G. Martin, Robotic Explorations: A Hands-on Introduction to Engineering, Prentice Hall,2001.

lørdag den 16. januar 2010

Projekt - 4

Dato:
16-01-2010

Antal timer brugt:
7 timer

Deltagende personer:
Kim Munk Petersen, Andreas Koefoed-Hansen og Tim Rasmussen

Målet:
  • Få oprettet Bluetooth-forbinelse mellem Legwayen og en computer.
  • Kunne styrre Legwayen, således den på kommandoer fra computeren kører frem og tilbage.
  • Evt. få Legwayen til at dreje.
Planen:
Planen for dagen er først og fremmest at få oprettet forbindelsen mellem Legwayen og en computer via Bluetooth. Til Robot Race'et udviklede Kim et program der gjorde at hans daværende gruppes robot kunne fjernstyres op ad Alishan train track. Vi ved derfor at det er muligt at fjernstyre en robot via Bluetooth og vi har altså også noget kode vi ved der virker. Denne kode bygger på eksemplet fra leJOS' communication tutorial [1], er meget lidt elegant og håndterer fx ikke tab af forbindelsen, så vi vil blot bruge den som skabelon til et nyt program. I første omgang vil vi blot få Legwayen til at kunne køre frem og tilbage, og senere også at kunne dreje. Når vi har fået oprettet forbindelse mellem computeren og Legwayen og vi er sikre på at de værdier NXT'en modtager stemmer overens med værdierne sendt fra computeren, vil vi arbejde videre med at få værdierne til at påvirke hvordan motorerne kører. Vi regner med at vi let kan tilføje funktionalitet således at vi kan dreje Legwayen efter vi har fået implementeret mulighed for at køre den frem og tilbage idet det blot er et spørgsmål om at give de to motorer forskellig power. At dreje robotten burde heller ikke bringe den ud af balance idet den har differential steering og drejer omkring sit tyngdepunkt.

Processen:
For at oprette forbindelse mellem computeren og Legwayen startede vi med at oprette de klasser der skal bruges for at kunne tilføje Bluetooth som en opførsel. Grunden til vi ville implementere det som en opførsel er at vi lettere kan udvide robottens funktionalitet med andre opførsler. Den fundne GELway-kode indeholder allerede Bluetooth funktionalitet, men da denne kun virker sammen med firmware 0.8 og ikke 0.85, samt har mangler som fx håndtering af mistet forbindelse, gør vi ikke brug af denne. I stedet benytter vi en klasse BTDriver, som implementer behavior-interfacet fra LeJOS. Denne klasse bruges på NXT'en til at omsætte en kommando til en fysisk handling. Klassen BTCommandReader står for selve kommunikationen med computeren. Grunden til at den hedder BTCommandReader at at den kun læser og altså ikke skriver tilbage til computeren. Vi mener at dette er tilstrækkeligt idet vi kun har brug for at sende kommandoer fra computeren til Legwayen, og ikke den anden vej. Der er således tale om envejskommunikation hvilket er praktisk anvendeligt idet Bluetooth er en connection-baseret protokol hvilket betyder at vi er garanteret at data der sendes også når frem medmindre forbindelsen afbrydes. I BTDriver klassen, har vi lavet en indre klasse ConnectionListener som "lytter" efter Bluetooth forbindelser. Så snart der er oprettet en Bluetooth-forbindelse, sendes objektet der repræsenterer denne videre til klassen BTCommandReader som så læser kommandoerne fra computeren. Herimens går ConnectionListener ind i en uendelig sleep hvorfra den kan vækkes vha. et interrupt fra BTCommandReader'en i tilfælde af at forbindelsen bliver afbrudt. Herefter starter ConnectionListener forfra med at vente på en forbindelse. Det betyder at vores Legway kan håndtere at forbindelser afbrydes og nye oprettes et vilkårligt antal gange. Konstruktøren i BTDriver ser ud som følgende:
public BTDriver(CtrlParam ctrl)
{
    car = new Car(ctrl);
    ConnectionListener cl = new ConnectionListener();
    cl.start();
}
Vi beskriver behavior endnu mere i sektionen behavior. 

ConnectionListener er som beskrevet den klasse der sørger for at forbindelser mellem computeren og enheden oprettes. Når der oprettes en instans af klassen, sættes tråden til at være en daemon tråd vha. setDaemon(). Grunden til at dette gøres, er for at sikre at tråden automatisk afsluttes når der ikke er andre user tråde kørende.

BTDriver implementerer som nævnt Behavior-interfacet i leJOS' subsumption framework. Det betyder at den skal have metoderne action(), supress() og takeControl(). Den tilkendegiver i takeControl-metoden at den gerne vil udføres, ved at returnere true hvis og kun hvis der er en aktiv Bluetooth-forbindelse hvilket giver mening idet den ellers ikke har nogle kommandoer at udføre. Dens action-metode udfører dens handling ved at hente den seneste kommando som NXT'en har modtaget. Er denne kommando anderledes end den forrige, udføres den. Bemærk at vi også har en kommando der svarer til "ingen handling" eller "stop" som bliver sendt når der ikke trykkes på nogen tast. Det betyder at man stadig kan udføre to ens egentlige kommandoer efter hinanden. Idéen er at Legwayen ikke skal begynde at udføre en kommando den allerede er ved at udføre. Suppress-metoden i BTDriver er tom siden Bluetooth opførslens action-metode terminerer hurtigt hvilket medfører at arbitratoren får kontrollen med det samme igen. Herved er der ingen grund til at stoppe udførslen af action-metoden selvom der findes en opførsel med højere prioritet.

Selvom vi bruger behaviors, er det vigtigt at nævne at vores BalanceControl, som er den klasse der sørger for at Legwayen holder balancen, ikke er en opførsel, men i stedet en tråd der hele tiden sørger for at Legwayen holder sig stående. Måden hvorpå man så får den til at køre frem og tilbage via Bluetooth er ved at ændre på tiltAngle parameteren, hvorved værdien Phi som bruges til at beregne error ændres. Dette betyder at Legwayen tror at den er ved at vælte forover hvorved den kører frem. Det modsatte er tilfældet baglæns.

- PC-programmet:
PC-programmet der skulle bruges til  styre robotten lavede vi som et andet projekt idet det skal compiles med den traditionelle Java-compiler, og ikke leJOS. Vi har sikret os at programmet kun opretter forbindelse til netop vores NXT-brick. Dette har vi gjort ved at navngive den "Legway" vha. nxjbrowse som er en del af leJOS-distributionen, og så sørge for at der kun ledes efter en NXT-brick med dette specifikke navn. Programmet bruger en bitmaske til at indikere hvilke knapper der er trykket ned. Vi registrerer en key-listener således at vi får kaldt en metode når en knap trykkes ned og en anden når den slippes igen. Dette er måden at gøre det på i Java idet det ikke umiddelbart er muligt på anden vis at kontrollere om en tast er trykket ned eller ej. Når der trykkes på en tast, OR'es bitstrengen med en hexadecimal konstant der angiver en bestemt tast og der AND'es med den inverse når tastes slippes igen. Vi har valgt de hexadecimale værdier som 0x01, 0x02, 0x04, 0x08 osv. således at bitmasken entydigt kan repræsentere at flere knapper er trykket ned. Når en tast trykkes ned eller slippes, sendes bitmasken til NXT-brick'en vha. den synkronierede metode sendKeys(). Grunden til at den er synkroniseret er at den kan tilgås af flere tråde på én gang og vi ønsker derfor at den udføres serielt. Vi kunne også have valgt at sende kommandoerne hele tiden, men dette ville bruge mere processorkraft og batteri på Legwayen pga. øget trafik hvorfor vi har valgt den anden løsning. Derudover mindsker vi også forsinkelsen ved at sende så snart der sker en ændring mht. tastetryk i stedet for hele tiden at sende den aktuelle tilstand. Herunder ses et snapshot af programmet. Det er blot et vindue med et tekstfelt der "fanger" tastetrykkene.



Vi havde nogle problemer med at få Bluetooth-kommunikationen til at virke. For det første brugte programmet fra Robot Race'et tovejskommunikation, dvs. både computeren og NXT'en sendte og modtog data. Vi lavede Legwayens program således at det kun læste data, men idet PC-programmet forventede respons ved et blokerende kald til readInt(), frøs kommunikationen fast. Dette rettede vi ved at fjerne kaldet til readInt() i PC-programmet således at det ikke længere ventede på respons fra NXT'en. For det andet var vi kommet til at bruge metoden write() til at sende bitmasken, i stedet for metoden writeInt(). Det betød at bitmasken blev sendt som en byte hvilket klart nok gjorde at NXT'en fortolkede de modtagne data forkert. Denne fejl var heldigvis også let at rette. Efter vi havde fået kommunikationen op at køre opstod et problem i form af en unchecked exception hvis vi ikke havde sendt kommandoer til NXT'en i ca. 15 sekunder idet forbindelsen fik timeout og derfor blev afbrudt. Måden vi løste det på var blot at få programmet til at sende bitmasken til NXT'en hvert femte sekund, udover også at sende når en tast blev trykket ned eller sluppet. Herved undgås timeout og det har ingen praktisk betydning at vi sender den samme kommando gentagne gange idet NXT'en som beskrevet ignorerer gentagne kommandoer. Vi havde også andre småproblemer som i sig selv ikke er interessante, men de krævede at vi lærte en ny teknik til at debugge programmer på NXT'en. NXT brick'en kastede en unhandled exception som blev vist på skærmen hvor årsagen var angivet som et klassenummer og et metodenummer. Disse numre sagde os intet, men vi fandt ud af at linkeren der linker leJOS-programmet udskriver disse numre og navnet på den tilhørende klasse. Derudfra kunne vi se at klasse 16 var en NullPointerException og metoden hvori den blev kastet. Herved blev fejl noget nemmere at lokalisere.


- Behavior:
Vi anvender en subsumption arkitektur, hvor vi har et lag 0 som er vores BalanceController, hvor på der er bygget flere forskellige lag ovenpå der alle kan påvirke vores BalanceController. Hver af disse ekstra lag, bliver beskrevet som opførsler. Hver af disse opførsler køres i tråd der har adgang til motoren og som også nævnt, så kører vores BalanceControler i en tråd der ikke kan suppreses af andre opførsler idet BalanceController ikke er en opførsel. Med andre ord, så kører BalanceControlleren hele tiden. Fordelen ved sådan en arkitektur er at vi kan blive ved med at tilføje flere lag til systemet uden at skulle ændre på de underliggende lag. Til at håndtere hvilke af de forskellige tråde der har ret til motorerne, bruger vi Arbitrator klassen fra leJOS biblioteket. Måden den fungerer på er ved at den tager en liste af forskellige behaviors, hvor den giver den behavior indsat sidst i listen højest prioritet.
Behavior[] bArray = { b1, b2 };
Arbitrator arby = new Arbitrator(bArray);
arby.start();
Koden viser hvordan man laver sin liste af opførsler som man så sender med til Abitratoren som derefter startes. Når Arbitratoren registrerer en opførsel der har højre prioritet end der kører, suppresser den den kørende og giver i stedet den anden lov at køre. Arbitratoren er opbygget af to dele som vi kalder executer og monitor. Monitor delen sørger for hele tiden at finde den opførsel med højest prioritet der ønsker at tage kontrol og derefter giver execute delen besked om dette. Execute sørger derefter for at starte den opførsel.

Som beskrevet så har vi en tom suppress metode i vores BTDriver klasse. Grunden til dette ligger i den måde Arbitratoren fungere på. Når Arbitratoren har fundet en tråd med højere prioritet en den kørende tråd, kalder den godt nok suppres på denne tråd, men hvis den tråd som i vores tilfælde alligevel ikke tilgår motoren ret langt tid af gangen, betyder det ikke noget at andre tråde venter denne tid.

Principperne anvendt i Arbitratoren ligner fuldstændig de principper anvendt af Fred. G. Martin[2], hvor hver behavior bliver tildelt en prioritet (i vores kode bliver prioriteten tildelt ud fra rækkefølgen af behaviors. Sidste element i listen har højest prioritet). Der er derefter Arbitratorens job at sørge for hele tiden af give den rigtige behavior retten til motorerne. Arbitratorens job kan sammenlignes med klassen Priority fra Martin.

Sammenligner man Fred. G. Martins[2] tilgang til hvordan håndteringen af de forskellige behaviors skal foregå med Rodney A. Brooks[3], så er der en væsentlig forskel. Martin anvender en central arbitrator til at bestemme hvilken af de forskellige opførsler der skal have adgang (selvfølgelig kun ud fra dem der ønsker at tage kontrol), mens Brooks i stedet giver opgaven til de enkelte opførsler. Dette løses ved at hver opførsel ved når de oprettes hvilken anden (underliggende) opførsel den skal suppresse. Nettop denne form for kontrol anvendte vi under øvelse 8, hvor eksemplet også er taget fra:
rd = new RandomDrive("Drive",1, null);
af = new AvoidFront ("Avoid",2,rd);
ps = new PlaySounds ("Play ",3,af);

Koden viser hvordan AvoidFront tager RandomDrive som parameter og PlaySound tager AvoidFront. Dette betyder at PlaySound er den opførsel med højest prioritet og når den kalder suppress() bliver alle underliggende lag suppresset eftersom metoden kaldes rekursivt ned igennem lagene.

Vi har valgt at gør brug af Fred Martins tilgangevinkel, eftersom vi ikke behøver at udføre noget egentligt suppress på vores opførsler. Grunden til dette er som beskrevet tidligere at vores opførsler alle afsluttes hurtigt og derfor ikke holder fast i retten til motorene. Vi har derfor blot brug for en enhed til at styre hver der skal have retten til motorene og dette tilbyder Martins metode.

Konklusion:
Konklusionen er at det lykkedes os at få Bluetooth til at virke. Udover at få robotten til at køre frem og tilbage, blev det også muligt at dreje den. Legwayen understøtter endnu ikke at man kan holde flere taster nede på én gang, selvom vores PC-program rent faktisk sender en bitmask der indikerer dette. Denne feature implementerer vi ved næste møde.
Derudover vil vi også tilføje to knapper til vores PC-program til at oprette og lukke forbindelsen til Legwayen således at vi ikke behøver at lukke programmet og starte det op igen hver gang vi vil lave en test.

Vi har overvejer meget hvordan vi skulle håndtere den subsumption arkitektur vi ønskede at anvende til de forskellige opførsler. Valget faldt på Martin, hvor vi har en central arbitrator der styre hvilken opførsel der skal have adgang til motorene.

Referencer:
  1. leJOS Tutorial: Communications: http://lejos.sourceforge.net/nxt/nxj/tutorial/Communications/Communications.htm
  2. Sequential and reactive control strategies, Chapter 5, pp.190-233 of Fred G. Martin, Robotic Explorations: A Hands-on Introduction to Engineering, Prentice Hall,2001. 
  3. Rodney Brooks, A robust layered control system for a mobile robot, IEEE Journal of Robotics and Automation, RA-2(1):14-23, 1986, MIT AI Memo 864, September 1985.

fredag den 15. januar 2010

Projekt - 3

Dato:
15-01-2010

Antal timer brugt:
5 timer

Deltagende personer:
Kim Munk Petersen, Andreas Koefoed-Hansen og Tim Rasmussen

Målet:
  1. Forstå hvordan robotten kan balancere.
  2. Forstå principperne i en PID-controller.
  3. Justere PID-controlleren så den passer til vores robot.
Planen:
Som vi beskrev i sidste blogindlæg, havde vi fundet noget kode som virkede rigtigt godt. Vi prøvede at bruge principperne i koden og lave vores egen gyroskopklasse og selv om den gav mere korrekte data, så fungerede den ikke sammen med PID controlleren. Koden indeholder en række parameter, hvoraf værdierne K_psi, K_phi, K_psidot og K_phidot er fundet ud fra en avanceret simulation i MathWorks Matlab og vi vil prøve at finde ud af hvordan disse har indflydelse på balanceevnen. Vi vil derfor forsøge at optimere værdierne Kp, Ki og Kd, således at robotten ikke overshooter så meget som nu.

Processen:

- Hvordan balancerer robotten?
Stevens kode benytter fire input, to fra gyroskopet og to fra motorerne. De to fra gyroskopet er robottens vinkel ift. lodret og dens vinkelhastighed. De to fra motorerne er TachoCount og RotationSpeed, altså også vinkel og vinkelahstighed. Brugen af flere sensorerne til at give en ønsket reaktion er beskrevet af Fred Martin som Sensor Fusion[1] der bruges for at give et mere komplet billede af situationen. Outputtet der læses fra gyroskopet er en vinkelhastighed. I gyroskopsensorklassen sættes vinklen fra starten til at være nul og opdateres løbende over tid ved at beregne ændringerne til vinklen ud fra vinkelhastighederne og addere disse til vinklen som beskrevet i første projekt-blogindlæg. Både vinkel og vinkelhastighed fra gyroskopet og input fra motorerne bliver benyttet til at beregne en error-værdi som senere bliver brugt i PID controlleren. De forskellige input er vægtet forskelligt ved at bruge de førnævte værdier: K_psi, K_phi, K_psidot og K_phidot. Vinklen fra gyroskopet har klart den højeste vægtning (ca. 50x større end fra motoren).

PID controlleren bruges til at beregne hvor meget power der skal gives til motorerne, dette er beskrevet i Fred Martin som Reactive Control[2] da motorerne reagerer direkte efter det input der kommer fra sensorerne. Det er dog ikke en ”ren” form for Reactive Control da der bliver set på fortiden i det både offsettet på gyroskopet bliver beregnet løbende og integral ledet i PID controlleren også ser på tidligere observationer, men disse led ikke spiller den store rolle i forhold til den endelige værdi.

- Generelt om PID controllers [3][4]:
En PID controller benytter tre forskellige parametre, Proportional (Kp), Integral (Ki) og Differential (Kd). Fælles for disse er at de tager udgangspunkt i en error værdi, der angiver hvor langt man er fra den ønskede tilstand.



- Proportional-regulering
Dette led i reguleringen består af en faktor der bare multipliceres på error. Reguleringen bliver foretaget på baggrund af størrelsen af den error der er, altså hvor langt man er fra den ønskede tilstand. Ulempen ved brug af kun denne simple form for regulering består i, at hvis man ønsker et meget hurtigt reagerende system, så er en stor konstant nødvendig. Dette kan det resultere i overshooting og efterfølgende oscillation.

- Integral-regulering
For at kunne kompensere for og lære af ændringer der sker over længere tid kan dette led benyttes. Den grundlæggende ide er, at tidligere error-værdier summeres. For at disse værdier ikke frit udvikler sig, er det ofte nødvendigt at indføre en form for dæmpning af værdien, eller indsætte en reel grænse for hvad den kan antage. Effekten af integral-leddet kan være at mindre fejl bliver udlignet, men også at systemet reagerer forholdsvis langsomt før netop en sum får en betydning.

- Differentiale-regulering
Ideen med dette led er at prøve at forudsige hvad eksempelvis den hastighed, hvormed systemet ændre sig, får af betydning. Dette kan bruges til at afdæmpe systemet ved meget pludselige ændringer og dermed bedre undgå overshooting. Dette led udregnes typisk ved at kigge på ændringen mellem de seneste to samples.


- PID controlleren i vores projekt:
Værdierne for PID controlleren var allerede sat i koden, så vores mål var at optimere disse og se hvad der skete når vi ændrede på dem. Vi valgte at gå systematisk frem og først ændre på Kp, derefter Ki og til sidst Kd. Herefter prøvede vi at ændre på flere på én gang, idet den optimale konfiguration ikke kan findes ved at skrue på en parameter af gangen. For at kunne se virkningen af ændringerne bedre valgte vi at logge de vinkler der blev udregnet af gyroskopklassen. Både værdierne fra getAngle() og getAngleVelocity() og blev gemt ved hjælp af vores egen datalogger-klasse, som bygger på den datalogger der var tilgængelig tidligere i kurset i forbindelse med Lydsensoren [5]. Den udleverede datalogger er kun i stand til at gemme heltal. Vi har udviddet den således at den også kan gemme alle de andre gængse datatyper, dvs. byte, short, long, float, double, char og String. Derudover kan vores datalogger også automatisk skrive timestamps på målingerne, tilføje forklarende overskrifter i toppen og inkrementelt forøge filnavnet med et tal således at tidligere log-filer ikke overskrives, men nye oprettes.

Ændringerne på PID controlleren kunne ses ved at plotte værdierne i et diagram, og i nogle tests kunne det også direkte ses på opførslen af robotten. Vi har taget nogle af resultaterne ud og vist dem herunder. Alle nedenstående grafer viser robottens udsving fra den blev startet og 10 sekunder frem.

Originale værdier:

P = 1.2, I = 0.25, D = 0.1

Dette er værdierne som Steven fandt frem til, grafen ser meget jævn ud og oscillation er hverken sigende eller faldende. Opførelsen af robotten afspejlede også dette da den stod stille og balancerede uden at bevæge sig meget.


P Increase:

P = 1.4, I = 0.25, D = 0.1

Vi prøvede i denne test at skrue lidt op for P for at se om det ville give en mere stabil balance, men som det ses ud fra grafen at der var en mere ujævn balancering og mere oscillation.


P Decrease:

P = 1.0, I = 0.25, D = 0.1

Denne graf blev dannet da vi prøvede at skrue ned for P hvilket resulterede i at der kom en del overshoot i starten og meget udsving, efterhånden blev balanceringen mere stabil.

I Decrease:


P = 1.2, I = 0.15, D = 0.1
Udsvingene på i vinkelen er ikke ret stor i begyndelsen, men fordi der ikke bliver taget meget hensyn til de tidligere målinger bygger der sig en fejl op og det resulterer i at udsvingene vokser med tiden.

I Increase:

P = 1.2, I = 0.35, D = 0.1
Overshooted i dette eksperiment var meget stort og på grafen kan det også ses hvordan vinkelen svinger meget frem og tilbage. Robottens balanceevne var ikke særlig god og den væltede kort efter at vi havde foretaget målingerne.

D Increase:


P = 1.2, I = 0.25, D = 0.2

Ved at ændre på D kom der ikke de store ændringer i starten men der blev gradvist overshootet lidt ad gangen indtil der var en meget ustabil balancering.


Koden med PID controlleren ligger i BalanceControl klassen og er som følgende:

double Psi = gyro.getAngle();
double PsiDot = gyro.getAngleVelocity();
           
// ctrl.tiltAngle() is used to drive the robot forwards and backwards
double Phi = motors.getAngle() - ctrl.tiltAngle();
double PhiDot = motors.getAngleVelocity();
// Proportional Error
double error = Psi * K_psi + Phi * K_phi + PsiDot * K_psidot + PhiDot * K_phidot;
// Integral Error
int_error += error;
// Derivative Error
double deriv_error = error - prev_error;
prev_error = error;
// Power sent to the motors
double pw = error * Kp + deriv_error * Kd + int_error * Ki;

Konklusion:
Efter at have eksperimenteret med de forskellige parametre i PID controlleren fandt vi ud af at de originale værdier var dem der virkede bedst. Det har dog ikke været spildt arbejde da vi ved at teste andre værdier har kunnet se at den teori der er bag PID controlleren stemmer nogenlunde overens med hvordan det virker i praksis. Vi har fået en bedre forståelse af hvordan en PID controller kan benyttes til at abstrahere fra fejlmålinger og derved give et bedre resultat.Vi vil de næste gange arbejde på at få oprettet en Bluetoothforbindelse mellem computeren og NXT'en og dermed få sendt input til robotten.

Referencer:
  1. Sensor Fusion.Chapter 5, pp. 207 of Fred G. Martin, Robotic Explorations: A Hands-on Introduction to Engineering, Prentice Hall, 2001.  
  2. Reactive Control.Chapter 5, pp. 192-193 of Fred G. Martin, Robotic Explorations: A Hands-on Introduction to Engineering, Prentice Hall, 2001. 
  3. PID Controller, http://en.wikipedia.org/wiki/PID_controller
  4. PID Control.Chapter 5, pp. 179-190 of Fred G. Martin, Robotic Explorations: A Hands-on Introduction to Engineering, Prentice Hall, 2001. 
  5. NXT Programming, Lesson 3, http://legolab.daimi.au.dk/DigitalControl.dir/NXT/Lesson3.dir/Lesson.html

mandag den 21. december 2009

Projekt - 2

Dato:
11-12-2009

Antal timer brugt:
7 timer

Deltagende personer:
Kim Munk Petersen, Andreas Koefoed-Hansen og Tim Rasmussen

Målet:
  • Få robotten til at balancere vha. vores gyroskop-sensor-klasse. 
Planen:
På baggrund af sidste blogindlæg, hvor vi havde store problemer med at gyroskopets værdier drifter, vil vi forsøge at finde frem til en løsning på dette. Vi ved at problemet blev løst af en gruppe fra tidligere år, så derfor vil vi forsøge at finde inspiration herfra. Når vi har løst drift-problemet, vil vi prøve at få robotten til at balancere vha. vores gyroskop klasse.

Processen:
For at kunne komme videre med projektet, blev vi nødt til at finde en løsning på gyroskopets drift-problem. En af grupperne fra forrige år havde prøvet at  løse problemet ved at løbende ændre offset'et ud fra de målte værdier fra gyroskopet. Offset'et beregnes således som et eksponentielt løbende gennemsnit [1] af det aktuelle offset og målte gyroskop-værdier. Formlen hertil er følgende, hvor alpha bestemmer vægten af de forskellige værdier.
offset = alpha * offset + (1-alpha) * sensorValue
Hvis værdien af alpha er omkring 1, vægtes de tidligere offsets højere end den målte værdi. Hvis den omvendt tæt på 0, vægtes den målte værdi højere end de tidligere offsets. Den målte værdi ændrer sig fra -533 til 391 ifølge vores tests fra tidligere [2]. Det betyder at en meget stor alpha-værdi gør at offset'et ikke ændres for meget, men alligevel at det langsomt flytter sig langsomt svarende til gyroskopets drift. For at dette virker, er antagelsen at der kommer lige meget udsving til begge sider. Denne antagelse burde holde idet at robotten netop skal holde sig oprejst og dermed skal en tiltning til den ene side ophæves af en ligeså stor tiltning til den anden side. Dette virkede udmærket i starten, men efter noget tid resulterede fejl-værdier i at den beregnede vinkel blev ukorrekt. Vi kunne ikke korrigere for denne fejl idet vinklen nogle gange driftede til den ene side og andre gange til den anden side.

På baggrund af ovenstående ledte vi efter en løsning på nettet. Vi fandt frem til en side hvor en kandidatstuderende, Steven Witzand, fra Australien havde bygget en "GELway" som hans speciale[5]. Navnet GELway kommer fra LEGO i omvendt orden uden O'et konkateneret med "way", inspireret af Segway. Koden til robotten er skrevet i leJOS, men er til version 0.80 så derfor var vi nødt til at ændre lidt på koden for at få den til at virke på vores NXT brick der bruger firmware version 0.85. Resultatet af dette var dog ikke særligt godt, da robotten satte begge motorer til at køre med fuld kraft fremad. Vi prøvede at skrive forskellige værdier ud for at se hvad problemet kunne være, men uden held. Først troede vi at det kunne være på grund af at forskellig firmware. Så vi hentede leJOS v. 0.80 og uploadede firmwaren til NXT´en. Dette havde heller ikke nogen indflydelse på opførslen af robotten.

Ved at prøve os frem med forskellige ting fandt vi frem til at gyro-sensoren skulle monteres omvendt, hvilket resulterede i at robotten i de første 3 sekunder prøvede at balancere, men herefter skiftede til at sætte fuld kraft på motorerne.
Vi overvejede hvad grunden til denne opførsel kunne være overvejede at det kunne være forskelle i design af robotten. Vi fandt en byggevejledning[3] til hans robot og så at han brugte 81,6 x 15 mm hjul hvor vi brugte 56 x 26 mm hjul. Vi udskiftede hjulene, men uden resultat. På billedet herunder til venstre er et billede af vores robot som vi byggede ved første projekt-gang. Vi besluttede os for at prøve at bygge vores robot om således at den blev magen til GELway'en. Den resulterende konstruktion ses på billedet herunder til højre.



Da vi testede den nye konstruktion, var den i stand til at balancere langt bedre end før. Det fysiske design af robotten viste sig altså at være meget betydningsfuldt. Vi konverterede igen alt koden i projektet til at passe til leJOS 0.85, men var denne gang mere påpasselige med at gøre det korrekt. Der var en del ting der skulle ændres, blandt andet at der som default ikke bliver givet strøm til en port hvis der ikke bliver oprettet en motor eller et sensor objekt der benytter porten. En anden ting der skulle ændres var at der på motorerne ikke findes en getActualSpeed()-metode i den nye firmware. Vi fandt ud af at metoden getRotationSpeed() virkede som en god erstatning. Efter disse ændringer blev foretaget og koden uploadet til NXT´en viste det sig stadig at virke. Vi tog tid på hvor længe robotten kunne balancere og det var op til 4 minutter før den kom for meget ud af balance og væltede.

Koden der er tilpasset version 0.85 kan ses på Google SVN vi har oprettet i forbindelse med kurset:
http://code.google.com/p/legolab/source/detail?r=19

- Ændring af mål:
På baggrund af det kode vi fandt på nettet og de resultater dette gav, ændrede vi vores mål til følgende. 
  • Forstå principperne i koden fundet på nettet, og på baggrund af dette konstrurere vores egen gyroskopklasse. 
  • Kontrollere at vores egen gyroskopklasse leverer fornuftige tal.
Vi prøvede at teste gyroskopklassen fra GELway for sig selv for at sammenligne resultaterne med den klasse vi selv havde lavet og det viste sig at den vinkel vi hentede ud, når vi gjorde brug af vores egen gyroskopklasse var noget mere nøjagtig end den vinkel vi fik når vi gjorde brug af den anden.
Desværre virker vores gyroskopklasse ikke særligt godt sammen med PID kontrolleren. Selv om værdierne er mere korrekte, så vælter robotten hurtigt.

- Fysiske overvejelser:
Som beskrevet fulgte vi samlevejledningen til GELwayen [3] da vi ombyggede vores robot. Selvom vi ikke fulgte den til punkt og prikke, var der kun tale om mindre forskelle. Bl.a. skulle der ifølge samlevejledningen bruges en EOPD-sensor (Electro Optical Proximity Decetion), men denne har vi ingen intentioner om at bruge, så det gjorde vi ikke. Efter at have samlet robotten, vurderede vi at dens design var utroligt solidt, i modsætning til vores initielle robot, hvilket er en god egenskab, både pga. at det giver robotten mere kontante bevægelser hvilket gør det nemmere at analysere og tune dens PID controller, men også at den kan holde til at vælte uden at falde fra hinanden. Desuden resonerede vi over følgende elementer i konstruktionen: den største forskel på vores initielle konstruktion og den nye er at robotten er blevet noget højere. Dette giver et større inerti-moment hvilket medfører en langsommere vinkelacceleration når robotten vælter. Det giver også en forøgelse af luftmodstanden idet vinkelfarten er højere jo længere væk fra omdrejningspunktet man kommer, men dette har dog ikke den store betydning i denne sammenhæng. Alt i alt har robotten altså længere tid til at korrigere hvilket selvsagt gør det lettere for den at holde balancen. Den nye konstruktion er også langt mere solid end den gamle. Den primære grund hertil, er de mange klodser der er brugt til at afstive den. Klart nok medfører det en øget vægt, men i forhold til NXT-brick'en og motorerne er dette negligibelt. Gyro'ens placering er for så vidt ubetydelig så længe den blot vender rigtigt. Dette skyldes at dens output ikke påvirkes af bevægelse, hvilket kunne mindskes ved at placere den tæt på robottens tyngdepunkt, men udelukkende af robottens hældning. Robottens hjul er placeret på ydersiden af robotten. Vi kunne også have placeret dem på indersiden, men det vil gøre robotten mere sidevejrs ustabil og besværliggøre eller umuliggøre placering af lyssensorer som vi måske får brug for til implementering af line-following. De store LEGO-hjul vi bruger gør at robotten kan bevæge sig hurtigt og dermed også korrigere for fejl hurtigere end med mindre hjul. Idet motorerne har intern gearing med en udveksling der giver meget trækkraft, er de på trods af de store hjul i stand til at give robotten en god accelerationsevne. Ultralydssensoren, som vi får brug for til implementering af en opførsel der får robotten til at undvige objekter foran den, er placeret over NXT-brick'en. Den er nødt til at være placeret højt eller pege opad for at undgå at pege ned i jorden når robotten læner sig forover eller kører op af en skråning. Idet vi regner med at placere lyssensorer under NXT-brick'en, er der ikke også plads til ultralydssensoren, og det er derfor plausibelt at placere den oven på robotten. NXT-brick'en er klart den dyreste komponent på robotten og den er derfor beskyttet af klodser både for og bag således at det ikke er den der rammes når robotten vælter. Ligeledes er gyro-sensoren beskyttet af en klods der absorberer noget af slaget når robotten vælter bagud.

Konklusion:
Vi fik endelig noget til at virke ved at benytte noget kode fundet op nettet fik vi en robot der kan balancere i et godt stykke tid. Planen er i første omgang at benytte Stevens kode og forstå hvordan den virker, og senere bygge vores egne udvidelser på. Senere kan vi lave vores egen gyroskopklasse og BalanceControl der virker sammen med de nye moduler.

Den første Legway vi byggede, var ud fra den samme samlevejledning som vi anvendte under den 4. øvelsesgang. Det viste sig at denne robot vi utrolig ustabil og vi byggede derfor en ny og mere solid en. Selv om samlevejledningen beskrev hvordan gyroskop- og ultralydsensoren kunne placeres på robotten, overvejede vi nøje hvor de var placeret mest optimalt. Efter nøje overvejelser besluttede vi at følge anvisningen til hvordan sensorerne kunne placeres. Samlevejledningen beskrev ikke noget om hvordan lyssensorerne til en senere line-following behavior kunne placeret. Det vigtige her, er at sensorerne skal sidde forholdsvis tæt på jorden for at kunne registrere lysændringer. Vi vender tilbage til dette senere hvis vi når at implementere behavioren.

Alt i alt kom vi frem til en solid robot hvor vi mener at de forskellige sensorer og hjul er placeret på den mest optimale måde.

Faste læsere