ROS 複数台での通信時の問題点：clientからmasterへと情報送信できない

よくわからないバグ？があるので誰かおしえてくださいという話です．

# 前提：複数台のデバイスでのROSの通信

masterとclientの2台のマシンがあるとする．
2台の間で1つのrosmasterを用意して相互にデータをやりとりする．


## やるべきこと＠ROS側
[公式の説明](http://wiki.ros.org/ja/ROS/Tutorials/MultipleMachines)によるとROS_MASTER_URIを設定するとあるが，これは若干舌足らずであり，[ここの質疑](https://answers.ros.org/question/163556/how-to-solve-couldnt-find-an-af_inet-address-for-problem/)にあるようにROS_IPも設定しなければならない．(ROS_HOSTNAMEもあったほうが良さそう．）
なお，スクリプトで[自動化した人](https://qiita.com/RyodoTanaka/items/860c79e76991f7e04ef3)もいる．

### master側の設定
ROSのmasterは随時変更したいので自分は接続先により以下のようなシェルスクリプトを組んでいる．

以下のスクリプト内の**master**には`172.16.XX.XXX`のようなmasterのIPアドレスが入ることに注意．

```shell
#!usr/bin 

export ROS_MASTER_URI=http://master:11311
export ROS_HOSTNAME=`hostname -I`
export ROS_IP=`hostname -I`
```

### client側での設定
クライアント側も同様．

```shell
#!usr/bin 

export ROS_MASTER_URI=http://master:11311
export ROS_HOSTNAME=`hostname -I`
export ROS_IP=`hostname -I`
```



## PCの設定：/env/hosts の編集

両者の/env/hostsを編集して
以下のような項を入れることで**master**と打つことでIPアドレスをうつかわりになる．

```
XXX.XXX.XXX.XXX master
YYY.YYY.YYY.YYY client
```

**しかし，複数台でROS_MASTERを共有する際にはこれらをすべて整理するのが非常に面倒なので極力省きたいと思っている．（これが前提）**


# 本題：/etc/hosts を設定せずに通信したらどうなるか
上記のmasterとclientの設定をsourceで実行した後，masterとclient間のデータ通信を確認する．

### master側からの操作
- roscoreまたは適当なroslaunchを実行

適当にturtlebotを実行．

```
 roslaunch turtle_tf2 turtle_tf2_demo.launch
```


### client側からの操作
- roscoreが立ち上がったのを確認した後，適当なプログラムを実行
カメラを繋いで起動する．

```
 roslaunch usb_cam usb_cam-test.launch
```

## 結果
- masterからもclientからも`rostopic list`で**リストが見れる**．
- clientからmasterのpublishしたデータが**見れる**（/tfの中身が見れた）
- masterからclientのpublishしたデータは**見れない**（カメラの映像は見れない）

**つまるところmasterがclientの情報を見れないという状況に陥る．**
んで，この情報についてざっと見てたどり着かない（一部のアプリケーションでは困らないかもだが）ので解決が待たれる．

### データが見れないとはどういう状況か
つまりはこういうこと．なぜだ．
- `rostopic hz`でno messageと出る．
- image_viewで何も表示できない．（もちろんclient側からは見れる）

### rqt_graphによる状況の図示
master側からのrqt_graphがこれ
![master.png](https://qiita-image-store.s3.amazonaws.com/0/188863/95c3a9d3-8f7c-dcca-4973-0a2e9665efbe.png)

client側からのがこれ
![client.png](https://qiita-image-store.s3.amazonaws.com/0/188863/6c5d0902-5485-c1b1-fd67-cf430d8193ca.png)

usbカメラって言ったけどzed_wrapperを走らせてます．
見ての通り，masterのrqtgraphにはclient側からのzed〜〜という名のnodeが見れない．そういうこと．

# 解決と考察（要編集）
ケーススタディです．
## 解決したケース：`hostname -I`のかわりにアドレス直打ち
Dockerなどを使っていると`hostname -I`で複数のIPアドレスを返すことがある．
その場合上記の書き方は良くないとここの[質疑](https://answers.ros.org/question/90536/ros-remote-master-can-see-topics-but-no-data/)へのコメントであるが真偽は不明．

今回の上記のケースでは`hostname -I`に謎のIPが紛れていたので（２つあった）このようにしたら**うまく行った**．

## 解決したケース：/etc/hostsを設定する
master側がclient側からの情報を見れていないのでmaster側の/etc/hostsの設定をする．（ていうかどっちもやった）

**→ 解決した場合があった**
あくまで場合が合った．これは他の人のPCと通信した時に起きたので再現不能．（今深夜なので）

## 考察：netcatを用いた確認
pingが通るのは当たり前である必要が有るが，pingが通っていてもROSの通信がダメな場合が有る．

ここの公式の手順を試してみるのもあり．http://wiki.ros.org/ja/ROS/NetworkSetup

## 関連するかもしないかもな事象
- **ファイヤウォールの設定を替える**とうまく行ったり行かなかったりとかがあるらしい．
- ROSが諸々の変更を反映するためにはdevel以下のsetup.bashを実行したほうがいいのかもしれない？（実際うまく行った時は/etc/hostsを設定した後にsetup.bashを実行している．その後/etc/hostsは戻したけど．）

# 結論（2018/5/31現在）
つまるところ，

- ROS_MASTER_URI,ROS_IP,ROS_HOSTNAMEを適切に設定すれば/etc/hostsの設定はなくても良さそう？ （エラーの状況によっては当然試すべき選択肢の一つになるが．）
- hostnameが複数のIPを所持している場合は要注意

## 謎
- 他の人のPCと実験した時もclientの情報をmasterから確認できない事象があった．
もう少し根が深い問題かもしれない（有識者のアドバイスを求む）
- ここに記述していない要素が絡んでいる可能性？