ROS
python2.7
indigo
プログラム作成

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

はじめに

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

環境

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

プログラム作成

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

Publisher

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

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が出ます。

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

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

   6 def talker():
   7     pub = rospy.Publisher('chatter', String, queue_size=10)
   8     rospy.init_node('talker', anonymous=True)
   9     r = rospy.Rate(10)

重要なところなので1行ずつ解説していきます。

pub = rospy.Publisher('Topic名', , size)

初めにこのPublisherがどのTopicに何の型をどのくらいのサイズを指定しています。
今回のプログラムの場合だと、

  • Topic名前:chatter
  • 型:String
  • サイズ:10

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

rospy.init_node('ノード名', anonymous=True)

これはノード名の宣言をしていると考えてください。
最初のうちはおまじないだと思っていただいて構いません。

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

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

r = rospy.Rate(10)

これは1秒間に送る送信回数を定めています。
今回でいうと1秒間に10回ということになりますね。

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

そして最後です。

  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

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

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()が呼び出されます

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

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

   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()が呼び出されます。

  6 def callback(data):
  7     rospy.loginfo(rospy.get_caller_id()+"I heard %s",data.data)

今回の場合だと受け取ったデータを表示しています。
表示されるものは、

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

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

  12     rospy.spin()

おわりに

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