上期我们完成了天气服务端(Server)的编写,它能根据日期随机返回天气。但如果每次都要手动敲命令去查询,那就太麻烦了!🥱
今天,我们要编写客户端(Client),让程序自动、定时地去请求天气服务,实现全自动的“天气播报员”!🌦️
🛠️ 一、客户端编写步骤介绍
用 Python 编写 ROS2 客户端,通常遵循以下 5 个标准步骤:
导入服务接口:引入我们自定义的 GetWeather消息类型。
创建请求结果接收回调函数:定义一个函数,专门处理服务端返回的结果。
声明并创建客户端:在节点中注册这个客户端,连接到指定的服务。
编写结果接收逻辑:在回调函数中打印或处理收到的天气数据。
调用客户端发送请求:主动向服务端发送请求数据(比如当前日期)。
🐍 二、Python 客户端代码编写
本次代码将编写在 weather_py_client 功能包中。请确保该功能包已创建并依赖 rclpy和 weather_service_demo(存放 srv 接口的包)。
在 weather_py_client包的 weather_py_client目录下,创建 weather_client.py。
1. 完整代码
import rclpyfrom rclpy.node importNode# 1. 导入自定义的服务接口 (注意这里是导入上一章的包)from weather_service_demo.srv import GetWeatherimport datetimeclass WeatherClient(Node): def __init__(self): super().__init__('weather_client') # 3. 声明并创建客户端 self.cli = self.create_client(GetWeather, 'get_weather') # 等待服务端上线 while not self.cli.wait_for_service(timeout_sec=1.0): self.get_logger().info('Service not available, waiting again...') self.get_logger().info('Weather Client is ready.') # 2. 创建请求结果接收回调函数 def send_request(self): # 5. 调用客户端发送请求 # 获取当前日期作为请求参数 today = datetime.datetime.now().strftime("%Y-%m-%d") request = GetWeather.Request() request.date = today self.get_logger().info(f'Sending request for date: {today}') # 发送请求并等待响应 future = self.cli.call_async(request) future.add_done_callback(self.response_callback) # 4. 编写结果接收逻辑 def response_callback(self, future): try: response = future.result() self.get_logger().info(f'Received weather: {response.weather_status}') except Exception as e: self.get_logger().error(f'Service call failed: {e}')def main(args=None): rclpy.init(args=args) weather_client = WeatherClient() # 每隔1秒发送一次请求 while rclpy.ok(): weather_client.send_request() rclpy.spin_once(weather_client, timeout_sec=1.0) weather_client.destroy_node() rclpy.shutdown()if __name__ == '__main__': main()
在 weather_py_client包的 setup.py中添加入口点:
entry_points={ 'console_scripts': [ 'weather_client = weather_py_client.weather_client:main', ],},
🧪 三、Python 客户端测试
现在,让我们把上一章的服务端和这次的客户端都跑起来!
1. 编译工作空间
回到工作空间根目录,执行编译:
colcon buildsource install/setup.bash
2. 运行测试
打开两个终端:
终端 1:启动服务端(来自 weather_service_demo 包)
ros2 run weather_py_server weather_py_server
终端 2:启动客户端(来自 weather_py_client 包)
ros2 run weather_py_client weather_client
预期效果:
你会看到客户端每隔 1 秒钟,自动发送一次请求(带上当前日期),服务端收到后随机返回一个天气(如 Sunny, Rainy),并回传给客户端显示。
📢 下期预告
我们已经用 Python 玩转了服务和客户端。但在追求极致性能的工业场景,C++ 才是主力。下期我们将挑战 C++ 编写服务端引用自定义服务接口!🚀
💬 互动一下:
你觉得这个“天气客户端”还能怎么玩?比如结合天气预报 API 做一个真实的天气查询?欢迎在评论区分享你的脑洞!👇