af Hanna/ hawei11, Juri/ juwul10, Kenza/ kesta12, Rasmus/ rajoe12 og Sacha/ sther06. Gruppen har stået for at designe agenten til byområdet og har taget ansvar for design af hele banen scenariet udspiller sig på.

Introduktion

Dette projekt er en del af et større Multi-Agent System (MAS) kaldet Resource Traffik System (RTS) udviklet på 2. Semester af kandidatuddannelsen Læring- og Oplevelsesteknologi. Det samlede system er en form for fangeleg imellem 2 børne-agenter og 3 voksen-agenter, hvor de to børn vil gemme sig på en bane bestående af 5 områder:

  1. Start zone
  2. Fællesområde
  3. Byområde
  4. Havneområde
  5. Skovområde

Gruppens opgave er at designe en agent, der kan patruljere byområdet og fællesområdet for børn, samt kan snakke sammen med de andre agenter for at fortælle når et barn er blevet fundet. Det er derfor vores mål at designe en agent, der:

  1. Er solidt bygget, så den ikke vakler eller falder i sving
  2. Ved, hvordan den skal:
    1. Finde fra startfeltet hen til sit område
    2. Navigere i byområdet
    3. Navigere i fællesområdet
  3. Kan kommunikere med andre robotter på banen

Og yderligere designe et byområde, der:

  1. Tydelig er en by, herunder:
    1. Indeholder bygninger
    2. Har veje, som køretøjer skal holde sig på

 

Metode

Vi har taget udgangspunkt i filosofien i de forskellige agile arbejdsmetoder ved at udvikle iterativt og med prototyper. Vi startede med idégenerering/brainstorm, lavede low-fidelity prototyper, der blev testet internt og derefter evaluteret i forhold til næste iteration, indtil vi mente vores krav blev opfyldt tilstrækkeligt.

Da vi er mange i gruppen har vi fordelt opgaverne for at projektet mere effektivt kommer i mål. Her har vi brugt Pair Programming, som er en agil arbejdsmetode indenfor softwareudvikling. Her har vi haft to programmører, der arbejder sammen på robottens fysiske udformning, i mens to andre har taget sig af dens AI, hvor begge par har snakket sammen for at få det hele til at gå op i en højere enhed. Vi har tage inspiration fra andre gruppers robotter, så vores egen lettere kan tilpasse sig miljøet og de andre robotter.

Materialer

  1. LEGO Mindstorm NXT klods
  2. 2 NXT Motor
  3. 2 IR sensorer
  4. Adskillige Lego byggeklodser

LEGO Mindstorm NXT Klods

I dette projekt er der arbejdet med LEGO Mindstorms NXT klods udgivet i 2006. NXT klodsen er et programmérbart stykke hardware der kommer med en række sensorer.

Selve klodsen har 4 indgange til sensorer, navngivet 1 – 4 og 3 indgange til motorer, navngivet A – C.

NXT’en programmeres i Mindstorms eget drag’n’drop sprog eller i et af de flere uofficielle sprog (NxC som vi har brugt eller NBC, leJOS NXJ og RobotC).

NXT Motor 

Til bevægelse af robotten er der benyttet 2 NXT motorer, der er lavet specifikt til NXT sættet. Denne fungerer som en meget præcis motor der kan sende data om, hvor stor en rotation der foretages ned til 1°. Motoren kører på 9V strømkilder, som både kan ske gennem et genopladeligt batteri til NXT klodsen eller 6 AA batterier i en battery pack.

IR Sensor 

IR sensoren afgiver data der benyttes til at bestemme robottens opførsel. Sensoren skelner mellem lys og mørke og er på den måde idéel til at følge linjer med. IR sensoren udsender  infrarødt lys og på baggrund og mængden af reflekteret lys, producerer den data.

LEGO Byggeklodser

For at få robotten til at hænge sammen er der benyttet en række LEGO Technic klodser til at bygge et stel om NXT klodsen, sensorerne og motorerne. Stellet er bygget rundt om klodsen med henblik på at få sensorerne til at sidde så fast som muligt under kørsel for at dataene, de udsender, er så pålidelig som muligt.

 

Resultater

Brainstorm

For at have en ide at arbejde ud fra i forhold til vores agents opførsel fandt vi frem til, at den skulle være en politibetjent, der er ude på sin rute og på samme tid leder efter de forsvundne børn. På den måde ville agenten kende sit eget området, og kunne derfor have et kort over byen indlagt i sin AI. Agenten skulle navigere ved hjælp af linier på vejene i byen og bruge en passende sensor til ‘se’ et barn i nærheden. Nedenfor ses et konceptuelt design for robotten.

del 1

 

Det første udkast til byområdet var at vejene skulle fungere som en form for labyrint og bygningerne skulle være forhindringer, som agenten skulle navigere udenom. Nedenfor ses første udkast hertil, den gule markering hentyder til agentens startposition. Her var det vigtigt at agenten kunne danne sig et overblik over vejene, så den kunne vælge en ny vej, hvis den kom til det samme kryds igen, for derved at afsøge et andet område at byen for barnet.  Byen skulle også være stor nok til at både by agenten og de forsvundne børn kunne navigere rundt i det uden at blive fanget i hjørner.

 

del 2

Iterationerne

Robottens grundlæggende fysiske udseende har ikke været igennem nogle iterationer, da vi har taget udgangspunkt i en allerede eksisterende robot. Placering af sensorer har derimod været igennem mange iterationer, både for at teste deres optimale placeringer og hvilke sensorer der skal bruges. Undervejs har gruppen også måttet redesigne, fordi sensorer ikke har været pålidelige eller slet ikke virkede.

For at vurdere hvilket område agenten befandt sig i var vores første tanke at bruge en farvesensor og farve alle områder i en unik farve, der ville kunne genkendes tydeligt. Dette ville have virket efter vores bedste overbevisning, men sensoren var ikke i god stand og vi måtte derfor finde en anden løsning. Løsningen blev, at agenten i stedet bruger to IR sensorer til at læse banen som en gråskala. Dette betød, at vores by nu skulle være opbygget i adskillige nuancer af grå, og at vores robot skulle kunne kende forskel på grå og de farver de andre gruppers områder var i. Vores første forsøg herpå var at give agenten en måde at holde styr på sin lokation igennem navigering.

Første iteration af navigering var at bruge et kompas, så agenten kunne vurdere, hvor den var på banen baseret på bevægelse og retning. Denne opsætning blev dog afvist dels fordi vi kom i mangel på porte til sensorer, og dels fordi det virkede unødvendigt kompliceret i forhold til anden (og endelige) iteration, der byggede på line following ved hjælp af de IR sensorer, der alligevel blev brugt til at vurdere hvilket område (by, havn, skov, fælles) agenten befandt sig i.

Ud fra vores begrænsninger i sensorer og efter flere tests af gråskalaen kom vi frem til, at vores linie, agenten skulle følge, var 20% grå da dette kunne tælle som hvid for de andre grupper, og de derfor ikke ville blive forstyrret af den. Selve byen skulle være mørkere (60% grå og bygningerne i byen er endnu mørkere (90%). På den måde skulle byen også kunne fungere for børne-agenterne.   

Endeligt design

Vores robot er grundlæggende bygget ud fra Castor Bot, hvortil vi har tilføjet vores eget stativ til at fastsætte sensorer. Vi har valgt at tage udgangspunkt i Castor Bot, fordi den fordeler vægten af hele robotten godt og gør agenten stabil. Baghjulet kan rotere 360° og gør agenten agil, hvilket er vigtigt, når den skal navigere rundt inde i byen og tage skarpe sving.

Agenten har to IR sensorer foran, placeret så tæt påbanen som muligt, og er yderligere blevet påklæbet sort papir, for at reducere støj på sensorerne. De bruges til at navigere efter den linje, som udgør vejene på banen. De er placeret tilpas langt fra hinanden til at agenten ikke hele tiden skal justere retning, fordi en af sensorerne rammer ind i linien. I et stativ, der går op over agenten er der placeret en IR seeker sensor, som bruges til at se efter børne-robotterne, der har en IR emitter. Sensoren er placeret i samme højde på alle agenter for at gøre det lettere at se signalet. Herudover bruger agenten Bluetooth (integreret i NXT’en) til at kommunikere med børn- og voksen-agenter.

 

01 02 03

Det endelige design for byområdet endte med at bruge gråskalaen, da vi blev nødsaget til at bruge IR sensorer for at agenten kunne se banen. Vi fandt igennem tests ud af, at sensorerne rimeligt præcist kunne se forskel på hvid, 20% sort, 40% sort, 60% sort, 80% sort og 100% sort. For at undgå at vores vej til line following får indflydelse på de andre gruppers sensorer, valgte vi at lave vejen i 20% sort, og vores byområde i 60% sort. På den måde kunne vi nu også lave en vej i fællesområdet, som ikke ville irritere de andre agenter. Byelementerne er på tegningen i 90% sort for at vise, hvor de er i forhold til vejen. Den 60% sorte flade er også nok til at børne robotten ikke opfatter området som sort, hvilket for børne-robotten betyder ‘stop, du er nået til kanten’. Startfeltet er lavet som en rundkørsel med en enkelt afkørsel/tilkørsel. Rundkørslen er en smule for stor til at fungere optimalt, og ville til et fremtidigt projekt skulle gøres mindre, så den ikke kommer så tæt på kanten af startfeltet.

dfghk

 

Kode

 

Robottens kode er skrevet i NXC (“Not Exactly C”). Al koden er delt op i forskellige tasks, der kører samtidigt. Der kører i alt seks tasks; en main task, der styrer programmet, og fem del tasks til:

  • Map-sensorerne
  • Line-following
  • IR-seeking
  • Motorstyring og
  • Bluetooth forbindelse med børnene

Main tasken starter automatisk, når programmet eksekveres, og det er herfra, at de andre tasks startes. Den første task, der startes, er den, der håndterer map-sensorerne. Herefter starter main tasken en kalibreringsfunktion. Når alle værdier er kalibreret, startet main tasken de øvrige tasks.

 

 

Kalibreringen

Det var på forhånd klart, at en kalibrering af sensorer  i.f.t. thresholds for de forskellige farver på kortet ville være nødvendigt. Der er blevet eksperimenteret med faste kalibreringer, som giver deres resultater til følgende programmer, samt nye kalibreringer i starten af hver eksekvering af programmet. Samtidigt er der blevet eksperimenteret med delte thresholds for bund-sensorerne og med individuelle thresholds. Det konstateres, at individuelle thresholds giver bedre resultater, da sensorerne kan være meget forskellige, og at kalibreringen i starten af hver eksekvering virker mest hensigtsmæssigt.

void calibrate(){
   int WhiteLeft = 9999;
   int WhiteRight = 9999;
   int LineLeft = 0;
   int LineRight = 0;
   int DarkLeft = 0;
   int DarkRight = 0;
   // Get white sensor data
   ClearScreen();
   TextOut(0, LCD_LINE1, "Calibration");
   TextOut(0, LCD_LINE2, "Press button for white");
   while(!ButtonPressed(BTNCENTER)){
      TextOut(0, LCD_LINE1, "Calibration");
      TextOut(0, LCD_LINE2, "Press button");
      TextOut(0, LCD_LINE3, "Next colour: ");
      TextOut(0, LCD_LINE4, "White");
   }
   for( int i = 0; i < 100; i++){
     if(leftsensor < WhiteLeft){
        WhiteLeft = leftsensor;
     }
     if(rightsensor < WhiteRight){
        WhiteRight = rightsensor;
     }
   }
   ClearScreen();
   TextOut(0,LCD_LINE1, "Left: ");
   NumOut(0,LCD_LINE2, WhiteLeft);
   TextOut(0,LCD_LINE4, "Right: ");
   NumOut(0,LCD_LINE5, WhiteRight);
   Wait(1000);

   ClearScreen();
   while(!ButtonPressed(BTNCENTER)){

      TextOut(0, LCD_LINE1, "Calibration");
      TextOut(0, LCD_LINE2, "Press button");
      TextOut(0, LCD_LINE3, "Next colour: ");
      TextOut(0, LCD_LINE4, "Line");
   }
   for( int i = 0; i < 100; i++){
      LineLeft += leftsensor;
      LineRight += rightsensor;
   }
   LineLeft = LineLeft / 100;
   LineRight = LineRight / 100;
   ClearScreen();
   TextOut(0,LCD_LINE1, "Left: ");
   NumOut(0,LCD_LINE2, LineLeft);
   TextOut(0,LCD_LINE4, "Right: ");
   NumOut(0,LCD_LINE5, LineRight);
   Wait(1000);
   ClearScreen();
   while(!ButtonPressed(BTNCENTER)){

      TextOut(0, LCD_LINE1, "Calibration");
      TextOut(0, LCD_LINE2, "Press button");
      TextOut(0, LCD_LINE3, "Next colour: ");
      TextOut(0, LCD_LINE4, "Dark");
   }
   for( int i = 0; i < 100; i++){
      if(leftsensor > DarkLeft){
         DarkLeft = leftsensor;
      }
      if (rightsensor > DarkRight){
         DarkRight = rightsensor;
      }
   }
   ClearScreen();
   TextOut(0,LCD_LINE1, "Left: ");
   NumOut(0,LCD_LINE2, DarkLeft);
   TextOut(0,LCD_LINE4, "Right: ");
   NumOut(0,LCD_LINE5, DarkRight);
   Wait(1000);

   // Now average values for both sensors have been found, need thresholds
   THleftlight = (WhiteLeft + LineLeft) / 2;
   THleftdark = (DarkLeft + LineLeft) / 2;
   THrightlight = (WhiteRight + LineRight) / 2;
   THrightdark = (DarkRight + LineRight) / 2;
   ClearScreen();
   TextOut(0,LCD_LINE1, "Leftlight: ");
   NumOut(70,LCD_LINE1, THleftlight);
   TextOut(0,LCD_LINE2, "Leftdark: ");
   NumOut(70,LCD_LINE2, THleftdark);
   TextOut(0,LCD_LINE3, "Rightlight: ");
   NumOut(70,LCD_LINE3, THrightlight);
   TextOut(0,LCD_LINE4, "Rightright: ");
   NumOut(70,LCD_LINE4, THrightdark);
   Wait(1000);

}

 

Map-Sensorerne

Lego-robottens standard IR-sensorer viste sig i tests at være meget svingende i deres værdier. Da robotten skal kunne skelne mellem meget lignende værdier – linien bruger 20% sort, baggrunden i fællesarealet bruger 0% sort (altså hvid), og baggrunden i byen bruger 60% sort, var det nødvendigt at bruge gennemsnittet på et antal målinger, for at minimere uhensigtsmæssige udslag. Testkørsler viser dog, at disse gennemsnitsmålinger ikke fuldstændigt kan eliminere fejlmålinger, som kan have drastiske konsekvenser for robottens opførsel.

task CheckLight() {
   int templeft;
   int tempright;
      while (true) {
         templeft = 0;
         tempright = 0;
         for(int i = 0; i < 100; i++){
            tempright += Sensor(IN_1);
            templeft  += Sensor(IN_3);
         }
         tempright = tempright / 100;
         templeft  = templeft  / 100;
         leftsensor  = templeft;
         rightsensor = tempright;
         TextOut(0, LCD_LINE7, "Left:");
         NumOut(40, LCD_LINE7, leftsensor);
         TextOut(0, LCD_LINE8, "Right:");
         NumOut(40, LCD_LINE8, rightsensor);
         //Wait(10);
      }
   }

 

Line Follower

Map-sensorernes gennemsnitsværdier læses af line-follow tasken. Denne task har som opgave, at styre robotten sikkert gennem både fællesområdet og byen, når der ikke skal scannes for børn. Line-followeren er delt op i tre dele:

  • Et fællesområde, der sætter en by-variabel til “false”, og navigerer på den hvide baggrund
  • Et byområde, der sætter by-variablen til “true” og navigerer på den mørke baggrund
  • En junction-del, der håndterer adfærden ved vejkryds i byen.

Da map-sensorerne ikke er fejlfrie, blev der i starten detekteret væsentligt for mange kryds. Dette prøves at minimere ved kun at tillade junction-detection, hvis by-variablen er “true”. Denne forbedring har reduceret antallet af fejlkryds, men har ikke været i stand til at eliminere dem. Dette formodes at skyldes sensorernes kvalitet, og de skiftende lysforhold på kortet, der mindsker kalibreringens effekt.

Mens disse false-positive kryds virker svært at påvirke, har robotten også problemer med false-negative kryds. Her overser robotten kryds. Dette kunne skyldes, at robotten kun har to map-sensorer, og at krydsene i siden af kortet ligner “T”-stykker, ikke fulde kryds. Det forventes, at tre sensorer og fulde kryds ville have givet mere sikre resultater. Grunden til at dette ikke er implementeret er for få sensor-pladser til ekstra udstyr, samt manglen på testkørsler på forskellige kryds for at finde den optimale bane.

flowchart line

task IndividualLine(){
int currentleft;
int currentright;
int turndirection = 1;
bool allowed = false;
   while(true){
      currentleft = leftsensor;
      currentright = rightsensor;
      // Check in which area we are:
      if (currentright >=THrightlight || currentleft >= THleftlight){
         // We are in the communal area
         town = false;
         turndirection = 1;
         if( currentleft <= THleftlight){ // Line to the left, turn left
            Line = 3;
            TextOut(0,LCD_LINE5, "Open-Left    ");
         } else if( currentright <=THrightlight){
            Line = 2;
            TextOut(0,LCD_LINE5, "Open-Right    ");
         } else{
            Line = 1;
            TextOut(0,LCD_LINE5, "Open-Straight");
         }
      } else if(currentleft <= THleftdark || currentright <= THrightdark){
         //We are in the city
         town = true;
         if(currentleft <= THleftdark && currentright <= THrightdark){
            Line = -1; // Town Straight
            TextOut(0, LCD_LINE5,"City-Straight");
         }else if( currentleft > THleftdark){ // Line to the left, turn left
            Line = -3;
            TextOut(0,LCD_LINE5, "City-Left   ");
         } else if( currentright > THrightdark){
            Line = -2;
            TextOut(0,LCD_LINE5, "City-Right   ");
         }
      } else if(town){

         // if we have no light and no dark fields, and we are in town,
         // then this must be a junction
         Junction = 4; // Tells the scheduler to turn off the motors
         Acquire(JunctionMux);
          allowed = JunctionGo;
         Release(JunctionMux);
         while(!allowed){
            Acquire(JunctionMux);
            allowed = JunctionGo;
            Release(JunctionMux);
            Wait(50);
         }
         PlaySound(SOUND_LOW_BEEP);
         Wait(500);
         Junction = 1; // Tells the scheduler to go straight
         Wait(700); // Driving forward!
         Junction = 4; // Tells the scheduler to turn off the motors
         Wait(1000); // Now waiting!
         currentright = rightsensor;
         currentleft  = leftsensor;
         // Turning direction based on value of turndirection
         if( turndirection == 2 || turndirection == 3 ||
             turndirection == 6 || turndirection == 7 ||
             turndirection == 10){ // We need a right turn
            while (currentright <= THrightdark) {
               Junction = 2;
               currentright = rightsensor;
               currentleft  = leftsensor;
            }
         } else{ // We need a left turn
            while (currentleft <= THleftdark) {
               Junction = 3;
               currentright = rightsensor;
               currentleft  = leftsensor;
            }
         }
         Junction = 4; // Stop turning
         Wait(1000);
         Junction = 0; // Tell scheduler that we're done here

         turndirection += 1;
         if (turndirection > 10) {
            turndirection = 1;
         }
      } // end of area (city, communal, junction)
   } // end of while true
} // end of task

 

IR-Seeker

IR-seekeren er ligetil i anvendelsen. Den har indbygget IR-sensorer i fem forskellige retninger, og dens funktion returnerer signal styrken i hver af disse retninger, samt en estimeret retning for signalets kilde, ud fra ni retninger. For at gøre koden mere fleksibel og mere overskuelig, er IR-seeker koden flyttet ind i en separat task. Denne task er inaktiv i et bestemt antal sekunder, hvorefter den vil aktivere, slukke motorerne, og opspore IR-signaler i fire vinkler omkring robottens front. Returnerer funktionen en værdi over en fastlagt threshold, sættes en variabel til “true”, for at fortælle bluetooth tasken, at et barn er blevet fundet.

task Seek(){
   bool allowed = false;
   while(true){
      Wait(SEEKWAIT); // only check every "SEEKWAIT" seconds
      if(TooSoon <= 0){ // If we are too close to a junction, we're not seeking
         SeekStop = 1; // Tell controller that it's time to seek
         Acquire (SeekMux);
         allowed = SeekGo;
         Release(SeekMux);
         while(!allowed){
            Acquire (SeekMux);   // Wait for positive response
            allowed = SeekGo;
            Release(SeekMux);
            Wait(50);
         }
         PlaySound(SOUND_DOUBLE_BEEP);
         for (int i = 0; i < 8; i++){
            now = true; // tell motor to rotate
            if(i == 0 || i == 1 || i == 6 || i == 7){
               Move(true);
            } else{
              Move(false);
            }
            while (now){} // wait for motor to stop turning
            sense();
         }
         allowed = false;
         SeekStop = 0;
      } // End of "if too soon"

   } // End of while true
} // End of Task

 

Motor task

Robotten skal kunne håndtere fire forskellige motor-input, der kommer fra tre parallelt kørende tasks; line-following, junction-handling, Bluetooth, og IR-seeking. For at de forskelliger input ikke afbryder hinanden, er der brug for en motor-task, der prioriterer de forskellige forslag. Denne motor-task prioriterer opgaver i følgende rækkefølge:

  1. Junctions
  2. Bluetooth
  3. IR-seeking
  4. Line-following

Dette skyldes, at vejkrydsene helst ikke skal misses, så andre tasks må ikke blokere denne. Line-following fungerer som den mest basale adfærd, der slås til, hvis ingen af de andre opgaver er aktive.

flwochart Motor Controller

 

task MotorController(){
   while(true){

   Acquire(SeekMux);
   SeekGo = false;
   Release(SeekMux);
   Acquire(JunctionMux);
   JunctionGo = false;
   Release(JunctionMux);
      //Junction has highest priority
      if(Junction != 0){
         TooSoon = 100;
         Off(OUT_AC);
         Acquire(JunctionMux);
         JunctionGo = true;
         Release(JunctionMux);
         while (Junction != 0){
            // A junction was detected
            if(Junction == 1){
               // Junction says go straight
               OnFwd(leftmotor, TownSpeed);
               OnFwd(rightmotor, TownSpeed);
            } else if( Junction == 2){
               // Junction says turn right
               OnFwd(rightmotor, -TownSpeed);
               OnFwd(leftmotor,   TownSpeed);
            } else if(Junction == 3){
               // Junction says turn left
               OnFwd(rightmotor,  TownSpeed);
               OnFwd(leftmotor,  -TownSpeed);
            } else{
               // Junction says stop
               Off(OUT_AC);
            }
         }// end of Junction
      } else if(BTStop){
         Off(OUT_AC);
         while(BTStop == true){
            // If bluetooth is sending, we should just stand still
            Off(OUT_AC);
         }
      } else if (SeekStop != 0){
            Off(OUT_AC);
            Acquire(SeekMux);
            SeekGo = true;
            Release(SeekMux);
            while(SeekStop != 0){
               // If it's time to look for children
               if( SeekStop == 1){ // Wait
                  Off(OUT_AC);
               } else if( SeekStop == 2){ // Turn left
                  OnFwd(rightmotor, TownSpeed +4);
                  OnRev(leftmotor, TownSpeed);
               } else if( SeekStop == 3){ // Turn right
                  OnFwd(leftmotor, TownSpeed);
                  OnRev(rightmotor, TownSpeed + 4);
               }
            }

      } else{
         // Let Linefollower do their job
         if(TooSoon >0)
            TooSoon--;
         if( Line == 1){ // Communal Area, Straight
            OnFwd(leftmotor,ComSpeed - 4);
            OnFwd(rightmotor,ComSpeed);
         } else if( Line == -1){ // Town Area, Straight
            OnFwd(leftmotor,TownSpeed - 4);
            OnFwd(rightmotor,TownSpeed);
         } else if (Line == 2){ // Communal Area, Right
            OnFwd(leftmotor, ComSpeed);
            OnFwd(rightmotor, 1);
         } else if (Line == -2){ // Town Area, Right
            OnFwd(leftmotor, TownSpeed);
            OnFwd(rightmotor, 1);
         } else if (Line == 3){ // Communal Area, Left
            OnFwd(leftmotor, 1);
            OnFwd(rightmotor, ComSpeed);
         } else if (Line == -3){ //Town Area Left
            OnFwd(leftmotor, 1);
            OnFwd(rightmotor, TownSpeed);
         }
      }
   } // While true
} // Scheduler

 

Bluetooth

Da alle arbejdsgrupper også havde individuelle udfordringer, blev bluetooth delen ikke prioriteret højt af nogen gruppe, og en fælles protokol blev ikke udarbejdet. Internt i gruppen blev der udviklet et forslag til protokollen, dette forslag er udformet i pseudokode og vist i nedenstående kodeblok.

var irSensorValue = ReadIr(IN_1);					//where IN_1 is receiving values on input port 1
var stopMotors = Off(OUT_AC);						//OUT_AC is output ports A and C
var startMotors = OnFwd(OUT_AC);

if(irSensorValue() < 40){							//40 is a threshold value that was found to be working by one group.
	stopMotors();
	BTCommunication(connection_1,'stopIR');			//connection_1 is the paired child robot no. 1 in the BT settings. The variable 'stopIR' is command for stop motors and turn off IR signal.
	BTCommunication(connection_2,'dontStopIR');		//connection_2 is the paired child robot no. 2 in the BT settings. The variable 'dontStopIR' is command for stop motors.
	wait(200);
	if(irSensorValue > 40){
		BTCommunication(connection_1,'goHome');		//irSensorValue is over 40 eg. its turned off so we then know its the "right" one, ask it to go home.
		BTCommunication(connection_2,'dontGoHome');	//ask child robot no. 2 to turn back on motors.
	}else{
		BTCommunication(connection_2,'goHome');
		BTCommunication(connection_1,'dontGoHome');
	}
	startMotors();
}

//there is no error handling if the irSensorValue fluctuates briefly below 40. Which results in maybe sending a random child robot home. This could happen if a alien IR signal is reveiced.

 

Test

Da elementet med kommunikation ikke blev implementeret med de andre grupper, har systemet ikke kunnet testes i sin helhed. Resultater nedenfor er for by-agenten alene.

På testdagen kørte robotten nogenlunde stabilt rundt i sit eget område, med enkelte problemer i.f.t. at opfatte kryds andre steder end i byområdet. Når agenten ‘leder efter børn’ kan den se børnene, men de kan ikke rette helt ordentligt op efter sin rundtur, og kan derfor ende med at komme på afveje efter sin søgning.

 

Diskussion

Der har undervejs i projektet opstået problemstillinger der skulle løses på bedst vis. Disse problemstillinger har vist sig hovedsagligt inden for fire områder: Hardware, software, kort og kommunikation.

IR sensorer gav forskellige data på den samme overflade, en farvesensor der ikke virkede og to NXT motorer, hvor den ene kørte stærkere end den anden. Dette opdagede vi løbende. Derved blev gruppens arbejde flere gange slået tilbage.

Hardwareproblemer har især været fokuseret på sensorerne. Der var usikkerhed omkring farvesensoren, hvor vidt denne var i stykker eller om var blevet brugt forkert. De to IR sensorer har givet forskellige resultater, og derfor måtte programmet tilpasses. IR sensorerne har også været støjfyldte, så resultaterne har ikke altid været konsistente. Dette har ført til usikkerhed i koden, samt langsom fremskridt.

Dog i forlængelse af at IR sensorerne giver forskellig data, har det hjulpet at kalibrere sensorerne før robotten startes i forhold til vejen, byområdet og fællesområdet.

Sensorernes upålidelighed forbedres med kalibreringsfunktioner og gennemsnit over sensor input. Tilføjelse af pap skjuler for udefrakommende lys, dog kan sensorernes input stadig vise sig forkerte, så robotten ikke kører hensigtsmæssigt.

Selvom om håndteringen af IR-seekeren har været forholdsvist ligetil, har der også været problemer forbundet med disse, vedrørende krydsene i byen og line-following generelt. For at børnerobotterne ikke køres ned, skal IR-seekeren være tændt ofte dog kan dette være besværligt pga. Robottens problemer med kørsel indenfor kryds.

IR-seekeren har heller ikke været perfekte, da risikoen for fejlfortolkede kryds, samt sandsynligheden for at line-following fejler opstår, når robotten placeres skævt.

Vores motor task blev indført meget sent i projektet, hvilket har gjort den mindre effektiv, og mere besværlig. Denne task har haft til formål at prioriterer hvilken opførsler der først sendes til motoren, for ikke at skabe kaos mellem alle de indkommende tasks. Dog har den sene implementering gjort koden for tung, og derfor skulle motor tasken været en del af koden fra starten.

Kortet over byen har også givet et par problemer, i særdeleshed dets forskellige lysforholde, som selv skyklapperne ikke kunne ændre noget ved. Dette skulle vi have tænkt over tidligere og eventuelt have foretaget målinger forskellige steder. Robotten har også problemer med line-following på kortet, i særdeleshed ved kryds. Det er usikkert om dette skyldes lys eller fejl i sensorerne.

Bluetooth har været svært at lave, da det kræver 100% kommunikation med de andre grupper. Dog har hver gruppe arbejdet meget individuelt ift. til deres robot og derfor udviklet dem forskelligt. Det har gjort det besværligt at koordinere mellem de mange grupper. Få individer har bedst muligt prøvet at få grupperne til at tage stilling til hinandens robotter og deres udvikling.

 

Konklusion

Vores byområde simulerer en by bygget på et grid, hvor veje løber parallet af og vinkelret på hinanden. Byen består af aflange bygningskæder langs veje, hvorpå der er designet en linie, der kan bruges til at navigere området. Alt i alt fremstår den som en by både i udseende og funktion.

Efter flere iterationer kom vi frem til et design, der virker rigtig godt i byområdet. By-agenten er solidt bygget og arbejder for så vidt muligt i højden, for at den har let ved at bevæge sig på veje inde i byen uden at støde ind i bygninger eller vægge, fx under sving.

Robotten kan navigere i byen ved at bruge line following og har en kode, der håndterer dens opførsel, når den støder ind i et kryds i byen og flere rutemuligheder opstår. På grund af sensorproblemer og et uhensigtsmæssigt tungt program, overses kryds dog nogle gange, hvorved robotten ikke kører som planlagt. På samme måde som agenten navigerer i byområdet bruger den line following til at finde rundt i fællesområdet. Dette fungerer godt i store dele af banen, men grundet i de forskellige lysforhold på den store bane, kan robotten nogle gange miste linjen.

Agenten kan i teorien kommunikere med børnene v.h.a. Bluetooth. Dette er dog endnu ikke testet i praksis, da alle grupperne ikke er nået lige langt, hvorved dette ikke har været muligt endnu.

 

Leave a Reply