Seiten

Freitag, 28. März 2014

Java8 CompletableFuture for JavaFX and CDI Part I

Java8 CompletableFuture for JavaFX and CDI Part I Java8 will give you a few more tools to solve concurrency problems.
One of them is the CompletableFuture. I will show you, how you could sync the
two different init-cycles from CDI and JavaFX with this.

CDI and JavaFX are using a life-cycle during the init process.
For CDI you can use the method that is annotated with the
AnnotationLiteral @Postconstruct and for JavaFX you can use the method initialize(..)
If you want to have a method that is called after both others are finished you have to think
about the problem that it is not clear which method is called first.
To show more in detail what the problem is let us think about the following.
 
private String pattern;
private SimpleDateFormat sdf;

//beispielhaft für eine init
public void createSDF(){
    this.sdf = new SimpleDateFormat(this.pattern);        
}

//beispielhaft für eine init
public void newPattern(final String pattern) {
    this.pattern = pattern;
}

public String format(final Date date){
    return sdf.fomat(date);
}
To use the method format(..) you must use the methods newPattern(..) and createSDF first.
But both in the right order like the following code snipp.
 
newPattern("yyyy.MM.dd");
createSDF();
final String s = versionAB.format(new Date());
System.out.println("s = " + s);
If you are calling first createSDF(..) for example you will get an exception.
But thinking to the problem with CDI and JavaFX it must be valid to do something like the following.
 
createSDF();
newPattern("yyyy.MM.dd");

final String s = versionAB.format(new Date());
System.out.println("s = " + s);
The method creatdSDF(..) is called before newPattern(..).
The solution is quite simple. The method call from createSDF must be non blocking but
waiting with the execution until newPattern(..) was called.
The same with format(..). This method call must wait until both are finished but itself it
is an blocking method call. This is to give the developer the feeling he expected,
if he is working with the result from format(..).
To solve this we have to booleans called initCompleteA and initCompleteB.
Both are false in the beginning. If newPattern(..) is called initcompleteA will be true,
and initCompleteB will be true after the method creatSDF() is ready.
 
public void newPattern(final String pattern) {
    this.pattern = pattern;
    initCompleteA=true;
    System.out.println("newPattern = " + pattern);
}
public void createSDF(){
    CompletableFuture<Void> supplyAsync
        = CompletableFuture
        .supplyAsync(taskCreateSDF, cachedThreadPool);
    supplyAsync.thenAccept(System.out::println);
}
public Supplier<Void> taskCreateSDF = ()-> {
    while(! initCompleteA ){
        try {
            System.out.println("createSDF is waiting" );
            TimeUnit.MILLISECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    sdf = new SimpleDateFormat(pattern);
    initCompleteB = true;
    return null;
};
The Method format(..) now is only waiting for both...
 
public Supplier<String> task = ()-> {
//Warten bis alle true
    while(! (initCompleteA && initCompleteB) ){
        try {
            System.out.println("initCompleteA = " + initCompleteA);
            System.out.println("initCompleteB = " + initCompleteB);
            System.out.println("pattern = " + pattern);
            System.out.println("sdf = " + sdf);
            TimeUnit.MILLISECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    return sdf.format(this.date);
};
private Date date;

public String format(final Date date){
    this.date = date;
    supplyAsync = CompletableFuture
        .supplyAsync(task, cachedThreadPool);
    try {
        return supplyAsync.get();
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
    return "";
}
The example you will find at http://stash.rapidpm.org/projects/PUB/repos/jaxenter.de-0016-async-calls/browse
The next Part will show how we have to implement the JavaFX CDI bootstrapping to use this.

Montag, 17. März 2014

Lego Mindstorms EV3 Components: Color Sensor - Part 1

In this and in our next postings on our Lego Mindstorms series we will have a closer look at the EV3 color sensor. Today we will use the sensor's ability of detecting and distinguishing different colors.

Meanwhile version 0.7.0 of the lejos api was released. But in this tutorial we will still use the 0.6.0-release as 0.7.0s changes weren't dramatic. So you should be able to run the same program with 0.7.0, too.

The robot

The only task the robot will do in this tutorial is: Detecting colors and tell us which color was detected. So in fact we only need the sensor. No motors or something like that is needed. But as we already have a robot from our last articles on the infrared sensor we will take that one and only switch the infrared sensor with the new color sensor.



The parcours

We built a stick with different colors: red, green, yellow and blue. We will hold the different colors in front of the robot's sensor and the robot should give feedback on the detected color by letting the background-LED of the brick's buttons illuminate in the same color. One exception: If blue is detected the program should exit.


The color sensor API

Like the infrared sensor the color sensor has different modes for different tasks. The infrared sensor for example had modes to detect signals of an infrared source or to detect objects and their distance to the robot.
There is a mode for every task a sensor can execute. To detect different colors we need the color sensor's colorIDMode. Once the sensor is in the right mode we only need to call colorSensor.getColorID to get the detected color.

Sounds easy, IS easy. Here comes the code.

The code

We have two classes this time: The Main-class and the ColorRecognizerThread-class. First, let's look at the (really small) main-class:

public class Main {


    public static void main(String[] args) throws InterruptedException {
        final EV3ColorSensor colorSensor = new EV3ColorSensor(SensorPort.S2);
        final SensorMode mode = colorSensor.getColorIDMode();
        final ColorRecognizerThread colorRecognizerThread = new ColorRecognizerThread(colorSensor);

        colorRecognizerThread.start();

        Button.waitForAnyPress();
    }

}

In contrast to our earlier postings we don't need a DifferentialPilot this time because the robot doesn't have to move. So the only things we do is instantiating a new ColorSensor-Instance and set it to the colorIDMode. Then we instantiate a ColorRecognizerThread (which extends Thread) and give it the color sensor object as a constructor parameter. In that thread we will implement the logic to detect colors and let the LED illuminate in the same color.
After starting the thread we wait for any button press as always so that our program won't just exit after starting the thread.

The ColorRecognizerThread looks like the following:

public class ColorRecognizerThread extends Thread {

    private EV3ColorSensor colorSensor;

    public ColorRecognizerThread(final EV3ColorSensor colorSensor) {
        this.colorSensor = colorSensor;
    }

    @Override
    public void run() {
        while(true){
            final int colorId = colorSensor.getColorID();
            switch (colorId){
                //RED
                case 0:
                    Button.LEDPattern(2);
                    break;
                //GREEN
                case 1:
                    Button.LEDPattern(1);
                    break;
                //BLUE
                case 2:
                    Button.LEDPattern(4);
                    threadSleep(2000);
                    Button.LEDPattern(0);
                    System.exit(0);
                //YELLOW
                case 3:
                    Button.LEDPattern(3);
                    break;
                default:
                    Button.LEDPattern(0);
            }
        }
    }

    private void threadSleep(final int ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

The constructor is easy as it only saves the color sensor object into a private variable so that we can use it in the run-method.
The really interesting part is the run-method of course, which is called when starting the thread in the main class. We have a deadloop as we want the robot to detect colors continuously. In that loop we get the color found by the color sensor by calling the getColorID()-Method. As you can see it returns an integer. By having a look at the sources (Color.java) we find out which integer value stands for which color:

    public static final int RED = 0;
    public static final int GREEN = 1;
    public static final int BLUE = 2;
    public static final int YELLOW = 3;
    public static final int MAGENTA = 4;
    public static final int ORANGE = 5;
    public static final int WHITE = 6;
    public static final int BLACK = 7;
    public static final int PINK = 8;
    public static final int GRAY = 9;
    public static final int LIGHT_GRAY = 10;
    public static final int DARK_GRAY = 11;
    public static final int CYAN = 12;
    public static final int BROWN = 13;
    public static final int NONE = -1;

So, after getting the id we have a "switch case"-statement for that id. If the found color is red, green or yellow we just want the background-LED of the brick to illuminate in the same color (case 0, 1 and 3). Maybe you are curious why the integer parameter for the Button.LEDPattern-method doesn't match with the integer values from the Color-class. Well, the LED doesn't have a pattern for all of the colors. It has 9 different patterns in total (thanks to tigger from the forum for that information!)

0: turn off button lights
1/2/3: static light green/red/yellow
4/5/6: normal blinking light green/red/yellow
7/8/9: fast blinking light green/red/yellow
>9: same as 9.
 If the color blue is found (case 2) I wanted the program to do the following: Turn the light of the color sensor of and exit the program. The api says that we can use the setFloodlight(int color)-method for that by calling it with Color.NONE:

/**
* Used to turn on or off the floodlight by color. If the sensor has multiple light colors,
* you can control which color is turned on or off. If the color does not exist, it does
* nothing and returns false. You can turn the floodlight off by using Color.NONE.
But this throws an exception if you look at the sources of EV3ColorSensor (the default case of the switch-statement):

public boolean setFloodlight(int color)
    {
        int mode;
        switch (color)
        {
        case Color.BLUE:
            mode = COL_AMBIENT;
            break;
        case Color.WHITE:
            mode = COL_COLOR;
            break;
        case Color.RED:
            mode = COL_REFLECT;
            break;
        default:
            // TODO: Should we ignore a wrong color or throw an exception?
            throw new IllegalArgumentException("Invalid color specified");
        }
        switchMode(mode, SWITCH_DELAY);
        // TODO Auto-generated method stub
        return true;
    }

But I never the less wanted to give some optic signal to show that the program is exiting. Turning off the LED wasn't enough because we already turn it of in our default case of our switch statement in the ColorRecognizerThread. In the end I decided to let the LED display the pattern 4 (blinking green) for two seconds before exiting the program. The threadSleep-method was just created to have the try-catch out of our run-method (because it looks stupid).

That's all.

The result

And here is the tiny result (watch on youtube for better quality):





Montag, 10. März 2014

Lego Mindstorms EV3 Components: Infrared Sensor - Part 3

This is the last part of our articles on the mindstorm's infrared sensor. After looking at the abilities of the remote sensor to recognize objects and commands from the remote control we will now have a closer a look on the functionality of finding an infrared signal sent by the remote control constantly.

In february the lejos api had a new release - 0.6.0-ALPHA, so while using the 0.5.0-ALPHA-release in our last articles we will by now use the 0.6.0-release.

The robot

We will use the robot from the last two articles on the infrared sensor again, and of course we will use the remote control. If you haven't checked the infrared articles already ( Part 1/Part 2) you should do so.

The parcours

There is the robot and there is the remote control. In this part we want to tell the robot: Hold a distance of about 20-35cm to the remote control!
Which means that if we move the remote control nearer to the robot, it should move backwards and if we move the remote control away from the robot it should follow. We will only use the toggling button this time. If it is toggled and sending a signal, the robot should care about holding the right distance to the remote control. The program will exit if the signal ends (the button is untoggled).

The infrared sensor API

As announced in our last part on the infrared sensor we will use the SeekMode this time to receive the relative position and distance of the remote control.

What we will need to instantiate therefore is: the infrared sensor and a RangeFinderAdaptor for the infrared sensor.

As soon as we instantiated a RangeFinderAdapter we can use its getRanges()-method which returns all required information to let the robot find the remote control and its position.

We will use a thread which will check those informations continuously so that the robot will always react to changes of the remote controls position.

Let us directly jump to the finished code and see how it works in detail.

The code

We have two classes this time: The Main-class and the InfraredSignalCheckerThread-class. First, let's look at the main-class:

public class Main {

    protected final static double PILOT_SPEED = 60.0;
    protected final static int PILOT_ACCELERATION = 500;
    protected final static double WHEEL_DIAMETER = 30.0f;
    protected final static double DISTANCE_BETWEEN_WHEELS = 170.0;

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

        final DifferentialPilot pilot = new DifferentialPilot(WHEEL_DIAMETER, DISTANCE_BETWEEN_WHEELS, Motor.C, Motor.B);
        final EV3IRSensor infraredSensor = new EV3IRSensor(SensorPort.S2);
        final RangeFinderAdaptor rangeFinderAdaptor = new RangeFinderAdaptor(infraredSensor.getSeekMode());
        final InfraredSignalCheckerThread checkerThread = new InfraredSignalCheckerThread(rangeFinderAdaptor, pilot);

        configurePilot(pilot);
        checkerThread.start();

        Button.waitForAnyPress();
    }

    private static void configurePilot(final DifferentialPilot pilot) {
        pilot.setAcceleration(PILOT_ACCELERATION);
        pilot.setRotateSpeed(PILOT_SPEED);
        pilot.setTravelSpeed(PILOT_SPEED);
    }
}

First, we instantiate the pilot and the infraredSensor as always. Then we instantiate the RangeFinderAdapter which gets the infrared-sensor's SeekMode as a parameter. The RangeFinderAdapter will return all informations on the remote control's position. We then instantiate a InfraredSignalCheckerThread which gets the adaptor to check the remote control's position continuosly and the pilot to let the robot react on the remote control's position.

After the instantiations we set the pilot's speeds and start the thread. So now let's have a look at our Thread-class:

public class InfraredSignalCheckerThread extends Thread {

    private RangeFinderAdaptor adaptor;
    private DifferentialPilot pilot;
    private boolean isMoving = false;
    private  boolean isBearing = false;

    public InfraredSignalCheckerThread(final RangeFinderAdaptor adaptor, final DifferentialPilot pilot){
        this.adaptor = adaptor;
        this.pilot = pilot;
    }

    @Override
    public void run() {
        while(true){
            final float bearing = adaptor.getRanges()[0];
            final float distance = adaptor.getRanges()[1];
            if(distance < 129.0f && distance > 127.0f && bearing < 1.0f){
                System.exit(0);
            }
            doBearing(bearing);
            doMoving(distance);
        }
    }

    private void doBearing(final float bearing) {
        if(bearingIsOk(bearing)){
            isBearing = false;
        }
        else {
            if(bearing > 5.0f){
                pilot.rotateRight();
                isBearing = true;
            } else {
                pilot.rotateLeft();
                isBearing = true;
            }
        }
    }

    private void doMoving(final float distance) {
        if(!isBearing){
            if(!isMoving){
                pilot.quickStop();
            }
            if(distanceIsOk(distance)){
                pilot.quickStop();
                isMoving = false;
            }
            else {
                if(distance < 25.0f){
                    pilot.backward();
                } else {
                    pilot.forward();
                }
                isMoving = true;
            }
        }
    }

    private boolean bearingIsOk(final float bearing) {
        if(bearing < 5.0f && bearing > -5.0f){
            return true;
        }
        return false;
    }

    private boolean distanceIsOk(final float distance) {
        if(distance >20.0f && distance < 35.0f){
            return true;
        }
        return false;
    }
}

The constructor is easy as it only saves the adaptor and the pilot into private variables so that we can use them in the run-method. If you have a look at the private variables you will see that there are two boolean attributes isBearing and isMoving. We need those variables because we want to robot to first react on direction changes of the remote control (which is done by rotating), and we don't want the robot to react on distance changes (which is done by moving forwards/backwards) until the bearing has finished.

Okay, let's have a look at the run-method which is called when we start the thread in the main-class.
We need two information on our remote control: The relative bearing to the robot and the distance to the robot. As said earlier, the getRanges()-Method returns those information. Here is what the api says:
/**
     * return a sample provider for the IR sensor operating in seek mode
     * The provider returns the bearing and distance to one or more IR beacons.
     * Up to four
     * beacons (on different channels 0-3) can be detected. Each beacon has an
     * associated two byte value (so the beacon on channel 0 will have values
     * in locations 0 and 1 in the array. The first location contains the relative
     * bearing to the beacon, the second the distance.

     * The bearing values range from -12 to +12 (with values increasing clockwise
     * when looking from behind the sensor. A bearing of 0 indicates the beacon is
     * directly in front of the sensor. Distance values (0-100) are in cm and if no
     * beacon is detected a bearing of 0 and a distance of 255 is returned.

So, we only care for the first two floats of the array because we only have one remote control. And we want the bearing-information of it ([0]) and the distance-information ([1]).

After writing those informations into float variables we check, if the information are valid: The api says, if no signal is found the value of bearing will be 0 and the distance will be 255. So first, we check this case and exit the program if no signal is found (I found out, that if no signal is sent, the distance value is 128.0 and not 255 as written in the api).

If the values are valid (a signal was received we call the methods doBearing and doMoving). Those methods will make the robot first react on direction changes of the remote control, and then react on distance changes afterwards. Let's have a closer look at these two methods, first the doBearing-Method:

private void doBearing(final float bearing) {
        if(bearingIsOk(bearing)){
            isBearing = false;
        }
        else {
            if(bearing > 5.0f){
                pilot.rotateRight();
                isBearing = true;
            } else {
                pilot.rotateLeft();
                isBearing = true;
            }
        }
    }

private boolean bearingIsOk(final float bearing) {
        if(bearing < 5.0f && bearing > -5.0f){
            return true;
        }
        return false;
    }

First, we check if the bearing is okay, which means that the remote control is more or less directly in front of the robot. As said in the api that value can be anything between -12 and 12 (I found out, that this value can be anything between -25 and 25). So we tell the program, if the value is between -5 and 5 the bearing is okay and the reaction of the robot has finished. If the bearing is not okay, we tell the robot to rotate right of the bearing is greater than 5, or rotate left if the value is lower than -5. While rotating, we tell the program, that the robot is reacting to the bearing, by setting the isBearing-attribute to true. By the rotation the bearing value will approach to 0. When that's the case we tell the program, that the robot has finished its reaction and set the isBearing variable to false.

And here's the doMoving-Method:

private void doMoving(final float distance) {
        if(!isBearing){
            if(!isMoving){
                pilot.quickStop();
            }
            if(distanceIsOk(distance)){
                pilot.quickStop();
                isMoving = false;
            }
            else {
                if(distance < 20.0f){
                    pilot.backward();
                } else {
                    pilot.forward();
                }
                isMoving = true;
            }
        }
    }
private boolean distanceIsOk(final float distance) {
        if(distance >20.0f && distance < 35.0f){
            return true;
        }
        return false;
    }

When the doBearing-method has finished, the doMoving-method will start. But we only want to react on the remote control's distance if the robot has finished it's reaction to the bearing. So we first check, if the robot is not bearing any longer. The second "if" that follows now is a bit tricky: We check, if the robot is moving as a result from the doMoving-Method or as a result from the doBearing-method. If it NOT moving as a result of the doMoving-method, it should stop because then we have the case, that the robot is still rotating as a reacting to the bearing (we didn't tell the program to stop rotating any time in the doBearing-method). So after that, we check if the remote control's distance is okay (which means the remote control is in a distance of 20 to 35cm) to the robot. If that is the case the robot should stop and we mark the isMoving-attribute as false. If the distance is NOT okay we tell the robot to move backwards of the distance is less then 25 (because it should "flee" from the remote control) or move forwards if the distance is greater than 35 (because it should "follow" the remote control).

The result

And here is the result (watch on youtube for better quality):