用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/MIUAV/vibe-coding-ros2 --skill ros2-service-communication命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | ros2-service-communication |
| description | ROS2 Service 通讯技能 - 服务端/客户端实现、同步/异步调用、常见服务类型 |
| user-invocable | true |
| argument-hint | 创建 service OR ros2 service OR 服务端客户端 OR server client |
ROS2 Service 服务通讯完整指南
当需要以下帮助时使用此技能:
Client (客户端) ──[Request]──> Server (服务端)
<──[Response]──
# 内置服务
/reset_positions # 关节复位
/set_light_state # 设置灯光
/get_map # 获取地图
# 自定义服务
/robot_control/ExecuteTrajectory
/navigation/SetGoal
#include <rclcpp/rclcpp.hpp>
#include <std_srvs/srv/set_bool.hpp>
class ServerNode : public rclcpp::Node {
public:
ServerNode() : Node("server_node") {
// 创建服务服务端
server_ = this->create_service<std_srvs::srv::SetBool>(
"/enable",
[this](const std::shared_ptr<rmw_request_id_t> request_id,
const std::shared_ptr<std_srvs::srv::SetBool::Request> request,
const std::shared_ptr<std_srvs::srv::SetBool::Response> response) {
RCLCPP_INFO(this->get_logger(), "Received request: %s",
request->data ? "true" : "false");
response->success = true;
response->message = "Processed successfully";
});
RCLCPP_INFO(this->get_logger(), "Service server ready");
}
private:
rclcpp::Service<std_srvs::srv::SetBool>::SharedPtr server_;
};
class StatefulServerNode : public rclcpp::Node {
public:
StatefulServerNode() : Node("stateful_server"), enabled_(false) {
server_ = this->create_service<std_srvs::srv::SetBool>(
"/set_state",
[this](const auto& request, auto& response) {
enabled_ = request->data;
response->success = true;
response->message = enabled_ ? "Enabled" : "Disabled";
RCLCPP_INFO(this->get_logger(), "State: %s",
enabled_ ? "enabled" : "disabled");
});
}
private:
bool enabled_;
rclcpp::Service<std_srvs::srv::SetBool>::SharedPtr server_;
};
class SyncClientNode : public rclcpp::Node {
public:
SyncClientNode() : Node("sync_client") {
client_ = this->create_client<std_srvs::srv::SetBool>("/enable");
// 等待服务可用
while (!client_->wait_for_service(1s)) {
if (!rclcpp::ok()) {
RCLCPP_ERROR(this->get_logger(), "Interrupted");
return;
}
RCLCPP_INFO(this->get_logger(), "Waiting for service...");
}
// 发送请求
auto request = std::make_shared<std_srvs::srv::SetBool::Request>();
request->data = true;
auto future = client_->async_send_request(request);
// 等待响应
if (rclcpp::spin_until_future_complete(this->get_node_base_interface(),
future) == rclcpp::FutureReturnCode::SUCCESS) {
auto response = future.get();
RCLCPP_INFO(this->get_logger(), "Response: %s, %s",
response->success ? "success" : "failed",
response->message.());
} {
(->(), );
}
}
:
rclcpp::Client<std_srvs::srv::SetBool>::SharedPtr client_;
};
class AsyncClientNode : public rclcpp::Node {
public:
AsyncClientNode() : Node("async_client") {
client_ = this->create_client<std_srvs::srv::SetBool>("/enable");
auto request = std::make_shared<std_srvs::srv::SetBool::Request>();
request->data = true;
client_->async_send_request(
request,
[this](rclcpp::Client<std_srvs::srv::SetBool>::SharedFuture future) {
auto response = future.get();
RCLCPP_INFO(this->get_logger(), "Async response: %s",
response->message.c_str());
});
}
private:
rclcpp::Client<std_srvs::srv::SetBool>::SharedPtr client_;
};
import rclpy
from rclpy.node import Node
from std_srvs.srv import SetBool
class ServerNode(Node):
def __init__(self):
super().__init__('server_node')
self.srv = self.create_service(SetBool, '/enable', self.callback)
def callback(self, request, response):
self.get_logger().info(f'Request: {request.data}')
response.success = True
response.message = 'Processed'
return response
class ClientNode(Node):
def __init__(self):
super().__init__('client_node')
self.cli = self.create_client(SetBool, '/enable')
self.req = SetBool.Request()
self.req.data = True
while not self.cli.wait_for_service(timeout=1.0):
self.get_logger().info('Waiting...')
self.future = self.cli.call_async(self.req)
def timer_callback(self):
if self.future.done():
try:
response = self.future.result()
self.get_logger().info(f'Response: {response.message}')
except Exception as e:
self.get_logger().error(f'Service call failed: {e}')
# my_service.srv
---
# Response (响应)
bool success # 是否成功
string message # 消息
string[] data # 返回的数据列表
---
# Request (请求) - 放在上面
bool enable # 启用标志
string mode # 运行模式
float64 timeout # 超时时间
find_package(ament_cmake REQUIRED)
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
"srv/MyService.srv"
"msg/MyMessage.msg"
)
# 依赖其他包
rosidl_get_typesupport_target(pkg_config ${PROJECT_NAME}
${FOO_PACKAGE} "rosidl_typesupport_cpp")
<depend>rosidl_default_generators</depend>
<member_of_group>rosidl_interface_packages</member_of_group>
class MultiClientNode : public rclcpp::Node {
public:
MultiClientNode() : Node("multi_client") {
// 创建多个服务客户端
clients_["robot1"] = this->create_client<MyService>("/robot1/do_action");
clients_["robot2"] = this->create_client<MyService>("/robot2/do_action");
// 并发调用
for (auto& [name, client] : clients_) {
auto request = std::make_shared<MyService::Request>();
request->task = "execute";
client->async_send_request(request,
[name](auto future) {
RCLCPP_INFO(rclcpp::get_logger("multi_client"),
"%s: %s", name.c_str(),
future.get()->result.c_str());
});
}
}
private:
std::map<std::string, rclcpp::Client<MyService>::SharedPtr> clients_;
};
class PeriodicClientNode : public rclcpp::Node {
public:
PeriodicClientNode() : Node("periodic_client") {
client_ = this->create_client<std_srvs::srv::SetBool>("/status");
timer_ = this->create_wall_timer(5s, [this]() {
auto request = std::make_shared<std_srvs::srv::SetBool::Request>();
request->data = true;
auto future = client_->async_send_request(request);
rclcpp::sleep_for(100ms); // 简短等待
if (future.valid()) {
auto response = future.get();
// 处理响应
}
});
}
private:
rclcpp::Client<std_srvs::srv::SetBool>::SharedPtr client_;
rclcpp::TimerBase::SharedPtr timer_;
};
class ServiceChainNode : public rclcpp::Node {
public:
ServiceChainNode() : Node("service_chain") {
sub_ = this->create_subscription<std_msgs::msg::String>(
"/input", 10, [this](const auto& msg) {
call_service_a(msg->data);
});
client_a_ = this->create_client<MyService>("/service_a");
client_b_ = this->create_client<MyService>("/service_b");
}
void call_service_a(const std::string& data) {
auto req = std::make_shared<MyService::Request>();
req->input = data;
client_a_->async_send_request(req,
[this](auto future) {
auto response = future.get();
if (response->success) {
call_service_b(response->output);
}
});
}
void call_service_b(const std::string& data) {
auto req = std::make_shared<MyService::Request>();
req->input = data;
client_b_->async_send_request(req,
[](auto future) {
});
}
};
# 列出服务
ros2 service list
# 查看服务类型
ros2 service type /service_name
# 调用服务
ros2 service call /enable std_srvs/srv/SetBool "{data: true}"
# 查找服务提供者
ros2 service find std_srvs/srv/SetBool
# 检查服务列表
ros2 service list
# 检查节点
ros2 node list
ros2 node info /node_name
# 等待服务
ros2 service call /service std_srvs/srv/SetBool "{data: true}"
# 使用 --help 查看详细用法
ros2 service call --help
# 调试输出
ros2 service call /enable std_srvs/srv/SetBool "{data: true}" -v
/robot/arm/move_to