编写一个简单的服务和客户端(Python) [4964]
目标: 使用Python创建和运行服务和客户端节点。 [4965]
教程级别: 初学者 [3951]
内容 [16422]
背景 [16410]
当使用:doc:services <../Beginner-CLI-Tools/Understanding-ROS2-Services/Understanding-ROS2-Services>`的方式进行通信时,发送请求数据的节点称为客户端节点,而响应请求的节点则是服务节点。请求和响应的结构由`
.srv``文件确定。 [4889]
这里使用的示例是一个简单的整数加法系统;一个节点请求两个整数的和,另一个节点返回结果。 [4890]
任务 [16427]
1 创建一个包 [3283]
在一个新的终端中 源化你的 ROS 2 安装,这样 ros2
命令才能正常工作。 [16429]
进入在 上一个教程 中创建的 ros2_ws
目录。 [4837]
请记住,包应该在“src”目录中创建,而不是工作区的根目录。进入“ros2_ws/src”并创建一个新的包: [4776]
ros2 pkg create --build-type ament_python py_srvcli --dependencies rclpy example_interfaces
您的终端将返回一条消息,确认已创建名为``py_srvcli``的包及其所有必要的文件和文件夹。 [4966]
``--dependencies``参数将自动向``package.xml``添加必要的依赖项。``example_interfaces``是包含 the .srv file 的包,您将需要使用它来构建请求和响应的结构: [4967]
int64 a
int64 b
---
int64 sum
前两行是请求的参数,在破折号以下是响应。 [4893]
1.1 更新 package.xml
[16432]
由于在包创建过程中使用了``--dependencies``选项,您无需手动将依赖项添加到``package.xml``文件中。 [4968]
同样,确保将描述、维护者电子邮件和姓名以及许可证信息添加到 package.xml
中。 [4780]
<description>Python client server tutorial</description>
<maintainer email="you@email.com">Your Name</maintainer>
<license>Apache License 2.0</license>
2 编写服务节点 [4894]
在``ros2_ws/src/py_srvcli/py_srvcli``目录中创建一个名为``service_member_function.py``的新文件,并将以下代码粘贴到其中: [4971]
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():
rclpy.init()
minimal_service = MinimalService()
rclpy.spin(minimal_service)
rclpy.shutdown()
if __name__ == '__main__':
main()
2.1 检查代码 [16436]
第一个 import
语句从 example_interfaces
包中导入了 AddTwoInts
服务类型。接下来的 import
语句导入了 ROS 2 Python 客户端库,具体导入了 Node
类。 [4972]
from example_interfaces.srv import AddTwoInts
import rclpy
from rclpy.node import Node
MinimalService
类的构造函数使用名称 minimal_service
初始化节点。然后,它创建一个服务并定义了类型、名称和回调函数。 [4973]
def __init__(self):
super().__init__('minimal_service')
self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.add_two_ints_callback)
服务回调函数的定义接收请求数据,对其求和,并将求和结果作为响应返回。 [4974]
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
最后,主类初始化了 ROS 2 Python 客户端库,实例化 MinimalService
类以创建服务节点,并旋转节点以处理回调函数。 [4975]
3.编写客户端节点 [4907]
在``ros2_ws/src/py_srvcli/py_srvcli``目录中创建一个名为``client_member_function.py``的新文件,并将以下代码粘贴到其中: [4978]
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, a, b):
self.req.a = a
self.req.b = b
self.future = self.cli.call_async(self.req)
rclpy.spin_until_future_complete(self, self.future)
return self.future.result()
def main():
rclpy.init()
minimal_client = MinimalClientAsync()
response = minimal_client.send_request(int(sys.argv[1]), int(sys.argv[2]))
minimal_client.get_logger().info(
'Result of add_two_ints: for %d + %d = %d' %
(int(sys.argv[1]), int(sys.argv[2]), response.sum))
minimal_client.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
3.1 检查代码 [4869]
客户端唯一不同的``import``语句是``import sys``。客户端节点代码使用`sys.argv <https://docs.python.org/3/library/sys.html#sys.argv>`__ 来获取请求的命令行输入参数访问权限。 [4979]
构造函数定义创建一个与服务节点相同类型和名称的客户端。客户端和服务必须具有匹配的类型和名称才能进行通信。 [4980]
构造函数中的``while``循环每秒检查是否有与客户端类型和名称匹配的服务可用。 [4981]
构造函数下方是请求定义,然后是``main``函数。 [4982]
客户端的``main``函数中唯一重要的区别是``while``循环。循环检查``future``以查看服务是否有响应,只要系统正在运行。如果服务发送了响应,结果将写入日志消息中。 [4983]
4 构建和运行 [16752]
在构建之前,最好在工作空间的根目录(ros2_ws
)中运行``rosdep``来检查是否缺少依赖项: [4791]
rosdep install -i --from-path src --rosdistro humble -y
rosdep 只能在 Linux 上运行,所以您可以跳过下一步。 [4792]
rosdep 只能在 Linux 上运行,所以您可以跳过下一步。 [4792]
返回到您的工作空间的根目录 ros2_ws
,并构建您的新包: [4793]
colcon build --packages-select py_srvcli
打开一个新的终端,导航到 ros2_ws
,并加载设置文件: [4794]
source install/setup.bash
. install/setup.bash
call install/setup.bat
现在运行服务节点: [4916]
ros2 run py_srvcli service
节点将等待客户端的请求。 [4986]
打开另一个终端,并再次从``ros2_ws``内部源化设置文件。启动客户端节点,然后输入由一个空格分隔的两个整数: [4987]
ros2 run py_srvcli client 2 3
例如,如果你选择了``2``和``3``,客户端将会收到如下响应: [4919]
[INFO] [minimal_client_async]: Result of add_two_ints: for 2 + 3 = 5
返回到运行服务节点的终端。您将看到当它接收到请求时,它会发布日志消息: [4988]
[INFO] [minimal_service]: Incoming request
a: 2 b: 3
在服务器终端中输入``Ctrl+C``以停止节点的运行。 [4921]