question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

subscriber does not work if create_subscription is after spin

See original GitHub issue

Bug 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:closed
  • Created 3 years ago
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
ivanpaunocommented, Nov 30, 2020

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.

0reactions
ivanpaunocommented, Dec 11, 2020

we call add_waitable here

That’s only called if the subscription was created with an event handler(s), which is not the most common case.

which triggers the guard condition of the node’s executor

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 in create_subscription, which seems to be an oversight. @ssumoo could you open a PR fixing that? thanks!

Read more comments on GitHub >

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

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found