Seiten

Freitag, 27. Dezember 2013

Developing leJOS programs with IntelliJ on Windows

LeJOS is the java library which is needed to develop and run java programs on Lego Mindstorms robots. Four days ago, the newest alpha version 0.5.0 was released. One big new feature is an all new gui-menu which is displayed on the LCD-Display for executing programs on the brick without executing a remote command (via telnet or SSH).

The official guides use eclipse as the IDE for developing lejos programs and in this tutorial I want to explain how to develop programs with IntelliJ on Windows. I will also show how to transfer finished programs to the brick and execute it via remote connection and via the new display menu.

Initial situation


You have created the bootable MicroSD-Card for running Lejos (version 0.5.0-alpha) on the Mindstorms brick and inserted it into the brick (a tutorial on how to create is can be found here. Recognize that the procedure has changed from version 0.4.0-alpha to 0.5.0-alpha). You also have a compatible WiFi-Stick (e.g. Netgear WNA1100) which is inserted into the USB-Plug on the brick.

So let's start. What we will do is:
  1. Clone the official lejos git repository to get the sources which we need to build our program
  2. Create and configure the IntelliJ-Project for our lejos program
  3. Write the code for the program (the usual HelloWorld from the official guide)
  4. Create a runnable JAR-File of the program
  5. Transfer the JAR-File onto the brick via WiFi / SSH
  6. Execute the program via the new display menu
  7. Alternative way of executing the program: Execute the program via WiFi / SSH (the old-fashioned pre-0.5.0-way)

1 Clone the official lejos git repository to get the sources which we need to build our program

For cloning the lejos git repository you must have installed git (which can be obtained from here). For comfort (not having to use single git commands on the command line) we used the free-to-use (for non-commercial use) GUI-Tool SmartGitHg 5 (version 5.0.5) by syntevo which rocks and can be downloaded on the official site. When you start the program for the first time you have to tell SmartGitHg where your git installation is located, but thats quite straight-forward and the wizard will help you doing that. After you have started and configured SmartGitHg choose:
"Project" --> "Clone ..."
Then choose:
"Remote Git, Mercurial or Subversion Repository" and enter git://git.code.sf.net/p/lejos/ev3 into the textfield.
Then click "Next". In the next window make sure both check boxes are checked. Click "Next" again. Choose a path where the source should be copied to (We chose the path "F:\projects\ev3-sources" which we will call EV3-SOURCES by now). Then click "Next" again. On the last window choose the option "Open in new project" and leave the name in the textfield as it is. Finally press "Finish". SmartGitHg will then start downloading all files from the repository. This might need some minutes. You can watch the progress in the right bottom corner of the window.
After the download has finished the window should look like the following:

SmartGitHg, downloaded EV3-sources



At last we have to choose the 0.5.0-alpha tag branch. Choose "Branch" --> "Checkout...". In the following window choose the 0.5.0-alpha tag branch as shown in the following picture:

checking out the 0.5.0-alpha tag branch
Press "Check out" and then choose "Check out commit without switching to a branch".

Now that we have the lejos sources in version 0.5.0-alpha let's start creating our IntelliJ project for our HelloWorld-Program.

2 Create and configure the IntelliJ-Project for our lejos program

Start IntelliJ and choose: "File" --> "New Project...". Choose "Java Module" and call it HelloWorld. We saved it in "F:\projects\HelloWorld" (which I will call HELLOWORLD by now). Then press "Next" and "Finish".

Now that we have a raw new project, lets first configure it before creating the HelloWorld-code. Open the project settings ("File"-->"Project Structure") and click on "modules". Then click on "Add Content Root" and choose EV3-SOURCES\ev3-classes\src and click on "OK". Do the same with EV3-SOURCES\DBusJava\src.
As next click on "Librarys" on the "Project Structure"-window. Click on the green "+" and choose "Java". Then choose the folder EV3-SOURCES\ev3-classes\lib and click on "OK". Click on "OK" again.
Press "Apply" and "OK" to close the project structure window now.
Your project structure should now look like this:

Project structure

3 Write the code for the program

Now let's create the code. Create a class in HelloWorld\src and call it "Main". Make it look like the following:

import lejos.hardware.Button;
import lejos.hardware.lcd.LCD;

public class Main {
    public static void main(String[] args) {
        LCD.clear();
        LCD.drawString("First EV3 Program", 0, 5);
        Button.waitForAnyPress();
        LCD.clear();
        LCD.refresh();

    }
}
 
If the imports fail, something went wrong with the configuration of the project structure.

As you can see the class implements the Main-method. It will show "First EV3 Program" on the display of your EV3-Brick until you press any button on the brick.

That's it. Now we are ready to create a runnable JAR of our program.

4 Create a runnable JAR-File of the program

Open the project settings again ("File" --> "Project Structure..."). Click on "Artifacts".Click on the green "+" and choose "Jar" --> "From modules with dependencies...". Leave everything as it is in the new window but enter "Main" into the field "Main Class" like in the following picture:

Creating jar-file
Then click on "OK". Click on "Apply" and close the Project Structure-Window. Now we need to do one last thing before creating our ready-to-execute Jar. There is a new folder in your HelloWorld-src folder called "META-INF". It contains a MANIFEST.MF-File. It contains two lines as you can see in the following picture:

MANIFEST-file




Now you need to add the following line:
Class-Path: /home/root/lejos/lib/ev3classes.jar /home/root/lejos/libjna/usr/share/java/jna.jar

You can copy/paste that line because the paths are absolute paths on the MicroSD-card.

That's it. Save everything and choose "Build"-->"Build artifacts..."-->HelloWorld.jar-->"build". If you get some warnings that's okay. If you get errors anything went wrong (let us know). Now we have created a Jar-File (in HELLOWORLD\out\artifacts\HelloWorld_jar) which we can transfer via WiFi to the EV3-Brick.

5 Transfer the JAR-File onto the brick via WiFi / SSH

To transfer the jar-file from our workstation to the EV3-Brick we need a connection to it. So start your EV3 with the lejos-MicroSD-card and the WiFi-Stick inserted. Make sure that your robot has an IP-Adress in your network. A description on how this is done via the menu can be found here (that didn't work for us, so we had to edit the file /etc/wpa_supplicant.conf on the microSD-card by hand).

Now that our EV3 is online and connected to the WiFi we will transfer the jar-file onto the robot. Therefore we need to download pscp.exe from http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html. We downloaded it to "C:\Users\Marco\Downloads".
Open up a cmd-box (Windows-Button --> enter "cmd", then choose cmd.exe) and navigate to the folder which contains the downloaded pscp.exe. Then enter the following command:


pscp -scp HELLOWORLD\out\artifacts\HelloWorld_jar\HelloWorld.jar root@IP_OF_EV3:/home/lejos/programs


If you are asked for the root password just hit enter. The root user on the linux-system on the microSD card has no password. In my case that looked like the following:

transfering the jar-file onto the brick
That's it! The file now was copied onto the EV3-brick (in /home/lejos/programs). Time to execute our program.



6 Execute the program via the new display menu

On the display menu move to "Files" (by pressing the right button). Press "Enter" (the middle button). Now you will see "HelloWorld.jar" on the display. Press "Enter" again. Now you will see "Execute Program" on the display. Press "Enter" once more and enjoy the magic :). It will need some seconds where you will only see a blank display. But then the "First EV3 Program" will be displayed as expected. When you press any button the program will end as expected and you will be back at the menu. Congratulations for running your lejos program developed with IntelliJ on Windows!

7 Alternative way of executing the program: Execute the program via WiFi / SSH (the old-fashioned pre-0.5.0-way)

Sometimes you might want to run your programs which you uploaded onto the brick remotely instead of pressing buttons on the brick. One solution for this is to use a ssh connection via putty. So  download it from http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html (putty.exe). After downloading, execute the putty.exe. Enter the IP of your EV3 into the field "Host Name (or IP address)" and click on "Open". This will open a remote console. Enter "root" as user name and just press enter when asked for password. Now you could run your program. But we have to do one more thing before executing the program: We have to disable the menu. If we wouldn't do this, both (the String "First EV3 Program" of our program AND the display menu) would be displayed in the display. So in the menu navigate to "System" and select "Suspend Menu". The menu will now be suspended and the display will be blank. Now back to our remote console. Enter the following command to execute the program (which we transfered to /home/lejos/programs on the brick earlier):
jrun -cp /home/lejos/programs/HelloWorld.jar Main
remote console in putty

Look at the display and enjoy the magic again ;). It will again need some seconds until you will see the string on the display. Hit any button on the brick to end the program. If you want the menu back after executing the program press the middle button and the lower button on the brick. The display menu will be back instantly.

If you have any questions or problems during the process feel free to leave a comment.

Dienstag, 24. Dezember 2013

Happy Holiday from RapidPM

Hey Folks,

we at RapidPM (humans as well as non-humans) wish you a happy holiday season and a happy new year 2014. May it be successful in every way for you and us. We would also like to thank you all for your interest in our blog and our projects and we hope you will keep visiting us in 2014 :-)


Montag, 16. Dezember 2013

Our new project: Lego® Mindstorms® M1ndSuite

*drum roll*..............Voila! Today we officially announce our new project called M1ndSuite. It will be developed parallel to our cdi-commons project.

What is it / What is it going to be?

In general: MindSuite (or "M1ndSuite") will be a gui- (web-)application for controlling and/or monitoring Lego® Mindstorms® robots.

For those, who don't know what Lego® Mindstorms® is: The official website says:
LEGO® MINDSTORMS® EV3 has arrived! Combining the versatility of the LEGO building system with the most advanced technology we’ve ever developed, unleash the creative powers of the new LEGO MINDSTORMS EV3 set to create and command Robots that walk, talk, think and do anything you can imagine. Follow the step-by-step 3D building instructions to create TRACK3R, R3PTAR, SPIK3R, EV3RSTORM and GRIPP3R and bring them to life with an easy, intuitive and icon-based programming interface.
Sounds cool, doesn't it?

Image what you could create with all those possilities! Or look what others already did :-D

  

But let's come back to our planned MindSuite application. At this juncture we can't tell what will be the definite features because we first have to become acquainted with the whole subject. But possible features might be:
  • offering pre-built programs for different robots
  • possibility to create new (persistent) programs for any robot (like with the official Lego software) and real-time transfer of these into the robot's operating system
  • real-time monitoring of the robot's sensors / motors / ...
  • real-time control for the robot (e.g. "move forward/backward", "turn left/right", "play sound xyz" ...)
We can imagine plenty of features, but (as already said) at this early moment we first have to get deeper into the topic. Our Mindstorm hardware just arrived on friday and we have just done our first experiments (we have built the Lego Mindstorm robot Gripp3r and loaded the standard Lego programs for it onto the EV3 brick so we could remote control it with the infrared remote control).

What frameworks will be used?

Well, of course nothing is certain at this moment (we don't even have certain features xD) but chances are good that the (web-)application will use the spring framework.
There is already a java API for creating programs for the robots called LeJOS (http://www.lejos.org/). We're pretty sure that we will use that to realize the communication between the MindSuite and the robots.

Why are we doing this?

Everyone is talking about the topics M2M (Machine-to-Machine) / IoT (Internet of Things) at the moment. We are very excited about these topics, too! And we love the idea behind Lego Mindstorms with all its possibilities! So creating a new software for controlling and monitoring those robots seems to be the perfect chance for us to get into that stuff. We can't wait to get started!

As always with our projects, MindSuite will be open source and its code will be hosted on bitbucket. You will find the code at https://bitbucket.org/rapidpm/m1ndsuite, but at this moment you won't find anything there of course. Give us some weeks ( or months? :) )..we don't have a roadmap yet. But we will regularly post updates on our blog to keep you informed of the current state, be curious! :D

first logo concept
we already built one of the Lego Mindstorms (Gripp3r)

Montag, 9. Dezember 2013

Adam Bien´s afterburner.fx internals explained..

Today I am writing about Adam´s framework afterburner.fx. This is a MVP framework for dependency injection into JavaFX apps. It is very small, containing only two classes.

What could you do with this afternburner.fx? What are the restrictions?

Let´s start with the project init. You will need only a normal pom.xml, plain no special libs are needed. I am using JDK8 because of the simple JavaFX config. (no config ;-) )

Convention over Configuration:
CoC is the main in this framework. This means, that you don´t need to configure something. But you have to follow the base structure that this framework is expecting.

As app-base-pkg I am using org.rapidpm.demo.jaxenter.blog008. (you could get all from my git repo under https://bitbucket.org/rapidpm/jaxenter.de-0008-afterburner ) The main class will be Main, this is the JavaFX Application Class with the basic boostrapping intro. The sup-pkg orig contains the pkg presentation with only one GUI module called demo. For every GUI Module you will need two classes. The first one is a class with a name ending with View and the second one will end with Presenter. In our examplke you will find the two classes, DemoView and DemoPresenter.

The DemoPresenter is nothing else as the Controller class for the View, declared inside the fxml file.
The fxml File itself must be named demo.fxml and at the same place as the Presenter/Controller class.

 The DemoView is the GUI Component itself and must extend the FXMLView class from the framework.

The View - FXMView 
The DemoView have a default constructor, calling the init method. init(Class clazz, String conventionalName) 


public FXMLView() {
    this.init(getClass(), getFXMLName());
}

private void init(Class clazz, String conventionalName) {
    final URL resource = clazz.getResource(conventionalName);
    String bundleName = getBundleName();
    ResourceBundle bundle = getResourceBundle(bundleName);
    this.loader = new FXMLLoader(resource, bundle);
    this.loader.setControllerFactory(new Callback, Object>() {
        @Override
        public Object call(Class p) {
            return InjectionProvider.instantiatePresenter(p);
        }
    });
    try {
        loader.load();
    } catch (Exception ex) {
        throw new IllegalStateException("Cannot load " 
            + conventionalName, ex);
    }
}
The init will load the ResourceBundle and the fxml-file with an instance of the class FXMLLoader. The most importand step is the setting of the ControllerFactory. Inside the instance of the ControllerFactory you will see the methodcall InjectionProvider.instantiatePresenter(p);  This ist the place where the injection will be taken place. One big point to know is, only inside a controller/presenter you will be able to use injection. Inside the Presenter no injection is available.

The InjectionProvider - DI with reflection
The InjectionProvider ist the heart of the framework. The base steps are the following:
- create an instance
- inject the attributes with the annotation Inject
- call the method with annotation Postconstruct
Thats all... but how it is realized?

The first step is quite easy, just call clazz.newInstance().

Step two is a littele bit more complex. You have to instantiate the attributes but the the attributes inside too. Thes means the injection must be done recursive. To do this you will check the attributes if they are annotated with Inject, if so, do the same for this instance.. and so on..
There is a small thig to know. The implementation from Adam will only create one instance of every used class. This means you will get only singletons!! And this for the complete application.

The last step is easy again, call all methods with the annotation Postconstruct per reflection.

static Object instantiateModel(Class clazz) {
    Object product = models.get(clazz);
    if (product == null) {
        try {
            product = injectAndInitialize(clazz.newInstance());
            models.put(clazz, product);
        } catch (InstantiationException | IllegalAccessException ex) {
            throw new IllegalStateException(
                "Cannot instantiate view: " + clazz, ex);
        }
    }
    return product;
}

static Object injectAndInitialize(Object product) {
    injectMembers(product);
    initialize(product);
    return product;
}

static void injectMembers(final Object instance) {
    Class aClass = instance.getClass();
    Field[] fields = aClass.getDeclaredFields();
    for (final Field field : fields) {
        if (field.isAnnotationPresent(Inject.class)) {
            Class type = field.getType();
            final Object target = instantiateModel(type);
            AccessController.doPrivileged(new PrivilegedAction() {
                @Override
                public Object run() {
                    boolean wasAccessible = field.isAccessible();
                    try {
                        field.setAccessible(true);
                        field.set(instance, target);
                        return null; // return nothing...
                    } catch (IllegalArgumentException | 
                                IllegalAccessException ex) {
                        throw new IllegalStateException(
                            "Cannot set field: " + field, ex);
                    } finally {
                        field.setAccessible(wasAccessible);
                    }
                }
            });
        }
    }
}
static void initialize(Object instance) {
    invokeMethodWithAnnotation(instance, PostConstruct.class);
}
Lesson Learned
The framework afterburner.fx from Adam Bien is really small without any configuration. You could use this to inject Instances per annotation Inject. If you want to use this inside your application you have to know the following:


  • There are no Scopes, all instances will have the the lifecycle of the application. The only way to terminate them earlier is to call the method forgettAll(), but this will terminate all instances. The method annotated with PreDestroy will be called before. You could not select the order the instances are destroyed.
  • All instances are singletons
  • No Producers, this means you could not abstract over an Interface layer. Or you can not switch between different implementations like you could do with Qualifiers.
If you could deal with this limitations, this will be good form you. But to use this to learn more about injection works, this is a good project to play with.