NAOqi is the name of the main software that runs on the robot and controls it.
The NAOqi Framework is the programming framework used to program NAO.
It answers to common robotics needs including: parallelism, resources, synchronization, events.
This framework allows homogeneous communication between different modules (motion, audio, video), homogeneous programming and homogeneous information sharing.
The framework:
Software can be developed in C++ and Python. In all cases, programming methods are exactly the same, all existing API can be indifferently called from any supported languages:
Most of the time you will develop your behaviors in Python and your services in C++.
These features are also linked to this section: Introspection.
Introspection is the foundation of robot API, capabilities, monitoring and action on monitored functions. The robot knows all the available API functions. Unloading a library will automatically remove the corresponding API functions. A function defined in a module can be added in the API with a BIND_METHOD (defined in almodule.h).
If you bind a function - just three source code lines - you automatically benefit from the following features:
The API is displayed on a web browser. Just type in the robot url and port 9559 - for example http://127.0.01:9559. The Robot will display its modules list, method list, method parameters, descriptions and examples. The browser also displays parallel methods that can be monitored, made to wait, stopped.
A real time application can be only one standalone executable or tree of robot, tree of processes, tree of modules. Whatever your choice is, the call methods are always the same. Connect an executable to another robot with IP address and port, and all the API methods from other executables are available in exactly the same way as with a local method. NAOqi makes the choice between fast direct call (LPC) and remote call (RPC).
The NAOqi executable which runs on the robot is a broker. When it starts, it loads a preferences file called autoload.ini that defines which libraries it should load. Each library contains one or more modules that use the broker to advertise their methods.
The broker provides lookup services so that any module in the tree or across the network can find any method that has been advertised.
Loading modules forms a tree of methods attached to modules, and modules attached to a broker.
A broker is an object that provides two main roles:
Most of the time, you don’t need to think about brokers. They do their work transparently, allowing you to write code that will be the same for calls to “local modules” (in the same process) or “remote modules” (in another process or on another machine).
A proxy is an object that will behave as the module it represents.
For instance, if you create a proxy to the ALMotion module, you will get an object containing all the ALMotion methods.
To create a proxy to a module, (and thus calling the methods of a module) you have two choices:
The full difference between local and remote modules is explained in the Local modules section.
To learn how to extend the NAO API, you must learn how to create new modules. You can read a tutorial about creating a C++ NAOqi module in the Extending NAO API - Creating a new module section.
Typically each Module is a class within a library. When the library is loaded from the autoload.ini, it will automatically instantiate the module class.
In the constructor of a class that derives from ALModule, you can “bind” methods. This advertises their names and method signatures to the broker so that they become available to others.
A module can be either remote or local.
Each module contains various methods. Among them, some methods are bound, which means they can be called from outside the module, for example inside another module, from an executable etc. The way to call these bound functions does not vary if the module is remote or local: the module automatically adapts.
The module API can be seen from the robot web page.
Local modules are two (or more) modules launched in the same process. They speak to each other using only ONE broker.
Since local modules are in the same process, they can share variables and call each others’ methods without serialization nor networking. This allow the fastest possible communication between them.
If you need to do some close loop (enslavement for example), you MUST use local modules.
Remote modules are modules which communicate using the network. A remote module needs a broker to speak to other modules. The broker is responsible for all the networking part. You must know that remote modules work using SOAP over the network. You cannot do fast access using remote module (direct memory access for example).
Remote modules can speak with other modules by connecting their brokers to other modules’ brokers using a proxy.
You can connect two modules together by connecting their brokers.
For example, you have two modules B and C. When you connect their brokers, B can access to C’s functions and C can access to B’s functions.
To connect modules this way you need to specify the IP address and port number of the main broker. (--pip, --pport command line option when you start your module). Then you can access the module by getting a proxy on it:
AL::ALProxy proxy = AL::ALProxy(<modulename>);
Since module’s broker is already connected using --pip and --pport, you do not need to specify IP address and port number when you create a proxy.
You can connect your module to another one without specifying --pip and --pport. To do that, you need to create a proxy inside your module and connect it to the broker IP address and port number you want.
For example, you have two modules B and C. When you connect B to C just using a proxy, B can access to C functions BUT C cannot access to B functions.
AL::ALProxy proxy = AL::ALProxy(<modulename>, <ip_adress>, <port_number>);
NAOqi offers two ways to call methods:
ALMemory is the robot memory. All modules can read or write data, subscribe on events so as to be called when events are raised.
Please be aware that ALMemory is not a real-time synchronization tool. Limit subscribe on DCM/time or motion/synchro or real time variable.
ALMemory is an array of ALValue’s (see ALValue). Variable access is thread safe. We use read/write critical sections to avoid bad performance when memory is read.
ALMemory contains three types of data and provides three different APIs.
A few modules exposes also some events.
You must subscribe to event from an other module, using a callback that must be a method of your subscriber.
For instance, you can have a module called FaceReaction containing a method onFaceDetected.
You can subscribe the FaceReaction module to the FaceDetected method of the ALFaceRecognition module with the onFaceDetected callback.
This will cause the face detection algorithm to run, and every time a face is detected, the onFaceDetected callback will be called.
To see how this is done in Python, please see the Making a Python module - Reacting to events section.