2323#include " rclcpp/macros.hpp"
2424#include " rclcpp_lifecycle/lifecycle_node.hpp"
2525
26+ #include " yaml-cpp/yaml.h"
27+
2628#include " lifecycle_msgs/msg/transition.hpp"
2729#include " lifecycle_msgs/msg/state.hpp"
2830
29- #include < grid_map_ros/grid_map_ros.hpp>
31+ #include " grid_map_ros/grid_map_ros.hpp"
32+ #include " grid_map_cv/grid_map_cv.hpp"
33+ #include " cv_bridge/cv_bridge.hpp"
34+ #include " opencv2/highgui/highgui.hpp"
3035
3136#include " easynav_gridmap_maps_builder/GridmapMapsBuilderNode.hpp"
3237#include " easynav_common/types/PointPerception.hpp"
3338
39+ #include " ament_index_cpp/get_package_share_directory.hpp"
40+ #include " ament_index_cpp/get_package_prefix.hpp"
41+
3442namespace easynav
3543{
3644
@@ -50,9 +58,48 @@ GridmapMapsBuilderNode::GridmapMapsBuilderNode(const rclcpp::NodeOptions & optio
5058 declare_parameter (" perception_default_frame" , " map" );
5159 }
5260
61+ std::string package_name, map_path_file;
62+ if (!has_parameter (" package" )) {
63+ declare_parameter (" package" , package_name);
64+ }
65+
66+ if (!has_parameter (" map_path_file" )) {
67+ declare_parameter (" map_path_file" , " map_path_file" );
68+ }
69+
70+ // if (package_name != "" && map_path_file != "") {
71+ // std::string pkgpath;
72+ // try {
73+ // pkgpath = ament_index_cpp::get_package_share_directory(package_name);
74+ // map_path_ = pkgpath + "/" + map_path_file;
75+ // } catch(ament_index_cpp::PackageNotFoundError & ex) {
76+ // return std::unexpected("Package " + package_name + " not found. Error: " + ex.what());
77+ // }
78+ //
79+ // if (!load_gridmap(map_path_, map_)) {
80+ // return std::unexpected("File [" + map_path_ + "] not found");
81+ // }
82+ // }
83+
5384 pub_ = this ->create_publisher <grid_map_msgs::msg::GridMap>(
5485 " map_builder_gridmap/gridmap" , rclcpp::QoS (1 ).transient_local ().reliable ());
5586
87+ // savemap_srv_ = node->create_service<std_srvs::srv::Trigger>(
88+ // node->get_name() + std::string("/") + plugin_name + "/savemap",
89+ // [this](
90+ // const std::shared_ptr<std_srvs::srv::Trigger::Request> request,
91+ // std::shared_ptr<std_srvs::srv::Trigger::Response> response)
92+ // {
93+ // (void)request;
94+ // if (!save_gridmap(map_path_, map_)) {
95+ // response->success = false;
96+ // response->message = "Failed to save map to: " + map_path_;
97+ // } else {
98+ // response->success = true;
99+ // response->message = "Map successfully saved to: " + map_path_;
100+ // }
101+ // });
102+ //
56103 register_handler (std::make_shared<PointPerceptionHandler>());
57104}
58105
@@ -236,4 +283,83 @@ GridmapMapsBuilderNode::register_handler(std::shared_ptr<PerceptionHandler> hand
236283 handlers_[handler->group ()] = handler;
237284}
238285
286+
287+ bool
288+ GridmapMapsBuilderNode::save_gridmap (const std::string & filename, const grid_map::GridMap & map)
289+ {
290+ std::string dir = std::filesystem::path (filename).parent_path ();
291+ YAML::Emitter yaml;
292+ yaml << YAML::BeginMap;
293+ yaml << YAML::Key << " layers" << YAML::Value << YAML::BeginSeq;
294+
295+ for (const std::string & layer : map.getLayers ()) {
296+ // Compute min and max values of the layer
297+ float min_val = std::numeric_limits<float >::max ();
298+ float max_val = std::numeric_limits<float >::lowest ();
299+ for (grid_map::GridMapIterator it (map); !it.isPastEnd (); ++it) {
300+ if (!map.isValid (*it, layer)) continue ;
301+ float value = map.at (layer, *it);
302+ min_val = std::min (min_val, value);
303+ max_val = std::max (max_val, value);
304+ }
305+
306+ // Save layer image
307+ cv::Mat image;
308+ grid_map::GridMapCvConverter::toImage<unsigned char , 1 >(map, layer, CV_8UC1, min_val, max_val, image);
309+ std::string image_filename = layer + " .pgm" ;
310+ std::string image_path = dir + " /" + image_filename;
311+ cv::imwrite (image_path, image);
312+
313+ yaml << YAML::BeginMap;
314+ yaml << YAML::Key << " name" << YAML::Value << layer;
315+ yaml << YAML::Key << " min" << YAML::Value << min_val;
316+ yaml << YAML::Key << " max" << YAML::Value << max_val;
317+ yaml << YAML::EndMap;
318+ }
319+ yaml << YAML::EndSeq;
320+ yaml << YAML::Key << " resolution" << YAML::Value << map.getResolution ();
321+ yaml << YAML::Key << " length" << YAML::Value << YAML::Flow << std::vector<double >{map.getLength ().x (), map.getLength ().y ()};
322+ yaml << YAML::Key << " position" << YAML::Value << YAML::Flow << std::vector<double >{map.getPosition ().x (), map.getPosition ().y ()};
323+ yaml << YAML::EndMap;
324+
325+ std::ofstream file_out (filename);
326+ if (!file_out) return false ;
327+ file_out << yaml.c_str ();
328+ return true ;
329+ }
330+
331+ bool
332+ GridmapMapsBuilderNode::load_gridmap (const std::string & filename, grid_map::GridMap & map)
333+ {
334+ std::ifstream file_in (filename);
335+ if (!file_in) return false ;
336+
337+ YAML::Node config = YAML::LoadFile (filename);
338+ if (!config[" layers" ]) return false ;
339+
340+ map.setFrameId (" map" );
341+
342+ auto resolution = config[" resolution" ].as <double >();
343+ auto length = config[" length" ].as <std::vector<double >>();
344+ auto position = config[" position" ].as <std::vector<double >>();
345+
346+ map.setGeometry (grid_map::Length (length[0 ], length[1 ]), resolution, grid_map::Position (position[0 ], position[1 ]));
347+
348+ std::string dir = std::filesystem::path (filename).parent_path ();
349+
350+ for (const auto & layer_node : config[" layers" ]) {
351+ std::string layer_name = layer_node[" name" ].as <std::string>();
352+ float min_val = layer_node[" min" ].as <float >();
353+ float max_val = layer_node[" max" ].as <float >();
354+
355+ std::string image_path = dir + " /" + layer_name + " .pgm" ;
356+ cv::Mat image = cv::imread (image_path, cv::IMREAD_GRAYSCALE);
357+ if (image.empty ()) return false ;
358+
359+ grid_map::GridMapCvConverter::addLayerFromImage<unsigned char , 1 >(image, layer_name, map, min_val, max_val);
360+ }
361+
362+ return true ;
363+ }
364+
239365} // namespace easynav
0 commit comments