私は現在、サブスクライバーとパブリッシャーの両方を持つ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()
では、どこに公開すればよいですか?
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()
を呼び出す必要があります。
さて、ここにはたくさんの解決策があると思います。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のレートで公開されます。
お役に立てば幸いです。