tirsdag den 12. juni 2012

Slutprojekt, del 7

Deltagere: Bjarke, Mikkel, Troels, Jesper
Tid: 9 timer



NB: Denne blog er resultatet af to dages arbejde. Der taget ikke højde for dette i beskrivelsen af det udførste arbejde.

Mål

Vores mål for dagen er at få Seekeren til at køre rundt i banen, baseret på instruktioner fra Hivemind'en. Disse instruktioner skal være baseret på den bane robotten opdager, mens den kører.

Plan

1. Rej fejl i kortet der tegnes på computeren. 
2. Ændre måden kortet tegnes på computeren, således at det vender korrekt i forhold til robotternes fysiske placering. 
3. Implementer en test-stub der skal gøre debugging af server softwaren lettere.  
4. Få robotten til at følge anvisninger fra computeren.

5. Udvis test-stub for at håndtere problemer fundet i punkt 4. 
6.Tilføj PID-kontrol som beskrevet i [1], dog kun med P.
7. Få farvesensoren til pålideligt at reagere på rød, blå og grøn.

Resultater

1.
Der var et problem med nogle tiles der ikke blev lagt ind i tiles[ ][ ] double arrayet. Det gjorde at de ikke blev repræsenteret i kortet da det kun tegnede kanter imellem to tiles der eksisterer i arrayet. Dette blev fikset, således at hver gang en edge oprettes, oprettes begge tiles den spænder imellem også. 

Udover dette oplevede vi også, at der blev markeret edges på kortet, der ikke passede med Seekerens placering. Da en edge repræsenteres som en hash værdi, der skabes vha. koordinater for de to tiles denne spænder mellem, mistænkte vi vores hash funktion for ikke at lave en unik mapping mellem koordinater og de tilhørende hash værdier. Et sådant problem kunne skabe kollisions, hvilket kunne give de problemer vi oplevede.
Derfor omskrev vi hash funktionen til at være baseret på primtal. Ved at lave en liste med de første 400 primtal (400 da den maksimale størrelse på banen var 20x20) kan hvert tile bindes til et unikt primtal og kanter mellem to tiles kan gemmes som produktet af de to primtal. Derved undgås enhver form for kollision.


Bemærk: Følgende er tilføjet d. 20/06/2012


Den anvendte hash funktionen så således ud: 


( (tile1.x + tile2.x) ^ 37) * (tile1.y + tile2.y) 


Det essentielle ved funktionen er, at der ikke må opstå kollisioner mellem hash værdier for forskellige tiles, der ligger op ad hinanden (Enten x eller y værdierne for de to tiles varierer med plus eller minus én). Dette kan ikke give kollisioner i hash værdien, så længe vi holder os inden for disse restriktioner. 
Dette var desværre ikke blevet kommunikeret klart ud, da kortet skulle laves, hvorfor måden den indtegner kendte kanter på, er baseret på at gennemløb af alle tiles i banen, for hvert eksisterende tile. Derved blev vores krav om, kun at hashe umiddelbare naboer ikke overholdt, og der opstod kollisioner. Dette resulterede i indtegninger af kanter på mere eller mindre tilfældige positioner. Vi antog, som beskrevet i punkt 1 ovenfor, at dette problem var resultatet af dårlig hash funktion, men dette har nu vist sig ikke udelukkende at være tilfældet. Dog er den nye implementation mere robust og med sikkerhed pænere end den tidligere.

2. 

Vores kort fungerede efter rettelsen fra punkt 1. Desværre var repræsentationen af verden ikke let at overskue for tilskuere, idet vores nord-syd akse vendte forkert. Dette skyldes at kortet vises i et canvas. Dette har, i modsætning til et almindeligt koordinatsystem, punktet (0,0) i øverste venstre hjørne. Udgangspunktet, da vi programmerede Hivemind'en, var at (0,0) lå i nederste venstre hjørne.
Problemet blev løst ved at ændre placeringen af alle objekter på det tegnede kort. Da vores maksimale størrelse af banen var 20x20, kunne vi tilføje denne ændring ved hjælp af følgende funktion, beskrevet i pseudo kode:


y-coordinate = (y-coordinate * (-1)) + 19;


Dette tilføjede en fejl, der betød at tiles der havde et y-koordinat mindre end vores garager (der ligger i (10,10) og (11,10)) ikke blev indtegnet, men grundet den måde den fysiske bane var konstrueret på, ville dette ikke give problemer og derfor blev denne nedprioriteret. 


Det computer-tegnede kort, efter ændringen.




3. 
Som beskrevet i forrige blog post, besluttede vi at implementere en test-stub der skulle erstatte robotten i robot-server kommunikationen. Dette fandt vi nødvendigt, idet vi havde problemer med softwaren på både robotten og serveren. Derfor ville vi fjerne den ene af disse variable, for at udføre en mere målrettet debugging. Løsningen blev, at vi implementerede en stub udgave af sender og modtager klasserne og lod dem implementere hhv. ISender og IReceiver interfacene. 
Implementationen af sender-stubben kaldte metoder direkte i receiver-stubben, hvorved vi efterlignede kommunikation med robotton, uden at vores resterende implementationer blev påvirket af dette. På den måde kunne vi i højere grad styre kommunikationen og få mere målrettet debugging. Derved fangede vi flere mindre logik fejl der plagede vores system. Selve implementationen var simpel og sparede os meget tid.

4. 

Efter at have rettet flere fejl, hvoraf enkelte var kritiske for en korrekt gennemsøgning af banen, fik vi robotten til at søge som forventet. Den finder vejkryds og fortsætter ud af kanter, på en måde der tilsvarer det resultat vi havde planlagt. Desværre er der stadig enkelte problemer der viser sig når robotten finder enden på en kant eller en hule. Disse blev ikke testet af vores test-stub, hvilket dog ville være muligt ved simple tilføjelser. Udover dette gav farvesensorerne fortsat problemer. De læser grønt og blåt korrekt når underlaget har disse farver, men genkender desværre også farverne når robotten blot følger en sort sti. 
Udvidelsen af test-stubben samt håndteringen af huler og blinde veje beskrives i næste punkt. Forbedringerne af farvesensoren beskrives i punkt 7.

5. 

Udvidelsen af test-stubben var simpel. Vi lavede en begrænsning på den bane vores test-stub efterlignede, hvorved vi kunne teste blinde edges. Derudover lagde vi en hule ind, så denne også kunne testes. 
Problemerne noteret i punkt 4 var, at vi under programmeringen af Hivemind'en havde antaget, at robotten ville køre baglæns tilbage til forrige tile, når den fandt enten en blind edge eller en hule. Dette vidste sig desværre ikke at være muligt i praksis, hvorfor vi måtte tage en anden tilgang. Vi havde en eksisterende funktion til rådighed, der tillod robotten at lave en u-vending og ved at anvende denne, kunne vi samtidig løse enkelte andre problemer der havde generet os.
Indførelsen af blinde veje i test-stubben gav også mulighed for at teste, hvorledes robotten ville afsøge en hel verden og derved om logikken omkring dette holdte vand. Som resultat af dette rettede vi enkelte logik fejl i vores algoritme for korteste vej mellem to tiles. Derudover blev det åbenlyst, at når banen blev tilstrækkelig stor, ville tiden for at finde den korteste vej blive forøget markant. Dette løste vi ved løbende at opdatere længden på den korteste sti vi havde fundet, mens algoritmen rekursivt afsøgte alle mulige veje. Dette tillod tidlig terminering af mange grene.

6. 

Det lykkedes os at implementere en PID kontrol, med kun P. Robotten sporede pænere ind på linjen efter noget tid, men hvis den tabte linjen havde den svært ved at spore ind igen. Grundet banens opbygning vil robotterne kun køre meget korte stykker ad gangen og skal være ret gode til at spore ind på stregen igen, især når der drejes i et kryds. Derfor valgte vi at gå tilbage til den helt simple on-off kontrol. Denne metode oscillerer mere, men er effektiv til at spore ind på stregen.
Vi kunne have valgt at at udvide vores PID kontrol med både I og D, men dette vil være en kæmpe arbejdsbyrde at få tunet og tilpasset så det kører lige så godt som den simple løsning og vores fokus var fortsat på farvesensoren, hvilket beskrives i næste punkt.

P kode:  
lightValue = bw.getLightValue();
error = lightValue - offset;
turn = kP * error;
turn = turn / 100;
powerA = Math.abs(minPower + turn);
powerB = Math.abs(minPower - turn);
Car.forward(powerA, powerB);  


7. 
Der har været en del iterationer af dette punkt. Først prøvede vi at anvende forskellige farver, men det viste sig at alle farverne kan blive opdaget når de ikke er der. Rød er her en undtagelse, men desværre opdager robotten ikke et rødt underlag helt pålideligt. Herefter prøvede vi at skærme sensoren af, så det kun var dens eget floodlight der oplyste dens synsfelt. Dette hjalp lidt, men den så stadig blå og grøn tilfældigt.
Vores endelige løsning blev, at man skal lave mere end én måling af farverne før robotten reagerer på det. Det viste sig dog, at det stadig ikke var helt nok for at undgå blå, da denne farve ofte blev læst mens robotten fulgte en sort streg. Så vi tilpassede den således at rød og grøn blev opdaget hurtigere end blå. Dette hjalp, mens den stadigt opdagede blå pålideligt.


Vores colorsensor kode fungerer nu på en sådan måde, at vi har tre color counters. Disse tæller op hvor meget rød, grøn og blå vi har set. Hver farve bliver talt op mindst to hver gang vi ser farven, samtidig bliver alle farver, inklusiv farven selv, talt ned. Samtidig tæller vi alle farverne to ned når vi ikke ser nogen af de tre farver. Denne metode sikrer, at vi ikke husker "gamle opdagelser" og at vi samtidig reagere på farverne når vi ser disse i et længere stykke tid. Denne løsning kan samtidig justeres så hver farve bliver talt forskelligt op, alt efter hvor tit vi læser fejl på farven. Rød læser vi stort set aldrig fejl på, derfor bliver den talt hurtigere op end blå, som vi tit læser fejl på.
Alle farverne har i den nuværende implementation den samme grænse, men dette kan ændres for an nuancere sensorerne endnu mere [2].
 


Konklusion
Efter dagens mange rettelser i Hivemind'en er vi klar til igen at teste på robotten. Hivemind'en opfører sig som forventet når den anvender test-stubbene og farvesensoren er nu mere pålidelig end ved sidste test.
Flere af problemerne har været et direkte resultat af dårlig kommunikation internt i gruppen, delvist fordi vi har arbejdet meget separat på robotten og Hivemind'en.
Målet for næste møde bliver at teste systemet på den fysiske robot og forhåbentlig få en fuld gennemkørsel.

Referencer

1. http://www.inpharmix.com/jps/PID_Controller_For_Lego_Mindstorms_Robots.html
2. https://dl.dropbox.com/u/357278/Lego/TeddyMiners/miner/main/AbstractMiner.java

Ingen kommentarer:

Send en kommentar