ROS2-python服务service和client节点(实现加法运算)

当节点通过服务进行通讯的时候,发送数据请求的一方我们称之为客户端接收数据然后相应的一端我们称之为服务器端请求和响应的数据结构有一个.srv文件决定

本例程当中我们做一个加法运算,一个节点发送一个将两个整数相加的请求,另外一个节点对请求进行相应。

第一步:创建包

mkdir -p dev_ws/src
cd ~/dev_ws/src
ros2 pkg create --build-type ament_python py_srvcli --dependencies rclpy example_interfaces

 功能包叫py_srvcli,example_interfaces也添加到package.xml里面了。

这个接口并不需要我们自己去写,在以后的应用场景下我们也可以自定义接口。(之后的文章会教大家如何写自定义接口)

这个example_interfaces接口可以按照如下方法查找它的路径

ros2 pkg prefix example_interfaces
cat /opt/ros/<ros2-distro>/share/example_interfaces/srv/AddTwoInts.srv

这时你就可以看到数据结构srv里的内容了

第二步:编写服务service节点

进入dev_ws/src/py_srvcli/py_srvcli,创建service_member_function.py文件 

from example_interfaces.srv import AddTwoInts

import rclpy
from rclpy.node import Node


class MinimalService(Node):

    def __init__(self):
        super().__init__('minimal_service')
        self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.add_two_ints_callback)

    def add_two_ints_callback(self, request, response):
        response.sum = request.a + request.b
        self.get_logger().info('Incoming request\na: %d b: %d' % (request.a, request.b))

        return response


def main(args=None):
    rclpy.init(args=args)

    minimal_service = MinimalService()

    rclpy.spin(minimal_service)

    rclpy.shutdown()


if __name__ == '__main__':
    main()

代码解释:

1、第一行加载了服务的消息类型(也就是接口的路径import它里面的类),然后加载了ROS2的Python客户端和节点的类

from example_interfaces.srv import AddTwoInts

import rclpy
from rclpy.node import Node

2、接下来在构造函数里面初始化了节点的名字minimal_service(可以自定义节点名称但保证下面的代码要改对)

服务类型AddTwoInts ,这是example_interfaces包中定义的服务类型

服务名称add_two_ints,客户端将使用这个名称来找到并调用这个服务

回调函数self.add_two_ints_callback

def __init__(self):
    super().__init__('minimal_service')
    self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.add_two_ints_callback)

3、回调函数将接收到的两个数字相加后返回相应,同时往控制台打印消息。(只有服务端要写回调)

def add_two_ints_callback(self, request, response):
    response.sum = request.a + request.b
    self.get_logger().info('Incoming request\na: %d b: %d' % (request.a, request.b))

    return response

最后,主函数主类初始化ROS2 Python客户端,创建服务节点,等待处理回调。

def main(args=None):
    rclpy.init(args=args)

    minimal_service = MinimalService()

    rclpy.spin(minimal_service)

    rclpy.shutdown()

第三步:编写客户端client节点

进入 dev_ws/src/py_srvcli/py_srvcli,创建client_member_function.py文件

import sys

from example_interfaces.srv import AddTwoInts
import rclpy
from rclpy.node import Node


class MinimalClientAsync(Node):

    def __init__(self):
        super().__init__('minimal_client_async')
        self.cli = self.create_client(AddTwoInts, 'add_two_ints')
        while not self.cli.wait_for_service(timeout_sec=1.0):
            self.get_logger().info('service not available, waiting again...')
        self.req = AddTwoInts.Request()

    def send_request(self):
        self.req.a = int(sys.argv[1])
        self.req.b = int(sys.argv[2])
        self.future = self.cli.call_async(self.req)


def main(args=None):
    rclpy.init(args=args)

    minimal_client = MinimalClientAsync()
    minimal_client.send_request()

    while rclpy.ok():
        rclpy.spin_once(minimal_client)
        if minimal_client.future.done():
            try:
                response = minimal_client.future.result()
            except Exception as e:
                minimal_client.get_logger().info(
                    'Service call failed %r' % (e,))
            else:
                minimal_client.get_logger().info(
                    'Result of add_two_ints: for %d + %d = %d' %
                    (minimal_client.req.a, minimal_client.req.b, response.sum))
            break

    minimal_client.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()
代码解释

由于我们需要获得程序输入的参数,我们新加了一行import sys

和服务端类似,首先定义了一个类,然后在构造函数中创建了一个类型名称和服务端一样的节点。

然后white循环一直寻找服务端
之后是发送请求的函数和main函数的定义
在主函数中while循环检测等待服务的相应,同时进行了一个异常处理,如果响应正确打印消息。

添加程序入口

打开setup.py文件,和服务端一样我们添加客户端的程序入口

entry_points={
    'console_scripts': [
        'service = py_srvcli.service_member_function:main',
        'client = py_srvcli.client_member_function:main',
    ],
},

编译运行

进入工作空间根目录进行编译

cd ~/dev_ws
colcon build

打开一个新的终端,我们运行service服务端

cd ~/dev_ws
source install/setup.bash
ros2 run py_srvcli service

再打开一个新的终端,我们运行client客户端

cd ~/dev_ws
source install/setup.bash
ros2 run cpp_srvcli client 2 3

效果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值