ROS学习经历(6)——服务(下)

ROS学习经历(6)

在上一节,我们创建了对应的服务接口,现在让我们来创建服务吧。

1. 如何编写一个Python服务

步骤如下:
服务端

  1. 导入服务接口
  2. 创建服务端回调函数
  3. 声明并创建服务端
  4. 编写回调函数逻辑处理请求

2. 编写服务端李四代码

首先打开我们的town_ws工作区。

2.1 导入服务接口

1)添加依赖,ament_python只需要在package.xml中加入代码:

  <depend>village_interfaces</depend>

在这里插入图片描述
2)程序中导入,在程序开头加入代码:

#从村庄接口服务类中导入借钱服务
from village_interfaces.srv import BorrowMoney

2.2 创建服务端并定义服务回调函数

1)由于面向对象的继承特性,WriteNode继承了Node的属性,所以我们可以在当中的__init__函数中创建成员变量borrow_server

# 新建借钱服务
self.borrow_server = self.create_service(BorrowMoney, "borrow_money", self.borrow_money_callback)

传入的三个参数:

  • 服务接口类型,BorrowMoney,上一章创建的
  • 服务名称,"borrow_money",具有唯一性,是我们自己创建的
  • 回调函数,self.borrow_money_callback,我们下一步定义

2.3 定义回调函数

def borrow_money_callback(self,request, response):
    """
    借钱回调函数
    参数:request 客户端请求对象,携带着来自客户端的数据
         response 服务端响应,返回服务端的处理结果
    返回值:response
    """
    return response

这个函数有三个入口参数:

  • request是客户端的请求对象,带着客户端的数据
    其结构就是服务接口中定义的namemoney
  • reponse是服务端响应,返回服务端的处理结果
    其结构由successmoney组成

2.4 编写回调函数

代码并不复杂,理解一下就可以了

def borrow_money_callback(self,request, response):
    """
    借钱回调函数
    参数:request 客户端请求
         response 服务端响应
    返回值:response
    """
    self.get_logger().info("收到来自: %s 的借钱请求,目前账户内还有%d元" % (request.name, self.account))
    #根据李四借钱规则,借出去的钱不能多于自己所有钱的十分之一,不然就不借
    if request.money <= int(self.account*0.1):
        response.success = True
        response.money = request.money
        self.account = self.account - request.money
        self.get_logger().info("借钱成功,借出%d 元 ,目前账户余额%d 元" % (response.money,self.account))
    else:
        response.success = False
        response.money = 0
        self.get_logger().info("对不起兄弟,手头紧,不能借给你")
    return response

2.5 编写服务端代码

1)编译

colcon build --packages-select village_li

2)启动并查看服务列表

source install/setup.bash
ros2 run village_li li4_node

3)手动借钱

source install/setup.bash
ros2 service call /borrow_money village_interfaces/srv/BorrowMoney  "{name: 'li3', money: 5}"

4)再借50块钱,观测效果

ros2 service call /borrow_money village_interfaces/srv/BorrowMoney  "{name: 'li3', money: 50}"

3 创建客户端

让我们再创建一个节点li3来作为客户端吧,首先按照前面创建一个节点。
编写服务通信的客户端的一般步骤:

  1. 导入服务接口
  2. 创建请求结果接受回调函数
  3. 声明并创建客户端
  4. 编写结果接受逻辑
  5. 调用客户端发送请求

3.1 导入服务接口

1)修改package.xml,但李三和李四在用一个功能包中,所以不需要再修改
2)导入接口

from village_interfaces.srv import BorrowMoney

3.2 创建请求结果接受回调函数

def borrow_respoonse_callback(self,response):
    """
    借钱结果回调
    """
    pass

只有一个入口response

3.3 创建客户端

#在__init__函数中创建一个服务的客户端
self.borrow_money_client_ = self.create_client(BorrowMoney, "borrow_money")

函数中有两个入口参数,一个是服务接口类型,一个是服务名称

这里的两个参数需要和服务端的完全一致,才可通信。这点要特别注意。

3.4 编写回调函数处理逻辑

根据结果反应

    def borrow_respoonse_callback(self,response):
        """
        借钱结果回调
        """
        # 打印一下信息
        result = response.result()
        if result.success == True:
            self.get_logger().info("果然是亲弟弟,借到%d,吃麻辣烫去了" % result.money)
        else:
            self.get_logger().info("害,连几块钱都不借,我还是不是他亲哥了,世态炎凉呀")

3.5 创建发送请求函数

我们在li3中编写一个函数用于创建发送的数据,并请求发送。

def borrow_money_eat(self):
    """
    借钱吃麻辣烫函数
    """
    #打印一句话
    self.get_logger().info("找我弟借钱吃麻辣烫喽")
    #等待服务启动,每1s检查一次,如果服务没有启动,则一直循环
    while not self.borrow_money_client_.wait_for_service(1.0):
        self.get_logger().warn("我弟不在线,我再等等。")
    # 构建请求内容
    request = BorrowMoney.Request()
    #将当前节点名称作为借钱者姓名
    request.name = self.get_name()
    #借钱金额10元
    request.money = 10
    #发送异步借钱请求,借钱成功后就调用borrow_respoonse_callback()函数
    self.borrow_money_client_.call_async(request).add_done_callback(self.borrow_respoonse_callback)

核心部分在call_async(request).add_done_callback,用于发送请求,并且添加了一个任务完成时的回调函数

3.6 在main中调用发送函数

加入一行代码

node.borrow_money_eat() #增加一行,李三借钱

这时的main的代码内容如下:

def main(args=None):
    """
    ros2运行该节点的入口函数,可配置函数名称
    """
    rclpy.init(args=args) # 初始化rclpy
    node = BaiPiaoNode()  # 新建一个节点
    node.borrow_money_eat() #增加一行,李三借钱
    rclpy.spin(node) # 保持节点运行,检测是否收到退出指令(Ctrl+C)  
    rclpy.shutdown() # rcl关闭

3.7 测试

1)编译功能包

colcon build --packages-select village_li

2)运行li3节点

source install/setup.bash
ros2 run village_li li3_node

3)运行li4节点

source install/setup.bash
ros2 run village_li li4_node

4)运行wang2节点来买小说

source install/setup.bash
ros2 run village_wang wang2_node 

5)再运行li3节点

ros2 run li3_node
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值