web-dev-qa-db-ja.com

パブリッシャーとサブスクライバーの両方でrosノードを作成しますか?

私は現在、サブスクライバーとパブリッシャーの両方を持つPythonでROSノードを作成しようとしています。

コールバック内でメッセージが公開される例を見てきましたが、メッセージを「常に」公開し、その場合はコールバックを実行する必要があります。

これが私が今それをする方法です:

#!/usr/bin/env python

import rospy
from std_msgs.msg import Empty
from std_msgs.msg import String
import numpy as np

pub = rospy.Publisher('/status', String, queue_size=1000)

def callback(data):
    print "Message received"

def listener():

    rospy.init_node('control', anonymous=True)

    rospy.Subscriber('control_c', Empty, callback)
    rospy.spin()

if __name__ == '__main__':
    print "Running"
    listener()

では、どこに公開すればよいですか?

5
Carlton Banks

rospy.spin()を次のループに置き換えるだけです。

_while not rospy.is_shutdown():
    # do whatever you want here
    pub.publish(foo)
    rospy.sleep(1)  # sleep for one second
_

もちろん、スリープ時間を任意の値に調整できます(または完全に削除することもできます)。

このリファレンス によると、rospyのサブスクライバーは別のスレッドで実行されているため、spinをアクティブに呼び出す必要はありません。

Roscppでは(つまり、C++を使用している場合)、これは異なる方法で処理されることに注意してください。そこで、whileループでros::spinOnce()を呼び出す必要があります。

3
luator

さて、ここにはたくさんの解決策があると思います。pythonプロセスを利用することもできますが、私が提案しているのは ros Timer を使用したROSアプローチです。 =。

私はpythonでそれほど効率的ではありませんが、このコードはあなたに頭を上げるかもしれません。

#!/usr/bin/env python

import rospy
from std_msgs.msg import Empty
from std_msgs.msg import String
import numpy as np

last_data = ""
started = False
pub = rospy.Publisher('/status', String, queue_size=1000) 

def callback(data):
    print "New message received"
    global started, last_data
    last_data = data
    if (not started):
        started = True

def timer_callback(event):
    global started, pub, last_data
    if (started):
        pub.publish(last_data)
        print "Last message published"


def listener():

    rospy.init_node('control', anonymous=True)

    rospy.Subscriber('control_c', String, callback)
    timer = rospy.Timer(rospy.Duration(0.5), timer_callback)

    rospy.spin()    
    timer.shutdown()

if __name__ == '__main__':
    print "Running"
    listener()

ここで、コールバックはメッセージを更新し、タイマーは0.5秒ごとに起動し、最後に受信したデータを公開します。

このコードをテストするには、「/ contriol_c」に3秒ごとにデータを公開し、タイマーを0.5秒に設定します。/statusでエコーを開始します

$ rostopic echo /status

メッセージは2Hzのレートで公開されます。

お役に立てば幸いです。

4
Vtik