ROS TeleopでAndroid-PC間を無線通信してみよう


# ROS Teleopって？
ROS TeleopはOSRF(Open Source Robotics Foundation)からリリースされているROSで動作するロボットの操作用アプリです。
![0.jpg](https://qiita-image-store.s3.amazonaws.com/0/57052/95a8e503-bae1-d370-2854-c88d678623aa.jpeg)
そもそもROSってなにかって？？
ROSというのはRobot Operating Systemの略です。
Robot OSと言ったりもしますが**OSではありません。**
ロボットのためのソフトウェアを開発するためのビルドツールです。
さらには、ソフトウェアプロセス同士が通信するためのライブラリも用意してくれます。
とにかく**OSではありません。**ROSに関しては日本語でもWikiがありますので
[ここ](http://wiki.ros.org/ja)をチェック！！

# ROSのいいところ

ROSの一番いいところはプロセスとプロセスの通信を簡単な記述で
自動的に行ってくれるところだと思っています。(あくまで個人的に)
基本的にROSの通信は以下のようなシチュエーションでやることになるかと思います。

- ひとつのシステムのなかでさまざまな制御プロセスが通信しあう
- 母艦PC(サーバ)があり、それを介して複数のクライアントが通信しあう

今回は後者のほうに似ています。クライアントであるROS Teleopから入力された
リモコンの命令をPCで受け取るということをします。

# ROSの通信スタイル

ROSではPublish/Subscribeメッセージングというものをしています。
![image](https://qiita-image-store.s3.amazonaws.com/0/57052/eb941eaa-1e59-fa9a-97cc-873e580316a0.png)
各要素の役目を簡単に説明すると…

- Message：ROSで使用するデータの呼び名。中身のデータ構造はROSにあらかじめ用意されているものか独自の定義が可能
- Topic：メッセージを分類する系統、メッセージの通信経路
- Publisher：メッセージを特定のトピックへ配信する人
- Subscriber：特定のトピックを購読対象として登録しメッセージを受信する人

ざっとこんな感じでしょうか。Publisher側は誰がSubscibeしてるだとかは気にすることないし
Subscribe側も登録してあるTopicの中身を読むだけなので互いに疎な関係です。
そのため、各ノード(機能)の追加・変更が用意に行えます。

# ROS Teleopを起動してみた。
さて、そろそろ本題に入りましょう。
当初、androidとPCをROSで通信するといってもandroidでROSが
動くかわからないしどうしようとか思っていました。

とりあえずandroidのplaystoreで”ROS"と検索すると
なんと出てくるではありませんか**ROS Teleop**が！！
![yaruo_585.png](https://qiita-image-store.s3.amazonaws.com/0/57052/163ef38d-65be-d437-533c-108bde92052a.png)
ということでまずAndoroid側でROS Teleopを起動してみました。
(スクショが手元にないので後で貼ります)

起動すると、roscore(ROSマスターサービスのことroscoreの詳細は[ここ](http://wiki.ros.org/ja/roscore))の動作しているPCのホストアドレスとポート番号を打てと言われます。
それぞれ打ち込んで***connect***を押すと***connected!***とかでます。

？？？？
![yaruo_10.gif](https://qiita-image-store.s3.amazonaws.com/0/57052/83cba744-c0f9-f54f-c83b-0b2f16ecf359.gif)

となりました。つまりROS Teleopが何しているかわからないし、
本当につながっているかどうかも分からなかったわけですね。

# ROS Teleopはどこへ何をPublishしている？
ROS Teleopが本当に現在起動中のroscoreに登録されているか知る必要がありました。
そこでROSにはとっても便利なアプリケーションがあるんです。
その名も**rosgraph**。
このアプリケーションは現在起動中のroscoreに登録されてあるPublisher、Subscriberを
GUIで覗くことができる優れものなのです。どんな風に見えるかというとこんな感じです↓
![rosgraph.png](https://qiita-image-store.s3.amazonaws.com/0/57052/f39fbd9d-db9a-f9d1-6b51-a83546ce25c9.png)

注目して欲しいのは***android***という四角。この中では**android**というパッケージで
2つのノードが登録されていました。

前述した通りPublisherとSubscriberは互いに知り合いである必要はないのですが
**Topic**と**メッセージのデータ構造**だけはどちらも等しくなければなりません。
つまりAndroidとPC間で通信するためには**ROS Teleop**(Publisher)が
**どこへ(どのTopicへ)何を(どんなデータ構造のメッセージを)Publishしているか**
把握する必要がありました。

こいつら調べればなんとかなるのでは！と思ってググってみました。[結果](http://wiki.ros.org/android_teleop)↓

***/android/virtual_joystick***

- Publishing
 - Topic: /cmd_vel
 - Type: geometry_msgs/Twist
- Subscribing
 - Topic: /odom
 - Type: nav_msgs/Odometry

***/android/camera_view***

- Publishing
 - None
- Subscribing
 - Topic: (robot_name)/application/camera/rgb/image_color/compressed_throttle
 - Type: sensor_msgs/CompressedImage

動作しているノードはvirtual_joystickとcamera_viewというノードの2つでした。今回は
PC側へ操作するためのメッセージをPublishしているであろう***virtual_joystick***に注目します。

Publishingの項目をみてみると

```
・ Publishing
 ・ Topic: /cmd_vel
 ・ Type: geometry_msgs/Twist
```
これはつまり何を意味するかというと**cmd_vel**というトピックに**geometry_msgs::Twist**という型のメッセージを送っているということになります。
ということは***cmd_vel***をsubscribeすれば何かわかる！と考えつきました。

# geometry_msgs::Twistについて
さて、cmd_velをSubscribeするとはいえこのトピックに配信されるメッセージの
データ構造がわからなければどうしようもありません。ということで調べてみます。
以下のファイルを覗いてみるとこの型の定義やメンバ変数などがわかります。

```
/opt/ros/hydro/include/geometry_msgs/Twist.h
```
＊ROSメッセージについては以下の記事も書きましたのでご参照ください。
[ROSで32bit整数型の配列をメッセージとして使用する](http://qiita.com/kazuyamashi/items/b64cc546da816c6f20d9)
geometry_msgs/Twist.hの中身を調べるとデータ構造はいかに示すようなものでした。
![image](https://qiita-image-store.s3.amazonaws.com/0/57052/9ea78094-dd71-556f-43b5-011fa0befb3d.png)
vector3クラスのオブジェクトlinearとangularに
それぞれfloat型のメンバ変数がそれぞれx、y、zあるのがわかります。

# さぁ通信であります
回りくどいことたくさん説明してきましたが、結局はPCとandroidは接続されていて
データの中身がわからないという状況だったわけです。

ということでcmd_velを購読してgeometry_msgs::Twist型のメッセージを購読してみました！
(ソースコード今は手元にないので後で公開します)
ROS Teleopは以下のようなインターフェイスで操作できます。右にある矢印のついたボタンを
スライドさせてアナログルティックのように方向の操作を行えるようです。
![unnamed (1).png](https://qiita-image-store.s3.amazonaws.com/0/57052/d7370ddf-6f21-dfae-be90-5f4cfde98c31.png)
(playstoreから引用。カメラ画像はホスト側からPublishしないと表示されない)



```
#linearの結果
linear x = 0.668243, y =-0.000000, z = 0.000000
linear x = 0.865166, y =-0.000000, z = 0.000000
linear x = 1.000000, y =-0.000000, z = 0.000000
linear x = 1.000000, y =-0.000000, z = 0.000000
linear x = 0.944478, y =-0.000000, z = 0.000000
linear x = 0.831879, y =-0.000000, z = 0.000000
linear x = 0.731174, y =-0.000000, z = 0.000000
linear x = 0.654750, y =-0.000000, z = 0.000000
```

```
#angularの結果
angular x = 0.000000, y =0.000000, z = -0.010223
angular x = 0.000000, y =0.000000, z = -0.000000
angular x = 0.000000, y =0.000000, z = 0.104223
angular x = 0.000000, y =0.000000, z = 0.213782
angular x = 0.000000, y =0.000000, z = 0.246961
angular x = 0.000000, y =0.000000, z = -0.000000
angular x = 0.000000, y =0.000000, z = -0.227378
angular x = 0.000000, y =0.000000, z = -0.327994
```
写真に示すインターフェイス上で操作をしながらログを取ってみました。
![image](https://qiita-image-store.s3.amazonaws.com/0/57052/42c2e0c8-38f7-7860-a9de-db97aec76da8.png)
スティックを縦に上下すると**linear.x**の値が変動し、
スティックを円状に動かすと**angular.x**の値が変動しました。
他のパラメータに関しては特に変動はみられなかったと思います。

一応これでAndroid-PC間の通信ができて、中身のデータもみれました。

# まとめ

- ROS TeleopはROSのロボット操作用アプリケーション
- rosgraphは便利
- PC-android間の通信はroscoreの起動してるホスアドレスとポート番号さえわかれば特別な設定はいらない
- データの中身をみるためにはメッセージングに使うTopicとメッセージのデータ構造を知る必要がある

# おわりに
なんだかタイトルの割には拍子抜けな感じで終わってしまった気がします笑
またわかったことあればちょくちょく記事にしていきたいと思います。