LeJOS NXJ Tutorial

183
7/23/2019 LeJOS NXJ Tutorial http://slidepdf.com/reader/full/lejos-nxj-tutorial 1/183 Introduction What is leJOS NXJ leJOS NXJ is a Java programming environment for the LEGO MINDSTORMS NXT ®. It allows you to program LEGO ® robots in Java. It consists of:  Replacement firmware for the NXT that includes a Java Virtual Machine.  A library of Java classes (classes.jar) that implement the leJOS NXJ Application Programming Interface (API).  A linker for linking user Java classes with classes.jar to form a binary file that can be uploaded and run on the NXT.  PC tools for flashing the firmware, uploading programs, debugging, and many other functions.  A PC API for writing PC programs that communicate with leJOS NXJ  programs using Java streams over Bluetooth or USB, or using the LEGO Communications Protocol (LCP).  Many sample programs As leJOS is a firmware replacement, the new leJOS NXJ firmware must be flashed onto the NXT, and will replace the standard LEGO MINDSTORMS firmware. This wipes out any files currently held on the LEGO firmware. The LEGO firmware can be restored using the LEGO supplied software. leJOS is an open source project hosted in the sourceforge repository. It was originally created from the TinyVM project that implemented a Java VM for the LEGO Mindstorms RCX system. The RCX version of leJOS proved very popular with the LEGO Mindstorms Robotic Inventions Systems owners, and close to 200,000 downloads of all versions of leJOS have been done. The original author of TinyVM and the RCX version of leJOS was Jose Solorzano. The NXT has given the leJOS development team the opportunity to greatly expand the capability of leJOS. Advantages of leJOS NXJ There are many advantages of using leJOS NXJ rather than the NXT-G or other  programming environments for the NXT. These include:

Transcript of LeJOS NXJ Tutorial

Page 1: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 1/183

Introduction

What is leJOS NXJ

leJOS NXJ is a Java programming environment for the LEGO MINDSTORMS NXT

®. It allows you to program LEGO ® robots in Java.

It consists of:

  Replacement firmware for the NXT that includes a Java Virtual Machine.  A library of Java classes (classes.jar) that implement the leJOS NXJ

Application Programming Interface (API).  A linker for linking user Java classes with classes.jar to form a binary file that

can be uploaded and run on the NXT.  PC tools for flashing the firmware, uploading programs, debugging, and many

other functions.  A PC API for writing PC programs that communicate with leJOS NXJ

 programs using Java streams over Bluetooth or USB, or using the LEGOCommunications Protocol (LCP).

  Many sample programs

As leJOS is a firmware replacement, the new leJOS NXJ firmware must be flashedonto the NXT, and will replace the standard LEGO MINDSTORMS firmware. Thiswipes out any files currently held on the LEGO firmware. The LEGO firmware can berestored using the LEGO supplied software.

leJOS is an open source project hosted in the sourceforge repository. It was originallycreated from the TinyVM project that implemented a Java VM for the LEGOMindstorms RCX system. The RCX version of leJOS proved very popular with theLEGO Mindstorms Robotic Inventions Systems owners, and close to 200,000downloads of all versions of leJOS have been done. The original author of TinyVMand the RCX version of leJOS was Jose Solorzano.

The NXT has given the leJOS development team the opportunity to greatly expandthe capability of leJOS.

Advantages of leJOS NXJ

There are many advantages of using leJOS NXJ rather than the NXT-G or other programming environments for the NXT. These include:

Page 2: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 2/183

  It uses the industry-standard Java language.  It supports object-oriented programming.  It is an open source project with many contributors.  It allows you a choice of professional Integrated Development Environments

including Eclipse and Netbeans.  It has plugins for both Eclipse and Netbeans.  It has cross platform support –  Windows, Linux and Mac OS X.  It is much faster than NXT-G.  It has full support for Bluetooth, USB, I2C and RS485 protocols.  It provides highly accurate motor control.  It support the latest Java 1.6 language features.  It has advanced navigation support.  It supports localization including Monte Carlo Localization (MCL).  It supports other probabilistic robotics algorithms such as Kalman filters.  It provides Behavior classes that support the subsumption architecture for ease

of programming of complex robot behaviors.  It supports many third party sensors.  It supports remote logging to the PC over Bluetooth or USB, optionally by

redirecting System.out and System.err.  It supports remote monitoring and tracing of your leJOS NXJ program from the

PC.  It provides floating point Math, trigonometry and other Math functions.  It supports the JME LCD user Interface including many graphics functions.  It supports multithreading.

  It supports listeners and events.  It supports safe memory management with garbage collection.  It supports standard Java input/output streams over Bluetooth, USB and RS485.  It has a flash file system accessed by the standard java.io classes.  It supports data logging and remote capturing of the logs.  It has sound support including playing 8-bit WAV files.  It provides dozens of sample programs.  It supports remote execution of a large subset of the API from the PC.  The Web site has online forums to help solve any problems you might have, to

share projects ideas, and to communicate with the development team.  It has telerobotics support via standard TCP/IP sockets.  It supports NXT to NXT Bluetooth and RS485 communications.  It supports Bluetooth communication with other devices, such as GPS

receivers.  It has support for GPS devices including support for the

 javax.microedition.location API.

Page 3: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 3/183

  It supports Bluetooth keyboards that use the Bluetooth Serial Port Profile(SPP).

  It supports two-way communication with RCX via third party adapters such asthe Mindsensors NRLink.

  It supports servo motors and Power Function (PF) motors.  It provides compatibility with Lego Communications Protocol (LCP), so that

many tools that work with the standard LEGO firmware, also work with leJOS.  It has an easy to use menu system.  It is widely used by universities and other education establishments.  It has support for simple computer vision applications.

Getting Started

Operating Systems

leJOS NXJ is currently supported on three operating systems.

Please select which operating system you are using:

  Microsoft Windows   Linux   Mac OS X 

Getting Started on Microsoft Windows

This version of the tutorial is for the 0.9 release of leJOS NXJ.

Prerequisites

USB Driver

To run leJOS NXJ on Microsoft Windows you will need a suitable USB driver onyour PC. If you have installed the standard LEGO Mindstorms software, a suitabledriver will already be installed. If you do not wish to install the LEGO software onyour PC you can get a Fantom driver from The LEGO Mindstorms site. 

Page 4: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 4/183

Java Development Kit 

You will also need a Java Development Kit (JDK) on your PC. Note that a JavaRuntime Environment (JRE) is not sufficient as it does not allow you to compile Java

 programs. You can download the latest JDKfrom http://www.oracle.com/technetwork/java/index.html . Follow the instructions forinstalling it. leJOS NXJ has been tested with JDK versions 1.5 and 1.6, and will notwork with earlier versions. JDK 1.6 is recommended, and some PC sample programswill not work with JDK 1.5.

leJOS NXJ only works with 32-bit version of the JDK and JRE, so even if you have a64-bit system, you should select a 32-bit version of the JDK.

You will need to add the JDK bin directory to your system or user PATH, so that

commands such asjavac and java can be called from a command prompt. If you donot know how to do this, see the "Setting up environment variables" section below.

You should set the environment variable JAVA_HOME to the folder where youinstalled the JDK. If you have multiple JDKs on your PC, and do not want to changeJAVA_HOME, you can set LEJOS_NXT_JAVA_HOME instead.

Bluetooth Stack 

If you want to communicate with the NXT over Bluetooth, you will need a Bluetoothdongle or built-in support on your PC, and a Bluetooth software stack. leJOS NXJ has been tested with the Microsoft and Widcomm stacks, but should work with others.

You can use leJOS NXJ without Bluetooth.

Downloading the software

You can download the leJOS NXJ software from The leJOS NXJ download page. 

It is recommended that you use the Windows installer, but there is a ZIP file releasethat you can use if you prefer to do a manual installation.

Running the GUI installer

Page 5: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 5/183

Run leJOS_NXJ_0.9.0-Setup.exe and you will see the following screen:

Select "Yes" and you will see: 

 Note that Installjammer is the open source software we have used to produce the

installer. 

Click "Next and you will see:

Page 6: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 6/183

 

You can change the destination if you need to. Click on the "Browse" button tochange the destination. 

The JDK version that we have detected is displayed on this screen

Once you have selected the destination, click "Next" and you will see:

Page 7: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 7/183

 

Again you can change the destination for the leJOS projects. It defaults toleJOSNXJProjects in the users home directory. On Windows 7 or Vista this isC:\Users\user  and on XP it is C:\Documents and Settings\user . 

All the Java source in leJOS NXJ is issued as projects that can be opened in Eclipseand Netbeans.

Once you have selected the projects destination, the installation will start. If youalready have leJOS NXJ installed in the selected destination, you will see:

Page 8: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 8/183

 

Click next and the previous version will be uninstalled: 

Once you have confirmed that you want the old version uninstalled, you will see: 

Page 9: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 9/183

 

and then: 

Page 10: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 10/183

 

After any previous version has been uninstalled, the installation of the new versionstarts and you see: 

Page 11: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 11/183

 

Check that the destination directories are correct and click "Next". You will see: 

Page 12: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 12/183

 

When the software installation is complete, you see: 

Page 13: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 13/183

 

When you click "Finish" the GUI version of the NXJ firmware flash utility will startand allow you to update the firmware on one of more NXTs.  

You will see:

Page 14: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 14/183

 

Click "Start Program" and you will be asked: 

Page 15: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 15/183

 

Click OK and you will be asked: 

If you select "Yes" all current files on the NXT are erased. It is a good idea to selectthis as old .nxj files may not work with the new firmware.  

You will then see:

Make sure that your NXT is connected to the PC by the USB cable and witched on.Then press "OK" and you should see some progess messages, such as: 

Page 16: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 16/183

 

When your NXT has been updated, you will be asked: 

Page 17: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 17/183

 

If you have more NXTs to update, click "Yes". When you have finished click "No"and the flash utility will terminate and then the installer will terminate, and you aredone. 

Skip to the section below on testing your installation.

Manual installation

Skip this section and go to "Testing the Installation" if you are using the GUI installer.

Unzipping the release 

Unzip the release to a folder such as c:\lejosbeta9. The zip file includes a directorycalled lejos_nxj, so your NXJ_HOME folder will be c:\lejosbeta9\lejos_nxj.

Setting up environment variables 

You need to set:

Variable  Value  Example 

 NXJ_HOME

The folder you

installed leJOS NXJ

into

C:\lejosbeta9\lejos_nxj

JAVA_HOMEThe folder where

you installed theC:\Program Files\Java\jdk1.6.0_24

Page 18: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 18/183

JDK

PATH

Add the bin folders

for the JDK and

leJOS

C:\Program

Files\Java\jdk1.6.0_24\bin;C:\lejosbeta9\lejos_nxj\bin;

 Note that you can set LEJOS_NXT_JAVA_HOME instead, if you do not want tochange JAVA_HOME. The bin directory for the JDK may already be on your PATH.

You can set these environment variables by going to Control Panel > System >Advanced > Environment Variables and creating them or editing existing values. Youcan set them either as user or system variables depending on whether you want leJOS

 NXJ to be available to all users or just the current user.

Using a Command Window 

You will need to run command-line commands to test your installation and optionallyto flash the firmware. If you plan to use IDE such as Eclipse or Netbeans, once youhave installed your IDE, you should not need to use the command window any more.

You can start a command window on Windows XP by Start > Run and typing cmd.

On Vista or Windows 7, type "Command Prompt".

Type set to list environment variables and check they are all set up correctly.

Flashing the Firmware 

As leJOS NXJ is a firmware replacement, you will need to flash the firmware to your NXT. Note that this will overwrite any existing firmware. If you have the standardLEGO firmware or other third-party firmware on your NXT, existing files will be lost.

The 0.85 release increases the amount of flash memory used by the firmware and thestartup menu, so the first time you flash this version of the firmware, existing leJOS NXJ files will be deleted.

Make sure your NXT is attached to the PC by its USB cable, and switch it on by pressing the orange button.

Page 19: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 19/183

You can either use the command line nxjflash command or the nxjflashg GUI program.

Using the command line:

Type nxjflash to flash the leJOS NXJ firmware. If your NXT is in firmware updatemode, the firmware will be updated. You will see some messages on your commandwindow, and the NXT should show the leJOS splash screen and then the leJOS NXJmenu. If your NXT has a previous version of the leJOS or LEGO firmware on it, a listof the NXTs connected to the USB will be shown, and you will be asked to input thenumber in the list of the NXT you want updated - this will be 1 if a single NXT isconnected to your PC. If your NXT has other firmware on it, or if nxjflash fails, youmust put your NXT into firmware update mode. Press the reset button (at the back ofthe NXT , upper left corner) for more than 4 seconds. A straightened paper clip could be useful for this. Your NXT will audibly tick when it is firmware update mode. Then

try nxjflash again.

Using the GUI version:

The GUI version of nxjflash is NXJFlashG. You start it by running the filenxjflashg.bat from the leJOS NXJ bin folder. When the program window opens, clickon Start Program and follow the instructions. A more complete explanation is in thetutorial "PC GUI Tools".

Testing your Installation

You can check that you have successfully installed leJOS NXJ on your PC and your NXT by compiling and running your first program.

Compiling and running your first program 

Java programs need to be compiled to class files before they can be run. For leJOS

 NXJ, all the class files that are to be run on the NXT needed to be linked to produce a binary file (with the extension .nxj) and this must then be uploaded to the NXT.

To run a sample program, such as the View.java sample, follow these steps:

Start a command window, and change directory to the View sample folder:

cd leJOSNXJProjects\samples\View

Page 20: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 20/183

Compile the program with the nxjc command:

nxjc View.java

Then link, upload and run it with the nxj command:

nxj -r View

You should see the menu of the View sample on your NXT.

Getting Started on Linux

This version of the tutorial is for the 0.9 release of leJOS NXJ.

Prerequisites

Java Development Kit

You will also need a Java Development Kit (JDK) on your PC. Note that a JavaRuntime Environment (JRE) is not sufficient as it does not allow you to compile Java programs. You can download the latest JDKfrom http://www.oracle.com/technetwork/java/index.html . Follow the instructions for

installing it. leJOS NXJ works has been tested with JDK versions 1.5 and 1.6, but willnot work with earlier versions. JDK 1.6 is recommended as some PC samples do notwork with JDK 1.5. Note that leJOS has only been tested with the official OracleJDK. It is likely to work with the Open JDK, but not with gcj.

You will need to add the JDK bin directory to your system or user PATH, so thatcommands such asjavac and java can be called from a command prompt. If you donot know how to do this, seeSetting up environment variables  below.

You should set the environment variable JAVA_HOME to the folder where you

installed the JDK. If you have multiple JDKs installed and do not want to haveJAVA_HOME, you can set LEJOS_NXT_JAVA_HOME instead.

libusb 

In order to use a USB connection to your NXT brick on Linux, you will need libusbinstalled on your sysyem. leJOS requires the legacy 0.1.12 release. On most Linux

Page 21: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 21/183

distributions the 0.1.12 version of the libusb package will normally be installed, butthe libusb development package may not be.. You can get more informationfrom http://libusb.sourceforge.net 

Package Dependencies 

You will need to ensure that the packages that leJOS NXJ is dependent on are on yoursystem. To build the jlibnxt JNI library, which is used for USB access, you needthe Development files for libusb (libusb-devel). Note that leJOS NXJ uses libusb(legacy release 0.1.12), not libusb1.

 Accessing USB devices 

If you are running leJOS NXJ from a non-root user, you will need to ensure that youhave read and write access the NXT USB device in /dev/bus/usb. If you can identifythe device in /dev/bus/usb, you can do this by:

 sudo chmod a+w /dev/bus/usb/xxx/yyy 

However, the yyy number will count up each time the NXT is disconnected andreconnected.

A better solution is to use udev rules. How to do this may vary with different Linuxsystems.

To use udev rules, set up a file such as /etc/udev/rules.d/70-lego.rules and populate itwith the following lines:

# Lego NXT

BUS=="usb", SYSFS{idVendor}=="03eb", GROUP="lego", MODE="0660" 

BUS=="usb", SYSFS{idVendor}=="0694", GROUP="lego", MODE="0660" 

This relies on the username you are using being in the lego group. You can modify thefile to your requirements. The two vendors are LEGO and Atmel (for the samba driverused in firmware update mode). You may need to reload the rules or restart udev. Onsome Linux systems, the command to reload the rules is udevadm control --reload-

rules. 

Page 22: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 22/183

Bluetooth 

If you want to communicate with the NXT over Bluetooth, you will need a Linuxsupported Bluetooth dongle or built-in support on your PC. leJOS uses the Bluecove

libraries which are included in the distribution.

You can use leJOS NXJ without Bluetooth.

Downloading the software

You can download the leJOS NXJ software from The leJOS NXJ download page. 

On Linux, leJOS is distributed as a .tar.gz file.

Installing leJOS

Unpacking the release

Unpack the release into a directory of your choice, e.g. /opt/lejos/

Setting up environment variables 

You need to set:

Variable  Value  Example 

 NXJ_HOMEThe folder you installed leJOS

 NXJ into/opt/lejos_nxj

JAVA_HOMEThe folder where you installed

the JDK/usr/java/

PATH Add the bin folders for the JDK $PATH:$JAVA_HOME/bin:$NXJ_HOME/bin

Page 23: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 23/183

and leJOS

 Note that you can set LEJOS_NXT_JAVA_HOME if you prefer. The bin directoryfor the JDK may already be on your PATH.

With most Linux distributions, you can set these environment variables for the currentuser in .bash_profile or for all users in /etc/profile.

You should check that the contents of the $NXJ_HOME/bin directory to check that allthe files have execute permission, and set it if if it is not set.

Building the release 

To build the release, change directory to lejos_nxj/build and type ant. If you have thedependent packages installed the release should build without errors.

Flashing the Firmware 

As leJOS NXJ is a firmware replacement, you will need to flash the firmware to your NXT. Note that this will overwrite any existing firmware. If you have the standardLEGO firmware or other third-party firmware on your NXT, existing files will be lost.

 Note that the 0.9 release changes the amount of flash memory reserved for thefirmware and the startup menu, so when you first flash the 0.9 firmware any existingfiles will be lost

Make sure your NXT is attached to the PC by its USB cable, and switch it on by pressing the orange button.

You can either use the command line nxjflash command or the nxjflashg GUI program.

Using the command line:

Type nxjflash to flash the leJOS NXJ firmware. You will see some messages on yourcommand window. If your NXT has a previous version of the leJOS or LEGOfirmware on it, a list of the NXTs connected to the USB will be shown, and you will be asked to input the number in the list of the NXT you want updated - this will be 1 ifa single NXT is connected to your PC. If your NXT has other firmware on it, orif nxjflash fails, you must put your NXT into firmware update mode. Press the reset

Page 24: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 24/183

 button (at the back of the NXT , upper left corner) for more than 4 seconds. Astraightened paper clip could be useful for this. Your NXT will audibly tick when it isfirmware update mode. Then try nxjflashagain. When flashing is successful, your NXT will reboot with the 0.9 version of the menu.

Using the GUI version:

To run the GUI version type nxjflashg. When the program window opens, click onStart Program and follow the instructions. A more complete explanation is in the PCGUI Tools tutorial page.

Testing your Installation

You can check that you have successfully installed leJOS NXJ on your PC and your NXT by compiling and running your first program.

Compiling and running your first program 

Java programs need to be compiled to class files before they can be run. For leJOS NXJ, all the class files that are to be run on the NXT needed to be linked to produce a binary file (with the extension .nxj) and this must then be uploaded to the NXT.

To run a sample program, such as the View.java sample, follow these steps:

Start a shell session, and change directory to the lejos_nxj/projects/samples/View

folder: 

Compile the program with the nxjc command: 

nxjc View.java

Then link, upload and run it with the nxj command:

nxj -r View

You should see the menu of the View sample on your NXT.

Page 25: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 25/183

Getting Started on OSX

This version of the tutorial is for the 0.9 release of leJOS NXJ and is compatible withOSX10.4 or higher and both intel and ppc processors.

Prerequisites

Standard Lego Software

To run leJOS NXJ on OSX you will need the standard Lego software installed so thatyou can connect to your NXT using USB.

Intel macs require the 10.5 firmware (fix) update. This is true for OSX10.4 intel users

as well. We have had several users report that this works... (the 10.5 update installeractually checks if your OS is 10.3+). PPC users need the 1.02 driver.

Java Development Kit 

You will also need a Java Development Kit (JDK). Note that a Java RuntimeEnvironment (JRE) is not sufficient as it does not allow you to compile Java programs. You can download the latest JDK from http://java.sun.com/. Follow theinstructions for installing it. A 32 bit version of Java is required and for Leopard onlyJava 1.5 is 32 bit. Snow Leopard Java 1.6 is both 32 and 64 bit. LEJOS scripts suchas nxjbrowse now set the -d32 flag to specify 32 bit.

Downloading and Untarring LEJOS Software 

You can download the leJOS NXJ software from The leJOS NXJ download page. 

Un-tar the release (you do not need to run the build script)

Page 26: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 26/183

(Optional) Bluetooth Stack 

If you want to communicate with the NXT over Bluetooth, you will need a Bluetoothdongle or built-in support on your Mac, and a Bluetooth software stack. LEJOS is

distributed with a 3rd party stack that is configured by default -- bluecove.

Pairing the NXT with your Mac should be done by pair from the computer. Browsefor the device and enter a passcode of 1234 on the mac.

Setting up the Environment

Environmental Variables

LEJOS scripts such as nxjbrowse will set their own paths so that it isn't necessary toset up Environmental Variables in order to use them. Setting Permissions is stillrequired

The build files for the samples contained in /projects/samples do look for the NXJ_HOME.

For convenience and to use the samples' build files you need to set the following:

Variable  Value  Example 

 NXJ_HOME

The

folder

you

installed

leJOS

 NXJ

into

/Users/me/lejos_nxj

JAVA_HOME The /System/Library/Frameworks/JavaVM.framework/Versions/1.

Page 27: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 27/183

folder

where

you

installed

the JDK

5.0/Home

PATH

Add the

 bin

folders

for the

JDK

and

leJOS

$JAVA_HOME/bin:$NXJ_HOME/bin;

DYLD_LIBRARY_PA

TH

(Only

necessar 

y for

using

the

Eclipse

 plugin)

Add the

 bin

folders

$NXJ_HOME/bin;

Page 28: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 28/183

for

Fantom

driver

You can set these environment variables either as user or system variables dependingon whether you want leJOS NXJ to be available to just the current user or to all users.

Set Up for Current User  

Create or Edit ~/.profile and set your environment there.

If it does not exist, you can create it with TextEdit. If it exists, you can open it from acommand prompt:

$ open ~/.profile

Example:

export

JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/1.5.0/Homeexport NXJ_HOME=/Users/me/lejos_nxj

export DYLD_LIBRARY_PATH=$NXJ_HOME/bin

export PATH=$PATH:$JAVA_HOME/bin:$NXJ_HOME/bin

Set Up for All Users

Same as for Current User set up except use:

/etc/profile

Example:

# System-wide .profile for sh(1)

if [ -x /usr/libexec/path_helper ]; then

Page 29: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 29/183

Page 30: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 30/183

 

(Optional) Testing with nxjbrowse 

Test it by running nxjbrowse -u you should be able to see your NXT.

Flashing the Firmware

As leJOS NXJ is a firmware replacement, you will need to flash the firmware to your NXT. Note that this will overwrite any existing firmware. If you have a previousversion of leJOS NXJ on your PC your existing files will be preserved, but if youhave the standard LEGO firmware or other third-party firmware on your NXT,existing files will be lost.

Make sure your NXT is attached by its USB cable, and switch it on by pressing theorange button.

You can either use the command line nxjflash command or the nxjflashg GUI program.

Using the command line:

Type nxjflash to flash the leJOS NXJ firmware. If your NXT is in firmware update

mode, the firmware will be updated. You will see some messages on your commandwindow, and the NXT should show the leJOS splash screen and then the leJOS NXJmenu. If your NXT has a previous version of the leJOS or LEGO firmware on it, a listof the NXTs connected to the USB will be shown, and you will be asked to input thenumber in the list of the NXT you want updated - this will be 1 if a single NXT isconnected to your PC. If your NXT has other firmware on it, or if nxjflashfails, youmust put your NXT into firmware update mode. Press the reset button (at the back ofthe NXT , upper left corner) for more than 4 seconds. A straightened paper clip could be useful for this. Your NXT will audibly tick when it is firmware update mode. Thentry nxjflash again.

Using the GUI version:

The GUI version of nxjflash is NXJFlashG. You start it by running the file nxjflashgfrom the leJOS NXJ bin folder. When the program window opens, click on StartProgram and follow the instructions. A more complete explanation is in the Windowstutorial "PC GUI Tools" section.

Page 31: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 31/183

 

(Optional) Eclipse

Installation

When installing the plug-in from http://lejos.sourceforge.net/tools/eclipse/plugin/nxj/,adding the site alone doesn't work. You need to unselect the option, group bycategory. The software seems to not be categorized. Then you should see the option toinstall the plug-in.

USB Connections 

The eclipse plugin does not find the libjfantom.jnilib driver we use for USB

connections and USB connection will not work. In eclipse, go to the lejos panel in the preferences window and select the "use bluetooth" options as USB is not available.

Creating a New Project 

When creating a new project simply create a java project and create a class (it will bea .java file). Right-click on the project in the project explorer and select Lejos andConvert to Lejos project. This is only for projects that are intended to run on the NXT.This is not for projects that run on your Mac.

If conversion fails, go to the preferences for eclipse (not the project settings), be surethat the LEJOS_HOME text box is set to the top level lejos_nxj directory.

Make sure to omit the normal Mac OS X libraries from projects that will run on the NXT. Standard Java libraries can not run on the custom NXT JVM.

PC API 

For programs running on your Mac (PC API), you need to add the bluecove.jar file tothe classpath for the "Run configuration" for the project. To do that, go to ProjectProperties, then Run/Debug settings, then edit the Launch configuration you've beenusing. It will be in the "Launch Configurations" window. Then select "User Entries"and "Add external jars...". Add bluecove.jar from lejos_nxj/3rdparty/lib

Page 32: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 32/183

You also need to force the jvm to run in 32-bit mode. To do this, modify the project properties by adding the -d32argument to the "VM Arguments" section of the"Arguments" tab.

Standard Mac OS X Java libraries are used to compile PC API programs

 Additional information on using Eclipse 

Writing your first leJOS NXJ program

The HelloWorld program

Let us start with a simple “Hello World” program. We will create a HelloWorld class

in the default java package:

public class HelloWorld

{

}

leJOS requires the standard main method for the program entry point:

public class HelloWorld {

public static void main (String[] args) {

}

}

leJOS NXJ supports the standard java System.out.println method and scroll the outputon the NXT LCD screen.

public class HelloWorld {

public static void main (String[] args) {

System.out.println("Hello World");

}

}

Page 33: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 33/183

If you run this program as it is, it will display Hello World” and then immediately

return to the menu, so you will not be able to see what is displayed (unless you arevery quick).

We either need the program to sleep for a while to allow the text to be read, or to wait

for a button to be pressed. Let us wait for a button to be pressed. To do this we need toinclude the leJOS NXJ Button class in the program. Button is in the lejos.nxt package.We can either include lejos.nxt.Button or lejos.nxt.* to allow any of the standardlejos.nxt classes to be used in the program. The Button class has a methodwaitForPress() that waits for any button to be pressed. You can find out what methodsa class supports by looking at the API documentation. 

The API documentation is on the leJOS web site here and included in the leJOSdownload in the docs folder of the classes project.

The complete HelloWorld program is:

import lejos.nxt.*;

public class HelloWorld {

public static void main (String[] args) {

System.out.println("Hello World");

Button.waitForPress();

}

}

Read the next section to learn how to compile and run this program

Compiling and Running Programs

This section describes how to compile and run leJOS NXJ programs.

Most people will want to write Java programs that run on the NXT brick, but that isnot the only option. leJOS NXJ also supports programs that run on the PC and controla NXT robot remotely. Such PC programs can control a NXT robot running the leJOS NXJ menu. They can also remotely control a robot running the standard LEGOfirmware. An even more interesting option that leJOS NXJ supports is to write a

Page 34: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 34/183

 program that runs partly on the NXT and partly on a PC with the two partscommunicating with each other over Bluetooth or USB. The part of your program thatruns on the PC has more memory and processing power available to it and can domore complex processing. It can also display interesting user interfaces such as mapsof where your robot is exploring. The part of the program that runs on the NXT can

respond quickly to sensors and can accurately control motors. If you are interested inwriting PC programs see the PC API command line tools section below.

While we are on the subject, it is also worth mentioning that leJOS NXJ programs canalso run on mobile phones or other devices that support the Java MicroEditionEnvironment (JME). Such programs can communicate with the NXT over Bluetooth.We plan to add a section to the tutorial soon that will describe how to develop programs that use the leJOS NXJ JME API.

You can also communicate with leJOS NXJ programs from Android phones - see

the Android tutorial page.

Finally, leJOS NXJ programs can be distributed across multiple NXT bricks whichcan communicate with each other over Bluetooth or via RS485 communication using NXT cables linking port 4 of two or more NXT bricks. Oh, and NXT programs canalso communicate with external devices such as Bluetooth GPS Receivers. This is alldescribed in Communications tutorial page.

We shall start, however, with writing programs that run on the NXT brick. You caneither compile and run your programs using the leJOS NXJ command line tools or

you can use an Integrated Development Environment (IDE).

While command line tools are very useful, programming for leJOS NXJ is best doneusing an IDE. IDEs have syntax-directed editors that immediately show you anysyntax errors in your program, rather than waiting until you compile the program andthen showing a list of errors. This, together with color coding of the source, automaticformatting of the code, prompting for method names and signatures, expanding andcollapsing parts of your program, and many other editing features, makes creatingyour program a much faster and more enjoyable experience. But the advantages of theIDE do not end there: they also help you with creating and building projects,

debugging, generating documentation, and creating user interfaces. Java IDEs put allthe Sun Java tools and a variety of third-party tools at your fingertips. They makesupporting new tools simple, either by use of plug-ins or by integration of externaltools.

Page 35: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 35/183

IDEs are easy to set up and use and you should use them for all your leJOS programming –  even the simplest of projects. Any type of leJOS NXJ program can becreated using an IDE.

You can produce leJOS NXJ programs with any Java IDE. This tutorial currently has

sections on how to use two of the most popular Jave IDEs: Eclipse and Netbeans.leJOS NXJ supports plugins for these two IDEs which makes writing and testing your programs even simpler.

To learn how to create, compile and run your programs from an IntegratedDevelopment Environment, go to one of the following sections:

  Eclipse    Netbeans 

This section of the tutorial will teach you how to use the command line tools. If youdecide to use the command line tools you can write your program using the editor ofyour choice. Many programmer's editors will let you invoke the tools directly fromthe editor.

Another option you can use to compile and run your leJOS NXJ programs is touse ant  build scripts. ant build scripts are usually used from an IDE. Netbeans does allcompiling and building of programs using ant, and it is an option in Eclipse. However,you can also use ant from the command line. ant build scripts are provided for all theleJOS NXJ samples. To run ant build scripts you just change directory to the directory

containing the build.xml file and type ant .

The scripts described in the following sections are Windows .cmd or .bat files or Unixshell scripts, depending on which operating system you are using. They set up theclass path, library path and boot class path needed by leJOS NXJ and then call a Javaclass that does all the work. The exception to this is nxjc which just calls javac. Notethat ant build scripts use the same underlying Java classes, but do not use the scripts.

Using the leJOS NXJ command line tools

leJOS uses the standard Sun Java compiler for compiling programs. However, it needsto replace the standard Java library with leJOS's own version of this - classes.jar. Forthis reason we provide a command called nxjc that sets the boot class path toclasses.jar. Its parameter are the same as those as javac 

Page 36: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 36/183

leJOS NXJ programs are different from normal Java programs in that they do notsupport dynamic class loading. Instead all the classes used in the program arecollected together and packaged in a binary file with a .nxj extension. This process isreferred to as linking. The linked binary is then uploaded to the NXT.

The tools for compiling, linking and uploading leJOS NXJ programs are:

  nxjc  nxjlink  nxjupload  nxj

 Note that you normally only need to use the nxjc and nxj commands, as nxj does theequivalent of nxjlink followed by nxjupload.

You need to open a command window to run these commands.

nxjc  – compile a program 

Compiles one or more java files.

Usage: nxjc <java-files>

Example:

nxjc View.java 

nxjc calls javac with parameters: 

  -bootclasspath <path to classes.jar>  <java-files>

-bootclasspath is set because leJOS does not use the standard java.lang classes but hasits own versions in classes.jar.

nxjlink  – link a program 

Calls the leJOS NXJ linker.

Page 37: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 37/183

Usage: nxjlink [-v|--verbose] [-g|--debug] [-gr|--remotedebug] [-a|--all] [-dm|--disablememcompaction] [-ea|--enableassertions] [-ec|--enablechecks] [-od|--outputdebug <debug-file> ] -o <binary> main-class

Example:

nxjlink -v Tune -o Tune.nxj 

Links the specified main class with any classes that it references in the currentdirectory and with the standard leJOS classes from classes.jar to produce a binary NXJ program that can be uploaded and run. 

The -v or --verbose flag causes a list of class names and method signatures included inthe binary to be sent to the standard output. This output is extremely useful fordebugging.

The -g or --debug flag causes a debug monitor to be included with the program. Thisallows the program to be interrupted while is running (by pressing ENTER+ESCAPE)and gives stack dumps when untrapped exceptions occur.

The -gr or --remotedebug flag is used to switch on remote debugging, which workswith the nxjconsole or nxjconsoleviewer tools.

The -od or --outputdebug flag is used to specify an output debug file, which is used byremote debugging and by nxjdebugtool.

The -ec or --enablechecks flag is used to enable additional run time checks. Thesechecks are relatively expensive (and rarely generate errors) and so are off by default.Currently the only check that this setting enables is the testing forArraystoreExceptions.

The -ea or --enableassertions flag is used to enable the checking of assert statementswith the program.

The -dm or --disablememcompactions flag is used to disable memory compaction.

 Normally the leJOS garbage collector will attempt to move large objects in memory tomaximise the amount of contiguous free space, this option disables this feature.

The linker removes methods that are not used. Specify -a or --all to include allmethods whether they are used or not. This should never be necessary.

Use the -h or --help flag to print out the options.

Page 38: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 38/183

 

nxjupload  – upload a program 

Usage: nxjupload [-b|--bluetooth] [-u|--usb] [-d|--address address] [-n|--name name] [-r|--run] <binary>

Example:

nxjupload Tune.nxj

Uploads the binary (.nxj) file. By default USB is tried first and then Bluetooth. If the --bluetooth flag is specified, only Bluetooth is tried. If --usb is specified, only USB istried.

When Bluetooth is used, a search for Bluetooth devices is done, unless the -addressflag is set, when a device with the given address is connected to.

The --name parameter limits the search for a NXT with the given name. If this is notspecified, nxjupload tries to connect to each NXT that it finds and will upload to thefirst NXT that is successfully connects to.

If the --run parameter is specified, the program is run after it has been uploaded.

nxj  – link, upload and run a program 

Usage: nxj [options] main-class

Example:

nxj -r Tune 

The nxj command links and uploads a leJOS NXJ program. It is the equivalent ofnxjlink followed by nxjupload. 

Any of the options for nxjlink and nxjupload can be specified.

The default binary name is <main-class>.nxj, e.g. Tune.nxj.

Page 39: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 39/183

 

Using PC API command line tools

The tools for compiling and running leJOS PC API programs are:

  nxjpcc  nxjpc

Reminder: If you are compiling or running a PC API program without using thesetools, you needpccomm.jar and bluecove.jar (Linux users also need bluecove-gpl) inyour CLASSPATH and classes.jar must be removed. Also, the java library

path needs to be set.

nxjpcc  – compile a PC API program for your pc 

Compiles one or more PC API java files.

Usage: nxjpcc [javac-options] <java-files>

Example:

nxjpcc SensorTest.java 

nxjpc  – run a PC API program on your pc 

Usage: nxjpc [java-options] <main-class>

Calls java to run your PC API program.

Example:

nxjpc SensorTest 

The leJOS NXJ Menu System

Main menu

Page 40: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 40/183

When leJOS NXJ starts, it displays the leJOS NXJ logo for 3 seconds and thendisplays the main menu:

The top line shows the battery voltage icon,the name of the NXT, indicators for activeUSB and Bluetooth connections, and the Bluetooth power icon. In this example, the power is on, but USB and Bluetooth are not connected. 

It then shows a graphic menu of icons. The selected icon is raised in the center and itsname is displayed. You can use the keys to navigate the menu:

Key Name Use

.

Left,Right Move left or right

Enter Select the menu item

Escape Quit a submenu and return to higherlevel menu.If on a top level menu, shut down the NXT.

Pressing Enter when "Run Default" is displayed will run the default program if one isset. The default program can be set from the Files menu. Note that if you set the "AutoRun" option from the System menu, the default program will run automatically onstart up, instead of this menu.

Using Eclipse

Installing Eclipse

Page 41: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 41/183

You can download Eclipse from Eclipse downloads. If you are only going to useEclipse for leJOS NXJ programs, you will only need standard Java developmentcapabilities - you will not need a version that supports the Java Enterprise Edition orother languages such as C++ or Eclipse plugin development. A package such as"Eclipse IDE for Java Developers" is sufficient for leJOS NXJ. Make sure you

download a package for your operating system. Note, however that for Windows,even if you are on a 64-bit system, you need a 32-bit version of Eclipse, for leJOS NXJ. The examples in this section are for Microsoft Windows, but the installation process is similar for other operating systems. If you are using Linux, yourdistribution may have its own Eclipse package, which you may prefer to use.

Unzip the package you downloaded to a folder. If you extract all files to C:\ then yourEclipse folder will be C:\eclipse.

You can start Eclipse by running eclipse.exe from your Eclipse folder. You may want

to put a shortcut to eclipse.exe on your desktop.

When you first start Eclipse, you are asked to select a workspace:

You can leave this as the default, or you can work with multiple workspaces andcreate one just for your leJOS projects. 

When you click OK, the IDE will open and you will see a welcome screen. You canclose the Welcome window and start developing leJOS programs.

The tutorial takes you through running the samples and PC samples that come withleJOS and then looks at an example project that uses an ant build file. It then shows

Page 42: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 42/183

you how to create your own project that uses an ant build file. If you are not interestedin this and only want to use the Eclipse plugin, skip to Installing the Eclipse plugin. 

Importing the leJOS NXJ projects into Eclipse

You should first import the leJOS projects into your Eclipse workspace. The easiestway to do this is to select File > Import... and then choose General > Existing Projectsinto Workspace. Browse to the folder where you installed the leJOS projects (e.g.C:\Users\Me\leJOSNXJProjects or C:\Documents andSettings\Me\leJOSNXJSettings), and select them all to import.

 Note that if you import the leJOS NXJ projects this way, the source does not getmoved to the workspace, but stays in leJOSNXJProjects. You may prefer to copy your

 projects from leJOSNXJProjects into the Eclipse workspace and then import them byselecting the Eclipse workspace as the source folder. That way you have always got aclean copy of the leJOS NXJ projects and the Eclipse versions will not be uninstalledwhen you install a new version of leJOS.

Using the samples project

You should then see several projects in your Package Explorer window including

samples. Try exploring the samples project. You can open up folders by clicking onthe expand/collapse toggles next to the folder name, and you can open files by double-clicking on file names. Try expanding the "BlueStats" folder, and its "default package" folder and opening BlueStats.java. You should see:

Page 43: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 43/183

 

There is a source folder within the samples project for each sample. Each foldercontains a build.xml file which is a build file for the sample written using "ant". Ant isa build system specially designed for Java - it comes bundled with Eclipse. 

There are other ways of building, uploading and running leJOS NXJ programs, suchas using the leJOS Eclipse plugin, but the ant build files are easy to use, so we willstart with them.

Ant build files have different "targets". The default target for the sample build.xmlfiles is "uploadandrun". This means that if you run the build.xml file it will compilethe Java source, link it with the standard leJOS classes (classes.jar) to produce a binary file and then upload ad run the binary file.

Turn on your NXT, make sure it is connected by USB or can be connected to via

Bluetooth. Then right-click on the build.xml and select "Run As" and "Ant Build":

Page 44: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 44/183

 

You should see output like the following in the Console window: 

Buildfile: C:\Users\Lawrie\leJOSProjects\samples\BlueStats\build.xml

clean:

compile:

[javac] Compiling 1 source file toC:\Users\Lawrie\leJOSProjects\samples\BlueStats

link:

[java] Class 0: java.lang.Object

[java] Class 1: java.lang.Thread

[java] Class 2: java.lang.String

[java] Class 3: java.lang.Throwable

[java] Class 4: java.lang.Error

[java] Class 5: java.lang.OutOfMemoryError

[java] Class 6: java.lang.NoSuchMethodError

[java] Class 7: java.lang.StackOverflowError

[java] Class 8: java.lang.NullPointerException

[java] Class 9: java.lang.ClassCastException

...

[java] Class 38: lejos.nxt.Flash

[java] Method 0: Class: java.lang.Object Signature: <init>()V PC 3222Signature id 2

Page 45: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 45/183

  [java] Method 1: Class: java.lang.Object Signature: notifyAll()V Nativeid 5

[java] Method 2: Class: java.lang.Object Signature: wait()V Native id 6

[java] Method 3: Class: java.lang.Object Signature: wait(J)V Native id7

[java] Method 4: Class: java.lang.Object Signature:toString()Ljava/lang/String; PC 3223 Signature id 95

...

[java] Method 147: Class: lejos.nxt.Flash Signature: writePage([BI)VNative id 75

[java] Method 148: Class: lejos.nxt.Flash Signature: <clinit>()V PC9337 Signature id 3

[java] Master record : 16 bytes.

[java] Class records : 39 (390 bytes).

[java] Field records : 80 (80 bytes).

[java] Static fields : 53 (106 bytes).

[java] Static state : 53 (202 bytes).[java] Constant records : 26 (104 bytes).

[java] Constant values : 26 (252 bytes).

[java] Method records : 149 (1788 bytes).

[java] Exception records: 67 (536 bytes).

[java] Code : 117 (6122 bytes).

[java] Total : 9597 bytes.

uploadandrun:

[java] Found nxt name NOISY address 001653007848

[java] leJOS NXJ> Upload successful in 1974 milliseconds

BUILD SUCCESSFUL

Total time: 4 seconds

This verbose output from the leJOS linker tells you all the classes and methods thathave been included in your program. It is very useful for debugging your programs.

You should see the Bluetooth statistics on your NXT LCD screen. You can stop theBlueStats program by pressing the ESCAPE button on the NXT.

You can browse through the samples and try them out. Some of the samples need tocommunicate with a program on the PC - see Using the PC samples project  below.

Other samples need specific sensors attached to the NXT or a robot with specificcharacteristics - such as a steerable wheeled vehicle. See the comments at the start ofeach of the Java files to understand the requirements of the sample.

 Note that the samples project uses default package names for simplicity. This is notgood practice for Java programming so when we create our own project, we will use a proper package name.

Page 46: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 46/183

 Note also that the samples project contains multiple programs each with a mainmethod. This is convenient for showing lots of examples of leJOS NXJ programmingin one project, but is not best practice. When we create our own projects, we will havea separate Eclipse project for each leJOS NXJ program

Using the PC samples project

If you imported all the leJOS NXJ projects into your workspace, you should have a pcsamples project. Open it up and look at one of the samples such as BTSend.

BTSend works with the BTReceive or NXTReceive samples. BTSend.java runs onthe PC and BTReceive.java (or NXTReceive.java) runs on the NXT.

There are no build files for the PC samples as they are not necessary. You can runBTSend.java by right-clicking on it and selecting, "Run as Java application", but firstwe need BTReceive running on the NXT.

Go to the samples application, select the build.xml file for BTReceive, and run it (Runas Ant Build) to upload BTReceive to the NXT.

 Now go back to the pcsamples project and run BTSend.java. BTSend should now runand connect to BTReceive, send it 100 integers and display the values it gets back.BTReceive will then wait for another connection.

You can use BTSend with the NXTReceive sample instead. NXTReceive is similar toBTReceive but it lets you choose which protocol and which mode you want to use tosend data.

You can look through the other PC samples and try them out in a similar way. Someof them are paired with NXT samples. Look at the comment at the start of the Javafiles. Some of them run a subset of the leJOS NXJ API on the PC using remoteexecution. AccelDemo, SensorTest and TachoCount are examples of this.TachoCount shows you how to control which NXT brick you connect to if you have

multiple NXT bricks available.

Using the org.lejos.example project

The org.lejos.example is a good example of how to create an Eclipse project for leJOSthat uses an ant build file.

Page 47: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 47/183

 

It is good practice to include the name of your organization in the project name toavoid name clashes with other projects in the work space. However if you are the onlyuser of a project, this is not necessary. 

The project has a src directory that holds all the source packages. The example projecthas a single package: org.lejos.example. Again it is a good idea to follow the standardJava conventions for package names, but if you are not sharing the project withanyone, it is not necessary.

The org.lejos.example has a single class file: HelloWorld.

The project is built by the ant build file: build.xml. build.xml uses a properties file build.properties which has properties that define which version of leJOS you are using(nxj.home) and the name and package of your masin class.

The build.xml has ant targets for linking and uploading the leJOS binary. The defaulttarget is uploadandrun, which compiles the source, links the binary, uploads the binary and runs it

Try right-clicking on build.xml and selecting "Ant Build". You should see the verboseoutput from the linker in the Eclipse console windows and the binary will be uploadedto the NXT and run.

Page 48: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 48/183

If you want to run a different ant target, right-click on build.xml and select "Ant Build...".

Creating your own project

This section describes how to create a project that uses an ant build file. If you preferto use the Eclipse plugin, skip to Installing the Eclipse plugin below.

To create a project, select File > New > Java Project. Give the project a name, e.g."org.me.myproject" and press Finish to accept all the defaults.

You should now see "org.me.myproject" in the Package Explorer.

You will need to add classes.jar to your project. To do this right-click on"org.me.myproject", select "Properties" and then "Java Build Path". Then selectLibraries and then "Add external Jar". Browse for classes.jar in your NXJ installationand select it. As classes.jar replaces the standard Java run time library, you shouldremove it by selecting "JRE System Library" and clicking "Remove". You will nowsee classes.jar (and not JRE System Library) under "Referenced Libraries" inorg.me.myproject.

You should use a package name for your project. We will also call our package"org.me.mypackage".

Select the "src" folder in org.me.myproject, right-click on it and select New > Packageand type your package name.

We now want to create main class.To do this, select the package you have justcreated, right-click on it and select New > Class. Type in the class name - we will use"HelloWorld". Select the "public static void main(String[] args)" option. You shouldnow have a HelloWorld.java program containing:

package org.me.mypackage;

public class HelloWorld {

/**

* @param args

*/

public static void main(String[] args) {

Page 49: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 49/183

  // TODO Auto-generated method stub

}

}

Edit the source so it reads:

package org.me.mypackage;

import lejos.nxt.*;

public class HelloWorld {

public static void main(String[] args) {

System.out.println("Hello World");

Button.waitForPress();

}

}

You will now need to build your project. One way to do this is to use an ant build filein the same way that the org.lejos.example project does. To do this, select a build.xmlfile from org.lejos.example, right-click on it and select "Copy". Then go to the srcdirectory, right-click on it and select "Paste". Do the same for build.properties

Double-click on build.xml to edit it and change the name and description attributes.Then change the main.class property to the name of your class, e.g. "HelloWorld" andthe "package" property to ""org.me.mypackage".

You are now ready to upload and run your first leJOS NXJ project. This is done in thesame way as for the samples: and org.lejos.example: by right-clicking on the build.xml file and selecting "Ant Build".

Make sure your NXT is switched on.

You should the verbose linker output in the Console window, and your programshould be uploaded to the NXT and run. You should see "Hello World" on the NXTLCD screen. Press any key on the NXT to stop the program.

Installing the Eclipse plugin

Page 50: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 50/183

An easier way to set up a project for leJOS is to use the Eclipse plugin.

The plugin will automatically convert your projects to leJOS NXJ projects.

To install the leJOS, click on the Help menu and select "Software Updates...". You

should see the following screen:

Select "Add Site..." and you will be prompted for the site name. Type"http://lejos.sourceforge.net/tools/eclipse/plugin/nxj/". 

Click on OK and the site is added. Select the newly added site: 

Page 51: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 51/183

 

Click on install and Eclipse will check for dependencies and then prompt you toinstall the plugin: 

Click on "Finish" and the plugin will be installed. When it is finished, you will be

 prompted to restart Eclipse: 

Click on "Yes" and Eclipse will restart. 

Page 52: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 52/183

When Eclipse has restarted, you can read the plugin help by select clicking on theHelp menu and selecting "Help Contents and then "leJOS NXJ".

It is a good idea to read the help page to familiarize yourself with the plugin. 

To Configure the plugin for your system and preferences, click on the "Window"menu and select Preferences and then "leJOS NXJ".

Page 53: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 53/183

Browse to where you installed leJOS NXJ and select it as NXJ_HOME. Select anyother options you require. It is a good idea to check the "Verbose" option. 

When you have set your preferences, click on "Apply" and then "OK".

The plugin is now set up and ready to use.

Using the Eclipse plugin

You can upload the leJOS NXJ firmware to your NXT from the plugin, by clicking onthe "leJOS NXJ" menu item and selecting "Upload Firmware" or by clicking on the button on the toolbar.

To create a new leJOS NXJ project using the plugin, create a Java project, by (forexample) clicking on File and selecting "New" and then "Java Project". Give your project a name and accept the defaults for project creation. 

When your project has been created, right-click on it, and select "leJOS NXJ" and"Convert to leJOS NXJ Project".

Page 54: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 54/183

 

This will mark your project as a leJOS NXJ project and replace the JRE SystemLibrary with classes.jar from your NXJ_HOME installation. 

You can now add packages and classes to your project and build it in the normal way

for Java projects (e.g. by setting the Build Automatically flag).

When you are ready to upload your program to the brick, right-click on your main program and select "Upload Program to the NXT Brick".

Page 55: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 55/183

 

You will see output on a leJOS NXJ Console and a progress screen: 

The upload will use USB or Bluetooth depending on which option you set on theleJOS NXJ Preferences page. You can change this and other preferences wheneveryou want. If you selected the "Run program after upload" option, the program willstart running on your NXT when it has finished uploaing. 

Setting up the leJOS GUI Tools

leJOS NXJ comes with a set of GUI tools that can be using for flashing the firmware,exploring files on the NXT, monitoring and debugging programs on the NXT,downloading data logs, etc. It is useful to be able to run these tools within Eclipse, andto do this you need to set them up as external tools.

To create external tools click on the down array next to the Run External Tools Iconon the toolbar and select "External Tools Configuration":

Page 56: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 56/183

 

Then select Program and click on the New Launch Configuration button and youshould see: 

Page 57: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 57/183

 

Type the name of your configuration, such as NXJ Flash and click on Browse FileSystem and find the bin directory of where you installed leJOS NXJ and selectnxjflashg.bat. 

If you have multiple installations of leJOS you can go to the Environment tab and set NXJ_HOME to the one you wish to use.

Other GUI tools you should set up include:

  nxjbrowse - an Explorer for NXJ files  nxjconsoleviewer - GUI viewer for RConsole debug output  nxjmonitor - Remote monitoring of programs running on the NXT  nxjdataviewer - GUI tool to download data logs from NXT  nxjcontrol - a GUI tool that combines the function of all of the above tool, and

adds a few more functions.

You may also want to set up command line tools such as:

  nxjflash - command line firmware flash tool  nxjconsole - command line viewer for RConsole debugging output  nxjsocketproxy - proxy for communicating with PC and Internet program using

sockets

Page 58: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 58/183

 

Files menu

Pressing the right button will display the Files icon:

Selecting "Files" will show a list of files using the TextMenu class.

You can move through the menu using the left and right buttons. It will scroll up anddown if there are more files than will fit on the screen and it will wrap round when

you reach the top or bottom of the list. 

When you select a particular file with the Enter button, the file submenu is displayed:

For any file a "Delete File" option is available. For program files (.nxj), you canexecute the program or set it as the default program. For sound files, you can play thesound sample. 

Page 59: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 59/183

Bluetooth menu

Pressing the right arrow from the Files menu icon, displays the Bluetooth menu icon:

Power On/Off  

Pressing ENTER shows the Power On/Power Off Bluetooth submenu. This is the

version when the power is on:

The status lines at the top show if power is on or off to the Bluetooth chip, and

whether the device is visible to Bluetooth searches. 

Switching the power off to the Bluetooth chip, increases battery life, but no Bluetoothcapability is available until the power is switched back on.

Press ENTER to switch the power off or back on.

Search/Pair  

Pressing the right Button from the Power On/Off submenu, shows the Search/Pairsubmenu.

Page 60: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 60/183

 

Pressing Enter starts a Bluetooth inquiry. The display is cleared and the first linedisplays “Searching…”. This takes about 10 seconds. 

When the search is finished a menu of all the Bluetooth devices found, is displayed:

All discoverable devices that support an SPP profile are displayed. This includes other NXT, GPS devices, mobile phones etc. 

Selecting one of the devices gives the following display:

Pressing Enter lets you pair the selected device with your NXT and adds it to the listof known devices. This makes connecting to the device from leJOS programs much

easier. 

When you press Enter to pair the device, a submenu is displayed for you to enter the pin for the selected device. You may need to go to the selected device and Enter the pin on that device as well.

Page 61: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 61/183

 

To enter the 4 digit pin on the NXT, press the left and right buttons to increment ordecrement the current digit, and Press Enter to go on to the next one. When you pressEnter on the last digit, the pairing will take place. The current digit has is displayed ina box to highlight it. 

Devices 

Pressing the right button from the Search/Pair submenu icon, takes you to the Devicessubmenu icon:

Pressing enter shows the devices currently in the Known Devices list for your NXT: 

Selecting a specific device will show details of it: 

Page 62: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 62/183

 

The first line gives the name and the second the address. 

Press Enter to remove the device from the Known devices list.

Visibility 

Pressing the right button from the Devices submenu, shows the Visibility submenu:

Pressing Enter on the Visibility submenu switches visibility of the NXT device to

Bluetooth inquiries on and off. The status is shown on the Visibility line at the top ofthe screen. 

Change Pin 

Pressing ENTER from the Visibility submenu, displays the Change Pin submenu:

Press Enter to get the Enter NXT Pin submenu: 

Page 63: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 63/183

 

This lets you change the pin for your NXT. The pin is required when you pair your NXT from another device. It is preset to 1234. 

To enter the 4 digit pin, press the left and right buttons to increment or decrement thecurrent digit, and Press Enter to go on to the next one. When you press Enter on thelast digit, the pairing will take place. The current digit has is displayed in a box tohighlight it.

Sound

Press the right button from the Bluetooth menu item, displays the Sound menu icon:

Press Enter and the Volume submenu is displayed. Click the Enter key to increase themain volume. After 10 it wraps round to mute (sound off). Presing it again increasesthe sound from level 1 upwards.

Press the right button from the Volume submenu and the Key Click submenu isdisplayed. 

Page 64: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 64/183

 

This sets the volume of the sound when a key is clicked. It works the same as theVolume submenu. 

System menu

Pressing the right button from the Sound menu icon, displays the System menu icon:

Selecting this shows information about the current state of the NXT brick, and allowsyou to format (wipe clean) the file system. 

This submenu shows some information about the status of the NXT, and allows you tochange some of these variables. 

The free flash memory and free RAM are displayed in bytes. An "R" after the batteryvoltage indicates that a rechargable battery pack is in use.

Press Enter to format the file system and wipe out all files. A submenu of Yes and Nois diaplayed, defaulted to No, to confirm the operation. Press the left or right arrows toselect Yes, and then press Enter to format the filesystem.

Page 65: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 65/183

Pressing right arrow when the Format submenu is diaplayed, shows the sleep timesubmenu:

Press Enter to increment the sleep time. It is in minutes. The maxiumum value is 10minutes. Pressing Enter when 10 is displayed, sets the sleep timer off. Pressing Enteragain starts incrementing it starting at 1. 

Pressing the right button when the Sleep time submenu is displayed, takes you to theAuto Run submenu:

Auto run defaults to off. It can only be switched on if a default program has beendefined. When it is on the default program will be run automatically on start up,instead of this menu. You can disable this and cause the menu to be displayed by pressing the left button during start up. 

Version

Pressing the right button from the System menu icon, displays the Version menu icon:

Page 66: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 66/183

Selecting this item, displays the version of the firmware and the menu. 

This menu is for information only. 

Controlling the Motors

Introduction to the Motor class.

This Motor class provides access to the NXT motors. To be useful, a motor must beconnected to one of the three NXT motor ports. This class provides an instance foreach port. They are: Motor.A, Motor.B and Motor.C.

Each of these three objects is an instance of the class NXTRegulatedMotor. This class provides methods for controlling the motor, and for finding out what the motor is

doing.

This tutorial contains a set of five programs for you to write. With them, you can perform experiments to understand how the NXT motor performs. They are simpleenough so you don’t need much Java experience to write them. Finally, there is a

discussion of  other motor methods , not used in the programs, that you might finduseful.

Program 1 - Basic movement controls.

This program uses the basic motor methods that control movement.

Methods used in this program 

Class Method name Notes

NXTRegulatedMotor,e.g. Motor.A 

forward()  Start the motorrotating forward

Page 67: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 67/183

  backward()  Start rotating backward

changeDirection()  Reverse thedirection of

rotationstop()  Stop quickly

Button  waitForPress()  Wait till any button is pressed

LCD  drawString(Stringstr, int x, inty) 

Draw a string.

What the program should do: 

1.  Run motor A in the forward direction.2.  Display FORWARD in the top line.3.  Wait until a button is pressed.4.  Run the motor backward.5.  Display BACKWARD in next line.6.  Wait until a button is pressed.7.  Run motor A in the forward direction.8.  Display FORWARD in the next line.9.  Wait until a button is pressed.10. Stop the motor.

It is possible to write this program using each Motor method only once.

Solution 

1

2 import lejos.nxt.*; // this is required for all programs that run on the NXT 345 /** 

6 *Motor runs forward then backward as button is pressed. 7 * @author Roger 8 */ 

9 public class BasicMotorTest10 {11

12 public static void main(String[] args)13 {14

Page 68: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 68/183

15 Motor.A.forward();16 LCD.drawString("FORWARD", 0, 0);17 Button.waitForPress();18 Motor.A.backward(); // you could use Motor.A.reverseDirectioninstead 19 LCD.drawString("BACKWARD", 0, 1);20 Button.waitForPress();21 Motor.A.reverseDirection();22 LCD.drawString("FORWARD", 0, 2);23 Button.waitForPress();24 Motor.A.stop();25 }26 }2728

Program 2 - Using the Tachometer.

The NXT motor has a built in tachometer that keeps track of the current angle (indegrees) of the motor axle. The purpose of this program is to use the tachometer tofind out how quickly the motor stops.

New methods used in this program 

Class Method name Notes

NXTRegulatedMotor,e.g. Motor.A 

flt()  Abbreviation for float. Turns

off the power, but does notapply the brake

getTachoCount()  Return s the motor angle indegrees

resetTachocount()  Sets the counter to zero

setSpeed(intspeed) 

speed –  degrees per second..The maximum speed that can be accurately maintained isabout 110 times the battery

voltage.intgetActualSpeed() 

Returns the actual motorspeed (deg/sec)

LCD  drawInt() 

Page 69: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 69/183

What the program should do 

1.  Run Motor.A forward.2.  Wait till the tacho count reaches 360.

3.  Stop the motor.4.  Wait until the motor has stopped.5.  Display the tachometer reading on the on the LCD.6.  Wait for a button press to give you time to read the screen display.7.  Set the motor speed to 720 (the default is 360).8.  Reset the tachometer count to zero.9.  Repeat steps 1 through 6. Note: you can avoid duplicated code by writing a

method that executes these steps.

Repeat the entire experiment by modifying your code to use flt() instead of stop(); ( flt

is the abbreviation for float, a Java reserved word). This method sets the motor powerto zero, but does not apply the brake.

Observe that, even using the brake, the motor does not stop immediately, becausemotor has inertia.

Solution 

import lejos.nxt.*;

/** * Test the overshoot after stop() at different speeds; 

* @author Roger */ 

public class InertiaTest{

public static void main(String[] args){

LCD.drawString("Inertia Test", 0, 0); // just so the program willnot start immeditely 

Button.waitForPress();rotate720();

Motor.A.resetTachoCount();Motor.A.setSpeed(800);rotate720();

}/** * helper method - rotates to 720, stops, display tacho count, wait; */ 

public static void rotate720(){

Motor.A.forward();

Page 70: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 70/183

  int count = 0;

while( count < 720 )count = Motor.A.getTachoCount();Motor.A.stop();

// Motor.A.flt(); LCD.drawInt(count , 0, 1);

while(Motor.A.getActualSpeed()>0);

LCD.drawInt(Motor.A.getTachoCount(), 7,1 );Button.waitForPress();LCD.clear();

}}

Program 3 - Accurate rotation control.

The Motor class has a regulator thread that runs all the time. It has two principle jobs,one of which is to stop the motor at a specified angle. This program will test the

accuracy of the rotate() method.

New methods used in this program 

Class Method name Notes

NXTRegulatedMotor,e.g. Motor.A 

rotate(angle)  Rotatesthrough angle degrees

rotateTo(angle)  Rotates to angle 

rotateTo(angle,true)  Sets the counter to zero

What the program should do 

1.  Rotate the motor one complete revolution.2.  Display the tachometer reading on the on the LCD, row 0.3.  Rotate the motor to angle 0.

4.  Display the tachometer reading on the on the LCD, row 1.5.  Wait for a button press to give you time to read the LCD.6.  Clear the LCD.7.  Set the speed to 720.8.  Repeat steps 1 through 6.

 Note: you can avoid duplicated code by writing a method that executes these steps.

Page 71: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 71/183

Observe the motor usually stops within 1 degree of the specified angle if the motorregulator is doing its job. It works by calculating how far the motor will continue toturn after the brake has been applied. It applies the brake before reaching the specifiedangle. It then makes minor adjustments to the motor position till it is close enough.

Observe: Once the motor has stopped if you try to turn it by hand it will resist you andwill even return nack to the stopped position. This is because when you use the stopmethod the regulator will continue to control the position of the motor. If you don'twant this to happen you can call the flt() method. This will release the motor fromregulation and you will be able to turn it easily by hand. If you call one of the rotatemethods and allow them to complete, then the default state at the end of the rotationwill be as if you had called stop, so the motor position will be maintained.

Solution 

import lejos.nxt.*;

/** * A more object - oriented code.  the main method just starts the program 

* @author Roger */ 

public class RotationTest{

public static void main(String args[]){

LCD.drawString("Rotation", 0, 0);//display program name beforerunning 

Button.waitForPress();LCD.clear();

RotationTest robot = new RotationTest();robot.go();// create an instance of the class and calls go 

}

/** * this method does the actual work */ 

public void go(){

rotate720();

Motor.A.setSpeed(800);rotate720();}

/** * helper method for go(); stops motor when button ia pressed */ 

public void rotate720(){

Motor.A.rotate(720);

Page 72: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 72/183

  LCD.drawInt(Motor.A.getTachoCount(), 4, 0, 1);Motor.A.rotateTo(0);LCD.drawInt(Motor.A.getTachoCount(), 4, 0, 2);Button.waitForPress();

}}

Program 4.Interrupting rotation

Sometimes you will want the motor stop (or do something else) before it reaches thespecified angle. This program will detect a button press to interrupt the rotation task ifyou press a button soon enough. The rotate() methods will not return until the motorhas stopped at the target angle. But the new methods in this program can returnimmediately. The motor will still stop at the specified angle unless a new motor

method is called in the meantime.

New methods used in this program 

Class Method name Notes

NXTRegulatedMotor,e.g. Motor.A 

rotate(angle,immediateReturn)  The method returns immediatelyif the boolean parameter immediateReturn is true rotateTo(angle,immediateReturn)  

(boolean)isRotating()  Returns false when the motor hasstopped at the specified angle

Button  int readButtons()  Returns the ID of the button pressed.

What the program should do 

1.  Start a rotation of 720 degrees.2.  While the motor is rotating, display the tacho count at the position of row 1.

3.  When a button is pressed, stop the motor.4.  After the motor has stopped, display the tacho count in the center of the row.5.  Wait for a button press.6.  Start a rotation to 0.7.  Repeat steps 2,3,5.

Page 73: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 73/183

Observe: if you press the button before the rotation is complete, the motor will stopwithout completing its rotation. Otherwise, the stop() method has no effect.

Solution 

import lejos.nxt.*;/** * allows interruption of a rotation task 

* @author Roger */ 

public class RotInterrupt{

/** * This method has the logic - rotate 720, return, wait for button * then rotate to 0 - wait for button * Another way to get results to the lcd */ 

public void go()

{System.out.println("Interrupt \n rotation");Sound.twoBeeps();Button.waitForPress();

Motor.A.rotate(720,true);showRotation(1);

Motor.A.rotateTo(0,true);showRotation(1);

}/** * helper method - saves repeated code */ 

public void showRotation(int row )

{while(Motor.A.isRotating()){

LCD.drawInt(Motor.A.getTachoCount(),4, 0, row);

if (Button.readButtons()>0) Motor.A.stop();}

while(Motor.A.getActualSpeed()>0);LCD.drawInt(Motor.A.getTachoCount(), 4,8,row);Button.waitForPress();

}/** * Main reduced to one line */ 

public 

static 

void main(String[] args){

new RotInterrupt().go();}

}

Page 74: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 74/183

Program 5: Regulating motor speed

The other principle task of the regulator thread is to control the motor speed. Onereason for doing this is that a two wheel vehicle will only travel in a straight line if both motors run at the same speed.(obviously). The standard Lego software solves this

 problem by directly synchronizing two motors. NXJ takes a different approach:keeping each motor rotation synchronized to the system clock. The regulatorcompares the tacho count (minus its reference count) with speed times elapsed time,and adjust the power to keep these two quantities closely matched. The regulatorresets its reference count and its elapsed time to zero and begins its comparison againwhenever you call any of the motor methods you have used so far.

New methods used in this program 

Class Method name Notes

Stopwatch  elapsed()  Returns elapsed time inmilliseconds

reset()  Resets the watch to 0.

The Stopwatch class is in the package lejos.util. 

What the program should do: 

1.  Create a new stopwatch.2.  Start all three motors running at 2 revolutions/second.3.  Every 200 ms, display all 3 tacho count values in the same row.4.  Repeat step 3, 8 times, using a different row each time.5.  Write down maximum difference you see between the motor tacho counts.

The motors should remain within a few degrees of each other. You may want tomodify the program and try the same test without regulation, to do this you will needto use the NXTMotor class and setPower method (see below). When regulation is not

used, the difference in angle of rotation get larger with time unless you have anunusually well matched set of motors.

Solution 

mport lejos.nxt.*;

import lejos.util.*;

Page 75: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 75/183

/** * Test the accuracy of motor speed regulation. 

* @author Roger */ 

public class RegulateTest{

Stopwatch sw = new Stopwatch();Motor [] m = {Motor.A, Motor.B, Motor.C}; //build an array of motors 

/** * Display program name, wait for button, then call go/ 

* @param args */ 

public static void main( String[] args){

LCD.drawString(" Reg Test", 0, 0);Button.waitForPress();LCD.clear();

new RegulateTest().go();}/** * helper method - does the detailed work; resets tacho count, runs 

motors, * displays data */ 

public void go(){

LCD.clear();sw.reset();

for( int i = 0; i<3; i++)m[i].resetTachoCount();

for( int i = 0; i<3; i++)m[i].setSpeed(720);

for( int i = 0; i<3; i++)m[i].forward();

for(int r = 0 ; r<8; r++){

while(sw.elapsed() < 200* r)Thread.yield();

for( int i = 0; i<3; i++)LCD.drawInt(m[i].getTachoCount(),5*i,r);

}

for( int i = 0; i<3; i++)m[i].stop();Button.waitForPress();

}

}

When might you want to turn off speed regulation? 

In some robots, the motor speed should not be constant but changed in response to asensor reading as for example in a line follower or a balancing robot. If the speedcorrections happen frequently, there is no advantage in the regulator thread using CPU

Page 76: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 76/183

cycles in adjusting the motor power to maintain constant speed between adjustments.To use an unregulated Motor you must create an instance of the class NXTMotor. Forexample:

NXTMotor m1 = new NXTMotor(MotorPort.A);

 NXTMotor has many of the methods of NXTRegulatedMotor, but instead of thesetSpeed method, it has a setPower method, and, as it has no regulation thread, it doesnot support any of the rotate methods.

When should you use speed regulation? 

If you specify a very slow speed, the power to maintain it may not be enoughovercome the motor internal friction, so the motor never moves. In this case, a call torotate() will never return. But with speed regulation on, the regulator will keepincreasing the power until the motor comes up to speed.

Can you mix the two methods of control?  

Yes you can. Simply create an instance of both NXTRegulatedMotor and NXTMotorclasses for the same motor port. When you want to use setPower simply turn offmotor regulation by calling suspendRegulation on the NXTRegulatedMotor instance.

Other Motor Methods

Finding out what the motor is doing

   boolean isMoving();

This is useful to test if the motor has finished rotating. isMoving() returns truewhen the Motor is moving for any reason (e.g. forward() or backward() have been called or a rotate() task is in progress)

  int getLimitAngle()

Returns the angle to which the motor is currently rotating

Page 77: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 77/183

  int getSpeed()

Returns the current speed setting.

  int getActualSpeed()

Returns the actual speed of the motor.

   boolean isStalled()

Tells you if the motor is stalled or if the regulation of the motor speed hasfailed (have you asked it to go faster then is possible?).

Various other motor methods 

  resetTachoCount()

This method not only sets the tacho count to 0 but also resets the origin used bythe regulator thread in deciding when to stop a rotation task.

  void setAcceleration(int acceleration)

Lets you control how fast the motor speed will change from one speed toanother. The acceleration is set in degrees per second per second. Use smallvalues (try 200 or 500) to have your robot smoothly accelerate up to speed.

  void getAcceleration()

Returns the current acceleration value for the motor

  suspendRegulation()

Turns of the regulation of the motor. Use this method if you want to mixregulated and unregulated control of the same motor.

NXTMotor methods 

  setPower(int aPower)

Page 78: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 78/183

Used to control motor power directly. Use a value between 0 and 100. Don’t

call this method if speed regulation is turned on because then the regulatorthread is continuously adjusting the power.

  int getPower()

returns the current power setting in the range of 0 to 100.

Controlling Wheeled Vehicles

Overview

A common type of robot is the two wheeled vehicle with independently controlledmotors. This design uses differential steering and can turn in place. The classes thatcontrol vehicles of this design deal with several levels of abstraction. At bottom, thereare the motors that turn the wheels, controlled by the NXTRegulatedMotor  class. TheDifferentialPilot class uses the motors to control elementary moves: rotate in place,travel in a straight line, or travel in an arc. At the next level, the NavPathControlleruses a DifferentialPilot to move the robot through a complicated path in a plane. Todo navigate, the path controller needs the robot location and the direction it is heading.It uses a OdometeryPoseProvider to keep this information up to date. Therelationships among these classes is shown in the in the table.

Class Uses

 NavPathControllerDifferentialPilot

OdometryPoseProvider

OdometryPoseProvider DifferentialPilot

DifferentialPilot RegulatedMotor

The flow of control is from the top down: the path controller controls the pilot whichcontrols the motors. But the flow of information is from bottom up. The pilot usesinformation from the motors to control them. The pose provider uses odometryinformation from the pilot to update its current estimate of the robot pose. The poseconsists of the robot's coordinates (x and y) and its heading angle (the direction it is

Page 79: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 79/183

facing ). The robot heading uses Cartesian coordinates, with angles in degrees; 0degrees is the direction of the positive x axis, 90 degrees is the positive y axis. The path controller uses this data to calculate the distance and direction to its destination.

This flow of information uses the listener and event model. The pilot registers as a

listener to with motors, which inform it when a motor rotation is started or completed.The pose provider registers as a listener with the pilot, which informs it of the startand completion of every movement. This event driven information flow automatic.The path controller can also requests a pose estimate whenever it needs to, even whilethe robot is moving,

DifferentialPilot

The DifferentialPilot class steers the vehicle by controlling the speed and direction ofrotation of its motors. The pilot object needs to know the wiring diagram of the robot,

i.e. which ports the motors are connected to and whether driving the motors forwardmakes the robot move forward or backward (reverse). It also needs to know thediameter of the wheels and the width of the track, i.e. the distance between the centresof the tracks of the two wheels. DifferentialPilot uses the wheel diameter to calculatethe distance it has traveled. It uses the track width to calculate how far it has rotated.Obviously, both parameters must be in the same units, but they can be anything youwish. With proper adjustment of these parameters, errors in distance traveled andangle of rotation can be held do 2% or perhaps less. This information is passed to the pilot constructor. DifferentialPilot is in the lejos.robotics.navigation package. Thedocumentation for this class is here. 

Constructors: 

  DifferentialPilot(float wheelDiameter, float trackWidth, Motor leftMotor,Motor rightMotor)

  DifferentialPilot(float wheelDiameter, float trackWidth, Motor leftMotor,Motor rightMotor, boolean reverse)Use this constructor if you need to set the reverse boolean to true . Then themotors will rotate backward to make the robot move forward,

Straight line movement 

To control the robot moving in a straight line, use:

  void setTravelSpeed(double travelSpeed)sets the speed of the motors in distance (wheel diameter)units per second

Page 80: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 80/183

  void forward()starts the robot moving forward

  void backward()  void stop()

To control the distance the robot moves, use:

  void travel(double distance)  void travel(double distance, boolean immediateReturn)

distance is in the same units as wheel diameter; a negative distance meanstravel backwards.

  getMovement().getDistanceTraveled() - returns the distance the vehicletraveled since the last call of resetTachoCount()

Example:

import lejos.nxt.*;

import lejos.navigation.Pilot;

/**

* Robot that stops if it hits something before it completes its travel.

*/

public class TravelTest {

DifferentialPilot pilot;

TouchSensor bump = new TouchSensor(SensorPort.S1);

public void go() {

pilot.travel(20, true);

while (pilot.isMoving()) {

if (bump.isPressed()) pilot.stop();

}

System.out.println(" "+pilot.getMovement().getDistanceTraveled());

Button.waitForPress();

}

public static void main(String[] args) {

TravelTest traveler = new TravelTest();

traveler.pilot = new DifferentialPilot(2.25f, 5.5f, Motor.A, Motor,C);

traveler.go();

}

}

Page 81: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 81/183

You can cause the robot to rotate in place by a specified angle by using

  void rotate(double degrees)

You must have accurate values for wheelDiameter and trackWidth for this

method to produce accurate results.

Program SquareTracer  

Write a program that uses a DifferentialPilot to trace out a square, using the travel androtate methods.

Solution 

import lejos.nxt.*;

import lejos.robotics.navigation.DifferentialPilot;

/** * Trace a square 

* @author Roger */ 

public class SquareTracer{

DifferentialPilot pilot ;

public void  drawSquare(float length){

for(int i = 0; i<4 ; i++){

pilot.travel(length);pilot.rotate(90);

}}

public static void main(String[] args){

SquareTracer sq = new SquareTracer();

sq.pilot = new DifferentialPilot(2.25f, 5.5f, Motor.A, Motor.C);sq.drawSquare(20);

}}

Page 82: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 82/183

Program SquareTracer2 

Write a program that traces 2 squares with increasing angle at the corners, thenretraces the same path in the opposite direction.. Modify the traceSquare method of

 program DifferentialPilot 1 so it can trace a square in either direction, and use it inthis program. This is stringent test of the accuracy of the wheel diameter and trackwidth constants you use in you pilot.

Solution 

import lejos.nxt.*;

import lejos.robotics.navigation.DifferentialPilot;

/** * Trace  two squares, twice. 

* @author Roger */ 

public class SquareTracer2{

DifferentialPilot pilot ;

public void  drawSquare(float length){

byte direction = 1;

if (length < 0 ){

direction = -1;length = -length;

}

for(int i = 0; i<4 ; i++){

pilot.travel(length);pilot.rotate(direction * 90);

}}

public static void main( String[] args){

System.out.println(" Square Tracer 2");Button.waitForPress();

SquareTracer2 sq = new SquareTracer2();

sq.pilot = new DifferentialPilot(2.25f, 5.5f, Motor.A, Motor.C);

byte direction = 1;

int length = 20;

for(int i = 0; i<4; i++){

sq.drawSquare(direction * length );

if ( i == 1){

sq.pilot.rotate( 90);direction = -1;

}}

Page 83: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 83/183

  }}

Movement along a curved path 

The pilot can turn the robot in place by driving one wheel forward and the other backward. The methods that do it are:

  void rotate(int angle)  void rotate(int angle, boolean immediateReturn )

If angle is positive, the robot turns to the left. The immediateReturn  parameter

works as in the Motor methods – allowing the calling thread to do other workwhile the rotation task in progress.

DifferentialPilot can also control the robot to move in a circular path using thesemethods:

  void steer(double turnRate) –  follows a circular path until another method isexecuted

  void steer(double turnRate, int angle)  void steer(double turnRate, int angle, boolean immediateReturn)

The turnRate  parameter determines the radius of the path. A positive value means thatcenter of the circle is to the left of the robot (so the left motor drives the inside wheel).A negative value means the left motor is the outside wheel. The absolute value is between 0 and 200, and this determines the ratio of inside to outside motor speed. Theoutside motor runs at the set speed of the robot; the inner motor is slowed down tomake the robot turn. At turn rate 0, the speed ratio is 1.0 and the robot travels in astraight line. At turn rate 200, the speed ratio is -1 and the robot turns in place. Turnrate 100 gives speed ratio 0, so the inside motor stops. The formula is: speed ratio =100 - abs(turnRate).

The angle  parameter determines the rotation angle at which the robot stops. If theangle is negative, the robot follows the circular path defined by the turn rate, but itmoves backwards.

  getMovement().getAngleTurned() - returns the angle of vehicle rotation sincethe last call of resetTachoCount()

Page 84: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 84/183

Program SteerTester  

Write a program that uses the ButtonCounter to enter the turn rate and angle variables,and then calls the steer() method. It does this in a loop so you can try different values

of these parameters to control the robot path.

Solution 

import lejos.nxt.*;

import lejos.navigation.*;

import lejos.util.*;

/** * Test the turn() method * Left botton enters 100's digit, right - 10's digit. */ 

public class SteerTest{

public static void main( String[] args){

DifferentialPilot pilot = new DifferentialPilot(2.25f, 4.8f, Motor.A,Motor.C); //units: inches 

ButtonCounter bc = new ButtonCounter();

while(true){

bc.count("Turn Rate x10");

int turnRate = 100 * bc.getLeftCount() + 10 * bc.getRightCount();bc.count("Angle x 10");

int angle = 100 * bc.getLeftCount() + 10 * bc.getRightCount();

pilot.steer(turnRate,angle);}

}}

Communicating with OdometryPoseProvider  

The OdometryPoseProvider keeps track of the robot position and heading. To do this,

it needs to know about every move made by the DifferetnialPilot. So the pilot needs toregister as a listener with the pose provider by calling the addListener method. Afterthe pilot does this,it will automatically call the moveStarted method on the pose provider every time a movement starts, andmoveStopped when the move is complete. Ifthe pose provider needs to know the status of a movement that is in progress, it callsthe getMovement() method on the pilot.

Page 85: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 85/183

Other methods for DifferentialPilot 

  void resetTachocount()Resets the count for both motors.

   boolean isMoving()Returns true if either motor is moving. Useful if you have used theimmediateReturn parameter and need to know if the task is still in progress.

   boolean stalled()returns true if either motor actual speed is zero. Remember, the actual speed iscalculated every 100ms. So stalled() will return true  for the first 100ms afterthe robot begins its move.

If you really need to deal with individual motors, you can use:

  Motor getLeft()  Motor getRight()

Compass Pilot

The CompassPilot is an extension of the DifferentialPilot class. It implements thesame methods, but uses a Compass Sensor  to ensure that the pilot does not deviatefrom the correct angle of robot heading.

It needs a HiTechnic or Mindsensors compass sensor plugged in to one of the sensor ports. Its constructors are similar those of DifferentialPilot, but with the additionalinformation of the compass sensor port.

Constructors: 

  CompassPilot(SensorPort compassPort, float wheelDiameter, floattrackWidth,Motor leftMotor, Motor rightMotor)

  CompassPilot(SensorPort compassPort, float wheelDiameter, floattrackWidth,Motor leftMotor, Motor rightMotor, boolean reverse)

 Additional methods in CompassPilot: 

  void calibrate()calibrate the compass sensor; rotates the robot slowly through 360 degreees.

Page 86: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 86/183

  setHeading(int angle)set the desired robot heading, in degrees in Cartesian coordinates (a left turnincreases the heading)

  int getHeading()return the desired robot heading

  int getAngle()return the compass Cartesian angle. Also the actual robot heading assuming thecompass sensor points forward.

 Additional methods in CompassPilot: 

Write a program that does these steps:

1.  Calibrate the compass.

2.  Rotate the robot to a heading or 90 degrees3.  Reset the Cartesian zero of the compass sensor to correspond the current

heading.4.  Move the robot a fixed distance forward.5.  Rotate 90 degrees to the left.6.  Move the robot the same distance backwards.7.  Display the compass reading and the distance traveled at the end of each move.

Suggestion: while the robot is moving, nudge it off course and watch it steer back tothe correct heading.

Solution 

import lejos.nxt.*;

import lejos.navigation.*;

/** * Testing the compass pilot. 

* @author Roger */ 

public class CompassPilotTst

{

public static void main(String[] args){

System.out.println("CompassPilot Test");Button.waitForPress();

CompassPilot pilot = new CompassPilot(SensorPort.S3, 2.25f, 4.8f,Motor.A, Motor.C);

pilot.calibrate();LCD.drawInt(pilot.getAngle(), 4, 0, 0);

Page 87: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 87/183

  Button.waitForPress();pilot.rotateTo(90);pilot.getCompass().resetCartesianZero();pilot.travel(20);

LCD.drawInt((int) pilot.getTravelDistance(), 4, 0, 1);LCD.drawInt(pilot.getAngle(), 5, 8, 1);pilot.rotateTo(180);pilot.travel(-20);

LCD.drawInt((int) pilot.getTravelDistance(), 4, 0, 2);LCD.drawInt(pilot.getAngle(), 5, 8, 2);Button.waitForPress();

}}

OdometryPoseProvider

The responsibility of this class is to maintain a current estimate of the robot locationand the direction in which it is heading. This information is stored in a Pose object.The API for Pose is here. For the OdometryPoseProvider documentation click here. The only constructor for this class is:

  OdometryPoseProvider(MoveProvider mp) )It registers the new pose provider object as a listener with the MoveProvider.

The methods that the move provider uses at the obvious times are:

  moveStarted(Move move, MoveProvider mp)   public void moveStopped(Move move, MoveProvider mp)

The odometry data is contained in the Move object, which the pose provider uses tocalculate the new robot pose.

The only methods you are likely to use are:

  setPose(Pose aPose)  Pose getPose()

If this method is called while the robot is moving, the pose provider will callgetMovement() on the move provider. This guarantees that the pose is current.

NavPathController

Page 88: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 88/183

 NavPathController (the navigator) uses a pilot and a PoseProvider to follow a route, aseries of locations. Each location is stored in a WayPoint object. The WayPoint APIis here. The route stored as a queue. When the a way point is reached, it is removedfrom the route and the robot goes to the next one. New way points can be added to theroute at any time. Documentation for the NavPathController is here. 

There are three ways to construct an instance of this class:

Constructors: 

   NavPathController(MoveControlle aPilot)To use this constructor, you must construct a pilot and use it as the parameter.The consttructor will create its own OdometryPoseProvider

   NavPathController(MoveController pilot, PoseProvider poseProviderUse this if you want to use another PoseProvider class

   NavPathController(MoveController pilot, PoseProvider poseProvider,PathFinder pathFinder)This constructor also attaches a PathFinder.

Navigation methods 

The primary methods for navigating the route in the absence of obstacles are listed below. The methods that do not have a immediateReturn are non-blocking (they willreturn immediately).

  followRoute(Collection<WayPoint> aRoute, boolean immediateReturn)This method does exactly what its name suggests. If immediateReturn is false,the method will return when the last way point is reached. Otherwise, themethod is non-blocking

  addWayPoint(WayPoint aWayPoint)The WayPoint is added to the route. If the route was empty, the robotimmediately starts moving.

  goTo(WayPoint destination, boolean immediateReturn)If the queue is not empty, it is flushed. The destination is added to the route and

the robot starts moving.  goTo(WayPoint destination)

The non-blocking version of the previous method.  goTo(double x,double y)

Just another way to specify the destination. Acts like the previous method.  interrupt()

Stops the robot but preserves the route.

Page 89: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 89/183

  resume()Start following the route again. use after calling interrupt().

  isGoing()Returns the navigator status. false if the last way point has not yet been reachedor the route has been interrupted and not resumed.

ShortestPathFinder

Suppose your robot is in a known location and needs to get to a destination. But thereare obstacles in the way. These obstacles are shown on a map. So what route should itfollow? This class can find the shortest path to the destination, and produce a route (acollection of WayPoints) that the NavPathController can use. The map this classneeds is a LineMap which, as its name suggests, consists of straight lines.The

complete documentation for this class is here. Using this class is very simple. Theconstructor is:

  ShortestPathFinder(LineMap map)

After you constructed the path finder, you can get the route by using either of theroute finding methods. They both use a Pose as the starting point, which might bereturned returned by the a pose provider, and a WayPoint as the destination. The bothwill throw the DestinationUnreachableException if no route cab be found.

  findRoute(Pose start,WayPoint finish)  findRoute(Pose start, WayPoint finish, LineMap theMap) throws

DestinationUnreachableExceptionIf you don't want to use the map specified in the constructor, you can use adifferent one in this method.

The shortest path, if not a direct line, will have way points at the ends of lines, such asthe corners of obstacles on the map. But the physical robot is not a point, so if thecenter of the robot tries to pass through a corner, there will be a crash. One solution tothis difficulty is to enlarge the map obstacles to allow clearance for the robot.

However, this may be tedious to by hand, and complex to do with software. A simplerscheme is to extends all the lines on the original map so that a corner now isrepresented by two points, each some distance from the corner. To make thismodification of the map,use the method :

  lengthenLines(float delta)

Page 90: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 90/183

which adds a segment of length delta to each line on the map. The extension deltashould probably be at least the track width of the robot, plus an allowance foruncertainties in the robot location.

Object Detection

Object detection allows a robot to detect objects in its path and take some action, suchas avoiding the object. We chose the term feature to describe an object rather thanobstacle, because sometimes the object is something the robot wants to seek, ratherthan avoid (such as a soccer ball). We didn't use the word "object" because it was a potentially confusing class name with object oriented Java programming.

Feature Detectors

A FeatureDetector detects objects using a sensor, such as a touch sensor or ultrasonicsensor. It is the main interface in the object detection package from which all dataoriginates. There are many benefits of using a FeatureDetector:

  Automatic scanning and reporting of data  A listener interface to segregate the "action-response" code  Allows one code segment to respond to data from multiple sensors

There are currently two implementations:

  RangeFeatureDetector - uses RangeFinder classes, such as the LEGOUltrasonicSensor.

  TouchFeatureDetector - uses Touch classes, such as the LEGO TouchSensor.

The RangeFeatureDetector allows you to specify some parameters for the sensor, suchas the maximum range you want it to report findings for, and the time between performing scans. Construct a simple RangeFeatureDetector as follows:

int MAX_DISTANCE = 50; // In centimeters

int PERIOD = 500; // In milliseconds

UltrasonicSensor us = new UltrasonicSensor(SensorPort.S4);

FeatureDetector fd = new RangeFeatureDetector(us, MAX_DISTANCE, PERIOD);

Page 91: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 91/183

Once you have a FeatureDetector instantiated, you can perform a scan on it to retrievedata:

Feature result = fd.scan();

if(result != null)System.out.println("Range: " + result.getRangeReading().getRange());

Warning: Make sure to check for a null object before trying to read data from the

returned Feature object, otherwise your code will throw a null pointer exception. 

The main benefit of a FeatureDeteector is the ability to automatically notify otherclasses when an object is detected via a listener interface. The next section discussesthis in more detail.

Feature Listeners

Once you have a FeatureDetector instantiated, you can add a FeatureListener to it.The FeatureListener code will be notified when an object is detected via theFetureListener.featureDetected() method. There you can make your robot react to thedetected object by performing some sort of action. The following code shows how touse a FeatureListener:

import lejos.nxt.*;

import lejos.robotics.objectdetection.*;

public class ObjectDetect implements FeatureListener {

public static int MAX_DETECT = 80;

public static void main(String[] args) throws Exception {

ObjectDetect listener = new ObjectDetect();

UltrasonicSensor us = new UltrasonicSensor(SensorPort.S4);

RangeFeatureDetector fd = new RangeFeatureDetector(us,MAX_DETECT, 500);

fd.addListener(listener);

Button.ENTER.waitForPressAndRelease();

}

public void featureDetected(Feature feature, FeatureDetectordetector) {

Page 92: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 92/183

  int range = (int)feature.getRangeReading().getRange();

Sound.playTone(1200 - (range * 10), 100);

System.out.println("Range:" + range);

}

}

Feature data

The most basic class to implement the Feature interface is the RangeFeature class.This class is a data container, and the data is retrieved by these methods:

  getRangeReading() - returns a RangeReading object  getRangeReadings() - returns a RangeReadings collection

  getTimeStamp() - returns the system time (in ms) when this data was collected

Some scanners are capable of returning multiple object detections, such as the LEGOultrasonic sensor. Other sensors are only capable of producing a single objectdetection. In either case, they are both capable of producing data to fulfill bothmethods, as described below.

Single Reading 

When the getRangeReading() method is called, it returns the closest object that was

detected by a scanner, even if it is capable of returning more than one hit.

Multiple Readings 

When the getRangeReadings() method is called, it returns the all objects it detected. Ifthe scanner is only capable of returning one hit, the RangeReadings object willcontain only one RangeReading.

Multiple Feature Detectors

It is also possible to combine several different FeatureDetectors into oneFeatureDetector using the FusorDetector class. This is useful for robots that have anumber of detector sensors located on the robot (several bumpers at different locationsand range sensors). The code to fuse many FeatureDetectors looks like this:

UltrasonicSensor us = new UltrasonicSensor(SensorPort.S4);

Page 93: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 93/183

FeatureDetector detector1 = new RangeFeatureDetector(us,MAX_DETECT,RANGE_READING_DELAY);

Touch leftBump = new TouchSensor(SensorPort.S2);

FeatureDetector detector2 = new TouchFeatureDetector(leftBump, 10,TOUCH_Y_OFFSET);

Touch rightBump = new TouchSensor(SensorPort.S3);

FeatureDetector detector3 = new TouchFeatureDetector(rightBump, -10,TOUCH_Y_OFFSET);

FusorDetector fusion = new FusorDetector();

fusion.addDetector(detector1);

fusion.addDetector(detector2);

fusion.addDetector(detector3);

fusion.addListener(myFeatureListener);

Hardware: I/O and Sensors

This section covers the classes for user input and output, and also the standard NXT

sensors. The NXT hardware has buttons for input, a Liquid Crystal Display (LCD)and a small speaker for output. leJOS NXJ provides software abstractions for all these bits of hardware.

LCD

The LCD class has no instances (there being only one LCD on the NXT), so all themethods are static. It can be used in text mode and graphics mode.

LCD Text methods 

As a text display, the NXT LCD screen is 16 characters wide and eight charactersdeep. It is addressed using (x, y) co-ordinates as follows:

Page 94: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 94/183

 

x ranges from 0 to 15, and y from 0 to 7. 

The methods to write to the LCD in text mode are :-

  void drawString(String str, int x, int y)

This draws a string of text to the LCD screen starting at text co-ordinate (x, y).

  void drawInt(int i, int x, int y)

This draws an integer starting at text co-ordinate (x,y).The integer is leftaligned and takes up as many characters as are necessary.

  void drawInt(int i, int places, int x, int y)

This variant of drawInt right-aligns the integer and always uses the number ofcharacters indicated by places. This means that it always writes to a fixednumber of character places and, if used in a loop, the previous value willalways be fully overwritten.

  void clear()

Clears the display.

Example:

import lejos.nxt.*;

import java.io.*;

public class LCDTest {

public static void main(String[] args) throws Exception {

Page 95: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 95/183

  LCD.drawString("Free RAM:", 0, 0);

LCD.drawInt((int) System.getRuntime().freeMemory(), 6, 9, 0);

Thread.sleep(2000);

}

}

 Note that you can also write to the LCD display with System.out.println(String str).This scrolls the display up one line and writes to the bottom line of the screen.

 Note, also, that by default, the LCD display is refreshed automatically. If you want tocontrol when the LCD is refreshed, you can call LCD.setAutoRefresh(0) to turn offauto-refreshing and call LCD.refresh() when you want to refresh the display.

LCD Graphics methods 

As a graphics display, the NXT LCD screen is 100 pixels wide and 64 pixels deep. Itis addressed using (x, y) pixel co-ordinates in the same way as for text co-ordinates:

x ranges from 0 to 99, and y from 0 to 63. 

To display graphics on the LCD screen, you can use the Graphics class from the package javax.microedition.lcdui. See the Graphics class API. With this class, you can

draw lines, rectangles, arcs, and position strings with pixel accuracy.

Example:

import javax.microedition.lcdui.Graphics;

Page 96: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 96/183

public class GraphicsSample {

public static void main(String [] options) throws Exception {

Graphics g = new Graphics();

g.drawLine(5,5,60,60);

g.drawRect(62, 10, 25, 35);Thread.sleep(2000);

}

}

Buttons

The Button class has four instances, accessed by static fields:

  Button.ENTER  Button.ESCAPE  Button.LEFT  Button.RIGHT

To test if a button is pressed, you use:

   boolean isPressed()

Example:

import lejos.nxt.*;

public class ButtonPresses {

public static void main(String[] args) throws Exception {

while (true) {

LCD.clear();

if (Button.ENTER.isPressed()) LCD.drawString("ENTER", 0, 0);

if (Button.ESCAPE.isPressed()) LCD.drawString("ESCAPE", 0, 0);if (Button.LEFT.isPressed()) LCD.drawString("LEFT", 0, 0);

if (Button.RIGHT.isPressed()) LCD.drawString("RIGHT", 0, 0);

}

}

}

Page 97: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 97/183

To wait for a specific button to be pressed and released, you use:

  void waitForPressAndRelease() throws InterruptedException

Example:

import lejos.nxt.*;

public class ButtonTest

{

public static void main (String[] args)

throws Exception

{

Button.ENTER.waitForPressAndRelease();

LCD.drawString("Finished", 3, 4);Thread.sleep(2000);

}

}

To wait for any button to be pressed, you use:

  static int waitForPress()

The returns the id code of the button that is pressed.

button ENTER LEFT RIGHT ESCAPE 

Code 1 2 4 8 

To specify a listener to listen for button events for this button, you: use

  void addButtonListener (ButtonListener aListener)

See “Listeners and Events” for how button listeners work. 

To read the current state of all the buttons, you use:

  static int readButtons()

The return value is the sum of the codes of the buttons that are pressed.

Page 98: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 98/183

 

Sound

This class controls the single speaker so it has no instances and all the methods are

static.

To play a single tone, use

  void playTone(int aFrequency, int aDuration)

Example:

import lejos.nxt.*;

public class PlayTones {

private static final short [] note = {2349,115, 0,5, 1760,165, 0,35};

public static void main(String [] args) throws Exception {

for(int i=0;i <note.length; i+=2) {

short w = note[i+1];

int n = note[i];

if (n != 0) Sound.playTone(n, w*10);

Thread.sleep(w*10);

}

}

}

There are two ways to play system sounds. One is:

  void systemSound (boolean aQueued, int aCode)

The aQueued parameter is ignored on the NXT, it is here to be backwards

compatible with the RXC.

The values of code are:

code = 0 Short beepcode = 1 Double beepcode = 2 Descending arpeggio

Page 99: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 99/183

code = 3 Ascending arpeggiocode = 4 Long, low buzz

Individual methods to play a particular system sound, if you don’t remember the code,

are

  void beep()  void twoBeeps()  void beepSequence()  void beepSequenceUp()  void buzz();int playSample(File aWAVfile)  int playSample(File aWAVfile, int volume)

There is also a method to produce a rest when playing a tune; time in milliseconds

  void pause(int time)

You can use this method anytime you want your program wait, and don’t want

to bother with the try/catch block required by Thread.sleep().

leJOS NXJ has methods that can also play 8-bit WAV files:

  int playSample(File aWAVfile)  int playSample(File aWAVfile, int volume)

The return value of milliseconds the sample will play for or < 0 if there is an error.

To play a musical note, use:

  void playNote(int[] inst,int freq, int len)

The inst  array contains the attack, decay, sustain and release parameters for thenote. The static constants for some predefined instruments are: FLUTE, PIANOand XYLOPHONE. You can also experiment with defining you own.

Battery

There are two static methods to get the battery voltage:

  int getVoltageMilliVolt()  float getVoltage()

Page 100: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 100/183

Example:

import lejos.nxt.*;

public class BatteryTest {public static void main(String[] args) throws Exception {

LCD.drawString("Battery: " + Battery.getVoltage(), 0, 0);

Thread.sleep(2000);

}

}

Sensors

The NXT comes with four sensors; the touch sensor, the sound sensor, the light sensorand the ultrasonic sensor. leJOS NXJ provides software abstractions of all thesesensor types, as well as many provided by third parties.

A physical sensor must be connected to a port, and the sensor object must know which port this is. To provide this information, you create an instance of the sensor, and passthis information in its constructor. The possibilities are: SensorPort.S1, S2, S3 or S4.

Touch Sensor  

To use a touch sensor, you create an instance of it, using the constructor:

  TouchSensor(SensorPort port)

To test if the touch sensor is pressed, you use the isPressed() method:

   boolean isPressed()

Example:

import lejos.nxt.*;

public class TouchTest {

public static void main(String[] args) throws Exception {

TouchSensor touch = new TouchSensor(SensorPort.S1);

Page 101: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 101/183

 

while (!touch.isPressed() ;

LCD.drawString("Finished", 3, 4);

}

}

Light Sensor  

To use a light sensor, you create an instance of it using the constructor:

   public LightSensor(SensorPort port)

Example:

import lejos.nxt.*;

public class LightTest {

public static void main(String[] args) throws Exception {

LightSensor light = new LightSensor(SensorPort.S1);

while (true) {LCD.drawInt(light.getLightValue(), 4, 0, 0);

LCD.drawInt(light.getNormalizedLightValue(), 4, 0, 1);

LCD.drawInt(SensorPort.S1.readRawValue(), 4, 0, 2);

LCD.drawInt(SensorPort.S1.readValue(), 4, 0, 3);

}

}

}

Sound Sensor  

The sound sensor supports two modes: DB and DBA. These modes give differentfrequency response, so that it may be possible to get an idea of the frequency of asound by switching between modes.

Page 102: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 102/183

There are two constructors:

  SoundSensor(SensorPort port)

creates a sound sensor using DB mode.

  SoundSensor(SensorPort port, dba)

creates a sound sensor using DBA mode if the second parameter is true .

You can switch modes with:

  void setDBA(boolean dba)

Example using DB mode only:

The above example gives a graphical display of the way the sound reading varies overa two-second period.

import lejos.nxt.*;

public class SoundScope {

public static void main(String[] args) throws Exception {

SoundSensor sound = new SoundSensor(SensorPort.S1);

while (!Button.ESCAPE.isPressed()) {

LCD.clear();

for (int i = 0; i < 100; i++) {

LCD.setPixel(1, i, 60 - (sound.readValue() / 2));

Thread.sleep(20);

}

}

}

}

Ultrasonic Sensor  

To create an instance, use the constructor:

Page 103: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 103/183

  UltrasonicSensor( Port aSensorPort)

The sensor operates in two modes, continuous (default) and ping. When in continuousmode the sensor sends out pings as often as it can and the most recently obtainedresult is available via a call to

  int getDistance()

The return value is in centimeters. If no echo was detected, the returned value is255. The maximum range of the sensor is about 170 cm.

Example:

import lejos.nxt.*;

public class SonicTest {

public static void main(String[] args) throws Exception {

UltrasonicSensor sonic = new UltrasonicSensor(SensorPort.S1);

while (!Button.ESCAPE.isPressed()) {

LCD.clear();

LCD.drawString(sonic.getVersion(), 0, 0);

LCD.drawString(sonic.getProductID(), 0, 1);

LCD.drawString(sonic.getSensorType(), 0, 2);

LCD.drawInt(sonic.getDistance(), 0, 3);

}

}

}

When in ping mode, a ping is sent only when a call is made to

  void ping()

This sets the sensor in ping mode and sends a single ping and up to 8 echoes

are captured. These may be read by making a call to

  int readDistances(int [] distances)

You provide an integer array of length that contains the data after the methodreturns. A delay of approximately 20ms is required between the call to ping andgetDistances. This delay is not included in the method. Calls to getDistances

Page 104: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 104/183

 before this period may result in an error or no data being returned. The normalgetDistance call may also be used with ping, returning information for the firstecho.Calling ping() will disable the default continuous mode. Toto switch back tocontinuous mode, call

  int continuous()

Program: multiple echoes 

Write a program that displays the distances from multiple echoes in a column. The program should make four calls to ping(), and display the four columns of results,then wait for a button press. Exit if the ESCAPE button was pressed.

Solution 

import lejos.nxt.*;

/** * Ultrasonic Sensor test of ping  multiple distances 

* @author  Roger */ 

public class USPingTest{

public static void main( String[] args){

LCD.drawString(" USPing",0,0);

Button.waitForPress();LCD.clear();

UltrasonicSensor sonar = new UltrasonicSensor(SensorPort.S3);

int[] distances = new int[8];

int col = 0;

boolean more = true;

while(more){

sonar.ping();Sound.pause(30);sonar.getDistances(distances);

for(int i = 0; i<distances.length;i++){

LCD.drawInt(distances[i], 4, 4*col,i);}col ++;

if (col >4 ){

more = Button.waitForPress()<8;col = 0;

}}

Page 105: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 105/183

  }}

Threads, Listeners and Events

Java Threads

When a Java program starts, there is a single thread running –  the main thread.

Many of the leJOS classes start extra threads running for various purposes, forexample:

  Button and SensorPort start a listener thread if listeners are used

   NXTRegulatedMotor (and hence Motor) start a single motor regulator thread  The Bluetooth class starts a thread to talk to the separate Bluetooth chip  Each Timer object starts a timer thread  Some of the navigation classes, e.g. NavPathController, start extra threads

User programs can create their own threads by subclassing Thread, and then using thestart method to start the thread. In leJOS NXJ 0.7 and later, threads can be createdfrom any class that implements the Runnable interface.

Background threads that do not need to terminate in order for the user program to

terminate, should be marked as daemon threads by calling setDaemon(true).

When using threads, care should be taken with concurrency issues. When data itemsare accessed by multiple threads, synchronization is necessary to ensure that data isnot read when it is in an inconsistent state.

leJOS NXJ supports the standard Java synchronization mechanisms: synchronizedmethods and synchronized statements using a monitor object.

As an example of a leJOS thread, consider the Indicators thread in the leJOS

StartUpText menu. This is used to keep the display of the battery level up to date, byreading its value every second, and to indicate when the menu is uploading files ordoing other communication from the PC:

import lejos.nxt.LCD;

class Indicators extends Thread {

Page 106: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 106/183

  private boolean io = false;

public void ioActive() {

io = true;

}

public void run() {

String[] ioProgress = { ". ", " . ", " . " };

int ioIndex = 0;

boolean rewrite = false;

while (true) {

try {

if (io) {

StartUpText.g.drawString(" ", 76, 0);

ioIndex = (ioIndex + 1) % ioProgress.length;

StartUpText.g.drawString(ioProgress[ioIndex], 78, 0);io = false;

rewrite = true;

} else if (rewrite) {

LCD.drawString(" ", 13, 0);

// invert when power is off

StartUpText.g.drawString(" BT", 82, 0, !StartUpText.btPowerOn);

StartUpText.g.refresh();

rewrite = false;

}

Thread.sleep(1000);} catch (InterruptedException ie) {

}

}

}

}

The main method starts this thread by:

Indicators ind = new Indicators();

ind.setDaemon(true);

ind.start();

Listeners and Events

Page 107: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 107/183

leJOS implements a listener thread that listens for particular events.

The listener thread supports:

  Button Listeners  Sensor Port Listeners

Button listeners are used to detect when a button is pressed, whatever your program isdoing at the time.

To listen for a press of a specific button, you register as listener for that button.

Example:

import lejos.nxt.*;

public class ListenForButtons {

public static void main(String[] args) throws Exception {

Button.ENTER.addButtonListener(new ButtonListener() {

public void buttonPressed(Button b) {

LCD.drawString("ENTER pressed", 0, 0);

}

public void buttonReleased(Button b) {

LCD.clear();

}

});

Button.ESCAPE.waitForPressAndRelease();

}

}

Error Handling and Debugging

leJOS NXJ provides several features for error handling and debugging, including:

  Exceptions  Data Aborts  Debugging

Page 108: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 108/183

The Remote Monitoring and Tracing facility, which is described in its own section below, can also be used for debugging.

Exceptions

Most of the standard Java language exception classes are supported by leJOS, anduser can create their own exception classes.

Example:

The following ExceptionTest example demonstrates what happens for an exceptionthat is not caught –  in this case an ArrayIndexOutOfBounds exception.

public class ExceptionTest {

static void m1(){

int test[] = new int[2];

// Force an exception

test[0] = test[1] + test[2]; // This is line 6

}

static void m2()

{

m1();

}

public static void main (String[] aArg) throws Exception

{

System.out.println("Running");

m2();

}

}

When this code is run the NXT will display the uncaught exception screen. Which

looks something like this:

Exception: 28

at: 20(11)

at: 21(1)

at: 22(9)

Page 109: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 109/183

 

But what are these numbers telling us? The first line tells us the number of theexception class that has been thrown, in this case class 28. The following lines showus a mini stack trace, one for each method in the call stack, showing the method

number and the program counter location within the method. The top most item is thelocation that the exception was thrown, which in this case was at location 11 inmethod number 20.

So we now understand what the numbers are, but how do we relate them to our program? Well one way is to use the verbose output from the linker, an abbreviatedversion of which looks like this:

Class 0: java.lang.Object

Class 1: java.lang.ThrowableClass 2: java.lang.Error

Class 3: java.lang.OutOfMemoryError

Class 4: boolean

Class 5: char

Class 6: float

Class 7: double

Class 8: byte

Class 9: short

Class 10: int

Class 11: long

Class 12: void

Class 13: java.lang.Object[]

Class 14: java.lang.NoSuchMethodError

Class 15: java.lang.StackOverflowError

Class 16: java.lang.NullPointerException

Class 17: boolean[]

Class 18: char[]

Class 19: float[]

Class 20: double[]

Class 21: byte[]

Class 22: short[]

Class 23: int[]

Class 24: long[]

Class 25: reserved

Class 26: java.lang.ClassCastException

Class 27: java.lang.ArithmeticException

Class 28: java.lang.ArrayIndexOutOfBoundsException

Page 110: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 110/183

Class 29: java.lang.IllegalArgumentException

Class 30: java.lang.InterruptedException

Class 31: java.lang.IllegalStateException

Class 32: java.lang.IllegalMonitorStateException

Class 33: java.lang.ThreadDeath

.... other classes omittedMethod 0: java.lang.Object.<init>() PC 1976 Signature id 2

Method 1: java.lang.Object.getClass() PC 1977 Signature id 121

Method 2: java.lang.Object.toString() PC 1985 Signature id 123

Method 3: java.lang.Throwable.i<init>() PC 2013 Signature id 2

Method 4: java.lang.Throwable.<init>(java.lang.String) PC 2023 Signature id124

Method 5: java.lang.Throwable.getLocalizedMessage() PC 2038 Signature id125

Method 6: java.lang.Throwable.getMessage() PC 2043 Signature id 29

Method 7: java.lang.Throwable.toString() PC 2048 Signature id 123

Method 8: java.lang.Throwable.fillInStackTrace() PC 2096 Signature id 126

Method 9: java.lang.NullPointerException.<init>() PC 2109 Signature id 2

Method 10: java.lang.Class.isInterface() PC 2114 Signature id 133

Method 11: java.lang.Class.toString() PC 2131 Signature id 123

Method 12: java.lang.String.<init>(int) PC 2177 Signature id 128

Method 13: java.lang.String.<init>(char[], int, int) PC 2189 Signature id141

Method 14: java.lang.String.charAt(int) PC 2206 Signature id 145

Method 15: java.lang.String.length() PC 2231 Signature id 155

Method 16: java.lang.String.toString() PC 2237 Signature id 123

Method 17: java.lang.String.valueOf(java.lang.Object) PC 2239 Signature id167

Method 18: java.lang.Thread.run() PC 2253 Signature id 1

Method 19: java.lang.Thread.currentThread() Native id 12

Method 20: ExceptionTest.m1() PC 2273 Signature id 175

Method 21: ExceptionTest.m2() PC 2288 Signature id 176

Method 22: ExceptionTest.main(java.lang.String[]) PC 2292 Signature id 0

Method 23: lejos.nxt.VM.<clinit> PC 2304 Signature id 3

Method 24: lejos.nxt.VM.<init>() PC 2323 Signature id 2

Method 25: lejos.nxt.VM.getVM() PC 2358 Signature id 177

Method 26: lejos.nxt.VM.memPeek(int, int, int) Native id 103

.... other methods omitted

We can use the class table to look up the exception class, in this case class 28 is java.lang.ArrayIndexOutOfBoundsException so we know we have an array out of bounds exception. Now we can look up the method names. Method 20 isExceptionTest.m1, method 21 is ExceptionTest.m2 and method 22 is

Page 111: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 111/183

ExceptionTest.main. Which tells us that the exception has been thrown in method m1,that was called from method m2, that was in turn called from method main. So far sogood, but how do we use the value of the location counter to narrow down whereexactly the exception occurred. Well we could decompile the byte code classes anduse that but there has to be an easier way right? Well yes there is. leJOS comes with

two tools that make this process much easier, one helps you decode the abovenumbers, the other will do all of the work for you. Both tools require an additionallinker option -od which tells the linker to output extra debug information to thespecified file. Once we have this file we can use the NXJDebugTool to decode theexception data as shown below:

C:\samples\ExceptionTest>nxjc ExceptionTest.java

C:\samples\ExceptionTest>nxjlink -o ExceptionTest.nxj -od ExceptionTest.nxdExceptionTest

C:\samples\ExceptionTest>nxjdebugtool -di ExceptionTest.nxd -c -m 28 20 11

The class number 28 refers to:

java.lang.ArrayIndexOutOfBoundsException(ArrayIndexOutOfBoundsException.java)

The method number 20 refers to:

ExceptionTest.m1()V (ExceptionTest.java)

PC 11 refers to:

line 6 in ExceptionTest.java

Which as you can see tells you exactly which line in the source code the exceptionwas thrown on.

The final option is to make use of the leJOS remote console application (see below formore details). again we need some extra linker options, this time -od to create thedebug information and -gr to add the remote console debug code to the program. If welink with these options and run the program again, then three extra things happen, first

the program will wait for the remote console application to connect to it, secondly anyoutput that uses the System.out stream will be re-directed to the console display (inthis case "Running") and finally the exception information will be displayed by theremote console in an easy to understand form. See below for an example of this:

C:\samples\ExceptionTest>nxjc ExceptionTest.java

Page 112: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 112/183

C:\samples\ExceptionTest>nxjlink -gr -o ExceptionTest.nxj -odExceptionTest.nxd ExceptionTest

C:\samples\ExceptionTest>nxjupload -r ExceptionTest.nxj

Found NXT: nxt2 001653015066

leJOS NXJ> Connected to nxt2

leJOS NXJ> Upload successful in 2904 millisecondsC:\samples\ExceptionTest>nxjconsole -di ExceptionTest.nxd

Debug attached

Found NXT: nxt2 001653015066

leJOS NXJ> Connected to nxt2

Connected to nxt2 001653015066

Console open

Running

Exception: java.lang.ArrayIndexOutOfBoundsException

at: ExceptionTest.m1(ExceptionTest.java:6)

at: ExceptionTest.m2(ExceptionTest.java:12)at: ExceptionTest.main(ExceptionTest.java:18)

Console closed

Data Aborts

If the leJOS firmware crashes you will normally a Data Abort. The screen shows thePC value where the failure occurred, and other details of the failure.

The screen is something like:

DATA ABORT

PC 00140BAC

AASR 1831BF01

ASR 00020601

OPCODE ???

DEBUG1 00020010

DEBUG2 00000000

The most common reason for data aborts is executing a file that is not a leJOS NXJ binary, or executing an incomplete leJOS NXJ file.

If you get a data abort in any other case, you should report the error to the leJOSdevelopment team by posting the details on the leJOS NXJ forums.

Page 113: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 113/183

Remote Debugging

You can use your PC as a remote console to display tracing statements generated your NXJ program. The lejos.nxt.comm.RConsole class has methods to it. Since there areno instances of this class, all methods are static.

To start debugging, you use one of these methods:

  void open()

opens a USB connection with no timeout

  void openUSB(int timeout)  void openBluetooth(int timeout)

The NXT displays USB Console.. or BT Console.

and waits for the PC based monitor to connect.

Then execute the nxjconsole  program on your PC. When the connection isestablished, the NXT displays Got Connection and, after some seconds, both the NXTand the PC display Console open. 

If you use the variant of open with a timeout, it waits the specified number of secondsand if the debug monitor has not connected, proceeds without debugging. If the

timeout is zero, it waits indefinitely.

You can also use the ConsoleViewer  application to display the output.

Debug statements can be output using one of the methods:

  void println(String s)  void print(String s);

If no successful open statement has been executed, the debug output is discarded. Ifthere was a successful output, the string appears on standard out in the window orterminal that nxjconsole was run from, on the PC.

When debugging is completed, you should call:

  void close()

This closes the USB or Bluetooth connection.

Page 114: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 114/183

Example:

import lejos.nxt.*;

import lejos.nxt.comm.*;

/** * example using RConsole*/

public class TestRConsole {

public static void main(String[] args) {

RConsole.open();

RConsole.println("Start for loop ");

for (int i = 0; i < 5; i++) {

RConsole.print(" " + i);

LCD.drawInt(i, 2, 2 * i, 4);

}

RConsole.println("\n done ");RConsole.close();

Button.waitForPress();

}

}

Communications

leJOS NXJ supports communications using Bluetooth and USB. The NXJcommunications classes are designed so that most of your code is independent ofwhether you are using Bluetooth or USB –  you can write applications that work with both (see the example below). And you can use Java streams, which are a veryflexible and easy to use.

USB has the advantage of speed, but the cable can be used only to connect a NXT to aPC. Bluetooth is slower, but much flexible. It supports a multitude of methods of

communicating NXT to NXT, PC to NXT, Mobile phone to NXT, NXT to remoteBluetooth device, etc.

The first step in communicating is to establish a connection. A connection has aninitiator and a receiver. The receiver waits for a connection from the initiator. Theinitiator connects to a specific device that must be waiting for a connection. When theconnection has been established, both ends of the connection can use it to open input

Page 115: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 115/183

and output streams and read and write data. In this tutorial we do not deal with thecase where the NXT is an initiator and the PC is a receiver, although this is possiblefor Bluetooth connections. In most cases of PC to NXT or mobile phone to NXTcommunications, it is more convenient for the NXT to be the receiver and the PC theinitiator.

The initiator program may run on a PC (always for USB), another NXT, a mobile phone or another device that supports the Bluetooth Serial Port Profile (SPP). Someexternal devices, such as GPS Bluetooth devices only act as a receiver, so whencommunicating with these devices, the NXT must act as the initiator. Note that suchexternal devices must implement SPP - this is the only profile that the NXT supports.

Receiver

A receiver program on the NXT waits for a connection by calling the

waitForConnection() method in the Bluetooth or USB class. These are:-

  BTConnection waitForConnection();  USBConnection waitForConnection();

Even though the Bluetooth class returns a BTconnection object, and the USB classreturns a USBConnection object, both of classes implement the NXTConnectiioninterface. So an object of either class can be assigned to an reference variable thatimplements that interface.

Bluetooth Example:

NXTConnection connection = Bluetooth.waitForConnection();

You need to ensure that Bluetooth power and visibility are on before calling thismethod. The leJOS NXJ start-up menu can be used to do this.

USB Example:

NXTConnection connection = USB.waitForConnection();

You need to ensure that the USB cable is connected before calling this method.

Here is an example program that selects between USB and Bluetooth at run time:

Page 116: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 116/183

 

import lejos.nxt.*;

import lejos.nxt.comm.*;

import java.io.*;

/**

* sample of selecting channel at run time

*/

public class CommTest

{

public static void main( String[] args) {

LCD.drawString("right BT",0, 0);

NXTConnection connection = null;

if(Button.waitForPress() == 4){

LCD.drawString("waiting for BT", 0,1 );

connection = Bluetooth.waitForConnection();

} else {

LCD.drawString("waiting for USB", 0,1 );

connection = USB.waitForConnection();

}

DataOutputStream dataOut = connection.openDataOutputStream();try {dataOut.writeInt(1234);}

catch (IOException e ) {System.out.println(" write error "+e);}

}

}

}

Streams

Once a connection has been established, streams can then be opened by calling any ofthe following methods in the NXTConnection interface:

  InputStream openInputStream() throws IOException;  OutputStream openOutputStream() throws IOException;

Page 117: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 117/183

  DataInputStream openDataInputStream() throws IOException; (the exampleabove did this)

  DataOutputStream openDataOutputStream() throws IOException;

Data items can then be read from the DataInputStream by:

  int read(byte b[]) throws IOException  int read(byte b[], int off, int len)throws IOException   boolean readBoolean() throws IOException   byte readByte() throws IOException  short readShort() throws IOException  readInt() throws IOException  char readChar() throws IOException  float readFloat() throws IOException  String readLine() throws IOException

Be aware: The stream read methods are blocking –  that is, they do not return untildata is read. If your program has other tasks that need attending to while waiting fordata, calls to the read methods should be made in a separate thread.

Data can be written to the DataOutputStream by:

  void write(byte b[], int off, int len) throws IOException  void writeBoolean(boolean v) throws IOException  void writeByte(int v) throws IOException  void writeShort(int v) throws IOException  void writeChar(int v) throws IOException  void writeInt(int v) throws IOException  void writeFloat(float v) throws IOException;  void writeChars (String value) throws IOException

Example of reading and writing integers using data streams (dis and dos are aDataInputStream and DataOutputStream that has been opened):

for(int i=0;i <100;i++) {int n = dis.readInt();

LCD.drawInt(n,7,0,1);

dos.writeInt(-n);

dos.flush();

}

Page 118: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 118/183

Be aware: you must flush the output stream to be sure the data is actually transmitted.Furthermore, it is possible for transmission to fail without throwing an exception.

The DataInputStream, DataOutputstream and NXTConnection can then be closedusing the close() method.

The full example using BlueTooth is:

public class BTReceive {

public static void main(String [] args) throws Exception {

String connected = "Connected";

String waiting = "Waiting...";

String closing = "Closing...";

while (true) {LCD.drawString(waiting,0,0);

NXTConnection connection = Bluetooth.waitForConnection();

LCD.clear();

LCD.drawString(connected,0,0);

DataInputStream dis = connection.openDataInputStream();

DataOutputStream dos = connection.openDataOutputStream();

for(int i=0;i<100;i++) {

int n = dis.readInt();LCD.drawInt(n,7,0,1);

dos.writeInt(-n);

dos.flush();

}

dis.close();

dos.close();

LCD.clear();

LCD.drawString(closing,0,0);

btc.close();

LCD.clear();

}

}

}

Page 119: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 119/183

To modify this example to work with USB, you only have to changeBluetooth.waitForConnection() to USB.waitForconnection()

NXT Initiator

To initiate a Bluetooth connection from one NXT to another NXT, you first need toadd the receiver NXT to the initiator NXT’s Bluetooth devices. 

To do this, you go to the Bluetooth menu in the leJOS NXJ start-up menu and select“Search”. Providing the Bluetooth power is on and visibility is on for the receiving

 NXT, it will be found and you can select “Add” to add it to the initiator’s Bluetooth

devices.

To check it is in the Devices list, you can select “Devices” from the Bluetooth menuof the initiator NXT.

You can then create a BTRemoteDevice class on the initiator NXT:

Example:

BTRemoteDevice btrd = Bluetooth.getKnownDevice(name);

You can connect to the remote device by its address, which you can get by:

   public byte[] getDeviceAddr()

You can then connect to the remote device by calling one of the connect() methods inthe Bluetooth class:

  BTConnection connect(BTRemoteDevice remoteDevice)

  BTConnection connect(byte[] device_addr)  BTConnection connect(byte[] device_addr, byte[] pin)

Example:

BTRemoteDevice btrd = Bluetooth.getKnownDevice(name);

if (btrd == null) {

Page 120: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 120/183

  LCD.clear();

LCD.drawString("No such device", 0, 0);

Button.waitForPress();

System.exit(1);

}

BTConnection btc = Bluetooth.connect(btrd);

if (btc == null) {

LCD.clear();

LCD.drawString("Connect fail", 0, 0);

Button.waitForPress();

System.exit(1);

}

Having got a BTconnection object you can open the data input and output streams andread data as in the receiver example above.

The complete BTConnectTest example, which works as the initiator program for theBTReceive receiver program, is:

public class BTConnectTest {

public static void main(String[] args) throws Exception {

String name = "NXT";

LCD.drawString("Connecting...", 0, 0);

BTRemoteDevice btrd = Bluetooth.getKnownDevice(name);

if (btrd == null) {

LCD.clear();

LCD.drawString("No such device", 0, 0);

Button.waitForPress();

System.exit(1);

}

BTConnection btc = Bluetooth.connect(btrd);

if (btc == null) {

LCD.clear();

LCD.drawString("Connect fail", 0, 0);

Button.waitForPress();

System.exit(1);

Page 121: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 121/183

  }

LCD.clear();

LCD.drawString("Connected", 0, 0);

DataInputStream dis = btc.openDataInputStream();DataOutputStream dos = btc.openDataOutputStream();

for(int i=0;i<100;i++) {

try {

LCD.drawInt(i*30000, 8, 0, 2);

dos.writeInt(i*30000);

dos.flush();

} catch (IOException ioe) {

LCD.drawString("Write Exception", 0, 0);

}

try {

LCD.drawInt(dis.readInt(),8, 0,3);

} catch (IOException ioe) {

LCD.drawString("Read Exception ", 0, 0);

}

}

try {

LCD.drawString("Closing... ", 0, 0);dis.close();

dos.close();

btc.close();

} catch (IOException ioe) {

LCD.drawString("Close Exception", 0, 0);

}

LCD.drawString("Finished",3, 4);

Button.waitForPress();

}

}

PC Initiator

Page 122: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 122/183

A PC program can initiate a connection to a NXT and open a Java data stream.

The API on the PC is different to the NXT API. See pcapidocs. and how to compileand run PC API Programs 

To connect to the NXT, you need a NXTComm object that can be obtained using the NXTCommFactory class:

  static NXTComm createNXTComm(int protocol)

Bluetooth Initiator  

A NXTComm object to connect via Bluetooth can be obtained by:

NXTComm nxtComm = NXTCommFactory.createNXTComm(NXTCommFactory.BLUETOOTH);

The reason for using a factory method is that there are several implementations ofcomms drivers for Bluetooth and USB on the PC and the one that is used depends onwhat operating system you are using and the contents of he nxj.properties file.

You can connect to the NXT by address or by do a Bluetooth inquiry:

To connect by address, you create a NXTInfo object using the constructor:

   public NXTInfo(String name, String address)

Example:

NXTInfo nxtInfo = new NXTInfo("NXT", "00:16:53:00:78:48");

To find the available NXTs doing a Bluetooth inquiry, you do:

NXTInfo[] nxtInfo = nxtComm.search("NXT",NXTCommFactory.BLUETOOTH)

Page 123: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 123/183

USB Initiator  

The initiator sequence using USB is almost the same as for Bluetooth; You just haveto use USB instead of Bluetooth.in your code. While USB cannot use a device address

, but you can use the NXT name.

NXTComm nxtComm = NXTCommFactory.createNXTComm(NXTCommFactory.USB);

To find the available NXT , you do:

nxtComm.search("MYNXT", NXTCommFactory.BLUETOOTH);

If there is only one NXT connected, you can use a null name parameter in the search()method.

Using the NXTInfo object 

Once you have a NXTInfo object,you can call the open() method of the NXTComm

object to connect to the NXT:

   public boolean open(NXTInfo nxt) throws NXTCommException;

Once the NXT is open, you can obtain an InputStream and an OutputSttream, bycalling the getInputStream() anf getOutputStream() methods of the NXTCommobject:

   public OutputStream getOutputStream();   public InputStream getInputStream();

From these you can construct a DataInputStream and a DataOutputStream and senddata to the receiving NXT.

The complete BTSend sample is in the samples folder.

Page 124: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 124/183

Advanced Communications

In this section you will learn how to:

  Control one NXT with another NXT over Bluetooth

  Control an external Bluetooth device like a GPS receiver  Communicate between a NXT and an RCX

Controlling a remote NXT 

The RemoteNXT class allows one NXT running leJOS NXJ to control another,remote NXT, running NXJ or the standard LEGO firmware. It uses the LEGOCommunications Protocol (LCP) over Bluetooth to control the remote NXT.

Currently, the class is limited and I2C and RCX sensors are not supported, and themotors must be used in a simple way as the regulation thread is not used.

To access a remote NXT, you use the constructor:

   public RemoteNXT(String name) throws IOException

Example:

try {

LCD.drawString("Connecting...",0,0);

nxt = new RemoteNXT("NXT");

LCD.clear();

LCD.drawString("Connected",0,0);

} catch (IOException ioe) {

LCD.clear();

LCD.drawString("Conn Failed",0,0);

Button.waitForPress();

System.exit(1);

}

The name of the remote NXT must have already been added to the known devices ofthe initiating NXT by do a Bluetooth search followed by “Add” fron the leJOS NXJ

Bluetooth menu.

Page 125: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 125/183

The constructor opens the connection and creates instances of the remote motor andsensor ports.

It is then possible to get access to information about the remote NXT by using themethods:

   public String getBrickName()   public String getBluetoothAddress()   public int getFlashMemory()   public String getFirmwareVersion()   public String getProtocolVersion()

Example:

LCD.drawString(nxt.getBrickName(), 0, 6);LCD.drawString(nxt.getFirmwareVersion(), 0, 7);

LCD.drawString(nxt.getProtocolVersion(), 4, 7);

LCD.drawInt(nxt.getFlashMemory(), 6, 8, 7);

There are also methods that act on the remote NXT:

   public byte deleteFlashMemory()

A remote Battery object is created that can be used to get the voltage of the remote battery using the normal Battery methods.

Example:

LCD.drawString( "Battery: " + nxt.Battery.getVoltageMilliVolt() 0,4);

Objects are also created for the sensor ports of the remote NXT. These are accessed asS1, S2, S3 and S4.

Local sensor objects can then be created using these ports and use exactly as if theywere connected to a local sensor port.

Example:

LightSensor light = new LightSensor(nxt.S1);

Page 126: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 126/183

LCD.drawString("Light: " + light.readValue(),0,5);

Motor objects are created for the remote motors. They are named A, B and C.

These can be used in the normal way, e.g:

nxt.A.setSpeed(360);

nxt.A.forward();

nxt.A.stop();

nxt.A.backward();

External Bluetooth devices 

The NXT can connect to external Bluetooth devices that implement the Serial PortProfile (SPP).

Such devices can be searched for on the Bluetooth menu and added to the knowndevices.

An example of such a device is an external Bluetooth GPS receiver. These can be

used to obtain to obtain the geographic location of a robot

leJOS supports external Bluetooth GPS receivers that support the NMEA protocol viathe GPS and NMEASentence classes. NMEASentence is a utility class used by GPS,and is not directly accessed.

One such device that has been tested with leJOS NXJ is the Holux M-1200.

Most such devices have a PIN that is required to connect to them, but it may have adefault value such as “0000”. 

To connect to a GPS device, you do:

final byte[] pin = {(byte) '0', (byte) '0', (byte) '0', (byte) '0'};

BTRemoteDevice btGPS = Bluetooth.getKnownDevice(name);

if (btrd == null) {

Page 127: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 127/183

  LCD.drawString("No such device", 0, 0);

Button.waitForPress();

System.exit(1);

}

btGPS = Bluetooth.connect(btrd.getDeviceAddr(), pin);

if(btGPS == null)

LCD.drawString("No Connection", 0, 1);

Button.waitForPress();

System.exit(1)

}

LCD.drawString("Connected!", 0, 1);

GPS gps = null;InputStream in;

try {

in = btGPS.openInputStream();

gps = new GPS(in);

LCD.drawString("GPS Online", 0, 6);

} catch(Exception e) {

LCD.drawString("GPS Connect Fail", 0, 6);

Button.waitForPress();

System.exit(1);}

As you see from this example, the GPS constructor takes the input stream from theBluetooth connection as a parameter:

   public GPS(InputStream in)

The GPS class starts thread and uses the NMEASentence class to process messages(known as sentences) from the Bluetooth device. Messages such as the $GPGGAsentence that gives the current latitude, longitude and altitude, are processed.

To read the current values of latitude, longitude and altitude, you use the methods:

   public float getLatitude()   public float getLongitude()   public float getAltitude()

Page 128: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 128/183

You can also get the time stamp corresponding to these values by:

   public int getTime()

Communicating with the RCX 

IR communication with the RCX can be done using the Mindsensors NRLink RCX IRadapter. The software abstraction of this device is the RCXLink class. The constructoris:

   public RCXLink(I2CPort port)

For example:

RCXLink link = new RCXLink(SensorPort.S1);

The NRLink-Nx supports a set of macros in ROM and EEPROM that can be used tosend messages to the RCX using the LEGO RCX IR protocol. The EEPROM macoscan be overwritten allowing the user to define their own macros.

Macros can be run by:

   public void runMacro(int addr)

There are convenience methods for running the ROM macros:

   public void beep()   public void runProgram(int programNumber)   public void forwardStep(int id)   public void backwardStep(int id)   public void setRCXRangeShort()   public void setRCXRangeLong()   public void powerOff()   public void stopAllPrograms()

A new macro in the EEPROM address range can be defined by:

Page 129: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 129/183

   public void defineMacro(int addr, byte[] macro)

There is a convenience method to define and run a macro:

PC GUI Tools

The NXJ Browser

leJOS NXJ includes a PC-based file browser for viewing and manipulating the fileson the NXT.

It is started by the nxjbrowse script. If you are using an IDE, you can set NXJ Browse

up as an external tool.

The NXJ Browser need the NXT it is connecting to, to be turned on and to be runningthe leJOS start-up menu. Although it should work while a user program is running, ifthe program starts the LCPBTResponder thread, this is not recommended.

The NXJ Browser first looks for a NXT connected by USB, and if it finds one shows just that in the selection window.

If it cannot find a USB-connected NXT, it does a Bluetooth inquiry to find any NXTs

in range and shows them in the selection window. You then select the one you wish toconnect to, and press connect.

Page 130: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 130/183

 

After pressing Connect, the main browser screen is shown: 

Page 131: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 131/183

 

The NXJ browser shows you all the files on your NXT, together with their size in bytes and their location in the file system (start page, end page). See “Understanding

the leJOS NXJ File System” to understand the meaning of the start and end pages. 

The friendly name of the NXT you are connected to is shown in the title bar of the

Windows –  the name is “NXT” in this case. 

From this screen, you can:

  Delete programs  Upload programs and other files to the NXT  Download files from the NXT to the OC

Page 132: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 132/183

  Run programs  De-fragment the file system  Set the friendly name of the NXT

Deleting programs 

To delete files from the NXT, click the Delete  tick boxes and press Delete F il es . Thenext will make a chirping sound for each file deleted, and the NXJ Browser displaywill be updated. If the NXT is on the Files menu, its LCD will also be updated. Anautomatic defrag will occur when files are deleted, so there should be no gaps in thefile system.

Uploading files 

When you click Upload F il e, an Open file dialog box appears. Browse for the file youwant to upload, select it, and click Open. NXJ Browse is not normally used foruploading program files as this is better done using the nx j  or nxjupload  tool or theleJOS Eclipse plugin. However, it is useful for uploading WAV files and data files for programs.

Downloading files 

Files can be downloaded from the NXT to the PC by selecting the NXT file and pressing “Download”. This open a dialog that allows you to select the folder and

filename to download the file to.

Running programs 

A program on the NXT can be run by selecting it and pressing “Run”. This shuts

down NXJ Browser.

De-fragmenting the file system 

The NXT file system cab be defragmented (removing any gaps between files) by pressing “Defrag”. In the latest versions of leJOS the file system does not normally

need to be defragmented.

Page 133: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 133/183

Setting the friendly name of the NXT 

The Bluetooth friendly name of the NXT can be set by pressing “Set Name”, filling in

the name (up to 16 characters) and pressing OK. Note that the Bluetooth power be on

in order to set the friendly name, even if the connection to the NXT is by USB.

Remote Monitoring and Tracing

You can monitor a leJOS program over a Bluetooth connection while it is running bystarting the LCPBTResponder thread and running the NXJ Monitor tool on the PC.

You an example of this, see the MonitorTest sample.

 NXJ Monitor lets you see the values of sensors, and the values of motor tachometers,in near real-time, while your program executes.

It also lets you program displaying tracing messages to indicate what it is doing.These are displayed on the NXJ Monitor screen.

The program being monitored should include the following code in its start-upsequence:

LCPBTResponder lcpThread = new LCPBTResponder();

lcpThread.setDaemon(true);

lcpThread.start();

On the PC, the NXJ Monitor tool should be run. NXJ Monitor lists the NXTsavailable over Bluetooth in the same way as the NXJ Browser tool, and lets youchoose which one you wish to connect to.

When a connection has been made, the following window is displayed:

Data Viewer

Page 134: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 134/183

The Data Viewer displays the output from DataLogger. You can cut and paste the datainto a spreadsheet for further analysis. It uses USB by default, but you can selectBluetooth if you wish. When you start the program, this window appears:

It connects to the NXT via USB by default, but if you click the Use BlueTooth button,it will.. For the fastest BlueTooth connection, enter the Bluetooth address. If you don’t

know it, enter the NXT name. Otherwise, the program will take some time to searchand complete the connection. By default, the program displays 2 data values per row, but you can enter any number you wish before starting to download. The DataLoggergives you the option to resending its data if you want to see it again (with a different

row length for example). If you do, click the Start Download  button again.. 

The Console viewer

The Console Viewer displays the output from RConsole, which is described in thesection of Error Handling and Debugging. When you start the program, this windowappears:

Page 135: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 135/183

 

It connects to the NXT via USB by default, but if you click the Use BlueTooth button,it will. For the fastest BlueTooth connection, enter the Bluetooth address. If you don’t

know it, enter the NXT name. Otherwise, the program will take some time to searchand complete the connection. 

The Connect  button will initiate the connection with the NXT provided that theRConsole program is running on the NXT.

NXJFlashG

This is the GUI version of NXJFlash. It installs the firmware into the flash memory ofyour NXT. If your NXT has a recent version of the firmware already installed, it onlyneeds to be turned on and connected to the PC with the USB cable. Otherwise, itneeds to be put into firmware update mode by pressing the reset button for 4 secondsor more.

When the program opens, it looks like this:

Page 136: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 136/183

 

When you click start you see this : 

Page 137: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 137/183

 

The next message is : 

If you click Yes, the entire flash memory of the NXT will be cleared. If you click noand the installation fails, it might be because the the flash memory has been badlycorrupted. In which case, try again and click Yes. 

As the installation proceeds, the progress log will be written. At the end, you have achance to install firmware again.

leJOS Utilities

ButtonCounter

This class allows simple data entry by pressing the NXT buttons. It counts the numberof presses of theLeft and Right buttons, Pressing Left (or Right) simultaneouslywith Enter decrements the count.

To start counting, call one of these methods:

  void count(String message)  void count(String message, int left, int right)

These methods exit when the user presses ESC. Then the values can be retrieved by

Page 138: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 138/183

  int getLeftCount()  int getRightCount()

The complete API for Button Counter is here 

DataLogger

This class stores float values in an array and transmits them tothe DataViewer  application running on a PC. It will use BlueTooth or USB as selected by the user at run time.

Methods:

  void writeLog(float value)

Writes a value to the array  void writeLog(float v0, float v1)

Writes two values to the array  void transmit()

Transmits the data to the PC. When this method is called, a message isdisplayed on the NXT screen allowing the user to select USB or BlueTooth asthe transmission channel

The complete API of Data:logger is here. 

Stopwatch

This class represents an elapsed time stopwatch. You can construct as many instancesas you need.

There are only two methods

  void reset()

resets the watch to zero

  int elapsed()

returns the elapsed time (since the last reset() in milliseconds.

The API of Stopwatch is here. 

Page 139: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 139/183

Timer

This class is used with a Timer Listener, to which it sends timedOut() message periodically. It uses a private thread.

Methods:

  void start()

call this first.

  void setDelay(int delay)

set the interval between calls to the listener.

  void stop()

The Timer API is here. 

Timer Listener  

To use the Timer, you need a class that implements this interface. This interface hasonly one method.

  void timedOut()

which is called every time the Timer fires.

Java Utilities

leJOS NXJ supports several of the Java data structures. They are:

  ArrayList 

  BitSet   Hashtable   Queue   Stack    Vector    Enumeration   Iterator  

Page 140: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 140/183

It also supports two other Java utilities:

  Random   Properties   StringTokenizer    Timer    TimerTask  

Advanced Motors, Sensors and Third Party Hardware

Motor interfaces

leJOS supports a variety of motors, including the NXT motors, RCX motors, PFmotors, and a variety of servos. It supports them directly attached to a NXT motor port, or connected by a multiplexer, or via RCX or PF converter cables, or connectedto a remote NXT via Bluetooth or RS485, or connected to a remote RCX via aninfrared link.

To help classify the types of motor, there are a set of motor interfaces in thelejos.robotics packages. These interfaces allow you to write programs that areessentially independent of the specific type of motor used and the way it is connected.It is only the constructor for the a specific motor and its connection that needs to

change to use another type of motor or connection.

BaseMotor  

The simplest interface that all motors implement is BaseMotor. It supports themethods:

   public void forward()   public void backward()   public boolean isMoving()   public void flt()   public void stop()

All leJOS NXJ motors implement this interface. However, servo motors are notcurrently supported as they do not normally support these methods.

Page 141: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 141/183

DCMotor  

The DCMotor interface extends BaseMotor and adds methods for setting the powerand getting the current power setting. It is used for unregulated motors.

   public void setPower(int power)   public int getPower()

Unregulated motors without encoders, such as the RCX motor, support this interface.

Encoder  

Some motors, such as the NXT motors, have built in encoders. The Encoder interfacesdefines the methods that these support.

   public int getTachoCount();   public void resetTachoCount();

EncoderMotor  

The EncoderMotor interface extends DCMotor and Encoder and adds no newmethods. It is used for unregulated motors with encoders. The NXTMotor classimplements this interface.

TachoMeter  

Tachometers are more sophisticated encoders that not only give a tachometer count, but also continuously monitor the tachometer readings to give a rotation speed. Theyare implemented in software for NXT motors. The tachometer interface extendsEncoder and adds:

   public int getRotationSpeed();

RegulatedMotor  

The RegulatedMotor interface is used for motors that implement speed regulation andstopping at a defined encoder count, such as the NXTRegulatedMotor class thatimplements the interface for NXT motors.

Page 142: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 142/183

The RegulatedMotor interface extends BaseMotor and Tachometer and adds thefollowing methods:

   public void addListener(RegulatedMotorListener listener);   public int getLimitAngle(;)   public float getMaxSpeed();   public int getSpeed();   public boolean isStalled();   public void rotate(int angle);   public void rotate(int angle, boolean immediateReturn);   public void rotateTo(int limitAngle);   public void rotateTo(int limitAngle, boolean immediateReturn);   public void setAcceleration(int acceleration);   public void setSpeed(int speed);   public void stop(boolean immediateReturn);   public void waitComplete();

 NXTRegulatedMotor (which is the class of Motor.A, Motor.B, and Motor.C) supportthis interface. RemoteMotor also supports it but with some restrictions.

RegulatedMotorListener  

Regulated motors must generate events when the motor starts and stops. Classes thatlisten for these events implement the RegulatedMotorListener interface, which has the

methods:

   public void rotationStarted(RegulatedMotor motor, int tachoCount, booleanstalled, long timeStamp);

   public void rotationStopped(RegulatedMotor motor, int tachoCount, booleanstalled, long timeStamp);

DifferentialPilot is an example of a class that supports this interface.

Unregulated Motor classes

BasicMotor

As well as the interface defined above, leJOS has an abstract motor class that simplifythe implementation of the unregulated motor classes.

Page 143: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 143/183

BasicMotor is an abstract class which implements the DCMotor interface, and providemethods common to all implementations of unregulated motors.

NXTMotor  

 NXTMotor is a very simple implementation of an unregulated motor for NXT motors.It extends BasicMotor and implements the Encoder interface method, and thereforeimplements the EncoderMotor interface.

It is used for applications such as Segway robots that need to directly control the power supplied to the NXT motors, and do not need speed regulation or rotation to alimit point.

To use an NXTMotor you create an instance of the NXTMotor class using one of the

constructors:

   public NXTMotor(TachoMotorPort port);   public NXTMotor(TachoMotorPort port, int PWMMode);

Example:

NXTMotor m1 = new NXTMotor(MotorPort.A);

RCXMotor

The RCX motors do not have an in-built tachometer and so cannot support theadvanced functions of the NXT motors such as the rotate and rotateTo methods andthe speed regulation.

A simpler class is used to support the RCX motors. It has similar methods to theMotor class in the RCX version of leJOS (which are the same as those supported bythe BasicMotor class).

To use an RCX motor you create an instance of the RCXMotor class using theconstructor:

   public RCXMotor(BasicMotorPort port)

Example:

Page 144: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 144/183

 

RCXMotor rcxMotor = new RCXMotor(MotorPort.A);

You can use RCX Motors with leJOS NXJ by connecting them with the conversion

cables that can be purchased from LEGO (and are bundled with the LEGOMINDSTORMS NXT educational kits). You can also use the RCXMotor class tocontrol RCX motors connected to a remote RCX - see the "Communications" tutorial.

RCXMotor extends BasicMotor and therefore implements the DCMotor interface.

RCX motors can be connected to a sensor port via the RCXMotorMultiplxer device.This allows up to 4 RCX motors to be connected and thus entends the number ofmotors that a NXT can support.

RCX Motors can be attached to RCX bricks and controlled remotely via theMindsensors NRLink device using the RCXRemoteMotorPort class.

Regulated motor classes

The NXTRegulatedMotor class controls the NXT motors, and is describedin Controlling the Motors. It implements speed regulation and rotation by a specifiednumber of degrees. Motor.A, Motor.B and Motor.C are instances of NXTRegulatedMotor.

RemoteMotor also implements the RegulatedMotor class but with restrictions. Itsends LCP commands to a remote NXT, which uses an instance of NXTRegulatedMotor to implement them. RemoteMotor is available on the NXT andon the PC (via the pccomms API). On the PC, Motor.A, Motor.B and Motor.C areinstances of RemoteMotor.

On the NXT, RemoteMotor can be used to control motors on another NXT either overBluetooth, or using RS485, by connecting port 4 of the two NXTs via a NXT cable.RS485 has lower latency than Bluetooth, so the motors will be more responsive overRS485.

MotorPort classes

Page 145: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 145/183

To use the NXT motors it is not necessary to explicitly use the MotorPort class: youcan just use the variables Motor.A, Motor.B and Motor.C. So if you are only using NXT motors, you can skip this section.

However it is useful to understand how motor ports work as they are used by:

  The NXTRegulatedMotor class  The RCXMotor class  The RemoteNXT class  The RCXMotorMultiplexer class  Remote RCX motors accessed via the RCXLink class

There is a hierarchy of interfaces defined for motor ports:

  BasicMotorPort  Tachometer  TachoMotorPort

All motor ports support the BasicMotorPort interface which allows control of amotors power and mode (forward, backward, stop, float).

Ports that supports this include:

   NXT ports connected to NXT motors   NXT ports connected via the RCX conversion cable to RCX motors

  Ports on the RCXMotorMultiplexer adapter  Ports on remote NXTs accessed via the RemoteNXT class  Ports on remote RCXs accessed via the RCXLink class

The implementations of BasicMotorPort include:

  MotorPort  PFMotorPort  RemoteMotorPort  RCXPlexedMotorPort

  RCXRemoteMotorPort

The tachometers that are built in to the NXT motors support the Tachometer interface.

 NXT motor ports support the TachoMotorPort interface which includes theBasicMotorPort and Tachometer interfaces.

Page 146: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 146/183

Implementations of TachoMotorPort include:

  MotorPort  RemoteMotorPort

All this sounds rather complicated, but is simple to use:

  For NXT motors, you use Motor.A, Motor.B and Motor.C  For RCX motors connected by the conversion cable you use

RCXMotor(MotorPort.A), RCXMotor(MotorPort.B) orRCXMotor(MotorPort.C)

  For NXT motors on a remote NXT, you use remoteNXT.Motor.A,remoteNXT.Motor.B or remoteNXT.Motor.C where remoteNXT is an instanceof RemoteNXT.

  For RCX motors connected by the RCX Motor Multiplexer, you use

rcxMotorMultiplexer.A, rcxMotorMultiplexer.B, rcxMotorMultiPlexer.C orrcxMotorMultiplexer.D, where rcxMotorMultiplexer is an instance ofRCXMotorMultiPlexer.

  For RCX motors connected t remote RCXs via the RCXLink class you usercxLink.A, rcxLink.B or rcxLink.C where rcxLink is an instance of theRCXLink class.

LEGO Power Function motors

LEGO PF motors can be controlled by leJOS NXJ in a variety of ways. They can bedirectly connected to the NXT via converter cables, or they can be controlled remotelyusing their IR receivers use several different third party devices.

If you use converter cables, then PF motors are best driven using the RCXMotor class.

To drive PF Motors remotely, via the IR Receiver, three different devices can be used.

The Mindsensors PFMate device is designed to drive PF motors directly. This device

is supported by the PFMate and PFMateMotor classes. PFMate implements theDCMotor interface, and therefore provides similar methods to RCXMotor.

Using the HiTechnic IRLink device, one way to drive PF motors is to use thePFMotorPort class. This provides a BasicMotorPort interface and so can be used asthe BasicMotorPort parameter for the RCXMotor constructor. This allows RCXMotorto drive remotely connected PF motors. Another option is to use the methods of the

Page 147: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 147/183

PFLink class directly. This gives greater control but the methods are specific to thisdevice.

A third device that can be used to drive PF motors is the Mindsensors NRLink. ThePFLink class can be used to drive this device and send commands to the PF motors.

The methods are specific to this device and none of the motor or motor port interfacesare supported.

Servos and Linear Actuators

leJOS NXJ has several classes in lejos.nxt.addon to support Servo motors.

The Mindsensors MSC8 device is supported by the MSC and MServo classes. MSC

represents the controller, which allows up to 8 servo motors to be connected. MServorepresents each servo. the main methods are setSpeed and setAngle. None of themotor interfaces are supported.

The Lattebox range of products is supported by the NXTe, LSC and LServo classes.

Firgelli L12-NXT-50 and L12-NXT-100 Linear Actuators are supported by theLnrActuator class.

Motor multiplexers

The motor multiplexors supported by leJOS NXJ are:

  Mindsensors RCX multiplexer  Mindsensors NXT multiplexer

The RCX multiplexor is supported by the RCXMotorMultiplexor andRCXPlexdMotorPort classes.

Sensor Ports

If you are using a sensor connected directly to a NXT sensor port, you can use theSensorPort class and you can probably skip this section.

Page 148: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 148/183

But if you are using a port splitter, or a remote NXT or RCX, it may be of interest.

The NXT sensor ports support three different types of sensor:

   NXT Analog/Digital Sensors  I2C Sensors  Legacy RCX sensors

Corresponding to each of the different types of sensor, there is a correspondinginterface:

  ADSensorPort which extends BasicSensorPort  I2CPort extends BasicSensorPort  LegacySensorPort extends ADSensorPort

At the top of the interface hierarchy is the BasicSensorPort. All sensor port classesimplement this interface. This interface allows the type and mode of a sensor to be set.These type and mode constants are defined by the interface SensorConstants, which isinherited by the BasicSensorPort interface.

The types of sensors are:

TYPE_NO_SENSOR = 0

TYPE_SWITCH = 1

TYPE_TEMPERATURE = 2TYPE_REFLECTION = 3

TYPE_ANGLE = 4

TYPE_LIGHT_ACTIVE = 5

TYPE_LIGHT_INACTIVE = 6

TYPE_SOUND_DB = 7

TYPE_SOUND_DBA = 8

TYPE_CUSTOM = 9

TYPE_LOWSPEED = 10

TYPE_LOWSPEED_9V = 11

TYPE_HISPEED = 12

TYPE_COLORFULL = 13

TYPE_COLORRED = 14

TYPE_COLORGREEN = 15

TYPE_COLORBLUE = 16

TYPE_COLORNONE = 17

Page 149: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 149/183

and the modes are:

MODE_RAW = 0x00

MODE_BOOLEAN = 0x20

MODE_TRANSITIONCNT = 0x40MODE_PERIODCOUNTER = 0x60

MODE_PCTFULLSCALE = 0x80

MODE_CELSIUS = 0xA0

MODE_FARENHEIT = 0xC0

MODE_ANGLESTEP = 0xE0

The BasicSensorPort interface defines the methods:

   public int getmode();    public int gettype();    public void  setmode(int mode);    public void  settype(int type);    public void  settypeandmode(int type, int mode); 

Most of the time, with leJOS NXJ, these types and modes do not need to be setexplicitly as it is done by the constructor for the sensor class being used, e.g.TouchSensor, LightSensor and UltrasonicSensor.

The implementation of the NXT sensor port –  SensorPort –  supports all theseinterfaces. The reason for separating out the different interfaces is that there are otherimplementations of sensor ports that only support a subset of these interfaces, anddifferent types of sensors only require particular interfaces to be implemented:

  I2C Sensors just require I2CPort   NXT Analog/Digital sensors just require ADSensorPort  RCX sensors such as the RCX Light sensor require LegacySensorPort

Port splitters like the Mindsensors Split-Nx only support I2C sensors and thus,effectively, only support the I2CPort interface.

There are other implementations that only support the other interfaces. For examplethe current implementation of remote sensor ports –  RemoteSensorPort –  currentlyonly supports the ADSensorPort interface.

The classes for RCX Sensors multiplexers –  such as the forthcoming Mindsensorsversion –  will only support the LegacySensorPort interface.

Page 150: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 150/183

 

Sensors

Each sensor supported by leJOS NXJ has a specific class that is used to access the

sensor. Each of these sensor classes has, as a parameter, a sensor port that supports therequired interface. Any sensor port class that implements the interface can bespecified as the parameter. As the SensorPort class supports all the interfaces, if thesensor being accessed is directly connected to the NXT, the parameter should be oneof SensorPort.S1, SensorPort.S2, SensorPort.S3 or SensorPort.S4.

If a port splitter is used the parameter again should be one of SensorPort.S1,SensorPort.S2, SensorPort.S3 or SensorPort.S4. This specifies the port that the splitteris connected to. If multiple sensors are connected to the splitter they must each havedifferent I2C addresses. Most I2C sensors can have their address changed  –  see the

manufacturers instructions. To specify the address that a sensor uses, if it is not thedefault, then you may need to use an alternate constructor for the sensor class to allowyou to specify the address. If such a constructor does not exist please report this to usand use the setAddress method of I2CSensor.

The sensor ports supported by leJOS NXJ together with the class that supports themand the type of sensor port they require is given in the following table:

Hardware Device  Class SensorPort

interface 

LEGO NXT TouchSensor

TouchSensor ADSensorPort

LEGO NXT LightSensor

LightSensor ADSensorPort

LEGO NXT SoundSensor

SoundSensor ADSensorPort

LEGO NXT ColorSensor

ColorSensor SensorPort

LEGO NXT UltrasonicSensor UltrasonicSensor I2CPort

RCX Light Sensor RCXLightSensor LegacySensorPort

RCX TemperatureSensor

RCXTemperatureSensor ADSensorPort

RCX Rotation Sensor RCXRotationSensor ADSensorPort

Page 151: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 151/183

HiTechnic CompassSensor

CompassSensor I2CPort

HiTechnic Color Sensor ColorSensorHT I2CPort

HiTechnic Acceleration

Sensor AccelHTSensor I2CPort

HiTechnic Gyro Sensor GyroSensor ADSensorPort

HiTechnic IR Seeker IRSeeker ADSensorPort

HiTechnic IRSeeker v2 IRSeekerV2 ADSensorPort

HiTechnic IRLink IRLink I2CPort

HiTechnic EOPDSensor

EOPD ADSensorPort

HiTechnic Sensor

Multiplexer SensorMux I2CPort

HiTechnic Angle Sensor AngleSensor I2CPort

Mindsensors CompassSensor

CompassSensor I2CPort

MindsensorsAcceleration Sensor

AccelMindSensor I2CPort

Mindsensors NXTCam NXTCam I2CPort

Mindsensors LineLeader LineLeader I2CPort

Mindsenors NXTMMX NXTMMX I2CPort

Mindsensors Dist-Nx OpticalDistanceSensor I2CPort

RCX Touch Sensor TouchSensor ADSensorPort

Mindsenors NRLink-Nx PFLink I2CPort

Mindsensors PFMate PFMate I2CPort

Mindsensors PSP-Nx PSPNXController I2CPort

Mindsensors NRLink RCXLink I2CPort

Mindsensors RCXMultiplexer

RCXMotorMultiplexer I2CPort

Mindsensors RTC RealTimeClock I2CPort

Mindsensors TouchMultiplexer

TouchMUX I2CPort

Mindsensors Servo MSC I2CPort

Page 152: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 152/183

Multiplexer

Codatext RFID Sensor RFIDSensor I2CPort

Dexter IndustriesDSwitch

DSwitch I2CPort

Dexter Industries dGPSsensor

GPSSensor I2CPort

Linear Actuator LnrActuator I2CPort

Lattebox LSC LSC I2CPort

Lattebox NXTe NXTe I2CPort

Micro Infinity CruizcoreGyro

CruizcoreGyro I2CPort

RCX Sensors

RCX sensors, other than the touch sensor, are active sensors that have voltage appliedfor all but the short period every three milliseconds when the measurement is taken.

RCX Light Sensor  

The RCX light sensor is supported by the RCXLightSensor class.

The constructor is:

   public RCXLightSensor(LegacySensorPort port)

For example:

RCXLightSensor light = new RCXLightSensor(SensorPort.S1);

The RCX light sensor is automatically activated, so current is applied to it and theLED comes on. It can be passivated and activated explicitly.

The methods are:

   public int readValue()

Page 153: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 153/183

   public void activate()   public void passivate()

RCX Touch Sensor  

As the RCX touch sensor is a passive sensor similar to the NXT version, it issupported by the standard TouchSensor class.

RCX Rotation Sensor  

The RCX rotation sensor is not currently supported by leJOS NXJ.

RCX Temperature Sensor  

The constructor is:

   public RCXTemperatureSensor(LegacySensorPort port)  The methods are:  int readValue() - returns raw value  float getCelcius() - return the temperature in degrees Celcius  float getFarenheit() - return the temperature in degrees Farenheit

Third party sensors and other devices

leJOS NXJ supports many third party sensors. The two main vendors of third partysensors are Mindsensors and HiTechnic.

Most of the third party sensors and I2C sensors and extend the I2CSensor class butthere are also Analog/Digital sensors such as the HiTechnic Gyro sensor and the IRSeeker.

There are also other I2C devices supplied by the third parties, that are not sensors, butare multiplexers or adapters.

The RCX Motor Multiplexer from Mindsensors is an example of a multiplexer. Itallows up to 4 RCX motors to be connected to a NXT sensor port and to beindependently controlled.

Page 154: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 154/183

The Mindstorms NRLink-Nx infra-red communications adapter is an example of anadapter. It allows two-way communication between the NXT and RCXs. It alsoallows control of Power Function motors.

I2CSensor

The I2CSensor class implements the basic methods for accessing I2C sensorsincluding getData and SendData.

It also includes methods that are implemented by all the I2C sensors, includinggetVersion, getProductID and getSensorType.

The method signatures are:

   public int getData(int register, byte [] buf, int len)   public int sendData(int register, byte [] buf, int len)   public int sendData(int register, byte value)   public String getVersion()   public String getProductID()   public String getSensorType()

Individual I2C devices have registers that can be read and written and registers thatcan be used to execute commands. Each I2C device has a class that extends

I2CSensor and has methods to access the registers and execute the commands specificto that sensor.

The I2CSensor class can be used to implement an I2C device explorer that reportswhat devices are connected to which sensor using which address –  see the I2CDevicessample. This is possible as all the NXT I2C sensors and other devices support thegetVersion, getProductID and getSensorType methods.

See the table above for the complete list of sensors and other third party devices.

I2CPort

The I2CPort provides low level access to a port being used for I2C communications.In many cases these operations are not required and the higher level I2CSensor classis used. However some advanced applications (like those scanning ports to identifysensors) may require access at this level.

Page 155: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 155/183

The method signatures are:

   public void i2cEnable(int mode)   public void i2cDisable()   public int i2cStatus()   public int i2cTransaction(int deviceAddress, byte[]writeBuf, int writeOffset, int

writeLen, byte[] readBuf, int readOffset, int readLen)

To use a port with I2C it must be enabled. When I2C operation is no longer required itshould be disabled. The enable method also sets the operating mode of the port. Theavailable operating modes are:

STANDARD_MODE = 0

LEGO_MODE = 1

ALWAYS_ACTIVE = 2NO_RELEASE = 4

HIGH_SPEED = 8

The mode normally used is LEGO_MODE. This offers compatibility with thestandard Lego firmware. The bus will operate at 9.6Kbps and will add delays to becompatible with the Lego Ultrasonic sensor. This mode will normally work with all NXT compatible devices. STANDARD_MODE operates the port in a more I2Cstandard compliant way. You may wish to try using this if you are having problems

with a device. HIGH_SPEED mode operates the bus at a much higher speed(125Kbps), to function at this speed the device will typically need to be using ahardware implementation of I2C (many of the HiTechnics and Mindsensors devicescan be used at this speed). It should be noted that these modes operate at the port levelnot for an individual sensor so if more than one sensor is attached to the same portthey will all share the same operating mode. To set the operating mode of a port a callto enable(mode) should be made prior to creating any instances of sensors to beassociated with the port.

Advanced Topics: Files, LCP, Memory, NXJ Tools

Understanding the leJOS File System

Page 156: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 156/183

The NXT has 256kb of flash memory. A fixed section at the start of the flash memoryis allocated to the system. It is used to hold the firmware, followed by the startupmenu. The rest of this system area is unused. The size of the system area varies between releases.

The firmware is written in C, with some ARM assembly language. The startup menuis written in Java (in the startup project in SVN).

Flash memory is read and written in 256-byte pages. The first page after the systemarea is used for persistent system settings administered by the startup menu.

The rest of the flash memory is used for the user file system. The first two pages holdthe file table (directory), and the rest of the pages hold user files. Files are held as acontiguous set of bytes –  i.e they use a single range of page numbers with no gaps.This allows a file to be addressed as a region of memory.

The Flash class 

The Flash class has methods to read and write 256-byte pages of flash memory. Itshould not be used by user programs.

The System Settings class 

The SystemSettings class is used to administer the system settings page. It should not be used by user programs.

The File class 

The File class has static methods that manipulate the file system as a whole andinstance methods that give access to specify files.

Static methods:

  void defrag() - removes unused pages in the file system.  void format() - erases all the files and reformats the flash memory.  int freeMemory() - returns the total free memory in the file system.  File[] listfiles() - returns an array of files in the system

To read and write files, you need to use streams. The stream constructors throw anIOException so they also must be in a try/catch block.

Page 157: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 157/183

The file streams read and write individual bytes, so you will usually want to use a datastream filter.

FileOutputStream 

The constructors are:

  FileOutputStream(File f) - creates new OutputStream to write to this file,starting at the beginning of the file. The file is deleted if it already exists. Anew file is then created. Methods:

  FileOutputStream(File f, boolean append) - create a new OutputStream to writeto this file

  void write(int b) - write 1 byte to the file  void flush() - Flushes this output stream and forces any buffered output bytes to

 be written  void close() - Write the buffer to flash memory and update the file parameters

in flash. Be sure to call this method before your program exits.

Example:

import java.io.*;

import lejos.nxt.*;

public class FileWriteTest {public static void main(String[] args) {

FileOutputStream out = null; // declare outside the try block

File data = new File("log.dat");

try {

out = new FileOutputStream(data);

} catch(IOException e) {

System.err.println("Failed to create output stream");

Button.waitForPress();

System.exit(1);

}

DataOutputStream dataOut = new DataOutputStream(out);

float x = 1f;

int length = 8;

Page 158: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 158/183

  try { // write

for(int i = 0 ; i<length; i++ ) {

dataOut.writeFloat(x);

x = x*-2.2f;

}

out.close(); // flush the buffer and write the file} catch (IOException e) {

System.err.println("Failed to write to output stream");

}

Sound.beep();

Button.waitForPress();

}

}

After you run this example, look for the newly created file in the Files menu.

You can also use the PrintStream class or the OutputStreamWriter class to write tofiles.

FileInputStream 

The constructor is:

  FileInputStream( File afile)

Methods:

  int read() - returns a value between 0 and 255, representing a single byte  int available() - returns the number of bytes available to be read.

Here is an example that reads the file

import java.io.*;

import lejos.nxt.*;

public class FileReadTest {

public static void main(String[] args) {

File data = new File("log.dat");

int i = 0;

try {

Page 159: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 159/183

  InputStream is = new FileInputStream(data);

DataInputStream din = new DataInputStream(is);

while (is.available() > 3) { // at least 4 bytes left to read

float x = din.readFloat();

System.out.println("" + x);

}

din.close();

} catch (IOException ioe) {

System.err.println("Read Exception");

}

Button.waitForPress();

}

}

Understanding LCP 

LEGO defines a protocol called the LEGO MINDSTORMS NXT CommunicationsProtocol (LCP) which is used to send commands to the standard LEGO firmware. Thespecification is available athttp://mindstorms.lego.com/Overview/NXTreme.aspx  inthe Bluetooth Development Kit. The commands are separated into direct commandsand system commands. The direct commands are described in a separate document:LEGO MINDSTORMS NXT : Direct Commands.

Direct commands are those that are designed for user programs and tools to use tocontrol robots. The system commands are designed for tools that upload anddownload files and do other administrative tasks.

leJOS NXJ emulates many of the direct and systems commands so that many toolsthat work with the standard LEGO firmware also work with leJOS.

Many of the leJOS NXJ tools including nxj, nxjuload, nxjbrowse and nxjmonitor useLCP. leJOS NXJ has some minor additions to LCP to make its tools work better.

The implementation of LCP is in the lejos.nxt.comm.LCP class. As leJOS sensors andmotors work a bit differently than the standard firmware, the semantics of LCP onleJOS are not always identical to the standard LEGO firmware.

Page 160: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 160/183

The start-up menu uses LCP to support the leJOS NXJ tools and third-party tools.This means that LCP commands can be executed over Bluetooth or USB when themenu is running.

Understanding leJOS NXJ use of memory

The NXT has 256kb of flash memory and 64kb of RAM.

Flash memory can be read like RAM (access is a bit slower) but can only be written in256-byte pages by specific hardware instructions,. Flash memory cannot be read whilea page is being written.

The leJOS NXJ firmware is written in a combination of C and ARM assembler code.

It consists of the initialization code, the Java VM and device drivers for all thehardware subsystems. The leJOS firmware is a complete firmware replacement andhas no reliance on the standard LEGO firmware. Most code is executed from flashmemory, but a small amount (e.g. the code that writes pages of flash memory) iscopied to RAM. Read-only data is held in flash memory but read/write data is copiedto RAM. The firmware uses a fixed size stack and interrupt stack.

The leJOS NXJ Java VM executes one Java program at a time. This can either be auser program or the leJOS start-up menu. One Java program can execute another.When this is done the first Java program is removed from memory, and the second

one is then executed. This is how the start-up menu executes user programs.

Java programs execute from flash memory. Static read-only data is held in flashmemory. Static read-write data is copied to RAM. Objects are created in a heap thatstarts at the top of the RAM and grows downwards. The Java stack starts at the bottom of free RAM memory and grows up. A garbage collector frees memory used by unreferenced objects when the heap becomes full.

Understanding the key leJOS NXJ tools

nxjflash

In order to flash firmware to the NXT, it is necessary that the NXT is in firmwareupdate mode. If you have the standard LEGO firmware installed (or if you have a veryrecent version of leJOS), then the nxjflash program will do this automatically for you.

Page 161: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 161/183

If not or if there is some problem with the automatic method then you will need to place the NXT into firmware update mode by pressing the reset button for 4 secondsor more. This causes the NXT to run a small boot assistant program called SAM-BA.The was written by Atmel, the maker of the ARM chipset that the NXT uses. SAM-BA includes a USB driver and accepts commands sent over the USB link. These

command allows data to be uploaded to RAM and code to be executed. Early versionof leJOS used this mechanism to run in RAM before there was a flash version ofleJOS NXJ. The latest version of nxjflash will put the NXT into update mode if it isnot already so.

On Microsoft Windows and MAC OS X, the standard LEGO USB drivers are used.These come with the LEGO software, which is why this software must be installed.On Microsoft windows, when the NXT is in firmware update mode, a USB cable isattached to your PC and the NXT is switched on (by pressing the orange button), ifyou go to Control Panel > System > Hardware > Device Manager you will see under“Lego Devices” an entry for the USB driver, labelled “LEGO MINDSTORMS NXT

Firmware Update Mode”. 

To flash new firmware, nxjflash uploads the firmware image a 256-byte page at a timeand then executes a small RAM-resident routine to write the page to flash memory. Inthis way the leJOS NXJ firmware, lejos_nxt_rom.bin is written to flash memory.

nxjflash also uploads the leJOS NXJ start-up menu StartUpText.bin. This menu iswritten in Java and built like any other leJOS NXJ Java programs. It implements theleJOS NXJ menu system and supports threads for executing Lego CommunicationProtocol (LCP) commands over USB and Bluetooth. When both the firmware and themenu have been uploaded, nxjflash sends a SAM-BA command to the NXT causing itto jump to address zero and the leJOS NXJ firmware executes.

nxjupload 

nxjupload uploads programs or other files over USB or Bluetooth. It is a command

line interface that is suitable for use from command windows, ant scripts, and as anexternal command from IDEs such as Eclipse or Netbeans.

nxjupload sends LCP system commands to the NXT to upload the file. The commandsare OPEN_WRITE, WRITE and CLOSE.

Page 162: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 162/183

By default nxjupload first looks for a NXT connected by USB. If it does not find one,it tries Bluetooth. It does a Bluetooth inquiry looking for NXTs, and saves the resultsis in a cache file which it uses in preference to doing a Bluetooth inquiry when it can .It it finds any it tries to connect to each one, and uploads the file to the first one itsuccessfully connects to. This means that if you have multiple NXTs, it will upload to

the one that is currently switched on.

nxjupload uses the apache Commons CLI command line processor.

nxjlink 

nxjlink calls the linker (class js.tinyvm.TinyVM).

The linker first looks for the specified class in the linker classpath, and then looks forall classes that this references to form a “closure” of the classes. The linker class path

should include classes.jar and all the user classes in the program. The class specifiedon the command line must be the one containing the main method. The Jakarta apacheByte Code Engineering Library (BCEL) is used to process the class files.

The linker omits methods that have not been referenced unless the – a or – all flag isspecified. The way this is done uses a simple algorithm and does not manage to omitall unreferenced methods.

The linker produces a leJOS NXJ binary file and writes it to the file specified in the – 

o parameter.

nxjlink needs to know the byte order of the processor it is producing the binary for.For the NXT this is set by “–writeorder LE” for Little-Endian.

If the verbose option is set, a list of the classes and methods in the binary is output tostandard out. This is very useful for debugging.

nxjlink uses the apache Commons CLI library for command line processing.

Behavior programming

Programming Behavior with leJOS NXJ

Page 163: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 163/183

When most people start programming a robot, they think of the program flow as aseries of if-thens, which is remeniscent of structured programming (Figure 1). Thistype of programming is very easy to get started in and hardly requires any thought ordesign beforehand. A programmer can just sit at the computer and start typing (although a little thought before the typing may avoid a lot of grief later. )

Fig 1 Structured programming visualized.

The problem is, the code ends up as spaghetti code; all tangled up and difficult toexpand.The behavior control model, in contrast, requires a little more planning before coding begins, but the payoff is that each behavior is nicely encapsulated within an easy tounderstand structure. This will theoretically make your code easier to understand byother programmers familiar with the behavior control model, but more importantly it becomes very easy to add or remove specific behaviors from the overall structure,

without negative repercussions to the rest of the code. It also makes it possible to testand debug each behavior by itself.

The concepts of Behavior Programming as implemented in leJOS NXJ are very

simple.: 

  Only one behavior can be active and in control of the robot at any time.  

  Each behavior has a fixed priority.  Each behavior can determine if it should take control.  The active behavior has higher priority than any other behavior that should take

control.

The Behavior API

The Behavior API is is composed of only one interface and one class. The Behavior

interface defines the individual behavior classes. The Behavior interface is very

Page 164: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 164/183

general and defines three public methods. Each task that the robot must perform can

 be defined in its own class. It works quite well because, even though the individual

implementations of a behavior vary widely, they are all treated alike. Once all the

 behaviors are created, they are given to an Arbitrator to regulate which behavior

should be activated at any time. The Arbitrator class and the Behavior interface are

located the lejos.subsumption package. The API for the Behavior interface is as

follows.

lejos.subsumption.Behavior  

   boolean takeControl() 

Returns a boolean value to indicate if this behavior should become active. Forexample, if a touch sensor indicates the robot has bumped into an object, thismethod should return true. This method should return quickly, not perform along calculation.

  void action()

The code in this method begins performing its task when the behavior becomesactive. For example, if takeControl() detects the robot has collided with an

object, the action() code could make the robot back up and turn away from theobject.

A behavior is active as long as its action() method is running, so the action()method should exit when it's task is complete. Also, the action() method shouldexit promptly when suppress() is called. When it exits, it should leave the robotin a safe state for the next behavior.

Page 165: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 165/183

  void suppress()

The code in the suppress() method should immediately terminate the coderunning in the action() method. It also should exit quickly.

As you can see, the three methods in the Behavior interface are quite simple. If a robothas three discreet behaviors, then the programmer will need to create three classes,with each class implementing the Behavior interface. Once these classes are complete,your code should hand the behavior objects off to the Arbitrator to deal with.

lejos.subsumption.Arbitrator  

The constructor is:

   public Arbitrator(Behavior[] behaviors, boolean returnWhenInactive)

Creates an Arbitrator object that regulates when each of the behaviors will become active.Parameter: behaviors. The index of each behavior is its index in the array. So behaviors[0] has the lowest priority.

Parameter: boolean returnWhenInacative; If true, the program exits when thereno behavior that should take control. Otherwise, the program runs until shutdown by pressing the Enter and Escape buttons.

Parameter: an array of Behaviors

Public Methods:

   public void start()

Starts the arbitration system.

The Arbitrator class is even easier to understand than Behavior. When an Arbitratorobject is instantiated, it is given an array of Behavior objects. Once it has these, thestart() method is called and it begins arbitrating; deciding which behavior will becomeactive. The Arbitrator calls the takeControl() method on each Behavior object, startingwith the object with the highest index number in the array. It works its way downthrough the array, (in decreasing priority order) till it finds a behavior that wants totake control. If the priority index of this behavior is greater than that of the currentactive behavior, the active behavior is suppressed. The action method is then called on

Page 166: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 166/183

the behavior of this index. As a result, if several behaviors want to take control, thenonly the only the highest priority behavior will become active. (Figure 2).

Figure 2: Higher level behaviors suppress lower level behaviors.

Coding Behaviors

For reliable performance of the behavior control system, it is essential that action()method terminates promptly when suppress() is called. One way to guarantee this is todefine a boolean flag suppressed in each behavior. This variable is set to true by thesuppress() method and tested in every loop of the action() method. Of course, the firstthing an action() method must do is set this flag to false. The action() method might be quite complex, such as a separate thread for line tracking or wall following, but itmust be coded to ensure prompt exit from action() when necessary. This isthe recommended design pattern . .

 Now that we are familiar with the Behavior API under leJOS, let's look at a simpleexample using three behaviors. For this example, we will program some behavior fora simple robot with differential steering. This robot will drive forward as it's primarylow-level behavior. . This activity continues unless the robotic hits an object,then ahigh priority behavior will become active to back the robot up and turn it 90 degrees.There will also be a third behavior which we will insert into the program after the firsttwo have been completed. Let's start with the first behavior.

As we saw in the Behavior interface, we must implement the methods action(),

suppress(), and takeControl(). The behavior for driving forward will take place in theaction() method. It simply needs to make motors A and C rotate forward and it exitswhen the motors are no longer moving, or suppress is called; This behavior remainsactive as long as the motors are turning. The method code is::

public void action() {

suppress = false; // standard first line of action

Page 167: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 167/183

  Motor.A.forward();

Motor.C.forward();

while( !suppressed)

Thread.yield(); // wait for suppressed to be called}

Motor.A.stop(); // clean up

Motor.C.stop();}

That was easy enough! Now the standard suppress() method will stop this action whenit is called:

public void suppress() {

suppressed = true;

}

So far, so good. Now we need to implement a method to tell Arbitrator when this behavior should become active. As we outlined earlier, this robot will drive forwardalways, unless something else suppresses it, so this behavior should always want totake control (it's a bit of a control freak). The takeControl() method should return true,no matter what is happening. This may seem counter intuitive, but rest assured thathigher level behaviors will be able to cut in on this behavior when the need arises. Themethod appears as follows:

public boolean takeControl() {

return true;

}

That's all it takes to define our first behavior to drive the robot forward. The completecode listing for this class is as follows:

import lejos.subsumption.*;

import lejos.nxt.*;

public class DriveForward implements Behavior {

private boolean suppressed = false;

Page 168: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 168/183

 public boolean takeControl() {

return true;

}

public void suppress() {

suppressed = true;}

public void action() {

suppressed = false;

Motor.A.forward();

Motor.C.forward();

while( !suppressed ) Thread.yield();

Motor.A.stop(); // clean up

Motor.C.stop();

}

The second behavior is a little more complicated than the first, but still very similar.The main action of this behavior is to reverse and turn when the robot strikes an objector detects one close by. In this example, we would like the behavior to take controlonly when the touch sensor strikes an object, or the ultrasonic sensor gets an echofrom a close object. Here is the takeConrol() method that does it:

public boolean takeControl() {

return touch.isPressed() || sonar.getDistance() < 25;

}

This assumes that a TouchSensor object has been created in an instance variablecalled touch and a new UltraSonicSensor object has been assigned to thevariable sonar .

For the action, we want the robot to back up and rotate when it detects an object, sowe will define the action() method as follows:

public void action()

{

suppressed = false;

Page 169: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 169/183

  Motor.A.rotate(-180,true);

Motor.C.rotate(-360,true);

while(Motor.C.isRotatinng() && !suppressed)

Thread.yield(); // wait till turn is complete or suppressed is

called}if(suppressed ){

Motor.A.stop();

Motor.C.stop();

}

}

We use the standard suppress() method here too.

public void suppress {

suppressed = true;

}

The complete listing for this behavior is as follows:

import lejos.subsumption.*;

import lejos.nxt.*;

public class HitWall implements Behavior {

public HitWall(SensorPort port )

{

sonar = new UltrasonicSensor(port );

}

private boolean suppressed = false;

private TouchSensor touch;

private UltrasonicSensor sonar;private boolean suppressed = false;

public boolean takeControl() {

return touch.isPressed() || sonar.getDistance() < 25;

}

public void suppress() {

Page 170: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 170/183

  suppressed = true;

}

public void action() {

// Back up and turn

suppress = false;

Motor.A.rotate(-180,true);

Motor.C.rotate(-360,true);

while( Motor.C.isRotating() & !suppressed )

Thread.yield();

Motor.A.stop();

Motor.C.stop();

}

We now have our two behaviors defined, and it's a simple matter to make a class witha main() method to get things started. All we need to do is create an array of our behavior objects, and instantiate and start the Arbitrator as shown in the following

code listing:

import lejos.subsumption.*;

public class BumperCar {

public static void main(String [] args) {

Behavior b1 = new DriveForward();

Behavior b2 = new HitWall(SensorPort.S2);

Behavior [] bArray = {b1, b2};

Arbitrator arby = new Arbitrator(bArray);

arby.start();

}

}

The above code is fairly easy to understand. The first two lines in the main() methodcreate instances of our behaviors. The third line places them into an array, with the

Page 171: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 171/183

lowest priority behavior taking the lowest array index. The fourth line creates theArbitrator, and the fifth line starts the Arbitration process. When this program isstarted the robot will scurry forwards until it bangs into an object, then it will retreat,rotate, and continue with its forward movement until the power is shut off.

This seems like a lot of extra work for two simple behaviors, but now let's see howeasy it is to insert a third behavior without altering any code in the other classes. Thisis the part that makes behavior control systems very appealing for robotics programming. Our third behavior could be just about anything. We'll have this new behavior monitor the battery level and play a tune when it dips below a certain level.Examine the completed Behavior:

import lejos.subsumption.*;

import lejos.nxt.*;

public class BatteryLow implements Behavior {

private float LOW_LEVEL;

private boolean suppressed = false;

private static final short [] note = {

2349,115, 0,5, 1760,165, 0,35, 1760,28, 0,13, 1976,23,

0,18, 1760,18, 0,23, 1568,15, 0,25, 1480,103, 0,18,

1175,180, 0,20, 1760,18, 0,23, 1976,20, 0,20, 1760,15,

0,25, 1568,15, 0,25, 2217,98, 0,23, 1760,88, 0,33, 1760,

75, 0,5, 1760,20, 0,20, 1760,20, 0,20, 1976,18, 0,23,

1760,18, 0,23, 2217,225, 0,15, 2217,218};

public BatteryLow(float volts) {

LOW_LEVEL = volts;

}

public boolean takeControl() {

float voltLevel = Battery.getVoltage();

System.out.println("Voltage " + voltLevel);

return voltLevel < LOW_LEVEL;}

public void suppress() {

suppressed = true;

}

public void action() {

Page 172: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 172/183

  suppressed = false;

play();

System.exit(0);

}

public static void play() {for(int i=0;i <note.length; ; i+=2) {

final short w = note[i+1];

Sound.playTone(note[i], w);

Sound.pause(w*10);

if (suppressed) return; // exit this method if suppress is called

}

}

}

The complete tune is stored in the note array at line 6 and the method to play the notesis at line 30. This behavior will take control only if the current battery level is less thevoltage specified in the constructor. The takeControl() method looks a little inflated,and that's because it also displays the battery charge to the LCD display. The action()method is comparatively easy. Action makes a bunch of noise, then exits the program.Since this behavior stops the program, we might get away without a a suppress()method. But just in case we detect a wall, while playing the tune, we use one.

To insert this behavior into our scheme is a trivial task. We simply alter the code of

our main class as follows:

import lejos.subsumption.*;

public class BumperCar {

public static void main(String [] args) {

Behavior b1 = new DriveForward();

Behavior b2 = new BatteryLow(6.5f);

Behavior b3 = new HitWall();

Behavior [] bArray = {b1, b2, b3};

Arbitrator arby = new Arbitrator(bArray);

arby.start();

}

}

Page 173: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 173/183

 Note: The voltage level of the NXT at rest is different from the voltage when inaction. The voltage level at rest might be 7.8 V, but when motors are activated theynaturally cause a drop in the voltage reading. Make sure the voltage threshold used inthe BatteryLow constructor is low enough.

This example beautifully demonstrates the real benefit of behavior control coding.Inserting a new behavior, no matter what the rest of the code looks like, is simple. Thereason for this is grounded in object oriented design; each behavior is a self contained,independent object.

TIP: When creating a behavior control system, it is best to program each behavior oneat a time and test them individually. If you code all the behaviors and then uploadthem all at once to the NXT brick, there is a good chance a bug will exist somewherein the behaviors, making it difficult to locate. By programming and testing them oneat a time it makes it easier to identify where the problem was introduced.

Notes on the recommended design pattern

In order to understand why we recommend this design pattern, it is useful to dig alittle deeper into the inner workings of the arbitrator. The Arbitrator contains amonitor thread that cycles through each of the behaviors, checking the takeControl()method to see if the behavior should become active. It starts with behavior of largestindex (because they are are stored in increasing priority order) and works down the

array. As soon as it comes across a behavior that should take control, this is thehighest priority behavior that wants control at the moment. If this behavior has higher priority than the active behavior, the monitor thread executes suppress() on the active behavior, and then starts checking each behavior from the top again. The main threadof the Arbitrator is very simple. It just calls the action() method on the highest priority behavior, (as determined by the Monitor thread) and that behavior becomes the active.When action() exits, either because its task is complete or because the Monitor threadhas called suppress in it, that behavior is no longer active, and the loop continues,calling action() on the behavior that is now has the highest priority as determined bythe Monitor thread. It is possible that the same behavior repeatedly becomes active.

It would be nice if all behaviors were as simple as the examples given above, but inmore complex coding there are some unexpected results that can sometimes beintroduced. If it is necessary to have a behavior that uses its own Thread, for example,can sometimes be difficult to halt it from the suppress() method, which can lead totwo different threads fighting over the same resources - often the same motor! But inthis pattern, the suppress() method does not try to halt anything. It is the responsibility

Page 174: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 174/183

of the action() method to keep testing the suppressed variable, exit as soon as it become true, and leave the robot is a safe state for the next behavior.

Another advantage of this design pattern is that each behavior is coded in the sameway without making any assumptions about its priority. You can then change the

 priority order of your behaviors or reuse them in other applications withoutreprogramming any of them.

 Note: If you would like to remove any mystery about what goes on in the Arbitratorclass, take a look at the source code located insrc/classes/lejos/subsumption/Arbitrator.java.

Summary

Behavior coding is predominantly used for autonomous robots - robots that work

independently, on their own free will. A robot arm controlled by a human wouldlikely not use behavior programming, although it would be possible. For example, arobot arm with four joystick movements could have a behavior for each direction ofmovement. But as you may recall, behaviors are ordered with the highest order taking precedence over lower order behaviors. Who is to say that pushing left on the joystickwould take precedence over pushing up? In other words, behavior control in anythingother than autonomous robots is largely overkill.

So why use the Behavior API? The best reason is because in programming we striveto create the simplest, most powerful solution possible, even if it takes slightly more

time. The importance of reusable, maintainable code has been demonstratedrepeatedly in the workplace, especially on projects involving more than one person. Ifyou leave your code and come back to it several months later, the things that lookedso obvious suddenly don't anymore. With behavior control, you can add and remove behaviors without even looking at the rest of the code, even if there are 10 or more bhaviors in the program. Another big plus of behavior control is programmers canexchange behaviors with each other easily, which fosters code reusability. Hundredsof interesting, generic behaviors could be uploaded to websites, and you could simply pick the behaviors you want to add to your robot (assuming your robot is the correcttype of robot). This reusability of code can be taken forward even more by using

standard leJOS NXJ classes such as the Navigation API.

Using leJOS with Android

Page 175: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 175/183

leJOS can be used in Android applications (.apks) via the leJOS PC API thatcommunicates using Bluetooth with either:

  leJOS NXJ programs running on your NXT. [This requires the leJOS firmwareto be on your NXT]

  the LEGO Communications Protocol (LCP). [This DOES NOT require theleJOS firmware to be on your NXT, and works with the standard LEGOfirmware]

This tutorial is not a complete explanation of how to create Android applicationswhich can quickly become far more complicated than the normal difficulty of usingleJOS. Three leJOS sample programs have been included in one Android .apk, andthis tutorial will explain the most relevant aspects of getting them to work underAndroid. Please note: The robotics package is not supported.

Android specific questions should be directed to theAndroid Developer Mailing List, while leJOS specific ones can go to our forum 

Prerequisites

 Android SDK

To build .apks that run on Android or to upload the sample .apk to your Androiddevice, you need to download the SDK for your OS and install it. 

IDE Plugins 

There is an Eclipse Plugin or a  Netbeans Plugin to simplify developing and building.apks. The LeJOSDroid sample project was set up using the Eclipse Android Pluginand can be imported into Eclipse by selecting File --> Import --> General --> ExistingProjects into Workspace and selecting the android/leJOS-Droid folder

To use leJOS in your own Android project within Eclipse (same principles apply for Netbeans), make sure:

Page 176: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 176/183

  the lejos pccomms.jar (.9 or later) is in your project/libs dir

  the lejos pccomms.jar is in your build path

Sdcard Cache File 

leJOS uses a nxj.cache file to record the MAC addresses of paired NXT devices.Running the sample LeJOSDroid.apk will set this up for you. To enable thisotherwise, create a leJOS directory in the root dir of your Android's sdcard. Withoutthis cache file, leJOS will iterate through the list of paired devices on your Android

handset and connect to the first NXT it finds.

Device Setup 

To develop with an Android device, which is necessary for anything involving aBlueTooth connection to the NXT, you will need to set up your Android device fordebugging. The Android emulator can be used to develop the GUI of your application, but the emulator can not do bluetooth connections.

Logging can be seen in the Eclipse window or via a shell by using logcat via adb 

LeJOSDroid Samples

The LeJOSDroid.apk Android application includes three leJOS samples modifiedfrom /pcsamples that typically run on your PC or MAC:

Page 177: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 177/183

  TachoCount     BTSend     RCNavigationControl  

The samples have been tailored for Android, and it is important to understand the

modifications required by Android Application Fundamentals 

The LeJOSDroid.apk can be installed with the adb tool in your-android-sdk-location/platform-tools/. Please uninstall the distributed LeJOSDroid.apk from yourAndroid device (via Settings --> Applications --> Manage Applications) beforereinstalling a new LeJOSDroid.apk or there will be an error about conflictingsignatures. How to sign an Application. 

TachoCount 

TachoCount works with either LEGO or leJOS firmware via LCP. Nothing needs to be uploaded to or run on your brick.

BTSend 

The BTSend example requires that samples/BTRecieve must be uploaded and runningon a NXT with leJOS firmware. See the section on flashing the leJOS firmwarein getting started for your OS, and compiling and running leJOS programs on the

 NXT.

RCNavigationControl 

The BTSend example requires that samples/RCNavigator must be uploaded andrunning on a NXT with leJOS firmware. See the section on flashing the leJOSfirmware in getting started for your OS, and compiling and running leJOS programs on the NXT.

Application Fundamentals

Below are some Android application fundamental considerations:

Further details on the topics touched on below, as well as complete information on UIdesign and other topics are available from the Android Developer Site 

Page 178: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 178/183

Connection 

You will need to pair with the NXT from your Android device before being able toconnect.

leJOS connection is done via the standard lejos.pc.comm.NXTConnector method. leJOSwill detect the Android environment and attempt toloadlejos.pc.comm.NXTCommAndroid. NXTCommAndroid is not included in the pccomm.jar due to Android dependencies and must be included in the src of your project.

You'll notice the LeJOSDroid method is static and returns a connected NXTConnector. The reason is that the two examples which use this code (BTSendand TachoCount), call it from another thread that those examples create. The reasons

will be discussed in the next section on threading. 

Example -- LeJOSDroid connection method:

private final static String TAG = "LeJOSDroid";

Page 179: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 179/183

  <--- used to label the logging

public static NXTConnector connect(final CONN_TYPE connection_type) {

<--- method to return connectionLog.d(TAG, " about to add LEJOS listener ");

NXTConnector conn = new NXTConnector();

conn.setDebug(true);

conn.addLogListener(new NXTCommLogListener() {

public void logEvent(String arg0) {

Log.e(TAG + " NXJ log:", arg0);

}

public void logEvent(Throwable arg0) {

Log.e(TAG + " NXJ log:", arg0.getMessage(), arg0);

}

});

switch (connection_type) { <--- specifies the connection typei.e. LCP or packet

case LEGO_LCP:

conn.connectTo("btspp://NXT", NXTComm.LCP);

break;

case LEJOS_PACKET:

conn.connectTo("btspp://");

break;

}

return conn;

}

Page 180: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 180/183

Threading 

Most work in Android must be done off the main UI thread, otherwise the user willsee a ANR (Android Non-Response) message when there is no response to an input

event (e.g. key press, screen touch) within 5 seconds.

For this reason, the BTSend and TachoCount samples are run in their own thread. In particular, BTSend has a while loop that could take more than 5 seconds.Similarly, TachoCount could run into ANR problems if it were run on the main UIthread and included a method that took longer than 5 seconds to execute which is possible using LCP as some methods such as Motor.rotate() don't return until aftercompleting.

It should be noted that while the NXTCommAndroid class creates threads internally for IO

(one to read incoming and one to write outgoing data via bluetooth),the NXTCommAndroid read()method will block until data is available. Also,the NXTCommAndroid open() methods used for connection creation will block until theconnection is made and IO streams are available.Since lejos.pc.comm.NXTConnector.connectTo()methods ultimately callthe NXTCommAndroid open() method that blocks, calls to open connections should bedone off the main UI thread as done in the examples.

The RCNavigationControl example has a more complex UI which isn't easilycombined with LeJOSDroid and so is run as a new activity. This new activity is, in

fact now, the UI thread that creates other threads to handle the connection and readingwhich block. If an ANR message appears from work done on the main UI thread, thatwork too will need to be threaded. In actuality, the code to connect forRCNavigationControl works fine even if it is taken out of it's own thread because inall likelyhood the user won't be creating an input event (via a key press or screentouch for example) while waiting for a connection to be made.

Internal Messaging 

One implication of Android threading is that MessageHandlers or  BlockingQueues must be used to exchange data between threads as directcommunication is not advised.

Page 181: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 181/183

RCNavigationControl is extremely illustrative of this point. In theoriginal pcsamples/RCNavigationControl, the RCNavComms class is created while passingin the RCNavigationControl instance in the constructor, and the instance is used toupdate the UI.

public class RCNavigationControl extends javax.swing.JFrame{//example for PC or MAC

...

private RCNavComms communicator = new RCNavComms(this);

<------ This (using an instance to update the UI thread) isdangerous in

Android with potential memory leaks and unpredictable behavior

}

public class RCNavComms { //example for PC or MAC

RCNavigationControl control;

public RCNavComms(RCNavigationControl control)

{

this.control = control;

}

class Reader extends Thread{

...

public void run(){

...

control.showtRobotPosition(x, y, h);

<------ This (using an instance to update the UI thread) isdangerous in

Android with potential memory leaks and unpredictable behavior

}

}

}

In comparision, the RCNavComms class for the Android example uses a Handler thatwas passed in through the constructor (instead of the RCNavigationControl instance).

public class RCNavComms{ //example for Android

Handler mUIMessageHandler;

Page 182: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 182/183

 

public RCNavComms(Handler mUIMessageHandler){

this.mUIMessageHandler=mUIMessageHandler;

}

public void sendPosToUIThread(float x, float y, float h) {float[] pos= {x,y,h};

Bundle b = new Bundle();

b.putFloatArray(RCNavigationControl.ROBOT_POS, pos);

Message message_holder = new Message();

message_holder.setData(b);

mUIMessageHandler.sendMessage(message_holder);

}

class Reader extends Thread{

...public void run(){

...

sendPosToUIThread(x, y, h); <------ Sends a message via aHandler

}

}

}

public class RCNavigationControl extends TabActivity{ //example forAndroid

...

class UIMessageHandler extends Handler {

float[] pos;

@Override

public void handleMessage(Message msg) {

//Log.d(TAG, "handleMessage");

switch (msg.what) {

case LeJOSDroid.MESSAGE:

//Log.d(TAG, (String)msg.getData().get(LeJOSDroid.MESSAGE_CONTENT));

mMessage.setText((String)msg.getData().get(LeJOSDroid.MESSAGE_CONTENT));

break;

Page 183: LeJOS NXJ Tutorial

7/23/2019 LeJOS NXJ Tutorial

http://slidepdf.com/reader/full/lejos-nxj-tutorial 183/183

 

default:

pos =msg.getData().getFloatArray(ROBOT_POS);

showtRobotPosition(pos[0], pos[1],pos[2]);

}

}

}

Please see the documentation to learn more about Handlers. While theRCNavigationControl example does in fact work even without using a Handler and passing in an instance to use to update the UI, it's very true that Threads will run briefly as the UI thread if you try to update the UI by passing in an instance andmodifying the View (as would be done by using the PC or MAC example). Views inAndroid are decidedly single threaded and sanity checks may not catch what you aredoing and thus lead to unpredictable behavior Also there is a risk of memory leaks