GTSPSolver.cpp
Go to the documentation of this file.
00001 
00002 /*
00003  * GTSPSolver.cpp
00004  *
00005  *  Created on: Feb 18, 2012
00006  *      Author: hess
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     //  //insert start as first point
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()); // remove first point again
00052     for (unsigned int i = 0; i < traj.size(); ++i) {
00053         traj[i] = traj[i] - 1; // correct indexes
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     //collect end-effector poses and iksolutions for the trajectory
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                 //get the number belonging to the edge we need the pose for
00070                 int local_edge_nb = -1; // minus one: e.g. edge 1 is indexed on index 0
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                 //if this happens often, than your weight function is weired or the graph not well enough connected
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                     //                          tmp_joints[j][5] = ik_solutions_to_optimize[ik_solutions_to_optimize.size() - 1][0][5]; // get the last node -> gripper orientation should be the same for all poses
00086                 }
00087                 ik_solutions_to_optimize.push_back(tmp_joints);
00088                 pose_path.push_back(coll_free_poses_[curr_node][0]); // any edge just that we have a pose
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                 //                              tmp_joints[j][5] = ik_solutions_to_optimize[ik_solutions_to_optimize.size() - 1][0][5]; // get the last node -> gripper orientation should be the same for all poses
00098             }
00099             ik_solutions_to_optimize.push_back(tmp_joints);
00100             pose_path.push_back(coll_free_poses_[curr_node][0]); // any edge just that we have a pose
00101         }
00102     }
00103 
00104     //insert the start joint position
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     //computing the joint space path with dijktra
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     //save the result
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     // get number of new nodes --> introduce two nodes per edge --> note that
00132     int n_new_nodes = adj_bool.sum();
00133     int n_nodes = adj_bool.rows();
00134     
00135     //number of edges per node
00136     Eigen::VectorXi row_sum = adj_bool.rowwise().sum();
00137 
00138     std::vector<SurfacePatch> tmp_patches;
00139     //get cummulated number of edges --> use later as index
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     //new matrices
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_; //all edges not computed have high cost --> not connected
00152 
00153     int curr_edge_index = 0;
00154     float sum_assigned_weights = 0;
00155     //iterate over all nodes - save the cost
00156     for (int i = 0; i < n_nodes; ++i) {
00157 
00158         //introduce new node for each edge of the current node
00159         for (int j = 0; j < n_nodes; ++j) {
00160 
00161             //if there is an edge between node i and node j
00162             if (adj_bool(i, j) == 1) {
00163 
00164                 //get indexes of possible nodes in multinode b where edges could end
00165                 int n2_start = 0;
00166                 if (j != 0) {
00167                     n2_start = row_cumsum[j - 1];
00168                 }
00169 
00170                 //insert the cost
00171                 Eigen::Vector3f edge1 = patches[j].getVector3fMap() - patches[i].getVector3fMap();
00172                 float euclidean_cost = edge1.norm();
00173                 int curr_edge_from_j = 0; //current edge count leading form j to another node
00174                 //iterate over all possible ends
00175                 for (int k = 0; k < n_nodes; ++k) {
00176 
00177                     if (adj_bool(j, k) == 1) {
00178 
00179                         //check where the end is going
00180                         Eigen::Vector3f edge2 = patches[k].getVector3fMap() - patches[j].getVector3fMap();
00181 
00182                         //if the result of the dot product is smaller -1 due to precision errors
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                         //it is the pose difference --> thus we can always use the smaller angle
00191                         float angular_cost = acos(dotproduct) / M_PI;
00192                         
00193                         //compute weight as convex combination of translation and rotation
00194                         float cost = (1 - alpha_) * euclidean_cost + alpha_ * angular_cost;
00195                         
00196                         //contribute to the sum of assigned weights
00197                         sum_assigned_weights += cost;
00198                         
00199                         //save the weigts and adjacency
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     //    for (unsigned int i = 0; i < new_adj_float.rows(); ++i) { //alle nodes
00211     //        for (unsigned int j = 0; j < new_adj_float.cols(); ++j) { //alle nodes
00212     //
00213     //            if (new_adj_float(i, j) > (max_adjacency_ - 0.001)) {
00214     //                Eigen::Vector3f edge1 = tmp_patches[j].getVector3fMap() - tmp_patches[i].getVector3fMap();
00215     //                float cost = edge1.norm();
00216     //                new_adj_float(i, j) = new_adj_float(i, j) + (1-alpha_)*cost;
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     //iterate over all multinodes
00233     //assign zero cost to move to successor node in multinode
00234     for (int i = 0; i < n_multinodes; ++i) {
00235 
00236         //find all nodes in multinode
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         //shift/rotate the cost --> last line is now first
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         //save back to the original matrix
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         //link from end to start to close the cycle
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                         //check if multinode has already been pushed in the last step
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); // we are at the last node - thus use planning to get to the final pose
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 //void testGTSPConstruction() {
00335 //    SurfacePatch p1;
00336 //    p1.x = 0.0;
00337 //    p1.y = 0.0;
00338 //    p1.z = 0.0;
00339 //    SurfacePatch p2;
00340 //    p2.x = 1.1;
00341 //    p2.y = 0.0;
00342 //    p2.z = 0.0;
00343 //    SurfacePatch p3;
00344 //    p3.x = 2.0;
00345 //    p3.y = 0.1;
00346 //    p3.z = 0.0;
00347 //    SurfacePatch p4;
00348 //    p4.x = 1;
00349 //    p4.y = 1;
00350 //    p4.z = 0.0;
00351 //    GTSPSolver gtsp;
00352 //    std::vector<SurfacePatch> patches;
00353 //    patches.push_back(p1);
00354 //    patches.push_back(p2);
00355 //    patches.push_back(p3);
00356 //    patches.push_back(p4);
00357 //
00358 //    Eigen::MatrixXi adj_bool = Eigen::MatrixXi::Ones(4, 4);
00359 //    adj_bool(0, 0) = 0;
00360 //    adj_bool(1, 1) = 0;
00361 //    adj_bool(2, 2) = 0;
00362 //    adj_bool(3, 3) = 0;
00363 //
00364 //    Eigen::VectorXi mapping;
00365 //    Eigen::MatrixXi new_adj_bool;
00366 //    Eigen::MatrixXf new_adj_float;
00367 //    gtsp.transformGraphToGTSP(adj_bool, patches, mapping, new_adj_bool, new_adj_float);
00368 //
00369 //    std::cout << new_adj_bool << std::endl;
00370 //    std::cout << new_adj_float << std::endl;
00371 //
00372 //}
00373 //
00374 //void testGTSPToTSP() {
00375 //
00376 //    GTSPSolver gtsp;
00377 //    Eigen::MatrixXi multinode_mapping = Eigen::MatrixXi::Zero(4, 1);
00378 //    multinode_mapping(0) = 2;
00379 //    multinode_mapping(1) = 3;
00380 //    multinode_mapping(2) = 4;
00381 //    multinode_mapping(3) = 7;
00382 //
00383 //    Eigen::MatrixXi adj_bool = Eigen::MatrixXi::Zero(7, 7);
00384 //    Eigen::MatrixXf adj_float = Eigen::MatrixXf::Ones(7, 7) * 1000;
00385 //
00386 //    adj_bool(2, 0) = 1;
00387 //    adj_bool(3, 0) = 1;
00388 //    adj_bool(4, 0) = 1;
00389 //    adj_bool(5, 0) = 1;
00390 //    adj_bool(6, 0) = 1;
00391 //
00392 //    adj_bool(2, 1) = 1;
00393 //    adj_bool(3, 1) = 1;
00394 //    adj_bool(4, 1) = 1;
00395 //    adj_bool(5, 1) = 1;
00396 //    adj_bool(6, 1) = 1;
00397 //
00398 //    adj_bool(0, 2) = 1;
00399 //    adj_bool(1, 2) = 1;
00400 //    adj_bool(4, 2) = 1;
00401 //    adj_bool(5, 2) = 1;
00402 //    adj_bool(6, 2) = 1;
00403 //
00404 //    adj_bool(0, 3) = 1;
00405 //    adj_bool(1, 3) = 1;
00406 //    adj_bool(4, 3) = 1;
00407 //    adj_bool(5, 3) = 1;
00408 //    adj_bool(6, 3) = 1;
00409 //
00410 //    adj_bool(0, 4) = 1;
00411 //    adj_bool(1, 4) = 1;
00412 //    adj_bool(2, 4) = 1;
00413 //    adj_bool(3, 4) = 1;
00414 //
00415 //    adj_bool(0, 5) = 1;
00416 //    adj_bool(1, 5) = 1;
00417 //    adj_bool(2, 5) = 1;
00418 //    adj_bool(3, 5) = 1;
00419 //
00420 //    adj_bool(0, 6) = 1;
00421 //    adj_bool(1, 6) = 1;
00422 //    adj_bool(2, 6) = 1;
00423 //    adj_bool(3, 6) = 1;
00424 //
00425 //    adj_float(2, 0) = 6;
00426 //    adj_float(3, 0) = 2;
00427 //    adj_float(4, 0) = 9;
00428 //    adj_float(5, 0) = 8;
00429 //    adj_float(6, 0) = 4;
00430 //
00431 //    adj_float(2, 1) = 3;
00432 //    adj_float(3, 1) = 1;
00433 //    adj_float(4, 1) = 7;
00434 //    adj_float(5, 1) = 4;
00435 //    adj_float(6, 1) = 7;
00436 //
00437 //    adj_float(0, 2) = 5;
00438 //    adj_float(1, 2) = 8;
00439 //    adj_float(4, 2) = 9;
00440 //    adj_float(5, 2) = 6;
00441 //    adj_float(6, 2) = 9;
00442 //
00443 //    adj_float(0, 3) = 7;
00444 //    adj_float(1, 3) = 9;
00445 //    adj_float(4, 3) = 3;
00446 //    adj_float(5, 3) = 5;
00447 //    adj_float(6, 3) = 7;
00448 //
00449 //    adj_float(0, 4) = 4;
00450 //    adj_float(1, 4) = 3;
00451 //    adj_float(2, 4) = 4;
00452 //    adj_float(3, 4) = 5;
00453 //
00454 //    adj_float(0, 5) = 6;
00455 //    adj_float(1, 5) = 1;
00456 //    adj_float(2, 5) = 2;
00457 //    adj_float(3, 5) = 6;
00458 //
00459 //    adj_float(0, 6) = 2;
00460 //    adj_float(1, 6) = 5;
00461 //    adj_float(2, 6) = 4;
00462 //    adj_float(3, 6) = 1;
00463 //    std::cout << "org transition matrix \n" << adj_float;
00464 //    gtsp.transformGTSPToTSP(multinode_mapping, adj_bool, adj_float);
00465 //
00466 //    std::cout << "new transition matrix \n" << adj_float;
00467 //}
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends


coverage_3d_planning
Author(s): Juergen Hess
autogenerated on Wed Dec 26 2012 15:26:11