ROSでの超基本的なプログラム作成

#はじめに
この記事ではROSでの超基本的なプログラム作成および解説を行います。
これすらもできなければROSで何もすることは出来ないでしょう。
ROSを利用するには何を記述すればいいのかを把握してください。

##環境
ROS : indigo
OS  : Ubuntu14.04
言語 : python2.7
参考ページ : http://wiki.ros.org/ja/ROS/Tutorials/WritingPublisherSubscriber%28python%29

#プログラム作成
とりあえずPublisherとSubscriberのプログラムを書いたのちに、必要な点について実行順に説明していきます。

##Publisher
初めに送り手側のプログラムとなります。

```python:talker.py
   1 #!/usr/bin/env python
   2 # coding: UTF-8
   3 import rospy
   4 from std_msgs.msg import String
   5 
   6 def talker():
   7     pub = rospy.Publisher('chatter', String, queue_size=10)
   8     rospy.init_node('talker', anonymous=True)
   9     r = rospy.Rate(10) 
  10     while not rospy.is_shutdown():
  11         str = "hello world %s"%rospy.get_time()
  12         rospy.loginfo(str)
  13         pub.publish(str)
  14         r.sleep()
  15 
  16 if __name__ == '__main__':
  17     try:
  18         talker()
  19     except rospy.ROSInterruptException: pass
```

##解説
最初にmain()が実行されたのちに、talker()が呼び出されます。
何らかの影響で呼び出せなかった場合はROSInterruptExceptionが出ます。

```python
  16  if __name__ == '__main__':
  17     try:
  18         talker()
  19     except rospy.ROSInterruptException: pass
```

ここがPublisherの基本的な宣言となります。

```python
   6 def talker():
   7     pub = rospy.Publisher('chatter', String, queue_size=10)
   8     rospy.init_node('talker', anonymous=True)
   9     r = rospy.Rate(10)
```
重要なところなので１行ずつ解説していきます。

```python
pub = rospy.Publisher('Topic名', 型, size)
```
初めにこのPublisherがどのTopicに何の型をどのくらいのサイズを指定しています。
今回のプログラムの場合だと、

+ Topic名前：chatter
+ 型：String
+ サイズ：10

といったようになります。

```python
rospy.init_node('ノード名', anonymous=True)
```
これはノード名の宣言をしていると考えてください。
最初のうちはおまじないだと思っていただいて構いません。

重要なのはrospy.init_nodeは１ノード１回しか使えないということです。
また最も奥が深く、今回は引数を２つしか挙げていませんが実際は他にあと３つほど引数を持たせることにより、ROSの拡張性を高めることができます。

興味がある方は是非モジュールソースを読んでみましょう。
暇だったら後日解説を行います。

```python
r = rospy.Rate(10)
```
これは１秒間に送る送信回数を定めています。
今回でいうと１秒間に１０回ということになりますね。

私は研究するにあたりここをいじることで、
１回送信する速度を上げたり下げたりの調整を変数を用いて行っていました。

そして最後です。

```python
  10     while not rospy.is_shutdown():
  11         str = "hello world %s"%rospy.get_time()
  12         rospy.loginfo(str)
  13         pub.publish(str)
  14         r.sleep()
```

while not rospy.is_shutdown()はCtr-Cが押されるまでwhileされます。
rospy.loginfo(str)はなくてもいいです。
単純にPublishしてる感を出すだけです。

そしてpub.publish(str)によりstrをtopicにPublishしています。
今回は"hello world 現在時間"がPublishされているはずです。

r.sleep()により処理が終わったらwhile戻します。
while、pub、sleepはセットだと考えて良いでしょう。

##Subscriber
次に受け手側のプログラムです。
めちゃくちゃ短いです。

```python:listener.py
   1 #!/usr/bin/env python
   2 # coding: UTF-8
   3 import rospy
   4 from std_msgs.msg import String
   5 
   6 def callback(data):
   7     rospy.loginfo(rospy.get_caller_id()+"I heard %s",data.data)
   8     
   9 def listener():
  10     rospy.init_node('listener', anonymous=True)
  11     rospy.Subscriber("chatter", String, callback)
  12     rospy.spin()
  13         
  14 if __name__ == '__main__':
  15     listener()
```

##解説
main()によってlistener()が呼び出されます

```python
  14 if __name__ == '__main__':
  15     listener()
```

ここはかなりPublisherの宣言と似ていますね。
ですので軽く解説するだけにします。

```python
   9 def listener():
  10     rospy.init_node('listener', anonymous=True)
  11     rospy.Subscriber("chatter", String, callback)
```
rospy.init_nodeでノード名宣言
ropy.Subscriberによって引数を前から

+ chatter : Subscribeしたいtopic名
+ String : Subscribeする型
+ callback : 呼び出す関数

したがって次にcallback()が呼び出されます。

```python
  6 def callback(data):
  7     rospy.loginfo(rospy.get_caller_id()+"I heard %s",data.data)
```
今回の場合だと受け取ったデータを表示しています。
表示されるものは、

+ SubscriberのID
+ Subscribeしたデータの中身

すべての処理が終了するとrospy.spin()によって待機状態に戻ります。

```python
  12     rospy.spin()
```

#おわりに
次回は今回作成したプログラムを実行しましょう。
簡単な便利機能も紹介します。