LoginSignup
9
3

More than 5 years have passed since last update.

ROS の wildcard Subscriber / Publisher を作った

Posted at

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 に名前を変えたほうが良いかも...
9
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
3