ROS2 入门应用 引用自定义服务(Python)
- 1. 查看自定义消息
- 2. 修改服务应答
- 3. 修改服务请求
- 4. 修改依赖关系
- 5. 编译和运行
1. 查看自定义消息
引用在《ROS2 入门应用 创建自定义接口》中自定义的
服务AddThreeInts.srv
ros2 interface show tutorial_interfaces/srv/AddThreeInts
# int64 a
# int64 b
# int64 c
# ---
# int64 sum
需要对《ROS2 入门应用 请求和应答(Python)》中创建的服务端/客户端功能包稍作修改
cd ~/ros2_ws/src/py_srvcli/py_srvcli
将把数值的字符串更改为球体半径
2. 修改服务应答
修改service_member_function.py
服务端源文件,涉及服务类型变更和应用变化
from tutorial_interfaces.srv import AddThreeInts # CHANGE
import rclpy
from rclpy.node import Node
class MinimalService(Node):
'''
服务端节点类
'''
def __init__(self):
# 初始化节点
super().__init__('minimal_service')
# 初始化服务端,服务类型AddThreeInts,服务add_three_ints,回调函数add_three_ints_callback
self.srv = self.create_service(AddThreeInts, 'add_three_ints', self.add_three_ints_callback) # CHANGE
def add_three_ints_callback(self, request, response): # CHANGE
'''
服务端回调函数
'''
# 从请求request中添加两个整数,并将总和提供给响应response
response.sum = request.a + request.b + request.c # CHANGE
self.get_logger().info('Incoming request\na: %d b: %d c: %d' % (request.a, request.b, request.c)) # CHANGE
return response
def main():
# 初始化ROS2
rclpy.init()
# 创建服务端节点
minimal_service = MinimalService()
# 运行服务端节点
rclpy.spin(minimal_service)
# 退出ROS2
rclpy.shutdown()
if __name__ == '__main__':
main()
3. 修改服务请求
修改client_member_function.py
客户端源文件,涉及服务类型变更和应用变化
和修改等待应答的方式
import sys
from tutorial_interfaces.srv import AddThreeInts # CHANGE
import rclpy
from rclpy.node import Node
class MinimalClientAsync(Node):
'''
客户端节点类
'''
def __init__(self):
# 初始化节点
super().__init__('minimal_client_async')
# 初始化客户端,服务类型AddThreeInts,服务add_three_ints
self.cli = self.create_client(AddThreeInts, 'add_three_ints') # CHANGE
# 搜索服务节点,间隔1s
while not self.cli.wait_for_service(timeout_sec=1.0):
self.get_logger().info('service not available, waiting again...')
# 定义请求
self.req = AddThreeInts.Request() # CHANGE
def send_request(self, a, b, c):
'''
请求发送函数
'''
self.req.a = a
self.req.b = b
self.req.c = c # CHANGE
# 发送请求
self.future = self.cli.call_async(self.req)
# CHANGE
# 等待至发送请求得到应答
# rclpy.spin_until_future_complete(self, self.future)
# 返回应答结果
# return self.future.result()
def main():
# 初始化ROS2
rclpy.init()
# 创建客户端节点
minimal_client = MinimalClientAsync()
# 请求发送
minimal_client.send_request(int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3])) # CHANGE
# CHANGE
# 循环等待应答
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_three_ints: for %d + %d + %d = %d' % # CHANGE
(minimal_client.req.a, minimal_client.req.b, minimal_client.req.c, response.sum)) # CHANGE
break
# 销毁节点,退出ROS2
minimal_client.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
4. 修改依赖关系
在package.xml
清单文件中,添加对自定义服务的依赖项的声明
<exec_depend>tutorial_interfaces</exec_depend>
Python源文件应用不涉及到CMake编译信息,因此不用修改
CMakeLists.txt
编译文件
setup.py
安装软件包说明的程序入口点entry_points
字段在之前已经设置完成
entry_points={
'console_scripts': [
'service = py_srvcli.service_member_function:main',
'client = py_srvcli.client_member_function:main',
],
},
5. 编译和运行
进入工作空间根目录
cd ~/ros2_ws
编译:
colcon build --packages-select py_srvcli
打开一个新终端,运行服务端节点准备应答:
ros2 run py_srvcli service
打开一个新终端,运行客户端节点发送请求:
ros2 run py_srvcli client 1 2 3
# [INFO] [minimal_client_async]: Result of add_three_ints: for 1 + 2 + 3 = 6
谢谢