# 5. 动作 Action Action 用于 **长时任务**:Goal、Feedback、Result,支持取消与抢占。对标 ROS 2 Action。 | 本文 §5 | 相关文档 | |---------|----------| | 长任务 | [§0 指南](00_guide.md) · [§2 节点 Node](02_node.md) · [commsgs Action](../14_Commsgs/08_nav_planning_msgs.md) | Python Action 示例尚未实现(`py_action_server.py` 为占位);以下以 C++ 与 `examples.proto` 为准。 --- ## 5.1 调用流程
长任务 Client ↔ Server · Goal / Feedback / Result Channel 上封装三种消息(Traits 聚合);异步 Goal、流式 Feedback,可取消与抢占
Client AsyncSendGoal AsyncGetResult · AsyncCancelGoal
Server 工作线程执行 PublishFeedback · SucceededCurrent
要点说明
Traits聚合 Goal / Feedback / Result 三种 protobuf(见下方示例)
与 ServiceService 同步阻塞一轮;Action 异步 + 流式 Feedback
取消AsyncCancelGoalIsCancelRequestedTerminateCurrent
抢占新 Goal → IsPreemptRequestedAcceptPendingGoal
```protobuf message SimpleMessageAction { message Goal { string text = 1; } message Feedback { int32 index = 1; } message Result { bool success = 1; } } ``` ```cpp struct SimpleMessageActionTraits { using Goal = ae::SimpleMessageAction_Goal; using Feedback = ae::SimpleMessageAction_Feedback; using Result = ae::SimpleMessageAction_Result; }; ``` Autonomy 导航 Action 定义见 [commsgs Action](../14_Commsgs/08_nav_planning_msgs.md)。 --- ## 5.2 SimpleActionServer `action_listener.cpp` 使用 `SimpleActionServer`,在 goal 被接受后于 **工作线程** 执行: ```cpp constexpr char kActionName[] = "examples/simple_message_action"; void RunAcceptedGoal(const std::shared_ptr& server) { GoalPtr goal = server->GetCurrentGoal(); AINFO << "Executing goal, text=\"" << goal->text() << "\""; for (int i = 0; i < kFeedbackSteps; ++i) { if (server->IsCancelRequested()) { ResultPtr aborted = std::make_shared(); aborted->set_success(false); server->TerminateCurrent(aborted); return; } if (server->IsPreemptRequested()) { server->AcceptPendingGoal(); // 切换至 pending goal break; } FeedbackPtr fb = std::make_shared(); fb->set_index(i); server->PublishFeedback(fb); std::this_thread::sleep_for(kFeedbackPeriod); } ResultPtr ok = std::make_shared(); ok->set_success(true); server->SucceededCurrent(ok); } int main(int argc, char* argv[]) { autolink::Init(argv[0]); auto node = autolink::CreateNode(node_name); std::shared_ptr server; server = std::make_shared( node, kActionName, [&server]() { RunAcceptedGoal(server); }); // execute 回调 autolink::WaitForShutdown(); } ``` **关键 API**: | 方法 | 用途 | |------|------| | `GetCurrentGoal()` | 当前执行中的 goal | | `PublishFeedback(fb)` | 推送进度 | | `IsCancelRequested()` | 客户端请求取消 | | `IsPreemptRequested()` | 新 goal 抢占 | | `AcceptPendingGoal()` | 切换到 pending goal | | `SucceededCurrent(result)` | 成功结束 | | `TerminateCurrent(result)` | 取消 / 异常结束 | --- ## 5.3 AsyncSendGoal `action_talker.cpp` 演示 Client 侧完整流程: ```cpp auto client = autolink::action::CreateClient( node, kActionName); // 1. 等待 Server 就绪 while (autolink::OK() && !client->ActionServerIsReady()) { std::this_thread::sleep_for(kWaitServerReady); } // 2. 构造 Goal 与回调选项 SimpleMessageActionTraits::Goal goal; goal.set_text("hello from action_talker"); ActionClient::SendGoalOptions opts; opts.goal_response_callback = [](std::shared_ptr gh) { if (!gh) AWARN << "Goal rejected by server"; }; opts.feedback_callback = [](auto gh, auto fb) { if (fb) AINFO << "Feedback index=" << fb->index(); }; // 3. 发送并等待接受 const auto accepted_future = client->AsyncSendGoal(goal, opts); accepted_future.wait_for(kAcceptTimeout); std::shared_ptr handle = accepted_future.get(); // 4. 等待最终结果 auto result_future = handle->AsyncGetResult(); result_future.wait_for(kResultTimeout); LogActionOutcome(handle, result_future.get()); ``` `GoalHandle::WrappedResult` 含终端状态:`SUCCEEDED`、`CANCELED`、`ABORTED` 等,可用 `autolink::action::ToString(wr.code)` 打印。 --- ## 5.4 运行示例 ```bash export AUTOLINK_PATH=... cd build/autolink/bin/examples # terminal 1 — 必须先启 Server ./action_listener # terminal 2 ./action_talker ``` 预期日志:Server 周期 `feedback index=0..N`,Client 打印 `Goal accepted` 与 `Action terminal: SUCCEEDED`。 --- ## 5.5 集成要点 - **Execute 在工作线程**:`SimpleActionServer` 的 execute 回调内长循环会阻塞新 goal 接受。 - **Feedback**:Server 调用 `PublishFeedback`;Client 注册 `feedback_callback`。 - **Autonomy**:Navigator 以 Action Client 调用 Controller,消息定义见 [commsgs](../14_Commsgs/08_nav_planning_msgs.md)。 --- **导航**:[← §4 服务 Service](04_service.md) · [§0 指南](00_guide.md) · [§6 参数 Parameter →](06_parameter.md)