voronoi_graph_node.cpp
Go to the documentation of this file.
1 #include <ros/ros.h>
2 #include <nav_msgs/OccupancyGrid.h>
6 #include <memory>
7 #include <tuw_multi_robot_msgs/Graph.h>
8 #include <string>
9 
10 void publishTf(std::string mapName);
11 
12 bool allowPublish = false;
13 
14 int main(int argc, char **argv)
15 {
16 
17  ros::init(argc, argv, "voronoi_graph_node");
19 
21 
22  ros::Rate r(0.5);
23 
24  ROS_INFO("Initialization done!");
25 
26  while (ros::ok())
27  {
28  ros::spinOnce();
29 
30  if (allowPublish)
31  {
32  mapNode.publishMap();
33  mapNode.publishSegments();
34  }
35 
36  r.sleep();
37  }
38 
39  return 0;
40 }
41 
42 namespace tuw_graph
43 {
45 {
46 
47  n_param_.param<std::string>("map_topic", topicGlobalMap_, "/map");
48 
49  n_param_.param<int>("map_smoothing", smoothing_, 0);
50 
51  n_param_.param<std::string>("voronoi_topic", topicVoronoiMap_, "voronoi_map");
52 
53  n_param_.param<std::string>("segments_topic", topicSegments_, "/segments");
54 
55  n_param_.param<float>("segment_length", path_length_, 1.0);
56 
58  n_param_.param<float>("opt_crossings", crossingOptimization_, 0.2);
59 
60  n_param_.param<float>("opt_end_segments", endSegmentOptimization_, 0.2);
61  //endSegmentOptimization_ = std::min<float>(endSegmentOptimization_, 0.7 * path_length_);
62 
63  n_param_.param<std::string>("graph_cache_path", graphCachePath_, "/tmp");
64 
65  if (graphCachePath_.back() != '/'){
66  graphCachePath_ += "/";
67  }
68  n_param_.param<std::string>("custom_graph_path", customGraphPath_, "");
69 
70  if (customGraphPath_.back() != '/' && customGraphPath_.size() != 0){
71  customGraphPath_ += "/";
72  }
73 
74  subMap_ = n.subscribe(topicGlobalMap_, 1, &VoronoiGeneratorNode::globalMapCallback, this);
75  //pubVoronoiMap_ = n.advertise<nav_msgs::OccupancyGrid>(topicVoronoiMap_, 1); //DEBUG
76  pubSegments_ = n.advertise<tuw_multi_robot_msgs::Graph>(topicSegments_, 1);
77 
78  //ros::Rate(1).sleep();
79  ros::spinOnce();
80 }
81 
82 void VoronoiGeneratorNode::globalMapCallback(const nav_msgs::OccupancyGrid::ConstPtr &_map)
83 {
84  std::vector<signed char> map = _map->data;
85 
86  Eigen::Vector2d origin;
87  origin[0] = _map->info.origin.position.x;
88  origin[1] = _map->info.origin.position.y;
89 
90  size_t new_hash = getHash(map, origin, _map->info.resolution);
91 
92  if (customGraphPath_.size() == 0)
93  {
94  if (new_hash != current_map_hash_)
95  {
96  if (!loadGraph(new_hash))
97  {
98  ROS_INFO("Graph generator: Graph not found! Generating new one!");
99  createGraph(_map, new_hash);
100  }
101  else
102  {
103  ROS_INFO("Graph generator: Graph loaded from memory");
104  }
105 
106  current_map_hash_ = new_hash;
107 
108  allowPublish = true;
109  }
110  }
111  else
112  {
113  ROS_INFO("loading custom graph from: %s", customGraphPath_.c_str());
115  ROS_INFO("graph loaded");
116  else
117  ROS_INFO("failed to load graph");
118  }
119 }
120 
121 void VoronoiGeneratorNode::createGraph(const nav_msgs::OccupancyGrid::ConstPtr &_map, size_t _map_hash)
122 {
123  std::vector<signed char> map = _map->data;
124 
125  segments_.clear();
127 
128  ROS_INFO("Graph generator: Computing distance field ...");
129  origin_[0] = _map->info.origin.position.x;
130  origin_[1] = _map->info.origin.position.y;
131  resolution_ = _map->info.resolution;
132 
133  cv::Mat m(_map->info.height, _map->info.width, CV_8SC1, map.data());
136 
137  ROS_INFO("Graph generator: Computing voronoi graph ...");
139 
140  ROS_INFO("Graph generator: Generating graph ...");
141  potential.reset(new float[m.cols * m.rows]);
142  float pixel_path_length = path_length_ / resolution_;
144 
145  //Check Directroy
146  save(graphCachePath_ + std::to_string(_map_hash) + "/", segments_, origin_, resolution_);
147  ROS_INFO("Graph generator: Created new Graph %lu", _map_hash);
148 }
149 
150 bool VoronoiGeneratorNode::loadGraph(std::size_t _hash)
151 {
152  segments_.clear();
154  return load(graphCachePath_ + std::to_string(_hash) + "/", segments_, origin_, resolution_);
155 }
156 
158 {
159  if (!allowPublish)
160  {
161  segments_.clear();
163  allowPublish = true;
164  return load(_path, segments_, origin_, resolution_);
165  }
166  return false;
167 }
168 
170 {
171  tuw_multi_robot_msgs::Graph graph;
172  graph.header.frame_id = "map";
173  graph.header.seq = 0;
174  graph.header.stamp = ros::Time::now();
175 
176  graph.resolution = resolution_;
177 
178  graph.origin.position.x = origin_[0]; //TODO test
179  graph.origin.position.y = origin_[1]; //TODO test
180 
181  for (auto it = segments_.begin(); it != segments_.end(); ++it)
182  {
183  tuw_multi_robot_msgs::Vertex seg;
184 
185  seg.id = (*it).getId();
186  seg.weight = (*it).getLength();
187  seg.width = (*it).getMinPathSpace();
188  seg.valid = true;
189  std::vector<Eigen::Vector2d> path = (*it).getPath();
190 
191  for (uint32_t i = 0; i < path.size(); i++)
192  {
193  geometry_msgs::Point pos;
194  pos.x = path[i][0];
195  pos.y = path[i][1];
196  pos.z = 0;
197 
198  seg.path.push_back(pos);
199  }
200 
201  //ROS_INFO("distORIG: %i/%i", (*it)->GetPredecessors().size(), (*it)->GetSuccessors().size());
202  std::vector<uint32_t> predecessors = (*it).getPredecessors();
203 
204  for (uint32_t i = 0; i < predecessors.size(); i++)
205  {
206  seg.predecessors.push_back(predecessors[i]);
207  }
208 
209  std::vector<uint32_t> successors = (*it).getSuccessors();
210 
211  for (uint32_t i = 0; i < successors.size(); i++)
212  {
213  seg.successors.push_back(successors[i]);
214  }
215 
216  graph.vertices.push_back(seg);
217  }
218 
219  pubSegments_.publish(graph);
220 }
221 
223 {
224  nav_msgs::OccupancyGrid grid;
225  // Publish Whole Grid
226  grid.header.frame_id = "map";
227  grid.header.stamp = ros::Time::now();
228  grid.info.resolution = resolution_;
229 
230  int nx = map_.cols;
231  int ny = map_.rows;
232 
233  grid.info.width = nx;
234  grid.info.height = ny;
235 
236  //double wx, wy;
237  //costmap_->mapToWorld(0, 0, wx, wy);
238  grid.info.origin.position.x = origin_[0];
239  grid.info.origin.position.y = origin_[1];
240  grid.info.origin.position.z = 0.0;
241  grid.info.origin.orientation.w = 1.0;
242 
243  grid.data.resize(nx * ny);
244 
245  for (unsigned int i = 0; i < grid.data.size(); i++)
246  {
247  grid.data[i] = (map_.data[i]);
248  }
249 
250  //pubVoronoiMap_.publish(grid);
251 }
252 
253 } // namespace tuw_graph
void createGraph(const nav_msgs::OccupancyGrid::ConstPtr &_map, size_t _map_hash)
void publish(const boost::shared_ptr< M > &message) const
void globalMapCallback(const nav_msgs::OccupancyGrid::ConstPtr &_map)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
std::unique_ptr< float[]> potential
static void resetId()
resets the id counter (which is used to generate uinique ids)
Definition: segment.cpp:182
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
#define ROS_INFO(...)
bool load(const std::string &_mapPath, std::vector< Segment > &_segs, Eigen::Vector2d &_origin, float &_resolution)
loads a graph from memory which is saved in plain text
Definition: serializer.cpp:42
bool param(const std::string &param_name, T &param_val, const T &default_val) const
ROSCPP_DECL bool ok()
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
bool sleep()
std::vector< Segment > segments_
bool allowPublish
VoronoiGeneratorNode(ros::NodeHandle &n)
void save(const std::string &_mapPath, const std::vector< Segment > &_segs, const Eigen::Vector2d &_origin, const float &_resolution)
saves the graph to a specific path in xml format
Definition: serializer.cpp:142
static Time now()
void publishTf(std::string mapName)
size_t getHash(const std::vector< signed char > &_map, Eigen::Vector2d _origin, float _resolution)
generate a hash from a _map
Definition: serializer.cpp:25
bool loadCustomGraph(std::string _path)
ROSCPP_DECL void spinOnce()
int main(int argc, char **argv)
void computeVoronoiMap(const cv::Mat &_distField, cv::Mat &_voronoiMap)
computes the voronoi _map
void computeDistanceField(const cv::Mat &_map, cv::Mat &_distField)
computes the distance field of a map
std::vector< Segment > calcSegments(cv::Mat &_map, cv::Mat &_distField, cv::Mat &_voronoiPath, float *potential, float _path_length, float _optimizeCrossingPixels, float _optimizeEndSegmentsPixel)
calculates the search graph
void prepareMap(const cv::Mat &_map, cv::Mat &_smoothedMap, int _blurSize)
prepares the map by smoothing it


tuw_voronoi_graph
Author(s): Benjamin Binder
autogenerated on Mon Jun 10 2019 15:42:44