トピックの書き方

ROSチュートリアルの流れ

はじめに

ROSでは、使用するプログラム言語として主にPythonC++が用いられますが、このチュートリアルではPythonを使用したいと思います。
ROSの通信方式は主にトピック、サービス、アクションの3つあります。この章では最も使用されることが多いトピックから説明していきます。
まず、トピックで使用されるパブリッシャ(publisher)とサブスクライバ(subscriber)ついて説明します。
この2つは、ノード間をトピックを介してデータをやり取りするときに使用され、 簡易的に説明するとこうなります。
  • パブリッシャ : データを配信
  • サブスクライバ : データを受け取る
やり取りするデータはメッセージの指定された型に入れ配信されます。
詳しくはROSでよく使用する用語を御覧ください。
メッセージは、標準パッケージのstd_msgsの他に、自分で定義することもできます。
それではパブリッシャとサブスクライバを書いていきましょう。
まずROSパッケージの作り方で作成したros_tutorialに移動します。ディレクトリ移動にはroscdという便利なコマンドがあります。このコマンドはどこからでも指定のパッケージに移動できます。
詳しくはよく使用するROSコマンドのroscdを御覧ください。
roscd ros_tutorial
Pythonのプログラムはscriptsディレクトリの中で作成します。 scriptsディレクトリが無い場合は作成しましょう。
mkdir scripts

パブリッシャ

今回は、現在時刻を送るプログラムを書いていきます。
プログラム名はtime_pub.pyとします。
vim scripts/time_pub.py
time_pub.py
#!/usr/bin/env python
import rospy
from std_msgs.msg import Float64
rospy.init_node('time_pub')
pub = rospy.Publisher('UnixTime', Float64 , queue_size=1)
rate = rospy.Rate(10)
while not rospy.is_shutdown():
now = rospy.get_time()
pub.publish(now)
rate.sleep()
書いたプログラムには以下のコマンドを実行してください。
chmod +x scripts/time_pub.py
これはプログラムに実行権限を与えています。
Pythonの場合は、プログラムに対しchmod +x <プログラム名>を行い、一度実行権限を与えれば、変更のたびにcatkin_makeは必要ありません。

コード解説

#!/usr/bin/env python
Pythonでプログラムを書くときのお約束で、シバンといいます。
import rospy
rospyというモジュールをインポートしています。rospyはPythonでROSを扱うときに使用します。
from std_msgs.msg import Float64
std_msgsFloat64という型のメッセージをインポートしています。Float64は浮動小数点変数の64ビットという意味です。
rospy.init_node('time_pub')
time_pubというノードを定義しています。
pub = rospy.Publisher('UnixTime', Float64 , queue_size=1)
UnixTimeというトピック名、Float64というメッセージの型、queue_sizeが1のパブリッシャを定義しています。queue_sizeはバッファの数で、10 [Hz]周期でパブリッシュするときは1でも大丈夫です。10 [Hz]以上の周期でパブリッシュするときや複数のメッセージをパブリッシュするときは大きい値にするといいでしょう。
rate = rospy.Rate(10)
while not rospy.is_shutdown():
now = rospy.get_time()
pub.publish(now)
rate.sleep()
now = rospy.get_time()nowという変数に現在のUnixTimeを代入しています。
pub.publish(now)nowをパブリッシュしています。
シャットダウンされるまで10 [Hz] 周期で上記の2つを行っています。

サブスクライバ

次にサブスクライバを書きます。
サブスクライバはtime_sub.pyとします。
vim scripts/time_sub.py
time_sub.py
#!/usr/bin/env python
import rospy
from std_msgs.msg import Float64
def callback(message):
print(message.data)
if __name__ == "__main__":
rospy.init_node('time_sub')
sub = rospy.Subscriber('UnixTime', Float64 , callback)
rospy.spin()
パブリッシャと同様に以下のコマンドを実行してください。
chmod +x scripts/time_sub.py

コード解説

#!/usr/bin/env python
import rospy
from std_msgs.msg import Float64
ここまでパブリッシャと同じです。
def callback(message):
print(message.data)
callback関数を定義しています。
message.dataというのは、Float64の中のdataを参照するという意味です。
if __name__ == "__main__":
Pythonではプログラムがインポートされた場合、関数を自動で実行してしまいますが、 このif文内に書いた関数は自動で実行されなくなります。
rospy.init_node('time_sub')
time_subというノードを定義しています。
sub = rospy.Subscriber('UnixTime', Float64 , callback)
サブスクライバの宣言をしています。
パブリッシャがUnixTimeという名前のトピック、Float64という型で配信しているため、こちらも合わせる必要があります。
最後のcallbackは、受け取ったFloat64型のデータを渡す関数を書く部分であり、今回はcallback関数に渡しています。
rospy.spin()
プログラムを終了させないようにしています。

相関図

実行方法

それぞれ別のターミナルでそれぞれを起動します。
roscore
rosrun ros_tutorial time_pub.py
rosrun ros_tutorial time_sub.py

実行結果

time_sub.pyを起動したとき、以下のように出力されたら正常に動作しています。
$ rosrun ros_tutorial time_sub.py
1540459203.78
1540459203.88
1540459203.98
1540459204.08
1540459204.18
1540459204.28
1540459204.38
1540459204.48
1540459204.58
1540459204.68
1540459204.78
1540459204.88
1540459204.98
1540459205.08
1540459205.18
 ︙
出力されているこの数値はUNIX時間というもので、 1970年1月1日午前0時0分0秒からの経過秒数になります。
Copy link
On this page
ROSチュートリアルの流れ
はじめに
パブリッシャ
コード解説
サブスクライバ
コード解説
相関図
実行方法
実行結果