ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
1

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

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

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
4

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

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

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

1

Thank you. This was extremely helpful.

j1337 gravatar image j1337  ( 2017-07-24 12:47:35 -0600 )edit
4

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 image jayess  ( 2017-08-09 16:16:46 -0600 )edit

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

Thanks for the advice.

Ruben Alves gravatar image Ruben Alves  ( 2017-10-09 07:25:23 -0600 )edit

THANK YOU!

AlessandroSaviolo gravatar image AlessandroSaviolo  ( 2020-03-19 11:55:12 -0600 )edit
2

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

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 -0600

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

Question Tools

2 followers

Stats

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

Seen: 10,954 times

Last updated: Oct 09 '17