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.


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 by 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.


Sensor take measurements, in LeJOS a measurement is called a sample. A sample consists of one ore more values taken at one moment in time. A sound sensor for example returns one value at a time, some accelerometers return three values at a time. Mo matter how much values a sensor measures, they are always returned in an array of floats.
All sensor classes 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. The methods are defined in the SampleProvider interface, therefor sensor classes are also known as sample providers.


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. LeJOS implements each mode as a class. An object for using a sensor in a particular mode can be obtained from the sensor class. There is no need for configuring the sensor for a particular mode, this is done internally by LeJOS. You can use different modes in one program. To do so you just need to obtain an object for each of the modes that you want to use. You do not have to switch between modes, you just fetch a sample from the mode object of your choice. If needed the sensor is configured internally. This might take some time and you should be aware of that when mixing up different modes.
A sensor class that support multiple modes implements the SensorModes interface. It has a method to get an list of supported modes: ArrayList<String> getAvailableModes(). It also has a method to obtain a certain mode: SampleProvider getMode(int index) or: SampleProvider getMode(string modeName).

An example

The following example shows how to work with sensors that support multiple modes.

// 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");

// initialise an array of floats for fetching samples
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 it on as a sample. 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.
As the code shows 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 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.