rate.sleep() blocks node after first callback function

asked 2023-04-25 16:48:03 -0500

updated 2023-04-25 16:49:06 -0500

After receiving the first callback function in the following code, the node blocks and stops running, that is, it doesn't execute the instructions inside the while loop nor the callback function anymore. By removing the rate.sleep() function it fixes the problem but the while loop is not running at the desired rate of 10 hz anymore.... Is this a bug or I'm missing something? The rate.sleep() works well if it doesn't have any callback.

 #!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from rclpy.executors import SingleThreadedExecutor
from gazebo_msgs.msg import ModelStates

class MyNode(Node):
    def __init__(self):
        super().__init__('my_node')
        self.subs_model_states = self.create_subscription(
            ModelStates,
            '/gazebo/model_states',
            self.model_states_callback,
            10)
        self.subs_model_states  # prevent unused variable warning

    def model_states_callback(self, msg):
        try:
            self.get_logger().info(f"Callback")
        except Exception as e:
            self.get_logger().error(f"Error in callback: {e}")


def main(args=None):
    rclpy.init(args=args)
    node = MyNode()
    executor = SingleThreadedExecutor()
    executor.add_node(node)
    rate = node.create_rate(10) # 10 Hz
    while rclpy.ok():
        rclpy.logging.get_logger("main").info(f"Running!")
        executor.spin_once(timeout_sec=0.1)
        rate.sleep()
    node.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()
edit retag flag offensive close merge delete

Comments

How do you start your node? Using ros2 run <package> <your_prog> works in my system. The line #!/usr/bin/env python3 suggests to me, that you start the file directly from the command line as a normal python file (e.g. $python3 file.py )

Andromeda gravatar image Andromeda  ( 2023-04-26 04:13:45 -0500 )edit

I'm using the same command as you to start the node.

The reason of the line:

#!/usr/bin/env python3

it's because I'm starting a python node in the same package as C++ nodes. Basically, I'm using CMake. Do you think it has something to do with that?

andrestoga gravatar image andrestoga  ( 2023-04-26 10:31:36 -0500 )edit

I do not know... In my humble installation, your code works without any change. What happens if you remove that line and you use ros2 run ... to start the node?

Andromeda gravatar image Andromeda  ( 2023-04-26 11:18:35 -0500 )edit

If I do it in a C++ package I'll get an error.

Anyways, I removed that line, I put that Python node in a Python only package, and I still got the same behavior...

You can see an screenshot here(I don't know how to add pictures in comments) https://imgur.com/a/XykgTRG

andrestoga gravatar image andrestoga  ( 2023-04-26 15:42:29 -0500 )edit

I have no idea... tomorrow I have access to another PC, where I developed some programs using spin_once and I try to compare them to your code, to investigate the problem

Andromeda gravatar image Andromeda  ( 2023-04-27 11:36:01 -0500 )edit

Ok, can you try the same identical code above but putting the following line: rclpy.spin_once() after executor.spin_once(timeout_sec = 0.1) (BUT BEFORE the rate.sleep() )? Build, try and report.

Andromeda gravatar image Andromeda  ( 2023-04-28 02:02:26 -0500 )edit

To be clear:

...
executor.spin_once(timeout_sec=0.1)
rclpy.spin_once()
rate.sleep()
...
Andromeda gravatar image Andromeda  ( 2023-04-28 02:05:26 -0500 )edit

I have to add to the spin_once:

rclpy.spin_once(node)

because I was getting this error:

TypeError: spin_once() missing 1 required positional argument: 'node'

Unfortunately, I'm getting the same behavior.

andrestoga gravatar image andrestoga  ( 2023-04-29 17:17:06 -0500 )edit