diff --git a/src/target_selector_pkg/CMakeLists.txt b/src/target_selector_pkg/CMakeLists.txt new file mode 100644 index 0000000..b76bd7e --- /dev/null +++ b/src/target_selector_pkg/CMakeLists.txt @@ -0,0 +1,54 @@ +cmake_minimum_required(VERSION 3.8) +project(target_selector_pkg) + + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# Find dependencies +find_package(visualization_msgs REQUIRED) +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(std_msgs REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(cv_bridge REQUIRED) +find_package(image_transport REQUIRED) +find_package(OpenCV REQUIRED) # Ensure OpenCV is found +find_package(vision_msgs REQUIRED) + +# Declare Executables +add_executable(target_selector_node target_selector_node.cpp) + + + +# Link Dependencies for target_selector_node +ament_target_dependencies(target_selector_node + rclcpp + std_msgs + vision_msgs + visualization_msgs +) + +# OpenCV linking +include_directories(${OpenCV_INCLUDE_DIRS}) + +# Compiler Features +target_compile_features(target_selector_node PUBLIC c_std_99 cxx_std_17) + +# Install Executables + + +install(TARGETS target_selector_node + DESTINATION lib/${PROJECT_NAME} +) + + +if(BUILD_TESTING) + find_package(ament_lint_auto REQUIRED) + set(ament_cmake_copyright_FOUND TRUE) + set(ament_cmake_cpplint_FOUND TRUE) + ament_lint_auto_find_test_dependencies() +endif() + +ament_package() diff --git a/src/target_selector_pkg/package.xml b/src/target_selector_pkg/package.xml new file mode 100644 index 0000000..994fc84 --- /dev/null +++ b/src/target_selector_pkg/package.xml @@ -0,0 +1,23 @@ + + + + target_selector_pkg + 0.0.0 + TODO: Package description + admin + TODO: License declaration + + ament_cmake + + rclcpp + std_msgs + visualization_msgs + vision_msgs + + ament_lint_auto + ament_lint_common + + + ament_cmake + + diff --git a/src/target_selector_pkg/target_selector_node.cpp b/src/target_selector_pkg/target_selector_node.cpp new file mode 100644 index 0000000..6071eff --- /dev/null +++ b/src/target_selector_pkg/target_selector_node.cpp @@ -0,0 +1,82 @@ +#include "rclcpp/rclcpp.hpp" +#include "vision_msgs/msg/detection2_d_array.hpp" +#include "vision_msgs/msg/detection2_d.hpp" +#include "std_msgs/msg/header.hpp" +#include +#include + +class TargetSelectorNode : public rclcpp::Node +{ +public: + TargetSelectorNode() : Node("target_selector_node") + { + // Declare and get camera resolution parameters + this->declare_parameter("image_width", 1280.0); + this->declare_parameter("image_height", 720.0); + this->get_parameter("image_width", image_width_); + this->get_parameter("image_height", image_height_); + center_x_ = image_width_ / 2.0; + center_y_ = image_height_ / 2.0; + + // Set up publishers and subscribers + detection_sub_ = this->create_subscription( + "/detections", 10, + std::bind(&TargetSelectorNode::detection_callback, this, std::placeholders::_1)); + + target_pub_ = this->create_publisher("/target", 10); + + RCLCPP_INFO(this->get_logger(), "Target Selector Node initialized with resolution %.0fx%.0f", image_width_, image_height_); + } + +private: + rclcpp::Subscription::SharedPtr detection_sub_; + rclcpp::Publisher::SharedPtr target_pub_; + + double image_width_; + double image_height_; + double center_x_; + double center_y_; + + void detection_callback(const vision_msgs::msg::Detection2DArray::SharedPtr msg) + { + if (msg->detections.empty()) + { + RCLCPP_DEBUG(this->get_logger(), "No detections received."); + return; + } + + double min_distance = std::numeric_limits::max(); + vision_msgs::msg::Detection2D best_detection; + + for (const auto &detection : msg->detections) + { + double dx = detection.bbox.center.position.x - center_x_; + double dy = detection.bbox.center.position.y - center_y_; + double distance = dx * dx + dy * dy; + + if (distance < min_distance) + { + min_distance = distance; + best_detection = detection; + } + } + + best_detection.header.stamp = this->get_clock()->now(); + best_detection.header.frame_id = msg->header.frame_id; + + target_pub_->publish(best_detection); + + RCLCPP_INFO(this->get_logger(), "Published best detection at (%.2f, %.2f)", + best_detection.bbox.center.position.x, + best_detection.bbox.center.position.y); + } +}; + +int main(int argc, char *argv[]) +{ + rclcpp::init(argc, argv); + auto node = std::make_shared(); + rclcpp::spin(node); + rclcpp::shutdown(); + return 0; +}