5. 动作 Action

Action 用于 长时任务:Goal、Feedback、Result,支持取消与抢占。对标 ROS 2 Action。

本文 §5

相关文档

长任务

§0 指南 · §2 节点 Node · commsgs Action

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
message SimpleMessageAction {
    message Goal   { string text = 1; }
    message Feedback { int32 index = 1; }
    message Result { bool success = 1; }
}
struct SimpleMessageActionTraits {
    using Goal = ae::SimpleMessageAction_Goal;
    using Feedback = ae::SimpleMessageAction_Feedback;
    using Result = ae::SimpleMessageAction_Result;
};

Autonomy 导航 Action 定义见 commsgs Action


5.2 SimpleActionServer

action_listener.cpp 使用 SimpleActionServer,在 goal 被接受后于 工作线程 执行:

constexpr char kActionName[] = "examples/simple_message_action";

void RunAcceptedGoal(const std::shared_ptr<ActionServer>& 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<Result>();
            aborted->set_success(false);
            server->TerminateCurrent(aborted);
            return;
        }
        if (server->IsPreemptRequested()) {
            server->AcceptPendingGoal();   // 切换至 pending goal
            break;
        }
        FeedbackPtr fb = std::make_shared<Feedback>();
        fb->set_index(i);
        server->PublishFeedback(fb);
        std::this_thread::sleep_for(kFeedbackPeriod);
    }

    ResultPtr ok = std::make_shared<Result>();
    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<ActionServer> server;
    server = std::make_shared<ActionServer>(
        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 侧完整流程:

auto client = autolink::action::CreateClient<SimpleMessageActionTraits>(
    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<GoalHandle> 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<GoalHandle> handle = accepted_future.get();

// 4. 等待最终结果
auto result_future = handle->AsyncGetResult();
result_future.wait_for(kResultTimeout);
LogActionOutcome(handle, result_future.get());

GoalHandle::WrappedResult 含终端状态:SUCCEEDEDCANCELEDABORTED 等,可用 autolink::action::ToString(wr.code) 打印。


5.4 运行示例

export AUTOLINK_PATH=...
cd build/autolink/bin/examples

# terminal 1 — 必须先启 Server
./action_listener

# terminal 2
./action_talker

预期日志:Server 周期 feedback index=0..N,Client 打印 Goal acceptedAction terminal: SUCCEEDED


5.5 集成要点

  • Execute 在工作线程SimpleActionServer 的 execute 回调内长循环会阻塞新 goal 接受。

  • Feedback:Server 调用 PublishFeedback;Client 注册 feedback_callback

  • Autonomy:Navigator 以 Action Client 调用 Controller,消息定义见 commsgs


导航← §4 服务 Service · §0 指南 · §6 参数 Parameter →