六、服务(service)与接口(interface)
📌服务是指由一个服务端提供服务,由客户端去请求,与话题的不同之处在于:服务只在需要时去请求即可,并且可以传递参数
📌接口可以用来定义服务传递的数据的结构
1.动手实现一个加法计算服务
(1)创建接口
cd ~/dev_ws/src
ros2 pkg create --build-type ament_cmake learning_interface
cd learning_interface
rm -rf include src # 可选
mkdir srv && cd srv
touch Add.srv
Add.srv代码
int64 a # 第一个加数
int64 b # 第二个加数
---
int64 sum # 求和结果
在package.xml中添加:
<build_depend>rosidl_default_generators</build_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>
在CMakeLists.txt中添加:
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
"srv/Add.srv"
)
构建软件包
cd ~/dev_ws
colcon build
source install/local_setup.bash
(2)服务端
cd ~/dev_ws/src
ros2 pkg create --build-type ament_python learning_service
add_server.py
import rclpy
from rclpy.node import Node
from learning_interface.srv import Add
class AddServer(Node):
def __init__(self, node_name):
super().__init__(node_name)
self.srv = self.create_service(Add, "add", self.callback)
def callback(self, request, response):
response.sum = request.a + request.b
self.get_logger().info('request: a: %d b: %d' % (request.a, request.b))
return response
def main(args=None):
rclpy.init(args=args)
node = AddServer("add_server")
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
(3)客户端
add_client.py
import sys
import rclpy
from rclpy.node import Node
from learning_interface.srv import Add
class AddClient(Node):
def __init__(self, name):
super().__init__(name)
self.client = self.create_client(Add, 'add')
while not self.client.wait_for_service(timeout_sec=1.0):
self.get_logger().info('waiting service...')
self.request = Add.Request()
def send_request(self):
self.request.a = int(sys.argv[1])
self.request.b = int(sys.argv[2])
self.future = self.client.call_async(self.request)
def main(args=None):
rclpy.init(args=args)
node = AddClient("add_client")
node.send_request()
while rclpy.ok():
rclpy.spin_once(node)
if node.future.done():
try:
response = node.future.result()
except Exception as e:
node.get_logger().info('service failed %r' % (e,))
else:
node.get_logger().info(
'result: %d + %d = %d' %
(node.request.a, node.request.b, response.sum))
break
node.destroy_node()
rclpy.shutdown()
(4)配置节点并运行
ros2 run learning_service add_server
ros2 run learning_service add_client 33 44