服务通信接口的定义与使用

描述

了解了通信接口的概念,接下来我们再从代码实现的角度,研究下如何定义以及使用一个接口。

在之前服务概念讲解的课程中,我们编写了这样一个例程,我们再来回顾下。

服务端

有三个节点:

第一个驱动相机发布图像话题;

第二个是机器视觉识别节点,封装了一个服务的服务端对象,提供目标识别位置的查询服务;

第三个节点在需要目标位置的时候,就可以发送请求,收到位置进行使用了。

服务端

接口定义

在这个例程中,我们使用GetObjectPosition.srv定义了服务通信的接口:

learning_interface/srv/GetObjectPosition.srv

bool get      # 获取目标位置的指令---int32 x       # 目标的X坐标int32 y       # 目标的Y坐标

定义中有两个部分,上边是获取目标位置的指令,get为true的话,就表示我们需要一次位置,服务端就会反馈这个x、y坐标了。

完成定义后,还需要在功能包的CMakeLists.txt中配置编译选项,让编译器在编译过程中,根据接口定义,自动生成不同语言的代码:

...find_package(rosidl_default_generators REQUIRED)rosidl_generate_interfaces(${PROJECT_NAME}  "srv/GetObjectPosition.srv")...

功能包的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 > ...

程序调用

我们在代码中再来重点看下接口的使用方法。

客户端接口调用

learning_service/service_object_client.py

#!/usr/bin/env python3# -*- coding: utf-8 -*-"""@作者: 古月居@说明: ROS2服务示例-请求目标识别,等待目标位置应答"""import rclpy                                            # ROS2 Python接口库from rclpy.node   import Node                           # ROS2 节点类from learning_interface.srv import GetObjectPosition    # 自定义的服务接口class objectClient(Node):    def __init__(self, name):        super().__init__(name)                          # ROS2节点父类初始化        self.client = self.create_client(GetObjectPosition, 'get_target_position')        while not self.client.wait_for_service(timeout_sec=1.0):            self.get_logger().info('service not available, waiting again...')        self.request = GetObjectPosition.Request()    def send_request(self):        self.request.get = True        self.future = self.client.call_async(self.request)def main(args=None):    rclpy.init(args=args)                             # ROS2 Python接口初始化    node = objectClient("service_object_client")      # 创建ROS2节点对象并进行初始化    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 call failed %r' % (e,))            else:                node.get_logger().info(                    'Result of object position:n x: %d y: %d' %                    (response.x, response.y))            break    node.destroy_node()                              # 销毁节点对象    rclpy.shutdown()                                 # 关闭ROS2 Python接口

服务端接口调用

learning_service/service_object_server.py

#!/usr/bin/env python3# -*- coding: utf-8 -*-"""@作者: 古月居(www.guyuehome.
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分