126 lines
4.1 KiB
C++
126 lines
4.1 KiB
C++
|
#include "cyberdog_marker/marker_service.hpp"
|
||
|
|
||
|
namespace cyberdog
|
||
|
{
|
||
|
namespace marker
|
||
|
{
|
||
|
|
||
|
MarkerService::MarkerService(const rclcpp::NodeOptions & options)
|
||
|
: Node("cyberdog_marker_service", options),
|
||
|
marker_count_(0)
|
||
|
{
|
||
|
// 创建服务提供位置标记功能
|
||
|
place_marker_service_ = create_service<cyberdog_marker::srv::PlaceMarker>(
|
||
|
"place_marker",
|
||
|
std::bind(
|
||
|
&MarkerService::handle_place_marker, this,
|
||
|
std::placeholders::_1, std::placeholders::_2));
|
||
|
|
||
|
// 创建客户端连接到Gazebo的spawn_entity服务
|
||
|
spawn_entity_client_ = create_client<gazebo_msgs::srv::SpawnEntity>("spawn_entity");
|
||
|
|
||
|
RCLCPP_INFO(get_logger(), "Marker service started");
|
||
|
}
|
||
|
|
||
|
void MarkerService::handle_place_marker(
|
||
|
const std::shared_ptr<cyberdog_marker::srv::PlaceMarker::Request> request,
|
||
|
std::shared_ptr<cyberdog_marker::srv::PlaceMarker::Response> response)
|
||
|
{
|
||
|
// 等待Gazebo服务可用
|
||
|
if (!spawn_entity_client_->wait_for_service(std::chrono::seconds(5))) {
|
||
|
response->success = false;
|
||
|
response->message = "Gazebo spawn_entity service not available";
|
||
|
RCLCPP_ERROR(get_logger(), "%s", response->message.c_str());
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// 生成唯一的标记名称
|
||
|
marker_count_++;
|
||
|
std::string marker_name = "marker_" + std::to_string(marker_count_);
|
||
|
|
||
|
// 生成SDF标记内容
|
||
|
std::string marker_sdf = generate_marker_sdf(request->color);
|
||
|
|
||
|
// 创建spawn_entity请求
|
||
|
auto spawn_request = std::make_shared<gazebo_msgs::srv::SpawnEntity::Request>();
|
||
|
spawn_request->name = marker_name;
|
||
|
spawn_request->xml = marker_sdf;
|
||
|
spawn_request->robot_namespace = "";
|
||
|
|
||
|
// 设置标记位置
|
||
|
spawn_request->initial_pose.position.x = request->x;
|
||
|
spawn_request->initial_pose.position.y = request->y;
|
||
|
spawn_request->initial_pose.position.z = request->z;
|
||
|
spawn_request->initial_pose.orientation.w = 1.0;
|
||
|
|
||
|
// 发送请求
|
||
|
auto future = spawn_entity_client_->async_send_request(spawn_request);
|
||
|
|
||
|
// 等待响应
|
||
|
if (rclcpp::spin_until_future_complete(shared_from_this(), future) ==
|
||
|
rclcpp::FutureReturnCode::SUCCESS)
|
||
|
{
|
||
|
auto spawn_response = future.get();
|
||
|
response->success = spawn_response->success;
|
||
|
if (response->success) {
|
||
|
response->message = "Successfully placed marker '" + marker_name + "' at ("
|
||
|
+ std::to_string(request->x) + ", "
|
||
|
+ std::to_string(request->y) + ", "
|
||
|
+ std::to_string(request->z) + ")";
|
||
|
} else {
|
||
|
response->message = "Failed to place marker: " + spawn_response->status_message;
|
||
|
}
|
||
|
} else {
|
||
|
response->success = false;
|
||
|
response->message = "Failed to call spawn_entity service";
|
||
|
}
|
||
|
|
||
|
RCLCPP_INFO(get_logger(), "%s", response->message.c_str());
|
||
|
}
|
||
|
|
||
|
std::string MarkerService::generate_marker_sdf(const std::string & color, double radius)
|
||
|
{
|
||
|
// 解析颜色
|
||
|
double r = 1.0, g = 0.0, b = 0.0; // 默认红色
|
||
|
if (color == "red") {
|
||
|
r = 1.0; g = 0.0; b = 0.0;
|
||
|
} else if (color == "green") {
|
||
|
r = 0.0; g = 1.0; b = 0.0;
|
||
|
} else if (color == "blue") {
|
||
|
r = 0.0; g = 0.0; b = 1.0;
|
||
|
} else if (color == "yellow") {
|
||
|
r = 1.0; g = 1.0; b = 0.0;
|
||
|
}
|
||
|
|
||
|
// 创建SDF模型
|
||
|
std::stringstream sdf;
|
||
|
sdf << "<?xml version='1.0'?>\n"
|
||
|
<< "<sdf version='1.6'>\n"
|
||
|
<< " <model name='marker'>\n"
|
||
|
<< " <static>true</static>\n"
|
||
|
<< " <link name='link'>\n"
|
||
|
<< " <visual name='visual'>\n"
|
||
|
<< " <cast_shadows>false</cast_shadows>\n"
|
||
|
<< " <geometry>\n"
|
||
|
<< " <sphere>\n"
|
||
|
<< " <radius>" << radius << "</radius>\n"
|
||
|
<< " </sphere>\n"
|
||
|
<< " </geometry>\n"
|
||
|
<< " <material>\n"
|
||
|
<< " <ambient>" << r << " " << g << " " << b << " 1</ambient>\n"
|
||
|
<< " <diffuse>" << r << " " << g << " " << b << " 1</diffuse>\n"
|
||
|
<< " <specular>0.1 0.1 0.1 1</specular>\n"
|
||
|
<< " </material>\n"
|
||
|
<< " </visual>\n"
|
||
|
<< " </link>\n"
|
||
|
<< " </model>\n"
|
||
|
<< "</sdf>";
|
||
|
|
||
|
return sdf.str();
|
||
|
}
|
||
|
|
||
|
} // namespace marker
|
||
|
} // namespace cyberdog
|
||
|
|
||
|
#include "rclcpp_components/register_node_macro.hpp"
|
||
|
RCLCPP_COMPONENTS_REGISTER_NODE(cyberdog::marker::MarkerService)
|