[ROS2][service][topic]service and topic cooperate
The existing system has topics cmd_vel
,light_sensors
and a service motor_power
. I created a node that it will take the msg from light_sensors
, then publish msg into cmd_vel
. While, I wanna call service motor_power
to turn on/off the motor when the msg from light_sensors
meets some conditions.
I found many examples that executes topics and services separately, but there is no example that combine the service and topic. Also, I found an article about actions, but I am not quite sure if it is what I want.
What is the right way/design to do so? Calling a service from the callback function of a subscriber? Or there is more proper way? I have tried this, but it did not work for me, and the post is in 2018, a bit old?
#!/usr/bin/env python3
import sys
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
from std_srvs.srv import SetBool
class SubscriberClientAsync(Node):
def __init__(self):
super().__init__('sub_client_node')
self.client = self.create_client(SetBool, 'motor_power')
self.sub = self.create_subscription(String, 'topic', self.topic_cb)
def topic_cb(self, msg):
// How should I implement here to just spin once self.client ?
if msg.data == 'stop':
req = SetBool.Request()
req.data = False
self.future = self.client.call_async(req)
if __name__ == '__main__':
rclpy.init()
node = SubscriberClientAsync()
try:
rclpy.spin(node)
except KeyboardInterrupt:
pass
node.destroy_node()
I simply added
self.client.call_async(...)
in the subscriber's callback function, and it worked. However, since it is in the loop of topic, I can see the service is called many times till the node is destroyed, instead ofspin_once()
. As the background of service, the service should only be called once when it is needed. Therefore, I am wondering if it is the proper way to call service inside the callback of subscriber like this? Or is there a way I can combine usingspin_once()
for calling service inside of aspin()
for continuously updating topic?