subscriber does not work if create_subscription is after spin
See original GitHub issueBug report
Required Info:
- Operating System:
- Ubuntu 20.04
- Installation type:
- via Debian Packages
- Version or commit hash:
- ROS 2 Foxy Fitzroy
- DDS implementation:
- Default
- Client library (if applicable):
- N/A
Steps to reproduce issue
If a subscriber is created after ros is spun (with some delay), the subscriber callback does not receive the messages.
In my uses case I have to create subscribers after program started. I spin the ros in a thread so that my main thread is used for other works. If after sime time, I create a subscriber, it does not receive any message. The below example is based on subscriber_member_function.py. Note this line:
time.sleep(1) # Make this zero and it works
If this delay is zero, it works. Otherwise it does not.
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
import threading
import time
class MinimalSubscriber(Node):
def __init__(self):
super().__init__('minimal_subscriber')
def listener_callback(self, msg):
self.get_logger().info('I heard: "%s"' % msg.data)
def build_subscriber(self):
self.subscription = self.create_subscription(
String,
'topic',
self.listener_callback,
10)
self.subscription # prevent unused variable warning
def main(args=None):
rclpy.init(args=args)
minimal_subscriber = MinimalSubscriber()
# Spin ros in a thread
def ros_spin():
print('ROS spins')
rclpy.spin(minimal_subscriber)
ros_thread = threading.Thread(target=ros_spin, args=()) # run-time thread
ros_thread.start()
time.sleep(1) # Make this zero and it works
minimal_subscriber.build_subscriber()
# Main thread
print("main thread begins")
while True:
try:
time.sleep(1)
except KeyboardInterrupt:
break
# Destroy the node explicitly
# (optional - otherwise it will be done automatically
# when the garbage collector destroys the node object)
minimal_subscriber.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
Expected behavior
To receive messages
Actual behavior
No message is received
Issue Analytics
- State:
- Created 3 years ago
- Comments:5 (5 by maintainers)
Top Results From Across the Web
Dynamically subscribing to nodes in ROS2 after rospy.spin
It can be a dummy subscriber and doesn't need to actually do anything. After self.create_subscription(...) , add a self.guards line. It looks ...
Read more >Method: projects.subscriptions.create | Cloud Pub/Sub ...
If the subscription is a push subscription, pushes to the endpoint will not be made. enableExactlyOnceDelivery. boolean. If true, Pub/Sub ...
Read more >Create a Publisher and Subscriber in C++ | ROS 2 Foxy Fitzroy
Open a new terminal, and run the publishing subscriber node. ros2 run cpp_pubsub pubsub_node. You will not see any output from running this...
Read more >Step 5: Create a subscription set and a subscription-set member
You can also create a subscription set by selecting the Registered Tables folder of the SAMPLE database, right-clicking the DEPARTMENT table in the...
Read more >Create a Microsoft Customer Agreement subscription - Azure ...
Or, if you have a Microsoft Online Service Program (MOSP) billing account, also called pay-as-you-go, you can create subscriptions starting in ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Hi @ssumoo, adding an explicit timeout is a possible workaround, but it’s not an ideal solution performance wise (
spin
is waken unnecessarily periodically).Ideally, the creation of any waitable (subscriber, service, etc) should awake the executor associated with the node by triggering this guard condition of the associated executor. For that to happen, the node should keep a weak reference to that guard condition of its associated executor.
That would be a nice improvement to the
rclpy
executor, if you want to implement it and have any question feel free to tag me.That’s only called if the subscription was created with an event handler(s), which is not the most common case.
This is much simpler of what I thought originally, if you add here
self._wake_executor()
the problem should be solved.Actually, that’s done in all
create_*
/destroy_*
methods except increate_subscription
, which seems to be an oversight. @ssumoo could you open a PR fixing that? thanks!