Avoiding a circular dependency in a ROS node
how can I publish and subscribe simultaneously on 2 different topics. I have two nodes A and B. A is located in ROS and i am using roslibpy to communicate with B. A publishes first on custom_topic1, B subscribes this, processes it and publishes on custom_topic2 which is then subscribed by A. A processess this again and publishes back on custom_topic1. and then it works in the loop.
I am somehow getting stuck in an infinite loop.
I would want to do something like this :
ros = roslibpy.Ros(host='...', port=9090)
publisher = Topic(ros, '/custom_topic1', 'ros_tutorials/Msg2')
subscriber = Topic(ros, '/custom_topic2', 'ros_tutorials/Msg1')
def publish:
publisher.publish(Message({'x': 123, 'y': [{'a': 1, 'b': 2, 'c': 3.14, 'e': 7.23, 'f': 2.353}]}))
subscriber.subscribe(receive_message)
def receive_message(message):
a = message['j']
print('a')
Tosimplify it , A -> custom_topic1 -> B -> custom_topic2 -> A -> custom_topic1
(so, A will enter in a loop because it's subscribed to custom_topic2 but publishes that again to custom_topic1).
So this is entering a circular dependency. Any ideas how to avoid it ?
EDIT :
Here is the code for Node1:
import rospy
import sys
import time
from std_msgs.msg import String
from ros_tutorials.msg import VehicleControl
from ros_tutorials.msg import DetectedObjectList
Lane_Width = 2
Brake_Distance = 30
class DemoFunction():
def __init__(self):
print("entering constructor")
#super().__init__('custom_talker')
self.sub = rospy.Subscriber('objects',DetectedObjectList, self.object_callback)
self.pub = rospy.Publisher('control',VehicleControl, queue_size = 10)
def object_callback(self, msg):
print ("entering callback")
for obj in msg.objects:
if self.obj_in_path(obj):
print("Found object in path: \n{}".format(obj))
self.send_brake_message()
else:
self.normal_driving()
break
def send_brake_message(self):
print("entering brake function")
self.pub.publish(VehicleControl(accelerator_pedal = 0.0, brake_pedal = 1.0, steering_wheel = 0.0, gear = 1.0))
def normal_driving(self):
print("entering normaldriving function")
self.pub.publish(VehicleControl(accelerator_pedal = 0.0, brake_pedal = 0.0, steering_wheel = 0.0, gear = 1.0))
def obj_in_path(self,obj):
print("entering ovbect in path function")
if (abs(obj.y) < Lane_Width and (obj.x < Brake_Distance)):
return True
return False
if __name__ == '__main__':
print("entering main")
rospy.init_node('aeb_node')
try:
DemoFunction()
print("entering Try")
rospy.spin()
except rospy.ROSInterruptException:
print("exception thrown")
pass
This is the code for node 1 which is using ROS_bridge.
def start_sending():
print('entering start_sending function')
while True:
#print('entering while true')
if not ros.is_connected:
break
#print('not entering break and should advertise the publisher')
publisher.advertise()
publisher.publish(Message({'id': int(10), 'objects' : [{'id':int(1),'x':2,'y':1,'v_rad':3,'a_rad':4}]}))
#print('Object found : x distance is : ')
#time.sleep(0.1)
def receive_message(message):
print('entering receive_message')
#assert message['data'] == 'hello world' , 'Unexpected message content'
#LOGGER.info('Received message : %d', message['brake_pedal'])
a = message['brake_pedal']
print('brake_pedal : ', a)
def start_receiving():
print('entering start receiving')
listener.subscribe(receive_message)
listener.subscribe(print)
publisher.unadvertise()
ros.on_ready(lambda: print('Is ROS connected ?', ros.is_connected))
ros.on_ready(start_sending, run_in_thread=True)
#ros.on_ready(start_receiving, run_in_thread=True)
ros.get_topics(print)
ros.get_nodes(print)
ros.run_forever()
if __name__ == '__main__':
print('main')
import logging
#logging.basicConfig ...
Wouldn't service be sufficient for your cause? ROS service provides one-on-one communication where a "client" sends some data to the "service" and the service sends some data back to the client.
could be one use case, but i think must also work with Messages. Or ? I implemented a similar sort of functionality with ROS2 but here i am getting a bit confused with ROS bridge.
I suppose this depends on what you need to achieve. What you described does sound like a job for a ROS service. However if you need more nodes to get the information from topics
custom_topic2
andcustom_topic1
or if you want to allow loosing some messages, that is a job for ROS topic.@kump : I would like to use
Topics
since my node one would be sending an object list and thus as soon as it detects any objects, it should just keep on publishing irrespective of any request.ok. So why is the "circular dependancy" a problem, anyway?
because i am somehow getting stuck in a deadlock. i.e. some implementation problem. If I publish in the callback function for the first node, it will never begin since it wont enter the callback (no new message). If I publish outside, it publishes once and then stays in callback, So i need a return.
return statement in callback with which i can come out from callback and publish again.
It's hard to understand if I can't see the code. Why should it stay in the callback if you publish outside of callback? That doesn't sound as a standard behavior.