'My timing accuracy is related to the number of spin_once
My timing accuracy is related to the number of spin_once.
I try to call service 'compute_rectangle_area' at a constant rate. The strange thing happens.
If I set the rate to 1 Hz, It seems that I have to do spin_once four times to get correct timing!
If the times of spins is smaller than four, the programming will get stuck at the following screen.
If the time of repeats is bigger than four, the programming sleeps longer than expected.

Here is my code.
#!/usr/bin/python3
from asyncio import Future
from functools import partial
import rclpy
from rclpy.node import Node
from robot_interfaces1.srv import ComputeRectangleArea
class ComputeRectangleAreaClientNode(Node):
def __init__(self, node_name: str) -> None:
super().__init__(node_name)
self.client_ = self.create_client(ComputeRectangleArea,"compute_rectangle_area")
def call_compute_rectangle_area_server(self,length:float,width:float)->bool:
if(self.client_.wait_for_service(5)):
msg_request = ComputeRectangleArea.Request()
msg_request.length = length
msg_request.width = width
future = self.client_.call_async(msg_request)
future.add_done_callback\
(partial(self.callback_call_compute_rectangle_area_server,length=length,width=width))
return True
else:
self.get_logger().error("Server is not ready.")
return False
pass
def callback_call_compute_rectangle_area_server \
(self,future:Future,length:float,width:float):
if future.exception() == None:
response_:ComputeRectangleArea.Response = future.result()
self.get_logger().info(f"{length} * {width} = {response_.area}.")
else:
self.get_logger().error(f"The {self.get_name()} returns {future.exception()}.")
def main(args=None):
rclpy.init(args=args)
n = ComputeRectangleAreaClientNode("compute_rectangle_area_client")
loop_rate = n.create_rate(1)
counter = 0
while rclpy.ok():
if(n.call_compute_rectangle_area_server(67.4,45.6)):
n.get_logger().info(f"Call {counter} times.")
counter += 1
rclpy.spin_once(n)
rclpy.spin_once(n)
rclpy.spin_once(n)
rclpy.spin_once(n)
rclpy.spin_once(n)
rclpy.spin_once(n)
loop_rate.sleep()
rclpy.shutdown()
if __name__ == "__main__":
main()
Solution 1:[1]
As per your comment, the problem with the logic is you're not using a timer where you should be; there isn't an issue with core logic apart from using spin_once() multiple times.
The reason you're seeing this issue is because spin_once has no relation to timing, it simply calls available callbacks. If you want data to be processed at a fixed rate, it is best to just let the callbacks and services run using rclpy.spin(node), then have a fixed rate timer calling a main loop.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | BTables |
