ROS2 服务
是什么?
ROS2平台上的一种 通信机制 ,
组成: 生产端(producer) 和 消费端(consumer)
作用: 消费端(consumer) 提出 请求(request) , 生产端(producer) 返回 回复(response)
特点在于消费端
代码快速开发
代码逻辑
创建生产端对象 -> 创建服务 -> 编写服务回调函数(收到 请求(request) 做什么,返回怎么样的 回复(response))
创建消费端对象 -> 关联服务 -> 编写 请求(request) (根据消息格式定义 请求(request) 内容) -> 编写服务端返回结果回调函数(收到 回复(response),做什么)
代码框架
生产端(producer)
创建生产端
1
2
3
4
5/* srv1.创建生产端服务 */
srv_producer_temp_ = this->create_service<SrvInterface>(
"srv_temp",
std::bind(&SrvProducerTemp::srv_producer_temp_callback, this, std::placeholders::_1, std::placeholders::_2));
// 指定服务名称,(未知参数),回调函数编写服务回调函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25/* srv2.服务回调函数 */
void srv_producer_temp_callback(const std::shared_ptr<SrvInterface::Request> request, const std::shared_ptr<SrvInterface::Response> response)
{
/* srv2.1 处理服务端响应 */
int8_t length = request->test_request_data;
RCLCPP_INFO(this->get_logger(), "SrvProducerTemp received request with length %d", length);
/* srv2.2 返回响应结果 */
response->test_response_data = SrvInterface::Response::SUCCESS; // 调用常量,返回响应结果
// 数组操作示例/参数调用示例
if (param_name2_ > 0 && length > param_name2_)
{
response->test_response_data = SrvInterface::Response::SUCCESS;
response->test_array_data.resize(length); // 确保数组有足够的空间
for (int i = 0; i < param_name2_; i++)
{
response->test_array_data[i] = i;
}
}
else
{
response->test_response_data = SrvInterface::Response::FAILURE;
}
}*声明和获取参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30/* srv3.声明和获取参数*/
this->declare_parameter("param_name1", 1.0);
this->declare_parameter("param_name2", 1);
this->get_parameter("param_name1", param_name1_);
this->get_parameter("param_name2", param_name2_);
// 添加参数设置回调
parameters_callback_handle_ = this->add_on_set_parameters_callback(
[&](const std::vector<rclcpp::Parameter> ¶ms)
-> rcl_interfaces::msg::SetParametersResult
{
// 遍历参数
for (auto param : params)
{
if (param.get_name() == "param_name1")
{
RCLCPP_INFO(this->get_logger(), "更新参数 %s 值为:%f", param.get_name().c_str(), param.as_double());
param_name1_ = param.as_double();
}
else if (param.get_name() == "param_name2")
{
RCLCPP_INFO(this->get_logger(), "更新参数 %s 值为:%ld", param.get_name().c_str(), param.as_int());
param_name2_ = param.as_int();
}
}
auto result = rcl_interfaces::msg::SetParametersResult();
result.successful = true;
return result;
});
消费端(consumer)代码框架
创建消费端(consumer)
1
2srv_consumer_temp_ = this->create_client<SrvInterface>("srv_temp"); // 请求服务的名称
编写发送请求逻辑
等待服务端上线
1
2
3
4
5
6
7
8
9
10
11/* cli2.1等待服务端上线 */
while (!srv_consumer_temp_->wait_for_service(1s))
{
// 等待时检测rclcpp的状态
if (!rclcpp::ok())
{
RCLCPP_ERROR(this->get_logger(), "等待服务的过程中被打断...");
return;
}
RCLCPP_INFO(this->get_logger(), "等待服务端上线中");
}构造请求
1
2
3/* cli2.2构造请求*/
auto request = std::make_shared<SrvInterface::Request>();
request->test_request_data = 10;发送请求
1
2
3/* cli2.3发送异步请求,然后等待返回,返回时调用回调函数*/
// 回调函数见 SrvConsumerTemp::srv_consumer_temp_callback()
srv_consumer_temp_->async_send_request(request, std::bind(&SrvConsumerTemp::srv_consumer_temp_callback, this, std::placeholders::_1));编写服务端返回结果回调函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16/* 服务端返回结果回调函数 */
void srv_consumer_temp_callback(std::shared_future<typename SrvInterface::Response::SharedPtr> result_future)
{
/* cli2.4获取和处理服务端返回的结果 */
auto response = result_future.get();
/* cli2.4处理服务端返回的结果 */
if (response->test_response_data == SrvInterface::Response::SUCCESS)
{
RCLCPP_INFO(this->get_logger(), "处理成功");
}
else if (response->test_response_data == SrvInterface::Response::FAILURE)
{
RCLCPP_INFO(this->get_logger(), "处理失败");
}
}
*编写参数修改请求函数(服务请求另一种实现方式)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64/* 参数修改请求函数*/
void param_modify_request(int new_value)
{
/* par1.创建参数修改请求 */
auto param = rcl_interfaces::msg::Parameter();
param.name = "param_name2"; // 参数名称
auto param_value = rcl_interfaces::msg::ParameterValue(); // 参数值对象
param_value.type = rclcpp::ParameterType::PARAMETER_INTEGER; // 参数类型
param_value.integer_value = new_value; // 参数值
param.value = param_value;
/* par2.发送请求函数 */
// 见 SrvConsumerTemp::param_modify_request_send()
auto response = param_modify_request_send(param);
/* par3.处理返回结果 */
if (response == nullptr)
{
RCLCPP_WARN(this->get_logger(), "参数修改失败");
return;
}
else
{
for (auto result : response->results)
{
if (result.successful)
{
RCLCPP_INFO(this->get_logger(), "参数 已修改为:%d", new_value);
}
else
{
RCLCPP_WARN(this->get_logger(), "参数 修改失败, 失败原因:%s", result.reason.c_str());
}
}
}
};
/* 参数修改请求发送函数 */
std::shared_ptr<rcl_interfaces::srv::SetParameters::Response> param_modify_request_send(rcl_interfaces::msg::Parameter param)
{
/* par2.1创建客户端 */
auto param_client = this->create_client<rcl_interfaces::srv::SetParameters>(
"/srv_producer_temp_node/set_parameters");
/* par2.2等待服务端上线 */
while (!param_client->wait_for_service(1s))
{
// 等待时检测rclcpp的状态
if (!rclcpp::ok())
{
RCLCPP_ERROR(this->get_logger(), "等待服务的过程中被打断...");
return nullptr;
}
RCLCPP_INFO(this->get_logger(), "等待参数修改服务端上线中");
}
/* par2.3构造请求 */
auto request = std::make_shared<rcl_interfaces::srv::SetParameters::Request>();
request->parameters.push_back(param);
/* par2.4发送请求 */
auto response_future = param_client->async_send_request(request);
/* par2.5等待返回结果 */
rclcpp::spin_until_future_complete(this->get_node_base_interface(), response_future);
/* par2.6获取返回结果 */
auto response = response_future.get();
return response;
}