Sensor Framework

Lawrie Griffiths Aswin
coordinates.png (5669 bytes)

Sensor framework

LeJOS 0.5.0-alpha introduces a uniform framework for sensors. This section explains some of the concepts of the framework and provides some examples as well.

Sensors, modes and samples

LeJOS considers a sensor a piece of hardware that measures one or more aspects of the surrounding. It often can do this in several different ways. A color sensor for example can measure the color of a surface but also the intensity of the ambient light. In leJOS each type of measurement a sensor can make is called a mode or sensor mode. A single measurement from a sensor is called a sample in leJOS.


A sensor is a piece of hardware for measuring some aspects of the surrounding and that can be connected to a sensor port. Most sensors can operate in different ways, where each way of operation gives different kind of information. A color sensor for example can measure both the color of a surface and the intensity of ambient light. In leJOS these ways of operation are called sensor modes. A sensor supports at least one mode, but often more than one.
It is important to understand that only using a combination of a sensor and a mode will define a measurement. The sensor by itself does not take measurements.
A sensor class implements the SensorModes interface. This interface defines methods to get a list of supported modes: ArrayList<String> getAvailableModes(). It also has methods to obtain the mode of your choice: SampleProvider getMode(int index) or SampleProvider getMode(string modeName) or SampleProvider getModenameMode().


Sensor classes now follow a strict naming convention. This should help you to quickly find the right class for your sensor.
The first part of the class name is EV3 for EV3 sensors made by Lego. NXT for Lego sensors made for the NXT, or the name of the manufacturer for third party sensors. The second part of the class name consists of the full sensor name (as used by the manufacturer). There might be a third part to the class name, a V followed by a version number. It is used to distinguish between hardware versions of a sensor. For example, the ultrasonic sensor that ships with the EV3 is called EV3UltrasonicSensor, the angle sensor from HiTechnic is called HiTechnicAngleSensor.
All sensor classes are found in the lejos.hardware.sensor package.


Some sensors have multiple ways of operation. These are called modes. The EV3 ultrasonic sensor for example has both a mode to measure distance and a mode to listen to other ultrasonic sensors. Only modes can take measurements, the sensor by itself does not. LeJOS implements each mode as a class that implements the SampleProvider interface, therefore a sensor in a particular mode is also known as sample provider.
If a sensor supports multiple modes you can use and mix them in a single program. You do not have to switch between modes, you just fetch a sample from the mode object of your choice.


A SampleProvider takes measurements, in LeJOS a measurement is called a sample. A sample consists of one ore more value taken at one moment in time. A color sensor in ambient light mode returns one value at a time, in RGB mode it returns three values at a time. Mo matter how much values a sensor measures in a sample, it is always returned as an array of floats.
All SampleProviders use the same method for taking a measurement: void fetchSample( float[] sample, int offset). The sensors also have a method to query the number of elements in a sample: int getSampleSize(). This number does not change over time.

An example

The following example shows how to work with sensors and modes. There are always five steps in using a sensor. Get a port, initialize the sensor, get a SampleProvider, create a an array to store samples and take samples. Only the last step has to be repeated every time the program needs a new measurement. The other steps are done just once in a program.

// get a port instance
Port port = LocalEV3.get().getPort("S2");

// Get an instance of the Ultrasonic EV3 sensor
SensorModes sensor = new EV3UltrasonicSensor(port);

// get an instance of this sensor in measurement mode
SampleProvider distance= sensor.getMode("Distance");

// initialize an array of floats for fetching samples. 
// Ask the SampleProvider how long the array should be
float[] sample = new float[distance.sampleSize()];

// fetch a sample
  distance.fetchSample(sample, 0);

Standard units

In LeJOS sensors use standard units. This makes sensors of different manifacturers interchangeable. It also simplifies further processing of a sample. For units LeJOS uses SI-units. So, distances are always returned in meters, acceleration is always returned in m/s^2, etc. Angles are always measured in degrees.

Coordinate system

LeJOS uses a cartesian coordinate system. The positive X-axis points in the same direction as the plug you plug into a sensor. This is also the direction the Ultrasonic sensors from Lego point to. The positive Y-axis points to the left of the X-axis and the positive Z-axis points upwards. Angles follow the right hand rule. This means that a counter clockwise rotation of a robot is measured as a positive rotation by its sensors.
On sensors that support multiple axes, like some gyroscopes and accelerometers, the axis order in a sample is always X,Y,Z.


Filters are used to alter a sample or to alter the flow of samples. They are an integral part of the framework. Filters take a sample from a SampleProvider, modify it and then pass the sample on. They are in fact, SampleProviders themselves. LeJOS comes with some ready made filters, they are found in the lejos.robotics.filter package. The example below shows how to use a filter to get the running average of the last five samples of an ultrasonic sensor.
The code shows that a filter constructor takes a SampleProvider as its first parameter followed by some configuration parameters. Instead of fetching a sample from the sensor class it is now fetched from the filter.
Filters can be stacked on top of each other to allow for more complex manipulations. The second filter takes the identifier of the first filter in its constructor and so on. One always fetches the sample from the last filter in the stack.

// get a port instance
Port port = LocalEV3.get().getPort("S2");

// Get an instance of the Ultrasonic EV3 sensor
SensorModes sensor = new EV3UltrasonicSensor(port);

// get an instance of this sensor in measurement mode
SampleProvider distance= sensor.getModeName("Distance");

// stack a filter on the sensor that gives the running average of the last 5 samples
SampleProvider average = new MeanFilter(distance, 5);

// initialise an array of floats for fetching samples
float[] sample = new float[average.sampleSize()];

// fetch a sample
average.fetchSample(sample, 0);

Backward compatibility

LeJOS 0.5.0-alpha deals with sensors in a different way than its predecessors. In general it does not provide backward compatibility. There are a few exceptions though. There are some adaptors in the lejos.robotics package that do provide backward compatibility. If you do not want to alter your existing programs too much, it is advised to look in this package for an adaptor that makes a sensor backward compatible. An adaptor can be stacked on a sensor of filter just like a filter. If there is no adaptor available for your sensor, then the adaptors in the package can be used as examples for writing an adaptor yourself.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

No, thanks