ROS服务端(Server)和客户端(Client)的python编程实现(保姆级教程)

引言

       这个教程是和之前的有些联系的,基础以及重复的知识我就不做讲解啦,本身这个内容也不是太难,关于之前的话题通信以及怎么创建msg或者srv大家可以看之前的教程。

传送门:
ROS发布者(Publisher)和订阅者(Subscriber)的python编程实现(讲解超级详细)
创建ROS消息(msg)和服务(srv)

接下来让我们进入正题吧!

一、创建功能包

       我们在之前的工作空间创建一个service的功能包,用来存放这个教程的所有文件:

在这里插入图片描述
       让我们先整体看一下这个功能包的文件,主要有一个客户端和一个服务端程序,然后还有一个srv文件:

在这里插入图片描述
AddTwoInts.srv内容如下:

int64 A
int64 B
---
int64 Sum

二、编写服务端节点

       我们将创建简单的服务端节点add_two_ints_server,该节点将接收两个整数,并返回它们的和。
整体代码如下:

#!/usr/bin/env python

from __future__ import print_function
from service.srv import AddTwoInts,AddTwoIntsResponse #注意是功能包名.srv
import rospy

def handle_add_two_ints(req):
    print("Returning [%s + %s = %s]"%(req.a, req.b, (req.a + req.b)))
    return AddTwoIntsResponse(req.a + req.b)

def add_two_ints_server():
    rospy.init_node('add_two_ints_server')
    s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints)
    print("Ready to add two ints.")
    rospy.spin()

if __name__ == "__main__":
    add_two_ints_server()

       我们使用rospy.init_node()声明我们的节点,然后再声明我们的服务:

 s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints)

       这声明了一个名为add_two_ints的新服务,其服务类型为AddTwoInts。所有的请求(request)都传递给了handle_add_two_ints函数。handle_add_two_intsAddTwoIntsRequest的实例调用,返回AddTwoIntsResponse实例。就像订阅者中的例子一样,rospy.spin()可以防止程序在服务关闭之前退出。

如何实现一个服务端节点?
1.初始化ROS节点;
2.创建Server实例;
3.循环等待服务请求,进入回调函数;
4.在回调函数中完成服务功能的处理,并反馈应答数据。

二、编写客户端节点

整体代码如下:

#!/usr/bin/env python

from __future__ import print_function 

import sys
import rospy
from service.srv import * #注意是功能包名.srv

def add_two_ints_client(x, y):
    rospy.wait_for_service('add_two_ints')
    try:
        add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)
        resp1 = add_two_ints(x, y)
        return resp1.sum
    except rospy.ServiceException as e:
        print("Service call failed: %s"%e)

def usage():
    return "%s [x y]"%sys.argv[0]

if __name__ == "__main__":
    if len(sys.argv) == 3:
        x = int(sys.argv[1])
        y = int(sys.argv[2])
    else:
        print(usage())
        sys.exit(1)
    print("Requesting %s+%s"%(x, y))
    print("%s + %s = %s"%(x, y, add_two_ints_client(x, y)))

       对于客户端来说不需要调用init_node()。我们首先调用:

rospy.wait_for_service('add_two_ints')

       这是一种很方便的方法,可以让在add_two_ints服务可用之前一直阻塞。

add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)

       这里我们为服务的调用创建了一个句柄(handle)。

 resp1 = add_two_ints(x, y)
 return resp1.sum

       然后我们可以使用这个句柄,就像普通的函数一样调用它。

       因为我们已经将服务的类型声明为AddTwoInts,它会为你生成AddTwoIntsRequest对象。如果调用失败,rospy.ServiceException将会抛出,所以应该编写一个合适的try/except部分(异常处理)。

如何实现一个客户端节点?
1.初始化ROS节点;
2.创建一个Client实例;
3.发布服务请求数据;
4.等待Server处理之后的应答结果。

三、编译

       我们需要在package.xml添加如下内容:

在这里插入图片描述

CMakeLists.txt整体如下:
在这里插入图片描述
       然后进行编译。
       这些内容之前都有讲解,这里就不一一赘述啦。

四、运行结果

在这里插入图片描述

五、服务通信机制

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

六、话题与服务区别

在这里插入图片描述

本文内容参考:
ROS官方wiki:http://wiki.ros.org
古月——ROS入门21讲
《ROS机器人开发实践》

如有错误或者不足之处,欢迎大家留言指正!

  • 11
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
ROS系统中,服务端客户端的概念可以理解为提供服务和请求服务的节点。服务端节点提供服务客户端节点请求服务,它们之间通过消息传递进行通信。 下面是一个简单的服务端客户端Python编程示例: 服务端代码: ```python #!/usr/bin/env python import rospy from std_srvs.srv import Empty def my_service_callback(request): print("My service has been called!") #实现服务功能 return [] rospy.init_node('my_service_server') my_service = rospy.Service('/my_service', Empty, my_service_callback) print("My service is ready to receive requests!") rospy.spin() #保持节点运行状态 ``` 客户端代码: ```python #!/usr/bin/env python import rospy from std_srvs.srv import Empty rospy.init_node('my_service_client') rospy.wait_for_service('/my_service') #等待服务启动 my_service_proxy = rospy.ServiceProxy('/my_service', Empty) response = my_service_proxy() #发送请求 ``` 上述代码中,服务端使用`rospy.Service`函数创建一个服务节点,指定服务名称为`/my_service`,服务类型为`Empty`,并指定回调函数`my_service_callback`用于处理服务请求。 客户端使用`rospy.ServiceProxy`函数创建一个服务代理,指定服务名称为`/my_service`,服务类型为`Empty`,并通过调用`my_service_proxy()`方法发送请求,最终获得服务的响应结果。 需要注意的是,服务端客户端的节点名称应该相互独立,避免节点名称冲突。同时,在ROS系统中,服务端客户端节点的启动顺序也很重要,需要确保服务端节点在客户端节点之前启动。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

☆下山☆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值