Thursday, April 25, 2013

Week 10

Dato:

25-04-2013

Varighed:

Fælles lab: 3 timer
Blog: 3 timer

Deltagere:

Steffen Høi
Nikolaj Mols Hansen
Martin Vang
Ulrik Sahl Lystbæk

Status

Vi har monteret en marker på vores LEGO-robot og eksperimenteret med NXT motorernes tacho-counter og navigationssystemet i leJOS.

Mål

Målet for denne laboratoriesession er at bruge NXT motorernes tacho-counter til at holde rede på positionen og retningen af LEGO-bilen med såkaldt differential drive, hvor to motorer bliver brugt uafhængigt af hinanden til at flytte og styre bilen, som vist på figur 11.

Plan

  • Konstruere en LEGO-robot med en marker monteret, så den kan markere LEGO-bilens bevægelse.
  • Udarbejdelse af opgaverne for "Week 10 - Navigation and Map Building".
  • Udarbejdelse af blogindlæg for denne laboratoriesession2.

Opgaver


Navigation


For at holde det simpelt valgte vi at udbygge vores LEGO-robot med muligheden for at holde en marker, som Maja Mataric3 beskriver. Til at holde markeren har vi fjernet sensoren forrest på LEGO-robotten og monteret to hjul, der kan holde fast om markeren.



For at kunne benytte koden sammen med vores SDK var vi nødsaget til at skifte klassen TachoNavigator til Navigator. Vi instantierede vores DifferentialPilot til Navigator med værdierne 5.5 cm for dæk-diameter og 17 cm for bredden af dækket.

Vores første kørsel resulterede i, at robotten kørte ud over kanten på tavlen, som vi havde robotten til at køre på. Derfor forkortede vi alle distancer i koden til en fjerdedel. Nedenstående video viser robotten på dens anden kørsel fra samme startpunkt.

Nedenunder ses slutresultatet af kørslen fra videoen.


Som det fremgår tydeligt, ligger de to streger ikke helt oven i hinanden. Dette kan skyldes unøjagtighed i, hvordan vi har placeret robotten imellem de to test kørsler. På billedet fremgår det, at forskellen imellem de to streger vokser, specielt når robotten roterer, som Brian Bagnall4 også pointerer mht. til hans Blightbot . For at teste denne påstand har vi opbygget en ny teststub i koden, hvor vi forsøger at rotere mest muligt og derefter sammenligne robottens endelige position.
               navigator.goTo(0, -1);
               navigator.goTo(0, 0);
               navigator.goTo(0, -1);
               navigator.goTo(0, 0);
               navigator.goTo(0, -1);
               navigator.goTo(0, 0);
               navigator.goTo(25f, 25f);
               Thread.sleep(12000);

Billedet viser to testkørsler med den nye teststub.


Den grønne marker er brugt til at lave referencepunkter for at placere robotten ens under hver testkørsel. Den blå og den røde marker ligger meget tæt på hinanden og afviger kun lidt. Afvigelsen vil dog være noget større på en større skala, men de forskellige tests viste at afvigelsen var meget ens, og derfor mener vi, at vores robot kunne klare opgaven ret præcist.

Navigation while avoiding objects

For at få LEGO-bilen til at undgå objekter foran den, kunne man montere en ultrasonic-sensor. Når man skal undgå objekter samtidig med at bruge Navigationen, kan man tjekke for objekter i en særskilt tråd. Det er ikke nødvendigt at starte en tråd til Navigationen, da den automatisk kører i en særskilt tråd. Tråden der bruges til at opdage objekter med kan stoppe Navigationen, når den ser et objekt og beregne en ny rute, som der skal navigeres efter.

Improved navigation

For at navigere korrekt beregnes der i Java Robotics Tutorials5 en fejl ud fra, hvor meget et hjul burde have kørt i forhold til, hvad det rent faktisk har kørt. Fejlen bruges til at udligne retningen ved at give mere styrke til motoren, der er bagud og mindre styrke til motoren som er foran. På denne måde vil robotten komme til at oscillere. Det er en proportional kontrol uden integral og derivate, så det vil være svært at mindske oscilleringen.

Thomas Hellstrom6 beskriver, hvorledes det er muligt at lave præcise svingninger. Dog kan formlen også bruges ift. at køre ligeud, da man så blot betragter afvigelsen fra ikke at have svinget. Eftersom denne model ikke bruger akkumulering af afvigelse til at korrigere for fejl, er den mere præcis. Når afvigelsen opstår, bliver der med det samme reguleret på hastigheden af hjulene. Dette betyder, at modellen faktisk forsøger at lave et estimat af hvilken kraft, der skal på motorerne for at lave et givet sving, og undervejs i svinget korrigerer hastigheden af hjulene, så svinget bliver korrekt. Altså, modellen benytter viden om, hvor man skal hen til at lave en vurdering af, hvordan der skal tilpasses, i stedet for at se på hvor vi er henne lige nu, ift. hvor vi burde være henne lige nu.

Vi har også taget et kig på hvordan Navigator og særligt TachoNavigator er implementeret i leJOS. Efter at have undersøgt det lidt nærmere kom vi frem til, at ArcAlgorithms7 bliver brugt til selve beregningen af en Path frem til en destination. Præcis hvad der sker i denne klasse er dog noget kaotisk, ikke mindst fordi der er talrige kode-kommentarer om ting, der enten ikke fungerer helt efter hensigten, ting der lige er blevet rettet, eller forslag til hvordan koden kan skrives om, så den kan læses af andre. Herunder er vores bud på hvad klassen gør:
Dette betyder, at når man vil fra punkt A til B, og vil forsøge at undgå en slingretur jf. den grønne linje, så benyttes en cirkel til at svinge ind på linjen ved punkt A. Derefter kørers der ligeud vha. en anden beregning, hvorefter en cirkel om punkt B forsøger at sikre retningen af bilen, når den rammer punkt B. Ift. hvordan disse paths rent faktisk laves, så ser det ud til, at der er eksperimenteret med kørsler indtil man har fundet 16 ”gode standard”-paths, som alle kan tilpasses bilens dimensioner og afstanden imellem A og B. Her kan det f.eks. nævnes at algoritmen specifikt ignorerer, om man gerne vil dreje til venstre eller højre, når den vælger en ”best path”, så vi må håbe, at de har valgt de 16 standard-paths på en meget snu måde. Da vi ikke kan få et ordentligt overblik over, hvad der rent faktisk sker i ArcAlgorithms, har vi haft svært ved at finde frem til, om vi kan forbedre navigatoren i leJOS vha. Java Robotics Tutorial eller Thomas Hellstroms noter.

Konklusion

Denne uge har vi eksperimenteret med at bruge NXT motorernes tacho-counter til at holde rede på positionen og retningen af LEGO-bilen med såkaldt differential drive. Vi har bygget vores LEGO-robot om, så den nu har en marker monteret, så vi kan følge bilens bevægelse. Vi har fået bilen til at flytte sig mellem forskellige positioner og set, at den er god til at måle distancer, men at den ikke roterer helt ens hver gang. Vi har desuden overvejet, hvordan man kan få LEGO-robotten til at undgå objekter samtidig med at bruge leJOS navigationssystemet. Desuden har vi kigget på de to artikler; Java Robotics Tutorial og Thomas Hellstrom, og vurderet at den model Thomas Hellstrom beskriver, er den mest præcise. Vi har også kigget på, hvordan leJOS i ArcAlgorithms opdaterer positionen og retningen, men vi har haft svært ved helt præcist at se, hvordan leJOS i ArcAlgorithms, har implementeret dette, så det har været vanskeligt for os at finde frem til, om vi kan bruge Thomas Hellstroms noter til at forbedre dette.
____________________________________________________________________________________________________________

1. http://legolab.cs.au.dk/DigitalControl.dir/NXT/pictures.dir/DiffCar.jpg
2. http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson9.dir/Lesson.html
3. Brian Bagnall, Maximum Lego NXTBuilding Robots with Java Brains, Chapter 12, Localization, p.297 - p.298.
4. Maja J Mataric, Integration of Representation Into Goal-Driven Behavior-Based Robots, in IEEE Transactions on Robotics and Automation, 8(3), Jun 1992, 304-312.
5. Java Robotics Tutorials, Enabling Your Robot to Keep Track of its Position.
6. Thomas Hellstrom, Foreward Kinematics for the Khepera Robot
7. https://sites.google.com/site/digikaison/ArcAlgorithms.java

Thursday, April 18, 2013

Week 9

Dato:

18-04-2013

Varighed:

Fælles lab: 7 timer
Blog: 4 timer

Deltagere:

Steffen Høi
Nikolaj Mols Hansen
Martin Vang
Ulrik Sahl Lystbæk

Status

Vi har bygget en sumo wrestling LEGO-robot med en løftemekanisme og programmeret den, så den kan kæmpe mod andre sumo wrestling LEGO-robotter i en sumo arena.

Mål

Målet for denne laboratoriesession er at bygge og programmere en sumo wrestling LEGO-robot, der kan kæmpe mod andre sumo wrestling LEGO-robotter i en sumo arena, som beskrevet på "figur 1"1.

Plan

  • Konstruere en sumo wrestling LEGO-robot ud fra de udleverede instruktioner fra "Week 9 - Agents and behaviour selection in agents, subsumption architecture"2.
  • Programmering af LEGO-robotten, så den kan kæmpe mod de andre sumo wrestling robotter i sumo arenaen.
  • Udarbejdelse af blogindlæg for denne laboratoriesession.

Opgaver


Konstruktion af sumo wrestling LEGO-robotten

Vi startede med at hente programmet Lego Digital Designer3, hvilket var nødvendigt for at, vi kunne læse instruktionerne for, hvordan man bygger de forskellige moduler, der til sammen udgør sumo wrestling LEGO-robotten. Nedenunder ses hvordan, LEGO-robotten til sidst kom til at se ud.




LEGO robot that exhibits several behaviors

Vi har uploadet det udleverede SumoBot-program4 til LEGO-robotten og afprøvet LEGO-robotten på sumo arenaen. Da vi observerede robotten i sumo arenaen, lagde vi mærke til at robotten havde 3 typer adfærd; Drive, Turn og Avoid, der blev skrevet på LCD-skærmen.  Sumo wrestler Lego-robotten startede med at køre lige ud og i den forbindelse blev der på LCD-skærmen skrevet 0 ved alle typer adfærd, hvilket betyder at ingen af de tre typer adfærd bliver undertrykt. Desuden blev f skrevet på displayet, hvilket betyder, at LEGO-robotten kører lige ud. Hvert 5. sekund blev denne adfærd undertrykt af Turn-adfærden, der fik LEGO-robotten til at dreje og på LCD-skærmen kom der et 1-tal ved Drive-adfærden, hvilket betyder, at denne bliver undertrykt af den nye adfærd, som LEGO-robotten får. Desuden blev skrevet t på LCD-skærmen, da robotten drejede. Når sumo wrestling LEGO-robotten kom for tæt på den hvide kant i sumo arenaen, blev Avoid-adfærden aktiveret, hvilket medførte, at der blev skrevet et 1-tal ved både Drive-adfærden samt Turn-adfærden, da den nye adfærd undertrykker dem begge. Desuden blev der på LCD-skærmen udskrevet b, f og s. På LCD-skærmen blev lysværdien for lyssensoren desuden også udskrevet.

Nedenstående video viser hvordan, robotten opførte sig samt hvilke værdier, der blev uskrevet på LCD-skærmen, i forbindelse med kørslen af programmet.


Behaviors as concurrent threads

Vi kiggede nu indeni klasserne for de tre forskellige typer adfærd for at identificere hvordan betingelsen, der udløser de forskellige adfærd, er implementeret, samt hvordan handlingerne for hver adfærd er implementeret. De tre implementerede adfærd; Drive, Turn og AvoidEdge har prioritering således, at AvoidEdge kan undertrykke Drive og Turn. Turn kan undertrykke Drive og Drive kan ikke undertrykke nogen. Drive kører derfor altid, medmindre den bliver undertrykt. Det vil sige, at der ikke er nogen betingelse, der får Drive til at køre, andet end at den ikke må være undertrykt af nogen anden adfærd. Når Drive udføres kører LEGO-robotten bare lige frem. Turn venter i 5 sekunder og prøver så at tage kontrol. Hvis ikke Turn undertrykkes af AvoidEdge, stopper den, venter 300 ms., drejer til en tilfældig vinkel og stopper. AvoidEdge bruger lyssensoren til at tjekke, om den ser hvid. Hvis den ser hvid, må det være den hvide kant, som omringer den sorte bane, og AvoidEdge bliver udført. AvoidEdge bakker først, venter 1 sekund, drejer til venstre, venter 800 ms., stopper og venter til sidst 500 ms.

Class Behavior

Trådene til alle adfærd er erklæret daemon tråde, så de ikke eksplicit behøver at blive afsluttet. Når alle andre end hovedtråden er daemon tråde, stopper JVM med at eksekvere tråde, når hovedtråden dør, hvilket er, hvad der sker i det udleverede program.

Klassen Behavior bruger SuppressNode til at undertrykke adfærd, som er på et lavere niveau end den selv. Når en Behavior instantieres, skal en reference til den adfærd, som ligger på niveauet lige under den Behavior, der instantieres, med i constructoren. Den første Behavior instantieres med null som den Behavior, der bruges til SuppressNode. Når en Behavior skal undertrykke de Behaviors, der er på lavere niveau kaldes suppress() på den, hvilken undertrykker den Behavior, der er på niveauet lige under den. Dette bliver den ved med, indtil den forsøger at undertrykke null. Dette betyder, at alle Behaviors helt ned til laveste niveau er undertrykt.

Add a behavior OverturnOpponent

Udfordringen ved denne opgave (at vælte modstanderen) lå dels i at lave en konstruktion, der faktisk var i stand til at vælte en modstander og dels i at programmere en adfærd, der var velfungerende i hierarkiet af de eksisterende adfærd. Vi har valgt ikke, at gøre meget ud af konstruktionen, da vi tidligt i indledende tests fandt frem til, at det ville være temmelig svært at lave en robot-arm, der var i stand til at vende en sumo wrestling LEGO-robot om på ryggen. Vi har i stedet lavet en mere simpel arm, der blot skal løfte modstanderen nok fra jorden til, at han ikke har trækkekraft med sit hjul. Derefter burde de andre adfærd være i stand til at få modstanderen skubbet ud over siden af ringen (Drive).

Efter nogle tests med robotten, blev det tydeligt, at den havde svært ved at finde en modstander uden hjælp. Første problem, der skulle løses, var derfor at lave en Search-adfærd, der kunne finde modstandere. Denne adfærd drejer LEGO-robotten om dens egen akse, imens ultralydssensoren ser efter om, der er noget inden for 35cm. Hvis der er, stopper drejningen. Denne adfærd har højere prioritet end Drive, men lavere end alle andre. Lykkes det ikke LEGO-robotten at se en modstander efter ca. 190 graders omdrejning, bliver adfærden undertrykt i 2,5 sekunder.
Denne adfærd sikrer at LEGO-robotten er i stand til at finde og køre ind i ting, hvilket er vigtigt for at vores løfteadfærd kan blive relevant.
Løfteadfærden (Flip) er lavet på en sådan måde, at den ikke blokerer. Den har internt en værdi, der holder styr på om armen er på vej op, eller ned. Derudover har den en række fortolkninger af hardware-målinger (tacho-omdrejninger og sensor-distance), der kan oversættes til følgende:

  1. Hvis armen er ”helt nede”, og der er noget inden for 16cm, så løft armen meget hurtigt.
  2. Hvis armen er ”helt oppe”, så sænk den hurtigt.
  3. Hvis armen er imellem ”helt oppe” og ”helt nede”, så fortsæt med at udføre den sidste bevægelse.
  4. Ellers, Stop arm-motoren og vent til du ser noget inden for 16cm.

Disse fire punkter, der er i prioriteret rækkefølge, sikrer at robotten aldrig låser eller bruger nævneværdig tid indeni en kritisk sektion af koden for Flip. Grunden til at dette er vigtigt er, at vi ikke kan være sikre på, hvornår en adfærd, der er højere i hierakiet vil undertrykke vores Flip. I vores tilfælde valgte vi kun at placere Avoid over Flip, og det kan naturligvis diskuteres hvor ofte, robotten er ved at vælte en modstander, imens den kører ud over kanten.

Vores adfærdshieraki er nu som følger, da vores Search erstatter Turn:

Avoid   3
Flip       2
Search  1
Drive    0

I forbindelse med AvoidEdge, har vi fundet en pudsig detalje, hvilket er, at den desværre nogle gange får robotten til at køre ud over kanten, i stedet for væk fra den. Dette sker konsekvent hver gang, robotten har en meget skæv vinkel på den hvide yderkant. Adfærden Avoid vil så bakke en smule (følge kanten tilbage) og lave et sving til venstre ud over kanten. Billedet nedenfor viser, hvordan indfaldsvinklen skal være med blå, hvor robotten bakker tilbage til med grøn, samt hvordan den er hardcoded til at svinge derefter. Det skal dog bemærkes, at vores robot er højre-venstre forvirret, hvilket betyder at billedet sandsynligvis er spejlvendt ift. alle andre robotter. Princippet er dog præcis det samme.
Vi har forsøgt at ændre denne adfærd en smule for at undgå dette i vores robot ved at dreje på stedet, i stedet for at lave et sving. Derudover er der pillet en smule i variabler i vores AvoidEdge, for at få vores konkrete robot til at være lidt hurtigere om at komme tilbage på banen.

Nedenstående video viser en sumo wrestling kamp mellem vores LEGO-robot og en anden gruppes LEGO-robot, efter at vores LEGO-robot har fået monteret en løftemekanisme og en modificeret udgave af SumoBot-programmet5 uploadet.


Konklusion

Denne uge har vi, ud fra de udleverede instruktioner, bygget en sumo wrestling LEGO-robot med en løftemekanisme og programmeret den, så den kan kæmpe mod andre sumo wrestling LEGO-robotter i en sumo arena. Vi har først observeret, hvordan det udleverede program udstyrer robotten med tre typer adfærd, samt hvilke omstændigheder, der gør at handlingen i adfærden bliver udført. Dernæst har vi set, hvordan SumoBot-programmet er programmeret med den reaktive strategi, som Fred Martin6 beskriver, samt erfaret at hver adfærd er sin egen tråd. Desuden har vi også set, at alle adfærd er erklæret daemon tråde, så de ikke eksplicit behøver at blive afsluttet, samt hvordan surpression-mekanismen virker. Til sidst har vi monteret en ekstra motor på LEGO-robotten og lavet en løftemekanisme, der skal forsøge at vælte modstanderens LEGO-robot, når denne kommer tæt nok på, samt implementeret den nye adfærd OverturnOpponent i SumoBot-programmet.

____________________________________________________________________________________________________________

1. http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson8.dir/moresumosonboard.jpg
2. http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson8.dir/Lesson.html
3. http://ldd.lego.com/
4. http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson8.dir/Classes.zip
5. SumoBot-program med adfærden OverturnOpponent
https://sites.google.com/site/digikaison/SumoBot.java
https://sites.google.com/site/digikaison/Car.java
https://sites.google.com/site/digikaison/Turn.java
https://sites.google.com/site/digikaison/SuppressNode.java
https://sites.google.com/site/digikaison/Search.java
https://sites.google.com/site/digikaison/Flip.java
https://sites.google.com/site/digikaison/Drive.java
https://sites.google.com/site/digikaison/Behavior.java
https://sites.google.com/site/digikaison/AvoidEdge.java
6. Fred G. Martin, Robotic Explorations: A Hands-on Introduction to Engineering, Prentice Hall, 2001.

Saturday, April 13, 2013

Week 8

Dato:

11-04-2013

Varighed:

Fælles lab: 40-45 timer
Blog: 5 timer

Deltagere:

Steffen Høi
Nikolaj Mols Hansen
Martin Vang
Ulrik Sahl Lystbæk

Status

Vi har bygget en LEGO-bil, der kan gennemføre "Alishan Train Track" på 23,386 sekunder ved en delvis sekventiel løsning med lyssensorer samt PID-Controller, hvor vi har fulgt reglerne fra "Week 8 - Robot Race"1.

Mål

Målet for denne laboratoriesession er at bygge en LEGO-bil, der gennemfører "Alishan Train Track" i den hurtigst mulige tid samt at følge reglerne fra "Week 8 - Robot Race"1.

Plan

  • Konstruere en LEGO-bil med formålet, at den skal kunne køre hurtigt.
  • Programmering af LEGO-bilen, så den kan gennemføre banen i den bedst mulige tid, og udnytte bilens fysiske konstruktion bedst muligt.
  • Udarbejdelse af blogindlæg for denne laboratoriesession.

Konstruktionen af robotten

Da vi skulle til at konstruere robotten var vores udgangspunkt, at vi gerne ville lave en konstruktion, der udnyttede motorernes kraft bedst muligt. Vi valgte derfor at lave et gearingssystem bestående af et lille og et stort tandhjul, hvilket fik hjulet til at dreje 3:1 ratio af normal hastighed grundet tandhjulenes størrelse i forhold til hinanden. For at gøre LEGO-bilen mere stabil, besluttede vi os for at lægge NXT Bricken ned, og vi monterede desuden to hjul på hver sin motor for at sikre, at bilen havde et bedre greb på banen samt, at den ikke ville skride så meget i svingene. Endvidere satte vi et fleksibelt hjul bagpå for at LEGO-bilen kunne holde balancen og bedre klare svingene. For at gøre motorerne mere kraftfulde skaffede vi os desuden nogle almindelige AA-batterier, hvilket gav en mærkbar forskel i forhold til at bruge det almindelige Lithium-ion-batteri.

Vi eksperimenterede kortvarigt med flere forskellige kombinationer af tandhjul for at finde en god ratio2 til banens hældning og bilens motor. En af de kombinationer der holdt længst i vores test-kørsler, var 5:1 som kan ses nedenfor. Den blev dog fravalgt, da vi ikke kunne få robotten til at følge linjen ordenligt ved meget over 3:1, og den ekstra gearing gjorde derfor blot vores robot mindre præcis i svingene.
Den endelige konstruktion af vores robot, som den ser ud ved "Sekventiel løsning med lyssensorer samt PID-Controller", ses på nedenstående billeder:


Løsningsforslag


Sekventiel løsning

Den umiddelbare måde vi tænkte at programmere vores LEGO-bil på var, så den kunne klare banen sekventielt. Ideen var at bruge klassen TachoMotor og tælle TachoCount. Her fik vi dog et problem allerede ved den første strækning på banen, da LEGO-bilen ikke ville køre lige, men hele tiden kørte skævt og dermed af banen. Dette fandt vi ud af skyldtes, at de to motorer ikke havde samme kraft, og vi blev derfor nødt til at finde en løsning, der kunne tage højde for dette, og rette bilen op, når denne kørte skævt.

Fjernstyret løsning

Efter forrige forsøg med den sekventielle løsning overvejede vi, hvad vi kunne gøre for at sikre, at bilen ikke kørte skævt. Dette førte os til en fjernstyret løsning af problemet. Vi lavede en GUI, hvor vi kunne indtaste værdierne til de to motorer, og dermed ændre bilens retning på kørselstid. Problemet ved denne løsning var, at kaldene nogle gange blev forsinket en del, formentlig pga. Bluetooth-forbindelsen. Af denne årsag kunne vi derfor ikke få LEGO-bilen til at reagere hurtigt nok.
Kommandoerne vi uploadede til robotten blev også gemt og udført sekventielt, hvilket betød at det var meget besværligt at reagere på pludselige udsving fra robottens side - den skulle først køre en ordre færdig før den ville tage imod en anden. Dette var det endelige argument for ikke at fjernstyre hele vejen, men vi overvejede, om det ville give mening at kunne lave små "tilpasninger" af kørslen vha. vores GUI, hvilket vi dog ikke fik afprøvet.

Sekventiel løsning med lyssensorer

Den næste løsning vi kom frem til var at montere 4 lyssensorer på robotten, så vi kunne korrigere vores bil efter den sorte linje. Dette gjorde, at vi kunne få robotten til at holde sig inden for banen og køre nogenlunde lige. For at lyssensorerne kunne være på bilen, så de sad langt fremme, blev vi nødt til at sætte det lille drejehjul forrest. Vi forsøgte derefter at lave et sving på det første plateau, fange den sorte linje på den modsatte side og dernæst køre ligeud opad den næste bakke. Grunden til at vi ville lave et sving, og ikke bare prøve at følge den sort linje rundt var, at vi mente, at det ville tage kortere tid at lave et sving, samt at det ville være svært at følge den sorte linje hele vejen, da den delte sig i to stier ved et sving. Da vi prøvede på at implementere svinget, opstod der dog et nyt problem, hvilket var, at bilen kom meget forskelligt ind i svinget. Derfor, var det næsten umuligt at forudsige nogenlunde præcist hvorhenne, bilen ville ramme linjen. For at sikre at bilen kom nogenlunde ensartet ind i svinget, blev vi altså nødt til at finde en måde hvorpå, vi kunne mindske oscilleringen af bilen. Denne løsning kan ses i det efterfølgende afsnit.
Vi arbejdede nu med lyssensorer, hvilket skabte en ny udfordring, der skulle tages højde for. Den måde banen stod på gjorde, at der kom sidelys ind, så der i løbet af dagen var meget forskellig lys på banen. Dette betød, at vi fik problemer med, at lyssensorerne opfattede LEGO-bilens egen skygge som sort, hvilket gjorde, at selvom vi kalibrerede ofte, havde vi stadig problemer med at hvid plus skygge blev opfattet som sort af robotten.
Vores løsning til skygge-problemet var at kalibrere én gang, for så at tilpasse sort/hvid værdierne manuelt for at se hvilke værdier, der fungerede bedst (typisk lige omkring de mest ekstreme forskelle på banen).

Sekventiel løsning med lyssensorer samt PID-Controller

Problemstillingen fra forrige afsnit vedrørende bilen, der oscilerede, besluttede vi at løse ved at lave en PID-Controller. Dette medførte, at vi i stedet for at bruge 4 lyssensorer, kunne nøjes med at bruge 3. Ideen bag PID-controlleren var at benytte forskellen fra hvid for de to yderste lyssensorer til samlet set at betegne error og bruge den midterste lyssensor til at nulstille integralet, hver gang den læste sort. Til at lave selve svinget brugte vi stadig TachoMotor klassen til at rotere bilen. Dette var dog en smule upræcist, og vi fandt senere ud af, at man ved at bruge klassen DifferentialPilot, kunne lave et mere præcist sving med robotten. Dette var dog ikke så ligetil, som først antaget, da vi fik et nyt problem med at motoren blev blokeret i forbindelse med et sving, og vi derfor ikke umiddelbart efter kunne kalde funktionerne på TachoMotoren. Dette problem fik vi dog løst ved at finde kildekoden3 inde på hjemmesiden for LEJOS og ændre i Stop-metoden (sætte motorerne til float efter alle stop) inde i klassen DifferentialPilot, så vi nu havde vores egen modificerede udgave af denne klasse. Dette viste sig også senere at komme os til nytte, da vi skulle lave nummer to sving, da DifferentialPilot, når vi skulle rotere, huskede rotationen fra forrige gang og foretog den umiddelbart efter, vi havde lavet den drejning, der var relevant for at klare svinget. Dette krævede, at vi lavede om i Reset-metoden i vores modificerede udgave af DifferentialPilot, så tacho-counterne rent faktisk blev nulstillet hver gang, vi skulle i gang med et nyt sving (jf. metodens java-doc).
Nedenfor ses en pseudo-kode beskrivelse af, hvad vi gør for at få vores PID-Controller til at fungere.


Endnu en udfordring ved at lave drejningen var at hjulets diameter og omdrejningsgrader ikke passede pga. vores gearingssystem, og det var derfor nødvendigt at tilpasse den til at tage højde for dette. Her forventede vi, at vores 3:1 gearing ville betyde, at vi kunne rotere 180/3 grader for at lave et 180 graders sving, men dette var ikke tilfældet. Det kan enten være, at vi har en bug et sted i koden4, eller at DifferentialPilot ikke helt håndterer gearede hjul så godt.
For at fange den sorte linje igen efter et sving, lavede vi vores egen line-catcher, hvilken var en del lettere nu, hvor vi nogenlunde præcist vidste, hvor robotten ville lande efter et sving. Til at lave en 180-grader stillestående rotation oppe på toppen af banen, brugte vi også DifferentialPilot. Nedad turen skulle justeres en del i svingene i forhold til turen opad, da bilen skred nedad bakke. Dette prøvede vi på at løse ved at sætte et ekstra hjul på hver motor, så der på hver side af bilen nu er 3 hjul, hvilket hjalp en smule på problemet, samt gjorde at bilen blev mere konsekvent i den måde, den klarede svingene på. En stor faktor der påvirkede, hvor hurtigt vores LEGO-bil kunne klare banen og nå frem til svingene viste sig desuden at være, hvor meget strøm, der var tilbage på batteriet, og vi fandt derfor ud, at det var en fordel at have to lithium-ion-batterier at skifte imellem, så vi havde nogenlunde samme power til vores motorer.

Resultater

Vi fik optaget tre videoer af vores LEGO-bil, hvor den gennemførte banen.

Kørsel 1

Tid: 32,009 sekunder

Nedenstående video blev taget første gang, det lykkedes vores LEGO-bil at gennemføre banen. Denne tid mente vi dog godt, at vi kunne forbedre ved at lave nogle optimeringer i koden.




Kørsel 2

Tid: 23,386 sekunder

Efter at have optimeret vores kode ved b.la. at sætte tiden ned for, hvor meget LEGO-bilen skulle sove i et sving og sætte power op på de lige strækninger samt forbedre vores line-catcher, så den fangede den sorte linje bedre, kunne vi skære godt 9 sekunder af vores tid i forhold til kørsel 1.

Kørsel 3

Tid: 23,417 sekunder

Denne kørsel var en anelse langsommere end kørsel 2, der er den bedste tid vores LEGO-bil har gennemført banen på.


Konklusion

Denne uge har vi bygget en LEGO-bil og programmeret den, så den kan gennemføre "Alishan Train Track" på 23,386 sekunder, som den hurtigste tid. Vi har været en del løsningsforslag igennem, som vi teoretisk set troede ville virke, men pga. de fysiske forhold, som at motorerne ikke trækker med samme kraft samt forsinkelse i Bluetooth, praktisk set ikke virker. Vi har desuden set, hvor lidt der skal til af forandring i den fysiske verden, såsom skygger samt den måde lyset falder på for at påvirke robotten samt sensorernes evne til at læse et givet resultat, som man forventer. Desuden har vi fundet ud af, at den løsning, vi har kunnet opnå det bedste resultat på, har været ved at lave en delvis sekventiel løsning, hvor vi bruger lyssensorer til at følge den sorte linje samt en PID-Controller for at LEGO-bilen ikke skal oscilere så meget, at den vil komme skævt ind i et sving. Det har desuden været en udfordring, at der har været så mange variabler, der kan ske at skulle ændres, hvis f.eks. kraften til motorerne falder, som følge af at batteriet mister styrke. Vi har desuden lært, hvordan DifferentialPilot klassen i LEJOS fungerer, samt hvad man skal være opmærksomme på, når man bruger denne sammen med TachoMotor klassen, og hvordan man kan ændre i den, så man får den funktionalitet, man i en specifik situation skal bruge.

____________________________________________________________________________________________________________

1. http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lesson7.dir/Lesson.html
2. http://sariel.pl/tools/ratios/
3. http://svn.code.sf.net/p/lejos/code/branches/lejos_nxj_0.9.1-x/pccomms/src/lejos/robotics/navigation/DifferentialPilot.java
4.
https://sites.google.com/site/digikaison/AlishanTrain.java
https://sites.google.com/site/digikaison/Car.java
https://sites.google.com/site/digikaison/DifferentialPilot2.java
https://sites.google.com/site/digikaison/BlackWhiteSensor.java
https://sites.google.com/site/digikaison/Turn.java
https://sites.google.com/site/digikaison/FollowLine.java
https://sites.google.com/site/digikaison/CatchLine.java