MultiWavefrontPlanner.cpp
Go to the documentation of this file.
2 #include <geometry_msgs/Pose2D.h>
3 #include <nav_msgs/GridCells.h>
4 
5 typedef std::multimap<double,unsigned int> Queue;
6 typedef std::pair<double,unsigned int> Entry;
7 
8 using namespace ros;
9 
11 {
12  NodeHandle robotNode;
13  robotNode.param("robot_id", mRobotID, 1);
14  robotNode.param("map_frame", mMapFrame, std::string("map"));
15 
17  std::string tfPrefix = tf.getTFPrefix();
18  mMapFrame = tf::resolve(tfPrefix, mMapFrame);
19 
20  NodeHandle navigatorNode("~/");
21  mWaitForOthers = false;
22 
23  // Initialize Publisher/Subscriber
24  mWavefrontPublisher = navigatorNode.advertise<nav_msgs::GridCells>("wave", 1);
25  mOtherWavefrontPublisher = navigatorNode.advertise<nav_msgs::GridCells>("others", 1);
26 }
27 
29 {
30 
31 }
32 
33 int MultiWavefrontPlanner::findExplorationTarget(GridMap* map, unsigned int start, unsigned int &goal)
34 {
35  // Initialize a search map
36  unsigned int mapSize = map->getSize();
37  int* searchMap = new int[mapSize];
38  for(unsigned int i = 0; i < mapSize; i++)
39  {
40  searchMap[i] = 0;
41  }
42 
43  // Initialize the queue with the robot position
44  Queue queue;
45  Entry startPoint(0.0, start);
46  queue.insert(startPoint);
47  searchMap[start] = mRobotID;
48 
49  // A second queue for cells occupied by other robots
50  Queue buffer;
51 
52  // Insert position of other robots
53  PoseList l = mRobotList.getRobots();
54  for(PoseList::iterator p = l.begin(); p != l.end(); p++)
55  {
56  if((int)p->first == mRobotID) continue;
57  unsigned int robot_x = (double)(p->second.x - map->getOriginX()) / map->getResolution();
58  unsigned int robot_y = (double)(p->second.y - map->getOriginY()) / map->getResolution();
59  unsigned int robot = 0;
60  if(map->getIndex(robot_x, robot_y, robot))
61  {
62  queue.insert(Entry(0.0, robot));
63  searchMap[robot] = p->first;
64  }else
65  {
66  ROS_WARN("Couldn't place robot %d in search map!", p->first);
67  }
68  }
69 
70  Queue::iterator next;
71  double linear = map->getResolution();
72  bool foundFrontier = false;
73  bool hasFrontiers = false;
74  int cellCount = 0;
75 
76  std::vector<std::pair<double, double> > points;
77  std::vector<std::pair<double, double> > others;
78 
79  // Do full search with weightless Dijkstra-Algorithm
80  while(!foundFrontier && !queue.empty())
81  {
82  cellCount++;
83  // Get the nearest cell from the queue
84  next = queue.begin();
85  double distance = next->first;
86  unsigned int index = next->second;
87  queue.erase(next);
88  int currentBot = searchMap[index];
89 
90  // Add all adjacent cells
91  if(map->isFrontier(index))
92  {
93  hasFrontiers = true;
94  if(currentBot == mRobotID)
95  {
96  foundFrontier = true;
97  goal = index;
98  }
99  }else
100  {
101  std::vector<unsigned int> neighbors = map->getFreeNeighbors(index);
102  for(unsigned int i = 0; i < neighbors.size(); i++)
103  {
104  unsigned int x,y;
105  if(!map->getCoordinates(x,y,neighbors[i])) continue;
106  if(searchMap[neighbors[i]] == 0)
107  {
108  queue.insert(Entry(distance+linear, neighbors[i]));
109  searchMap[neighbors[i]] = currentBot;
110  if(currentBot == mRobotID)
111  {
112  points.push_back(std::pair<double, double>(((x+0.5) * map->getResolution()) + map->getOriginX(), ((y+0.5) * map->getResolution()) + map->getOriginY()));
113  }else
114  {
115  others.push_back(std::pair<double, double>(((x+0.5) * map->getResolution()) + map->getOriginX(), ((y+0.5) * map->getResolution()) + map->getOriginY()));
116  }
117  }else if(searchMap[neighbors[i]] != mRobotID && currentBot == mRobotID)
118  {
119  // We don't continue the dijkstra now, but keep the point for possible later use
120  buffer.insert(Entry(distance+linear, neighbors[i]));
121  }
122  }
123  }
124  }
125 
126  // If not supposed to wait, now continue the wavefront into other robots area
127  if(!mWaitForOthers)
128  {
129  while(!foundFrontier && !buffer.empty())
130  {
131  cellCount++;
132  // Get the nearest cell from the buffer
133  next = buffer.begin();
134  double distance = next->first;
135  unsigned int index = next->second;
136  buffer.erase(next);
137 
138  // Add all adjacent cells
139  if(map->isFrontier(index))
140  {
141  foundFrontier = true;
142  goal = index;
143  }else
144  {
145  std::vector<unsigned int> neighbors = map->getFreeNeighbors(index);
146  for(unsigned int i = 0; i < neighbors.size(); i++)
147  {
148  if(map->isFree(neighbors[i]) && searchMap[neighbors[i]] != mRobotID)
149  {
150  unsigned int x,y;
151  if(!map->getCoordinates(x,y,neighbors[i])) continue;
152  buffer.insert(Entry(distance+linear, neighbors[i]));
153  searchMap[neighbors[i]] = mRobotID;
154  points.push_back(std::pair<double, double>(((x+0.5) * map->getResolution()) + map->getOriginX(), ((y+0.5) * map->getResolution()) + map->getOriginY()));
155  }
156  }
157  }
158  }
159  }
160 
161  delete[] searchMap;
162  ROS_DEBUG("Checked %d cells.", cellCount);
163 
164  // GridCells for debugging in RVIZ
165  nav_msgs::GridCells wave_msg;
166  wave_msg.header.frame_id = mMapFrame.c_str();
167  wave_msg.header.stamp = Time::now();
168  wave_msg.cell_width = map->getResolution();
169  wave_msg.cell_height = map->getResolution();
170  wave_msg.cells.resize(points.size());
171  for(unsigned int i = 0; i < points.size(); i++)
172  {
173  wave_msg.cells[i].x = points[i].first;
174  wave_msg.cells[i].y = points[i].second;
175  wave_msg.cells[i].z = 0.0;
176  }
177  mWavefrontPublisher.publish(wave_msg);
178 
179  wave_msg.cells.resize(others.size());
180  for(unsigned int i = 0; i < others.size(); i++)
181  {
182  wave_msg.cells[i].x = others[i].first;
183  wave_msg.cells[i].y = others[i].second;
184  wave_msg.cells[i].z = 0.0;
185  }
186  mOtherWavefrontPublisher.publish(wave_msg);
187 
188  if(foundFrontier)
189  {
190  return EXPL_TARGET_SET;
191  }else if(hasFrontiers)
192  {
193  if(buffer.size() > 0)
194  return EXPL_WAITING;
195  else
196  {
197  ROS_WARN("[MultiWave] Frontiers present, but not reachable.");
198  return EXPL_FAILED;
199  }
200  }else
201  {
202  if(cellCount > 50)
203  return EXPL_FINISHED;
204  else
205  {
206  ROS_WARN("[MultiWave] No Frontiers present, but robot seems locked.");
207  return EXPL_FAILED;
208  }
209  }
210 }
double getResolution()
ROSCPP_DECL void start()
std::string getTFPrefix() const
#define EXPL_WAITING
std::pair< double, unsigned int > Entry
double getOriginX()
TFSIMD_FORCE_INLINE const tfScalar & y() const
#define ROS_WARN(...)
unsigned int getSize()
std::multimap< double, unsigned int > Queue
std::string resolve(const std::string &prefix, const std::string &frame_name)
#define EXPL_FINISHED
bool isFree(unsigned int index)
double distance(double x0, double y0, double x1, double y1)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
#define EXPL_TARGET_SET
std::multimap< double, unsigned int > Queue
TFSIMD_FORCE_INLINE const tfScalar & x() const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
std::pair< double, unsigned int > Entry
std::map< unsigned int, geometry_msgs::Pose2D > PoseList
#define EXPL_FAILED
static Time now()
bool isFrontier(unsigned int index)
bool getIndex(unsigned int x, unsigned int y, unsigned int &i)
int findExplorationTarget(GridMap *map, unsigned int start, unsigned int &goal)
std::vector< unsigned int > getFreeNeighbors(unsigned int index, int offset=1)
double getOriginY()
bool getCoordinates(unsigned int &x, unsigned int &y, unsigned int i)
#define ROS_DEBUG(...)


nav2d_exploration
Author(s): Sebastian Kasperski
autogenerated on Thu Jun 6 2019 19:20:48