[ros2] Why does sleep not work inside callback?
I noticed that sleep does not work inside callback in default settings, i.e., SingleThreadedExecutor
with MutuallyExclusiveCallbackGroup
. Please see a sample code snippet below:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from example_interfaces.action import Fibonacci
import rclpy
from rclpy.action import ActionServer
from rclpy.node import Node
class MinimalActionServer(Node):
def __init__(self):
super().__init__('minimal_action_server')
self.as_ = ActionServer(self, Fibonacci, 'fib', execute_callback=self.execute_cb)
def execute_cb(self, goal_handle):
fb = Fibonacci.Feedback(sequence=[0, 1])
loop_rate = self.create_rate(1, self.get_clock()) # 1 Hz
for i in range(1, goal_handle.request.order):
self.get_logger().info(f'[{i}] Executing goal...')
fb.sequence.append(fb.sequence[i] + fb.sequence[i - 1])
self.get_logger().info(f'Publishing feedback: {fb.sequence}')
goal_handle.publish_feedback(fb)
loop_rate.sleep() # commenting this line makes the callback work
goal_handle.succeed()
return Fibonacci.Result(sequence=fb.sequence)
def main(args=None):
rclpy.init(args=args)
node = MinimalActionServer()
try:
rclpy.spin(node)
except KeyboardInterrupt:
pass
finally:
rclpy.shutdown()
if __name__ == '__main__':
main()
Question
Why does sleep not work inside callback?
Additional Info
- Operating System: Ubuntu 20.04.4 LTS
- Installation type: binaries
- Version or commit hash: ROS Galactic
- DDS implementation: Default
- Client library: rclpy
Asked by ravijoshi on 2022-07-30 21:07:19 UTC
Answers
Above the loop_rate.sleep()
command, add a ros::spinOnce()
command.
ros::spin()
and ros::spinOnce()
are commands that are tasked to handle communication events, such as messages. Any subscription to a message, service, or an action must be called by spin to process the events.
ros::spinOnce()
: Handles the events and returns immediately with more controllability.
ros::spin()
: Blocks incoming events until ROS invokes a shutdown command.
rate.sleep()
: A threadwith a duration defined by a frequency.
Source: Callback & Spinnings
Asked by qilin_gundamenjoyer on 2022-07-31 20:39:09 UTC
Comments
Sorry, it seems you are referring to ROS 1. The question is related to ROS 2.
Asked by ravijoshi on 2022-07-31 20:44:43 UTC
My bad. You are right.
Asked by qilin_gundamenjoyer on 2022-08-01 00:19:00 UTC
So I'm coming in late, but I had the same problem. There are two ways to make the code above work.
- Use
MultiThreadedExecutor
- Initialize
loop_rate
in the constructor
Code for 1:
def main(args=None):
rclpy.init(args=args)
node = MinimalActionServer()
executor = MultiThreadedExecutor()
try:
rclpy.spin(node, executor=executor)
except KeyboardInterrupt:
pass
finally:
rclpy.shutdown()
Code for 2:
class MinimalActionServer(Node):
def __init__(self):
super().__init__('minimal_action_server')
self.loop_rate = self.create_rate(1, self.get_clock()) # 1 Hz This can be initialized after self.as_ as well
self.as_ = ActionServer(self, Fibonacci, 'fib', execute_callback=self.execute_cb)
I currently have not figured out where exactly the problem is located by at least it runs for now.
Asked by tlipps on 2023-02-22 03:18:55 UTC
Comments