FP Perception 0.1.2
Loading...
Searching...
No Matches
default_vision_driver.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <atomic>
4#include <mutex>
5#include <condition_variable>
6#include <opencv2/opencv.hpp>
7#include <cv_bridge/cv_bridge.hpp>
11#include <sensor_msgs/msg/image.hpp>
12#include <image_transport/image_transport.hpp>
13
14namespace fp_perception
15{
16
18{
19public:
20 DefaultDriver() = default;
21
23 {
25 }
26
34 void initialize(const rclcpp::Node::SharedPtr& node) override
35 {
36 // Configure parameters for the node
37 node->declare_parameter("driver.vision.DefaultDriver.name", "DefaultDriver");
38 node->declare_parameter("driver.vision.DefaultDriver.topic", "/camera/raw");
39
40 // Load parameters from the node
41 name_ = node->get_parameter("driver.vision.DefaultDriver.name").as_string();
42 interface_name_ = node->get_parameter("driver.vision.DefaultDriver.topic").as_string();
43
44 // Initialize the base driver
45 initialize_base(node);
46
47 // Publish about the assigned driver parameters
48 RCLCPP_INFO(node_->get_logger(), "Assigned driver name: %s", name_.c_str());
49 RCLCPP_INFO(node_->get_logger(), "Assigned driver topic: %s", interface_name_.c_str());
50
51 RCLCPP_INFO(node_->get_logger(), "DefaultDriver subscribing on topic %s", interface_name_.c_str());
52
53 image_transport::ImageTransport transport(node_);
54
56 transport.subscribe(interface_name_, 1, std::bind(&DefaultDriver::imageCallback, this, std::placeholders::_1));
57
59 {
60 enable_diagnostics("vision-topic-" + name_, name_ + " status",
61 [this](diagnostic_updater::DiagnosticStatusWrapper& status) { produce_diagnostics(status); });
62 }
63
64 RCLCPP_INFO(node_->get_logger(), "Started. Subscribed to image topic: %s", interface_name_.c_str());
65 }
66
71 void deinitialize() override
72 {
74 image_sub_.shutdown();
75 RCLCPP_INFO(node_->get_logger(), "DefaultDriver unsubscribed from topic: %s", interface_name_.c_str());
76 }
77
85 {
86 // Wait for the latest image to be available
87 std::unique_lock<std::mutex> lock(buffer_mutex_);
88 buffer_cv_.wait(lock, [this] { return latest_image_ != nullptr; });
89
90 vision_frame frame;
91 frame.frame_id = latest_image_->header.frame_id;
92 frame.stamp = latest_image_->header.stamp;
93
94 try
95 {
96 auto cv_ptr = cv_bridge::toCvCopy(latest_image_, latest_image_->encoding);
97 frame.image = cv_ptr->image.clone();
98 }
99 catch (const cv_bridge::Exception& e)
100 {
101 throw fp_perception_exception("cv_bridge conversion failed: " + std::string(e.what()));
102 }
103
104 return frame;
105 }
109 void test() override
110 {
111 RCLCPP_INFO(node_->get_logger(), "DefaultDriver test function called");
112
113 // Create the "test" directory if it doesn't exist
115
116 try
117 {
118 cv::imwrite("test/default_vision_image.jpg", captureFrame().image);
119 }
120 catch (const cv_bridge::Exception& e)
121 {
122 throw fp_perception_exception("cv_bridge conversion failed: " + std::string(e.what()));
123 }
124
125 RCLCPP_INFO(node_->get_logger(), "Test image saved to test/default_vision_image.jpg. Test completed.");
126 }
127
128protected:
129 void imageCallback(const sensor_msgs::msg::Image::ConstSharedPtr& msg)
130 {
131 std::lock_guard<std::mutex> lock(buffer_mutex_);
132 latest_image_ = msg;
134
135 buffer_cv_.notify_all();
136 }
137
138 void produce_diagnostics(diagnostic_updater::DiagnosticStatusWrapper& status)
139 {
140 sensor_msgs::msg::Image::ConstSharedPtr image;
141 {
142 std::lock_guard<std::mutex> lock(buffer_mutex_);
143 image = latest_image_;
144 }
145
146 if (!image)
147 status.summary(diagnostic_msgs::msg::DiagnosticStatus::WARN, "Waiting for image frames");
148 else
149 status.summary(diagnostic_msgs::msg::DiagnosticStatus::OK, "Receiving image frames");
150
151 status.add("topic", interface_name_);
152 status.add("received_image_count", received_image_count_.load());
153 status.add("latest_frame_available", image ? "true" : "false");
154 if (image)
155 {
156 status.add("latest_frame_id", image->header.frame_id);
157 status.add("latest_stamp_sec", image->header.stamp.sec);
158 status.add("latest_stamp_nanosec", image->header.stamp.nanosec);
159 status.add("latest_width", static_cast<int>(image->width));
160 status.add("latest_height", static_cast<int>(image->height));
161 }
162 }
163
164 std::string interface_name_;
165 image_transport::Subscriber image_sub_;
166 sensor_msgs::msg::Image::ConstSharedPtr latest_image_;
167 std::atomic<uint64_t> received_image_count_{ 0 };
168};
169
170} // namespace fp_perception
Definition default_vision_driver.hpp:18
~DefaultDriver()
Definition default_vision_driver.hpp:22
vision_frame captureFrame() override
Get the latest image data from the driver.
Definition default_vision_driver.hpp:84
void initialize(const rclcpp::Node::SharedPtr &node) override
Initialize the driver.
Definition default_vision_driver.hpp:34
void test() override
Test function to check the driver functionality by writing the image to a file.
Definition default_vision_driver.hpp:109
image_transport::Subscriber image_sub_
Definition default_vision_driver.hpp:165
std::string interface_name_
Definition default_vision_driver.hpp:164
void produce_diagnostics(diagnostic_updater::DiagnosticStatusWrapper &status)
Definition default_vision_driver.hpp:138
std::atomic< uint64_t > received_image_count_
Definition default_vision_driver.hpp:167
void imageCallback(const sensor_msgs::msg::Image::ConstSharedPtr &msg)
Definition default_vision_driver.hpp:129
void deinitialize() override
Stop driver streaming.
Definition default_vision_driver.hpp:71
sensor_msgs::msg::Image::ConstSharedPtr latest_image_
Definition default_vision_driver.hpp:166
void check_directory(std::string folder_name)
Check if the test directory exists, create it if not.
Definition driver_base.hpp:68
std::mutex buffer_mutex_
Mutex to protect access to the driver data.
Definition driver_base.hpp:149
std::string name_
Name of the driver.
Definition driver_base.hpp:143
std::condition_variable buffer_cv_
Condition variable to notify when new data is available.
Definition driver_base.hpp:155
rclcpp::Node::SharedPtr node_
ROS node for the driver.
Definition driver_base.hpp:138
void initialize_base(const rclcpp::Node::SharedPtr &node)
Initializer base driver in place of constructor due to plugin semantics.
Definition driver_base.hpp:95
void disable_diagnostics()
Definition driver_base.hpp:129
bool diagnostics_enabled() const
Definition driver_base.hpp:105
void enable_diagnostics(const std::string &hardware_id, const std::string &task_name, std::function< void(diagnostic_updater::DiagnosticStatusWrapper &)> task, std::chrono::milliseconds period=std::chrono::seconds(1))
Definition driver_base.hpp:110
Definition vision_source_driver.hpp:10
Definition audio_buffer.hpp:16
Base class for driver exceptions.
Definition exceptions.hpp:14
Definition structs.hpp:12
cv::Mat image
Definition structs.hpp:13
rclcpp::Time stamp
Definition structs.hpp:15
std::string frame_id
Definition structs.hpp:14