MQTT で subscribe 時にワイルドカードを使えるのを見て、ROS でも使えたらいいのに!と思ったので、
トピック名をワイルドカード指定して subscribe / publish できるユーティリティを作りました。
ros_wild の紹介
概要
ROS で使えるワイルドカード Publisher, Subscriber ユーティリティです。
https://github.com/yuma-m/ros_wild から clone して使えます。
$ git clone https://github.com/yuma-m/ros_wild.git /path/to/your/catkin_ws/src/ros_wild
$ cd /path/to/your/catkin_ws && catkin_make
使い方(コマンドライン)
ros_wild echo
$ rosrun ros_wild echo "トピック名の正規表現"
のように使います。
例えば、全トピックの内容を echo してみると、以下のような感じで、トピック名、メッセージの型とメッセージの中身が表示されます。
$ rosrun ros_wild echo ".+"
---
topic: /ultrasound_sensor
type: sensor_msgs/Range
header:
seq: 1
stamp:
secs: 1478776655
nsecs: 143582
frame_id: ultrasound_sensor
radiation_type: 0
field_of_view: 0.569999992847
min_range: 0.20000000298
max_range: 3.0
range: 0.600000023842
---
topic: /rosout
type: rosgraph_msgs/Log
header:
seq: 1
stamp:
secs: 1479382593
nsecs: 476881255
frame_id: ''
level: 4
name: /foo_pkg/bar_node
msg: this is example message
file: /home/foo/catkin_ws/src/foo_pkg/src/bar_node.cpp
function: main
line: 170
topics: ['/rosout', '/foo_pkg/example']
僕は同一種類の複数のセンサー値を確認する時によく利用します。
トピック毎にターミナルを開いていると、それだけで画面がいっぱいになってしまうので。
使い方 (Python)
利用例 (Subscriber)
/bool/.+
のようなトピックにまとめて subscribe して、 callback メソッドを設定する場合は、以下のような感じで書きます。
from ros_wild import Subscriber
def callback_bool(msg):
print(msg.data)
sub = Subscriber(r"/bool/.+", callback=callback_bool)
print("Subscribed topics are {}".format(sub.subscribed_topics))
実行結果
Subscribed topics are ['/bool/01', '/bool/02', '/bool/03']
True
True
False
...
rospy.Subscriber との違い
rospy.Subscriber
との違いは、2つ目の引数である data_class
が不要なことです。
- rospy の場合
rospy.Subscriber("/foo/bar", std_msgs.msg.String, callback_func, callback_args="hoge", ...)
- ros_wild の場合
ros_wild.Subscriber("/foo/bar", callback_func, callback_args="hoge", ...)
つまり、メッセージ型を指定せずにトピックに subscribe することが出来ます。
これは便利な半面、思わぬバグや例外を招く危険性があり、使い方には注意が必要です。
そこで register_callback
メソッドを利用して以下のように書いてあげることで、より安全な実装が可能です。
利用例 (register_callback)
トピック名の正規表現のみを指定して Subscriber
を作成し、 後から data_class
の種類毎に異なるコールバックを登録することが出来ます。
これにより、トピックのメッセージ型が想定した型と異なる場合のエラーを防ぐことができます。
from ros_wild import Subscriber
from std_msgs.msg import Bool, String
def callback_bool(msg):
print("bool is {}".format(msg.data))
def callback_string(msg):
print("string is {}".format(msg.data))
sub = Subscriber(r".+")
print("Subscribed topics are {}".format(sub.subscribed_topics))
sub.register_callback(Bool, callback_bool)
sub.register_callback(String, callback_string)
print("Topics with callback are {}".format(sub.topics_with_callback))
実行結果
Subscribed topics are ['/bool/01', '/rosout', 'rosout_agg', '/string/01']
Topics with callaback are ['/bool/01', '/strings/01']
bool is True
string is foo bar
...
利用例 (Publisher)
使い方は自分でもよく分かりませんが、一応 Publisher も作りました。
複数のロボットに同一のコマンドを送りたいとか、rviz で全 Range センサーに円錐を表示したいとか、そんな用途に使う...のかなぁ。
import rospy
from ros_wild import Publisher
from geometry_msgs.msg import Range
# publish to all Range topics
rospy.init_node("test")
pub = Publisher("/range/.+", queue_size=1)
pub.publish(Range(field_of_view=0.314, range=1.0))
今後の課題
パッケージに登録
まだ反映はされていませんが、ROS のパッケージリポジトリに登録しました。
最初はパッケージの登録の仕方が全然分からなかったのですが、bloom のチュートリアルに丁寧に記述されています。
基本的には上記チュートリアルの Releasing a package for the first time に則って、コマンドを実行していくだけで、releaseリポジトリへのコミットやrosdistroへのプルリクエストの作成を自動で行ってくれます。
ビルド自体はプルリクのマージから24-48時間以内に行われるのですが、debian パッケージとして apt でインストールできるようになるまでは数週間かかるようです。
機能拡張
今後の課題として以下の機能追加を考えています。
プルリク大歓迎です、お待ちしています!
-
Subsciber
,Publisher
作成時のメッセージ型による絞り込み - C++ 対応
- (機能拡張じゃないけど) ros_wild じゃなくて roswild に名前を変えたほうが良いかも...