#include "goal_source_adapter.h" #include #include namespace mission_plugins { mission_adapters::MissionSourceAdapter::Ptr GoalSourceAdapter::create() { return std::make_shared(); } bool GoalSourceAdapter::configure(const std::string& name, robot::NodeHandle& nh) { (void)nh; // nguồn này chưa có param riêng name_ = name; return true; } std::string GoalSourceAdapter::schema() const { return mission_adapters::schema::kPoseStamped; } bool GoalSourceAdapter::validate(const mission_adapters::MissionRequest& request, std::string& reason) const { if (!request.pose) { reason = "request is missing the pose payload"; return false; } const auto& position = request.pose->pose.position; const auto& orientation = request.pose->pose.orientation; // NaN/Inf từ host phải bị chặn ngay tại biên: lọt xuống dưới thì mọi phép so khoảng cách tới // goal đều trả false và robot chạy tới khi có người bấm dừng. if (!std::isfinite(position.x) || !std::isfinite(position.y) || !std::isfinite(position.z)) { reason = "goal contains NaN/Inf in position"; return false; } if (!std::isfinite(orientation.x) || !std::isfinite(orientation.y) || !std::isfinite(orientation.z) || !std::isfinite(orientation.w)) { reason = "goal contains NaN/Inf in orientation"; return false; } // Quaternion toàn 0 là lỗi hay gặp khi host quên set orientation — nó không phải "hướng bất kỳ", // nó là dữ liệu hỏng. const double norm_squared = orientation.x * orientation.x + orientation.y * orientation.y + orientation.z * orientation.z + orientation.w * orientation.w; if (std::sqrt(norm_squared) < kMinQuaternionNorm) { reason = "goal has a quaternion that cannot be normalized (norm ~ 0)"; return false; } return true; } mission_adapters::ConversionResult GoalSourceAdapter::convert(const mission_adapters::MissionRequest& request) { mission_adapters::ConversionResult result; if (!request.pose) return result; auto mission = std::make_shared(); mission->type = mission_adapters::MissionType::SIMPLE_GOAL; mission->goal = *request.pose; mission->motion_hint = "position"; // Goal đơn lẻ luôn thay việc đang chạy: người dùng bấm một đích mới nghĩa là bỏ đích cũ. result.mode = mission_adapters::SubmitMode::kReplace; result.missions.push_back(mission); return result; } } // namespace mission_plugins BOOST_DLL_ALIAS(mission_plugins::GoalSourceAdapter::create, GoalSourceAdapter)