13
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Python】ROSのプログラムをPythonのclassを使ったらとても便利だった

Last updated at Posted at 2020-04-30

はじめに

最近少しずつROSを触り始めていて、Pythonでノードを実装するときに1つのノード内でpublisherとsubscriberを実装するにあたって困ったポイントがあったので紹介します。Pythonのクラスを使うことできれいにすることができました。
自分でパッケージが作れる程度のROSの知識と少しのオブジェクト指向の知識がある前提です。

実装例はこちら

やりたかったこと

このトピックのデータをsubscribeして、処理をして、あのトピックにpublishしたいな

ということがあると思います。調べ方が悪かったのか1つのノードで同時にsubscriberとpublisherを使うときはどうすればいいんだ、、、
と、かなりはまりました。

Pythonで実装するROSのPublisherとSubscriber

ROS.orgやよく紹介されているPublisherとSubscriberのチュートリアルでは以下のようになっていることが多いと思います。

Publisher(talkerとも)

rospy.Publisher で トピック名とメッセージのタイプを指定して、pub.publish()でpublish。

talker.py
# rospyとメッセージのimport
import rospy
import std_msgs.msg import String

def talker():
    pub = rospy.Publisher('chatter', String, queue_size=10)
    rospy.init_node('talker', anonymous=True)

    # 処理が続く
    
    pub.publish(data)

if __name__ == '__main__':
    try:
         talker()
    except rospy.ROSInterruptException: pass

Subscriber(listenerとも)

rospy.Subscriberでトピック名、データの型の指定、そしてcallback関数を指定してsubscribe後の処理をcallback関数で行う、という形になっています。

listener.py
# rospyとメッセージのimport
import rospy
from std_msgs.msg import String

def callback(data):
    # subscribeのcallback関数
    
def listener():
    rospy.init_node('listener', anonymous=True)

    rospy.Subscriber("chatter", String, callback)

    rospy.spin()
        
if __name__ == '__main__':
    listener()

Publish と Subscribeを同時に1つのノードで行う

チュートリアルが終わって、PublishとSubscribeの仕組みなどは一応理解しました。
じゃあ新しいノードを作ってPublishとSubscribe同時にやろうかなー。と思い、実装してみると rospy.Subscriberのcallback関数内でPublishすればいいのか、、?とコードをきれいにできずに悩みました。

その時にこの記事を見ていて、コードも拝見したところとてもきれいだったので参考にさせていただきました。
上記のチュートリアルではPythonのクラスを使っていませんでしたが、クラスを使うときれいに実装することができます。

__init__()でPublisher, Subscriberを作成し、callback関数、Publishする関数という流れで処理をしていきます。
実行する際にはmainの部分でクラスを作成すれば完了です!

test.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-

import rospy
from std_msgs.msg import String

import time

class testNode():
    def __init__(self):
        # Subscriberの作成
        self.sub = rospy.Subscriber('topic name', String, self.callback)
        # Publisherの作成
        self.pub = rospy.Publisher('topic name', String, queue_size=1)

    def callback(self, data):
        # callback関数の処理をかく

        self.publish(data)

    def publish(self, data):
        self.pub.publish(data)

    def function(self, data):
        # そのほかの処理もあったら書く

        return data

if __name__ == '__main__':
    rospy.init_node('test_node')

    time.sleep(3.0)
    node = testNode()

    while not rospy.is_shutdown():
        rospy.sleep(0.1)

おわりに

個人的にオブジェクト指向はとっかかりづらいと思っていましたが便利にきれいに書くことができました。
こんな感じでテンプレートを作ってくれている方もいますね!

"ros python publish subscribe 同じノード" とかの検索に欲しい情報なかったです。。。ROS初心者すぎるから自分が見当違いなことしているのですかね。なにかおかしかったら教えてください。

参考

ROSの機械学習用に、OpenPoseから関節角度をTopicで流すパッケージ作った
ROS講座31 python基礎
ROS のプログラムテンプレート
シンプルな配信者(Publisher)と購読者(Subscriber)を書く(Python)

13
15
1

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
13
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?