二、服务通信
1、服务通信核心实现
适用于对实时性有要求,具有一定逻辑处理的应用场景中
1-1、C++服务端
1.包含头文件
#incldue “rclcpp/rclcpp.hpp”
#include “服务接口消息.hpp”
Tips:
using和using namespace的区别:
using用于引入某个命名空间中的特定名称,而using namespace则是用于引入整个命名空间的内容。
2.创建服务端
server = this->create_service<AddInts>("add_ints",std::bind(&MinimalService::add, this, _1, _2));
API:创建服务端
create_service()
/*
模板:服务接口类型
参数:
1、服务话题
2、回调函数
返回值:服务对象指针( rclcpp::Service::SharedPtr server;)
*/
3.处理请求数据并响应结果
void add(const AddInts::Request::SharedPtr req,const AddInts::Response::SharedPtr res)
回调函数中有两个内置参数,一个是AddInts::Request,一个是AddInts::Response。
*/
Tips:
可以使用命令测试服务端:
ros2 service call 服务话题(/add_ints) 声明提交数据的类型(base_interfaces_demo/srv/AddInts) 提交的数据(“{‘num1’:10,‘num2’:30}”)
1-2、C++客户端
1.包含头文件;
#include “rclcpp/rclcpp.hpp”
#include “base_interfaces_demo/srv/add_ints.hpp”
2、定义节点类
2-1.创建客户端;
rclcpp::Client<AddInts>::SharedPtr client;
client = this->create_client<AddInts>("add_ints");
API:创建客户端
create_client<服务接口>(服务话题名称)
/*
模板:服务接口消息类型
参数:服务话题名称
返回值:客户端对象指针
*/2-2.等待服务连接;(对于服务通信而言,如果客户端连接不到服务器,那么不能发送请求)
API:等待服务器连接
wait_for_service(1s)
/*
参数:
1、等待时间
*/2-3.组织请求数据并发送;
rclcpp::Client::FutureAndRequest send_request(int_32 num1,int_32 num2)
{
auto request = std::make_shared<AddInts::Request>();
request.num1 = num1;
request.num2 = num2;
return client->async_send_request(request);
}
API:异步发送数据
async_send_request()
/*
参数:
1、消息变量request
/*
3.创建对象指针调用其功能,并处理响应;
此时不需要使用spin函数(服务通信机制是一问一答的,当响应请求后,客户端不需要一直挂起,所以这里直接创建一个客户端对象即可)
auto client = std::make_shared<类名>();
3-1.需要调用连接服务的函数,然后根据链接结果做下一步处理
bool flag = client->connect_server()
3-2.连接服务后,调用请求提交函数并处理响应结果
auto future->send_request(atoi(argv[1]),atoi(argv[2]));
3-3.处理响应
rclcpp::spin_until_future_complete(client,response) == rclcpp::FutureReturnCode::SUCCESS
判断future的一个状态码
/*
参数:
1、当前节点指针
2、future指针
*/
Python服务端核心实现
“”"
1.导包;
2.初始化 ROS2 客户端;
3.定义节点类;
3-1.创建服务端;
3-2.处理请求数据并响应结果。
4.调用spin函数,并传入节点对象;
5.释放资源。
“”"
** 1.导包**
import rclpy
from rclpy.node import Node
from base_interfaces_demo.srv import AddInts
3.定义节点类
3-1.创建服务端
self.srv = self.create_service(AddInts, 'add_ints', self.add_two_ints_callback)
API:创建服务端
create_service()
/*
参数:
1、服务接口消息类型
2、服务话题名称
3、回调函数
*/
3-2.处理请求数据并响应结果
回调函数
def add(self,request,response}
该函数主要用于处理请求并产生响应
Python客户端核心实现
“”
1.导包;
2.初始化 ROS2 客户端;
3.定义节点类;
3-1.创建客户端;
3-2.等待服务连接;
3-3.组织请求数据并发送;
4.创建对象调用其功能,处理响应结果;
5.释放资源。
“”
1、导包
import sys import rclpy from rclpy.node import Node from base_interfaces_demo.srv import AddInts from rcpy.logging import get_logger//日志
3.定义节点类
3-1.创建客户端
self.client = self.create_client(AddInts,"add_ints")
API:创建客户端
create_client()
/*
参数:
1、服务接口类型
2、服务话题名称
*/
3-2.等待服务连接
self.client.wait_for_service(timeout_sec=1.0)
API:等待服务连接
wait_for_service()
/*
参数:
1、等待超时时间
/
3-3.组织请求数据并发送
自定义异步发送服务请求函数
def send_request(self):
self.req = AddInts.Request()
self.req.num1 = int(sys.argv[1])
self.req.num2 = int(sys.argv[2])
self.future = self.cli.call_async(self.req)
API:异步发送服务请求
call_async()
/
参数:
1、服务请求对象 req*/
4.创建对象调用其功能,处理响应结果
4-1.发送请求
client = AddIntsClient() clent.send_request()
4-2.处理响应
rclpy.spin_until_future_complete(minimal_client,minimal_client.future)
API:等待异步操作完成
spin_until_future_cmplete(client,future)
/*
参数:
1、当前客户端对象
2、future 异步操作的结果
*/rclpy.spin_until_future_complete(minimal_client,minimal_client.future) try: response = minimal_client.future.result()//返回响应对象 except Exception as e: minimal_client.get_logger().info('服务请求失败:%r' % (e,) else: minimal_client.get_logger().info( '响应结果:%d + %d = %d' % (minimal_client.req.num1, minimal_client.req.num2, response.sum)