Med Asbjørn, Christer og Jesper

fredag den 30. november 2007

Oplæg til projekt

Tidsforbrug: 3 timer.
Deltagere: Asbjørn og Christer
(Jesper er på Island i denne uge)

Disse er opstillet i prioriteret rækkefølge. Vi vil helst arbejde med den øverste (rubiks kube løseren). Fælles for dem alle er, at de benytter en eller flere farvesensorer (NXT Color Sensor). Den findes ikke i det udleverede NXT sæt og skal derfor først indkøbes hos LEGO.
Som første del vil vi undersøge egenskaberne ved en sådan sensor. Vi kan se i lejOS APIen at den er understøttet og at man kan få en RGB-værdi ud. Indkøb af en eller flere af disse sensorer mener vi kan retfærdiggøres af, at vi undersøger og beskriver egenskaberne set i forhold til den ordinære lyssensor. Først efter en sådan undersøgelse vil vi tage den i anvendelse. Så vil farvesensorerne eventuelt kunne anvendes i senere udgaver af kurset.

  1. Robot der med en farvesensorer indscanner siderne på en rubiks kube og ud fra denne måling løser den.
  2. Robot der på et gulv med legoklodser søger rundt og "spiser" klodser med en bestemt farve.
  3. Robotter der kører rundt mellem hinanden og kan skelne mellem ven og fjende baseret på hinandens farver.

Projekt 1 - Robot der løser en rubiks kube. (Primært valg)
Hardware/software platfom:
Vi skal bruge en NXT, 3 motorer og 2 stk NXT Color Sensor. Motorer, sensorer og software vil blive beskrevet i de følgende afsnit.

Motorer:
Den mekaniske del skal kunne:
  1. Rotere terningen (1 motor) ved at terningen hviler i en slæde der går 1/3 op på den
  2. Holde terningen fast mens den nederste 1/3 roterer (1 motor), samt at skubbe terningen på plads når den roteres om en anden akse (se næste punkt)
  3. Rotere terningen i en dimension mere (1 motor).


Med disse tre funktioner kan vi rotere og manipulere terningen som vi vil, da alle handlinger kan reduceres til en serie af disse.

Sensorer:
Før man kan løse en rubiks kube, skal man kende farverne på alle felterne. Dette kan løses på to måder:
  1. Vi kan taste kubens farver ind på forhånd.
  2. Robotten kan undersøge det selv med farvesensorer.
Da det mest er i kursets ånd med selvstændighed, vil den anden mulighed være at foretrække. Vi har hos LEGO fundet en farvesensor (NXT Color Sensor), der vil kunne bruges til dette formål.
Angående dette projekt er vi kommet frem til at 2 sensorer vil kunne gøre det uden at vi skal montere flere motorer. Med de eksisterende motorer vil vi kunne skubbe disse hen over siderne på kuben og "scanne" to rækker felter ad gangen. Ved at rotere kuben kan vi således komme hele vejen omkring. Med kun én enkelt sensor skal vi bruge en del ekstra mekanik for at kunne have komplet dækning, da vi ikke umiddelbart kan nå både centrum og hjørnerne på en side på denne måde uden ekstra mobilitet.
Sensorerne er markeret med "S" på billedet.

Software:
Vi skal dels kunne:
  • Løse en rubiks kube algoritmisk. Dette er et velkendt problem, som sagtens kan implementeres i lejOS java.
  • Styre motorerne, så de manipulerer kuben som ønsket.
  • Scanne overfladerne på kuben og omsætte resultatet til et kort over den. Ud fra dette kort og de to ovenstående punkter, kan vi løse kuben.
Største udfordring:
I dette projekt vil den største udfordring være at scanne overfladen på kuben. Her vil vi komme til at arbejde med en ny type sensor og mekanik der er stabilt nok til denne anvendelse. En ekstra udfordring ville være at understøtte kuber med et på forhånd ukendt farveskema. Her vil programmet være nødt til at tage alle målingerne (6 sider á 9 målinger) og forsøge at placere dem i 6 clusters i et tredimensionelt RGB-rum. Hvis dette kan lykkes, kan man udlede hvilke felter der skal ende op på samme side af kuben.

Hvad vi regner med at nå frem til:
En mekanisme der automatisk undersøger siderne på en rubiks kube og derefter mekanisk manipulerer den til en løsning.

Opdeling i delmål:
  1. Test af NXT Color Sensor.
  2. Manupulation af kuben med motorer
  3. Indscanning af kube
  4. Selvstændig løsning af rubiks kube i NXT'en.
  5. Skelne imellem farver der ikke er fastlagt ved compiletime.

De alternative projekter:

Projekt 2 - Køre på et gulv med legoklodser hvor robotten søger rundt og "spiser" klodser med en bestemt farve.

Hardware/software platform:

En NXT, 3+ motorer (og muligvis en motor multiplexer) og en NXT Color Sensor.

Motorer:
Vi skal dels:
  • Kunne navigere rundt på en todimensionel flade (2 motorer).
  • Kunne "spise" en klods med en specifik farve op fra gulvet (ukendt antal motorer).
Sensorer:
Der skal bare være en NXT Color Sensor til at måle farven på hver klods.

Software:
Softwaren skal kunne:
  • Måle og skelne mellem et antal farver.
  • Køre rundt og lede efter klodser på en mere eller mindre udtømmende måde.
  • Samle en klods op fra gulvet.
Største udfordring:
Vi har ikke overblik over hvordan man nemmest (dvs med mindste antal motorer) samler en legoklods op fra gulvet. Derfor vil dette være den største udfordring.

Hvad vi ville regne med at nå frem til:
Såfremt det kan lykkes at samle en klods op fra gulvet, ser vi ikke andre hindringer mod at opnå en komplet løsning.

Projekt 3 - Robotter der kører rundt mellem hinanden og kan skelne mellem ven og fjende baseret på hinandens farver.

Hardware/software platform:
Pr robot vil vi have brug for: en NXT, to motorer og en NXT Color Sensor.

Motorer:
Motorerne skal køre robotten rundt på samme måde som vi har eksperimenteret med til de almindelige øvelsesgange.

Sensorer:
I hver robot skal vi have en farvesensor, så vi kan skelne mellem ven og fjende.

Software:
Softwaren skal kunne ændre robottens adfærd baseret på hvad den ser.

Største udfordring:
Robotterne skal formentlig meget tæt på hinanden før man kan lave en præcis farvemåling. Den præcise adfærd omkring denne måling vil være den største udfordring i et projekt som dette.

Hvad vi ville regne med at nå frem til:
Såfremt vi kunne få robotterne til at skelne mellem hinanden på en pålidelig måde, ser vi ingen grund til ikke at kunne opnå komplet funktionalitet.

fredag den 23. november 2007

NXT programmering, lesson 10

Tidsforbrug: 3 timer. Deltagere: Asbjørn, Christer og Jesper.
I dag vil vi undersøge hvordan en adfærdsbaseret arkitektur er implementeret i leJOS NXJs subsumption API.

Vi vil gennemgå disse skridt et for et:
  • BumperCar
    • Ombygge bilen ved at tilføje touch sensor.
    • Hvad sker der hvis man holder touch sensoren inde?
    • Tilføj 3. adfærd.
  • En ny arbitrator.
  • Motivation functions.
  • Resten af tiden.
    • Da Jesper er bortrejst i næste uge, påbegynder vi projekt-brainstorm nu.
BumperCar.
Tidsforbrug: 1 time.

Vi hentede BumperCar koden, tilføjede en touch sensor på bilen og kørte koden. I første omgang kørte bilen baglæns, da vores nuværende konstruktion har motorerne vendt modsat.

Hvis man holder touch sensoren inde, stopper bilen helt. HitWall udføres én gang og bilen venter da på at sensoren slippes igen. På grund af arbitratoren kan den ikke komme videre før sensoren slippes. Hvis takeControl i DriveForward kaldes mens HitWall er aktiv, busy-waiter den indtil sidstnævnte bliver inaktiv.

Sidste delopgave her var, at implementere en tredje adfærd med højeste prioritet. Vi valgte en musikafspiller som foreslået i opgaven. Hver gang den spiller, trumfer den alle de andre adfærdsmønstre. Det vil sige, at når vi holder touch sensoren inde, vil musikadfærden før eller siden komme og undertrykke HitWall, hvorefter robotten ikke behøver vente på at sensoren slippes.
Det er ikke altid at arbitratoren virker som den bør. Det kan godt ske at HitWall fortsætter med at kontrollere motorerne. Det vil sige, at en lav-prioritets adfærd godt kan undgå at blive undertrykt af en høj-prioritetsadfærd.

En ny arbitrator.
Tidsforbrug: 1/2 time.

Vi hentede og compilede den nye arbitrator. Denne gang ser vi en ny adfærd ved HitWall. Nu gentager den undvigemanøvren indtil touch sensoren slippes. Til gengæld virkede vores musikafspiller ikke mere. Den kom aldrig "til fadet" her på trods af sin høje prioritet.

Motivation functions.
Tidsforbrug: 1/2 time.

Man kunne ændre takeControl til at returnere en motivationsværdi. I tilfældet med touch sensoren og HitWall kunne den returnere en værdi når den trykkes og eksempelvis 0 når den ikke trykkes. Jo højere, jo mere motivation. Arbitratoren kunne da bestemme adfærd ud fra disse værdier. Med andre ord kunne man udskifte de statiske prioriteter med dynamiske prioriteter bestemt ud fra sensor input.
Dette svarer cirka til idéen i Thiemo Krinks motivation functions. Touch sensorens input mappes af en funktion til en motivationsvariabel for berøring, som decision-makeren aktiverer et behavior-pattern ud fra. Den adfærd der er mest motivation for, HitWall, udføres og robotten undviger ved at ændre retningen på motorerne.

Resten af tiden.
Tidsforbrug: 1 time.

Da Jesper er på Island i næste uge, besluttede vi at påbegynde projekt-brainstorm nu.

fredag den 16. november 2007

NXT programmering, lesson 9

Tidsforbrug: 3 timer.
Deltagere: Asbjørn og Christer.
(Jesper er til programmeringskonkurrence i Holland.)

Målet med dagens session er, at eksperimentere med navigation ud fra motorernes tacho tællere med og uden forhindringer på banen.

Vi vil gennemgå disse skridt et for et:
  • Bygge bilen i noten og få den udleverede kode til at virke.
    • Vores egen bil havde et uheldigt tyngdepunkt og notens bil virkede enklere.
  • Teste præcision af Blightbot koden.
    • Testen udføres et antal gange.
    • Vi ændrer ruten i koden for at teste præcision i sving.
  • Navigation uden om forhindringer.
Bygge bilen i noten og få den udleverede kode til at virke.
Tidsforbrug: 30 min.

Som sagt var vores gamle design uegnet. Det var for stort og klodset og havde et dårligt tyngdepunkt (højt og forskudt). Byggeinstruktionerne i noten var rimeligt lette at følge i kraft af bilens simple opbygning. Der var kun enkelte problemer hvor kvaliteten af fotokopieringen gjorde det svært at se præcis hvor tingene skulle monteres. En mere kompliceret konstruktion ville have været vanskelig at bygge på denne måde.

Den udleverede kode virkede med det samme uden problemer.







Teste præcision af Blightbot koden.
Tidsforbrug: 30 min.

Af pladshensyn var vi nødt til at ændre afstandsangivelser i den initielle rute i koden. Vi havde simpelthen ikke gulvareal nok til at køre programmet som det var. Derfor halverede vi alle afstande før vi startede. Vi kørte robotten med Blightbot koden flere gange med enslydende resultat hver gang. Afvigelsen mellem startpositionen og slutpositionen var ca ½ cm ved alle vores tests.

Ifølge opgaven har denne robot en præcisionsmæssig svaghed når den drejer. Derfor ændrede vi ruten i koden så den fik flere sving. På tegningen ses den nye rute der køres i rækkefølgen 1-6. Nu var afvigelsen mellem start og stop ca 3.5 cm hver gang. Altså er sving tilsyneladende designets svaghed.



Navigation uden om forhindringer.
Tidsforbrug:2 timer.

Vi besluttede at genbruge sidste uges AvoidFront behavior kode. Desuden modificerede vi RandomDrive til TachoDrive. Tanken er da at vi så vil have en robot med disse to behaviors. I denne forbindelse monterede vi ultralydssensoren igen.

Hvad skal der ske når den ser en forhindring?
En mulighed er at bakke lidt tilbage, dreje og prøve igen. Ved gentagne gange at foretage denne handling burde man før eller siden kunne komme forbi forhindringen.

I praksis fik vi desværre ikke denne løsning til at virke inden for tidsrammen. Efter den ser forhindringen første gang går det galt og den fortsætter aldrig mod målet igen.

fredag den 9. november 2007

NXT programmering, lesson 8

Tidsforbrug: 3 timer. Deltagere: Asbjørn, Christer og Jesper.
Målet med dagens er, at eksperimentere med flere forskellige simultane adfærdsmønstre.

Vi vil gennemgå disse skridt et for et:
  • Ombygning af bilen.
    • Der skal monteres en ultrasonisk sensor.
  • Eksperimenter med den udleverede kode.
    • Først med et enkelt adfærdsmønster, derefter flere.
  • Diskussion af klasserne Behavior og Locomotion
    • Besvarelse af konkrete spørgsmål i opgaveformuleringen.
  • Tilføjelse af nyt adfærdsmønster: "kør mod lyset"
Ombygning af bilen.
Tidsforbrug: 15 minutter.

Vi har valgt at genbruge LEGO-modellen, vi brugte som sidste uges Braitenberg vehicle. Herpå har vi så monteret den ultrasoniske sensor ovenpå.

Eksperimenter med den udleverede kode.
Tidsforbrug: 45 minutter.

Først kørte vi kun med RandomDrive. Denne ændrede vi hurtigere og uden pauser. Dette gjorde vi fordi den kørte så langsomt, at den kun meget sjældent kørte ind i ting.
Herefter aktiverede vi AvoidFront klassen. Denne virkede dog ikke umiddelbart og gav en konstant måling på 255. Løsningen var at flytte sensoren fra port 4 til port 3. Nu virkede den, men den kørte stadig ind i ting. Problemet løste vi ved at sætte threshold op fra 20 cm til 40 cm. Dette bevirkede at den herefter stoppede i god tid før kollision. Til sidst aktiverede vi PlaySounds og observerede at alle tre adfærdsmønstre kørte.

Under vores gennemgang af koden opdagede vi et par småfejl. Et par steder (AvoidFront og PlaySounds) fandt vi en række drawString() inde i en løkke. Dette er ikke noget problem i sig selv, men når den opretter et nyt String-objekt hver gang og VM'en ikke har en garbage collector, bliver det et problem med memory leaks. Vi løste problemet ved at ændre disse til drawChar(), da det alligevel kun var et enkelt bogstav den udskrev hver gang.

Diskussion af klasserne Behavior og Locomotion.
Tidsforbrug: 30 minutter.

Hvad er formålet med daemon threads?
En daemon thread kan ikke holde Java VM'en kørende hvis programmet afsluttes.

Hvordan bruges undertrykkelses booleanvariablen i LocoMotion.java?
Hvis en klasse har sin undertrykkelsesboolean sat, vil LocoMotion ikke adlyde den. Dens adfærd bliver da undertrykt.

Hvordan vil vi beskrive delay metoden i Behavior?
Det er en metode der busywaiter til en af to ting sker:
  • Den når sin timeout værdi.
  • Den er undertrykt.
Formålet er at være en slags adfærds-reset.

Hvordan bruges undertrykkelsesmekanismen i Behavior til kontrolleret adgang til motorerne?
Som udgangspunkt skiftes adfærdsmønstrene til at tilgå motorerne. Hvis en adfærd er undertrykt, vil delay-metoden afslutte med det samme og adfærden vil ikke kunne komme til udtryk.

Er der situationer hvor denne model fejler?
Når den bliver undertrykt, vil en adfærden løkke bare stå og loope. I det øjeblik den ikke er undertrykt mere, vil den stoppe et sted i løkken. Vi kan ikke være sikre på hvor dette sker, men kun håbe på at det er et "godt" sted.

Tilføjelse af nyt adfærdsmønster: "kør mod lyset"
Tidsforbrug: 1 time og 30 minutter.

Det første vi gjorde var en mindre refaktorering af den udleverede kode. I den udleverede kode skal en behaviour eksplicit kende alle behaviours den vil undertrykke. Dette gør det besværligt at tilføje nye behaviours eller ændre rækkefølgen af eksisterende behaviours. Vi udvidede Behaviour super-klassen med to feltvariable: child og childSuppressed, hvor child er en Behaviour og childSuppressed er en boolean. Desuden udvidede vi koden i Behaviour med:

private void updateChildSuppressed()
{

if(child != null)
child.setSuppressed(suppressed || childSuppressed);
}

Et child er altså suppressed hvis enten dens ane er suppressed eller dens ane eksplicit har bedt om at barnet er suppressed. På denne måde får vi en kæde af behaviours hvor den enkelte behaviour kun behøves at kende til den umiddelbart foregående.

Til denne delopgave udvidede vi bilen med en lyssensor. For at kunne observere den nye adfærd i detalje, måtte vi ændre et par af de andre adfærdsmønstre:
  • RandomDrive blev ændret til at køre mere i cirkler og mindre lige ud. Hermed ville det være nemmere for den at "få øje på" lyskilden.
  • Threshold for AvoidFront blev sat ned til 30 cm. Igen pga det lille testrum.
Vi havde sidste gang eksperimenteret med en robot der kan søge lyset ved at kigge på forskellen mellem to lyssensorer. Vi var dog kun i stand til at anskaffe to RCX lyssensorer, disse var dog ikke gode nok til at skelne små forskelle i lys så det kom aldrig til at virke særligt god. Denne gang valgte vi derfor en simplere metode der kun kræver en enkelt lyssensor og derfor kunne vi bruge NXT sensoren. Algoritmen var simpel: Vi beregner et vægtet løbende gennemsnit (som beskrevet i teksten her) af de lysværdier vi har set og hvis den værdi vi måler nu er større end gennemsnittet antager vi at robotten peger mod lys, suppreser barnet til vores Behaviour og sætter bilen til at køre fremad:

avg.addValue(val);
if(val > avg.get())
{
setChildSuppressed(true);
Locomotion.forward(300, 300);
delay(300);
}

Denne behaviour blev indsat mellem DriveRandom og AvoidFront:

RandomDrive rd = new RandomDrive("Drive", 1);
GoTowardsTheLight gl = new GoTowardsTheLight("Light", 2, SensorPort.S4, rd);
AvoidFront af = new AvoidFront("Avoid", 3, SensorPort.S3, gl);
PlaySounds ps = new PlaySounds("Play", 4, af);

Ideen er at hvis vi ikke ser lys kører vi tilfældigt rundt. Når vi så (tilfældigvis) peger i retningen af lys kører vi fremad. På den måde burde vi i længden nærme os eventuelle lyskilder.

Nedenstående billede er taget med lang lukketid i et møkelagt rum. Kameraet var indstillet til først at tage et billede med blitz og derefter holde sig åbent i 15 sekunder. Da det er håndholdt, er der en vist mængde af rysten, hvilket kan ses på, at lyskilden øverst til venstre i billedet har flyttet sig undervejs. Det ændrer dog ikke på billedets centrale budskab.
Til at begynde med stod bilen hvor den ses på billedet. Efter lyset blev slukket ses det, at den først drejer rundt om sig selv. Da får den øje på lyskilden og kører hen mod denne. Lige før den når frem, træder AvoidFront adfærden i kraft og den bakker tilbage. Til sidst kører den tilfældigt og taber lyset af syne, hvorefter de 15 sekunder er gået.

fredag den 2. november 2007

NXT programmering, lesson 7

Tidsforbrug: 3 timer.
Deltagere: Asbjørn, Christer og Jesper.

Målet for dagen session er, at bygge og programmere Braitenberg vehicles 2a & 2b.

Bygning og programmering skal foregå i disse skridt jfr opgaven:
  • Bygge en bil og teste stabilitet.
  • Implementere et styreprogram ud fra Tom Deans noter.
  • Eksperiment med en flertrådet version.
  • Automatisk løbende tilpasning af MAX_LIGHT og MIN_LIGHT
Programmerne vi lavede under denne session kan findes på adressen:
http://www.daimi.au.dk/~jn/lego/uge8/

Disse punkter vil blive gennemgået ét for ét.

Bygge en bil og teste stabilitet.
Tidsforbrug: 1½ time.

Vores første bud på en bil viste sig at være for høj. Det gav den et højt tyngdepunkt og dermed en tendens til at vælte forover ved hurtige retningsskift. Dette har vi forsøgt at løse ved at sænke NXT'en, hvorved det samlede tyngdepunkt blev sænket.
Det har vist sig at virke. Robotten væltede ikke mere efter dette.





Implementere et styreprogram ud fra Tom Deans noter.
Tidsforbrug: 30 minutter.

Første delopgave her var, at få nogen fornuftige målinger ud af lyssensorerne. Til denne opgave anvender vi to RCX sensorer. Som beskrevet i et af de tidligere indlæg, er disse sensorer ikke specielt gode til at skelne mellem lysstyrker. Vi vil gerne have, at en lille forskel i en lav lysstyrke giver en tydelig måling fra sensoren. Desuden ønsker vi ensartede reaktioner på input fra begge sensorer. De giver målinger i forskellige intervaller på samme lyspåvirkning. Dette kan vi kompensere for ved at have en MIN_LIGHT og MAX_LIGHT per sensor. Så kan vi normalisere input.



Efter vi havde implementeret styreprogrammet, forsøgte vi at lade bilen køre i et mørkt rum. Samme program kan uændret anvendes til både vehicle 2a og 2b ved at man bytter rundt på forbindelserne til motorerne. Her viste RCX sensorerne deres svaghed. Ved forsøg med at følge lyset fra en LED cykellygte, opnåede vi kun at kunne "se" ca 20 cm frem. Var lyset længere væk, var det for svagt til at robotten kunne reagere på det. Men ud over den manglende lysfølsomhed virkede programmet efter hensigten. Vehicle 2a flygtede fra lyset og vehicle 2b kørte mod det.

Eksperiment med en flertrådet version.
Tidsforbrug: 30 minutter.

En flertrådet version af styreprogrammet blev implementeret. Vi kunne ikke observere nogen forskel på denne version og den enkelttrådede.

Automatisk løbende tilpasning af MAX_LIGHT og MIN_LIGHT.
Tidsforbrug: 30 minutter.

Vi begyndte at implementere det, men så gik tiden. Når sensorerne ikke er bedre end de er, besluttede vi at droppe denne del. Det ville ikke have betydet noget særligt alligevel.