This week's goals are to teach you some of the odds and ends that you will need to know in order to use leJOS to program your robots. It will include a brief introduction to command line work in DOS, information on how to set up the RCX brick to accept leJOS code, and how to actually program and run leJOS based code.
During the "lecture" component for this lab I will demo the following at the appropriate time. They are given here just as a quick reference.
The best way to get a command prompt is by selecting "Start->Run" and typing "cmd"
Once you get a prompt, there are only a handful of commands you should need
What is leJOS and why use it?
leJOS (pronounced like you might say lay-host if you didn't pronounce the 't') is a Java based "firmware" for the LEGO Mindstorms. In fact, leJOS stands for LEGO Java Operating System. You write code in a language that is almost Java, compile this to leJOS byte code, install the byte code on your RCX brick, and let a leJOS interpreter on the brick (stored in RAM) interpret this code down to the standard RCX machine language (stored in ROM). This interpreter is relatively small (~17 KB) yet allows you to write some fairly powerful code.
leJOS is not without its problems. Some of these are trivial, and some are serious. Of minor impact is the fact that leJOS is NOT Java. That is, it does not support all of the Java APIs. For example, switch statements, Long Arithmetic, and Java.lang.class are not supported in any capacity. Having a larger impact is the fact there is no garbage collection. While this may not SEEM like a big deal, it will become one. That is tied into the largest problem - RAM limits on the RCX
Recall that last week I mentioned that the RCX brick has 32 KB of RAM. While this is accurate, it is misleading. First of all, even if you were running the basic LEGO RCX Firmware, you would not have access to all 32 KB. The routines stored in ROM require 4 KB of RAM to perform their operations. Thus, at best, you would have access to 28 KB. The current implementation of the leJOS interpreter has a 17 KB footprint. This means that you have, at best, 11 KB of memory to work with once you have installed leJOS. Most of the sources I read state that this is a lot closer to 9 KB. This is 9 KB to not only load and store your byte code, but also store all of your data used by the code. This is where garbage collection becomes a problem. Create an array of Doubles, and memory may disappear fast.
To enable your RCX for the execution of leJOS programs, you will have to install the leJOS operating system. leJOS will be loaded into volatile RAM. That means that it will stay there as long as there are charged batteries in the RCX. Anytime the RCX loses power, you will need to re-enable leJOS. Fortunately, this is easily done:
bin directory of your
leJOS installation firmdl.batIf the download doesn't work, make sure that
The tower should blink green, when you start firmdl.
The original LEGO® firmware isn't deleted from the RCX. Hence you may re-activate it by just removing the batteries for a few minutes and replacing it.
There's a simple "Hello World" style example program available in the examples\hworld section of the leJOS tree:
import josx.platform.rcx.*;
/**
* @author Ryan VanderBijl
*/
/* This class uses char[] to display text on the LCD.
* Strings aren't really supported by TinyVM. :-(
*
* This program, after d/ling, waits for you to press the RUN
* button, and then displays "hello", for a small delay, and then
* displays "world". (Then a small delay, and then it returns to
* the TinyVM OS).
*/
public class HelloWorld
{
public static void main (String[] aArg)
throws Exception
{
LCD.clear();
TextLCD.print ("hello");
Thread.sleep(2000);
TextLCD.print ("world");
Thread.sleep(2000);
}
}
To run this program, you will:
examples\hworld
directory of your leJOS installation
lejosc instead of javac:lejosc HelloWorld.java
NOTE: When you write your own Java code, you will probably be using jGrasp. That being the case, as you write and "test compile" your code you may absolutely use the javac command by using the compile button/comand within jGrasp. However, the .class files created from here will not be recognized by later steps in this process. Therefore, you must always recompile using lejosc.
lejoslejos -o HelloWorld.bin HelloWorld
leJOSrun:lejosrun HelloWorld.bin
If lejosc or lejos isn't found, make sure your
PATH variable is set accordingly.
If the leJOS classes aren't found, check your CLASSPATH variable.
The two steps of linking and downloading (steps 3 and 4) may be done in
one with
lejos HelloWorld
However, I suggest doing it in two steps. I have simply discovered that there are less errors, and if they do occur it is easier to tell where they are (not to mention it is faster to reload a working program if it is already saved as a binary file).
Remember when you first started learning Java? For many of you the first program you saw was some variant of the "Hello World" program used in part 1. However, after seeing that you still didn't have any idea how to program in Java. Well, you are probably in the same boat here. That is, you have now seen a leJOS program, but you still don't know how to program with leJOS. Fortunately, leJOS is written on top of the Java language, so getting up to speed in leJOS shouldn't take much if you already know Java. In this portion of the lab we will take a closer look another application using the leJOS API and discuss some of its fundamental concepts. In order to complete this part of the lab, it is recommended that you have the RoverBot from last week built. At the very least, you should have your RCX connected to a motor via a cable mounted on port A.
Consider the following leJOS application. (You may want to copy and paste this into an editor such as jGrasp or Edit so that you can actually compile and download this onto your RCX).
import josx.platform.rcx.*;
//////////////////////////////////////
/**
* Represents a simple sample application.
*
* @author The leJOS Tutorial
* @version 1.0
*/
public class SimpleSample {
////////////////////////////////////////////
// public methods
////////////////////////////////////////////
////////////////////////////////////////////
/**
* main method
* @throws InterruptedException
*/
public static void main(String[] args)
throws InterruptedException {
TextLCD.print("DRIVE");
Motor.A.forward();
Motor.C.forward();
// just run until RUN button is pressed again
Button.RUN.waitForPressAndRelease();
}
}
import josx.platform.rcx.*;
The basic package, which contains most of the essential leJOS classes, is
josx.platform.rcx. The name is somewhat due to historical reasons,
for Jose Solarzano was the inventor and first developer of leJOS.
For an overview of this package consult the
leJOS API.
public static void main(String[] args)
throws InterruptedException {
As with most Java applications, the entry point of a lejos program is the
main() method.
In our case, it throws an InterruptedException arising eventually
from the Button.RUN.waitForPressAndRelease() call below.
What will happen when such an exception occurs?
The RCX will stop the execution of the main() method and display
some (rather cryptic) error information on its LCD. You should not concern
yourself about the details of these exceptions at this time.
TextLCD.print("DRIVE");
You might have noticed that the graphical user interface of the RCX is rather
limited - in fact, there's only the little LCD in its middle for such a purpose.
Worse yet, it is limited to writing up to only five numbers or letters to the
LCD using the static methods of the TextLCD or the LCD
class.
Thus the abilities of a leJOS program for visual output are quite weak (compared
to Java applications running on a PC) - a fact that makes debugging in leJOS a
somewhat challenging task. However, it is worth pointing out that you can
get at least simple messages out to the user using only the RCX brick.
There ARE mechanisms, though, to display graphical information to the user: you might transfer information to the IR tower using the IR sensor in front of the RCX and display it on your PC's screen. However, this is a more advanced feature - see the specialized trail on communication contained in this tutorial.
You already might have noticed two things of importance here:
java.lang.String class in leJOS.
TextLCD. This is a major concept of
leJOS: The classes which are directly connected to the actual RCX hardware
parts - e.g. motors, sensors, buttons or the LCD - are designed to be static
ones. As a result you never will construct any of these but just use the
methods of the existing single instance.
// drive forward
Motor.A.forward();
This piece of code runs the motor connected to the RCX's port A in "forward" mode (the direction the motor actually spins depends on the orientation in which you mounted the connector).
Again note that you use a static instance of the Motor class - to
be more precise, a static member (named A) of this class, which
refers to "motor connected to port A". As you might have already guessed, the
two other motors are referred to as Motor.B and Motor.C,
respectively. If the motor in question is connected to some wheel assembly accurately, your
robot will now drive forward.
// just run until RUN button is pressed again
Button.RUN.waitForPressAndRelease();
So, what's the use of this? you might be tempted to ask at this
point of time, Isn't my robot running yet?.
The answer is: yes AND no.
Let's take a look at the program and assume the last statement would be missing:
Motor.forward() method
returns immediately, so the program moves to the next statement. main() comes to an end and returns
control to the operating system, which terminates program execution (for there
is no thread left to be executed). Button.RUN.waitForPressAndRelease()
statement is the motor running for a very short period of time (maybe not
noticeable at all, leaving behind a staggered user) and stopping right away.
Regarding this we have to assure that program execution doesn't stop or a
least at the point of time we choose it to.
As always, there are many ways to accomplish this task. One of the simplest
ones, though, is to force the program waiting for the user pressing and
releasing the RUN button which is easily got by
Button.RUN.waitForPressAndRelease().
Just as there were pre-defined motor constants, there are pre-defined sensors
In most cases, when you go to use a Sensor you must “set type and mode” in order to use a sensor.
Where
For example, if you want to use a boolean touch sensor you would initialize:
However, you may want to read up on the SensorConstants class/interface.
You might argue that the following is easier to read from a code point
of view:
Once you have done this, you can write things like:
All buttons may be re-programmed except the “on/off” button. They are either controlled by the Button class (the SimpleSample above) or use event driving programming and Listeners (remember those in CS II?)
public class MyButtonListener implements
ButtonListener {
public void buttonPressed(Button b) {
//do something?
}
public void buttonReleased(Button b) {
//do something?
}
}
//to use
Button.RUN.addButtonListener(myButtonListener);
We have demonstrated only a few of the classes available using the leJOS API. However, there are a whole wealth of classes that you may use during the course of this semester. You will most likely want to make sure that you bookmark and frequently refer to the official leJOS API. There is also a copy of this stored locally on each computer With this site alone, you should be able to complete any task asked of you this semester.
Prior to attempting the specifics of this assignment you should make sure that you have completed the sections on installing leJOS on your RCX, and learning about the body of a program using leJOS. Once you have done so, it is time to dive in head first and see if you can figure out how to perform a simple task with your RoverBot from last week.
Your task this week is to program your RoverBot from last week so that it moves about its environment performing obstacle avoidance maneuvers when necessary. You will likely find that the finished program is short and simple in hind sight, but given your current knowledge of leJOS, I anticipate this may be a reasonable enough challenge for this week.
Using HelloWorld.java and SimpleSample.java as references, write a simple "main" class called ObjectAvoider.java. Upon downloading the binary for this class onto your RCX and pressing the RUN button, the program should cause your RoverBot to proceed in a straight line until it interacts with an obstacle. How will you know that you have interacted with an obstacle? You were to build a double-bumper last week which uses two touch sensors. Check out the leJOS API to figure out how to either poll your touch sensors, or have them send an "interrupt" when pressed.
Once an obstacle is detected, your RoverBot should attempt an avoidance maneuver. The simplest maneuver, and the one I would like you to use, is to back up, rotate away from the object, and then proceed again.
Your robot should continue "roving" and avoiding until the program is "terminated" by a human user.
By the due date and time, submit the files:
ObjectAvoider.javavia the electronic submission system. You will also need to prepare your documentation packet following the homework collection policies.
Portions of this lab modified from an excellent tutorial
for leJOS by
Matthias Paul Scholz available at
http://lejos.sourceforge.net/tutorial/