Ask Your Question
0

How can I publish exactly once when the node is run?

asked 2017-07-24 04:04:06 -0500

j1337 gravatar image

I want to publish a single /initialpose message when a node is run. How can I make sure it's only published once?

This is what I have:

#!/usr/bin/env python

import rospy
from geometry_msgs.msg import Pose, PoseWithCovarianceStamped
from std_msgs.msg import Header
from numpy import matrix

class PoseChange:
    def __init__(self):
        self.msg = PoseWithCovarianceStamped()
        rospy.init_node("pose_change", anonymous=True)
        rospy.Subscriber('/pose', Pose, self.callback)
        self.pub = rospy.Publisher('/initialpose', PoseWithCovarianceStamped, queue_size=3)

    def callback(self, data):
        self.msg.header = Header()
        self.msg.header.stamp = rospy.Time.now()
        self.msg.header.frame_id = "map"
        self.msg.pose.pose = data
        self.msg.pose.covariance = matrix([[0.09, 0, 0, 0, 0, 0], 
                                           [0, 0.09, 0, 0, 0, 0],
                                           [0, 0, 0.09, 0, 0, 0],
                                           [0, 0, 0, 0.25, 0, 0],
                                           [0, 0, 0, 0, 0.25, 0],
                                           [0, 0, 0, 0, 0, 0.25]])

    def run(self):
        self.pub.publish(self.msg)

if __name__ == "__main__":
    try:
        m = PoseChange()
        m.run()
    except rospy.ROSInterruptException:
        raise e

However, this never publishes when run. The /pose topic it's listening to is continuously publishing at 50 Hz.

edit retag flag offensive close merge delete

3 Answers

Sort by ยป oldest newest most voted
2

answered 2017-07-24 08:02:03 -0500

updated 2017-10-09 07:24:27 -0500

Hi @j1337,

ROS takes some time to notify the publishers and subscribers of the topics. So, you have two options:

1 - Sleep some seconds before publish the first message. In the "main" part of your code could be done like:

if __name__ == "__main__":
    try:

        from time import sleep
        print 'Sleeping 10 seconds to publish'
        sleep(10)
        print 'Sleep finished.'

        m = PoseChange()
        m.run()
    except rospy.ROSInterruptException:
        raise e

2 - Make sure that there are subscribers (using get_num_connections) when you starts publishing. In the "main" part of your code it would be like:

if __name__ == "__main__":
    try:
        m = PoseChange()
        rate = rospy.Rate(10)  # 10hz
        while not rospy.is_shutdown():
            connections = m.pub.get_num_connections()
            rospy.loginfo('Connections: %d', connections)
            if connections > 0:
                m.run()
                rospy.loginfo('Published')
                break
            rate.sleep()

    except rospy.ROSInterruptException, e:
        raise e

If you still have doubts, I made a video ( https://youtu.be/BGV6DI_PItA ) that shows how to solve exactly this question by checking the subscribers.

edit flag offensive delete link more

Comments

Thank you. This was extremely helpful.

j1337 gravatar imagej1337 ( 2017-07-24 12:47:35 -0500 )edit
3

Why not explain exactly how to solve this question here? The problem with linking to a video for more steps is that now part of the answer is external and this answer is not self-contained. What if the video gets taken down?

jayess gravatar imagejayess ( 2017-08-09 16:16:46 -0500 )edit

Ok, now the answer is self contained, @jayess.

Thanks for the advice.

Ruben Alves gravatar imageRuben Alves ( 2017-10-09 07:25:23 -0500 )edit
2

answered 2017-07-24 08:31:05 -0500

Airuno2L gravatar image

I think the problem is related to this similar question : "How do I publish exactly one message?"

The problem there was that the message was being published before the publisher or it's subscriber had time to setup all the way, the solution was to wait for a subscriber to subscribe before publishing (in rospy that would use get_num_connections.)

edit flag offensive delete link more
1

answered 2017-07-24 07:56:49 -0500

I think it's a known problem. The thing is that when you create a publisher, it's not connect yet to ROS master server. That's why you are not able to publish the message. You can try to "sleep" for a while, like 1~5 seconds, and the publisher will be connected.

If you need to publish something just once, I'd recommend you to use a ROS service.

You can check other related questions:

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

2 followers

Stats

Asked: 2017-07-24 04:04:06 -0500

Seen: 3,435 times

Last updated: Oct 09 '17