00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 #include <Eigen/Core>
00010 #include <coverage_3d_planning/GTSPSolver.h>
00011 #include <coverage_3d_planning/TSPSearch.h>
00012 #include <coverage_3d_tools/conversions.h>
00013 GTSPSolver::GTSPSolver() :
00014     alpha_(0.10) {
00015     dist_measure_ = "DIST";
00016     max_adjacency_ = 30000;
00017 }
00018 GTSPSolver::GTSPSolver(double max_adjacency) : alpha_(0.10) {
00019     dist_measure_ = "DIST";
00020     max_adjacency_ = max_adjacency;
00021 }
00022 
00023 void GTSPSolver::setAlpha(double alpha) {
00024     alpha_ = alpha;
00025 }
00026 
00027 void GTSPSolver::getSolution(std::vector<std::vector<double> >& joint_path, std::vector<tf::Pose>& pose_path,
00028     std::vector<unsigned int>& action, std::vector<unsigned int>& res_traj) {
00029 
00030     ROS_INFO("GTSPSolver::getSolution transforming graph to gtsp");
00031     Eigen::VectorXi multinode_mapping;
00032     Eigen::MatrixXf gtsp_weights;
00033     Eigen::MatrixXi gtsp_adjacency;
00034     transformGraphToGTSP(adjacency_, patches_, multinode_mapping, gtsp_adjacency, gtsp_weights);
00035 
00036     ROS_INFO("GTSPSolver::getSolution transforming gtsp to tsp");
00037     transformGTSPToTSP(multinode_mapping, gtsp_adjacency, gtsp_weights);
00038 
00039     
00040     Eigen::MatrixXf gtsp_start_weights;
00041     insertStartIntoWeights(gtsp_weights, multinode_mapping, gtsp_start_weights);
00042 
00043     ROS_INFO("GTSPSolver::getSolution calling TSP solver");
00044     TSPSearch tsp;
00045     tsp.writeToTSPFile(gtsp_start_weights);
00046     tsp.callTSPSolver();
00047     ROS_DEBUG("GTSPSolver::getSolution reading back TSP result");
00048     std::vector<unsigned int> traj;
00049     tsp.readResultTSPFile(traj);
00050 
00051     traj.erase(traj.begin()); 
00052     for (unsigned int i = 0; i < traj.size(); ++i) {
00053         traj[i] = traj[i] - 1; 
00054     }
00055 
00056     ROS_INFO_STREAM("GTSPSolver::getSolution mapping to the correct patches ");
00057     std::vector<unsigned int> multinode_traj;
00058     mapGTSPIndexToMultinode(multinode_mapping, traj, multinode_traj);
00059     ROS_DEBUG_STREAM("GTSPSolver::getSolution trajectory size " << traj.size() << " multinode traj size " << multinode_traj.size());
00060     
00061     std::vector<std::vector<std::vector<double> > > ik_solutions_to_optimize;
00062     for (unsigned int i = 0; i < multinode_traj.size(); ++i) {
00063         int curr_node = multinode_traj[i];
00064 
00065         if (i < multinode_traj.size() - 1) {
00066             int next_node = multinode_traj[i + 1];
00067             if ((adjacency_(curr_node, next_node) == 1)) {
00068 
00069                 
00070                 int local_edge_nb = -1; 
00071                 for (int j = 0; j <= next_node; ++j) {
00072                     local_edge_nb += adjacency_(curr_node, j);
00073                 }
00074                 ik_solutions_to_optimize.push_back(coll_free_ik_[curr_node][local_edge_nb]);
00075                 pose_path.push_back(coll_free_poses_[curr_node][local_edge_nb]);
00076             } else {
00077                 
00078                 ROS_WARN("GTSPSolver::getSolution Path planning edge taken --> should usually not happen.");
00079                 std::vector<std::vector<std::vector<double> > > tmp = coll_free_ik_[multinode_traj[i]];
00080                 std::vector<std::vector<double> > tmp_joints;
00081                 for (unsigned int j = 0; j < tmp.size(); ++j) {
00082                     for (unsigned int k = 0; k < tmp[j].size(); ++k) {
00083                         tmp_joints.push_back(tmp[j][k]);
00084                     }
00085                     
00086                 }
00087                 ik_solutions_to_optimize.push_back(tmp_joints);
00088                 pose_path.push_back(coll_free_poses_[curr_node][0]); 
00089             }
00090         } else {
00091             std::vector<std::vector<std::vector<double> > > tmp = coll_free_ik_[multinode_traj[i]];
00092             std::vector<std::vector<double> > tmp_joints;
00093             for (unsigned int j = 0; j < tmp.size(); ++j) {
00094                 for (unsigned int k = 0; k < tmp[j].size(); ++k) {
00095                     tmp_joints.push_back(tmp[j][k]);
00096                 }
00097                 
00098             }
00099             ik_solutions_to_optimize.push_back(tmp_joints);
00100             pose_path.push_back(coll_free_poses_[curr_node][0]); 
00101         }
00102     }
00103 
00104     
00105     std::vector<std::vector<double> > tmp_joint_start;
00106     tmp_joint_start.push_back(start_joint_);
00107     ik_solutions_to_optimize.insert(ik_solutions_to_optimize.begin(), tmp_joint_start);
00108     ik_solutions_to_optimize.push_back(tmp_joint_start);
00109    
00110     
00111     std::vector<std::vector<double> > path;
00112     std::vector<bool> valid_poses(ik_solutions_to_optimize.size(), true);
00113     traj_planner_.computeDijkstraPath(ik_solutions_to_optimize, valid_poses, path, dist_measure_);
00114     joint_path = path;
00115     std::vector<unsigned int> actions;
00116     getActions(multinode_traj, actions);
00117         
00118     
00119     res_traj = multinode_traj;
00120     pose_path.push_back(start_pose_);
00121     pose_path.insert(pose_path.begin(), start_pose_);
00122 
00123     actions.push_back(1);
00124     actions.insert(actions.begin(), 1);
00125     action = actions;
00126 
00127 }
00128 void GTSPSolver::transformGraphToGTSP(const Eigen::MatrixXi& adj_bool, const std::vector<SurfacePatch>& patches,
00129     Eigen::VectorXi& multinode_mapping, Eigen::MatrixXi& new_adj_bool, Eigen::MatrixXf& new_adj_float) {
00130 
00131     
00132     int n_new_nodes = adj_bool.sum();
00133     int n_nodes = adj_bool.rows();
00134     
00135     
00136     Eigen::VectorXi row_sum = adj_bool.rowwise().sum();
00137 
00138     std::vector<SurfacePatch> tmp_patches;
00139     
00140     Eigen::VectorXi row_cumsum = row_sum;
00141     for (int i = 1; i < row_sum.rows(); ++i) {
00142         row_cumsum(i) = row_sum(i) + row_cumsum(i - 1);
00143         for (int j = 0; j < row_sum(i); ++j) {
00144             tmp_patches.push_back(patches[i]);
00145         }
00146     }
00147     multinode_mapping = row_cumsum;
00148 
00149     
00150     new_adj_bool = Eigen::MatrixXi::Zero(n_new_nodes, n_new_nodes);
00151     new_adj_float = Eigen::MatrixXf::Ones(n_new_nodes, n_new_nodes) * max_adjacency_; 
00152 
00153     int curr_edge_index = 0;
00154     float sum_assigned_weights = 0;
00155     
00156     for (int i = 0; i < n_nodes; ++i) {
00157 
00158         
00159         for (int j = 0; j < n_nodes; ++j) {
00160 
00161             
00162             if (adj_bool(i, j) == 1) {
00163 
00164                 
00165                 int n2_start = 0;
00166                 if (j != 0) {
00167                     n2_start = row_cumsum[j - 1];
00168                 }
00169 
00170                 
00171                 Eigen::Vector3f edge1 = patches[j].getVector3fMap() - patches[i].getVector3fMap();
00172                 float euclidean_cost = edge1.norm();
00173                 int curr_edge_from_j = 0; 
00174                 
00175                 for (int k = 0; k < n_nodes; ++k) {
00176 
00177                     if (adj_bool(j, k) == 1) {
00178 
00179                         
00180                         Eigen::Vector3f edge2 = patches[k].getVector3fMap() - patches[j].getVector3fMap();
00181 
00182                         
00183                         float dotproduct = edge1.normalized().dot(edge2.normalized());
00184                         if (dotproduct < -1.0) {
00185                             dotproduct = -0.999999;
00186                         } else if (dotproduct > 1.0) {
00187                             dotproduct = 0.999999;
00188                         }
00189                  
00190                         
00191                         float angular_cost = acos(dotproduct) / M_PI;
00192                         
00193                         
00194                         float cost = (1 - alpha_) * euclidean_cost + alpha_ * angular_cost;
00195                         
00196                         
00197                         sum_assigned_weights += cost;
00198                         
00199                         
00200                         new_adj_float(curr_edge_index, n2_start + curr_edge_from_j) = cost;
00201                         new_adj_bool(curr_edge_index, n2_start + curr_edge_from_j) = 1;
00202                         curr_edge_from_j++;
00203                     }
00204                 }
00205                 curr_edge_index++;
00206             }
00207         }
00208     }
00209 
00210     
00211     
00212     
00213     
00214     
00215     
00216     
00217     
00218     
00219     
00220 
00221 
00222     new_adj_float = new_adj_float + (Eigen::MatrixXf::Ones(n_new_nodes, n_new_nodes) * sum_assigned_weights);
00223     ROS_DEBUG_STREAM("GTSPSolver::transformGraphToGTSP sum_assigned_weights " << sum_assigned_weights << "max_adjacency_ " << max_adjacency_ );
00224 }
00225 
00226 void GTSPSolver::transformGTSPToTSP(const Eigen::VectorXi& multinode_mapping, Eigen::MatrixXi& adj_bool,
00227     Eigen::MatrixXf& adj_float) {
00228 
00229     int n_multinodes = multinode_mapping.rows();
00230     int n_nodes = adj_bool.rows();
00231 
00232     
00233     
00234     for (int i = 0; i < n_multinodes; ++i) {
00235 
00236         
00237         int start = 0;
00238         if (i != 0) {
00239             start = multinode_mapping(i - 1);
00240         }
00241         int end = multinode_mapping(i) - 1;
00242 
00243         int curr_n_nodes = end - start + 1;
00244         if (curr_n_nodes == 1 || curr_n_nodes == 0) {
00245            ROS_WARN_STREAM("GTSPSolver::transformGTSPToTSP: failure " << curr_n_nodes << " " << i << " " << multinode_mapping(i - 1) << " "
00246                 << multinode_mapping(i));
00247             continue;
00248         }
00249         Eigen::MatrixXi tmp_bool = Eigen::MatrixXi::Zero(curr_n_nodes, n_nodes);
00250         Eigen::MatrixXf tmp_float = Eigen::MatrixXf::Zero(curr_n_nodes, n_nodes);
00251 
00252         
00253         tmp_bool.block(curr_n_nodes - 1, 0, 1, n_nodes) = adj_bool.block(start, 0, 1, n_nodes);
00254         tmp_float.block(curr_n_nodes - 1, 0, 1, n_nodes) = adj_float.block(start, 0, 1, n_nodes);
00255         tmp_bool.block(0, 0, curr_n_nodes - 1, n_nodes) = adj_bool.block(start + 1, 0, curr_n_nodes - 1, n_nodes);
00256         tmp_float.block(0, 0, curr_n_nodes - 1, n_nodes) = adj_float.block(start + 1, 0, curr_n_nodes - 1, n_nodes);
00257 
00258         
00259         adj_bool.block(start, 0, curr_n_nodes, n_nodes) = tmp_bool.block(0, 0, tmp_bool.rows(), tmp_bool.cols());
00260         adj_float.block(start, 0, curr_n_nodes, n_nodes) = tmp_float;
00261 
00262         for (int j = start; j < end; ++j) {
00263             adj_bool(j, j + 1) = 1;
00264             adj_float(j, j + 1) = 0;
00265         }
00266         
00267         adj_bool(end, start) = 1;
00268         adj_float(end, start) = 0;
00269     }
00270 }
00271 
00272 void GTSPSolver::mapGTSPIndexToMultinode(const Eigen::VectorXi& multinode_mapping,
00273     const std::vector<unsigned int>& traj, std::vector<unsigned int>& multinode_traj) {
00274     multinode_traj.clear();
00275     BOOST_FOREACH(unsigned int i, traj)
00276                 {
00277                     unsigned int j = 0;
00278                     while ((int) i >= multinode_mapping(j)) {
00279                         j++;
00280                     }
00281 
00282                     if (multinode_traj.size() == 0) {
00283                         multinode_traj.push_back(j);
00284                     } else {
00285                         
00286                         if (multinode_traj[multinode_traj.size() - 1] != j) {
00287                             multinode_traj.push_back(j);
00288                         }
00289                     }
00290                 }
00291 }
00292 
00293 unsigned int GTSPSolver::mapGTSPIndexToMultinode(const Eigen::VectorXi& multinode_mapping, unsigned int node) {
00294     unsigned int j = 0;
00295     while ((int) node >= multinode_mapping(j)) {
00296         j++;
00297     }
00298     return j;
00299 }
00300 
00301 void GTSPSolver::getActions(const std::vector<unsigned int>& traj, std::vector<unsigned int>& actions) {
00302 
00303     actions.clear();
00304 
00305     for (unsigned int i = 0; i < traj.size(); ++i) {
00306 
00307         if (i < (traj.size() - 1)) {
00308 
00309             if (adjacency_(traj[i], traj[i + 1]) == 1) {
00310                 actions.push_back(0);
00311             } else {
00312                 actions.push_back(1);
00313             }
00314         } else {
00315             actions.push_back(1); 
00316         }
00317     }
00318 }
00319 void GTSPSolver::insertStartIntoWeights(const Eigen::MatrixXf& weights, const Eigen::VectorXi& multinode_mapping,
00320     Eigen::MatrixXf& new_weights) {
00321 
00322     Eigen::Vector3f start = PoseTF2EigenVector3(start_pose_);
00323     new_weights = Eigen::MatrixXf::Ones(weights.rows() + 1, weights.rows() + 1) * max_adjacency_;
00324     for (int i = 1; i < new_weights.rows(); ++i) {
00325         unsigned int multinode_index = mapGTSPIndexToMultinode(multinode_mapping, i - 1);
00326         Eigen::Vector3f tmp = start - surface_points_[multinode_index].getVector3fMap();
00327         new_weights(i, 0) = tmp.norm();
00328         new_weights(0, i) = new_weights(i, 0);
00329     }
00330 
00331     new_weights.block(1, 1, weights.rows(), weights.cols()) = weights.block(0, 0, weights.rows(), weights.cols());
00332 }
00333 
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 
00408 
00409 
00410 
00411 
00412 
00413 
00414 
00415 
00416 
00417 
00418 
00419 
00420 
00421 
00422 
00423 
00424 
00425 
00426 
00427 
00428 
00429 
00430 
00431 
00432 
00433 
00434 
00435 
00436 
00437 
00438 
00439 
00440 
00441 
00442 
00443 
00444 
00445 
00446 
00447 
00448 
00449 
00450 
00451 
00452 
00453 
00454 
00455 
00456 
00457 
00458 
00459 
00460 
00461 
00462 
00463 
00464 
00465 
00466 
00467