独自のメッセージファイルの作り方

ROSチュートリアルの流れ

はじめに

この章では、独自のメッセージファイルを作成し、ROSで使用する方法を解説します。
独自のメッセージファイルをROSで使用するためには、 CMakeLists.txtpackage.xmlというファイルを編集します。
この2つのファイルは、ROSチュートリアルのROSパッケージの作り方でパッケージを作成したときに自動で出来たファイルです。 package.xmlはパッケージの設定が書いてあり、CMakeLists.txtはビルドする際の設定が書いてあります。
トピックの書き方ではUNIX時間を配信しましたが、この章では現在日時を送るものに改良したいと思います。
まず、現在日時を送るためのメッセージファイルから作成します。

メッセージファイルの作り方

メッセージファイルはmsgディレクトリに置きます。 無い場合はmsgディレクトリを作りましょう。
roscd ros_tutorial/
mkdir msg
日付と時間を送るためのメッセージをDate.msgとします。
vim msg/Date.msg
Date.msgの中は以下のように書きます。
int32 date
float64 time
1行目はint型32ビットのdateで、2行目はFloat型のtimeという名前にしています。

ここからが重要です。

まずpackage.xmlを編集します。

roscd ros_tutorial/
vim package.xml
40行目の<build_depend>message_generation</build_depend>と、46行目の<exec_depend>message_runtime</exec_depend>のコメントアウトを外します。

次にCMakeLists.txtを編集します。

vim CMakeLists.txt
10行目のfind_packageに、14行目ようにmessage_generationを追加します。
51行目のadd_message_filesのコメントアウトを外し、53行目にDate.msgを追加する。
71行目から74行目のgenerate_massagesのコメントアウトを外します。
108行目のcatkin_packageCATKIN_DEPENDSのコメントアウトを外し、message_runtimeを追加します。
catkin_wsに移動しcatkin_makeを行います。
cd ~/catkin_ws
catkin_make
これで、ビルドが通れば正常にDate.msgが作成されたはずです。
確認してみましょう。 以下のように打ち込み、
rosmsg show ros_tutorial/Date
以下のように表示されたら完了です。
int32 date
float64 time

プログラムを改良

先程作成したメッセージファイルを使用して、プログラムを改良しましょう。 まずros_tutorialに移動します。
roscd ros_tutorial

パブリッシャ

time_pub2.pyという名前にします。
vim scripts/time_pub2.py
time_pub2.py
#!/usr/bin/env python
import rospy
from ros_tutorial.msg import Date
from datetime import datetime
def talker():
l = []
d = Date()
rate = rospy.Rate(10)
while not rospy.is_shutdown():
d.date = ''
d.time = ''
now = datetime.now()
l = str(now)
for i in range(0,10):
d.date += l[i]
for i in range(11,25):
d.time += l[i]
d.date = int(d.date.replace('-', ''))
d.time = float(d.time.replace(':',''))
pub.publish(d)
rate.sleep()
if __name__ == '__main__':
rospy.init_node('time_pub')
pub = rospy.Publisher('Date_and_Time', Date , queue_size=1)
talker()
rospy.spin()
実行権限を与えます。
chmod +x scripts/time_pub2.py

コード解説

#!/usr/bin/env python
import rospy
from ros_tutorial.msg import Date
from datetime import datetime
新たに、先程作成したDateをインポートしています。また現在日時を取得するために必要なモジュールdatetimeもインポートしています。
def talker():
talkerという名前の関数を定義しています。
l = []
d = Date()
l = []はリストの初期化を行っています。
d = Date()はメッセージのDatedという名前でインスタンス化しています。
rate = rospy.Rate(10)
while not rospy.is_shutdown():
シャットドウンされるまで10Hzでwhile内のコードを実行します。
d.date = ''
d.time = ''
Date.msgdatetimeを初期化しています。
now = datetime.now()
l = str(now)
現在日時を取得し、配列にしてlに渡しています。
for i in range(0,10):
d.date += l[i]
for i in range(11,25):
d.time += l[i]
for文で配列の0~10番目を日付としてdateに渡しています。同様に配列の11~25番目を時間としてtimeに渡しています。
しかし、このままだと-:の文字が含まれているため、
d.date = int(d.date.replace('-', ''))
d.time = float(d.time.replace(':',''))
pub.publish(d)
rate.sleep()
replaceを用いて-:の文字を取り除き、int型とfloat型にしてパブリッシュしています。

サブスクライバ

サブスクライバはほとんど変わらないため、time_sub.pyをコピーし、time_sub2.pyという名前で保存しましょう。
cp scripts/time_sub.py scripts/time_sub2.py
vim scripts/time_sub2.py
3行目と6行目、10行目に変更を加えます。
time_sub2.py
#!/usr/bin/env python
import rospy
from ros_tutorial.msg import Date #changed
def callback(message):
print("date : %d , time : %f" % (message.date,message.time) ) #changed
if __name__ == "__main__":
rospy.init_node('time_sub')
sub = rospy.Subscriber('Date_and_Time', Date , callback) #changed
rospy.spin()
chmod +x scripts/time_sub2.py

コード解説

変更点だけ解説していきます。
from ros_tutorial.msg import Date
Dateをインポートしています。
print("date : %d , time : %f" % (message.date,message.time) )
dateはint型のため%dtimeはfloat型のため%fで表示しています。
sub = rospy.Subscriber('Date_and_Time', Date , callback)
トピック名をメッセージの型をDateに変更しています。

実行方法

それぞれ別のターミナルで実行しましょう。
roscore
rosrun ros_tutorial time_pub2.py
rosrun ros_tutorial time_sub2.py

実行結果

$ rosrun ros_tutorial time_sub2.py
date : 20181108 , time : 224947.85194
date : 20181108 , time : 224947.95175
date : 20181108 , time : 224948.05449
date : 20181108 , time : 224948.15677
date : 20181108 , time : 224948.25193
date : 20181108 , time : 224948.35248
date : 20181108 , time : 224948.45211
date : 20181108 , time : 224948.55515
date : 20181108 , time : 224948.6551
date : 20181108 , time : 224948.75641
date : 20181108 , time : 224948.85298
date : 20181108 , time : 224948.9519
date : 20181108 , time : 224949.05382
date : 20181108 , time : 224949.15634
date : 20181108 , time : 224949.25606
date : 20181108 , time : 224949.35245
date : 20181108 , time : 224949.45277
date : 20181108 , time : 224949.55351
date : 20181108 , time : 224949.65224
date : 20181108 , time : 224949.75421
date : 20181108 , time : 224949.8536
date : 20181108 , time : 224949.95257
2018年11月08日の22時49分49.95257秒を指しています。