Programming Mindstorms NXT using Java
Introduction
The aim of this tutorial is to introduce programming Lego Mindstorms NXT robot using Java Programming Language. You will perform several exercises that will go enforce all the Java programming concepts covered so far.
Background
The Lego Mindstorm NXT has a computer processor that can be programmed to perform different operations. To write, compile and run your Java programs, use Dr. Java IDE. When you run your program, the Java program is executed on NXT processor via the Bluetooth connection. The latter is possible due to prexisting java class files (already written by someone) grouped into a Java Archive (.jar), which is similar to zipping up bunch of files. These java class files are packaged into iCommand.jar and RXTX.jar and contain instructions such as to control NXT motors, working with sensor input and output, and sending files to the NXT via Bluetooth protocol.
Setup
- Your group must have one NXT and one Bluetooth dongle connected to the USB port on the computer.
- There is lenghty setup process for things to work but this stage is already done for you. In case you ever decide to work NXT and Java at home then you want to follow these links:
- Download the NXTRover.zip file onto your computer and unzip it.
- In Dr. Java, open (exsisting) project called Rover.pjt
- Click on Project > Open , browse the folder NXTRover to get the Rover.pjt
Details about NxtRover class in NxtRover.java (DO NOT EDIT THIS FILE!!)
The NXTRover.java contains the class (template) for creating NxtRover objects i.e. it describes a real world entity, the rover, which is a moving vehicle. Rover is actually Bristish automobile manufacturing company, but we call our automobile the NxtRover. The Lego NXT and lego parts are setup such that it looks like a moving vehicle and is called the NXTRover. The class conatins data fields (state) and methods (object behavior) that NXT Rover.
Data fields: The rover object has three data fields:
- Motor left
- Motor right
- double countPerDegree
The instance variables left and right represent the left and right wheels of the rover and are of reference type Motor. The Motor class (already written by someone) is a template that describes data and behavior for a rotating the a particular wheel. In objects terminology, the the Motor object models part of the problem - the problem being NXTRover vehicle. Since we need two wheels, the NXTRover class has two Motor objects i.e. left and right.
The NXTRover has additional field called countPerDegree of primitive type double is used to calculate the time that elapses when wheels rotate by angle of one degree.
Methods
The class implements many methods that will make the rover move in directions such as backward, forward, turn etc. We will use some of these methods in the lab today to make the rover move in a certain way. The methods are described as we do the tasks.
Constructor
Constructors are used to create objects. The NxtRover class has two constructor. One constructor without input parameters and one with three input parameters. We will use latter when creating NxtRover objects. The three parameters are:
- wheelDiameter - diameter of the wheel
- driveLength - distance between two wheels (a.k.a drive length)
- turnRatio - ratio of sensor rotations to wheel rotations.
The three parameters are of primitive type double and help to determine the countPerDegree variable value. More of this in the next section. Also the constructor intializes the left wheel to port C and right wheel to port A of Lego NXT. The ports on the NXT are used to communicate between the NXT processor and indivdual motors on either side. It also initializes the speed of the rover to 50. (Speed can range from 0 to 100).
Task1 - Introduction
Basically, in this task we make the NXT Rover to move forward, and turn for an amount of time such that it moves in a particular shape. Let's run this program.
- Getting Ready:
- Make sure that NXT is turned on and the left side upper conner of screen shows the bluetooth sign followed by "<". If the two symbols do not appear it means that Bluetooth option on NXT is not turned on. Ask your TA for help in that case.
- Click on My Bluetooth places, locate the icon as displayed on the right
- Right click on the icon and then select "Connect" . The icon should say "Connected", indicating that the communciation link between NXT and computer are established
- Right click on the same icon again and click on properties. Note down COM Port number associated with your NXT and Computer. Eg. You find COM7
- Now edit (using Notepad or Wordpad) the third line in the file icommand.properties (in NXTRover folder) to indicate the correct COM Port number from the above step. E.g. nxtcomm=COM7.
- Save the file icommand.properties file. Also you do not have to change this file over the course of tutorial.
- Compile: Compile the project with the Task1.java file selected under NxtRover [Source Files].
- Run:
- Place the robot on the floor at this point.
- Click on the "Run" button in Dr Java. You should see the "<>" on the NXT screen indicating that programming is being downloaded on the NXT via the bluetooth.
- It might take sometime before the robot actually starts moving (so be patient!)
- Also, the interactions pane will show the follow status:
Looking for 'icommand.properties' in working dir: S:\Javaprojects\NXTRover
NXTCOMM = COM5
Stable Library
=========================================
Native lib Version = RXTX-2.1-7
Java lib Version = RXTX-2.1-7
- If there is a problem with the Bluetooth connection, the following error will be displayed in the interactions pane:
Looking for 'icommand.properties' in working dir: S:\Javaprojects\NXTRover
NXTCOMM = COM5
Stable Library
=========================================
Native lib Version = RXTX-2.1-7
Java lib Version = RXTX-2.1-7
Error while connecting NXTCommand() constructor
gnu.io.NoSuchPortException
at gnu.io.CommPortIdentifier.getPortIdentifier(CommPortIdentifier.java:218)
at icommand.nxtcomm.NXTComm.open(Unknown Source)
at icommand.nxtcomm.NXTCommand.<clinit>(Unknown Source)
.........
In such case, do the following:
- Reset Dr Java using"Reset" icon.
- Turn off and then turn on the NXT.
- Also make sure that Bluetooth link is still connected in My Bluetooth Places otherwise repeat step 1.
- Click on the "Run" icon to try to step 3 again
- Observe and note down the Rovers movement. What shape is the rover moving in?
- Lets try to understand the code in Task1.java
public class Task1 { public static void main(String args[]){ //Declare and create the NxtRover object NXTRover rover = new NXTRover(56.0, 12.7, 2.0); //Command it to move
myNxtRover.moveForward(1000);
myNxtRover.turn(500);
myNxtRover.moveForward(1000);
myNxtRover.turn(500);
myNxtRover.moveForward(1000);
myNxtRover.halt(); //Close the Bluetooth connection - do not change the line below NXTCommand.close() }
}
You probably already know that each file of Java code defines a "class," which is something that encapsulates data and methods to describe an object. Here, we just define a class called "Task1" and it's only going to have one method (and no data) called main and its sole purpose is to create NxtRover object called rover and make it move in certain direction. For now ignore the words "static", "void" or the "(String args[])" part, as none of that is important for this lab. In creating the rover object, we use the constructor with three input parameters or arguments. The first parameter is diameter of the wheel. The wheel diameter is approximately 5.6 cm. The drive length is approximately measured to be 5.2 inches or 13.2 cm. The turn ratio is set 2. These parameters are used to calculate the countPerDegree data field.countPerDegree = (Distance traveled/One Full Rotation) * turn ratioDifferent setups of the rover could have different wheel diameter and drivelength, but for our setup the only input parameter you might need to change is the turn ratio (Do not change the value until Task 3).
The rover object can be moved in certain direction by giving the object the following commands (these methods are described in NXTRover.java):moveForward(int n) : Move forward for n milliseconds. moveBackward(int n) : Move backward for n milliseconds. turn(int n) : Turn counterclockwise (clockwise if negative) for n milliseconds. halt() : Stop the motors and wait for them to stopLet's examine one of the methods in Task1.java. We say that rover.moveForward(1000) commands the rover object to move forward for count of 1000 milliseconds. In programming lingo, we say that the moveForward method of rover is "invoked" or "called", getting the number 1000 "passed to it". Here the value 1000 is known as input parameter or argument and is of primitive type int. When moveForward(1000) is finished, control returns to main, which then goes on to its next line of code, and so forth. This is known Sequential excution or control of commands.
Note: The declaration or statement "import icommand.nxtcomm.*;" makes it possible to use data and methods in implemented in other classes. For example: NXTCommand.close() is a method in class icommand.nxtcomm placed in the package icommand.jar.
Task 2 - Make the Rover move in a shape
Complete the program in Task2.java such that it commands the rover to move in a approximately a a square shape either clockwise or counter-clockwise. Use only the methods described in Task1 to move your rover. You might have to change the input paramter to turn method so that the rover appears to move at right angles. Also if you want to turn the rover in counter-clockwise motion then the input parameter you want to provide the turn method should be negative. Example:
rover.turn(-500);Follow steps 1 to 4 from Task 1, to compile and run Task2.java. Observe and note down how the left and right wheels are turning. Also notice how hard it is to get the robot to turn exactly 90 degrees!
Task 3 - Additional Methods
To simplify the turn in Task 2, we introduce to the following NxtRover methods which allow the programming to specify the amount the rover should turn in degrees:
turnLeft(d) : Turn left d degrees turnRight(d) : Turn right d degreesThe degrees ranges from 0 to 360. If you apply negative degrees values then, the rover will move in the other direction. For example: turnLeft(-180), will turn right by 180.
In this task your goal is to implement the Task2 but this time using turnLeft and turnRight methods to make the square movement. Write your program in Task3.java . The turnLeft and turnRight methods work by turning wheels for a fixed amount of time based on how many time it takes to turn a degree. Hence the calculation for the countPerDegree.
Also, since motors vary in speed, batteries vary in charge, and surfaces provide different amount of friction, we might do a little extra work. Only if you observe that turnLeft or turnRight methods are of approximately +/- 5 degrees off the target degrees then do either of the following:
- Change the third constructor parameter turn ratio. You can give values between range 1.9 to 2.4
OR
- Increase or decrease the speed of the rover to turn faster or slower. After the constructor declaration do the following:
NXTRover rover = new NXTRover(56.0, 12.7, 2.0); rover.changeRoverSpeed(value); //changes the speed of the rover and the value can be in range 0 - 100 //Rest of of the commands
Task 4 - Using Control Structure
In Task4.java make your robot go in a square pattern like in Task3 but by using only one forward method call and one turnLeft or turnRight method call.
Task 5 - Using Constants
In Task5.java, we still want to move the rover in a square but, we want to constants instead literal values for the distance parameters. Insert the following lines of code in the main method after the constructor declaration:
final int DIST_TO_TRAVEL = 1000; final int DEGREES_TO_TURN = 90;These two lines create two constant values that can be used over and over again without using the literal numbers again. Use them in your code like so:
rover.moveForward(DIST_TO_TRAVEL);
rover.turnLeft(DEGREES_TO_TURN);Re-implementing your code to incorporate constants into your code is done for at least two reasons:
- They allow the programmer to define appropriate names for values (DEGREES_TO_TRAVEL instead of 90)
- They allow the program to change a value once and have it reflected throughout the program by simply changing the constant declaration.
Note: The "final" keyword tells the compiler that the value associated with identifier will not change during the execution of the program, and anything that tries to change it will cause an error. Also the constant identifier is capitalized as convention to distinguish it from a variable.
Task 6 - Using Variables and Expressions
A variable is a unit of storage that can be used and manipulated by the program as it runs. To use variables they must first be declared and to do this in Java you use the code like the following:
int x = 1;In this example int is the type of variable being declared. The x in our example is an identifier, the name the programmer gives to that variable. The variable is declared and initialized to 1. A handy use of variables it to apply arithmetic operations to the variable such as +,-,*,/,%, etc. to modify it as the program runs. These can be used as follows:
x = x + 5;This expression takes the int variable x and adds 5 to it. A simpler way of writing this same expression is:
x += 5;
Now to the task. Complete program in Task5.java such that it causes the rover to create three squares that decrease in size by 1/3 each time and start from the same location. See image.
Task 7 - Using Random and Math Class
Now let's incorporate some more function methods and employ some of the builtin methods of the java.lang.Math and java.util.Random class .
In Task7.java make the rover move in a triangle shape as shown in the digram to the right. Let the rover go straight a random distance x (rather random time x - as we are approximately moving 1 step at 1 milliseand by using moveForward(int milliseconds) method). Then turn 90°, go half the distance it went out forward (distance y = x/2), and then turn back towards base and go the proper distance z back to the base.
Let x be value between 1000 and 4000. The Random Generator class has function called nextInt(int value) which will generate a number between 0 and value - 1. Example:
Random r = new Random(); int x = r.nextInt(1000);Also since Random class is not part of the Java Language Library, you need to have the stament "import the java.util.Random" before the Class Task7 declaration.
To calculate distance z, recollect Pythagorean Theorem, that will give us the hypotanuse of the triangle. You will also need to compute the return angle a, which is labeled a in the diagram to the right. In your Trigonometry or Precalulus class you no doubt studied the trigonometric functions such as sine, cosine, and tangent. One such function that comes in handy is arctangent (inverse of tangent), which can be used to compute the value of the angle a which is equal to the arctangent of x divided by y (x / y). Figure out the function in Math class that will perform this function.
Also the methods return angle value in radians. In order for this code to work easily with our turnLeft or turnRight methods, we would like this to be in degrees. Search through the math class description (API) to figure a method that can covert radians to degrees.
Lab Report for NXT Java Lab 1
Report Due (Printed/Hard copy): Friday 8/10/07 by 2pm
Your lab report must follow the Lab Report Guidelines in reportguidelines.doc for most part. Some extra guidelines for certain sections are as follows:Overall Report
- 5 pages maximum.
- 1.5 spacing, 12pt Times New Roman font for all of the written material except code. Your java code should be in courier new, 12pt font, and single spaced.
- Submit one lab report for every group of 2 students
Introduction
- In your own words describe the tutorial briefly.
- Talk about what key concepts it emphasized regarding Java programming language. (Do a little research about pros and cons of Java versus other programming languages.)
Procedure and Results
- Combine the Procedure and Results section in your report.
- For each task assigned in the tutorial explain the thought process in solving the problem.
- Write your solution you came up with i.e. lines of java code you wrote in order to accomplish tasks 2 to 7. Explain what the lines of code are exactly doing in java terminology.
- Did the results appear right away the first try? What did you do in order to accurately perform the tasks you were given.
Discussion & Conclusion
- Talk about your overall experience while performing the tutorial.
- What new technologies were you exposed to if any?
- How did programming NXT using Lego Language compare to using Java?
- Was the picture story in Lego language easier to perceive?