import lejos.nxt.*;
public class MazeNavi // error located at line 344
{
static TouchSensor touch1 = new TouchSensor(SensorPort.S1); // touch1.isPressed() <--boolean
static TouchSensor touch2 = new TouchSensor(SensorPort.S4); // ...&& touch2.isPressed()
static LightSensor light = new LightSensor(SensorPort.S2); // light.read(Normalized)Value()
static SoundSensor sound = new SoundSensor(SensorPort.S3); // sound.readValue <--(0-100)?
/*
NEED TO REMEMBER:
Motor.A : right wheel -- rotate to turn left
Motor.C : left wheel -- rotate to turn right
*/
private static int RED; // can go left, right, or straight, should stop and poll here
private static int START_COLOR; // finishes when this color is seen
private static int END_COLOR; // reads stacked values from MemArray once this color is seen
public static final int CLAP_THRES = 70; // the threshold for a clap, this is *important*
// INPUT DATA
public static final int MAZE_WIDTH = 4;
public static final int MAZE_LENGTH = 5;
public static final int MAZE_START_W = 1;
public static final int MAZE_START_L = 1;
public static final int MAZE_START_DIR = 3; // the starting direction
public static final int MAZE_END_W = 2;
public static final int MAZE_END_L = 3;
// END INPUT DATA
private static int direction = MAZE_START_DIR;
/*
(relative to x-y coordinate plane of maze given by MAZE_START_W & MAZE_START_L)
1 : north
2 : west
3 : south
4 : east
turn left : ++
turn right : --
*/
private static boolean[][] map = new boolean[MAZE_WIDTH][MAZE_LENGTH]; // Array containing information for all of the blocks
/*
false : not been traversed
true : has been traversed
index of 0,0 : southwestern most block
*/
private static int mapIndexW = MAZE_START_W, mapIndexL = MAZE_START_L;
public static final int NUM_SQUARES = MAZE_LENGTH * MAZE_WIDTH; // the total number of squares in the maze
public static final int THRESHOLD = 20; // the threshold for seeing colors
public static final int AVG_SPEED = 200;
public static final int MAX_SPEED = 400;
public static final long PAUSE = 300;
public static final long CLAP_PAUSE_TOT = 2000; // total amount of time to wait for a clap, in ms
public static final int CLAP_REPS = 20;
// public static final double ROBO_LENGTH = 205;
public static final double CLAP_PAUSE = CLAP_PAUSE_TOT / CLAP_REPS;
public static final double BLOCK_SIZE = 279.4; // the *exact* size of one square, in mm
public static final int ADJ_RATIO = (int)BLOCK_SIZE/3;
public static final double WHEEL_CIRC = 173; // the *exact* circumference of one wheel, in mm
public static final double MM_PER_DEGREE = WHEEL_CIRC / 360;
public static final int BLOCK_DEGREES = (int)(BLOCK_SIZE / MM_PER_DEGREE)+1; // the amount of degrees to rotate to travel one square
public static final int ONEEIGHTY_TURN_DEGREES = 303; // the amount of degrees to rotate one wheel to turn at a 90 degree angle
public static final int TURN_DEGREES = 150;
private static boolean readMem = false; // should be true when END_COLOR is read, writesMem when false
private static boolean victory = false; // should be true when making a decision on which direction to go
private static boolean touched = false; // should be true when touch1.isPressed() || touch2.isPressed()
private static boolean calibrate = true;
private static boolean checkFinish = true;
private static boolean moved, noGood;
private static boolean wait;
private static int c = 0;
private static int value;
private static int x;
private static int[] memArray = new int[NUM_SQUARES]; // Array containing all of the correct decisions at areas where touch sensor is activated, or green squares
/*
0 : go straight -- should only be necessary on green squares
1 : turn right
2 : turn left
*/
private static int memIndex = 1; // index of memArray
public static void main (String[] aArg) throws Exception
{
light.setFloodlight(true);
Motor.A.regulateSpeed(true);
Motor.C.regulateSpeed(true);
//Motor.A.smoothAcceleration(true);
//Motor.C.smoothAcceleration(true);
map[MAZE_START_W][MAZE_START_L] = true;
while(calibrate)
{
if(touch1.isPressed() || touch2.isPressed())
{
value = light.readNormalizedValue();
if(c == 0)
{
RED = value;
Thread.sleep(500);
RED = RED + light.readNormalizedValue();
RED = RED / 2;
LCD.drawInt(RED, 0, 0);
LCD.refresh();
Thread.sleep(5000);
LCD.clear();
}
/*else if(c == 1)
{
END_COLOR = value;
Thread.sleep(500);
END_COLOR += light.readNormalizedValue();
END_COLOR /= 2;
LCD.drawInt(END_COLOR, 0, 0);
LCD.refresh();
Thread.sleep(5000);
LCD.clear();
}
else if(c == 2)
{
START_COLOR = value;
Thread.sleep(500);
START_COLOR += light.readNormalizedValue();
START_COLOR /= 2;
LCD.drawInt(START_COLOR, 0, 0);
LCD.refresh();
Thread.sleep(5000);
LCD.clear();
}*/
else if(c == 2)
{
LCD.clear();
calibrate = false;
}
c++; //hehe
}
}
memArray[0] = 3; // set initial value to three to prevent an array out of bounds exception
while(!Button.ESCAPE.isPressed() && !victory)
{
try{ Thread.sleep((long)PAUSE); }
catch(Exception e) {}
update();
if (!readMem) // finding the end
{
if (!touched)
{
if (light.readNormalizedValue()RED-THRESHOLD)
startDecisionSeq(0);
}
}
else // retracing back to start
{
if(!touched)
{
if (mapIndexW == MAZE_START_W && mapIndexL == MAZE_START_L)//light.readNormalizedValue()START_COLOR-THRESHOLD)
victory();
else if (light.readNormalizedValue()RED-THRESHOLD)
startRevDecisionSeq();
}
}
touched = false;
moveForward(true);
} // end of main loop
}
public static void moveForward(boolean check)
{
Motor.A.rotate(BLOCK_DEGREES, true);
Motor.C.rotate(BLOCK_DEGREES, false);
if(touch1.isPressed() || touch2.isPressed())
{
if(check)
{
touched = true;
if(!readMem)
startDecisionSeq(0);
else
startRevDecisionSeq();
}
}
else
{
if(direction == 1) // checking north
mapIndexL++;
else if(direction == 2) // checking west
mapIndexW--;
else if(direction == 3) // checking south
mapIndexL--;
else if(direction == 4) // checking east
mapIndexW++;
map[mapIndexW][mapIndexL] = true;
}
update();
if (mapIndexW == MAZE_END_W && mapIndexL == MAZE_END_L && checkFinish)//light.readNormalizedValue()START_COLOR-THRESHOLD)
{
startEndSeq();
checkFinish = false;
}
}
public static void update()
{
LCD.clear();
LCD.drawInt(light.readNormalizedValue(), 0, 0);
LCD.drawInt(mapIndexW, 0, 2);
LCD.drawInt(mapIndexL, 2, 2);
if(direction == 1) // checking north
LCD.drawString("Facing North", 0, 4);
else if(direction == 2) // checking west
LCD.drawString("Facing West", 0, 4);
else if(direction == 3) // checking south
LCD.drawString("Facing South", 0, 4);
else if(direction == 4) // checking east
LCD.drawString("Facing East", 0, 4);
if (light.readNormalizedValue()RED-THRESHOLD)
LCD.drawString("RED!", 0, 6);
LCD.refresh();
}
public static void checkDirection()
{
if(direction > 4)
direction = direction - 4;
else if(direction < 1)
direction = direction + 4;
}
public static boolean checkMap(int direction)
{
if(direction == 1 || direction == 5) // checking north
{
if(mapIndexL < MAZE_LENGTH-1)
return map[mapIndexW][mapIndexL+1];
else
return true;
}
else if(direction == 2) // checking west
{
if(mapIndexW > 0)
return map[mapIndexW-1][mapIndexL];
else
return true;
}
else if(direction == 3) // checking south
{
if(mapIndexL > 0)
return map[mapIndexW][mapIndexL-1];
else
return true;
}
else if(direction == 4 || direction == 0) // checking east
{
if(mapIndexW < MAZE_WIDTH-1)
return map[mapIndexW+1][mapIndexL];
else
return true;
}
else // something's wrong -- report error
{
LCD.drawString("Error: Invalid direction passed", 0, 6);
LCD.refresh();
try {Thread.sleep(2000);}
catch (Exception e){}
return false;
}
}
public static void startDecisionSeq(int dir)
{
if(touched)
{
readjust();
turnLeft();
dir++;
turn(dir);
}
else
{
turn(dir);
}
}
public static void readjust()
{
Motor.A.stop();
Motor.C.stop();
Motor.A.rotate((-1*ADJ_RATIO), true);
Motor.C.rotate((-1*ADJ_RATIO), false);
}
public static void waitForClap(int dir)
{
int i=0;
wait = true;
Motor.A.stop();
Motor.C.stop();
if(dir<2)
{
while(i CLAP_THRES)
{
wait = false;
if(dir == 0)
turnLeft();
else if(dir == 1)
turnAround();
}
i++;
}
}
}
public static void turn(int dir)
{
waitForClap(dir);
if(!wait)
{
dir++;
waitForClap(dir);
if(!wait && !touched)
dir++;
memArray[memIndex] = dir;
memIndex++;
moveForward(true);
}
else if(touched) // should have already turned left, dir = 1
{
moveForward(false);
if(touch1.isPressed() || touch2.isPressed()) // if this way's no good
{
readjust();
turnAround();
dir++; // it should equal 2 now
moveForward(false);
if(touch1.isPressed() || touch2.isPressed()) // if this way's no good, either...dead end?
{
readjust();
escape();
}
else
memArray[memIndex] = dir;
memIndex++;
}
else // that worked...i guess
{
memArray[memIndex] = dir;
memIndex++;
}
}
else // it was a red square...what to do...dir = 0
{
moved = false;
if(!checkMap(direction)) // have I been here before..?
{
moveForward(false); //// <----THIS IS THE CODE THAT MESSED ME UP, it detects a red square, then moves forward if it can, then makes the universal moveForward(true) call built into the end of the loop (line 156), thus skipping every second red square.
moved = true;
noGood = false;
}
else noGood = true;
if((touch1.isPressed() || touch2.isPressed()) || noGood) // if this way's no good
{
if(moved)
readjust();
moved = false;
turnLeft();
dir++; // now it's 1
if(!checkMap(direction)) // have I been here before..?
{
moveForward(false);
moved = true;
noGood = false;
}
else noGood = true;
if((touch1.isPressed() || touch2.isPressed()) || noGood) // if this way's no good
{
if(moved)
readjust();
moved = false;
turnAround();
dir++; // now it's 2
if(!checkMap(direction)) // have I been here before..?
{
moveForward(false);
moved = true;
noGood = false;
}
else noGood = true;
if((touch1.isPressed() || touch2.isPressed()) || noGood) // if this way's no good, either...dead end?
{
if(moved)
readjust();
moved = false;
escape();
}
else // that worked...i guess
{
memArray[memIndex] = dir;
memIndex++;
}
}
else // that worked...i guess
{
memArray[memIndex] = dir;
memIndex++;
}
}
else // that worked...i guess
{
memArray[memIndex] = dir;
memIndex++;
}
}
}
public static void escape()
{
int dir;
readMem = true;
touched = false;
turnRight(); // last resort pos is always right, so turn right again to turn around
moveForward(false);
while(readMem)
{
if(touch1.isPressed() || touch2.isPressed())
{
touched = true;
startRevDecisionSeq(); // face the direction from which you came
turnAround();
if(!checkMap(direction+1) && readMem) // check left
{
turnLeft();
dir = 1;
moveForward(false);
if(touch1.isPressed() || touch2.isPressed())
{
readjust();
turnRight();
}
else
{
memIndex++;
memArray[memIndex] = dir;
readMem = false;
}
}
if(!checkMap(direction-1) && readMem) // check right
{
turnRight();
dir = 2;
moveForward(false);
if(touch1.isPressed() || touch2.isPressed())
{
readjust();
turnLeft();
}
else
{
memIndex++;
memArray[memIndex] = dir;
readMem = false;
}
}
if(readMem)
{
turnRight();
escape();
}
}
else if (light.readNormalizedValue()RED-THRESHOLD)
{
startRevDecisionSeq(); // face the direction from which you came
turnAround();
if(!checkMap(direction) && readMem) // check ahead
{
dir = 0;
moveForward(false);
if(touch1.isPressed() || touch2.isPressed())
{
readjust();
}
else
{
memIndex++;
memArray[memIndex] = dir;
readMem = false;
}
}
if(!checkMap(direction+1) && readMem) // check left
{
turnLeft();
dir = 1;
moveForward(false);
if(touch1.isPressed() || touch2.isPressed())
{
readjust();
turnRight();
}
else
{
memIndex++;
memArray[memIndex] = dir;
readMem = false;
}
}
if(!checkMap(direction-1) && readMem) // check right
{
turnRight();
dir = 2;
moveForward(false);
if(touch1.isPressed() || touch2.isPressed())
{
readjust();
turnLeft();
}
else
{
memIndex++;
memArray[memIndex] = dir;
readMem = false;
}
}
if(readMem)
{
turnRight();
escape();
}
}
touched = false;
moveForward(false);
}
}
public static void startEndSeq()
{
if(touched)
readjust();
else
{
//Motor.A.rotate(BLOCK_DEGREES/2, true);
//Motor.C.rotate(BLOCK_DEGREES/2, false);
}
if(touch1.isPressed() || touch2.isPressed())
{
readjust();
}
for(int i=0; i<2; i++)
{
Sound.playTone((int)(501+Math.random()*1000), 100);
light.setFloodlight(false);
try{ Thread.sleep((long)500); }
catch(Exception e) {}
light.setFloodlight(true);
try{ Thread.sleep((long)500); }
catch(Exception e) {}
}
turnAround();
readMem = true;
}
public static void startRevDecisionSeq()
{
if(touched)
readjust();
else
{
//Motor.A.rotate(BLOCK_DEGREES/2, true);
//Motor.C.rotate(BLOCK_DEGREES/2, false);
}
if(memArray[memIndex] == 0) // go straight
memIndex--;
else if(memArray[memIndex] == 1) // turn right
{
turnRight();
memIndex--;
}
else if(memArray[memIndex] == 2) // turn left
{
turnLeft();
memIndex--;
}
else if(memArray[memIndex] == 3) // array out of bounds...assume victory
{
victory();
}
}
public static void turnRight()
{
Motor.A.stop();
Motor.C.stop();
Motor.C.rotate(TURN_DEGREES, true);
Motor.A.rotate(-1*TURN_DEGREES, false);
direction--;
checkDirection();
update();
}
public static void turnLeft()
{
Motor.A.stop();
Motor.C.stop();
Motor.A.rotate(TURN_DEGREES, true);
Motor.C.rotate(-1*TURN_DEGREES, false);
direction++;
checkDirection();
update();
}
public static void turnAround()
{
Motor.A.stop();
Motor.C.stop();
Motor.C.rotate(ONEEIGHTY_TURN_DEGREES, true);
Motor.A.rotate(-ONEEIGHTY_TURN_DEGREES, false);
direction = direction + 2;
checkDirection();
update();
}
public static void victory()
{
Motor.A.stop();
Motor.C.stop();
victory = true;
while(Button.ESCAPE.isPressed() == false) // victory dance
{
Sound.playTone((int)(501+Math.random()*1000), 100);
light.setFloodlight(false);
try{ Thread.sleep((long)500); }
catch(Exception e) {}
light.setFloodlight(true);
try{ Thread.sleep((long)500); }
catch(Exception e) {}
}
}
}