NAOqi Frameworkとは？

Softbankから発売されるPepperはAldebaran社との共同で作られており、そのフレームワークに同社のフレームワークであるNAOqi Frameworkが採用さているようです。

NAOqiとは
==============
Aldebaranロボティクス社のロボット上・もしくはロボット制御用ソフトウェアの総称です。
NAOqi OSの上でNAOqi Frameworkが動いているようです。
OSに注目が集まりがちですが、NAOqi OSは多分単なるリアルタイムLinuxであり、NAOqi Frameworkこそが
NAOqiの中核であると言えます。

NAOqi Frameworkとは
====================

NAOqi FrameworkとはNAOをプログラムするためのフレームワークで、
動作、音声、画像に対して、一貫したインタフェースを提供します。
(2014/08/22)現在のバージョンは2.1です。

以下は↓の参考URLの意訳になります。
参考： https://community.aldebaran.com/doc/2-1/dev/naoqi/index.html

NAOqi Frameworkの特徴
------------
以下の2つが特徴として挙げられています。

* クロスプラットフォーム（Windows/Linux/Mac）。Win/Macではクロスコンパイルのみ。
* 多言語対応(C++/Pythonのみ)

多言語対応
-----------
多言語といっても、日本語英語の話ではなく、C++/Pythonの話しです。
例えば、ロボットに何か喋らせたいとして、以下のようにほぼ（意味的に）同じコードで記述できます。

```py
textToSpeachProxy.say("こんにちわ")
```

```cpp
textToSpeachProxy->say("こんにちわ");
```

分散処理
------------
リアルタイムなアプリケーションはスタンドアロンなものにもなるし、分散環境にもなります。
どちらも同じように記述することができます。アプリケーションが他のロボットにIPアドレスとポートで接続すると、すべてのAPIがローカルAPIと全く同じ方法で実行することが出来ます。
ただし、外部から呼び出し可能なAPIを作成するにはモジュールという単位のライブラリをC++で作成する必要があります。Pythonは呼び出しのみ。

動作の仕組み
=============

Introspection
---------------
BIND_METHODというAPIを使うことで、Introspectionが使えるようになります。
これによりロボットが今ロードしているモジュールのどんなAPIが使えるかが簡単にわかります。

* 登録した関数がC++/Pythonのどちらからでも呼べるようになる
* その関数が実行中であるかどうか分かる
* 外部コンピュータや他のロボットからも関数呼び出しができるようになる
* wait/stop/isRunningが使える

APIを調べるには http://ROBOT_IP:9559 にアクセスするだけで出来ます(ROBOT_IPはロボットのIPアドレス(127.0.0.1など)。
モジュールのリスト、メソッドリスト、パラメータ、コメントやサンプルをブラウザ上に表示できます。
ブラウザ上には実行中の関数も表示されます。

プロセスモデル
-----------------

ロボットは実行にautoload.iniというファイルに書かれたライブラリを読み込みます。ライブラリの中にはモジュールが１つ以上含まれます。

### Broker ###

autoload.iniを読み込むプログラムはBrokerと呼ばれ、どんなモジュールがローカル・リモートに存在するかを管理します。

### Proxy ###

モジュールを呼び出すために対象としたモジュールに対応するProxyを作成します。
プロキシの作成の方法には、ローカルとリモートの２通りのやり方があります。

モジュール
------------
モジュールはライブラリ(.soファイル)中のC++のクラスとして作られます。これはautoload.iniにより読みこまれ、自動的にインスタンスが作成されます。

- リモートモジュール：ロボットの外部で実行する場合は、モジュールは１つの実行ファイルになります。ロボット外なので、デバッグがし易いですが、効率が悪いです。通信には[SOAP](http://ja.wikipedia.org/wiki/SOAP_(%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB))が使われています。そのため高速なデータ転送には向いていません。
- ローカルモジュール：ロボット体内の場合はライブラリになります。通信の遅延やオーバーヘッドがないので効率がよいです。ローカルモジュール同士は同一プロセスになります。

リモートモジュールの通信
=======================

- Broker同士の接続: Broker同士をつなげるとお互いのモジュールにすべてアクセス可能になります。
- BrokerへのProxyを作成: 外部Brokerへのプロキシを作成すると、そのProxyを通じて外部Brokerの持つモジュールすべてにアクセス可能になります。この場合は、外部Brokerに存在するモジュールからこちらのモジュールにはアクセス出来ません。

Broker同士の接続
---------------------

Broker同士を接続する場合は、モジュール実行時に--pipオプションと--pportオプションにより、外部BrokerのIPとポートを指定します。モジュールの中では、以下のようにして外部モジュールにアクセス出来ます。

```cpp
AL::ALProxy proxy = AL::ALProxy(MODULE_NAME);
```

実行時にIPとポートが指定されているので、プログラム中でそれらを気にする必要はありません。

BrokerへのProxyを作成
---------------------
BrokerへのProxyを作る場合はプログラム中で相手のIPとポートを指定する必要があります。

```cpp
// 接続先NAOqi ip
const std::string pip = "127.0.0.1"; // local NAOqi
// 接続先NAOqi port
int pport = 9559;

// 自分のBrokerの生成
const std::string brokerName = "mybroker";
boost::shared_ptr<AL::ALBroker> broker =
  AL::ALBroker::createBroker(brokerName, "0.0.0.0", 54000, pip, pport);
AL::ALProxy proxy = AL::ALProxy(broker, <modulename>);
```

ブロッキングとノンブロッキング
===============================

ブロッキングは普通の関数のように、処理が終わるまで待ちます。

```cpp
module.doSomething();
// 処理が終わってから進む
```

これを module.postというオブジェクトを通じて実行することで、ノンブロッキングに処理を行うことが出来ます。

```cpp
int taskID = module.post.doSomething();
// 処理が終わる前に先にすすむ
```

taskIDを使って、実行状態を調べることが出来ます。
これは非常に便利ですね。

メモリ
=============

ロボットはALMemoryという、すべてのモジュールが共通してアクセス可能な、スレッドセーフな記憶領域を持ちます。

イベント
=============
イベントという仕組みによって何かが発生したときのコールバックを登録しておくことが出来ます。
例えば人の顔を認識したときにイベントが発生するようにしておけば、それに対して、手を振る、人の顔の方向に首を曲げる、といったコールバックが登録可能です。


概要は以上になります。