wave_front_planner.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2020, Sebastian Pütz
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following
13  * disclaimer in the documentation and/or other materials provided
14  * with the distribution.
15  *
16  * 3. Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * authors:
34  * Sebastian Pütz <spuetz@uni-osnabrueck.de>
35  *
36  */
37 
39 #include <lvr2/util/Meap.hpp>
40 
41 #include <mbf_msgs/GetPathResult.h>
42 #include <mesh_map/util.h>
44 
46 //#define DEBUG
47 //#define USE_UPDATE_WITH_S
48 
50 
51 namespace wave_front_planner
52 {
54 {
55 }
56 
58 {
59 }
60 
61 uint32_t WaveFrontPlanner::makePlan(const geometry_msgs::PoseStamped& start, const geometry_msgs::PoseStamped& goal,
62  double tolerance, std::vector<geometry_msgs::PoseStamped>& plan, double& cost,
63  std::string& message)
64 {
65  const auto& mesh = mesh_map->mesh();
66  std::list<std::pair<mesh_map::Vector, lvr2::FaceHandle>> path;
67 
68  // mesh_map->combineVertexCosts(); // TODO should be outside the planner
69 
70  ROS_INFO("start wave front propagation.");
71 
72  mesh_map::Vector goal_vec = mesh_map::toVector(goal.pose.position);
73  mesh_map::Vector start_vec = mesh_map::toVector(start.pose.position);
74 
75  uint32_t outcome = waveFrontPropagation(goal_vec, start_vec, path);
76 
77  path.reverse();
78 
79  std_msgs::Header header;
80  header.stamp = ros::Time::now();
81  header.frame_id = mesh_map->mapFrame();
82 
83  cost = 0;
84  float dir_length;
85  if (!path.empty())
86  {
87  mesh_map::Vector vec = path.front().first;
88  lvr2::FaceHandle fH = path.front().second;
89  path.pop_front();
90 
91  const auto& face_normals = mesh_map->faceNormals();
92  for (auto& next : path)
93  {
94  geometry_msgs::PoseStamped pose;
95  pose.header = header;
96  pose.pose = mesh_map::calculatePoseFromPosition(vec, next.first, face_normals[fH], dir_length);
97  cost += dir_length;
98  vec = next.first;
99  fH = next.second;
100  plan.push_back(pose);
101  }
102 
103  geometry_msgs::PoseStamped pose;
104  pose.header = header;
105  pose.pose = mesh_map::calculatePoseFromPosition(vec, goal_vec, face_normals[fH], dir_length);
106  cost += dir_length;
107  plan.push_back(pose);
108  }
109 
110  nav_msgs::Path path_msg;
111  path_msg.poses = plan;
112  path_msg.header = header;
113 
114  path_pub.publish(path_msg);
115  mesh_map->publishVertexCosts(potential, "Potential");
116  ROS_INFO_STREAM("Path length: " << cost << "m");
117 
119  {
120  mesh_map->publishVectorField("vector_field", vector_map, publish_face_vectors);
121  }
122 
123  return outcome;
124 }
125 
127 {
128  cancel_planning = true;
129  return true;
130 }
131 
132 bool WaveFrontPlanner::initialize(const std::string& plugin_name,
133  const boost::shared_ptr<mesh_map::MeshMap>& mesh_map_ptr)
134 {
135  mesh_map = mesh_map_ptr;
136  name = plugin_name;
137  map_frame = mesh_map->mapFrame();
138  private_nh = ros::NodeHandle("~/" + name);
139 
140  private_nh.param("publish_vector_field", publish_vector_field, false);
141  private_nh.param("publish_face_vectors", publish_face_vectors, false);
142  private_nh.param("goal_dist_offset", goal_dist_offset, 0.3f);
143 
144  path_pub = private_nh.advertise<nav_msgs::Path>("path", 1, true);
145  const auto& mesh = mesh_map->mesh();
146  direction = lvr2::DenseVertexMap<float>(mesh.nextVertexIndex(), 0);
147  // TODO check all map dependencies! (loaded layers etc...)
148 
150  new dynamic_reconfigure::Server<wave_front_planner::WaveFrontPlannerConfig>(private_nh));
151 
152  config_callback = boost::bind(&WaveFrontPlanner::reconfigureCallback, this, _1, _2);
154 
155  return true;
156 }
157 
158 void WaveFrontPlanner::reconfigureCallback(wave_front_planner::WaveFrontPlannerConfig& cfg, uint32_t level)
159 {
160  ROS_INFO_STREAM("New height diff layer config through dynamic reconfigure.");
161  if (first_config)
162  {
163  config = cfg;
164  first_config = false;
165  return;
166  }
167  config = cfg;
168 }
169 
171 {
172  const auto& mesh = mesh_map->mesh();
173  const auto& face_normals = mesh_map->faceNormals();
174  const auto& vertex_normals = mesh_map->vertexNormals();
175 
176  for (auto v3 : mesh.vertices())
177  {
178  // if(vertex_costs[v3] > config.cost_limit || !predecessors.containsKey(v3))
179  // continue;
180 
181  const lvr2::VertexHandle& v1 = predecessors[v3];
182 
183  // if predecessor is pointing to it self, continue with the next vertex.
184  if (v1 == v3)
185  continue;
186 
187  // get the cut face
188  const auto& optFh = cutting_faces.get(v3);
189  // if no cut face, continue with the next vertex
190  if (!optFh)
191  continue;
192 
193  const lvr2::FaceHandle& fH = optFh.get();
194 
195  const auto& vec3 = mesh.getVertexPosition(v3);
196  const auto& vec1 = mesh.getVertexPosition(v1);
197 
198  // compute the direction vector and rotate it by theta, which is stored in
199  // the direction vertex map
200  const auto dirVec = (vec1 - vec3).rotated(vertex_normals[v3], direction[v3]);
201  // store the normalized rotated vector in the vector map
202  vector_map.insert(v3, dirVec.normalized());
203  }
204  mesh_map->setVectorMap(vector_map);
205 }
206 
208  std::list<std::pair<mesh_map::Vector, lvr2::FaceHandle>>& path)
209 {
210  return waveFrontPropagation(start, goal, mesh_map->edgeDistances(), mesh_map->vertexCosts(), path, potential,
211  predecessors);
212 }
213 
215  const lvr2::DenseEdgeMap<float>& edge_weights,
216  const lvr2::VertexHandle& v1, const lvr2::VertexHandle& v2,
217  const lvr2::VertexHandle& v3)
218 {
219  const auto& mesh = mesh_map->mesh();
220 
221  const double u1 = distances[v1];
222  const double u2 = distances[v2];
223  const double u3 = distances[v3];
224 
225  const lvr2::OptionalEdgeHandle e12h = mesh.getEdgeBetween(v1, v2);
226  const double c = edge_weights[e12h.unwrap()];
227  const double c_sq = c * c;
228 
229  const lvr2::OptionalEdgeHandle e13h = mesh.getEdgeBetween(v1, v3);
230  const double b = edge_weights[e13h.unwrap()];
231  const double b_sq = b * b;
232 
233  const lvr2::OptionalEdgeHandle e23h = mesh.getEdgeBetween(v2, v3);
234  const double a = edge_weights[e23h.unwrap()];
235  const double a_sq = a * a;
236 
237  const double u1_sq = u1 * u1;
238  const double u2_sq = u2 * u2;
239 
240  const double A = sqrt(std::max<double>((-u1 + u2 + c) * (u1 - u2 + c) * (u1 + u2 - c) * (u1 + u2 + c), 0));
241  const double B = sqrt(std::max<double>((-a + b + c) * (a - b + c) * (a + b - c) * (a + b + c), 0));
242  const double sx = (c_sq + u1_sq - u2_sq) / (2 * c);
243  const double sy = -A / (2 * c);
244  const double p = (-a_sq + b_sq + c_sq) / (2 * c);
245  const double hc = B / (2 * c);
246  const double dy = hc - sy;
247  // const double dy = (A + B) / (2 * c);
248  // const double dx = (u2_sq - u1_sq + b_sq - a_sq) / (2*c);
249  const double dx = p - sx;
250 
251  const double u3tmp_sq = dx * dx + dy * dy;
252  double u3tmp = sqrt(u3tmp_sq);
253 
254  if (u3tmp < u3)
255  {
256  if (distances[v1] < distances[v2])
257  {
258  const double S = sy * p - sx * hc;
259  const double t1cos = (u3tmp_sq + b_sq - u1_sq) / (2 * u3tmp * b);
260  if (S <= 0 && std::fabs(t1cos) <= 1)
261  {
262  const double theta = acos(t1cos);
263  predecessors[v3] = v1;
264  direction[v3] = static_cast<float>(theta);
265  distances[v3] = static_cast<float>(u3tmp);
266  const lvr2::FaceHandle fh = mesh.getFaceBetween(v1, v2, v3).unwrap();
267  cutting_faces.insert(v3, fh);
268 #ifdef DEBUG
269  mesh_map->publishDebugVector(v3, v1, fh, theta, mesh_map::color(0.9, 0.9, 0.2),
270  "dir_vec" + std::to_string(v3.idx()));
271 #endif
272  return true;
273  }
274  else
275  {
276  u3tmp = u1 + b;
277  if (u3tmp < u3)
278  {
279  predecessors[v3] = v1;
280  direction[v3] = 0;
281  distances[v3] = u3tmp;
282  const lvr2::FaceHandle fh = mesh.getFaceBetween(v1, v2, v3).unwrap();
283  cutting_faces.insert(v3, fh);
284 #ifdef DEBUG
285  mesh_map->publishDebugVector(v3, v1, fh, 0, mesh_map::color(0.9, 0.9, 0.2),
286  "dir_vec" + std::to_string(v3.idx()));
287 #endif
288  return true;
289  }
290  return false;
291  }
292  }
293  else
294  {
295  const double S = sx * hc - hc * c + sy * c - sy * p;
296  const double t2cos = (a_sq + u3tmp_sq - u2_sq) / (2 * a * u3tmp);
297  if (S <= 0 && std::fabs(t2cos) <= 1)
298  {
299  const lvr2::FaceHandle fh = mesh.getFaceBetween(v1, v2, v3).unwrap();
300  const double theta = -acos(t2cos);
301  direction[v3] = static_cast<float>(theta);
302  distances[v3] = static_cast<float>(u3tmp);
303  predecessors[v3] = v2;
304  cutting_faces.insert(v3, fh);
305 #ifdef DEBUG
306  mesh_map->publishDebugVector(v3, v2, fh, theta, mesh_map::color(0.9, 0.9, 0.2),
307  "dir_vec" + std::to_string(v3.idx()));
308 #endif
309  return true;
310  }
311  else
312  {
313  u3tmp = u2 + a;
314  if (u3tmp < u3)
315  {
316  direction[v3] = 0;
317  distances[v3] = u3tmp;
318  predecessors[v3] = v2;
319  const lvr2::FaceHandle fh = mesh.getFaceBetween(v1, v2, v3).unwrap();
320  cutting_faces.insert(v3, fh);
321 #ifdef DEBUG
322  mesh_map->publishDebugVector(v3, v2, fh, 0, mesh_map::color(0.9, 0.9, 0.2),
323  "dir_vec" + std::to_string(v3.idx()));
324 #endif
325  return true;
326  }
327  return false;
328  }
329  }
330  }
331  return false;
332 }
333 
335  const lvr2::DenseEdgeMap<float>& edge_weights,
336  const lvr2::VertexHandle& v1, const lvr2::VertexHandle& v2,
337  const lvr2::VertexHandle& v3)
338 {
339  const auto& mesh = mesh_map->mesh();
340 
341  const double u1 = distances[v1];
342  const double u2 = distances[v2];
343  const double u3 = distances[v3];
344 
345  const lvr2::OptionalEdgeHandle e12h = mesh.getEdgeBetween(v1, v2);
346  const double c = edge_weights[e12h.unwrap()];
347  const double c_sq = c * c;
348 
349  const lvr2::OptionalEdgeHandle e13h = mesh.getEdgeBetween(v1, v3);
350  const double b = edge_weights[e13h.unwrap()];
351  const double b_sq = b * b;
352 
353  const lvr2::OptionalEdgeHandle e23h = mesh.getEdgeBetween(v2, v3);
354  const double a = edge_weights[e23h.unwrap()];
355  const double a_sq = a * a;
356 
357  const double u1_sq = u1 * u1;
358  const double u2_sq = u2 * u2;
359 
360  const double sx = (c_sq + u1_sq - u2_sq) / (2 * c);
361  const double sy = -sqrt(std::max(u1_sq - sx*sx, 0.0));
362 
363  const double p = (b_sq + c_sq -a_sq) / (2 * c);
364  const double hc = sqrt(std::max(b_sq - p*p, 0.0));
365 
366  const double dy = hc - sy;
367  const double dx = p - sx;
368 
369  const double u3tmp_sq = dx * dx + dy * dy;
370  double u3tmp = sqrt(u3tmp_sq);
371 
372  if (!std::isfinite(u3tmp))
373  {
374  ROS_ERROR_STREAM("u3 tmp is not finite!");
375  }
376  if (u3tmp < u3)
377  {
378  const double t0a = (a_sq + b_sq - c_sq) / (2 * a * b);
379  const double t1a = (u3tmp_sq + b_sq - u1_sq) / (2 * u3tmp * b);
380  const double t2a = (a_sq + u3tmp_sq - u2_sq) / (2 * a * u3tmp);
381 
382  // corner case: side b + u1 ~= u3
383  if (std::fabs(t1a) > 1)
384  {
385  u3tmp = u1 + b;
386  if (u3tmp < u3)
387  {
388  auto fH = mesh.getFaceBetween(v1, v2, v3).unwrap();
389  cutting_faces.insert(v3, fH);
390  predecessors[v3] = v1;
391 #ifdef DEBUG
392  mesh_map->publishDebugVector(v3, v1, fH, 0, mesh_map::color(0.9, 0.9, 0.2),
393  "dir_vec" + std::to_string(v3.idx()));
394 #endif
395  distances[v3] = static_cast<float>(u3tmp);
396  direction[v3] = 0;
397  return true;
398  }
399  return false;
400  }
401  // corner case: side a + u2 ~= u3
402  else if (std::fabs(t2a) > 1)
403  {
404  u3tmp = u2 + a;
405  if (u3tmp < u3)
406  {
407  auto fH = mesh.getFaceBetween(v1, v2, v3).unwrap();
408  cutting_faces.insert(v3, fH);
409  predecessors[v3] = v2;
410 #ifdef DEBUG
411  mesh_map->publishDebugVector(v3, v2, fH, 0, mesh_map::color(0.9, 0.9, 0.2),
412  "dir_vec" + std::to_string(v3.idx()));
413 #endif
414  distances[v3] = static_cast<float>(u3tmp);
415  direction[v3] = 0;
416  return true;
417  }
418  return false;
419  }
420 
421  const double theta0 = acos(t0a);
422  const double theta1 = acos(t1a);
423  const double theta2 = acos(t2a);
424 
425 #ifdef DEBUG
426  if (!std::isfinite(theta0 + theta1 + theta2))
427  {
428  ROS_ERROR_STREAM("------------------");
429  if (std::isnan(theta0))
430  ROS_ERROR_STREAM("Theta0 is NaN!");
431  if (std::isnan(theta1))
432  ROS_ERROR_STREAM("Theta1 is NaN!");
433  if (std::isnan(theta2))
434  ROS_ERROR_STREAM("Theta2 is NaN!");
435  if (std::isinf(theta2))
436  ROS_ERROR_STREAM("Theta2 is inf!");
437  if (std::isinf(theta2))
438  ROS_ERROR_STREAM("Theta2 is inf!");
439  if (std::isinf(theta2))
440  ROS_ERROR_STREAM("Theta2 is inf!");
441  if (std::isnan(t1a))
442  ROS_ERROR_STREAM("t1a is NaN!");
443  if (std::isnan(t2a))
444  ROS_ERROR_STREAM("t2a is NaN!");
445  if (std::fabs(t2a) > 1)
446  {
447  ROS_ERROR_STREAM("|t2a| is > 1: " << t2a);
448  ROS_INFO_STREAM("a: " << a << ", u3: " << u3tmp << ", u2: " << u2 << ", a+u2: " << a + u2);
449  }
450  if (std::fabs(t1a) > 1)
451  {
452  ROS_ERROR_STREAM("|t1a| is > 1: " << t1a);
453  ROS_INFO_STREAM("b: " << b << ", u3: " << u3tmp << ", u1: " << u1 << ", b+u1: " << b + u1);
454  }
455  }
456 #endif
457 
458  if (theta1 < theta0 && theta2 < theta0)
459  {
460  auto fH = mesh.getFaceBetween(v1, v2, v3).unwrap();
461  cutting_faces.insert(v3, fH);
462  distances[v3] = static_cast<float>(u3tmp);
463  if (theta1 < theta2)
464  {
465  predecessors[v3] = v1;
466  direction[v3] = theta1;
467 #ifdef DEBUG
468  mesh_map->publishDebugVector(v3, v1, fH, theta1, mesh_map::color(0.9, 0.9, 0.2),
469  "dir_vec" + std::to_string(v3.idx()));
470 #endif
471  }
472  else
473  {
474  predecessors[v3] = v2;
475  direction[v3] = -theta2;
476 #ifdef DEBUG
477  mesh_map->publishDebugVector(v3, v2, fH, -theta2, mesh_map::color(0.9, 0.9, 0.2),
478  "dir_vec" + std::to_string(v3.idx()));
479 #endif
480  }
481  return true;
482  }
483  else if (theta1 < theta2)
484  {
485  u3tmp = u1 + b;
486  if (u3tmp < u3)
487  {
488  auto fH = mesh.getFaceBetween(v1, v2, v3).unwrap();
489  cutting_faces.insert(v3, fH);
490  predecessors[v3] = v1;
491  distances[v3] = static_cast<float>(u3tmp);
492 #ifdef DEBUG
493  mesh_map->publishDebugVector(v3, v1, fH, 0, mesh_map::color(0.9, 0.9, 0.2),
494  "dir_vec" + std::to_string(v3.idx()));
495 #endif
496  direction[v3] = 0;
497  return true;
498  }
499  return false;
500  }
501  else
502  {
503  u3tmp = u2 + a;
504  if (u3tmp < u3)
505  {
506  auto fH = mesh.getFaceBetween(v1, v2, v3).unwrap();
507  cutting_faces.insert(v3, fH);
508  predecessors[v3] = v2;
509  distances[v3] = static_cast<float>(u3tmp);
510 #ifdef DEBUG
511  mesh_map->publishDebugVector(v3, v2, fH, 0, mesh_map::color(0.9, 0.9, 0.2),
512  "dir_vec" + std::to_string(v3.idx()));
513 #endif
514  direction[v3] = 0;
515  return true;
516  }
517  return false;
518  }
519  }
520  return false;
521 }
522 
524  const mesh_map::Vector& original_goal,
525  const lvr2::DenseEdgeMap<float>& edge_weights,
526  const lvr2::DenseVertexMap<float>& costs,
527  std::list<std::pair<mesh_map::Vector, lvr2::FaceHandle>>& path,
528  lvr2::DenseVertexMap<float>& distances,
530 {
531  ROS_DEBUG_STREAM("Init wave front propagation.");
532 
533  const auto& mesh = mesh_map->mesh();
534  const auto& vertex_costs = mesh_map->vertexCosts();
535  auto& invalid = mesh_map->invalid;
536 
537  mesh_map->publishDebugPoint(original_start, mesh_map::color(0, 1, 0), "start_point");
538  mesh_map->publishDebugPoint(original_goal, mesh_map::color(0, 0, 1), "goal_point");
539 
540  mesh_map::Vector start = original_start;
541  mesh_map::Vector goal = original_goal;
542 
543  // Find the containing faces of start and goal
544  const auto& start_opt = mesh_map->getContainingFace(start, 0.4);
545  const auto& goal_opt = mesh_map->getContainingFace(goal, 0.4);
546 
547  ros::WallTime t_initialization_start = ros::WallTime::now();
548 
549  // reset cancel planning
550  cancel_planning = false;
551 
552  if (!start_opt)
553  return mbf_msgs::GetPathResult::INVALID_START;
554  if (!goal_opt)
555  return mbf_msgs::GetPathResult::INVALID_GOAL;
556 
557  const auto& start_face = start_opt.unwrap();
558  const auto& goal_face = goal_opt.unwrap();
559 
560  mesh_map->publishDebugFace(start_face, mesh_map::color(0, 0, 1), "start_face");
561  mesh_map->publishDebugFace(goal_face, mesh_map::color(0, 1, 0), "goal_face");
562 
563  path.clear();
564  distances.clear();
565  predecessors.clear();
566 
567  if (goal_face == start_face)
568  {
569  return mbf_msgs::GetPathResult::SUCCESS;
570  }
571 
572  lvr2::DenseVertexMap<bool> fixed(mesh.nextVertexIndex(), false);
573 
574  // clear vector field map
575  vector_map.clear();
576 
577  // initialize distances with infinity
578  // initialize predecessor of each vertex with itself
579  for (auto const& vH : mesh.vertices())
580  {
581  distances.insert(vH, std::numeric_limits<float>::infinity());
582  predecessors.insert(vH, vH);
583  }
584 
586  // Set start distance to zero
587  // add start vertex to priority queue
588  for (auto vH : mesh.getVerticesOfFace(start_face))
589  {
590  const mesh_map::Vector diff = start - mesh.getVertexPosition(vH);
591  const float dist = diff.length();
592  distances[vH] = dist;
593  vector_map.insert(vH, diff);
594  cutting_faces.insert(vH, start_face);
595  fixed[vH] = true;
596  pq.insert(vH, dist);
597  }
598 
599  std::array<lvr2::VertexHandle, 3> goal_vertices = mesh.getVerticesOfFace(goal_face);
600  ROS_DEBUG_STREAM("The goal is at (" << goal.x << ", " << goal.y << ", " << goal.z << ") at the face ("
601  << goal_vertices[0] << ", " << goal_vertices[1] << ", " << goal_vertices[2]
602  << ")");
603  mesh_map->publishDebugPoint(mesh.getVertexPosition(goal_vertices[0]), mesh_map::color(0, 0, 1), "goal_face_v1");
604  mesh_map->publishDebugPoint(mesh.getVertexPosition(goal_vertices[1]), mesh_map::color(0, 0, 1), "goal_face_v2");
605  mesh_map->publishDebugPoint(mesh.getVertexPosition(goal_vertices[2]), mesh_map::color(0, 0, 1), "goal_face_v3");
606 
607  float goal_dist = std::numeric_limits<float>::infinity();
608 
609  ROS_DEBUG_STREAM("Start wavefront propagation...");
610 
611  size_t fixed_cnt = 0;
612  size_t fixed_set_cnt = 0;
613  ros::WallTime t_wavefront_start = ros::WallTime::now();
614  double initialization_duration = (t_wavefront_start - t_initialization_start).toNSec() * 1e-6;
615 
616  while (!pq.isEmpty() && !cancel_planning)
617  {
618  lvr2::VertexHandle current_vh = pq.popMin().key();
619 
620  fixed[current_vh] = true;
621  fixed_set_cnt++;
622 
623  if (distances[current_vh] > goal_dist)
624  continue;
625 
626  if (vertex_costs[current_vh] > config.cost_limit)
627  continue;
628 
629  if (invalid[current_vh])
630  continue;
631 
632  if (current_vh == goal_vertices[0] || current_vh == goal_vertices[1] || current_vh == goal_vertices[2])
633  {
634  if (goal_dist == std::numeric_limits<float>::infinity() && fixed[goal_vertices[0]] && fixed[goal_vertices[1]] &&
635  fixed[goal_vertices[2]])
636  {
637  ROS_DEBUG_STREAM("Wave front reached the goal!");
638  goal_dist = distances[current_vh] + goal_dist_offset;
639  }
640  }
641 
642  try
643  {
644  std::vector<lvr2::FaceHandle> faces;
645  mesh.getFacesOfVertex(current_vh, faces);
646 
647  for (auto fh : faces)
648  {
649  const auto vertices = mesh.getVerticesOfFace(fh);
650  const lvr2::VertexHandle& a = vertices[0];
651  const lvr2::VertexHandle& b = vertices[1];
652  const lvr2::VertexHandle& c = vertices[2];
653 
654  if (invalid[a] || invalid[b] || invalid[c])
655  continue;
656 
657  // We are looking for a face where exactly
658  // one vertex is not in the fixed set
659  if (fixed[a] && fixed[b] && fixed[c])
660  {
661 // The face's vertices are already optimal
662 // with respect to the distance
663 #ifdef DEBUG
664  mesh_map->publishDebugFace(fh, mesh_map::color(1, 0, 0), "fmm_fixed_" + std::to_string(fixed_cnt++));
665 #endif
666  continue;
667  }
668  else if (fixed[a] && fixed[b] && !fixed[c])
669  {
670  // c is free
671 #ifdef USE_UPDATE_WITH_S
672  if (waveFrontUpdateWithS(distances, edge_weights, a, b, c))
673 #else
674  if (waveFrontUpdate(distances, edge_weights, a, b, c))
675 #endif
676  {
677  pq.insert(c, distances[c]);
678 #ifdef DEBUG
679  mesh_map->publishDebugFace(fh, mesh_map::color(0, 1, 1), "fmm_update");
680  sleep(2);
681 #endif
682  }
683  }
684  else if (fixed[a] && !fixed[b] && fixed[c])
685  {
686  // b is free
687 #ifdef USE_UPDATE_WITH_S
688  if (waveFrontUpdateWithS(distances, edge_weights, c, a, b))
689 #else
690  if (waveFrontUpdate(distances, edge_weights, c, a, b))
691 #endif
692  {
693  pq.insert(b, distances[b]);
694 #ifdef DEBUG
695  mesh_map->publishDebugFace(fh, mesh_map::color(0, 1, 1), "fmm_update");
696  sleep(2);
697 #endif
698  }
699  }
700  else if (!fixed[a] && fixed[b] && fixed[c])
701  {
702  // a if free
703 #ifdef USE_UPDATE_WITH_S
704  if (waveFrontUpdateWithS(distances, edge_weights, b, c, a))
705 #else
706  if (waveFrontUpdate(distances, edge_weights, b, c, a))
707 #endif
708  {
709  pq.insert(a, distances[a]);
710 #ifdef DEBUG
711  mesh_map->publishDebugFace(fh, mesh_map::color(0, 1, 1), "fmm_update");
712  sleep(2);
713 #endif
714  }
715  }
716  else
717  {
718  // two free vertices -> skip that face
719  continue;
720  }
721  }
722  }
723  catch (lvr2::PanicException exception)
724  {
725  invalid.insert(current_vh, true);
726  ROS_ERROR_STREAM("Found invalid vertex!");
727  continue;
728  }
729  catch (lvr2::VertexLoopException exception)
730  {
731  invalid.insert(current_vh, true);
732  ROS_ERROR_STREAM("Found invalid vertex!");
733  continue;
734  }
735  }
736 
737  if (cancel_planning)
738  {
739  ROS_WARN_STREAM("Wave front propagation has been canceled!");
740  return mbf_msgs::GetPathResult::CANCELED;
741  }
742  ros::WallTime t_wavefront_end = ros::WallTime::now();
743  double wavefront_propagation_duration = (t_wavefront_end - t_wavefront_start).toNSec() * 1e-6;
744  ROS_DEBUG_STREAM("Finished wave front propagation.");
745  ROS_DEBUG_STREAM("Computing the vector map...");
747 
748  ros::WallTime t_vector_field_end = ros::WallTime::now();
749  double vector_field_duration = (t_vector_field_end - t_wavefront_end).toNSec() * 1e-6;
750 
751  bool path_exists = false;
752  for (auto goal_vertex : goal_vertices)
753  {
754  if (goal_vertex != predecessors[goal_vertex])
755  {
756  path_exists = true;
757  break;
758  }
759  }
760 
761  if (!path_exists)
762  {
763  ROS_WARN("Predecessor of the goal is not set! No path found!");
764  return mbf_msgs::GetPathResult::NO_PATH_FOUND;
765  }
766 
767  ROS_DEBUG_STREAM("Start vector field back tracking!");
768 
769  lvr2::FaceHandle current_face = goal_face;
770  mesh_map::Vector current_pos = goal;
771  path.push_front(std::pair<mesh_map::Vector, lvr2::FaceHandle>(current_pos, current_face));
772 
773  // move from the goal position towards the start position
774  while (current_pos.distance2(start) > config.step_width && !cancel_planning)
775  {
776  // move current pos ahead on the surface following the vector field,
777  // updates the current face if necessary
778  try
779  {
780  if (mesh_map->meshAhead(current_pos, current_face, config.step_width))
781  {
782  path.push_front(std::pair<mesh_map::Vector, lvr2::FaceHandle>(current_pos, current_face));
783  }
784  else
785  {
786  ROS_WARN_STREAM("Could not find a valid path, while back-tracking from the goal");
787  return mbf_msgs::GetPathResult::NO_PATH_FOUND;
788  }
789  }
790  catch (lvr2::PanicException exception)
791  {
792  ROS_ERROR_STREAM("Could not find a valid path, while back-tracking from the goal: HalfEdgeMesh panicked!");
793  return mbf_msgs::GetPathResult::NO_PATH_FOUND;
794  }
795  }
796  path.push_front(std::pair<mesh_map::Vector, lvr2::FaceHandle>(start, start_face));
797 
798  ros::WallTime t_path_backtracking = ros::WallTime::now();
799  double path_backtracking_duration = (t_path_backtracking - t_vector_field_end).toNSec() * 1e-6;
800 
801  ROS_INFO_STREAM("Processed " << fixed_set_cnt << " vertices in the fixed set.");
802  ROS_INFO_STREAM("Initialization duration (ms): " << initialization_duration);
803  ROS_INFO_STREAM("Execution time wavefront propagation (ms): "<< wavefront_propagation_duration);
804  ROS_INFO_STREAM("Vector field post computation (ms): " << vector_field_duration);
805  ROS_INFO_STREAM("Path backtracking duration (ms): " << path_backtracking_duration);
806 
807  if (cancel_planning)
808  {
809  ROS_WARN_STREAM("Wave front propagation has been canceled!");
810  return mbf_msgs::GetPathResult::CANCELED;
811  }
812 
813  ROS_INFO_STREAM("Successfully finished vector field back tracking!");
814  return mbf_msgs::GetPathResult::SUCCESS;
815 }
816 
817 } /* namespace wave_front_planner */
818 
Handles.hpp
wave_front_planner::WaveFrontPlanner::config_callback
dynamic_reconfigure::Server< wave_front_planner::WaveFrontPlannerConfig >::CallbackType config_callback
dynamic reconfigure callback function binding
Definition: wave_front_planner.h:191
Meap.hpp
lvr2::PanicException
lvr2::BaseVector::length
CoordT length() const
lvr2::BaseVector
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(args)
boost::shared_ptr
wave_front_planner::WaveFrontPlanner::first_config
bool first_config
indicates if dynamic reconfigure has been called the first time
Definition: wave_front_planner.h:194
wave_front_planner::WaveFrontPlanner::private_nh
ros::NodeHandle private_nh
the private node handle with the user defined namespace (name)
Definition: wave_front_planner.h:167
PLUGINLIB_EXPORT_CLASS
PLUGINLIB_EXPORT_CLASS(wave_front_planner::WaveFrontPlanner, mbf_mesh_core::MeshPlanner)
mesh_map
lvr2::FaceHandle
wave_front_planner::WaveFrontPlanner::cancel_planning
std::atomic_bool cancel_planning
flag if cancel has been requested
Definition: wave_front_planner.h:170
wave_front_planner::WaveFrontPlanner::WaveFrontPlanner
WaveFrontPlanner()
Constructor.
Definition: wave_front_planner.cpp:53
wave_front_planner::WaveFrontPlanner::predecessors
lvr2::DenseVertexMap< lvr2::VertexHandle > predecessors
predecessors while wave propagation
Definition: wave_front_planner.h:203
lvr2::VertexLoopException
wave_front_planner::WaveFrontPlanner::waveFrontPropagation
uint32_t waveFrontPropagation(const mesh_map::Vector &start, const mesh_map::Vector &goal, std::list< std::pair< mesh_map::Vector, lvr2::FaceHandle >> &path)
Computes a wavefront propagation from the start until it reached the goal.
Definition: wave_front_planner.cpp:207
mesh_map::color
std_msgs::ColorRGBA color(const float &r, const float &g, const float &b, const float &a=1.0)
wave_front_planner::WaveFrontPlanner::config
WaveFrontPlannerConfig config
the current dynamic reconfigure planner configuration
Definition: wave_front_planner.h:197
wave_front_planner::WaveFrontPlanner::potential
lvr2::DenseVertexMap< float > potential
potential field / scalar distance field to the seed
Definition: wave_front_planner.h:212
lvr2::BaseVector::distance2
CoordT distance2(const BaseVector &other) const
p
SharedPointer p
lvr2::BaseVector::x
CoordT x
ROS_DEBUG_STREAM
#define ROS_DEBUG_STREAM(args)
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
BaseOptionalHandle< Index, EdgeHandle >::unwrap
EdgeHandle unwrap() const
ros::NodeHandle::advertise
Publisher advertise(AdvertiseOptions &ops)
f
f
class_list_macros.h
wave_front_planner::WaveFrontPlanner::reconfigureCallback
void reconfigureCallback(wave_front_planner::WaveFrontPlannerConfig &cfg, uint32_t level)
Dynamic reconfigure callback.
Definition: wave_front_planner.cpp:158
lvr2::VectorMap
wave_front_planner::WaveFrontPlanner::vector_map
lvr2::DenseVertexMap< mesh_map::Vector > vector_map
stores the current vector map containing vectors pointing to the seed
Definition: wave_front_planner.h:209
ROS_WARN_STREAM
#define ROS_WARN_STREAM(args)
lvr2::OptionalEdgeHandle
wave_front_planner::WaveFrontPlanner::map_frame
std::string map_frame
the map coordinate frame / system id
Definition: wave_front_planner.h:182
wave_front_planner::WaveFrontPlanner::cutting_faces
lvr2::DenseVertexMap< lvr2::FaceHandle > cutting_faces
the face which is cut by the computed line to the source
Definition: wave_front_planner.h:206
wave_front_planner::WaveFrontPlanner::makePlan
virtual uint32_t makePlan(const geometry_msgs::PoseStamped &start, const geometry_msgs::PoseStamped &goal, double tolerance, std::vector< geometry_msgs::PoseStamped > &plan, double &cost, std::string &message)
Compute a continuous vector field and geodesic path on the mesh's surface.
Definition: wave_front_planner.cpp:61
ros::WallTime::now
static WallTime now()
mbf_mesh_core::MeshPlanner
wave_front_planner::WaveFrontPlanner::waveFrontUpdateWithS
bool waveFrontUpdateWithS(lvr2::DenseVertexMap< float > &distances, const lvr2::DenseEdgeMap< float > &edge_weights, const lvr2::VertexHandle &v1, const lvr2::VertexHandle &v2, const lvr2::VertexHandle &v3)
Definition: wave_front_planner.cpp:214
lvr2::BaseVector::y
CoordT y
lvr2::VertexHandle
lvr2::Meap
lvr2::Meap::insert
boost::optional< ValueT > insert(KeyT key, const ValueT &value)
wave_front_planner::WaveFrontPlanner::computeVectorMap
void computeVectorMap()
Computes the vector field in a post processing. It rotates the predecessor edges by the stored angles...
Definition: wave_front_planner.cpp:170
wave_front_planner::WaveFrontPlanner::name
std::string name
the user defined plugin name
Definition: wave_front_planner.h:164
ROS_WARN
#define ROS_WARN(...)
wave_front_planner::WaveFrontPlanner::direction
lvr2::DenseVertexMap< float > direction
theta angles to the source of the wave front propagation
Definition: wave_front_planner.h:200
ROS_INFO_STREAM
#define ROS_INFO_STREAM(args)
ros::WallTime
wave_front_planner::WaveFrontPlanner::goal_dist_offset
float goal_dist_offset
an offset that determines how far beyond the goal (robot's position) is propagated.
Definition: wave_front_planner.h:185
wave_front_planner::WaveFrontPlanner::initialize
virtual bool initialize(const std::string &name, const boost::shared_ptr< mesh_map::MeshMap > &mesh_map_ptr)
Initializes the planner plugin with a user configured name and a shared pointer to the mesh map.
Definition: wave_front_planner.cpp:132
lvr2::Meap::isEmpty
bool isEmpty() const
wave_front_planner::WaveFrontPlanner::publish_face_vectors
bool publish_face_vectors
whether to also publish direction vectors at the triangle centers
Definition: wave_front_planner.h:179
wave_front_planner
Definition: wave_front_planner.h:47
start
ROSCPP_DECL void start()
lvr2::VectorMap::clear
void clear() final
wave_front_planner::WaveFrontPlanner
Definition: wave_front_planner.h:49
wave_front_planner.h
wave_front_planner::WaveFrontPlanner::publish_vector_field
bool publish_vector_field
whether to publish the vector field or not
Definition: wave_front_planner.h:176
lvr2::BaseVector::z
CoordT z
wave_front_planner::WaveFrontPlanner::waveFrontUpdate
bool waveFrontUpdate(lvr2::DenseVertexMap< float > &distances, const lvr2::DenseEdgeMap< float > &edge_weights, const lvr2::VertexHandle &v1, const lvr2::VertexHandle &v2, const lvr2::VertexHandle &v3)
Definition: wave_front_planner.cpp:334
wave_front_planner::WaveFrontPlanner::cancel
virtual bool cancel()
Requests the planner to cancel, e.g. if it takes too much time.
Definition: wave_front_planner.cpp:126
wave_front_planner::WaveFrontPlanner::path_pub
ros::Publisher path_pub
publisher for the backtracked path
Definition: wave_front_planner.h:173
lvr2::Meap::popMin
MeapPair< KeyT, ValueT > popMin()
lvr2::VectorMap::insert
boost::optional< ValueT > insert(HandleT key, const ValueT &value) final
ros::NodeHandle::param
T param(const std::string &param_name, const T &default_val) const
mesh_map::toVector
Vector toVector(const geometry_msgs::Point &point)
wave_front_planner::WaveFrontPlanner::~WaveFrontPlanner
virtual ~WaveFrontPlanner()
Destructor.
Definition: wave_front_planner.cpp:57
mesh_map::calculatePoseFromPosition
geometry_msgs::Pose calculatePoseFromPosition(const Vector &current, const Vector &next, const Normal &normal)
header
const std::string header
wave_front_planner::WaveFrontPlanner::reconfigure_server_ptr
boost::shared_ptr< dynamic_reconfigure::Server< wave_front_planner::WaveFrontPlannerConfig > > reconfigure_server_ptr
shared pointer to dynamic reconfigure server
Definition: wave_front_planner.h:188
ROS_INFO
#define ROS_INFO(...)
mesh
HalfEdgeMesh< Vec > mesh
util.h
ros::NodeHandle
BaseHandle< Index >::idx
Index idx() const
ros::Time::now
static Time now()


wave_front_planner
Author(s): Sebastian Pütz
autogenerated on Mon Jan 4 2021 03:44:17