00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "descartes_planner/planning_graph.h"
00026
00027 #include <stdio.h>
00028 #include <iomanip>
00029 #include <iostream>
00030 #include <utility>
00031 #include <algorithm>
00032 #include <fstream>
00033
00034 #include <ros/console.h>
00035
00036 #include <boost/graph/dijkstra_shortest_paths.hpp>
00037
00038 using namespace descartes_core;
00039 using namespace descartes_trajectory;
00040 namespace descartes_planner
00041 {
00042 PlanningGraph::PlanningGraph(RobotModelConstPtr model)
00043 : robot_model_(std::move(model)), cartesian_point_link_(NULL), custom_cost_function_(NULL)
00044 {
00045 }
00046
00047 PlanningGraph::PlanningGraph(RobotModelConstPtr model, CostFunction cost_function_callback)
00048 : robot_model_(std::move(model)), cartesian_point_link_(NULL), custom_cost_function_(cost_function_callback)
00049 {
00050 }
00051
00052 PlanningGraph::~PlanningGraph()
00053 {
00054 clear();
00055 }
00056
00057 void PlanningGraph::clear()
00058 {
00059 delete cartesian_point_link_;
00060 dg_.clear();
00061 joint_solutions_map_.clear();
00062 }
00063
00064 CartesianMap PlanningGraph::getCartesianMap() const
00065 {
00066 if (!cartesian_point_link_)
00067 {
00068 return CartesianMap();
00069 }
00070 else
00071 return *cartesian_point_link_;
00072 }
00073
00074 const JointMap& PlanningGraph::getJointMap() const
00075 {
00076 return joint_solutions_map_;
00077 }
00078
00079 const JointGraph& PlanningGraph::getGraph() const
00080 {
00081 return dg_;
00082 }
00083
00084 descartes_core::RobotModelConstPtr PlanningGraph::getRobotModel()
00085 {
00086 return robot_model_;
00087 }
00088
00089 bool PlanningGraph::insertGraph(const std::vector<TrajectoryPtPtr>* points)
00090 {
00091
00092 if (!points)
00093 {
00094
00095 ROS_ERROR_STREAM("points == null. Cannot initialize graph with null list.");
00096 return false;
00097 }
00098 if (points->size() < 2)
00099 {
00100 ROS_ERROR_STREAM(__FUNCTION__ << ": must provide at least 2 input trajectory points.");
00101 return false;
00102 }
00103
00104
00105 clear();
00106
00107
00108 cartesian_point_link_ = new std::map<TrajectoryPt::ID, CartesianPointInformation>();
00109
00110
00111
00112 TrajectoryPt::ID previous_id = descartes_core::TrajectoryID::make_nil();
00113
00114
00115 for (auto point_iter = points->begin(); point_iter != points->end(); ++point_iter)
00116 {
00117 (*cartesian_point_link_)[point_iter->get()->getID()].source_trajectory_ = (*point_iter);
00118 CartesianPointRelationship point_link = CartesianPointRelationship();
00119 point_link.id = point_iter->get()->getID();
00120 point_link.id_next = descartes_core::TrajectoryID::make_nil();
00121 point_link.id_previous = descartes_core::TrajectoryID::make_nil();
00122
00123
00124 if (cartesian_point_link_->find(previous_id) != cartesian_point_link_->end())
00125 {
00126 (*cartesian_point_link_)[previous_id].links_.id_next = point_link.id;
00127
00128 ROS_DEBUG_STREAM("PreviousID[" << previous_id << "].links_.id_next = " << point_link.id);
00129 }
00130
00131
00132 point_link.id_previous = previous_id;
00133
00134
00135 previous_id = point_link.id;
00136
00137
00138 (*cartesian_point_link_)[point_link.id].links_ = point_link;
00139 }
00140
00141
00142
00143 std::vector<std::vector<JointTrajectoryPt>> poses;
00144 if (!calculateJointSolutions(*points, poses))
00145 {
00146 ROS_ERROR_STREAM("unable to calculate joint trajectories for input points");
00147 return false;
00148 }
00149
00150 std::vector<JointEdge> edges;
00151 if (!calculateAllEdgeWeights(poses, edges))
00152 {
00153 ROS_ERROR_STREAM("unable to calculate edge weight of joint transitions for joint trajectories");
00154 return false;
00155 }
00156
00157 if (!populateGraphVertices(*points, poses))
00158 {
00159 ROS_ERROR_STREAM("unable to populate graph from input points");
00160 return false;
00161 }
00162
00163
00164 if (!populateGraphEdges(edges))
00165 {
00166 ROS_ERROR_STREAM("unable to populate graph from calculated edges");
00167 return false;
00168 }
00169
00170 return true;
00171 }
00172
00173 bool PlanningGraph::addTrajectory(TrajectoryPtPtr point, TrajectoryPt::ID previous_id, TrajectoryPt::ID next_id)
00174 {
00175 if (previous_id.is_nil() && next_id.is_nil())
00176 {
00177
00178 ROS_ERROR_STREAM("unable to add a point that is not connected to one or more existing points");
00179 return false;
00180 }
00181
00182 if (!previous_id.is_nil() && cartesian_point_link_->find(previous_id) == cartesian_point_link_->end())
00183 {
00184
00185 ROS_ERROR_STREAM("unable to find previous point");
00186 return false;
00187 }
00188 if (!next_id.is_nil() && cartesian_point_link_->find(next_id) == cartesian_point_link_->end())
00189 {
00190
00191 ROS_ERROR_STREAM("unable to find next point");
00192 }
00193
00194 CartesianPointRelationship point_link;
00195 point_link.id = point->getID();
00196 point_link.id_next = next_id;
00197 point_link.id_previous = previous_id;
00198
00199
00200 (*cartesian_point_link_)[point_link.id].links_ = point_link;
00201
00202
00203
00204 if (!previous_id.is_nil())
00205 {
00206 (*cartesian_point_link_)[previous_id].links_.id_next = point_link.id;
00207 }
00208
00209
00210 if (!next_id.is_nil())
00211 {
00212 (*cartesian_point_link_)[next_id].links_.id_previous = point_link.id;
00213 }
00214
00215 ROS_DEBUG_STREAM("New ID: " << point_link.id);
00216 ROS_DEBUG_STREAM("New Next ID: " << point_link.id_next);
00217 ROS_DEBUG_STREAM("New Previous ID: " << point_link.id_previous);
00218
00219 VertexMap joint_vertex_map;
00220 recalculateJointSolutionsVertexMap(joint_vertex_map);
00221
00222 if (!previous_id.is_nil() && !next_id.is_nil())
00223 {
00224
00225 std::vector<TrajectoryPt::ID> start_joint_ids = (*cartesian_point_link_)[previous_id].joints_;
00226 std::vector<TrajectoryPt::ID> end_joint_ids = (*cartesian_point_link_)[next_id].joints_;
00227 for (std::vector<TrajectoryPt::ID>::iterator start_joint_iter = start_joint_ids.begin();
00228 start_joint_iter != start_joint_ids.end(); start_joint_iter++)
00229 {
00230 for (std::vector<TrajectoryPt::ID>::iterator end_joint_iter = end_joint_ids.begin();
00231 end_joint_iter != end_joint_ids.end(); end_joint_iter++)
00232 {
00233 ROS_DEBUG_STREAM("Removing edge: " << *start_joint_iter << " -> " << *end_joint_iter);
00234 boost::remove_edge(joint_vertex_map[*start_joint_iter], joint_vertex_map[*end_joint_iter], dg_);
00235 }
00236 }
00237 }
00238
00239
00240 std::vector<std::vector<double>> joint_poses;
00241 point.get()->getJointPoses(*robot_model_, joint_poses);
00242
00243 if (joint_poses.size() == 0)
00244 {
00245 ROS_WARN_STREAM("no joint solution for this point... potential discontinuity in the graph");
00246 }
00247 else
00248 {
00249 for (std::vector<std::vector<double>>::iterator joint_pose_iter = joint_poses.begin();
00250 joint_pose_iter != joint_poses.end(); joint_pose_iter++)
00251 {
00252
00253 JointTrajectoryPt new_pt(*joint_pose_iter, point->getTiming());
00254
00255 (*cartesian_point_link_)[point->getID()].joints_.push_back(new_pt.getID());
00256
00257
00258 JointGraph::vertex_descriptor v = boost::add_vertex(dg_);
00259 dg_[v].id = new_pt.getID();
00260
00261 joint_solutions_map_[new_pt.getID()] = new_pt;
00262 }
00263 }
00264
00265
00266 std::vector<TrajectoryPt::ID> traj_solutions = (*cartesian_point_link_)[point->getID()].joints_;
00267
00268 (*cartesian_point_link_)[point->getID()].source_trajectory_ = point;
00269
00270 ROS_INFO_STREAM("SAVE CART POINT ID[" << point->getID() << "]: "
00271 << (*cartesian_point_link_)[point->getID()].source_trajectory_.get()->getID());
00272
00273 std::vector<JointEdge> edges;
00274
00275
00276 if (!previous_id.is_nil())
00277 {
00278 std::vector<TrajectoryPt::ID> previous_joint_ids = (*cartesian_point_link_)[previous_id].joints_;
00279 calculateEdgeWeights(previous_joint_ids, traj_solutions, edges);
00280 }
00281
00282 if (!next_id.is_nil())
00283 {
00284 std::vector<TrajectoryPt::ID> next_joint_ids = (*cartesian_point_link_)[next_id].joints_;
00285 calculateEdgeWeights(traj_solutions, next_joint_ids, edges);
00286 }
00287
00288
00289 populateGraphEdges(edges);
00290
00291
00292
00293
00294
00295
00296
00297
00298 return (cartesian_point_link_->find(point->getID()) != cartesian_point_link_->end());
00299 }
00300
00301 bool PlanningGraph::modifyTrajectory(TrajectoryPtPtr point)
00302 {
00303 TrajectoryPt::ID modify_id = point.get()->getID();
00304 ROS_INFO_STREAM("Attempting to modify point:: " << modify_id);
00305
00306
00307
00308 if (modify_id.is_nil())
00309 {
00310
00311 ROS_ERROR_STREAM("unable to modify a point with nil ID");
00312 return false;
00313 }
00314
00315 if (cartesian_point_link_->find(modify_id) == cartesian_point_link_->end())
00316 {
00317
00318 ROS_ERROR_STREAM("unable to find cartesian point link with ID: " << modify_id);
00319 return false;
00320 }
00321 else
00322 {
00323 ROS_INFO_STREAM("Found ID: " << modify_id << " to modify.");
00324 }
00325
00326 std::map<TrajectoryPt::ID, JointGraph::vertex_descriptor> joint_vertex_map;
00327 int num_joints = recalculateJointSolutionsVertexMap(joint_vertex_map);
00328
00329
00330 std::vector<TrajectoryPt::ID> start_joint_ids = (*cartesian_point_link_)[modify_id].joints_;
00331
00332 ROS_INFO_STREAM("start_joint_ids.size = " << start_joint_ids.size());
00333
00334 std::vector<JointGraph::edge_descriptor> to_remove_edges;
00335 std::vector<JointGraph::vertex_descriptor> to_remove_vertices;
00336
00337 for (std::vector<TrajectoryPt::ID>::iterator start_joint_iter = start_joint_ids.begin();
00338 start_joint_iter != start_joint_ids.end(); start_joint_iter++)
00339 {
00340
00341 JointGraph::vertex_descriptor jv = joint_vertex_map[*start_joint_iter];
00342
00343
00344 ROS_DEBUG_STREAM("jv: " << jv);
00345
00346
00347
00348 std::pair<OutEdgeIterator, OutEdgeIterator> out_ei = out_edges(jv, dg_);
00349
00350 for (OutEdgeIterator out_edge = out_ei.first; out_edge != out_ei.second; ++out_edge)
00351 {
00352 JointGraph::edge_descriptor e = *out_edge;
00353 ROS_DEBUG_STREAM("REMOVE OUTEDGE: " << dg_[e].joint_start << " -> " << dg_[e].joint_end);
00354 to_remove_edges.push_back(e);
00355 }
00356
00357
00358 std::pair<InEdgeIterator, InEdgeIterator> in_ei = in_edges(jv, dg_);
00359 for (InEdgeIterator in_edge = in_ei.first; in_edge != in_ei.second; ++in_edge)
00360 {
00361 JointGraph::edge_descriptor e = *in_edge;
00362 ROS_DEBUG_STREAM("REMOVE INEDGE: " << dg_[e].joint_start << " -> " << dg_[e].joint_end);
00363 to_remove_edges.push_back(e);
00364 }
00365
00366 to_remove_vertices.push_back(jv);
00367 joint_solutions_map_.erase(*start_joint_iter);
00368
00369 }
00370 for (std::vector<JointGraph::edge_descriptor>::iterator e_iter = to_remove_edges.begin();
00371 e_iter != to_remove_edges.end(); e_iter++)
00372 {
00373 ROS_DEBUG_STREAM("REMOVE EDGE: " << dg_[*e_iter].joint_start << " -> " << dg_[*e_iter].joint_end);
00374 boost:
00375 remove_edge(*e_iter, dg_);
00376
00377 }
00378 std::sort(to_remove_vertices.begin(), to_remove_vertices.end());
00379 std::reverse(to_remove_vertices.begin(), to_remove_vertices.end());
00380 for (std::vector<JointGraph::vertex_descriptor>::iterator v_iter = to_remove_vertices.begin();
00381 v_iter != to_remove_vertices.end(); v_iter++)
00382 {
00383
00384
00385 ROS_DEBUG_STREAM("REMOVE VERTEX: " << *v_iter);
00386 boost::remove_vertex(*v_iter, dg_);
00387
00388 }
00389 (*cartesian_point_link_)[modify_id].joints_.clear();
00390
00391
00392 std::vector<std::vector<double>> joint_poses;
00393 point.get()->getJointPoses(*robot_model_, joint_poses);
00394
00395 if (joint_poses.size() == 0)
00396 {
00397 ROS_WARN_STREAM("no joint solution for this point... potential discontinuity in the graph");
00398 }
00399 else
00400 {
00401 for (std::vector<std::vector<double>>::iterator joint_pose_iter = joint_poses.begin();
00402 joint_pose_iter != joint_poses.end(); joint_pose_iter++)
00403 {
00404
00405 JointTrajectoryPt new_pt(*joint_pose_iter, point->getTiming());
00406 (*cartesian_point_link_)[modify_id].joints_.push_back(new_pt.getID());
00407
00408
00409 JointGraph::vertex_descriptor v = boost::add_vertex(dg_);
00410 dg_[v].id = new_pt.getID();
00411
00412 joint_solutions_map_[new_pt.getID()] = new_pt;
00413 ROS_INFO_STREAM("Added New Joint: " << v);
00414 }
00415 }
00416
00417 std::vector<TrajectoryPt::ID> traj_solutions = (*cartesian_point_link_)[modify_id].joints_;
00418 (*cartesian_point_link_)[modify_id].source_trajectory_ = point;
00419
00420
00421
00422 TrajectoryPt::ID previous_cart_id =
00423 (*cartesian_point_link_)[modify_id].links_.id_previous;
00424 TrajectoryPt::ID next_cart_id = (*cartesian_point_link_)[modify_id].links_.id_next;
00425
00426 std::vector<JointEdge> edges;
00427
00428
00429 if (!previous_cart_id.is_nil())
00430 {
00431 std::vector<TrajectoryPt::ID> previous_joint_ids = (*cartesian_point_link_)[previous_cart_id].joints_;
00432 ROS_DEBUG_STREAM("Calculating previous -> new weights: " << previous_joint_ids.size() << " -> "
00433 << traj_solutions.size());
00434 calculateEdgeWeights(previous_joint_ids, traj_solutions, edges);
00435 }
00436
00437 if (!next_cart_id.is_nil())
00438 {
00439 std::vector<TrajectoryPt::ID> next_joint_ids = (*cartesian_point_link_)[next_cart_id].joints_;
00440 ROS_DEBUG_STREAM("Calculating new -> next weights: " << traj_solutions.size() << " -> " << next_joint_ids.size());
00441 calculateEdgeWeights(traj_solutions, next_joint_ids, edges);
00442 }
00443
00444 ROS_INFO_STREAM("NEW EDGES: " << edges.size());
00445
00446 return populateGraphEdges(edges);
00447
00448
00449
00450
00451 }
00452
00453 bool PlanningGraph::removeTrajectory(TrajectoryPtPtr point)
00454 {
00455 TrajectoryPt::ID delete_id = point.get()->getID();
00456 ROS_INFO_STREAM("Attempting to delete ID: " << delete_id);
00457
00458 if (delete_id.is_nil())
00459 {
00460
00461 ROS_ERROR_STREAM("unable to delete a point with nil ID");
00462 return false;
00463 }
00464 if (cartesian_point_link_->find(delete_id) == cartesian_point_link_->end())
00465 {
00466
00467 ROS_ERROR_STREAM("unable to find cartesian point link with ID: " << delete_id);
00468 return false;
00469 }
00470
00471 std::vector<TrajectoryPt::ID> start_joint_ids = (*cartesian_point_link_)[delete_id].joints_;
00472
00473 ROS_INFO_STREAM("Attempting to delete edges from " << start_joint_ids.size() << " vertices");
00474
00475 std::map<TrajectoryPt::ID, JointGraph::vertex_descriptor> joint_vertex_map;
00476 int num_joints = recalculateJointSolutionsVertexMap(joint_vertex_map);
00477
00478 std::vector<JointGraph::edge_descriptor> to_remove_edges;
00479 std::vector<JointGraph::vertex_descriptor> to_remove_vertices;
00480
00481 for (std::vector<TrajectoryPt::ID>::iterator start_joint_iter = start_joint_ids.begin();
00482 start_joint_iter != start_joint_ids.end(); start_joint_iter++)
00483 {
00484
00485 JointGraph::vertex_descriptor jv = joint_vertex_map[*start_joint_iter];
00486
00487
00488 std::pair<OutEdgeIterator, OutEdgeIterator> out_ei = out_edges(jv, dg_);
00489
00490 for (OutEdgeIterator out_edge = out_ei.first; out_edge != out_ei.second; ++out_edge)
00491 {
00492 JointGraph::edge_descriptor e = *out_edge;
00493 ROS_DEBUG_STREAM("REMOVE OUTEDGE: " << dg_[e].joint_start << " -> " << dg_[e].joint_end);
00494 to_remove_edges.push_back(e);
00495 }
00496
00497
00498 std::pair<InEdgeIterator, InEdgeIterator> in_ei = in_edges(jv, dg_);
00499 for (InEdgeIterator in_edge = in_ei.first; in_edge != in_ei.second; ++in_edge)
00500 {
00501 JointGraph::edge_descriptor e = *in_edge;
00502 ROS_DEBUG_STREAM("REMOVE INEDGE: " << dg_[e].joint_start << " -> " << dg_[e].joint_end);
00503 to_remove_edges.push_back(e);
00504 }
00505 to_remove_vertices.push_back(jv);
00506
00507
00508 joint_solutions_map_.erase(*start_joint_iter);
00509 }
00510
00511 for (std::vector<JointGraph::edge_descriptor>::iterator e_iter = to_remove_edges.begin();
00512 e_iter != to_remove_edges.end(); e_iter++)
00513 {
00514 boost:
00515 remove_edge(*e_iter, dg_);
00516 }
00517
00518 std::sort(to_remove_vertices.begin(), to_remove_vertices.end());
00519 std::reverse(to_remove_vertices.begin(), to_remove_vertices.end());
00520 for (std::vector<JointGraph::vertex_descriptor>::iterator v_iter = to_remove_vertices.begin();
00521 v_iter != to_remove_vertices.end(); v_iter++)
00522 {
00523
00524
00525 ROS_INFO_STREAM("REMOVE VERTEX: " << *v_iter);
00526 boost::remove_vertex(*v_iter, dg_);
00527
00528 }
00529 (*cartesian_point_link_)[delete_id].joints_.clear();
00530
00531
00532 CartesianPointRelationship links = (*cartesian_point_link_)[delete_id].links_;
00533 TrajectoryPt::ID previous_id = links.id_previous;
00534 TrajectoryPt::ID next_id = links.id_next;
00535
00536 if (!previous_id.is_nil())
00537 {
00538
00539 (*cartesian_point_link_)[previous_id].links_.id_next = next_id;
00540 }
00541 if (!next_id.is_nil())
00542 {
00543
00544 (*cartesian_point_link_)[next_id].links_.id_previous = previous_id;
00545 }
00546
00547 std::vector<JointEdge> edges;
00548
00549
00550 if (!previous_id.is_nil() && !next_id.is_nil())
00551 {
00552 std::vector<TrajectoryPt::ID> previous_joint_ids = (*cartesian_point_link_)[previous_id].joints_;
00553 std::vector<TrajectoryPt::ID> next_joint_ids = (*cartesian_point_link_)[next_id].joints_;
00554 calculateEdgeWeights(previous_joint_ids, next_joint_ids, edges);
00555 }
00556
00557
00558 populateGraphEdges(edges);
00559
00560
00561
00562
00563
00564 return true;
00565 }
00566
00567 bool PlanningGraph::findStartVertices(std::vector<JointGraph::vertex_descriptor>& start_points) const
00568 {
00569
00570 VertexMap joint_vertex_map;
00571 recalculateJointSolutionsVertexMap(joint_vertex_map);
00572
00573
00574 TrajectoryPt::ID cart_id = descartes_core::TrajectoryID::make_nil();
00575
00576 for (auto c_iter = cartesian_point_link_->begin(); c_iter != cartesian_point_link_->end(); ++c_iter)
00577 {
00578 if (c_iter->second.links_.id_previous.is_nil())
00579 {
00580 cart_id = c_iter->first;
00581 break;
00582 }
00583 }
00584
00585
00586 if (cart_id.is_nil())
00587 {
00588
00589
00590 ROS_ERROR("Could not locate TrajectoryPt with nil previous point. Graph may be cyclic.");
00591 return false;
00592 }
00593
00594
00595 const std::vector<descartes_core::TrajectoryPt::ID>& ids = cartesian_point_link_->at(cart_id).joints_;
00596
00597 for (const auto& id : ids)
00598 {
00599 JointGraph::vertex_descriptor v = joint_vertex_map.at(id);
00600 start_points.push_back(v);
00601 }
00602
00603 return !start_points.empty();
00604 }
00605
00606 bool PlanningGraph::findEndVertices(std::vector<JointGraph::vertex_descriptor>& end_points) const
00607 {
00608
00609 VertexMap joint_vertex_map;
00610 recalculateJointSolutionsVertexMap(joint_vertex_map);
00611
00612
00613 TrajectoryPt::ID cart_id = descartes_core::TrajectoryID::make_nil();
00614
00615 for (auto c_iter = cartesian_point_link_->begin(); c_iter != cartesian_point_link_->end(); ++c_iter)
00616 {
00617 if (c_iter->second.links_.id_next.is_nil())
00618 {
00619 cart_id = c_iter->first;
00620 break;
00621 }
00622 }
00623
00624
00625 if (cart_id.is_nil())
00626 {
00627
00628
00629 ROS_ERROR("Could not locate TrajectoryPt with nil next point. Graph may be cyclic.");
00630 return false;
00631 }
00632
00633
00634 const std::vector<descartes_core::TrajectoryPt::ID>& ids = cartesian_point_link_->at(cart_id).joints_;
00635
00636 for (const auto& id : ids)
00637 {
00638 JointGraph::vertex_descriptor v = joint_vertex_map.at(id);
00639 end_points.push_back(v);
00640 }
00641
00642 return !end_points.empty();
00643 }
00644
00645 bool PlanningGraph::getShortestPath(double& cost, std::list<JointTrajectoryPt>& path)
00646 {
00647
00648 std::vector<JointGraph::vertex_descriptor> start_points;
00649 findStartVertices(start_points);
00650 std::vector<JointGraph::vertex_descriptor> end_points;
00651 findEndVertices(end_points);
00652
00653
00654
00655 JointGraph::vertex_descriptor virtual_vertex = boost::add_vertex(dg_);
00656 for (const auto& pt : start_points)
00657 {
00658 auto e = boost::add_edge(virtual_vertex, pt, dg_);
00659 dg_[e.first].transition_cost = 0.0;
00660 }
00661
00662
00663 size_t num_vert = boost::num_vertices(dg_);
00664 std::vector<TrajectoryPt::ID> vertex_index_map(num_vert);
00665 std::pair<VertexIterator, VertexIterator> vi = boost::vertices(dg_);
00666 int i = 0;
00667 for (VertexIterator vert_iter = vi.first; vert_iter != vi.second; ++vert_iter)
00668 {
00669 JointGraph::vertex_descriptor jv = *vert_iter;
00670 vertex_index_map[i++] = dg_[jv].id;
00671 }
00672
00673
00674
00675 cost = std::numeric_limits<double>::max();
00676
00677
00678 JointGraph::vertex_descriptor cheapest_end_point;
00679
00680
00681 std::vector<JointGraph::vertex_descriptor> predecessors(num_vert);
00682 std::vector<double> weights(num_vert, std::numeric_limits<double>::max());
00683
00684 dijkstra_shortest_paths(
00685 dg_,
00686 virtual_vertex,
00687 weight_map(get(&JointEdge::transition_cost, dg_))
00688 .distance_map(boost::make_iterator_property_map(weights.begin(), get(boost::vertex_index, dg_)))
00689 .predecessor_map(&predecessors[0]));
00690
00691
00692 for (auto end = end_points.begin(); end != end_points.end(); ++end)
00693 {
00694 double weight = weights[*end];
00695
00696 if (weight < cost)
00697 {
00698 cost = weight;
00699 cheapest_end_point = *end;
00700 }
00701 }
00702
00703
00704 path.clear();
00705 auto current = cheapest_end_point;
00706
00707 while (current != virtual_vertex)
00708 {
00709 path.push_front(joint_solutions_map_[vertex_index_map[current]]);
00710 current = predecessors[current];
00711 }
00712
00713
00714 boost::clear_vertex(virtual_vertex, dg_);
00715 boost::remove_vertex(virtual_vertex, dg_);
00716
00717 if (cost < std::numeric_limits<double>::max())
00718 {
00719 ROS_INFO_STREAM("Descartes found path with total cost: " << cost);
00720 return true;
00721 }
00722 else
00723 {
00724 ROS_ERROR_STREAM("Descartes unable to find path");
00725 return false;
00726 }
00727 }
00728
00729 void PlanningGraph::printMaps()
00730 {
00731 ROS_DEBUG_STREAM("Number of points: " << cartesian_point_link_->size());
00732
00733 for (std::map<TrajectoryPt::ID, CartesianPointInformation>::iterator c_iter = cartesian_point_link_->begin();
00734 c_iter != cartesian_point_link_->end(); c_iter++)
00735 {
00736 ROS_DEBUG_STREAM("C_ID: " << c_iter->first << "[P_ID: " << c_iter->second.links_.id_previous << " -> N_ID: "
00737 << c_iter->second.links_.id_next << "](Joints: " << c_iter->second.joints_.size() << ')');
00738 }
00739 }
00740
00741 int PlanningGraph::recalculateJointSolutionsVertexMap(VertexMap& joint_map) const
00742 {
00743 std::pair<VertexIterator, VertexIterator> vi = vertices(dg_);
00744
00745 for (VertexIterator vert_iter = vi.first; vert_iter != vi.second; ++vert_iter)
00746 {
00747 JointGraph::vertex_descriptor jv = *vert_iter;
00748 joint_map[dg_[jv].id] = jv;
00749 }
00750 }
00751
00752
00753 void PlanningGraph::printGraph()
00754 {
00755 ROS_DEBUG_STREAM("\n\nPRINTING GRAPH\n\n");
00756 std::stringstream ss;
00757 ss << "GRAPH VERTICES (" << num_vertices(dg_) << "): ";
00758 ROS_DEBUG_STREAM(ss.str());
00759 std::pair<VertexIterator, VertexIterator> vi = vertices(dg_);
00760 ROS_DEBUG_STREAM("Graph OutEdges:");
00761 for (VertexIterator vert_iter = vi.first; vert_iter != vi.second; ++vert_iter)
00762 {
00763 JointGraph::vertex_descriptor jv = *vert_iter;
00764 ss.str("");
00765 ss << "Vertex: (" << jv << ")";
00766 ss << dg_[jv].id;
00767 std::pair<OutEdgeIterator, OutEdgeIterator> out_ei = out_edges(jv, dg_);
00768 ss << " -> {";
00769 for (OutEdgeIterator out_edge = out_ei.first; out_edge != out_ei.second; ++out_edge)
00770 {
00771 JointGraph::edge_descriptor e = *out_edge;
00772 ss << "[" << dg_[e].joint_end << "] , ";
00773 }
00774 ss << "}";
00775 ROS_DEBUG_STREAM(ss.str());
00776 }
00777
00778 ROS_DEBUG_STREAM("Graph InEdges:");
00779 for (VertexIterator vert_iter = vi.first; vert_iter != vi.second; ++vert_iter)
00780 {
00781 JointGraph::vertex_descriptor jv = *vert_iter;
00782
00783 std::pair<InEdgeIterator, InEdgeIterator> in_ei = in_edges(jv, dg_);
00784 ss.str("");
00785 ss << "{";
00786 for (InEdgeIterator in_edge = in_ei.first; in_edge != in_ei.second; ++in_edge)
00787 {
00788 JointGraph::edge_descriptor e = *in_edge;
00789 ss << source(e, dg_) << "[" << dg_[e].joint_start << "], ";
00790 }
00791 ss << "} -> ";
00792 ss << "Vertex (" << jv << "): ";
00793 ROS_DEBUG_STREAM(ss.str());
00794 }
00795
00796 ROS_DEBUG_STREAM("GRAPH EDGES (" << num_edges(dg_) << "): ");
00797
00798
00799 std::pair<EdgeIterator, EdgeIterator> ei = edges(dg_);
00800 for (EdgeIterator edge_iter = ei.first; edge_iter != ei.second; ++edge_iter)
00801 {
00802 JointGraph::vertex_descriptor jv = source(*edge_iter, dg_);
00803 JointGraph::edge_descriptor e = *out_edges(jv, dg_).first;
00804
00805 JointGraph::edge_descriptor e2 = *edge_iter;
00806 ROS_DEBUG_STREAM("(" << source(*edge_iter, dg_) << ", " << target(*edge_iter, dg_)
00807 << "): cost: " << dg_[e2].transition_cost);
00808 }
00809 ROS_DEBUG_STREAM("\n\nEND PRINTING GRAPH\n\n");
00810 }
00811
00812 bool PlanningGraph::calculateJointSolutions(const std::vector<TrajectoryPtPtr>& points,
00813 std::vector<std::vector<JointTrajectoryPt>>& poses)
00814 {
00815 poses.resize(points.size());
00816
00817 for (std::size_t i = 0; i < points.size(); ++i)
00818 {
00819 std::vector<std::vector<double>> joint_poses;
00820 points[i]->getJointPoses(*robot_model_, joint_poses);
00821
00822 if (joint_poses.empty())
00823 {
00824 ROS_ERROR_STREAM(__FUNCTION__ << ": IK failed for input trajectory point with ID = " << points[i]->getID());
00825 return false;
00826 }
00827
00828 poses[i].reserve(joint_poses.size());
00829 for (auto& sol : joint_poses)
00830 {
00831 poses[i].emplace_back(std::move(sol), points[i]->getTiming());
00832 }
00833 }
00834
00835 return true;
00836 }
00837
00838 bool PlanningGraph::calculateAllEdgeWeights(const std::vector<std::vector<JointTrajectoryPt>>& poses,
00839 std::vector<JointEdge>& edges)
00840 {
00841
00842
00843 for (std::size_t i = 1; i < poses.size(); ++i)
00844 {
00845 const std::vector<JointTrajectoryPt>& from = poses[i - 1];
00846 const std::vector<JointTrajectoryPt>& to = poses[i];
00847
00848 if (!calculateEdgeWeights(from, to, edges))
00849 {
00850 ROS_ERROR_STREAM(__FUNCTION__ << ": unable to calculate any valid transitions between inputs " << (i - 1)
00851 << " and " << i);
00852 return false;
00853 }
00854 }
00855
00856 return !edges.empty();
00857 }
00858
00859 bool PlanningGraph::calculateEdgeWeights(const std::vector<TrajectoryPt::ID>& start_joints,
00860 const std::vector<TrajectoryPt::ID>& end_joints,
00861 std::vector<JointEdge>& edge_results)
00862 {
00863 if (start_joints.empty() || end_joints.empty())
00864 {
00865 ROS_WARN_STREAM("One or more joints lists is empty, Start Joints: " << start_joints.size()
00866 << " End Joints: " << end_joints.size());
00867 return false;
00868 }
00869
00870 bool has_valid_transition = false;
00871
00872
00873 for (auto previous_joint_iter = start_joints.begin(); previous_joint_iter != start_joints.end();
00874 ++previous_joint_iter)
00875 {
00876
00877 const JointTrajectoryPt& start_joint = joint_solutions_map_[*previous_joint_iter];
00878
00879
00880 for (auto next_joint_iter = end_joints.begin(); next_joint_iter != end_joints.end(); ++next_joint_iter)
00881 {
00882 const JointTrajectoryPt& end_joint = joint_solutions_map_[*next_joint_iter];
00883
00884 EdgeWeightResult edge_result = edgeWeight(start_joint, end_joint);
00885
00886
00887 if (!edge_result.first)
00888 {
00889 continue;
00890 }
00891
00892
00893
00894 has_valid_transition = true;
00895
00896 JointEdge edge;
00897 edge.joint_start = *previous_joint_iter;
00898 edge.joint_end = *next_joint_iter;
00899 edge.transition_cost = edge_result.second;
00900 edge_results.push_back(edge);
00901 }
00902 }
00903
00904 return has_valid_transition;
00905 }
00906
00907 bool PlanningGraph::calculateEdgeWeights(const std::vector<JointTrajectoryPt>& start_joints,
00908 const std::vector<JointTrajectoryPt>& end_joints,
00909 std::vector<JointEdge>& edge_results) const
00910 {
00911 if (start_joints.empty() || end_joints.empty())
00912 {
00913 ROS_WARN_STREAM("One or more joints lists is empty, Start Joints: " << start_joints.size()
00914 << " End Joints: " << end_joints.size());
00915 return false;
00916 }
00917
00918 auto start_size = edge_results.size();
00919
00920
00921 for (const auto& start_joint : start_joints)
00922 {
00923
00924 for (const auto& end_joint : end_joints)
00925 {
00926
00927 EdgeWeightResult edge_result = edgeWeight(start_joint, end_joint);
00928
00929
00930 if (!edge_result.first)
00931 continue;
00932
00933 JointEdge edge;
00934 edge.joint_start = start_joint.getID();
00935 edge.joint_end = end_joint.getID();
00936 edge.transition_cost = edge_result.second;
00937 edge_results.push_back(edge);
00938 }
00939 }
00940
00941 return edge_results.size() > start_size;
00942 }
00943
00944 bool PlanningGraph::populateGraphVertices(const std::vector<TrajectoryPtPtr>& points,
00945 std::vector<std::vector<JointTrajectoryPt>>& poses)
00946 {
00947 if (points.size() != poses.size())
00948 {
00949 ROS_ERROR_STREAM(__FUNCTION__ << ": user trajectory and joint solutions should have same length");
00950 return false;
00951 }
00952
00953 if (!joint_solutions_map_.empty())
00954 {
00955 ROS_WARN_STREAM(__FUNCTION__ << ": Clearing joint solutions map.");
00956 joint_solutions_map_.clear();
00957 }
00958
00959
00960 for (std::size_t i = 0; i < points.size(); ++i)
00961 {
00962
00963 std::vector<TrajectoryPt::ID> ids;
00964 ids.reserve(poses[i].size());
00965
00966 std::transform(poses[i].begin(), poses[i].end(), std::back_inserter(ids), [](const JointTrajectoryPt& pt)
00967 {
00968 return pt.getID();
00969 });
00970
00971 auto& entry = cartesian_point_link_->at(points[i]->getID());
00972 entry.joints_ = std::move(ids);
00973
00974
00975 for (std::size_t j = 0; j < poses[i].size(); ++j)
00976 {
00977
00978 auto id = poses[i][j].getID();
00979 auto vertex = boost::add_vertex(dg_);
00980 dg_[vertex].id = id;
00981
00982 joint_solutions_map_.emplace(id, std::move(poses[i][j]));
00983 }
00984 }
00985
00986 return true;
00987 }
00988
00989 bool PlanningGraph::populateGraphEdges(const std::vector<JointEdge>& edges)
00990 {
00991 if (edges.size() == 0)
00992 {
00993
00994 ROS_ERROR_STREAM("no graph edges defined");
00995 return false;
00996 }
00997
00998 VertexMap joint_vertex_map;
00999 recalculateJointSolutionsVertexMap(joint_vertex_map);
01000
01001 for (auto edge_iter = edges.begin(); edge_iter != edges.end(); ++edge_iter)
01002 {
01003 JointGraph::edge_descriptor e;
01004 bool b;
01005
01006 boost::tie(e, b) =
01007 boost::add_edge(joint_vertex_map[edge_iter->joint_start], joint_vertex_map[edge_iter->joint_end], dg_);
01008
01009 dg_[e].transition_cost = edge_iter->transition_cost;
01010 dg_[e].joint_start = edge_iter->joint_start;
01011 dg_[e].joint_end = edge_iter->joint_end;
01012 }
01013
01014 return true;
01015 }
01016
01017 PlanningGraph::EdgeWeightResult PlanningGraph::edgeWeight(const JointTrajectoryPt& start,
01018 const JointTrajectoryPt& end) const
01019 {
01020 EdgeWeightResult result;
01021 result.first = false;
01022
01023 const std::vector<double>& start_vector = start.nominal();
01024 const std::vector<double>& end_vector = end.nominal();
01025 if (start_vector.size() == end_vector.size())
01026 {
01027
01028
01029 if (end.getTiming().isSpecified() && !robot_model_->isValidMove(start_vector, end_vector, end.getTiming().upper))
01030 {
01031 return result;
01032 }
01033
01034 if (custom_cost_function_)
01035 {
01036 result.second = custom_cost_function_(start_vector, end_vector);
01037 }
01038 else
01039 {
01040 double vector_diff = 0;
01041 for (unsigned i = 0; i < start_vector.size(); i++)
01042 {
01043 double joint_diff = std::abs(end_vector[i] - start_vector[i]);
01044 vector_diff += joint_diff;
01045 }
01046 result.second = vector_diff;
01047 }
01048
01049 result.first = true;
01050 return result;
01051 }
01052 else
01053 {
01054 ROS_WARN_STREAM("unequal joint pose vector lengths: " << start_vector.size() << " != " << end_vector.size());
01055 }
01056
01057 return result;
01058 }
01059
01060 }