15 #include "nav2_waypoint_follower/plugins/photo_at_waypoint.hpp"
20 #include "pluginlib/class_list_macros.hpp"
22 #include "nav2_ros_common/node_utils.hpp"
24 namespace nav2_waypoint_follower
35 const nav2::LifecycleNode::WeakPtr & parent,
36 const std::string & plugin_name)
38 auto node = parent.lock();
40 curr_frame_msg_ = std::make_shared<sensor_msgs::msg::Image>();
42 nav2::declare_parameter_if_not_declared(
43 node, plugin_name +
".enabled",
44 rclcpp::ParameterValue(
true));
45 nav2::declare_parameter_if_not_declared(
46 node, plugin_name +
".image_topic",
47 rclcpp::ParameterValue(
"/camera/color/image_raw"));
48 nav2::declare_parameter_if_not_declared(
49 node, plugin_name +
".save_dir",
50 rclcpp::ParameterValue(
"/tmp/waypoint_images"));
51 nav2::declare_parameter_if_not_declared(
52 node, plugin_name +
".image_format",
53 rclcpp::ParameterValue(
"png"));
55 std::string save_dir_as_string;
56 node->get_parameter(plugin_name +
".enabled", is_enabled_);
57 node->get_parameter(plugin_name +
".image_topic", image_topic_);
58 node->get_parameter(plugin_name +
".save_dir", save_dir_as_string);
59 node->get_parameter(plugin_name +
".image_format", image_format_);
62 save_dir_ = save_dir_as_string;
64 if (!std::filesystem::exists(save_dir_)) {
67 "Provided save directory for photo at waypoint plugin does not exist,"
68 "provided directory is: %s, the directory will be created automatically.",
71 if (!std::filesystem::create_directory(save_dir_)) {
74 "Failed to create directory!: %s required by photo at waypoint plugin, "
75 "exiting the plugin with failure!",
81 }
catch (
const std::exception & e) {
83 logger_,
"Exception (%s) thrown while attempting to create image capture directory."
84 " This task executor is being disabled as it cannot save images.", e.what());
90 logger_,
"Photo at waypoint plugin is disabled.");
93 logger_,
"Initializing photo at waypoint plugin, subscribing to camera topic named; %s",
94 image_topic_.c_str());
95 camera_image_subscriber_ = node->create_subscription<sensor_msgs::msg::Image>(
102 const geometry_msgs::msg::PoseStamped & curr_pose,
const int & curr_waypoint_index)
107 "Photo at waypoint plugin is disabled. Not performing anything"
113 std::filesystem::path file_name = std::to_string(
114 curr_waypoint_index) +
"_" +
115 std::to_string(curr_pose.header.stamp.sec) +
"." + image_format_;
116 std::filesystem::path full_path_image_path = save_dir_ / file_name;
119 std::lock_guard<std::mutex> guard(global_mutex_);
120 cv::Mat curr_frame_mat;
122 cv::imwrite(full_path_image_path.string().c_str(), curr_frame_mat);
125 "Photo has been taken successfully at waypoint %i", curr_waypoint_index);
126 }
catch (
const std::exception & e) {
129 "Couldn't take photo at waypoint %i! Caught exception: %s \n"
130 "Make sure that the image topic named: %s is valid and active!",
132 e.what(), image_topic_.c_str());
140 std::lock_guard<std::mutex> guard(global_mutex_);
141 curr_frame_msg_ = msg;
145 const sensor_msgs::msg::Image::SharedPtr & msg,
148 cv_bridge::CvImageConstPtr cv_bridge_ptr = cv_bridge::toCvShare(msg, msg->encoding);
149 cv::Mat frame = cv_bridge_ptr->image;
150 if (msg->encoding ==
"rgb8") {
151 cv::cvtColor(frame, frame, cv::COLOR_RGB2BGR);
157 PLUGINLIB_EXPORT_CLASS(
Base class for creating a plugin in order to perform a specific task at waypoint arrivals.
bool processAtWaypoint(const geometry_msgs::msg::PoseStamped &curr_pose, const int &curr_waypoint_index)
Override this to define the body of your task that you would like to execute once the robot arrived t...
static void deepCopyMsg2Mat(const sensor_msgs::msg::Image::SharedPtr &msg, cv::Mat &mat)
given a shared pointer to sensor::msg::Image type, make a deep copy to inputted cv Mat
void initialize(const nav2::LifecycleNode::WeakPtr &parent, const std::string &plugin_name)
declares and loads parameters used
void imageCallback(const sensor_msgs::msg::Image::SharedPtr msg)
PhotoAtWaypoint()
Construct a new Photo At Waypoint object.
~PhotoAtWaypoint()
Destroy the Photo At Waypoint object.