Title: Treasure%20Hunt%20Challenge
1Treasure Hunt Challenge
- How to locate an obstacle
- using a Lego NXT robot
- with a Java Brain
- Bert G. Wachsmuth
- Seton Hall University
2The Goal
- Locate a "treasure", head towards it, and stop
when you reach it without touching - There will be 2 obstacles head towards the
closer one - Move autonomously toward the treasure.
3The Setup
- Differential drive robot with ultrasound distance
sensor mounted in front - Java VM uploaded to NXT
- Connection NXT lt-gt PC via USB or Bluetooth
- Eclipse setup for Java programming
- Eclipse configured for LeJOS
4The Strategy
- Turn a full 360 degrees
- Scan as you turn with distance sensor
- With each scan check distance and turn angle
- Find smallest distance recorded and corresponding
angle - Rotate towards the angle found
- Drive forward for (distance 15 cm)
5The Tasks
- Need to drive a specific distance
- function travel(distance)
- Need to turn a specific degree
- function turn(degrees)
- Need to turn and scan distances at the same time
- function scan()
- Need to be able to find a minimum
- build into scan function
6State of the Robot
- State variables determine the state of the robot,
i.e. its relevant parts and the information it
needs to keep track of to solve its task - In our case
- Left and right motor
- Ultrasonic sensor
- Driving speed
- Turning speed
- Minimum distance
- Minimum angle
7Program Outline
- // state variables
- leftMotor, rightMotor,
- sensor
- speedDrive, speedTurn
- minDistance, minHeading
- // program algorithm
- scan()
- turn(minHeading)
- travel(minDistance - 15)
8Program Implementation
- To implement our outline we need to know the
correct Java syntax as well as the particular
statements to control the NXT - Java syntax develop as we go
- NXT control LeJOS API (see online link for this
lecture) - You have me as resource ?
- Start Eclipse
- Create a new class Hunter in the NXT project
9Program Implementation (2)
- import lejos.nxt.
- public class Hunter
-
- static Motor leftMotor Motor.C
- static Motor rightMotor Motor.A
- static UltrasonicSensor sensornew
UltrasonicSensor(SensorPort.S1) - static int speedDrive 300.
- static int speedTurn 200
- static int minDistance 255
- static int minHeading 0
- public static void main(String args)
-
- scan()
- turn(minHeading)
- travel(minDistance - 15)
-
10Program Implementation (2)
- import lejos.nxt.
- public class Hunter
-
- static Motor leftMotor Motor.C
- static Motor rightMotor Motor.A
- static UltrasonicSensor sensor new
UltrasonicSensor(SensorPort.S1) - static int speedDrive 300
- static int speedTurn 200
- static int minDistance 255
- static int minHeading 0
- public static void main(String args)
-
- scan()
- turn(minHeading)
- travel(minDistance - 15)
11Program Implementation (3)
- To get the program to compile correctly, we need
to define the functions scan, turn, and
travel. Add the following after the main
function - / Rotates 360 degrees and scans distances.
Modifies state - variables "minDistance" and "minHeading to
contain - directions to the closest object when done. /
- public static void scan()
-
-
- / Turns clockwise by the indicated angle /
- public static void turn(int angle)
-
-
- / Drive forward by the indicated distance in cm
/ - public static void travel(int distance)
-
-
12Program Implementation (4)
- The program should have no errors at this point
save it - We could download it to the NXT dont do it
- The program works theoretically only - if you
execute the program, nothing will happen - We need to carefully implement and test the
individual functions we defined but left blank
so far.
13Function Implementation travel
- Purpose
- drive forward by specified distance (in cm)
- Input
- positive integer distance to specify how far to
travel forward - Output
- none
- State change
- robot has moved forward by the indicated
positive distance
14Function Implementation travel
- public static void travel(int distance)
-
- int numDegrees (int)Math.round(distance20.1f
) //convert to deg - leftMotor.setSpeed(speedDrive)
//set left motor - leftMotor.resetTachoCount()
- rightMotor.setSpeed(speedDrive)
//set right motor - rightMotor.resetTachoCount()
- leftMotor.forward()
//engines on! - rightMotor.forward()
- while ((leftMotor.getTachoCount() lt
numDegrees) // check both - (rightMotor.getTachoCount() lt
numDegrees)) // encoders -
- if (leftMotor.getTachoCount() gt numDegrees)
// if left is - leftMotor.stop()
// done turn off - if (rightMotor.getTachoCount() gt
numDegrees) // if right is - rightMotor.stop()
// done turn off -
- leftMotor.stop()
// to be sure - rightMotor.stop()
// to be sure
15Test Function travel
- To test the travel function, we modify main
as follows - import lejos.nxt.
- public class Hunter
-
- // state variables as before (not shown here
) - public static void main(String args)
-
- travel(20)
- /
- scan()
- turn(minHeading)
- travel(minDistance - 15)
- /
-
- // rest of the code, including travel
function -
16Function Implementation turn
- Purpose
- turn clockwise by indicated amount (in degrees)
- Input
- positive integer to specify angle by which to
rotate - Output
- none
- State change
- robot has turned clockwise by the indicated
positive angle
17Function Implementation turn
- The turn function is similar to travel,
except that the motors need to turn in opposite
direction. But for a motor going backwards the
encoder is negative, necessitating some more
changes (in green). - public static void travel(int distance)
-
- int numDegrees (int)Math.round(distance20.1f
) //convert to deg - leftMotor.setSpeed(speedDrive)
//set left motor - leftMotor.resetTachoCount()
- rightMotor.setSpeed(speedDrive)
//set right motor - rightMotor.resetTachoCount()
- leftMotor.forward()
//engines on! - rightMotor.forward()
- while ((leftMotor.getTachoCount() lt
numDegrees) // check both - (rightMotor.getTachoCount() lt
numDegrees)) // encoders -
- if (leftMotor.getTachoCount() gt numDegrees)
// if left is - leftMotor.stop()
// done turn off - if (rightMotor.getTachoCount() gt
numDegrees) // if right is - rightMotor.stop()
// done turn off -
18Test Function turn
- Testing the turn function is similar to testing
travel - Keep unnecessary statements commented out
- Enter a turn(270) command (or any other degree)
- Download and execute
- You might need a few iterations of running the
test program until you get the conversion factor
right.
19Function Implementation scan
- Purpose
- finds distance and heading to closest object
- Input
- no input
- Output
- no output
- State change
- robot is in same position as before (one full
rotation) - minDistance contains distance to closest object
(in cm) - minHeading contains clockwise angle towards
closest object (in positive degrees)
20Function Implementation scan
- Similar to the turn function with the following
modifications - Should always turn 360 degrees for a full sweep
- Must initialize the sensor to continuous mode
- Must initialize the minDistance state variable
to 255 - Inside while loop read sensor distance and
store in variable distance - if distance less than minDistance then
- Set minDistance to distance (because we just
found a new min dist) - Set minHeading to current heading
- You can compute the heading in degrees by
checking one of the encoders and using the
conversion factor, somehow
21Test Function scan
- You test the scan function similar to before, but
since the state variables change, you need to
check them. Here is some sample code of the main
function (the original while loop is still
commented out) - // this is where the program starts
- public static void main(String args) throws
Exception -
- scan()
- LCD.drawString("Distance " minDistance, 1,
2) - LCD.drawString("Heading " minHeading, 1,
3) - Button.ENTER.waitForPressAndRelease()
- /
- as before, no change
- /
-
-
22Putting everything together
- If you are satisfied with the performance of
travel, turn, and scan individually, restore the
original code by removing the comment symbols - Test the performance of your robot by placing
obstacles on either side before executing the
program - Your robot should function in many cases, but not
always - It might miss the obstacle during the scan and
head in the wrong direction entirely - It might detect the obstacle and drive in the
approximately right direction, but end up on the
side of the obstacle, not in front - It has no way to correct any errors (open loop
solution)
23Problem with this Strategy
- Distance sensor has a scanning cone and may
pick up objects that are not straight ahead.
24Iterative Strategy (closed loop)
- Turn a full 360 degrees
- Scan as you turn with distance sensor
- With each scan check distance and turn angle
- Find smallest distance recorded and corresponding
angle - Rotate towards the angle found
- Drive forward for 1/2 the distance
- If not yet close enough, go to step 1 and repeat
25New Program Outline
- import lejos.nxt.
- public class Hunter
-
- // all state variables are unchanged
- public static void main(String args)
-
- while (minDistance gt 15)
-
- scan()
- turn(minHeading)
- travel(minDistance/2)
-
-
- // travel, turn, and scan are unchanged
26Putting everything together
- Test the performance of your robot by placing
obstacles on either side before executing the
program - Does your new strategy work better than the open
loop one from before? - Your robot should function in principle, but
there is still room for improvement - Your robot executes one additional turn even
though it is already close to the treasure (easy
to fix) - Your robot always turns clockwise, even if it
would be more efficient to sometimes turn
counter-clockwise (tricky to fix)
27Improvements
- Iterative solution is closed loop and
self-correcting but still disruptive and slow.
A better possible solution might be - Perform full 360-scan for shortest distance
heading - Travel in the found direction as long as distance
is decreasing (keep scanning) - If distance is no longer decreasing perform
40-degree scan in either direction - If object is reacquired, go to step 2 unless
distance is too small - If object is not reacquired, go to step 1