ros2_action_0">ros2 action相关
总体代码参考:
一定要先看这里的示例,后续是对这个示例的说明补充
重点关注execute中,思考action的客户端与服务端联动过程中需要的是,任务执行的一些状态信息交互,就能明补execute为什么这样写了
代码讲解
void execute(const std::shared_ptr<GoalHandleFibonacci> goal_handle)
{// 日志:开始执行目标RCLCPP_INFO(this->get_logger(), "Executing goal");// 设置循环频率为 1Hz(每秒执行一次)rclcpp::Rate loop_rate(1);// 获取目标参数(目标中的 Fibonacci 序列长度)const auto goal = goal_handle->get_goal();// 创建用于发送反馈的对象auto feedback = std::make_shared<Fibonacci::Feedback>();// 获取部分序列引用,初始时只包含两个数字 0 和 1auto & sequence = feedback->partial_sequence;sequence.push_back(0);sequence.push_back(1);// 创建结果对象,用于在目标完成时返回整个序列auto result = std::make_shared<Fibonacci::Result>();// 循环从 1 开始生成 Fibonacci 数列,直到达到目标数列长度或 ROS 停止for (int i = 1; (i < goal->order) && rclcpp::ok(); ++i) {// 检查是否有取消请求if (goal_handle->is_canceling()) {// 如果取消请求存在,将当前已生成的部分序列返回,并标记为取消result->sequence = sequence;goal_handle->canceled(result);RCLCPP_INFO(this->get_logger(), "Goal canceled");return; // 退出函数,停止执行}// 按照 Fibonacci 规则更新序列:每个数字是前两个数字的和sequence.push_back(sequence[i] + sequence[i - 1]);// 发布当前的反馈,更新部分已生成的 Fibonacci 序列goal_handle->publish_feedback(feedback);RCLCPP_INFO(this->get_logger(), "Publish feedback");// 按照 1Hz 的频率暂停,以保持循环节奏loop_rate.sleep();}// 如果目标完成并且没有被取消,且 ROS 正常运行if (rclcpp::ok()) {// 将生成的完整序列设置为结果result->sequence = sequence;// 标记目标完成,返回结果goal_handle->succeed(result);RCLCPP_INFO(this->get_logger(), "Goal succeeded");}
}
代码讲解:
- 初始化:goal_handle->get_goal() 获取传入的目标,它包含 Fibonacci 数列的目标长度(即需要生成多少个数字)。
初始化反馈的部分序列 sequence,最初包含 Fibonacci 数列的前两个元素 0 和 1。 - 反馈循环:通过 for 循环,逐步生成 Fibonacci 数列的后续数字。每次计算后,调用 publish_feedback(feedback) 发布当前生成的部分序列作为反馈。
循环每次睡眠 1 秒(通过 rclcpp::Rate(1) 控制),以模拟逐步计算的过程。 - 取消处理:在每次循环开始时,检查是否有取消请求 (goal_handle->is_canceling())。
如果接收到取消请求,服务器将返回已经计算的部分数列,调用 goal_handle->canceled(result) 标记该目标被取消,并退出执行函数。 - 目标完成:循环结束后,检查 ROS 是否在正常运行(rclcpp::ok()),如果是,意味着计算成功完成。
将最终计算的完整 Fibonacci 序列返回,并调用 goal_handle->succeed(result) 标记目标成功完成。
自带接口说明
get_goal()
、succeed(result)
、publish_feedback(feedback)
这些都是 ROS 2 动作接口提供的函数,用于处理动作服务器与客户端之间的通信,尤其是在动作(action)的目标执行、反馈、取消、以及结果返回方面。
我将详细解释这些接口,并讲解哪些是 Fibonacci
动作定义中的变量。
1. 动作接口函数
这些函数是 ROS 2 动作库中的标准接口,用于处理动作请求和响应:
-
get_goal()
:
这个函数用于获取客户端发送给动作服务器的目标(goal)。目标通常包含需要服务器执行的动作的参数。在你的例子中,目标就是 Fibonacci 数列的长度(order),即客户端要求生成的数列长度。 -
succeed(result)
:
这个函数用于通知动作服务器,目标执行已成功完成,并返回最终的结果。result
包含的是动作完成后的最终数据。在 Fibonacci 的例子中,result->sequence
是生成的完整 Fibonacci 序列。 -
publish_feedback(feedback)
:
这个函数用于发送反馈信息给客户端。在执行长时间任务时,服务器可以定期通过反馈将当前的状态或中间结果发送给客户端。在这个例子中,feedback->partial_sequence
是已经计算出的 Fibonacci 序列的部分数据。
这些接口函数是动作库的一部分,适用于任何 ROS 2 动作,不仅限于 Fibonacci 示例。
2. Fibonacci 动作中的定义变量
在 ROS 2 动作中,消息定义文件通常包含 三个部分:goal
(目标)、feedback
(反馈)、result
(结果)。在 Fibonacci 动作中,它们可能被定义如下:
action"># Fibonacci.action# Goal definition (目标)
int32 order # 要生成的 Fibonacci 数列的长度---
# Result definition (结果)
int32[] sequence # 完整的 Fibonacci 数列---
# Feedback definition (反馈)
int32[] partial_sequence # 部分生成的 Fibonacci 数列
具体来说:
-
Goal 部分:
int32 order
: 这是客户端传递给服务器的目标数据,表示要生成的 Fibonacci 数列长度。在代码中,使用goal_handle->get_goal()->order
获取这个值。
-
Result 部分:
int32[] sequence
: 最终的 Fibonacci 数列,服务器在成功完成目标后返回给客户端。它在代码中通过result->sequence
进行访问,并在目标完成时通过goal_handle->succeed(result)
返回。
-
Feedback 部分:
int32[] partial_sequence
: 当前生成的部分 Fibonacci 数列,服务器在执行过程中不断更新并通过goal_handle->publish_feedback(feedback)
发送反馈给客户端。在代码中,它通过feedback->partial_sequence
来访问和更新。
总结
get_goal()
: 从Goal
获取动作的目标(如 Fibonacci 数列长度)。succeed(result)
: 当动作成功完成时返回Result
(如完整的 Fibonacci 序列)。publish_feedback(feedback)
: 在执行过程中发送Feedback
(如部分生成的 Fibonacci 序列)。
Fibonacci 动作中的变量是 Goal
的 order
、Result
的 sequence
和 Feedback
的 partial_sequence
,这些都在代码中分别用于获取目标、生成反馈和返回结果。