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/sparse_planner.h>
00026 #include <algorithm>
00027
00028 using namespace descartes_core;
00029 using namespace descartes_trajectory;
00030
00031 namespace
00032 {
00033 descartes_core::TimingConstraint cumulativeTimingBetween(
00034 const std::vector<descartes_core::TrajectoryPtPtr>& dense_points, size_t start_index, size_t end_index)
00035 {
00036 descartes_core::TimingConstraint tm(0.0, 0.0);
00037 for (size_t i = start_index + 1; i <= end_index; ++i)
00038 {
00039 const descartes_core::TimingConstraint& pt_tm = dense_points[i]->getTiming();
00040 if (pt_tm.isSpecified())
00041 {
00042
00043 tm.upper += pt_tm.upper;
00044 tm.lower += pt_tm.lower;
00045 }
00046 else
00047 {
00048
00049 tm = descartes_core::TimingConstraint();
00050 break;
00051 }
00052 }
00053 return tm;
00054 }
00055 }
00056
00057 namespace descartes_planner
00058 {
00059 const int INVALID_INDEX = -1;
00060 const double MAX_JOINT_CHANGE = M_PI_4;
00061 const double DEFAULT_SAMPLING = 0.1f;
00062 const std::string SAMPLING_CONFIG = "sampling";
00063
00064 SparsePlanner::SparsePlanner(RobotModelConstPtr model, double sampling)
00065 : sampling_(sampling), error_code_(descartes_core::PlannerError::UNINITIALIZED)
00066 {
00067 error_map_ = { { PlannerError::OK, "OK" },
00068 { PlannerError::EMPTY_PATH, "No path plan has been generated" },
00069 { PlannerError::INVALID_ID, "ID is nil or isn't part of the path" },
00070 { PlannerError::IK_NOT_AVAILABLE, "One or more ik solutions could not be found" },
00071 { PlannerError::UNINITIALIZED, "Planner has not been initialized with a robot model" },
00072 { PlannerError::INCOMPLETE_PATH, "Input trajectory and output path point cound differ" } };
00073
00074 initialize(std::move(model));
00075 config_ = { { SAMPLING_CONFIG, std::to_string(sampling) } };
00076 }
00077
00078 SparsePlanner::SparsePlanner() : sampling_(DEFAULT_SAMPLING), error_code_(descartes_core::PlannerError::UNINITIALIZED)
00079 {
00080 error_map_ = { { PlannerError::OK, "OK" },
00081 { PlannerError::EMPTY_PATH, "No path plan has been generated" },
00082 { PlannerError::INVALID_ID, "ID is nil or isn't part of the path" },
00083 { PlannerError::IK_NOT_AVAILABLE, "One or more ik solutions could not be found" },
00084 { PlannerError::UNINITIALIZED, "Planner has not been initialized with a robot model" },
00085 { PlannerError::INCOMPLETE_PATH, "Input trajectory and output path point cound differ" } };
00086
00087 config_ = { { SAMPLING_CONFIG, std::to_string(DEFAULT_SAMPLING) } };
00088 }
00089
00090 bool SparsePlanner::initialize(RobotModelConstPtr model)
00091 {
00092 planning_graph_ =
00093 boost::shared_ptr<descartes_planner::PlanningGraph>(new descartes_planner::PlanningGraph(std::move(model)));
00094 error_code_ = PlannerError::EMPTY_PATH;
00095 return true;
00096 }
00097
00098 bool SparsePlanner::initialize(RobotModelConstPtr model, descartes_planner::CostFunction cost_function_callback)
00099 {
00100 planning_graph_ = boost::shared_ptr<descartes_planner::PlanningGraph>(
00101 new descartes_planner::PlanningGraph(std::move(model), cost_function_callback));
00102 error_code_ = PlannerError::EMPTY_PATH;
00103 return true;
00104 }
00105
00106 bool SparsePlanner::setConfig(const descartes_core::PlannerConfig& config)
00107 {
00108 std::stringstream ss;
00109 static std::vector<std::string> keys = { SAMPLING_CONFIG };
00110
00111
00112 for (auto kv : config_)
00113 {
00114 if (config.count(kv.first) == 0)
00115 {
00116 error_code_ = descartes_core::PlannerError::INVALID_CONFIGURATION_PARAMETER;
00117 return false;
00118 }
00119 }
00120
00121
00122 try
00123 {
00124 config_[SAMPLING_CONFIG] = config.at(SAMPLING_CONFIG);
00125 sampling_ = std::stod(config.at(SAMPLING_CONFIG));
00126 }
00127 catch (std::invalid_argument& exp)
00128 {
00129 ROS_ERROR_STREAM("Unable to parse configuration value(s)");
00130 error_code_ = descartes_core::PlannerError::INVALID_CONFIGURATION_PARAMETER;
00131 return false;
00132 }
00133
00134 return true;
00135 }
00136
00137 void SparsePlanner::getConfig(descartes_core::PlannerConfig& config) const
00138 {
00139 config = config_;
00140 }
00141
00142 SparsePlanner::~SparsePlanner()
00143 {
00144 }
00145
00146 void SparsePlanner::setSampling(double sampling)
00147 {
00148 sampling_ = sampling;
00149 }
00150
00151 bool SparsePlanner::planPath(const std::vector<TrajectoryPtPtr>& traj)
00152 {
00153 if (error_code_ == descartes_core::PlannerError::UNINITIALIZED)
00154 {
00155 ROS_ERROR_STREAM("Planner has not been initialized");
00156 return false;
00157 }
00158
00159 ros::Time start_time = ros::Time::now();
00160
00161 cart_points_.assign(traj.begin(), traj.end());
00162 std::vector<TrajectoryPtPtr> sparse_trajectory_array;
00163 sampleTrajectory(sampling_, cart_points_, sparse_trajectory_array);
00164 ROS_INFO_STREAM("Sampled trajectory contains " << sparse_trajectory_array.size() << " points from "
00165 << cart_points_.size() << " points in the dense trajectory");
00166
00167 if (planning_graph_->insertGraph(&sparse_trajectory_array) && plan())
00168 {
00169 int planned_count = sparse_solution_array_.size();
00170 int interp_count = cart_points_.size() - sparse_solution_array_.size();
00171 ROS_INFO("Sparse planner succeeded with %i planned point and %i interpolated points in %f seconds", planned_count,
00172 interp_count, (ros::Time::now() - start_time).toSec());
00173 error_code_ = descartes_core::PlannerError::OK;
00174 }
00175 else
00176 {
00177 error_code_ = descartes_core::PlannerError::IK_NOT_AVAILABLE;
00178 return false;
00179 }
00180
00181 return true;
00182 }
00183
00184 bool SparsePlanner::addAfter(const TrajectoryPt::ID& ref_id, TrajectoryPtPtr cp)
00185 {
00186 ros::Time start_time = ros::Time::now();
00187 int sparse_index;
00188 int index;
00189 TrajectoryPt::ID prev_id, next_id;
00190
00191 sparse_index = findNearestSparsePointIndex(ref_id);
00192 if (sparse_index == INVALID_INDEX)
00193 {
00194 ROS_ERROR_STREAM("A point in sparse array near point " << ref_id << " could not be found, aborting");
00195 return false;
00196 }
00197
00198
00199 prev_id = std::get<1>(sparse_solution_array_[sparse_index - 1])->getID();
00200 next_id = std::get<1>(sparse_solution_array_[sparse_index])->getID();
00201
00202
00203 index = getDensePointIndex(ref_id);
00204 if (index == INVALID_INDEX)
00205 {
00206 ROS_ERROR_STREAM("Point " << ref_id << " could not be found in dense array, aborting");
00207 return false;
00208 }
00209 auto pos = cart_points_.begin();
00210 std::advance(pos, index + 1);
00211 cart_points_.insert(pos, cp);
00212
00213
00214 if (planning_graph_->addTrajectory(cp, prev_id, next_id) && plan())
00215 {
00216 int planned_count = sparse_solution_array_.size();
00217 int interp_count = cart_points_.size() - sparse_solution_array_.size();
00218 ROS_INFO("Sparse planner add operation succeeded, %i planned point and %i interpolated points in %f seconds",
00219 planned_count, interp_count, (ros::Time::now() - start_time).toSec());
00220 }
00221 else
00222 {
00223 return false;
00224 }
00225
00226 return true;
00227 }
00228
00229 bool SparsePlanner::addBefore(const TrajectoryPt::ID& ref_id, TrajectoryPtPtr cp)
00230 {
00231 ros::Time start_time = ros::Time::now();
00232 int sparse_index;
00233 int index;
00234 TrajectoryPt::ID prev_id, next_id;
00235
00236 sparse_index = findNearestSparsePointIndex(ref_id, false);
00237 if (sparse_index == INVALID_INDEX)
00238 {
00239 ROS_ERROR_STREAM("A point in sparse array near point " << ref_id << " could not be found, aborting");
00240 return false;
00241 }
00242
00243 prev_id = (sparse_index == 0) ? descartes_core::TrajectoryID::make_nil() :
00244 std::get<1>(sparse_solution_array_[sparse_index - 1])->getID();
00245 next_id = std::get<1>(sparse_solution_array_[sparse_index])->getID();
00246
00247
00248 index = getDensePointIndex(ref_id);
00249 if (index == INVALID_INDEX)
00250 {
00251 ROS_ERROR_STREAM("Point " << ref_id << " could not be found in dense array, aborting");
00252 return false;
00253 }
00254 auto pos = cart_points_.begin();
00255 std::advance(pos, index);
00256 cart_points_.insert(pos, cp);
00257
00258 if (planning_graph_->addTrajectory(cp, prev_id, next_id) && plan())
00259 {
00260 int planned_count = sparse_solution_array_.size();
00261 int interp_count = cart_points_.size() - sparse_solution_array_.size();
00262 ROS_INFO("Sparse planner add operation succeeded, %i planned point and %i interpolated points in %f seconds",
00263 planned_count, interp_count, (ros::Time::now() - start_time).toSec());
00264 }
00265 else
00266 {
00267 return false;
00268 }
00269
00270 return true;
00271 }
00272
00273 bool SparsePlanner::remove(const TrajectoryPt::ID& ref_id)
00274 {
00275 ros::Time start_time = ros::Time::now();
00276 int index = getDensePointIndex(ref_id);
00277 if (index == INVALID_INDEX)
00278 {
00279 ROS_ERROR_STREAM("Point " << ref_id << " could not be found in dense array, aborting");
00280 return false;
00281 }
00282
00283 if (isInSparseTrajectory(ref_id))
00284 {
00285 if (!planning_graph_->removeTrajectory(cart_points_[index]))
00286 {
00287 ROS_ERROR_STREAM("Failed to removed point " << ref_id << " from sparse trajectory, aborting");
00288 return false;
00289 }
00290 }
00291
00292
00293 auto pos = cart_points_.begin();
00294 std::advance(pos, index);
00295 cart_points_.erase(pos);
00296
00297 if (plan())
00298 {
00299 int planned_count = sparse_solution_array_.size();
00300 int interp_count = cart_points_.size() - sparse_solution_array_.size();
00301 ROS_INFO("Sparse planner remove operation succeeded, %i planned point and %i interpolated points in %f seconds",
00302 planned_count, interp_count, (ros::Time::now() - start_time).toSec());
00303 }
00304 else
00305 {
00306 return false;
00307 }
00308
00309 return true;
00310 }
00311
00312 bool SparsePlanner::modify(const TrajectoryPt::ID& ref_id, TrajectoryPtPtr cp)
00313 {
00314 ros::Time start_time = ros::Time::now();
00315 int sparse_index;
00316 TrajectoryPt::ID prev_id, next_id;
00317
00318 sparse_index = getSparsePointIndex(ref_id);
00319 cp->setID(ref_id);
00320 if (sparse_index == INVALID_INDEX)
00321 {
00322 sparse_index = findNearestSparsePointIndex(ref_id);
00323 prev_id = std::get<1>(sparse_solution_array_[sparse_index - 1])->getID();
00324 next_id = std::get<1>(sparse_solution_array_[sparse_index])->getID();
00325 if (!planning_graph_->addTrajectory(cp, prev_id, next_id))
00326 {
00327 ROS_ERROR_STREAM("Failed to add point to sparse trajectory, aborting");
00328 return false;
00329 }
00330 }
00331 else
00332 {
00333 if (!planning_graph_->modifyTrajectory(cp))
00334 {
00335 ROS_ERROR_STREAM("Failed to modify point in sparse trajectory, aborting");
00336 return false;
00337 }
00338 }
00339
00340 int index = getDensePointIndex(ref_id);
00341 cart_points_[index] = cp;
00342 if (plan())
00343 {
00344 int planned_count = sparse_solution_array_.size();
00345 int interp_count = cart_points_.size() - sparse_solution_array_.size();
00346 ROS_INFO("Sparse planner modify operation succeeded, %i planned point and %i interpolated points in %f seconds",
00347 planned_count, interp_count, (ros::Time::now() - start_time).toSec());
00348 }
00349 else
00350 {
00351 return false;
00352 }
00353
00354 return true;
00355 }
00356
00357 bool SparsePlanner::isInSparseTrajectory(const TrajectoryPt::ID& ref_id)
00358 {
00359 auto predicate = [&ref_id](std::tuple<int, TrajectoryPtPtr, JointTrajectoryPt>& t)
00360 {
00361 return ref_id == std::get<1>(t)->getID();
00362 };
00363
00364 return (std::find_if(sparse_solution_array_.begin(), sparse_solution_array_.end(), predicate) !=
00365 sparse_solution_array_.end());
00366 }
00367
00368 int SparsePlanner::getDensePointIndex(const TrajectoryPt::ID& ref_id)
00369 {
00370 int index = INVALID_INDEX;
00371 auto predicate = [&ref_id](TrajectoryPtPtr cp)
00372 {
00373 return ref_id == cp->getID();
00374 };
00375
00376 auto pos = std::find_if(cart_points_.begin(), cart_points_.end(), predicate);
00377 if (pos != cart_points_.end())
00378 {
00379 index = std::distance(cart_points_.begin(), pos);
00380 }
00381
00382 return index;
00383 }
00384
00385 int SparsePlanner::getSparsePointIndex(const TrajectoryPt::ID& ref_id)
00386 {
00387 int index = INVALID_INDEX;
00388 auto predicate = [ref_id](std::tuple<int, TrajectoryPtPtr, JointTrajectoryPt>& t)
00389 {
00390 return ref_id == std::get<1>(t)->getID();
00391 };
00392
00393 auto pos = std::find_if(sparse_solution_array_.begin(), sparse_solution_array_.end(), predicate);
00394 if (pos != sparse_solution_array_.end())
00395 {
00396 index = std::distance(sparse_solution_array_.begin(), pos);
00397 }
00398
00399 return index;
00400 }
00401
00402 int SparsePlanner::findNearestSparsePointIndex(const TrajectoryPt::ID& ref_id, bool skip_equal)
00403 {
00404 int index = INVALID_INDEX;
00405 int dense_index = getDensePointIndex(ref_id);
00406
00407 if (dense_index == INVALID_INDEX)
00408 {
00409 return index;
00410 }
00411
00412 auto predicate = [&dense_index, &skip_equal](std::tuple<int, TrajectoryPtPtr, JointTrajectoryPt>& t)
00413 {
00414
00415 if (skip_equal)
00416 {
00417 return dense_index < std::get<0>(t);
00418 }
00419 else
00420 {
00421 return dense_index <= std::get<0>(t);
00422 }
00423 };
00424
00425 auto pos = std::find_if(sparse_solution_array_.begin(), sparse_solution_array_.end(), predicate);
00426 if (pos != sparse_solution_array_.end())
00427 {
00428 index = std::distance(sparse_solution_array_.begin(), pos);
00429 }
00430 else
00431 {
00432 index = sparse_solution_array_.size() - 1;
00433 }
00434
00435 return index;
00436 }
00437
00438 bool SparsePlanner::getSparseSolutionArray(SolutionArray& sparse_solution_array)
00439 {
00440 std::list<JointTrajectoryPt> sparse_joint_points;
00441 std::vector<TrajectoryPtPtr> sparse_cart_points;
00442 double cost;
00443 ros::Time start_time = ros::Time::now();
00444 if (planning_graph_->getShortestPath(cost, sparse_joint_points))
00445 {
00446 ROS_INFO_STREAM("Sparse solution was found in " << (ros::Time::now() - start_time).toSec() << " seconds");
00447 bool success =
00448 getOrderedSparseArray(sparse_cart_points) && (sparse_joint_points.size() == sparse_cart_points.size());
00449 if (!success)
00450 {
00451 ROS_ERROR_STREAM("Failed to retrieve sparse solution due to unequal array sizes, cartetian pts: "
00452 << sparse_cart_points.size() << ", joints pts: " << sparse_joint_points.size());
00453 return false;
00454 }
00455 }
00456 else
00457 {
00458 ROS_ERROR_STREAM("Failed to find sparse joint solution");
00459 return false;
00460 }
00461
00462 unsigned int i = 0;
00463 unsigned int index;
00464 sparse_solution_array.clear();
00465 sparse_solution_array.reserve(sparse_cart_points.size());
00466 for (auto& item : sparse_joint_points)
00467 {
00468 TrajectoryPtPtr cp = sparse_cart_points[i++];
00469 JointTrajectoryPt& jp = item;
00470 index = getDensePointIndex(cp->getID());
00471
00472 if (index == INVALID_INDEX)
00473 {
00474 ROS_ERROR_STREAM("Cartesian point " << cp->getID() << " not found");
00475 return false;
00476 }
00477 else
00478 {
00479 ROS_DEBUG_STREAM("Point with dense index " << index << " and id " << cp->getID() << " added to sparse");
00480 }
00481
00482 sparse_solution_array.push_back(std::make_tuple(index, cp, jp));
00483 }
00484 return true;
00485 }
00486
00487 bool SparsePlanner::getOrderedSparseArray(std::vector<TrajectoryPtPtr>& sparse_array)
00488 {
00489 const CartesianMap& cart_map = planning_graph_->getCartesianMap();
00490 TrajectoryPt::ID first_id = descartes_core::TrajectoryID::make_nil();
00491 auto predicate = [&first_id](const std::pair<TrajectoryPt::ID, CartesianPointInformation>& p)
00492 {
00493 const auto& info = p.second;
00494 if (info.links_.id_previous == descartes_core::TrajectoryID::make_nil())
00495 {
00496 first_id = p.first;
00497 return true;
00498 }
00499 else
00500 {
00501 return false;
00502 }
00503 };
00504
00505
00506 if (cart_map.empty() || (std::find_if(cart_map.begin(), cart_map.end(), predicate) == cart_map.end()) ||
00507 first_id == descartes_core::TrajectoryID::make_nil())
00508 {
00509 return false;
00510 }
00511
00512
00513 sparse_array.resize(cart_map.size());
00514 TrajectoryPt::ID current_id = first_id;
00515 for (int i = 0; i < sparse_array.size(); i++)
00516 {
00517 if (cart_map.count(current_id) == 0)
00518 {
00519 ROS_ERROR_STREAM("Trajectory point " << current_id << " was not found in sparse trajectory.");
00520 return false;
00521 }
00522
00523 const CartesianPointInformation& info = cart_map.at(current_id);
00524 sparse_array[i] = info.source_trajectory_;
00525 current_id = info.links_.id_next;
00526 }
00527
00528 return true;
00529 }
00530
00531 bool SparsePlanner::getSolutionJointPoint(const CartTrajectoryPt::ID& cart_id, JointTrajectoryPt& j)
00532 {
00533 if (joint_points_map_.count(cart_id) > 0)
00534 {
00535 j = joint_points_map_[cart_id];
00536 }
00537 else
00538 {
00539 ROS_ERROR_STREAM("Solution for point " << cart_id << " was not found");
00540 return false;
00541 }
00542
00543 return true;
00544 }
00545
00546 bool SparsePlanner::getPath(std::vector<TrajectoryPtPtr>& path) const
00547 {
00548 if (cart_points_.empty() || joint_points_map_.empty())
00549 {
00550 return false;
00551 }
00552
00553 path.resize(cart_points_.size());
00554 for (int i = 0; i < cart_points_.size(); i++)
00555 {
00556 TrajectoryPtPtr p = cart_points_[i];
00557 const JointTrajectoryPt& j = joint_points_map_.at(p->getID());
00558 TrajectoryPtPtr new_pt = TrajectoryPtPtr(new JointTrajectoryPt(j));
00559 path[i] = new_pt;
00560 }
00561
00562 return true;
00563 }
00564
00565 int SparsePlanner::getErrorCode() const
00566 {
00567 return error_code_;
00568 }
00569
00570 bool SparsePlanner::getErrorMessage(int error_code, std::string& msg) const
00571 {
00572 std::map<int, std::string>::const_iterator it = error_map_.find(error_code);
00573
00574 if (it != error_map_.cend())
00575 {
00576 msg = it->second;
00577 }
00578 else
00579 {
00580 return false;
00581 }
00582 return true;
00583 }
00584
00585 void SparsePlanner::sampleTrajectory(double sampling, const std::vector<TrajectoryPtPtr>& dense_trajectory_array,
00586 std::vector<TrajectoryPtPtr>& sparse_trajectory_array)
00587 {
00588 std::stringstream ss;
00589 int skip = std::ceil(double(1.0f) / sampling);
00590 ROS_INFO_STREAM("Sampling skip val: " << skip << " from sampling val: " << sampling);
00591 ss << "[";
00592
00593 if (dense_trajectory_array.empty())
00594 return;
00595
00596
00597 sparse_trajectory_array.push_back(dense_trajectory_array.front());
00598 ss << "0 ";
00599
00600
00601 int i;
00602 for (i = skip; i < dense_trajectory_array.size(); i += skip)
00603 {
00604
00605 descartes_core::TimingConstraint tm = cumulativeTimingBetween(dense_trajectory_array, i - skip, i);
00606
00607 descartes_core::TrajectoryPtPtr cloned = dense_trajectory_array[i]->copyAndSetTiming(tm);
00608
00609 sparse_trajectory_array.push_back(cloned);
00610
00611 ss << i << " ";
00612 }
00613 ss << "]";
00614 ROS_INFO_STREAM("Sparse Indices:\n" << ss.str());
00615
00616
00617 if (sparse_trajectory_array.back()->getID() != dense_trajectory_array.back()->getID())
00618 {
00619
00620
00621 descartes_core::TimingConstraint tm =
00622 cumulativeTimingBetween(dense_trajectory_array, i - skip, dense_trajectory_array.size() - 1);
00623
00624 descartes_core::TrajectoryPtPtr cloned = dense_trajectory_array.back()->copyAndSetTiming(tm);
00625
00626 sparse_trajectory_array.push_back(cloned);
00627 }
00628 }
00629
00630 bool SparsePlanner::interpolateJointPose(const std::vector<double>& start, const std::vector<double>& end, double t,
00631 std::vector<double>& interp)
00632 {
00633 if (start.size() != end.size())
00634 {
00635 ROS_ERROR_STREAM("Joint arrays have unequal size, interpolation failed");
00636 return false;
00637 }
00638
00639 if ((t > 1 || t < 0))
00640 {
00641 return false;
00642 }
00643
00644 interp.resize(start.size());
00645 double val = 0.0f;
00646 for (int i = 0; i < start.size(); i++)
00647 {
00648 val = end[i] - (end[i] - start[i]) * (1 - t);
00649 interp[i] = val;
00650 }
00651
00652 return true;
00653 }
00654
00655 bool SparsePlanner::plan()
00656 {
00657
00658 bool replan = true;
00659 bool succeeded = false;
00660 int replanning_attempts = 0;
00661 while (replan && getSparseSolutionArray(sparse_solution_array_))
00662 {
00663
00664
00665 int sparse_index, point_pos;
00666 int result = interpolateSparseTrajectory(sparse_solution_array_, sparse_index, point_pos);
00667 TrajectoryPt::ID prev_id, next_id;
00668 TrajectoryPtPtr cart_point;
00669 switch (result)
00670 {
00671 case int(InterpolationResult::REPLAN):
00672 replan = true;
00673 cart_point = cart_points_[point_pos];
00674 if (sparse_index == 0)
00675 {
00676
00677
00678 prev_id = descartes_core::TrajectoryID::make_nil();
00679 next_id = std::get<1>(sparse_solution_array_[sparse_index])->getID();
00680 }
00681 else
00682 {
00683
00684 int prev_dense_id = std::get<0>(sparse_solution_array_[sparse_index - 1]);
00685 int next_dense_id = point_pos;
00686 descartes_core::TimingConstraint tm = cumulativeTimingBetween(cart_points_, prev_dense_id, next_dense_id);
00687 descartes_core::TrajectoryPtPtr copy_pt = cart_point->copyAndSetTiming(tm);
00688 cart_point = copy_pt;
00689
00690 prev_id = std::get<1>(sparse_solution_array_[sparse_index - 1])->getID();
00691 next_id = std::get<1>(sparse_solution_array_[sparse_index])->getID();
00692 }
00693
00694
00695 {
00696 int prev_dense_id = point_pos;
00697 int next_dense_id = std::get<0>(sparse_solution_array_[sparse_index]);
00698 descartes_core::TimingConstraint tm = cumulativeTimingBetween(cart_points_, prev_dense_id, next_dense_id);
00699 descartes_core::TrajectoryPtPtr copy_pt = cart_points_[next_dense_id]->copyAndSetTiming(tm);
00700
00701 if (!planning_graph_->modifyTrajectory(copy_pt))
00702 {
00703
00704
00705 ROS_ERROR_STREAM("Could not modify trajectory point with id: " << copy_pt->getID());
00706 replan = false;
00707 succeeded = false;
00708 break;
00709 }
00710
00711
00712 if (planning_graph_->addTrajectory(cart_point, prev_id, next_id))
00713 {
00714 sparse_solution_array_.clear();
00715 ROS_INFO_STREAM("Added new point to sparse trajectory from dense trajectory at position "
00716 << point_pos << ", re-planning entire trajectory");
00717 }
00718 else
00719 {
00720 ROS_ERROR_STREAM("Adding point " << point_pos << "to sparse trajectory failed, aborting");
00721 replan = false;
00722 succeeded = false;
00723 }
00724 }
00725
00726 break;
00727 case int(InterpolationResult::SUCCESS):
00728 replan = false;
00729 succeeded = true;
00730 break;
00731 case int(InterpolationResult::ERROR):
00732 replan = false;
00733 succeeded = false;
00734 break;
00735 }
00736 }
00737
00738 return succeeded;
00739 }
00740
00741 bool SparsePlanner::checkJointChanges(const std::vector<double>& s1, const std::vector<double>& s2,
00742 const double& max_change)
00743 {
00744 if (s1.size() != s2.size())
00745 {
00746 ROS_ERROR_STREAM("Joint arrays have unequal size, failed to check for large joint changes");
00747 return false;
00748 }
00749
00750 for (int i = 0; i < s1.size(); i++)
00751 {
00752 if (std::abs(s1[i] - s2[i]) > max_change)
00753 {
00754 return false;
00755 }
00756 }
00757
00758 return true;
00759 }
00760
00761 int SparsePlanner::interpolateSparseTrajectory(const SolutionArray& sparse_solution_array, int& sparse_index,
00762 int& point_pos)
00763 {
00764
00765 joint_points_map_.clear();
00766 descartes_core::RobotModelConstPtr robot_model = planning_graph_->getRobotModel();
00767 std::vector<double> start_jpose, end_jpose, rough_interp, aprox_interp, seed_pose(robot_model->getDOF(), 0);
00768 for (int k = 1; k < sparse_solution_array.size(); k++)
00769 {
00770 auto start_index = std::get<0>(sparse_solution_array[k - 1]);
00771 auto end_index = std::get<0>(sparse_solution_array[k]);
00772 TrajectoryPtPtr start_tpoint = std::get<1>(sparse_solution_array[k - 1]);
00773 TrajectoryPtPtr end_tpoint = std::get<1>(sparse_solution_array[k]);
00774 const JointTrajectoryPt& start_jpoint = std::get<2>(sparse_solution_array[k - 1]);
00775 const JointTrajectoryPt& end_jpoint = std::get<2>(sparse_solution_array[k]);
00776
00777 start_jpoint.getNominalJointPose(seed_pose, *robot_model, start_jpose);
00778 end_jpoint.getNominalJointPose(seed_pose, *robot_model, end_jpose);
00779
00780
00781 joint_points_map_.insert(std::make_pair(start_tpoint->getID(), start_jpoint));
00782
00783
00784 int step = end_index - start_index;
00785 ROS_DEBUG_STREAM("Interpolation parameters: step : " << step << ", start index " << start_index << ", end index "
00786 << end_index);
00787 for (int j = 1; (j <= step) && ((start_index + j) < cart_points_.size()); j++)
00788 {
00789 int pos = start_index + j;
00790 double t = double(j) / double(step);
00791 if (!interpolateJointPose(start_jpose, end_jpose, t, rough_interp))
00792 {
00793 ROS_ERROR_STREAM("Interpolation for point at position " << pos << "failed, aborting");
00794 return (int)InterpolationResult::ERROR;
00795 }
00796
00797 TrajectoryPtPtr cart_point = cart_points_[pos];
00798 if (cart_point->getClosestJointPose(rough_interp, *robot_model, aprox_interp))
00799 {
00800 if (checkJointChanges(rough_interp, aprox_interp, MAX_JOINT_CHANGE))
00801 {
00802 ROS_DEBUG_STREAM("Interpolated point at position " << pos);
00803
00804
00805 const JointTrajectoryPt& last_joint_pt = joint_points_map_.at(cart_points_[pos - 1]->getID());
00806 std::vector<double> last_joint_pose;
00807 last_joint_pt.getNominalJointPose(std::vector<double>(), *robot_model, last_joint_pose);
00808
00809
00810
00811 const descartes_core::TimingConstraint& tm = cart_points_[pos]->getTiming();
00812
00813
00814 if (tm.isSpecified() && !robot_model->isValidMove(last_joint_pose, aprox_interp, tm.upper))
00815 {
00816 ROS_WARN_STREAM("Joint velocity checking failed for point " << pos << ". Replanning.");
00817
00818
00819
00820 point_pos = (j == step) ? (pos - 1) : pos;
00821 sparse_index = k;
00822 return static_cast<int>(InterpolationResult::REPLAN);
00823 }
00824
00825 joint_points_map_.insert(std::make_pair(cart_point->getID(), JointTrajectoryPt(aprox_interp, tm)));
00826 }
00827 else
00828 {
00829 ROS_WARN_STREAM("Joint changes greater that " << MAX_JOINT_CHANGE << " detected for point " << pos
00830 << ", replanning");
00831 sparse_index = k;
00832 point_pos = pos;
00833 return (int)InterpolationResult::REPLAN;
00834 }
00835 }
00836 else
00837 {
00838 ROS_WARN_STREAM("Couldn't find a closest joint pose for point " << cart_point->getID() << ", replanning");
00839 sparse_index = k;
00840 point_pos = pos;
00841 return (int)InterpolationResult::REPLAN;
00842 }
00843 }
00844 }
00845
00846 return (int)InterpolationResult::SUCCESS;
00847 }
00848
00849 }