用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/MIUAV/vibe-coding-ros2 --skill ros2-action-communication命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | ros2-action-communication |
| description | ROS2 Action 通讯技能 - ActionServer/ActionClient 实现、目标执行、反馈获取、任务取消 |
| user-invocable | true |
| argument-hint | 创建 action OR ros2 action OR 动作客户端 OR action server client |
ROS2 Action 异步任务执行完整指南
当需要以下帮助时使用此技能:
Goal (目标) ──> ActionServer <─── Execution
^ |
│ v
Feedback <────── Progress
^
│
Result <──────── Completion
#include <rclcpp/rclcpp.hpp>
#include <rclcpp_action/rclcpp_action.hpp>
#include <example_interfaces/action/fibonacci.hpp>
class FibonacciServer : public rclcpp::Node {
public:
using Fibonacci = example_interfaces::action::Fibonacci;
using GoalHandle = rclcpp_action::ServerGoalHandle<Fibonacci>;
FibonacciServer() : Node("fibonacci_server") {
// 创建 ActionServer
action_server_ = rclcpp_action::create_server<Fibonacci>(
this,
"fibonacci",
std::bind(&FibonacciServer::handle_goal, this, std::placeholders::_1, std::placeholders::_2),
std::bind(&FibonacciServer::handle_cancel, this, std::placeholders::_1),
std::bind(&FibonacciServer::handle_accepted, this, std::placeholders::_1));
RCLCPP_INFO(this->get_logger(), "Action server ready");
}
private:
rclcpp_action::Server<Fibonacci>::SharedPtr action_server_;
// 处理新目标
rclcpp_action::GoalResponse handle_goal(
const rclcpp_action::GoalUUID& uuid,
std::shared_ptr<const Fibonacci::Goal> goal) {
RCLCPP_INFO(this->get_logger(), "Received goal with order: %d", goal->order);
return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
}
// 处理取消请求
rclcpp_action::CancelResponse handle_cancel(
const std::shared_ptr<GoalHandle> goal_handle) {
RCLCPP_INFO(this->get_logger(), "Received cancel request");
return rclcpp_action::CancelResponse::ACCEPT;
}
// 处理接受的目标
void handle_accepted(const std::shared_ptr<GoalHandle> goal_handle) {
// 在新线程执行
std::thread([this, goal_handle]() { execute(goal_handle); }).detach();
}
// 执行目标
void execute(const std::shared_ptr<GoalHandle> goal_handle) {
RCLCPP_INFO(this->get_logger(), "Executing goal");
auto feedback = std::make_shared<Fibonacci::Feedback>();
auto& sequence = feedback->partial_sequence;
sequence.push_back(0);
sequence.push_back(1);
auto result = std::make_shared<Fibonacci::Result>();
for (int i = 1; i < goal_handle->get_goal()->order; ++i) {
// 检查取消
if (goal_handle->is_canceling()) {
result->sequence = sequence;
goal_handle->canceled(result);
RCLCPP_INFO(this->get_logger(), "Goal canceled");
return;
}
// 更新序列
sequence.push_back(sequence[i] + sequence[i-1]);
// 发布反馈
goal_handle->publish_feedback(feedback);
RCLCPP_INFO(this->get_logger(), "Published feedback");
// 模拟耗时操作
std::this_thread::sleep_for(1s);
}
// 完成
result->sequence = sequence;
goal_handle->succeed(result);
RCLCPP_INFO(this->get_logger(), "Goal succeeded");
}
};
class FibonacciClient : public rclcpp::Node {
public:
using Fibonacci = example_interfaces::action::Fibonacci;
using GoalHandle = rclcpp_action::ClientGoalHandle<Fibonacci>;
FibonacciClient() : Node("fibonacci_client") {
// 创建 ActionClient
action_client_ = rclcpp_action::create_client<Fibonacci>(
this,
"fibonacci");
// 等待服务可用
if (!action_client_->wait_for_action_server(10s)) {
RCLCPP_ERROR(this->get_logger(), "Action server not available");
return;
}
send_goal();
}
void send_goal() {
auto goal = Fibonacci::Goal();
goal.order = 10;
// 发送目标
auto send_goal_options =
rclcpp_action::Client<Fibonacci>::SendGoalOptions();
// 目标响应回调
send_goal_options.goal_response_callback = [this](
std::shared_ptr<GoalHandle> handle) {
if (!handle) {
RCLCPP_ERROR(this->get_logger(), "Goal was rejected");
} else {
RCLCPP_INFO(this->(), );
goal_handle_ = handle;
}
};
send_goal_options.feedback_callback = [](
std::shared_ptr<GoalHandle> handle,
std::shared_ptr<Fibonacci::Feedback> feedback) {
(->(), ,
feedback->partial_sequence.());
};
send_goal_options.result_callback = [](
rclcpp_action::ClientGoalHandle<Fibonacci>::WrappedResult& result) {
(result.code) {
rclcpp_action::ResultCode::SUCCEEDED:
(->(), );
;
rclcpp_action::ResultCode::CANCELED:
(->(), );
;
rclcpp_action::ResultCode::ABORTED:
(->(), );
;
}
};
action_client_->(goal, send_goal_options);
}
:
rclcpp_action::Client<Fibonacci>::SharedPtr action_client_;
std::shared_ptr<GoalHandle> goal_handle_;
};
void cancel_goal() {
if (goal_handle_) {
auto future = goal_handle_->async_cancel();
if (rclcpp::spin_until_future_complete(this->get_node_base_interface(),
future) == rclcpp::FutureReturnCode::SUCCESS) {
RCLCPP_INFO(this->get_logger(), "Cancel request sent");
}
}
}
import rclpy
from rclpy.node import Node
from rclpy.action import ActionServer
from rclpy.action.server import GoalResponse, CancelResponse
from example_interfaces.action import Fibonacci
class FibonacciServer(Node):
def __init__(self):
super().__init__('fibonacci_server')
self._action_server = ActionServer(
self, Fibonacci, 'fibonacci',
self.execute_callback,
goal_callback=self.goal_callback,
cancel_callback=self.cancel_callback)
def goal_callback(self, goal_handle):
self.get_logger().info(f'Received goal: {goal_handle.request.order}')
return GoalResponse.ACCEPT_AND_EXECUTE
def cancel_callback(self, goal_handle):
self.get_logger().info('Received cancel request')
return CancelResponse.ACCEPT
def execute_callback(self, goal_handle):
self.get_logger().info('Executing goal')
feedback = Fibonacci.Feedback()
feedback.partial_sequence = [0, 1]
i (, goal_handle.request.order):
goal_handle.is_canceling():
goal_handle.canceled()
Fibonacci.Result()
feedback.partial_sequence.append(
feedback.partial_sequence[i] + feedback.partial_sequence[i-])
goal_handle.publish_feedback(feedback)
goal_handle.succeed()
result = Fibonacci.Result()
result.sequence = feedback.partial_sequence
result
class FibonacciClient(Node):
def __init__(self):
super().__init__('fibonacci_client')
self._action_client = ActionClient(self, Fibonacci, 'fibonacci')
def send_goal(self, order=10):
goal = Fibonacci.Goal()
goal.order = order
self._action_client.wait_for_server()
self._send_goal_future = self._action_client.send_goal_async(
goal, feedback_callback=self.feedback_callback)
self._send_goal_future.add_done_callback(self.goal_response_callback)
def goal_response_callback(self, future):
goal_handle = future.result()
if not goal_handle.accepted:
self.get_logger().info('Goal rejected')
return
self.get_logger().info('Goal accepted')
self._result_future = goal_handle.get_result_async()
self._result_future.add_done_callback(self.result_callback)
def feedback_callback(self, feedback_msg):
self.get_logger().info(f'Feedback: {feedback_msg.feedback.partial_sequence}')
():
result = future.result().result
.get_logger().info()
# my_action.action
# Request (请求)
geometry_msgs/Pose target_pose # 目标位置
float64 speed # 运行速度
---
# Feedback (反馈)
float64 progress # 进度 0.0-1.0
string status # 当前状态
---
# Result (结果)
bool success # 是否成功
string message # 消息
geometry_msgs/Pose final_pose # 最终位置
rosidl_generate_interfaces(${PROJECT_NAME}
"action/MyAction.action"
)
<member_of_group>rosidl_interface_packages</member_of_group>
# 列出 action
ros2 action list
# 查看 action 类型
ros2 action type /fibonacci
# 发送 goal
ros2 action send_goal /fibonacci example_interfaces/action/Fibonacci "{order: 10}"
# 查看 action 信息
ros2 action info /fibonacci