sparse_planner.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (Apache License)
00003  *
00004  * Copyright (c) 2014, Southwest Research Institute
00005  *
00006  * Licensed under the Apache License, Version 2.0 (the "License");
00007  * you may not use this file except in compliance with the License.
00008  * You may obtain a copy of the License at
00009  *
00010  * http://www.apache.org/licenses/LICENSE-2.0
00011  *
00012  * Unless required by applicable law or agreed to in writing, software
00013  * distributed under the License is distributed on an "AS IS" BASIS,
00014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  * See the License for the specific language governing permissions and
00016  * limitations under the License.
00017  */
00018 /*
00019  * sparse_planner.cpp
00020  *
00021  *  Created on: Dec 17, 2014
00022  *      Author: Jorge Nicho
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       // Add time as normal
00043       tm.upper += pt_tm.upper;
00044       tm.lower += pt_tm.lower;
00045     }
00046     else
00047     {
00048       // A single unspecified timing makes the range unspecified
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   // verifying keys
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   // translating string values
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   // setting ids from sparse array
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   // inserting into dense array
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   // replanning
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   // inserting into dense array
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   // removing from dense array
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;  // last
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   // finding first point
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   // copying point pointers in order
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   // Add the first point
00597   sparse_trajectory_array.push_back(dense_trajectory_array.front());
00598   ss << "0 ";
00599   // The first point requires no special timing adjustment
00600 
00601   int i;  // We keep i outside of the loop so we can examine it on the last step
00602   for (i = skip; i < dense_trajectory_array.size(); i += skip)
00603   {
00604     // Add the cumulative time of the dense trajectory back in
00605     descartes_core::TimingConstraint tm = cumulativeTimingBetween(dense_trajectory_array, i - skip, i);
00606     // We don't want to modify the input trajectory pointers, so we clone and modify them here
00607     descartes_core::TrajectoryPtPtr cloned = dense_trajectory_array[i]->copyAndSetTiming(tm);
00608     // Write to the new array
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   // add the last one
00617   if (sparse_trajectory_array.back()->getID() != dense_trajectory_array.back()->getID())
00618   {
00619     // The final point is index size() - 1
00620     // The point before is index ( i - skip )
00621     descartes_core::TimingConstraint tm =
00622         cumulativeTimingBetween(dense_trajectory_array, i - skip, dense_trajectory_array.size() - 1);
00623     // We don't want to modify the input trajectory pointers, so we clone and modify them here
00624     descartes_core::TrajectoryPtPtr cloned = dense_trajectory_array.back()->copyAndSetTiming(tm);
00625     // Write to solution
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   // solving coarse trajectory
00658   bool replan = true;
00659   bool succeeded = false;
00660   int replanning_attempts = 0;
00661   while (replan && getSparseSolutionArray(sparse_solution_array_))
00662   {
00663     // sparse_index is the index in the sampled trajectory that a new point is to be added
00664     // point_pos is the index into the dense trajectory that the new point is to be copied from
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           // If the point is being inserted at the beginning of the trajectory
00677           // there is no need to tweak the timing that comes from the dense traj
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           // Here we want to calculate the time from the prev point to the new point
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;  // swap the point over
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         // In either case, the sparse_index point will have to be recalculated
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             // Theoretically, this should never occur as we are merely modifying an existing point in the sparse
00704             // graph.
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           // Add into original trajectory
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   // populating full path
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     // adding start joint point to solution
00781     joint_points_map_.insert(std::make_pair(start_tpoint->getID(), start_jpoint));
00782 
00783     // interpolating
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           // look up previous points joint solution
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           // retreiving timing constraint
00810           // TODO, let's check the timing constraints
00811           const descartes_core::TimingConstraint& tm = cart_points_[pos]->getTiming();
00812 
00813           // check validity of joint motion
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             // The last point in an interpolated segment will always succeed (as its from the solved graph)
00818             // but the timing may not be valid. We check this last point here and if it fails, the second to
00819             // last point is added to the graph so that this timing is thoroughly checked by planning graph.
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 } /* namespace descartes_planner */


descartes_planner
Author(s): Jorge Nicho
autogenerated on Thu Jun 6 2019 21:36:12