diff --git a/src/ve/ucv/ciens/ccg/nxtarbot/NxtAR_bot.java b/src/ve/ucv/ciens/ccg/nxtarbot/NxtAR_bot.java index 89bd2ee..638a535 100644 --- a/src/ve/ucv/ciens/ccg/nxtarbot/NxtAR_bot.java +++ b/src/ve/ucv/ciens/ccg/nxtarbot/NxtAR_bot.java @@ -29,6 +29,9 @@ import lejos.nxt.comm.NXTConnection; import ve.ucv.ciens.ccg.nxtarbot.threads.MotorControlThread; import ve.ucv.ciens.ccg.nxtarbot.threads.SensorReportThread; +/** + * Core class for the robot module of NxtAR. + */ public class NxtAR_bot{ private static DataOutputStream dataOutputStream; private static DataInputStream dataInputStream; @@ -36,6 +39,10 @@ public class NxtAR_bot{ private static MotorControlThread recvThread; private static SensorReportThread sendThread; + /** + *

Finishes the communication threads anc closes the Bluetooth data streams, + * then quits the application.

+ */ private static void quit(){ if(recvThread != null) recvThread.finish(); if(sendThread != null) sendThread.finish(); @@ -53,13 +60,23 @@ public class NxtAR_bot{ System.exit(0); } + /** + *

Application entry point.

+ *

Resets the motors, calibrates the light sensor and starts the + * networking threads.

+ * + * @param args Command line arguments. + */ public static void main(String[] args){ + // Set a listener to force quit if the ESCAPE button is pressed. Button.ESCAPE.addButtonListener(new QuitButtonListener()); + // Reset the rotation counts of the motors. Motor.A.resetTachoCount(); Motor.B.resetTachoCount(); Motor.C.resetTachoCount(); + // Start the light sensor and calibrate it. LightSensor lightSensor = new LightSensor(SensorPort.S1); lightSensor.setFloodlight(false); @@ -73,6 +90,8 @@ public class NxtAR_bot{ lightSensor.calibrateHigh(); System.out.println("--/--"); + // Connect with a Bluetooth device in raw mode. Then get the connection + // streams. bluetoothConnection = Bluetooth.waitForConnection(); bluetoothConnection.setIOMode(NXTConnection.RAW); dataOutputStream = bluetoothConnection.openDataOutputStream(); @@ -80,6 +99,7 @@ public class NxtAR_bot{ System.out.println("Connected"); + // Start the networking threads and wait for them to finish. sendThread = new SensorReportThread(dataOutputStream, lightSensor); recvThread = new MotorControlThread(dataInputStream); @@ -94,12 +114,21 @@ public class NxtAR_bot{ quit(); } + /** + *

Force quit button listener.

+ */ private static class QuitButtonListener implements ButtonListener{ + /** + * Force quit. + */ @Override public void buttonPressed(Button b) { quit(); } + /** + * Do nothing. + */ @Override public void buttonReleased(Button b){ } } diff --git a/src/ve/ucv/ciens/ccg/nxtarbot/threads/MotorControlThread.java b/src/ve/ucv/ciens/ccg/nxtarbot/threads/MotorControlThread.java index c732522..046a46a 100644 --- a/src/ve/ucv/ciens/ccg/nxtarbot/threads/MotorControlThread.java +++ b/src/ve/ucv/ciens/ccg/nxtarbot/threads/MotorControlThread.java @@ -23,19 +23,49 @@ import lejos.nxt.Battery; import lejos.nxt.Motor; import ve.ucv.ciens.ccg.nxtarbot.protocol.MotorMasks; +/** + *

Class to control the motors on the robot based on isntructions received via + * Bluetooth.

+ * + *

The instructions are codified on a very simple protocol:

+ *

+ */ public class MotorControlThread extends Thread{ private boolean done; private DataInputStream inputStream; - public MotorControlThread(DataInputStream inputStream){ + /** + * Create a new MotorControlThread. + * + * @param inputStream The stream to receive motor commands from. + * @throws NullPointerException If inputStream is null. + */ + public MotorControlThread(DataInputStream inputStream) throws NullPointerException{ + if(inputStream == null) + throw new NullPointerException("Input stream is null."); + done = false; this.inputStream = inputStream; } + /** + *

Marks this thread as ready to finish cleanly.

+ */ public void finish(){ done = true; } + /** + *

Receive and process motor control instructions via Bluetooth.

+ */ @Override public void run(){ boolean motorA, motorB, motorC, recenterMotorB; @@ -44,9 +74,11 @@ public class MotorControlThread extends Thread{ while(!done){ try{ + // Read the two bytes indicated by the protocol. message[0] = inputStream.readByte(); message[1] = inputStream.readByte(); + // Decode the instruction parameters. recenterMotorB = (message[0] & MotorMasks.RECENTER) > 0 ? true : false; motorA = (message[0] & MotorMasks.MOTOR_A) > 0 ? true : false; motorB = (message[0] & MotorMasks.MOTOR_B) > 0 ? true : false; @@ -54,6 +86,7 @@ public class MotorControlThread extends Thread{ direction = (message[0] & MotorMasks.DIRECTION) > 0 ? BasicMotorPort.FORWARD : BasicMotorPort.BACKWARD; if(motorA){ + // Set motor A to run at specified speed. Motor.A.setSpeed(message[1] * Battery.getVoltage()); if(direction == BasicMotorPort.FORWARD) Motor.A.forward(); @@ -62,6 +95,7 @@ public class MotorControlThread extends Thread{ } if(motorB){ + // Set motor B to run at specified speed. Motor.B.setSpeed(message[1] * Battery.getVoltage()); if(direction == BasicMotorPort.FORWARD) Motor.B.forward(); @@ -70,6 +104,7 @@ public class MotorControlThread extends Thread{ } if(motorC){ + // Set motor C to run at specified speed. Motor.C.setSpeed(message[1] * Battery.getVoltage()); if(direction == BasicMotorPort.FORWARD) Motor.C.forward(); @@ -78,6 +113,8 @@ public class MotorControlThread extends Thread{ } if(recenterMotorB){ + // Return motor B to it's origin. Rotate in the direction + // that implies less movement. tacho = Motor.B.getTachoCount() % 360; rotation = tacho > 180 ? 360 - tacho : -(tacho); Motor.B.rotate(rotation); @@ -85,6 +122,7 @@ public class MotorControlThread extends Thread{ } }catch(IOException io){ + // If disconnection terminate. done = true; } } diff --git a/src/ve/ucv/ciens/ccg/nxtarbot/threads/SensorReportThread.java b/src/ve/ucv/ciens/ccg/nxtarbot/threads/SensorReportThread.java index c3e48c8..bb31c08 100644 --- a/src/ve/ucv/ciens/ccg/nxtarbot/threads/SensorReportThread.java +++ b/src/ve/ucv/ciens/ccg/nxtarbot/threads/SensorReportThread.java @@ -20,21 +20,43 @@ import java.io.IOException; import lejos.nxt.LightSensor; +/** + *

Class to report the values read from the different sensors through a + * Bluetooth stream.

+ */ public class SensorReportThread extends Thread{ private boolean done; private LightSensor lightSensor; private DataOutputStream outputStream; - public SensorReportThread(DataOutputStream outputStream, LightSensor lightSensor){ + /** + *

Create a new SensorReportThread.

+ * + * @param outputStream The stream to send the data to. + * @param lightSensor An initialized and calibrated light sensor. + */ + public SensorReportThread(DataOutputStream outputStream, LightSensor lightSensor) throws NullPointerException{ + if(outputStream == null) + throw new NullPointerException("Output stream is null."); + + if(lightSensor == null) + throw new NullPointerException("Sensor is null."); + this.lightSensor = lightSensor; done = false; this.outputStream = outputStream; } + /** + *

Marks this thread as ready to finish cleanly.

+ */ public void finish(){ done = true; } + /** + *

Writes the values read from the light sensor to the output stream.

+ */ @Override public void run(){ byte message = 0; @@ -44,8 +66,8 @@ public class SensorReportThread extends Thread{ message = (byte)lightSensor.getLightValue(); outputStream.writeByte(message); outputStream.flush(); - }catch(IOException io){ + // If disconnection terminate. done = true; } }