torsdag den 26. april 2012

Lego LAB uge 10


Tilstede:
Mikkel Nielsen
Peter Jessen
Søren Bramer Schmidt

Tid brugt:
5 timer

Mål

Målet med dagens øvelse er at afprøve implementeringen af behavior-based arkitektur i leJOS's subsumption API og prøve de forskellige esperimenter beskrevet på ugeseddel 10.[1]

Plan
Planen er skrevet således, at vi følger opgaveformuleringen for uge 10. [1]
Vi vil:
1. Ombygge robotten til at have relevante sensorer og uploade BumperCar til robotten
2. Gå igennem listen af eksperimenter og rapportere resultaterne.
3. Rette subsumption mekanismen som beskrevet i Motivation Functions afsnittet på ugesedlen.

Resultater

Når touchsensoren bliver trykket ind, bliver DetectWall aktiveret af touch sensoren. Arbitratoren er implementeret således at søgning efter den højest prioriterede behavior starter forfra når der findes en behavior med en aktiv trigger condition. Det betyder at når touch sensoren forbliver aktiveret bliver behaviors med lavere prioritet aldrig kørt.

Implementation af exit-behaviour
Vi tilførte en exit behaviour, på linje med de andre behaviours. Exit behaviouren er givet højeste prioritet i arbitratoren. Vi kan observere, at Exit behavioren bliver aktiveret meget hurtigt. Det kræves dog at escape knappen holdes inde, da det kræver mere end en enkelt observation af tryk, før action delen udføres. Dette blev implementeret således:

class Exit implements Behavior {

 public boolean takeControl() {
  return Button.ESCAPE.isPressed();
 }

 public void suppress() {
  // højeste lag -> skal aldrig kaldes
 }

 public void action() {
  System.exit(0); // exit program
 }
}

Subsumption mekanismen er implementeret i run metoden i Arbitrator klassen. Den fungerer ved at løbe igennem alle behaviors startende med den højst prioriterede. Når den finder en med en triggering condition som er true stoppes gennemløbet.
Da DetectWall har højere prioritet end DriveForward bliver takeControl i DriveForward ikke kaldt når DetectWall trigger.

Ændring af sampling af distance
Vi ændrede indsamlingen af afstandsværdier som beskrevet på ugesedlen[1]. Den nye thread indsamler distancen med et interval på 20 millisekunder. Denne thread er så uafhængig af resten af programmet.Vi testede dette, men kunne ikke se nogen forskel på de to implementationer. De 20 millisekunder er ikke nok til at registrere en forskel.


Vi ændrede DetectWall behavioren således at robotten kører et sekund baglæns før den drejer. Dette gjorde vi ved at indsætte et delay med Thread.sleep.

Vores implementation med thread.sleep() gør det umuligt at interrupte DetectWall behavioren. Vi kan derfor ikke med denne implementation både køre baglæns i et sekund og samtidig er interruptable. De enkelte rotate kommandoer kan gøres interruptable ved at give dem parameteren "True". En bedre implementation er at bruge systemtiden til at måle et sekund ud, og så lade en whileløkke køre i sekundet imens det yielder og ikke er interrupted. Dette er f.eks. tilfældet i koden som er givet til os på ugesedlen[1]. 

Motivation focus
Vi afprøvede først koden, og kunne observere robotten kører fremad indtil den målte en forhindring foran den, eller til der trykkes på tryksensoren. Når dette skete, blev detectWall behaviouren aktiveret. Dette gjorde at robotten afspillede en lyd, kørte baglæns i et sekund, ventede et sekund, drejede og afspillede en lyd inden den kørte videre fremad.
Vi kunne observere at vi med denne implementation kunne interrupte detectWall, således at action() koden fra behaviouren blev genstartet. Dette ses f.eks. i denne video, hvor man kan høre at detectWall lyden bliver genafspillet igen og igen.  


 Status

Vi blev færdige med dagens program. Vi nåede det vi havde planlagt at lave. Vi valgte ikke selv at give os i kast med at skrive om på bumperCar koden. Vi havde dog brugt tid på at overveje hvordan det skulle gøres, og vores konklusioner mindede meget om koden fra ugesedlen. Koden fra ugesedlen fixer også et andet problem med arbitratoren som vi havde observeret. Den oprindelige arbitrator reagerede langsomt og derfor kunne f.eks. hurtige tryk på sensoren ikke registreres rigtigt.


Referencer

torsdag den 19. april 2012

Lego LAB uge 9

Tilstede:
Mikkel Nielsen

Peter Jessen


Tid brugt:
5 timer

Mål

Målet med dagens øvelse er at afprøve navigation via tacho-counters og prøve de forskellige esperimenter beskrevet på ugeseddel 9.[1]






Plan
Planen er skrevet således, at vi følger opgaveformuleringen for uge 9. [1]
Vi vil:
1. Opbyg robot med ultrasonic sensor, som beskrevet i bygningsmanualen side 8-22 og side 28-30.
2. Tilføje en marker så robotten trækker et spor efter sig.
3. Programmere og installere et program der er baseret på differentialPilot klassen.
4. Tilføje en avoid funktion der kan undgå forhindringer.

Resultater

 1. og 2. Bygning af robot

Vi byggede robotten som beskrevet i manualen. Vi valgte at bruge standard robotten, da den er nem at tilføje flere elementer til. Vi tilføjede en marker-tus ved at bruge elastikker der trækker tussen efter robotten.


  3. Programmet

Vi brugte differentialPilot til at syre robotten. Vi programmerede robotten således at den køre lige frem 20 cm, for herefter at dreje 90 grader til venstre. Denne lille sekvens gentog vi så 4 gange for at få robotten til at køre i en firkant.

Koden er vist her:


DifferentialPilot pilot = new DifferentialPilot(5.75f, 12.0f, Motor.A, Motor.C);

pilot.setTravelSpeed(10);
pilot.setRotateSpeed(30);

for(int i = 1; i <= 4; i++) {
pilot.travel(20);
pilot.rotate(90);
}


Vi tilførte herefter en marker tus og lod robotten køre rundt på et whiteboard på gulvet. Resultatet er som vist på videoen her:



Som man kan se stopper tussen cirka 1-2 cm fra hvor den startede. Dette fik vi fixet ved at ændre hjuldiameteren fra 5.6 cm til 5.75 cm. Dette fik tussen til at ramme inden for ½ cm af hvor den startede.


På den næste video, hvor vi havde ændret hjuldiameteren, er robotten sat til at køre firkanten 3 gange i træk. Som man kan se på videoen rammer tussen meget præcist oven på stregen fra de foregående omgange.



Vi lod herefter robotten kører firkanten 10 gange for at se forskellen. Her blev resultatet, at robotten kørte mere og mere upræcist. Som man kan se på billedet, er den 10. omgang markant anderledes end de foregående 9. Vi betragter dog denne omgang som en outlier, der skyldes en ukendt fejlkilde.





4. Avoid funktion

Vi tilføjede et while loop således at robotten vil afbryde sine kørsler fremad, såfremt den opdager at der befinder sig en forhindringer indenfor 10 cm foran robotten. I såfald skal robotten gå direkte til at dreje. Vi ændrede programmet til at køre en tilfældig afstand fremad og dreje et tilfældigt antal grader.

kode for tilfældig kørsel:




DifferentialPilot pilot = new DifferentialPilot(5.75f, 12.0f, Motor.A, Motor.C);
UltrasonicSensor sensor = new UltrasonicSensor(SensorPort.S1);

pilot.setTravelSpeed(10);
pilot.setRotateSpeed(30);

Random random = new Random();

while (true) {
pilot.travel(random.nextInt(200), true);

while (pilot.isMoving()) {
if (sensor.getDistance() <= 10) {
pilot.stop();
}
}

pilot.rotate(random.nextInt(180));
}




Resultatet er som vist på videoen her:



BONUS:

Vi prøvede tilsidst at tilføje en ekstra marker og legede lidt med variablerne i koden for at få robotten til at tegne en blomst. resultatet kan ses her:



 

 Status

Vi blev færdige med dagens program. Vi nåede det vi havde planlagt at lave, og fik samtidig tid til at lave en pæn tegning. Vi fandt ud af, at det svære problem er, at finde ud af, hvor robotten er efter den har roteret. Det er nemt at holde styr på hvor man er efter at have kørt lige ud. Udfordringen er at finde ud af hvor robotten er efter at have drejet.


Referencer

onsdag den 18. april 2012

Lego Robot-Race

Tilstede:
Mikkel Nielsen
Søren Bramer Schmidt
Peter Jessen


Tid brugt:
7 timer

Mål

Målet er at bygge en robot der kan gennemføre 'Alishan train track' i den bedst mulige tid. 





















Plan
Vi vil:
1. Bygge en robot der kan følge de lige stræk på banen, ved hjælp af lys-sensorer.
2. Teste de lige stræk med robotten på banen og justere variabler.
3. Tilføje svingene og toppen som særlige tilfælde i koden.
4. Teste svingene med robotten på banen og justere variabler.
5. Iterere imellem punkt 2 og punkt 4 for et samlet resultat.

Resultater

 1.Lige stræk
Vi valgte at lave en robot med et lavt tyngdepunkt og dobbelthjul bagpå. De dobbelte baghjul viste sig at være nødvendige da robotten ellers spinnede på hjulene på opkørslen. Foran placerede vi 3 lyssensorer for at holde optimal styr på hvor på banen robotten er. Idéen var at den ene sensor holdt øje med striben og de andre på hver side af striben. Disse 3 sensorer skulle så kalibreres før hver kørsel.

 2. Test af lige stræk

Vi testede robotten på de 3 lige strækninger. Her opdagede vi, at vi ikke kunne køre med fuld hastighed og samtidig holde styringen. Vi valgte derfor at nedsætte hastigheden til den højeste, hvor vi stadig kunne styre. Vi fandt også ud af, at lysforholdene var forskellige fra den laveste strækning til den øverste. Vi havde derfor store problemer, i at robotten ikke kunne følge striben øverst og nederst på samme kalibrering. Vi fandt ikke nogen god løsning på dette, ud over at sænke hastigheden yderligere for at undgå at robotten kørte af banen.

3. Sving

For at tage svingende og ikke køre af banen, valgte vi at lave sving på følgende måde. 
Vi tilførte en ultrasonic sensor yderst foran på robotten. Denne sensor kunne så registrere når det plan robotten køre på ændre sig. Dette sker f.eks. når robotten når det første plateau. I det tilfælde drejer robotten en tidsmålt mængde til højre, for herefter at falde tilbage på lige stræk algoritmen. Tilsvarende kode blev tilført til andet plateau og toppen, hvor robotten skulle foretage et u-sving. På nedkørslen køre vi en lignende kode, dog skal ultrasonic sensoren nu måle en kortere afstand til fladen forude, og robotten skal igen dreje forholdsvis til højre og til venstre.

4. Test af sving

Det viste sig at være svært at time svingene perfekt. Der var mange faktorer der spillede ind. F.eks. afhang svinget succes af hvorledes robotten havde fulgt striben op til svinget, da selv små ændringer i robottens retning havde store konsekvenser for svinget. Herudover ændredes robottens reaktion som følge af batteriets opladningsniveau. 

5. Generel test

Med koden på plads, testede vi med at samle de 2 dele og få robotten til at køre på banen. Nogen af de variable vi havde til at ændre på var:
  • Robottens hastighed på opkørslens lige stræk
  • Robottens hastighed på opkørslens sving
  • Robottens hastighed på nedkørslens lige stræk
  • Robottens hastighed på nedkørslens sving
  • Kalibreringsværdierne
  • Mængden af tid brugt på at svinge i alle 4 sving og på toppen.
  • Tidsdelay før robotten svinger følgende en, af ultrasonic sensoren, ændring i hældingen af planen.

Vi optog flere forsøg på video, hvor robotten dog ikke var i stand til at gennemføre banen.

 Status

Vi nåede til det punkt hvor vi kunne observere robotten gennemføre alle dele af banen enkeltvis. Dette kunne vi ved, f.eks. at starte fra toppen. Det bedste forsøg hvor vi startede fra startområdet er vist på filmen her:




torsdag den 12. april 2012

Lego LAB uge 7

Tilstede:
Mikkel Nielsen
Søren Bramer Schmidt
Peter Jessen


Tid brugt:
2 timer

Mål

Målet med dagens øvelse er at afprøve SoundCar med forskellige samtidigt kørende adfærd, som beskrevet på ugeseddel 7. 






Plan
Planen er skrevet således, at vi følger opgaveformuleringen for uge 7. [1]
Vi vil:
1. Opbyg robot med ultrasonic sensor, som beskrevet i bygningsmanualen side 8-22 og side 28-30.
2. Installere og køre SoundCar og observere dens adfærd ved at adskille de 3 adfærd.
3. Tilføje en lysfølsom adfærd.

Resultater

 1.Bygning af robot

Vi byggede robotten som beskrevet i manualen. Vi valgte at bruge standard robotten for at undgå potentielle fejl med den robot-race robot som vi byggede på sideløbende.


 2. Observation af SoundCar

Vi kørte først programmet med alle 3 adfærd kørende samtidigt. Vi kunne observere robotten kører tilfældigt rundt med et par sekunders mellemrum, spille en lyd og undgå forhindringer ved at bakke tilbage og dreje til venstre. For at bedre kunne observere de 3 adfærd skilte vi dem ad ved kun at starte enkelte tråde. Med RandomDrive som eneste tråd kunne vi observere at robotten kørte i omkring et sekund hvorefter den holdt pause i et par sekunder. Kørslen var tilfældig mellem at kører fremad, og køre på de enkelte motorer hver for sig. Med PlaySound seperat, spillede robotten regelmæssigt en lyd hvert 10. sekund. AvoidFront alene reagerede når robotten observerede en forhindring 20 cm foran sig. Adfærden var at bakke tilbage og dreje.

 Vi kørte herefter alle 3 tråde samtidigt igen for at teste de forskellige adfærds prioriteter. Vi kunne observere at lyden altid blev spillet med 10 sekunders mellemrum ligegyldigt af hvad robotten ellers foretog sig. Vi kunne også observere at RandomDrive adfærden udeblev når der var en forhindring foran ultrasonic sensoren. Dette passer godt overens med prioriteterne fra denne tegning:   




I konstruktoren for Behavior klassen bliver alle threads gjort til deamon. Dette har den effekt at når en thread dræbes, trækker den alle sine underthreads med ned. I suppress metoden bruges en suppressCount som tæller op for at markere at en thread er suppressed. Dette vil ske når en højere prioriteret thread suppresser sine under-threads for at udføre dets handling.

Fred Martin [2] bygger sin prioritetsalgoritme anderledes. Her er der en overordnet prioritetskø som styre hvilken tråd der skal køre ud fra deres prioriteter. Dette er i højere grad en topstyring af prioriteten. I SoundCar er prioriteten implementeret med et hieraki. Hvis en thread vil køre, og den har højere prioritet, vil den altid komme til, på bekostning af de andre. Prioriteten er derfor styret uden en ekstern prioritetsagent.

3. Tilføjelse af lys-følsom adfærd

Vi udbyggede robotten med en lys-sensor.

Herefter skrev vi kode til lys-styringen, således at vi kan prioritere den forskelligt i forskellige test. Vi valgte at lave den lysfølsome adfærd med et threshold, således at robotten kun reagerede ved stærk lys-påvirkning, f.eks. fra en lygte.

Kode fra ToLight behavioren:

public void run() 
    {
        while (true)
        {
            int lightValue = ls.getLightValue();
         
            while ( lightValue < lightThreshold )
            {
                lightValue = ls.getLightValue();
                drawInt(lightValue);
            }

            suppress();
            
            forward(100, 100);
            drawString("f");      
            delay(1500); 
      
            stop();
            drawString("s");
            delay(100);
      
            drawString(" ");
      
            release();     
       }
    }


I testen her er den lys-følsomme adfærd prioriteret under AvoidFront og over RandomDrive. Prioriteten kunne selvfølgelig også være anderledes.

Demonstration:



 Status

Vi blev færdige med dagens planlagte, noget korte, program. Vi vil næste gang arbejde på at bygge robot-race robotten færdig.


Referencer
[2] Fred G. Martin, Robotic Explorations: A Hands-on Introduction to Engineering, Prentice Hall, 2001.
[3] Kode for uge 7