roslibjsの基本的な使い方

## はじめに
roslibjsを使って開発している中で、日本語の情報がまとまっておらず不便だったためまとめてみました。
基本的には[ROS Wiki](http://wiki.ros.org/roslibjs) に記載されている内容ですが、サービスについては追加しています。
paramについては利用していないので記載していません。

他の使い方も、勉強し次第追記しようと思います。
間違い等あれば指摘していただけると幸いです。
## 環境
* Ubuntu16.04
* ROS kinetic
    * `rosbridge-server`パッケージをインストール
* node
    * `roslib`をインストール

ウェブページ等で動かす場合にはnodeのインストールは不要です。

## roslibjsのインポート
NodeJSを利用する場合

```js
const ROSLIB = require("roslib");
```

ウェブページ等で利用する場合 (html内に)

```html:

<script type="text/javascript" src="http://static.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js"></script>
<script type="text/javascript" src="http://static.robotwebtools.org/roslibjs/current/roslib.min.js"></script>
```
## rosとの接続の確立

接続するurlや`rosbridge-websocket`を介してrosと接続したとき、接続でエラーが起きたとき、接続が閉じられた時などに行う処理を記載します。

この際、url内のホスト名は`rosbridge-websocket`を起動するPCのホスト名であり、`roscore`が起動している`ROS_MASTER_URI`のホスト名とは異なるため注意します。

```js
const ros =  new ROSLIB.Ros({
    url: 'ws://localhost:9090'
});

ros.on('connection', () => {
    console.log('Connected to websocket server');
});

ros.on('error', error =>{
    console.log('Error connecting to websocket server: ', error);
});

ros.on('close', () => {
    console.log("Connection to websocket server was closed");
});
```
## Publish
トピックの宣言、メッセージの宣言等は以下のように行います。

```js
const cmdVel = new ROSLIB.Topic({
    ros : ros,
    name : '/cmd_vel',
    messageType : 'geometry_msgs/Twist'
});
   
const twist = new ROSLIB.Message({
    linear : {
     x : 0.1,
     y : 0.2,
     z : 0.3
    },
    angular : {
     x : -0.1,
     y : -0.2,
     z : -0.3
    }
});
```
宣言した`cmdVel`トピックのメッセージとして`twist`をpublishする場合は以下のようにします。

```js
cmdVel.publish(twist);
```
## Subscribe
まずは、publish時と同様に、subscribeしたいトピックを宣言します。

```js
const listener = new ROSLIB.Topic({
   ros : ros,
   name : '/listener',
   messageType : 'std_msgs/String'
});
```
そして、そのトピックを受け取った際に行う関数を登録します。

```js
listener.subscribe(message => {
    console.log('Received message on ' + listener.name + ': ' + message.data);
});
```

以上の方法でトピックを受け取ることができます。
これ以上受け取る必要がない場合には、以下のように`unsubscribe()`を実行しましょう。

```js
listener.unsubscribe();
```

## Service
ROS Wikiには、サービスコールについてのみしか記載されていないため、[roslibjsのリポジトリ](https://github.com/RobotWebTools/roslibjs)を見て理解したことをまとめます。


#### サービスの宣言
`name`にはサービスの名前を,`serviceType`にはサービスタイプを記載します。`rosbridge_websocket`を起動するPC上でsrvファイルを作成し、`catkin_make`しておくか、ROSの基本パッケージで定義されたサービスタイプを利用しましょう。
ここでは、ROS Wikiで使用されている`rospy_tutorials/AddTwoInts`を使用しています。必要な場合は`ros-kinetic-rospy-tutorials`をインストールしましょう。

```js
const addTwoIntsClient = new ROSLIB.Service({
    ros: ros,
    name: '/add_two_ints',
    serviceType: 'rospy_tutorials/AddTwoInts',
});
```

#### サービスコール
宣言したサービスへのリクエストの内容を宣言し、`サービス.callService()`の引数としてリクエストの内容と、レスポンスがあった際の処理を記載することでサービスコールを行うことができます。

```js
let request = new ROSLIB.ServiceRequest({
   a : 1,
   b : 2
});
   
addTwoIntsClient.callService(request, result => {
   console.log('Result for service call on '
     + addTwoIntsClient.name
     + ': '
     + result.sum);
});
```
#### サービスの実行
宣言したサービスを、js上で実行する方法です。
上で宣言したサービスをそのまま使ってもいいのですが、名前がClientなのに違和感があるので新たに宣言します。

```js
const addTwoIntsServer = new ROSLIB.Service({
    ros: ros,
    name: '/add_two_ints_server',
    serviceType: 'rospy_tutorials/AddTwoInts',
});
```

そして、リクエストへの処理をコールバックとして記述し、以下のように`サービス.advertise()`の引数に与えることでサービスを実行できます。

```js
addTwoIntsServer.advertise((req, res) => {
    res.sum = req.a + req.b
    return;
}
```  

この際、`rosbridge_websocket`を実行したままの状態で、ページの再読込等によって同じサービスの宣言が複数回行われてしまうと、初回のサービスコールが失敗する場合があるため注意してください。

#### サービスの停止
一度実行したサービスを停止したい場合には、以下のように`サービス.unadvertise`を実行します。

```js
addTwoIntsServer.unadvertise();
```    
    
#### おまけ
pythonやC++で開発を行う際に、別のノードで実行されているサービスへサービスコールを行う場合には,`waitForService()`等を利用するかと思います。
`roslibjs`には同様の関数はありませんが、

```js
ros.getServices(services => {
    if(services.indexOf('/add_two_ints') != -1){
        ...(中略)...
});

```
以上のように`getServices()`メソッドで、サービスの一覧をリストで取得できるため、使用したいサービスが格納されているindexを探すと、サービスが実行されているかが分かります。
もっと良い使い方があれば教えてください。