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

Two nodes subscribed to each other that should count do not start unless I force a publisher

asked 2018-01-22 08:46:25 -0500

hstusnick gravatar image

Here is the code for the first node called /first which is subscribed to /second_channel and publishes to /first_channel

#!/usr/bin/env python
import rospy
from std_msgs.msg import Int32
rospy.init_node('second')
bar = rospy.Publisher('first_channel', Int32, queue_size=10)
count = 0
def callback(msg):
     count = msg.data
     print count

bar.publish(count+1)

sub = rospy.Subscriber('second_channel', Int32, callback)
bar.publish(count)
rospy.spin()

Here is the code for the second node called /second which is subscribed to /first_channel and publishes to /second_channel

#!/usr/bin/env python
import rospy
from std_msgs.msg import Int32
rospy.init_node('first')
foo = rospy.Publisher('second_channel', Int32, queue_size=10)
count = 0
def callback(msg):
    count = msg.data
    print count
    foo.publish(count+1)

sub = rospy.Subscriber('first_channel', Int32, callback)
rospy.spin()

When I start both of these in terminal, they are running without anything published and the rqt_graph command shows that they are subscribed to each other. But when I run: 'rostopic pub -1 /first_channel std_msgs/Int32 2' both nodes start passing the counter back and forth correctly. How can I make the passing back and forth start?

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
1

answered 2018-01-22 09:06:58 -0500

gvdhoorn gravatar image

updated 2018-01-22 09:10:06 -0500

Setting up subscriptions takes time.

Make both of them wait until there is at least one subscriber to their topic.

Use Publisher::getNumSubscribers() for that.

Some related questions:

  • #q11167: How do I publish exactly one message?
  • #q32952: With rospy, messages don't seem to be recieved if published soon after creating the publisher
  • #q82536: ROS misses some messages
edit flag offensive delete link more

Comments

2

Note also that there is no guarantee of delivery anywhere in ROS 1 pub-sub. So if you have data that absolutely must get to 'the other side', pub-sub is perhaps not what you should use.

gvdhoorn gravatar image gvdhoorn  ( 2018-01-22 09:15:26 -0500 )edit
0

answered 2018-01-22 09:43:02 -0500

updated 2018-01-30 15:07:13 -0500

I assume the missing indentation in /second for bar.publish(count+1) is just formatting error since you got the nodes to work.

#!/usr/bin/env python
import rospy
from std_msgs.msg import Int32
rospy.init_node('second')
bar = rospy.Publisher('first_channel', Int32, queue_size=10)
count = 0
def callback(msg):
     count = msg.data
     print count
     bar.publish(count+1)  #EDIT: Indented to be inside callback function.

bar.publish(count)
rospy.spin()

What happens if you start /first in a terminal

$ rosrun PACKAGE_NAME first

and then start /second afterwards?

$ rosrun PACKAGE_NAME second

If you are starting both nodes together (via roslaunch perhaps), then then /second is publishing before /first starts "listening in" since ROS Subscribers take some > 0 time to register with the ROS Master.

Check out this thread for more.

Two possible solutions:
1) Use latching - this will cache the last message sent and resend it to new Subscribers that connect to the Topic.

bar = rospy.Publisher('first_channel', Int32, queue_size=10, latch=True)

2) Use the get_num_connections method - this will return the number of other connections to your topic.

#!/usr/bin/env python
import rospy
from std_msgs.msg import Int32
rospy.init_node('second')
bar = rospy.Publisher('first_channel', Int32, queue_size=10)
count = 0
def callback(msg):
     count = msg.data
     print count
     bar.publish(count+1)  #EDIT: Indented to be inside callback function.

rate = rospy.Rate(10)  # 10hz
subscriber_connected = False
while not subscriber_connected:
  num_connections = bar.get_num_connections()
  if num_connections > 0:
    subscriber_connected = True
  rate.sleep()

bar.publish(count)
rospy.spin()

You might also need similar code in /first's callback function


Sources:
http://wiki.ros.org/rospy/Overview/Pu...
http://docs.ros.org/api/rospy/html/ro...
http://docs.ros.org/api/rospy/html/ro...

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2018-01-22 08:46:25 -0500

Seen: 659 times

Last updated: Jan 30 '18