Date: 10-11. Januar 2010
Duration of activity: 10 hours
Group members participating: Heine Stokholm, Michael Vilhelmsen og Mads Møller Jensen
Group members participating: Heine Stokholm, Michael Vilhelmsen og Mads Møller Jensen
Dagens mål
- Optimere banen med tyndere streger
- Optimere robotten til den nye bane
- Få computeren til at lave en grafisk repræsentation af banen ud fra de informationer, den modtager fra robotten
- Gøre så den grafiske repræsentation kan bruges til at navigere med robotten.
Banen
Vi fik vha. gaffatape skabt en ny midterlinje på banen. Den nye midterlinje er 1,2 cm modsat de "gamle" streger, som var 2,5 cm. Det betyder at robotten kommer længere ind mod midten af banemodulerne, og vi undgår at den sidder fast i kanten af pladen. Den nye gaffatape har en anden farve end den "gamle", og vi har derfor været nød til at regulere PID-systemet endnu en gang. Derudover gør den nye tynde midterstribe, at robotten kan skyde over linjen, når den drejer de 90 grader. Derfor har vi lavet en sikkerhedsmekanisme, som gør, at robotten søger efter en grå linje, inden PID-systemet bliver slået til.
PID-systemet
Sikkerhedsmekanismen
public void findLine() throws Exception{
//if we are on the grey line we return
if(cs.green()) return;
//else we turn slowly right to find it
int time = 0;
while(time < 45){
tachoNav.rotate(1);
if(cs.green()) return;
time++;
Thread.sleep(10);
}
//if we still haven't found it we turn 90 degrees left and check for it
time = 0;
while(time < 90){
tachoNav.rotate(-1);
if(cs.green()) return;
time++;
Thread.sleep(10);
}
}
Vi vil nu gennemgå alle metoder kort og forklare hvad de enkelte metoder bruges til i programmet.
Først har vi getIntFromTile(Tile t). Den tager et tile som input og returnerer så den int værdi som svarer til tilens opbygning. Vi har specificeret en værdi for alle ti forskellige tiles så vi kunne nøjes med at sende den int over bluetooth istedet for at sende hele tilet.
Derefter kommer map() metoden som er backbone i hele vores program. Den styrer den sekventielle gennemgang af vores program og vi vil nu gå et gennemløb af koden igennem.
Når map bliver kaldt første gang starter den med at tilføje et nyt tile der hvor den står(1). Derefter kommer vi ind i et while loop der bliver kørt indtil vi er færdig med at mappe banen(2).
Vi kalder derefter getDirections() for at undersøge hvilken slags tile vi står på(3).
Når vi er færdige med at undersøge tilen vi står på skal vi bestemme hvilken retning vi nu vil køre i. I første omgang starter vi med at undersøge om en af de fire omkring liggende tiles har veje der mangler at bliver udforsket(4) og hvis ikke kalder vi metoden goToNull()(8) der finder den nærmeste tile der ikke er udforsket.
Hvis vi har fundet en tile skal vi nu køre derhen. Vi starter med at finde den grå linie(5), så kalder vi lineFollow()(6) og derefter kører robotten bare ligeud indtil den ser den sorte markering med sin sekundære sensor(7).
Når vi er færdige med at mappe banen starter vi med at sende mappet(9), for derefter at gå ind i et loop der venter på en int fra computeren(10) og kører hen til den tile der svarer til den modtagne int(11).
Først har vi getIntFromTile(Tile t). Den tager et tile som input og returnerer så den int værdi som svarer til tilens opbygning. Vi har specificeret en værdi for alle ti forskellige tiles så vi kunne nøjes med at sende den int over bluetooth istedet for at sende hele tilet.
//returns the int that represents the given tile
public int getIntFromTile(Tile t){
if(t.getNorth().isEmpty() && t.getEast().isEmpty()) return 0;
if(t.getSouth().isEmpty() && t.getEast().isEmpty()) return 1;
if(t.getNorth().isEmpty() && t.getWest().isEmpty()) return 2;
if(t.getSouth().isEmpty() && t.getWest().isEmpty()) return 3;
if(t.getNorth().isEmpty() && !t.getSouth().isEmpty() && !t.getWest().isEmpty() && !t.getEast().isEmpty()) return 4;
if(!t.getNorth().isEmpty() && !t.getSouth().isEmpty() && !t.getWest().isEmpty() && t.getEast().isEmpty()) return 5;
if(!t.getNorth().isEmpty() && t.getSouth().isEmpty() && !t.getWest().isEmpty() && !t.getEast().isEmpty()) return 6;
if(!t.getNorth().isEmpty() && !t.getSouth().isEmpty() && t.getWest().isEmpty() && !t.getEast().isEmpty()) return 7;
if(t.getWest().isEmpty() && t.getEast().isEmpty()) return 8;
if(t.getNorth().isEmpty() && t.getSouth().isEmpty()) return 9;
return 10;
}
Derefter kommer map() metoden som er backbone i hele vores program. Den styrer den sekventielle gennemgang af vores program og vi vil nu gå et gennemløb af koden igennem.
Når map bliver kaldt første gang starter den med at tilføje et nyt tile der hvor den står(1). Derefter kommer vi ind i et while loop der bliver kørt indtil vi er færdig med at mappe banen(2).
Vi kalder derefter getDirections() for at undersøge hvilken slags tile vi står på(3).
Når vi er færdige med at undersøge tilen vi står på skal vi bestemme hvilken retning vi nu vil køre i. I første omgang starter vi med at undersøge om en af de fire omkring liggende tiles har veje der mangler at bliver udforsket(4) og hvis ikke kalder vi metoden goToNull()(8) der finder den nærmeste tile der ikke er udforsket.
Hvis vi har fundet en tile skal vi nu køre derhen. Vi starter med at finde den grå linie(5), så kalder vi lineFollow()(6) og derefter kører robotten bare ligeud indtil den ser den sorte markering med sin sekundære sensor(7).
Når vi er færdige med at mappe banen starter vi med at sende mappet(9), for derefter at gå ind i et loop der venter på en int fra computeren(10) og kører hen til den tile der svarer til den modtagne int(11).
public void map() throws Exception{ //add the starting position to the map Tile start = new Tile(new Position(x,y)); (1) map.add(start); ma[x][y] = start; //loop until no tiles have a null pointer while(!finished()){ (2) //Check all the road that are null on a given tile checkDirections(); (3) //if we arent finished we move to a new tile if(!finished()){ Sound.twoBeeps(); int se = dir; //we checks if one of the four enclosing tiles has a nullpointer //and rotate to that direction if it does //We always starts with north boolean found = false; if(!ma[x][y].getNorth().isEmpty() && !found){ (4) if(ma[x][y+1].getNorth() == null || ma[x][y+1].getEast() == null || ma[x][y+1].getWest() == null || ma[x][y+1].getSouth() == null){ int rot = 90*(n-dir); if(rot < -180) rot = 90; if(rot > 180) rot = -90; tachoNav.rotate(rot, false); dir = 1; found = true; } } if(!ma[x][y].getEast().isEmpty() && !found){ ~~ } if(!ma[x][y].getSouth().isEmpty() && !found){ ~~ } if(!ma[x][y].getWest().isEmpty() && !found){ ~~ } //if we have found a tile that needs checking we drive there if(found){ //we update the position of the robot if(dir == 1) y++; if(dir == 2) x++; if(dir == 3) y--; if(dir == 4) x--; //tries to locate the gray line findLine();(5) //and use a pid line follower lineFollow();(6) //afterwards we drive forward until we see black on the secondary sensor tachoNav.stop(); tachoNav.forward(); while(secondaryColor.light() > secondaryColor.getBlackLightValue() + 100){}(7) tachoNav.stop(); Thread.sleep(500); //if no tile is found with null we find the shortest route to a tile with null and drives there }else{ goToNull(); (8) } } } //when we are finished mapping we tries to send our map sendMap();(9) //when finished we can control the robot from the computer while(true){ LCD.drawString(waiting,0,0); LCD.refresh(); //we wait for a incoming bluetooth connection BTConnection btc = Bluetooth.waitForConnection();(10) LCD.clear(); LCD.drawString(connected,0,0); LCD.refresh(); DataInputStream dis = btc.openDataInputStream(); //then we go to the tile that the int received represents goToStart(dis.readInt());(11) //and close the connections to start over dis.close(); Thread.sleep(100); // wait for data to drain LCD.clear(); LCD.drawString(closing,0,0); LCD.refresh(); btc.close(); LCD.clear(); } }
I checkDirections() gør vi følgende for alle fire retninger:
Checker om den allerede er undersøgt. (1)
Hvis ikke drejer vi robotten den retning. (2)
Måler om der er sort eller ej. (3)
Og opdaterer tiles afhængig af hvad vi målte.(4)
public void checkDirections() throws Exception{ //we get the tile on thors current position Tile current = ma[x][y]; try{ Thread.sleep(100); int tempDir = dir; //we loops four times to check all four ways the robot can leave the tile //we start by checking the direction we are currently facing and then turn right for(int i = 0; i<4; i++){ if(tempDir == 1){ //we only check the road if we don't know where it leads if(current.getNorth() == null){(1) //we rotate the robot to point the right direction int rot = 90*(n-dir); if(rot < -180) rot = 90; if(rot > 180) rot = -90; tachoNav.rotate(rot, false);(2) dir = 1; //if we dont see black if(!(cs.light() < cs.getGreenLightValue() - 50)){(3) Tile temp; //we get or create the tile in that direction(4) if(ma[x][y+1] != null){ temp = ma[x][y+1]; }else{ temp = new Tile(new Position(x,y+1)); } //and updates the references current.setNorth(temp); temp.setSouth(current); map.add(temp); ma[x][y+1] = temp; Sound.beep(); }else{ //else we point to the empty tile to symbolize a blocked road current.setNorth(emptyTile); } } Thread.sleep(100); } if(tempDir == 2){ if(current.getEast() == null){ ~~ } Thread.sleep(100); } if(tempDir == 3){ if(current.getSouth() == null){ ~~ } Thread.sleep(100); } if(tempDir == 4){ if(current.getWest() == null){ ~~ } } tempDir = tempDir + 1; if(tempDir == 5) tempDir = 1; } }catch(Exception e){ LCD.clear(); LCD.drawString(e.toString(),0,0); LCD.refresh(); Thread.sleep(5000); } Thread.sleep(300); }
Den sidste metode vi har valgt at gennemgå her har det noget vildledende navn goToStart(int t). Den gør faktisk det at den tager en int og ud fra den bruger den dijkstra til at finde den korteste rute hen til den tile.(1) Derefter har den så en løkke hvor kører derhen en tile af gangen.(2) Måden vi kører rundt mellem tilene er magen til den tidligere omtalt map() metode så det vil jeg ikke komme nærmere ind på her.
public void goToStart(int t) throws Exception{
// we start by finding the tile that is at position t
// our tiles are mapped like this:
//012
//345
//678
// and tlx,tly is the position of number 0
int tempx = 0;
int tempy = 0;
if(t == 0){
tempx = tlx;
tempy = tly;
}else if(t == 1){
tempx = tlx+1;
tempy = tly;
}else if(t == 2){
tempx = tlx+2;
tempy = tly;
}else if(t == 3){
tempx = tlx;
tempy = tly-1;
}else if(t == 4){
tempx = tlx+1;
tempy = tly-1;
}else if(t == 5){
tempx = tlx+2;
tempy = tly-1;
}else if(t == 6){
tempx = tlx;
tempy = tly-2;
}else if(t == 7){
tempx = tlx+1;
tempy = tly-2;
}else if(t == 8){
tempx = tlx+2;
tempy = tly-2;
}
if(tempx != x || tempy != y){
//We find the shortest route using dijkstra
Tile[] route = shortestRoute(ma[x][y], map, ma[tempx][tempy]);(1)
//the tile the robot is located on
Tile current = ma[x][y];
int i = 9;
while(route[i] == null) i--;
i--;
Tile next = route[i];
boolean f = false;
//while we haven't reached our goal
while(!f){(2)
//we check which way is next and rotate that way
if(next == current.getNorth()){
int rot = 90*(n-dir);
if(rot < -180) rot = 90;
if(rot > 180) rot = -90;
tachoNav.rotate(rot, false);
y = y + 1;
dir = 1;
}else if(next == current.getEast()){
~~
}else if(next == current.getSouth()){
~~
}else if(next == current.getWest()){
~~
}
//then we find the gray line
findLine();
//and use our pid line follower
lineFollow();
//drive forward until secondary sees black
tachoNav.forward();
while(secondaryColor.light() > secondaryColor.getBlackLightValue() + 100){}
tachoNav.stop();
Thread.sleep(500);
//and updates how far in the route we have gone
if(i == 1){
f = true;
}else{
current = next;
i--;
next = route[i];
}
}
}
}
Den grafiske repræsentation
Status
Ingen kommentarer:
Send en kommentar