dijkstra_mesh_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 #include <mbf_msgs/GetPathResult.h>
41 #include <mesh_map/util.h>
43 
45 
46 namespace dijkstra_mesh_planner
47 {
49 {
50 }
51 
53 {
54 }
55 
56 uint32_t DijkstraMeshPlanner::makePlan(const geometry_msgs::PoseStamped& start, const geometry_msgs::PoseStamped& goal,
57  double tolerance, std::vector<geometry_msgs::PoseStamped>& plan, double& cost,
58  std::string& message)
59 {
60  const auto& mesh = mesh_map->mesh();
61  std::list<lvr2::VertexHandle> path;
62  ROS_INFO("start dijkstra mesh planner.");
63 
64  mesh_map::Vector goal_vec = mesh_map::toVector(goal.pose.position);
65  mesh_map::Vector start_vec = mesh_map::toVector(start.pose.position);
66 
67  // call dijkstra with the goal pose as seed / start vertex
68  uint32_t outcome = dijkstra(goal_vec, start_vec, path);
69 
70  path.reverse();
71 
72  std_msgs::Header header;
73  header.stamp = ros::Time::now();
74  header.frame_id = mesh_map->mapFrame();
75 
76  cost = 0;
77  if (!path.empty())
78  {
79  mesh_map::Vector& vec = start_vec;
80  const auto& vertex_normals = mesh_map->vertexNormals();
81  mesh_map::Normal normal = vertex_normals[path.front()];
82 
83  float dir_length;
84  geometry_msgs::PoseStamped pose;
85  pose.header = header;
86 
87  while (!path.empty())
88  {
89  // get next position
90  const lvr2::VertexHandle& vH = path.front();
91  mesh_map::Vector next = mesh.getVertexPosition(vH);
92 
93  pose.pose = mesh_map::calculatePoseFromPosition(vec, next, normal, dir_length);
94  cost += dir_length;
95  vec = next;
96  normal = vertex_normals[vH];
97  plan.push_back(pose);
98  path.pop_front();
99  }
100  pose.pose = mesh_map::calculatePoseFromPosition(vec, goal_vec, normal, dir_length);
101  cost += dir_length;
102  plan.push_back(pose);
103  }
104 
105  ROS_INFO_STREAM("Path length: " << cost << "m");
106  nav_msgs::Path path_msg;
107  path_msg.poses = plan;
108  path_msg.header = header;
109 
110  path_pub.publish(path_msg);
111  mesh_map->publishVertexCosts(potential, "Potential");
112 
113  ROS_INFO_STREAM("Path length: " << cost << "m");
114 
116  {
117  mesh_map->publishVectorField("vector_field", vector_map, publish_face_vectors);
118  }
119 
120  return outcome;
121 }
122 
124 {
125  cancel_planning = true;
126  return true;
127 }
128 
129 bool DijkstraMeshPlanner::initialize(const std::string& plugin_name,
130  const boost::shared_ptr<mesh_map::MeshMap>& mesh_map_ptr)
131 {
132  mesh_map = mesh_map_ptr;
133  name = plugin_name;
134  map_frame = mesh_map->mapFrame();
135  private_nh = ros::NodeHandle("~/" + name);
136 
137  private_nh.param("publish_vector_field", publish_vector_field, false);
138  private_nh.param("publish_face_vectors", publish_face_vectors, false);
139  private_nh.param("goal_dist_offset", goal_dist_offset, 0.3f);
140 
141  path_pub = private_nh.advertise<nav_msgs::Path>("path", 1, true);
142  const auto& mesh = mesh_map->mesh();
143 
146  new dynamic_reconfigure::Server<dijkstra_mesh_planner::DijkstraMeshPlannerConfig>(private_nh));
147 
148  config_callback = boost::bind(&DijkstraMeshPlanner::reconfigureCallback, this, _1, _2);
150 
151  return true;
152 }
153 
155 {
156  return vector_map;
157 }
158 
159 void DijkstraMeshPlanner::reconfigureCallback(dijkstra_mesh_planner::DijkstraMeshPlannerConfig& cfg, uint32_t level)
160 {
161  ROS_INFO_STREAM("New height diff layer config through dynamic reconfigure.");
162  if (first_config)
163  {
164  config = cfg;
165  first_config = false;
166  return;
167  }
168  config = cfg;
169 }
170 
172 {
173  const auto& mesh = mesh_map->mesh();
174 
175  for (auto v3 : mesh.vertices())
176  {
177  const lvr2::VertexHandle& v1 = predecessors[v3];
178  // if predecessor is pointing to it self, continue with the next vertex.
179  if (v1 == v3)
180  continue;
181 
182  const auto& vec3 = mesh.getVertexPosition(v3);
183  const auto& vec1 = mesh.getVertexPosition(v1);
184 
185  // compute the direction vector and store it in the direction vertex map
186  const auto dirVec = vec1 - vec3;
187  // store the normalized rotated vector in the vector map
188  vector_map.insert(v3, dirVec.normalized());
189  }
190  mesh_map->setVectorMap(vector_map);
191 }
192 
194  std::list<lvr2::VertexHandle>& path)
195 {
196  return dijkstra(start, goal, mesh_map->edgeDistances(), mesh_map->vertexCosts(), path, potential, predecessors);
197 }
198 
199 uint32_t DijkstraMeshPlanner::dijkstra(const mesh_map::Vector& original_start, const mesh_map::Vector& original_goal,
200  const lvr2::DenseEdgeMap<float>& edge_weights,
201  const lvr2::DenseVertexMap<float>& costs, std::list<lvr2::VertexHandle>& path,
202  lvr2::DenseVertexMap<float>& distances,
204 {
205  ROS_INFO_STREAM("Init wave front propagation.");
206  ros::WallTime t_initialization_start = ros::WallTime::now();
207 
208  const auto& mesh = mesh_map->mesh();
209  const auto& vertex_costs = mesh_map->vertexCosts();
210 
211  auto& invalid = mesh_map->invalid;
212 
213  mesh_map->publishDebugPoint(original_start, mesh_map::color(0, 1, 0), "start_point");
214  mesh_map->publishDebugPoint(original_goal, mesh_map::color(0, 0, 1), "goal_point");
215 
216  // Find the closest vertex handle of start and goal
217  const auto& start_opt = mesh_map->getNearestVertexHandle(original_start);
218  const auto& goal_opt = mesh_map->getNearestVertexHandle(original_goal);
219  // reset cancel planning
220  cancel_planning = false;
221 
222  if (!start_opt)
223  return mbf_msgs::GetPathResult::INVALID_START;
224  if (!goal_opt)
225  return mbf_msgs::GetPathResult::INVALID_GOAL;
226 
227  const auto& start_vertex = start_opt.unwrap();
228  const auto& goal_vertex = goal_opt.unwrap();
229 
230  path.clear();
231  distances.clear();
232  predecessors.clear();
233 
234  if (goal_vertex == start_vertex)
235  {
236  return mbf_msgs::GetPathResult::SUCCESS;
237  }
238 
239  lvr2::DenseVertexMap<bool> fixed(mesh.nextVertexIndex(), false);
240 
241  // clear vector field map
242  vector_map.clear();
243 
244  ros::WallTime t_start, t_end;
245  t_start = ros::WallTime::now();
246 
247  // initialize distances with infinity
248  // initialize predecessor of each vertex with itself
249  for (auto const& vH : mesh.vertices())
250  {
251  distances.insert(vH, std::numeric_limits<float>::infinity());
252  predecessors.insert(vH, vH);
253  }
254 
256 
257  // Set start distance to zero
258  // add start vertex to priority queue
259  distances[start_vertex] = 0;
260  pq.insert(start_vertex, 0);
261 
262  float goal_dist = std::numeric_limits<float>::infinity();
263 
264  ROS_INFO_STREAM("Start Dijkstra");
265  ros::WallTime t_propagation_start = ros::WallTime::now();
266  double initialization_duration = (t_propagation_start - t_initialization_start).toNSec() * 1e-6;
267 
268  size_t fixed_set_cnt = 0;
269 
270  while (!pq.isEmpty() && !cancel_planning)
271  {
272  lvr2::VertexHandle current_vh = pq.popMin().key();
273  fixed[current_vh] = true;
274  fixed_set_cnt++;
275 
276  if (current_vh == goal_vertex)
277  {
278  ROS_INFO_STREAM("The Dijkstra Mesh Planner reached the goal.");
279  goal_dist = distances[current_vh] + goal_dist_offset;
280  }
281 
282  if (distances[current_vh] > goal_dist)
283  continue;
284 
285  if (vertex_costs[current_vh] > config.cost_limit)
286  continue;
287 
288  std::vector<lvr2::EdgeHandle> edges;
289  try
290  {
291  mesh.getEdgesOfVertex(current_vh, edges);
292  }
293  catch (lvr2::PanicException exception)
294  {
295  invalid.insert(current_vh, true);
296  continue;
297  }
298  catch (lvr2::VertexLoopException exception)
299  {
300  invalid.insert(current_vh, true);
301  continue;
302  }
303  for (auto eH : edges)
304  {
305  try
306  {
307  std::array<lvr2::VertexHandle, 2> vertices = mesh.getVerticesOfEdge(eH);
308  auto vH = vertices[0] == current_vh ? vertices[1] : vertices[0];
309  if (fixed[vH])
310  continue;
311  if (invalid[vH])
312  continue;
313 
314  float tmp_cost = distances[current_vh] + edge_weights[eH];
315  if (tmp_cost < distances[vH])
316  {
317  distances[vH] = tmp_cost;
318  pq.insert(vH, tmp_cost);
319  predecessors[vH] = current_vh;
320  }
321  }
322  catch (lvr2::PanicException exception)
323  {
324  continue;
325  }
326  catch (lvr2::VertexLoopException exception)
327  {
328  continue;
329  }
330  }
331  }
332 
333  if (cancel_planning)
334  {
335  ROS_WARN_STREAM("Wave front propagation has been canceled!");
336  return mbf_msgs::GetPathResult::CANCELED;
337  }
338 
339  ROS_INFO_STREAM("The Dijkstra Mesh Planner finished the propagation.");
340 
341  if (goal_vertex == predecessors[goal_vertex])
342  {
343  ROS_WARN("Predecessor of the goal is not set! No path found!");
344  return mbf_msgs::GetPathResult::NO_PATH_FOUND;
345  }
346 
347  ros::WallTime t_propagation_end = ros::WallTime::now();
348  double propagation_duration = (t_propagation_end - t_propagation_start).toNSec() * 1e-6;
349 
350  auto vH = goal_vertex;
351 
352  while (vH != start_vertex && !cancel_planning)
353  {
354  vH = predecessors[vH];
355  path.push_front(vH);
356  };
357 
358  t_end = ros::WallTime::now();
359  double execution_time = (t_end - t_start).toNSec() * 1e-6;
360  ROS_INFO_STREAM("Execution time (ms): " << execution_time << " for " << mesh.numVertices()
361  << " num vertices in the mesh.");
362 
364 
365  if (cancel_planning)
366  {
367  ROS_WARN_STREAM("Dijkstra has been canceled!");
368  return mbf_msgs::GetPathResult::CANCELED;
369  }
370 
371  ros::WallTime t_path_backtracking = ros::WallTime::now();
372  double path_backtracking_duration = (t_path_backtracking - t_propagation_end).toNSec() * 1e-6;
373 
374  ROS_INFO_STREAM("Processed " << fixed_set_cnt << " vertices in the fixed set.");
375  ROS_INFO_STREAM("Initialization duration (ms): " << initialization_duration);
376  ROS_INFO_STREAM("Execution time wavefront propagation (ms): "<< propagation_duration);
377  ROS_INFO_STREAM("Path backtracking duration (ms): " << path_backtracking_duration);
378 
379  ROS_INFO_STREAM("Successfully finished Dijkstra back tracking!");
380  return mbf_msgs::GetPathResult::SUCCESS;
381 }
382 
383 } /* namespace dijkstra_mesh_planner */
384 
dijkstra_mesh_planner::DijkstraMeshPlanner::name
std::string name
Definition: dijkstra_mesh_planner.h:166
Meap.hpp
lvr2::PanicException
dijkstra_mesh_planner.h
lvr2::BaseVector
boost::shared_ptr
dijkstra_mesh_planner::DijkstraMeshPlanner::cancel
virtual bool cancel()
Requests the planner to cancel, e.g. if it takes too much time.
Definition: dijkstra_mesh_planner.cpp:123
dijkstra_mesh_planner::DijkstraMeshPlanner::predecessors
lvr2::DenseVertexMap< lvr2::VertexHandle > predecessors
Definition: dijkstra_mesh_planner.h:189
mesh_map
lvr2::VertexLoopException
mesh_map::color
std_msgs::ColorRGBA color(const float &r, const float &g, const float &b, const float &a=1.0)
dijkstra_mesh_planner::DijkstraMeshPlanner::DijkstraMeshPlanner
DijkstraMeshPlanner()
Definition: dijkstra_mesh_planner.cpp:48
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
ros::NodeHandle::advertise
Publisher advertise(AdvertiseOptions &ops)
f
f
class_list_macros.h
lvr2::VectorMap
ROS_WARN_STREAM
#define ROS_WARN_STREAM(args)
dijkstra_mesh_planner::DijkstraMeshPlanner::dijkstra
uint32_t dijkstra(const mesh_map::Vector &start, const mesh_map::Vector &goal, std::list< lvr2::VertexHandle > &path)
runs dijkstra path planning and stores the resulting distances and predecessors to the fields potenti...
Definition: dijkstra_mesh_planner.cpp:193
dijkstra_mesh_planner::DijkstraMeshPlanner::publish_face_vectors
bool publish_face_vectors
Definition: dijkstra_mesh_planner.h:176
lvr2::Normal< float >
dijkstra_mesh_planner::DijkstraMeshPlanner::vector_map
lvr2::DenseVertexMap< mesh_map::Vector > vector_map
Definition: dijkstra_mesh_planner.h:194
dijkstra_mesh_planner::DijkstraMeshPlanner::map_frame
std::string map_frame
Definition: dijkstra_mesh_planner.h:178
ros::WallTime::now
static WallTime now()
mbf_mesh_core::MeshPlanner
dijkstra_mesh_planner::DijkstraMeshPlanner::getVectorMap
lvr2::DenseVertexMap< mesh_map::Vector > getVectorMap()
delivers vector field which has been generated during the latest planning
Definition: dijkstra_mesh_planner.cpp:154
dijkstra_mesh_planner::DijkstraMeshPlanner
Definition: dijkstra_mesh_planner.h:49
dijkstra_mesh_planner::DijkstraMeshPlanner::computeVectorMap
void computeVectorMap()
calculates the vector field based on the current predecessors map and stores it to the vector_map fie...
Definition: dijkstra_mesh_planner.cpp:171
lvr2::VertexHandle
lvr2::Meap
lvr2::Meap::insert
boost::optional< ValueT > insert(KeyT key, const ValueT &value)
dijkstra_mesh_planner::DijkstraMeshPlanner::~DijkstraMeshPlanner
virtual ~DijkstraMeshPlanner()
Destructor.
Definition: dijkstra_mesh_planner.cpp:52
dijkstra_mesh_planner::DijkstraMeshPlanner::publish_vector_field
bool publish_vector_field
Definition: dijkstra_mesh_planner.h:174
ROS_WARN
#define ROS_WARN(...)
dijkstra_mesh_planner::DijkstraMeshPlanner::reconfigureCallback
void reconfigureCallback(dijkstra_mesh_planner::DijkstraMeshPlannerConfig &cfg, uint32_t level)
gets called on new incoming reconfigure parameters
Definition: dijkstra_mesh_planner.cpp:159
ROS_INFO_STREAM
#define ROS_INFO_STREAM(args)
dijkstra_mesh_planner
Definition: dijkstra_mesh_planner.h:47
ros::WallTime
lvr2::Meap::isEmpty
bool isEmpty() const
dijkstra_mesh_planner::DijkstraMeshPlanner::cancel_planning
std::atomic_bool cancel_planning
Definition: dijkstra_mesh_planner.h:170
start
ROSCPP_DECL void start()
lvr2::VectorMap::clear
void clear() final
dijkstra_mesh_planner::DijkstraMeshPlanner::reconfigure_server_ptr
boost::shared_ptr< dynamic_reconfigure::Server< dijkstra_mesh_planner::DijkstraMeshPlannerConfig > > reconfigure_server_ptr
Definition: dijkstra_mesh_planner.h:183
dijkstra_mesh_planner::DijkstraMeshPlanner::first_config
bool first_config
Definition: dijkstra_mesh_planner.h:185
dijkstra_mesh_planner::DijkstraMeshPlanner::goal_dist_offset
float goal_dist_offset
Definition: dijkstra_mesh_planner.h:180
lvr2::Meap::popMin
MeapPair< KeyT, ValueT > popMin()
lvr2::VectorMap::insert
boost::optional< ValueT > insert(HandleT key, const ValueT &value) final
dijkstra_mesh_planner::DijkstraMeshPlanner::potential
lvr2::DenseVertexMap< float > potential
Definition: dijkstra_mesh_planner.h:196
ros::NodeHandle::param
T param(const std::string &param_name, const T &default_val) const
dijkstra_mesh_planner::DijkstraMeshPlanner::initialize
virtual bool initialize(const std::string &name, const boost::shared_ptr< mesh_map::MeshMap > &mesh_map_ptr)
initializes this planner with the given plugin name and map
Definition: dijkstra_mesh_planner.cpp:129
mesh_map::toVector
Vector toVector(const geometry_msgs::Point &point)
dijkstra_mesh_planner::DijkstraMeshPlanner::path_pub
ros::Publisher path_pub
Definition: dijkstra_mesh_planner.h:172
mesh_map::calculatePoseFromPosition
geometry_msgs::Pose calculatePoseFromPosition(const Vector &current, const Vector &next, const Normal &normal)
header
const std::string header
dijkstra_mesh_planner::DijkstraMeshPlanner::config
DijkstraMeshPlannerConfig config
Definition: dijkstra_mesh_planner.h:186
ROS_INFO
#define ROS_INFO(...)
dijkstra_mesh_planner::DijkstraMeshPlanner::config_callback
dynamic_reconfigure::Server< dijkstra_mesh_planner::DijkstraMeshPlannerConfig >::CallbackType config_callback
Definition: dijkstra_mesh_planner.h:184
mesh
HalfEdgeMesh< Vec > mesh
dijkstra_mesh_planner::DijkstraMeshPlanner::private_nh
ros::NodeHandle private_nh
Definition: dijkstra_mesh_planner.h:168
util.h
dijkstra_mesh_planner::DijkstraMeshPlanner::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)
Given a goal pose in the world, compute a plan.
Definition: dijkstra_mesh_planner.cpp:56
PLUGINLIB_EXPORT_CLASS
PLUGINLIB_EXPORT_CLASS(dijkstra_mesh_planner::DijkstraMeshPlanner, mbf_mesh_core::MeshPlanner)
ros::NodeHandle
ros::Time::now
static Time now()


dijkstra_mesh_planner
Author(s): Sebastian Pütz
autogenerated on Thu Jan 25 2024 03:42:54