ROS で OpenVPN を使う

# はじめに
`VPN`で`ROS`ネットワークを繋ぎたいと思ったこと，ありませんか？まぁ，あまり無いかもしれませんが笑．

![openvpntech_logo.png](https://qiita-image-store.s3.amazonaws.com/0/110138/fd9bca2d-a8e7-a627-e496-5dc62025b06d.png)

![rosLarge-680x365_c.png](https://qiita-image-store.s3.amazonaws.com/0/110138/df6c9ed0-6702-1507-1e12-91c828a59b86.png)

## きっかけ
きっかけは，[つくばチャレンジ](http://www.tsukubachallenge.jp/)です．

実は，かのつくばチャレンジの注意事項において，遠隔からのモニタリングは***「強く推奨」***されているということです．

> [1] ロボットの位置や状況のステーションにおけるモニタリング（強く推奨）

> - 参考: [つくばチャレンジ2016 - 注意事項等](http://www.tsukubachallenge.jp/tc2016/notice)

この考えには同意します．実社会に自律移動ロボットを投入しようと思ったら，***「遠隔監視は必須機能」***にする必要があるでしょう．産業用途への適用も考慮すると，なおさらです．

まぁここではチャレンジなのでそんなに重く考える必要はないのですが^^; とはいえ，遠隔から`ROS`ロボットをいじくれるなんて，なんとなくロマンがあって面白そうではありませんか^^

そうなると手っ取り早いのが`VPN`ということになります．つくばチャレンジに出場しているチームで`ROS`を使っている方なら，一度は`VPN`でつなげてみようと思ったことがあるのではないでしょうか？

よーし，じゃあ何か情報ないかな？と調べても，ちょろっと書いてある情報くらいしか見つからず，なんとなく冷めてしまう．そんな状況になった方もいらっしゃるのではないでしょうか？（私はそうなりました笑．）

> - 参考: [How to set up VPN between ROS machines](http://answers.ros.org/question/11045/how-to-set-up-vpn-between-ros-machines/)

というわけで，自分が忘れないように，かつどなたかのお役に立てればと思い，`OpenVPN`と`ROS`を連携させる手順を残しておこうと思います．

# 前提
下記に従って`OpenVPN`の設定が完了しているものとします．

VPN全然分からない！と言う状態からでも接続までは行けるようにステップバイステップで記述しましたので，よろしければご参照下さい．

- [図解！UbuntuでOpenVPNを使う：1. 準備](http://qiita.com/MoriKen/items/7fe17fda8442adb599d9)
- [図解！UbuntuでOpenVPNを使う：2. 証明書と認証鍵の作成](http://qiita.com/MoriKen/items/50d226e8c6395487c0a6)
- [図解！UbuntuでOpenVPNを使う：3. 設定](http://qiita.com/MoriKen/items/75587fd862b3ce93e4eb)
- [図解！UbuntuでOpenVPNを使う：4. 接続確認](http://qiita.com/MoriKen/items/682d31496fd0d2476af7)

# ネットワーク構成
上記設定が完了している場合，ネットワーク構成は下記の通りとなるはずです．

![01_initial.png](https://qiita-image-store.s3.amazonaws.com/0/110138/c472bf06-293b-b654-69a2-ee27b55bc39e.png)

この状態からスタートしましょう^^

# 環境
当方での検証環境です．両方ROSが動いていれば何でも良いです．

## VPNクライアント 兼 `ROS Master`（ロボット）
  - PC: Raspberry Pi 2
  - OS: Ubuntu 14.04
  - ROS: Indigo
  
## VPNサーバ（遠隔監視PC）
  - PC: Dell Precision M3800
  - OS: Ubuntu 14.04
  - ROS: Indigo

## 補足
- ラズパイが移動ロボットに使用されることを考慮しています．
- VPNサーバを遠隔監視側に設定したのは，ロボットに余計な負荷をかけさせないためです．
- また，本記事では記載していませんが，非マスタ側を[`rosserial_windows`](http://wiki.ros.org/rosserial_windows)にしても，データのやりとりはできることは確認しました．

# ROSネットワーク設定
下図のような設定にすることを目指します．

![02_rosnetwork.png](https://qiita-image-store.s3.amazonaws.com/0/110138/2aaad720-1592-bc27-4f1f-567d7b947056.png)

##`ROS Master`設定（ロボット側）
環境変数を下記の通りに設定して下さい．`ROS`を使用する全てのターミナルで設定を反映させて下さい．

```bash
$ export ROS_MASTER_URI=http://10.8.0.6:11311
$ export ROS_HOST_NAME=10.8.0.6
$ export ROS_IP=10.8.0.6
```

ちゃんと反映されているか確認しましょう．

```bash:(command)
$ env | grep ROS_
```

```bash:(output)
# 抜粋
ROS_HOST_NAME=10.8.0.6
ROS_MASTER_URI=http://10.8.0.6:11311
ROS_IP=10.8.0.6
```

##クライアント設定（遠隔監視PC側）
環境変数を下記の通りに設定して下さい．`ROS Master`側とは`ROS_HOST_NAME`と`ROS_IP`の末尾の番号が異なります．`ROS`を使用する全てのターミナルで設定を反映させて下さい．`ROS Master`と同様に確認もしておきましょう．

```bash
$ export ROS_MASTER_URI=http://10.8.0.6:11311
$ export ROS_HOST_NAME=10.8.0.1
$ export ROS_IP=10.8.0.1
```

この辺りを効率的に実施する方法が，@RyodoTanakaさんの [複数のPCでROSを使う時の設定](http://qiita.com/RyodoTanaka/items/860c79e76991f7e04ef3)で紹介されていますので，ご興味があればとても参考になると思います^^

# ROS 接続確認
`turtlesim`でも使って遊んでみようと思います♪

## `ROS Master`での`turtlesim`起動

![03_rosmaster.png](https://qiita-image-store.s3.amazonaws.com/0/110138/ec55564d-a168-0a95-cdad-b654396e60da.png)

マスタ側で次のようにコマンドを実行します．全てのターミナルでの環境変数の設定を忘れずに．

```bash:(command_master_terminal1)
$ roscore
```

```bash:(command_master_terminal2)
$ rosrun turtlesim turtlesim_node
```

おなじみ亀さんの登場です．

![Screenshot from 2016-10-27 01:37:43.png](https://qiita-image-store.s3.amazonaws.com/0/110138/0b27d43c-bb8a-1c67-5d29-bd3c381b67f8.png)

## `topic`の確認
手始めにVPNでも`topic`のリストが見られるか確認してみます．

### ロボット（`ROS Master`）側の`topic`を確認
本当にVPNネットワークがつながっているか，今一度確認します．

```bash:(command)
$ ifconfig
```

```bash:(output)
tun0      Link encap:不明なネット  ハードウェアアドレス 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inetアドレス:10.8.0.1  P-t-P:10.8.0.2  マスク:255.255.255.255

wlan0     Link encap:イーサネット  ハードウェアアドレス 
          inetアドレス:192.168.11.11  ブロードキャスト:192.168.179.255  マスク:255.255.255.0
```

`tun0`がルーティング方式におけるVPNの仮想ネットワーク，`wlan0`が実ローカルネットワークに対応します．

そして，`topic`を確認します．

```bash:(command_master_terminal3)
$ rostopic list
```

```bash:(output_master_terminal3)
/rosout
/rosout_agg
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose
```

### 遠隔監視PC側の`topic`を確認

```bash:(command)
$ ifconfig
```

```bash:(output)
tun0      Link encap:不明なネット  ハードウェアアドレス 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inetアドレス:10.8.0.6  P-t-P:10.8.0.5  マスク:255.255.255.255

wlan0     Link encap:イーサネット  ハードウェアアドレス 
          inetアドレス:192.168.179.7  ブロードキャスト:192.168.179.255  マスク:255.255.255.0
```

確かにVPNネットワークがつながっており，`ROS Master`とはことなるLANに接続されています．

それでは，`topic`を確認します．緊張の一瞬です．

```bash:(command_nonmaster_terminal1)
$ rostopic list
```

```bash:(output_nonmaster_terminal1)
/rosout
/rosout_agg
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose
```

`ROS Master`側と完全に一致しています！VPNを介して通信ができています^^

同様に，`rosnode`, `rosparam`もリストの確認をしたところ，完全に一致していました．

慎重すぎますかね… ^^; だって，ネットワークって，怖いんですもの…．

## ロボット（`ROS Master`）への`publish`を確認
亀さんを遠隔監視PCから`teleop`してみます．

![04_teleop.png](https://qiita-image-store.s3.amazonaws.com/0/110138/e0448b7e-6ad5-784c-d8ea-899d0a1e530e.png)

とは言っても，今回は`rostopic pub`メッセージで簡易的に動かしてみるだけですが^^; 検証としては十分でしょう．

遠隔監視PCから下記のコマンドを実行します．

```bash:(command_nonmaster_terminal1)
$ rostopic pub -1 /turtle1/cmd_vel geometry_msgs/Twist -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]'
```

![Screenshot from 2016-10-27 02:02:04.png](https://qiita-image-store.s3.amazonaws.com/0/110138/8e42f39d-fe98-8042-55d6-ffd8411cc9d2.png)

可愛い亀ちゃんが動きました．あー，良かった^^ これで`ROS Master`への`publish`を確認しました．

## ロボット（`ROS Master`）からの`subscribe`を確認

今度は，`ROS Master`で同じ`publish`コマンドを打って，遠隔監視PC側でその`topic`を`subscribe`できるかを確かめます．

![05_subscribe.png](https://qiita-image-store.s3.amazonaws.com/0/110138/e0846c26-a70b-c0dd-038e-b39b22a4ba3c.png)

- `ROS Master`で下記のコマンドを実行します．

```bash:(command_master_terminal3)
$ rostopic pub -1 /turtle1/cmd_vel geometry_msgs/Twist -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]'
```

- 遠隔監視PCで下記のコマンドを実行します．

```bash:(command_nonmaster_terminal1)
$ rostopic echo /turtle1/cmd_vel
```

亀さんが更なる回転を繰り出すと同時に，遠隔監視PCで下記の表示が出てくれば成功です！

```bash:(command_nonmaster_terminal1)
linear: 
  x: 2.0
  y: 0.0
  z: 0.0
angular: 
  x: 0.0
  y: 0.0
  z: 1.8
---
```

うん，ちゃんと受け取れています！`publish`, `subscribe`の両方がうまくいくことを確認できました！^^

# 慎重過ぎでは？
うーん，確かに確認の部分は少々慎重すぎるかもしれません^^;

とはいえ，これだけみっちり調べるのは理由があります．データの送信・受信の双方向通信を確実に確認しておきたいのです．

例えば，ファイアウォールの設定が一方通行だとこういうことが起こります．`rostopic list`はできたのに`publish`しても反応してもらえない，なんてこともあります．

片方通ったからと言って安心すると後で余計な時間を食って苦労することになります．すぐに検証できるセットアップの段階にこそ，少し手間をかけても確認できることは確認しておいた方が，後々のためというものです^^

# 注意点
注意点があります．

はい，勘の良い方は気が付いていると思います．そう，超遅いです．とにかく遅いです．要因はたくさんあります．

- モバイルルータを使用するので通信速度自体に限界がある．
- ラズパイのマシンパワーが弱い．
- VPN自体暗号化を要する通信なので処理に時間がかかる．

と言う感じなので，遅いのは当然だとは思いますが，それにしても遅いです．

`roscore`は常にネットワーク見張っているような状態だと思うので，そんな処理をVPN経由でやればそりゃーオーバヘッドもありそうなものです^^;　推測でしかありませんが．

今回検証した構成では，`Rviz`でリッチな状態監視なんて，まぁ***絶対無理***だと思います笑．

ですから，実際に遠隔監視をしようと思ったら，`topic`で投げるのはあまりお行儀が良くないと思います．各自の環境に合わせて，本当に必要な情報だけを`service`で定周期通知するくらいが妥当だと思います^^

# おわりに
かくして，`OpenVPN`と`ROS`ネットワークの連携ができました．`OpenVPN`さえつながってしまえば，なんてことは無いと思います．

## そもそもいるの？
え，別にポイントにならないからいいじゃないかって？それも一理あります．まずは走破，次に人物探索，そしてはじめて「その他」なのですから．

でも！そこで敢えて！ポイントにならないような事に***「わざわざ手を出せる」***からこそ，面白いのかな，とも思います^^
(こういう一見寄り道的な取り組み，実はものすごーく幸せな行為なんですよね^^; 気が付きにくいのですが…)

もちろん，走行に関してはある程度目処が付いていなければ手が出ないところかもしれません．

ところが，`ROS`という協力な武器を持ったチームの位置づけを思い出しましょう．世界の優秀なロボット研究者がメンテしている由緒正しきソフトウェアを無料で使わせてもらえるのです．チューニングは必要でしょうが，ベースとなるアルゴリズムの実装が完成しているのです！強くてニューゲームみたいなものです！

そうして節約した時間をつかって，自分たちの個性を出せるところで出す！拘るところに拘る！これこそ，ROSを使うメリットの1つだと思います．

それに，こうして手順を残しておけば，人柱になってハマる時間も節約できるので，設定自体も短時間でサクッと進められると思います^^

## というわけで
ROSで遠隔監視をしましょう！^^

つくばチャレンジで`ROS`を使うチームが皆こぞって遠隔監視をしている．その空間だけ一足先に，社会にロボットが浸透した未来の光景が広がっている．

そんな素敵な世界が実現できたらいいですね ^^