SoftBank Robotics documentation What's new in NAOqi 2.5?

Java SDK

Warning

The API presented here is still under development and may change in the future.

Introduction

The Java SDK provides Java bindings to:

  • call remote services,
  • create new services
  • and react to events.

This SDK is based on libqi-java, which in turn uses the qi Framework, and contains additional wrapper Java-dedicated classes that can be found in this Javadoc.

Requirements

  • Java 1.6 or higher.

Available on

OS Comment
Windows 32 bits No 64 bits support.
Linux 32 and 64 bits Tested with Ubuntu 12.04 LTS, but should work fine on any recent distribution.
Mac OS X 64 bits  
NAOqi OS 2.1 and higher Running on NAO V4 and V5.
Android 4.0 For ARM.

How to use

There is one .jar per NAOqi version and platform.

This .jar will allow you to use the Aldebaran‘s C++ API or to create your own services, and run them from a remote machine or directly in the robot.

First, download the java-naoqi-sdk-<version>-<platform>.jar from the Community website. Then, use it as you would do for any 3rd party Java library:

In eclipse

Add the java-naoqi-sdk-<version>-<platform>.jar as an external jar in the properties of your project.

From the command line

# Compile your application
javac -cp /path/to/java-naoqi-sdk-<version>-<platform>.jar YourClass.java

# Run your application
java -cp /path/to/java-naoqi-sdk-<version>-<platform>.jar:. YourClass

Directly in the Aldebaran robot

Warning

Java is not currently present in the system image.

However, you may install and configure Java on your robot if you wish to run your services directly in the robot.

Step Action
Download the JRE 32bits from the Oracle website.

Upload then extract it somewhere on the robot.

scp jre-7u60-linux-i586.tar.gz nao@nao.local:
ssh nao@nao.local
tar xvfz jre-7u60-linux-i586.tar.gz
mkdir /home/nao/java
mv jre1.7.0_60 /home/nao/java

Copy the java-naoqi-sdk-<version>-atom jar on the robot.

For instance, in: /home/nao/java/

scp java-naoqi-sdk-<version>-atom.jar nao@nao.local:/home/nao/java/

Create a sourceme file looking like:

nano /home/nao/java/sourceme

export JAVA_HOME=/home/nao/java/jre
export PATH=$PATH:/home/nao/java/jre/bin
export CLASSPATH=/home/nao/java/java-naoqi-sdk-<version>-atom.jar
Compile your code and upload the .class files to the robot. (see previous section From the command line)
Run source sourceme and use the command line to run your Java application.

Java SDK specificities

There are two important concepts to know that will allow you to communicate with your robot: Application and Session.

An Application is responsible of initializing the framework and connecting it to a session. A Session is what allows you to connect services together locally or over the network.

By default, the session URL is set to tcp://127.0.0.1:9559. If you wish to change this, you can pass it as a command line argument (using –qi-url):

java -cp /path/to/java-naoqi-sdk-<version>-<platform>.jar:. YourClass --qi-url=nao.local
public static void main(String[] args) {

    Application application = new Application(args);
    try{
        // Start the application and create a session.
        application.start();
        // A session has been created. It can be retrieved this way:
        // application.session();
    }
    catch(Exception e){
        // The application could not be started.
        e.printStackTrace();
    }
}

or in the Application constructor:

public static void main(String[] args) {
    // The robotUrl is specified here
    String robotUrl = "tcp://nao.local:9559";
    Application application = new Application(args, robotUrl);
    try{
        // Start the application and create a session.
        application.start();
        // A session has been created. It can be retrieved this way:
        // application.session();
    }
    catch(Exception e){
        // The application could not be started.
        e.printStackTrace();
    }
}

Warning

The Application constructor must be called exactly once in the main Java process for the type system and the event loop to work.

Getting Started

Calling a remote service

In Java SDK, there are dedicated classes for each service. This means that you must create an instance of the desired service to be able to call its methods.

The example below shows how to make the robot say “Hello World” by using ALTextToSpeech.

package com.aldebaran.examples;

import com.aldebaran.qi.Application;
import com.aldebaran.qi.helper.proxies.ALTextToSpeech;

public class SayHello {

    public static void main(String[] args) throws Exception {
        String robotUrl = "tcp://nao.local:9559";
        // Create a new application
        Application application = new Application(args, robotUrl);
        // Start your application
        application.start();
        // Create an ALTextToSpeech object and link it to your current session
        ALTextToSpeech tts = new ALTextToSpeech(application.session());
        // Make your robot say something
        tts.say("Hello World!");
    }
}

Reacting to events

It is possible to subscribe to ALMemory events by using the ALMemory.subscribeToEvent method but with a slight different signature: an EventCallback with the expected type is needed, and a subscription ID is given in return.

The example below shows how to make the robot react every time its front tactile head sensor is touched, and to stop reacting (unsubscribe from FrontTactilTouched event) when its rear tactile head sensor has been touched.

package com.aldebaran.examples;

import com.aldebaran.qi.Application;
import com.aldebaran.qi.CallError;
import com.aldebaran.qi.Session;
import com.aldebaran.qi.helper.EventCallback;
import com.aldebaran.qi.helper.proxies.ALMemory;
import com.aldebaran.qi.helper.proxies.ALTextToSpeech;

public class ReactToEvents {

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

        String robotUrl = "tcp://nao.local:9559";
        // Create a new application
        Application application = new Application(args, robotUrl);
        // Start your application
        application.start();
        System.out.println("Successfully connected to the robot");
        // Subscribe to selected ALMemory events
        ReactToEvents reactor = new ReactToEvents();
        reactor.run(application.session());
        System.out
                .println("Subscribed to FrontTactilTouched and RearTactilTouched.");
        // Run your application
        application.run();

    }

    ALMemory memory;
    ALTextToSpeech tts;
    long frontTactilSubscriptionId;

    public void run(Session session) throws Exception {

        memory = new ALMemory(session);
        tts = new ALTextToSpeech(session);
        frontTactilSubscriptionId = 0;

        // Subscribe to FrontTactilTouched event,
        // create an EventCallback expecting a Float.
        frontTactilSubscriptionId = memory.subscribeToEvent(
                "FrontTactilTouched", new EventCallback<Float>() {
                    @Override
                    public void onEvent(Float arg0)
                            throws InterruptedException, CallError {
                        // 1 means the sensor has been pressed
                        if (arg0 > 0) {
                            tts.say("ouch!");
                        }
                    }
                });
        // Subscribe to RearTactilTouched event,
        // create an EventCallback expecting a Float.
        memory.subscribeToEvent("RearTactilTouched",
                new EventCallback<Float>() {
                    @Override
                    public void onEvent(Float arg0)
                            throws InterruptedException, CallError {
                        if (arg0 > 0) {
                            if (frontTactilSubscriptionId > 0) {
                                tts.say("I'll no longer say ouch");
                                // Unsubscribing from FrontTactilTouched event
                                memory.unsubscribeToEvent(frontTactilSubscriptionId);
                            }
                        }
                    }
                });
    }

}

Creating a new service

It is also possible to create and register your own service.

First, create your own QiService. For example:

package com.aldebaran.examples;

import com.aldebaran.qi.QiService;

public class HelloService extends QiService {

    public String greet(String name) {
        return "Hello " + name;
    }

}

Then, register your service and run your application:

package com.aldebaran.examples;

import com.aldebaran.qi.Application;
import com.aldebaran.qi.DynamicObjectBuilder;
import com.aldebaran.qi.QiService;
import com.aldebaran.qi.Session;

public class MyApplication {

    public static void main(String[] args) throws Exception {
        String robotUrl = "tcp://nao.local:9559";

        // Create a new application
        Application application = new Application(args, robotUrl);

        // Create an instance of your service
        QiService service = new HelloService();

        // Create a DynamicObjectBuilder, that will render your service
        // compatible with other supported languages.
        DynamicObjectBuilder objectBuilder = new DynamicObjectBuilder();
        service.init(objectBuilder.object());

        // Advertise the greet method contained in your HelloService service.
        // You need to specify its signature.
        objectBuilder.advertiseMethod("greet::s(s)", service,
                "Greets the caller");

        // Start your application
        application.start();

        // Retrieve the created session
        Session session = application.session();

        // Register your service in your session
        session.registerService("MyHelloService", objectBuilder.object());

        // Run your application
        application.run();
    }
}

As long as your application is running, you can call the advertised methods of your MyHelloService service as you would do for any other NAOqi service.