Sensor framework

This is where you talk about the EV3 software itself, installation issues, and programming talk.

Moderators: roger, gloomyandy, skoehler

Sensor framework

Postby Aswin » Sun Jan 05, 2014 9:59 pm

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

Naming
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. The second part 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.

Samples
Sensor make 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 in all cases returned in an array of floats. All sensors use the same method for getting 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.

Modes
Some sensors have multiple ways of operation. These are called modes. The EV3 ultrasonic sensor 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 mode you want to use. You do not have to switch between modes, you just use 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.

Code: Select all
// 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");

// 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 each sensor uses 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 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 the sensors on it.
On sensors that support multiple axes, like some gyroscopes and accelerometers, the axis order in a sample is alway X,Y,Z.
Image

Filters
Filters are used to alter a sample or , sometimes, to alter the flow of samples. They are an integral part of the framewok. Filters take a sample from a SampleProvider, modify it and then pass it on as a sample. They are in fact, sample providers 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 sample provider 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.

Code: Select all
// 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 aailable for your sensor, then the available adaptors in the package provide a good example of writing an adaptor youself.
My NXT blog: http://nxttime.wordpress.com/
Aswin
leJOS Team Member
 
Posts: 198
Joined: Tue Apr 26, 2011 9:18 pm
Location: Netherlands

Re: Sensor framework

Postby jerryP » Sun Jan 05, 2014 11:26 pm

Thanks Aswin, that was very useful!
jerryP
New User
 
Posts: 18
Joined: Mon Aug 19, 2013 12:32 am

Re: Sensor framework

Postby lawrie » Mon Jan 06, 2014 7:28 pm

Hi Aswin, I have added this to the Wiki. Lawrie
lawrie
leJOS Team Member
 
Posts: 917
Joined: Mon Feb 05, 2007 1:27 pm

Re: Sensor framework

Postby comix » Wed Jan 08, 2014 1:57 am

Thank you Aswin!

I have a question, in the method

void fetchSample( float[] sample, int offset),

what does the offset mean?
comix
New User
 
Posts: 12
Joined: Fri Dec 27, 2013 2:05 am

Re: Sensor framework

Postby Aswin » Wed Jan 08, 2014 7:17 am

The offset value allows you to specify where the sample values are written in the sample array. An offset value of 0, what you would normally use, means that the first sample value is written to the first item in the array and so on.

The benefit of the offset value is that it allows you to collect samples from different sensors, or different moments in time, in one array.
My NXT blog: http://nxttime.wordpress.com/
Aswin
leJOS Team Member
 
Posts: 198
Joined: Tue Apr 26, 2011 9:18 pm
Location: Netherlands

Re: Sensor framework

Postby comix » Wed Jan 08, 2014 10:17 pm

Aswin wrote:The offset value allows you to specify where the sample values are written in the sample array. An offset value of 0, what you would normally use, means that the first sample value is written to the first item in the array and so on.

The benefit of the offset value is that it allows you to collect samples from different sensors, or different moments in time, in one array.


Got it, thank you!
comix
New User
 
Posts: 12
Joined: Fri Dec 27, 2013 2:05 am

Re: Sensor framework

Postby roger » Fri Feb 21, 2014 12:53 am

Hi Aswin,
Thanks for a great effort to unify the treatment of sensors, and to provide for filters. Unfortunately, I do not fully understand it.

There are two errors in the wiki.
1. The example has
Code: Select all
 SampleProvider distance = Sensor.getModeName(“Distance”) 

This produces an error in Eclipse because the method is actually
Code: Select all
Sensor.getMode(“Distance”)

2. Te wiki states that all sensors implement theSampleProvider interface, but the EV3UltrasonicSensor and the EV3 GyroSensor do not.
How do the sensor classes that implement the fetch Sample() method determine what mode to use?
For example, the EV3ColorSensor does have fetchSample() but from some experimenting, I get inconsistent results so I wonder what mode is being used. Apparently, there is no instance variable for the mode, and no method for setting the mode. So some sensor classes are SampleProivders but do not have mechanism for specifying which mode is to be used. Other sensors are not sample providers, and the user must get a Mode in order to fetch a sample.
My personal preference is that all Sensors provide their own samples, but it seems they must have a mechanism to specify the mode to be used. Perhaps the mode could be a parameter in the fetchSample() method.
Roger
roger
Moderator
 
Posts: 359
Joined: Fri Jun 01, 2007 4:31 am
Location: Berkeley, CA

Re: Sensor framework

Postby Aswin » Fri Feb 21, 2014 9:41 pm

Hi Roger,

Thanks for the feedback.

I corrected the code error in the wiki.


As for modes and SampleProviders. A SampleProvider that is associated with a sensor is a SensorMode. It represents just one mode of this sensor. You cannot switch the mode of a SensorMode. You can query the mode it represents using the getName() method.

Each sensor is represented by a class that implements the SensorModes interface. This interface provides methods to query the modes that a sensor supports. For each of these supported modes there is a distinctive class of the type SensorMode available that can be obtained from the SensorModes class. This is even true for sensors that support jst one mode. A SensorMode class (note the missing s!) represents exactly one mode of the sensor. So if a sensor supports three modes than there is one SensorModes class and there are thre SensorMode classes. You cannot fetch samples from the SensorModes class, you need a SensorMode class for that.
As this is a bit complicated for sensors that support just one mode you see that the sensor class (that implement SensorModes) also implement SensorMode. Therefore you can direcly fetch samples from the EV3TouchSensor without getting a mode object first.
Also some more complex sensors that support different modes have a default mode that is implemented by the sensor class itself. You only need to get a mode object for the non default modes. The EV3ColorSensor has a default mode.
You can get a description of the mode a SensorMode object implements using the getName() method.
My NXT blog: http://nxttime.wordpress.com/
Aswin
leJOS Team Member
 
Posts: 198
Joined: Tue Apr 26, 2011 9:18 pm
Location: Netherlands

Re: Sensor framework

Postby roger » Sat Feb 22, 2014 6:40 pm

Hi Aswin,
Thanks for your reply.
I do have some concerns about the Sensor Framework, which I am a little hesitant to mention since I have not paid attention to it before using it just recently. But I will anyhow.
The Sensor Framework is a good idea – to treat all sensors in a consistent way. But it seems to me that there is flaw in its implementation. My favorite authors on Java (Horstmann for example) say that a class should represent a single well defined, concept. And classes that are abstractions of real world objects should capture the essential features of the real world. For me, the essential feature of a physical senor is that it provides information about the external world. Also, many sensors have multiple modes for collecting and processing the data. Therefore, all Sensors should be Sample Providers. ( But in the current version of the Framework, some Sensors are not.) For sensors with multiple modes, it should be possible for programmer to specify to the Sensor which mode to use to calculate when providing the sample. In the current design, this is not possible. Instead, the Mode object both determines which mode will be used and also supplies the sample. This is a mixture of two separate concepts . As a result, we have Sensors that have a only 1 mode and do not need a Mode specification to provide samples, some sensors have multiple modes and can provide samples but do not give the programmer the ability to specify which mode to use, and some sensors that are not sample providers and rely on a Mode object to do that part of what should be the Sensor essential task.
I think that a redesign is in order with the following features:
1. All Sensors should be Sample Providers.
2. Programmers should have mechanism for specifying which mode is to be used
3. Mode classes should not be sample providers because that is not part of the concept of mode, but is key to the concept of the Sensor .
Other comments, based on pretty limited experience with the framework.
(4) I do not find the sensorModes class useful because I do not know what the mode names are or what getMode(2) might give me without looking at the sensor source code. Instead I use the getXXXmode() methods in the sensor classes.
(5 )I am curious about the design decision of the fetchSample() method. I usually expect the a method to return the result of its calculation. This one does not, but instead updates an array that is provided as a parameter.
Thanks for your patience in answering my questions.
Roger
roger
Moderator
 
Posts: 359
Joined: Fri Jun 01, 2007 4:31 am
Location: Berkeley, CA

Re: Sensor framework

Postby gloomyandy » Sat Feb 22, 2014 8:10 pm

Hi Roger,
all of the sensor classes are sensor providers (or you can obtain sensor providers from them). Remember that a SensorMode extends the SampleProvider interface and simply provides additional information (and in the future may well provide more). The SensorModes interface (which is implemented by all sensors) allows you to enumerate the modes supported by the sensor. Which ones do you think are not sensor providers?

The concept of modes was discussed a lot but in general it was felt that forcing the user to explicitly change mode does not really add anything. Instead simply asking for data (via the fetchSample method) associated with a particular Sensor Mode takes care of any mode switching if required. It really is pretty simple, try it. So for instance if you want color ids (ie red/green/blue etc.) from the the EV3ColorSensor simply obtain the sample provider by calling getColorIDMode, then when you call fetchSample the sensor will be set into the correct operating state and the sample returned. Similarly if you want the reflected light reading when an object is illuminated by a red light simply get the sample provider for this mode by calling getRedMode and then calling the associated to fetchSample, no need to set modes or do anything else simply call fetchSample and the required data is returned. It was felt that since we have sensors that support multiple modes, and others that contain multiple devices (but which do not require any mode switching to say return acceleration or gyro readings from the same device), that it was better to unify all devices around the same model and in effect abstract the mode switching detail away (in the same way that we hide the electrical interface details, we do not make a user need to understand if the sensor uses i2c, or a uart type conection).

The fetchSample interface is a compromise between efficiency and clarity. Many sensors return multiple values (like 3 axis accelerometers etc.) and we wanted the filter framework to be able to easily work on these multi-value items without having to define many different return objects. This is a little awkward for sensors that simply return a single value, but I think that overall it is worth it.

We had a very, very long and detailed discussion about this many months ago on the mailing list and pretty much every possible implementation was explored. You can probably dig this out from the mailing list archive if you want all of the details!

Andy
User avatar
gloomyandy
leJOS Team Member
 
Posts: 3950
Joined: Fri Sep 28, 2007 2:06 pm
Location: UK

Re: Sensor framework

Postby Aswin » Sat Feb 22, 2014 8:56 pm

In addition to Andy's answer.

The SensorModes interface relate to a physical sensor. The SensorMode/SampleProvider interface relate to a single type of measurement. So both relate to real world objects.
There is good reason why each type of measurement (mode) has its own SampleProvider that has not been mentioned before. This is best explained by taking an example of a sensor that can measure multiple types of measurements. let me take an IMU sensor that measures both rate of turn and acceleration. Suppose you want to process these measurements using filters. It is very likely that you want to process the rate of turn in a different way than acceleration. You might want to integrate rate of turn to get heading and process acceleration to get tilt. This requires different filters.As it is you would stack a one chain of filters on the rate of turn SampleProvider and another chain on the acceleration SampleProvider. Therefore it makes sense to have a different SampleProvider for each type of measurement or for each mode. This also applies to other sensors that provide different modes, it is very unlikely that theses modes will make use of the same filter stack.


Aswin
My NXT blog: http://nxttime.wordpress.com/
Aswin
leJOS Team Member
 
Posts: 198
Joined: Tue Apr 26, 2011 9:18 pm
Location: Netherlands

Re: Sensor framework

Postby skoehler » Sat Feb 22, 2014 10:45 pm

roger wrote:(5 )I am curious about the design decision of the fetchSample() method. I usually expect the a method to return the result of its calculation. This one does not, but instead updates an array that is provided as a parameter.

I think in python it is possible to return multiple values. In most other languages, it is the case that one can only return one scalar (refernce, int, float). Returning a reference to an array is of course feasible, but would bear the question whether the method creates a new array every call (terribly inefficient) or returns the same array over and over again (this is kind of unsafe as the caller may work with the array). A common technique (at least for C and Java) is that the caller passes a reference or pointer and thereby tells the callee where to put the result. This is both safe and efficient, however, the actual return value of the function then usually becomes size of what has been written, an error code, or something similar.
skoehler
leJOS Team Member
 
Posts: 1401
Joined: Thu Oct 30, 2008 4:54 pm

Re: Sensor framework

Postby tigger » Mon Feb 24, 2014 10:39 pm

A common technique (at least for C and Java) is that the caller passes a reference or pointer and thereby tells the callee where to put the result.


I think this is more the C way than a common technique in Java. As far as I see in Java EE code the object-oriented approach using data transfer objects is more common than reference passing. For sure, references are ways more efficient (faster, without memory wasting object references and in an embedded environment also energy saving), so this is the best solution here - but not as common as for a C programmer. First days in leJOS I also was confused with the return value as argument.
tigger
New User
 
Posts: 17
Joined: Mon Feb 10, 2014 10:04 pm

Re: Sensor framework

Postby wiso » Thu Jul 24, 2014 4:11 pm

Hi!
I'm trying to learn how to use the sensors. I want to use the EV3Ultrasonicsensor and display on the screen of EV3 the distance to an object at each times. I followed the steps in this post, but I don't know how to show each sample.

Thanks.
wiso
New User
 
Posts: 6
Joined: Fri Nov 29, 2013 11:05 am

Re: Sensor framework

Postby roger » Thu Jul 24, 2014 5:12 pm

What seems to be the difficulty? Getting the sample or displaying it? Could you post the code fragment that is not working properly?
Roger
roger
Moderator
 
Posts: 359
Joined: Fri Jun 01, 2007 4:31 am
Location: Berkeley, CA

Next

Return to EV3 Software

Who is online

Users browsing this forum: Yahoo [Bot] and 3 guests

more stuff