JointGTSPSolver.cpp
Go to the documentation of this file.
00001 
00003 #include <Eigen/Core>
00004 #include <coverage_3d_planning/JointGTSPSolver.h>
00005 #include <coverage_3d_planning/TSPSearch.h>
00006 #include <coverage_3d_tools/conversions.h>
00007 JointGTSPSolver::JointGTSPSolver() {
00008     dist_measure_ = "DIST";
00009     max_adjacency_ = 500000;
00010 }
00011 
00012 JointGTSPSolver::JointGTSPSolver(double max_adjacency, std::string tsp_type) {
00013     dist_measure_ = tsp_type;
00014     max_adjacency_ = max_adjacency;
00015 
00016 }
00017 
00018 void JointGTSPSolver::getSolution(std::vector<std::vector<double> >& joint_path, std::vector<tf::Pose>& pose_path,
00019     std::vector<unsigned int>& action, std::vector<unsigned int>& res_traj) {
00020 
00021     ROS_INFO("JointGTSPSolver: transforming graph to gtsp");
00022     Eigen::VectorXi multinode_mapping;
00023     Eigen::MatrixXf gtsp_weights;
00024     Eigen::MatrixXi gtsp_adjacency;
00025     transformGraphToGTSP(adjacency_, patches_, coll_free_ik_, multinode_mapping, gtsp_adjacency, gtsp_weights);
00026 
00027     ROS_INFO("JointGTSPSolver: transforming gtsp to tsp");
00028     transformGTSPToTSP(multinode_mapping, gtsp_adjacency, gtsp_weights);
00029     ROS_INFO_STREAM(
00030         "JointGTSPSolver: conversion result " << gtsp_adjacency.rows() << " " << gtsp_adjacency.cols() << " " << gtsp_weights.rows() << " " << gtsp_weights.cols());
00031 
00032     //insert start as first point
00033     Eigen::MatrixXf gtsp_start_weights;
00034     insertStartIntoWeights(gtsp_weights, multinode_mapping, gtsp_start_weights);
00035 
00036     ROS_INFO("JointGTSPSolver: searching tsp solution ");
00037     TSPSearch tsp;
00038     tsp.writeToTSPFile(gtsp_start_weights);
00039     tsp.callTSPSolver();
00040     ROS_INFO("JointGTSPSolver: reading back the result ");
00041     std::vector<unsigned int> traj;
00042     tsp.readResultTSPFile(traj);
00043 
00044     traj.erase(traj.begin()); // remove first point again
00045     for (unsigned int i = 0; i < traj.size(); ++i) {
00046         traj[i] = traj[i] - 1; // correct indexes
00047     }
00048 
00049     ROS_INFO("JointGTSPSolver: mapping solution to the correct patches ");
00050     std::vector<unsigned int> multinode_traj;
00051     mapGTSPIndexToMultinode(multinode_mapping, traj, multinode_traj);
00052 
00053     //collect end-effector poses
00054     for (unsigned int i = 0; i < multinode_traj.size(); ++i) {
00055         int curr_node = multinode_traj[i];
00056 
00057         if (i < multinode_traj.size() - 1) {
00058             int next_node = multinode_traj[i + 1];
00059             if ((adjacency_(curr_node, next_node) == 1)) {
00060 
00061                 //get the number belonging to the edge we need the pose for
00062                 int local_edge_nb = -1; // minus one: e.g. edge 1 is indexed on index 0
00063                 for (int j = 0; j <= next_node; ++j) {
00064                     local_edge_nb += adjacency_(curr_node, j);
00065                 }
00066                 pose_path.push_back(coll_free_poses_[curr_node][local_edge_nb]);
00067             } else {
00068                 ROS_WARN("JointGTSPSolver::getSolution Path planning edge taken --> should usually not happen.");
00069                 pose_path.push_back(coll_free_poses_[curr_node][0]); // any edge just that we have a pose
00070             }
00071         } else {
00072             std::vector<std::vector<std::vector<double> > > tmp = coll_free_ik_[multinode_traj[i]];
00073             std::vector<std::vector<double> > tmp_joints;
00074             for (unsigned int j = 0; j < tmp.size(); ++j) {
00075                 for (unsigned int k = 0; k < tmp[j].size(); ++k) {
00076                     tmp_joints.push_back(tmp[j][k]);
00077                 }
00078             }
00079             pose_path.push_back(coll_free_poses_[curr_node][0]); // any edge just that we have a pose
00080         }
00081     }
00082     std::vector<std::vector<double> > path;
00083     ROS_INFO_STREAM(
00084         "JointGTSPSolver: size of adjacency matrix" << gtsp_adjacency.rows() << " " << gtsp_adjacency.cols() << " " << traj.size());
00085     getJointPoses(multinode_mapping, traj, path);
00086     path.insert(path.begin(), start_joint_);
00087     path.push_back(start_joint_);
00088     joint_path = path;
00089 
00090     std::vector<unsigned int> actions;
00091     getActions(multinode_traj, actions);
00092     res_traj = multinode_traj;
00093 
00094     pose_path.push_back(start_pose_);
00095     pose_path.insert(pose_path.begin(), start_pose_);
00096 
00097     actions.push_back(1);
00098     actions.insert(actions.begin(), 1);
00099     action = actions;
00100 }
00101 void JointGTSPSolver::transformGraphToGTSP(const Eigen::MatrixXi& adj_bool, const std::vector<SurfacePatch>& patches,
00102     const std::vector<std::vector<std::vector<std::vector<double> > > >& coll_free_ik,
00103     Eigen::VectorXi& multinode_mapping, Eigen::MatrixXi& new_adj_bool, Eigen::MatrixXf& new_adj_float) {
00104 
00105     // get number of new nodes --> introduce two nodes per edge --> note that each edge is represented twice in the adjacency matrix
00106     int n_nodes = adj_bool.rows();
00107 
00108     std::vector<std::vector<std::vector<double> > > tmp_ik;
00109     tmp_ik.resize(n_nodes);
00110     Eigen::VectorXi row_sum = Eigen::VectorXi::Zero(n_nodes);
00111     int n_new_nodes = 0;
00112     for (unsigned int i = 0; i < coll_free_ik.size(); ++i) { //alle nodes
00113         for (unsigned int j = 0; j < coll_free_ik[i].size(); ++j) { //alle kanten eines node
00114             for (unsigned int k = 0; k < coll_free_ik[i][j].size(); ++k) {
00115                 tmp_ik[i].push_back(coll_free_ik[i][j][k]);
00116                 n_new_nodes++;
00117             }
00118         }
00119         row_sum[i] = tmp_ik[i].size();
00120     }
00121 
00122     //get cummulated number of edges --> use later as index
00123     Eigen::VectorXi row_cumsum = row_sum;
00124     for (int i = 1; i < row_sum.rows(); ++i) {
00125         row_cumsum(i) = row_sum(i) + row_cumsum(i - 1);
00126     }
00127     multinode_mapping = row_cumsum;
00128 
00129     //new matrices
00130     new_adj_bool = Eigen::MatrixXi::Zero(n_new_nodes, n_new_nodes);
00131     new_adj_float = Eigen::MatrixXf::Ones(n_new_nodes, n_new_nodes) * max_adjacency_; //all edges not computed have high cost --> not connected
00132 
00133     float sum_assigned_weights = 0;
00134     int curr_edge_index = 0;
00135 
00136     //iterate over all nodes - save the cost
00137     for (int i = 0; i < n_nodes; ++i) {
00138 
00139         int local_edge_nb = -1;
00140         //introduce new node for each edge of the current node
00141         for (int j = 0; j < n_nodes; ++j) {
00142 
00143             //if there is an edge between node i and node j
00144             if (adj_bool(i, j) == 1) {
00145 
00146                 local_edge_nb++;
00147                 //get indexes of possible nodes in multinode b where edges could end
00148                 int n2_start = 0;
00149                 if (j != 0) {
00150                     n2_start = row_cumsum[j - 1];
00151                 }
00152 
00153                 //iterate over all possible ik configurations from patch i edge local_edge_nb
00154                 for (unsigned int k = 0; k < coll_free_ik[i][local_edge_nb].size(); ++k) {
00155                     //link to all configurations in patch j
00156                     for (unsigned int l = 0; l < tmp_ik[j].size(); ++l) {
00157 
00158                         float cost = 0;
00159                         if (dist_measure_ == "DIST") {
00160                             cost = traj_planner_.absJointConfigurationDist(coll_free_ik[i][local_edge_nb][k],
00161                                 tmp_ik[j][l]);
00162                         } else if (dist_measure_ == "TIME") {
00163                             cost = traj_planner_.jointConfigurationMinTravelTime(coll_free_ik[i][local_edge_nb][k],
00164                                 tmp_ik[j][l]);
00165                         } else {
00166                             ROS_ERROR("JointGTSPSolver::transformGraphToGTSP Unknown TSP version");
00167                         }
00168 
00169                         sum_assigned_weights = sum_assigned_weights + cost;
00170                         new_adj_float(curr_edge_index, n2_start + l) = cost;
00171                         new_adj_bool(curr_edge_index, n2_start + l) = 1;
00172 
00173                     }
00174                     curr_edge_index++;
00175                 }
00176             }
00177         }
00178     }
00179 
00180     //    //    //do all this for short jumps
00181     //    std::vector<std::vector<double> > tmp_ik2;
00182     //    for (unsigned int i = 0; i < coll_free_ik_.size(); ++i) {
00183     //        for (unsigned int j = 0; j < coll_free_ik_[i].size(); ++j) {
00184     //            for (unsigned int k = 0; k < coll_free_ik_[i][j].size(); ++k) {
00185     //                tmp_ik2.push_back(coll_free_ik_[i][j][k]);
00186     //            }
00187     //        }
00188     //    }
00189     //    for (unsigned int i = 0; i < new_adj_float.rows(); ++i) { //alle nodes
00190     //        for (unsigned int j = 0; j < new_adj_float.cols(); ++j) { //alle nodes
00191     //
00192     //            if (new_adj_float(i, j) > (max_adjacency_ - 0.0000001)) {
00193     //
00194     //                float cost = 0;
00195     //                if (dist_measure_ == "DIST") {
00196     //                    cost = traj_planner_.absJointConfigurationDist(tmp_ik2[i], tmp_ik2[j]);
00197     //                } else if (dist_measure_ == "TIME") {
00198     //                    cost = traj_planner_.jointConfigurationMinTravelTime(tmp_ik2[i], tmp_ik2[j]);
00199     //                } else {
00200     //                    ROS_ERROR("Unknown TSP version");
00201     //                }
00202     //                new_adj_float(i, j) = new_adj_float(i, j) + cost;
00203     //            }
00204     //        }
00205     //    }
00206 
00207     new_adj_float = new_adj_float + (Eigen::MatrixXf::Ones(n_new_nodes, n_new_nodes) * sum_assigned_weights);
00208 }
00209 
00210 void JointGTSPSolver::transformGTSPToTSP(const Eigen::VectorXi& multinode_mapping, Eigen::MatrixXi& adj_bool,
00211     Eigen::MatrixXf& adj_float) {
00212 
00213     int n_multinodes = multinode_mapping.rows();
00214     int n_nodes = adj_bool.rows();
00215 
00216     //iterate over all multinodes
00217     //assign zero cost to move to successor node in multinode
00218     for (int i = 0; i < n_multinodes; ++i) {
00219 
00220         //find all nodes in multinode
00221         int start = 0;
00222         if (i != 0) {
00223             start = multinode_mapping(i - 1);
00224         }
00225         int end = multinode_mapping(i) - 1;
00226 
00227         int curr_n_nodes = end - start + 1;
00228         if (curr_n_nodes == 1 || curr_n_nodes == 0) {
00229             ROS_WARN_STREAM(
00230                 "JointGTSPSolver::transformGTSPToTSP  failure " << curr_n_nodes << " " << i << " " << start << " " << multinode_mapping(i));
00231             continue;
00232         }
00233         Eigen::MatrixXi tmp_bool = Eigen::MatrixXi::Zero(curr_n_nodes, n_nodes);
00234         Eigen::MatrixXf tmp_float = Eigen::MatrixXf::Zero(curr_n_nodes, n_nodes);
00235 
00236         //shift/rotate the cost --> last line is now first
00237         tmp_bool.block(curr_n_nodes - 1, 0, 1, n_nodes) = adj_bool.block(start, 0, 1, n_nodes);
00238         tmp_float.block(curr_n_nodes - 1, 0, 1, n_nodes) = adj_float.block(start, 0, 1, n_nodes);
00239         tmp_bool.block(0, 0, curr_n_nodes - 1, n_nodes) = adj_bool.block(start + 1, 0, curr_n_nodes - 1, n_nodes);
00240         tmp_float.block(0, 0, curr_n_nodes - 1, n_nodes) = adj_float.block(start + 1, 0, curr_n_nodes - 1, n_nodes);
00241 
00242         //save back to the original matrix
00243         adj_bool.block(start, 0, curr_n_nodes, n_nodes) = tmp_bool.block(0, 0, tmp_bool.rows(), tmp_bool.cols());
00244         adj_float.block(start, 0, curr_n_nodes, n_nodes) = tmp_float;
00245 
00246         for (int j = start; j < end; ++j) {
00247             adj_bool(j, j + 1) = 1;
00248             adj_float(j, j + 1) = 0;
00249         }
00250         //link from end to start to close the cycle
00251         adj_bool(end, start) = 1;
00252         adj_float(end, start) = 0;
00253     }
00254 }
00255 
00256 void JointGTSPSolver::mapGTSPIndexToMultinode(const Eigen::VectorXi& multinode_mapping,
00257     const std::vector<unsigned int>& traj, std::vector<unsigned int>& multinode_traj) {
00258     multinode_traj.clear();
00259     int counter = 0;
00260     BOOST_FOREACH(unsigned int i, traj) {
00261         counter++;
00262         unsigned int j = 0;
00263 
00264         while (i >= multinode_mapping(j)) {
00265             j++;
00266         }
00267 
00268         if (multinode_traj.size() == 0) {
00269             multinode_traj.push_back(j);
00270         } else {
00271             //check if multinode has already been pushed in the last step
00272             if (multinode_traj[multinode_traj.size() - 1] != j) {
00273                 multinode_traj.push_back(j);
00274             }
00275         }
00276     }
00277 }
00278 
00279 unsigned int JointGTSPSolver::mapGTSPIndexToMultinode(const Eigen::VectorXi& multinode_mapping, unsigned int node) {
00280     unsigned int j = 0;
00281     while (node >= multinode_mapping(j)) {
00282         j++;
00283     }
00284     return j;
00285 }
00286 
00287 void JointGTSPSolver::getJointPoses(const Eigen::VectorXi& multinode_mapping, const std::vector<unsigned int>& traj,
00288     std::vector<std::vector<double> >& joint_path) {
00289     joint_path.clear();
00290     std::vector<std::vector<double> > tmp_ik;
00291     for (unsigned int i = 0; i < coll_free_ik_.size(); ++i) {
00292         for (unsigned int j = 0; j < coll_free_ik_[i].size(); ++j) {
00293             for (unsigned int k = 0; k < coll_free_ik_[i][j].size(); ++k) {
00294                 tmp_ik.push_back(coll_free_ik_[i][j][k]);
00295             }
00296         }
00297     }
00298 
00299     for (unsigned int i = 0; i < traj.size() - 1; ++i) {
00300         int curr_multinode = mapGTSPIndexToMultinode(multinode_mapping, traj[i]);
00301 
00302         if (i == 0) {
00303             joint_path.push_back(tmp_ik[traj[i]]);
00304         } else {
00305             int last_multinode = mapGTSPIndexToMultinode(multinode_mapping, traj[i - 1]);
00306             if (curr_multinode != last_multinode) {
00307                 joint_path.push_back(tmp_ik[traj[i]]);
00308             }
00309         }
00310     }
00311     //push_back last node as this one must lead back to the start position
00312     //  joint_path.push_back(tmp_ik[traj[traj.size() - 1]]); TODO:check if correct
00313 
00314 }
00315 
00316 void JointGTSPSolver::getActions(const std::vector<unsigned int>& traj, std::vector<unsigned int>& actions) {
00317 
00318     actions.clear();
00319 
00320     for (unsigned int i = 0; i < traj.size(); ++i) {
00321         if (i < (traj.size() - 1)) {
00322             if (adjacency_(traj[i], traj[i + 1]) == 1) {
00323                 actions.push_back(0);
00324             } else {
00325                 actions.push_back(1);
00326             }
00327         } else {
00328             actions.push_back(1); // we are at the last node - thus use planning to get to the final pose
00329         }
00330     }
00331 }
00332 void JointGTSPSolver::insertStartIntoWeights(const Eigen::MatrixXf& weights, const Eigen::VectorXi& multinode_mapping,
00333     Eigen::MatrixXf& new_weights) {
00334 
00335     std::vector<std::vector<double> > tmp_ik;
00336     for (unsigned int i = 0; i < coll_free_ik_.size(); ++i) {
00337         for (unsigned int j = 0; j < coll_free_ik_[i].size(); ++j) {
00338             for (unsigned int k = 0; k < coll_free_ik_[i][j].size(); ++k) {
00339                 tmp_ik.push_back(coll_free_ik_[i][j][k]);
00340             }
00341         }
00342     }
00343 
00344     new_weights = Eigen::MatrixXf::Ones(weights.rows() + 1, weights.rows() + 1) * max_adjacency_;
00345     for (int i = 1; i < new_weights.rows(); ++i) {
00346 
00347         if (dist_measure_ == "DIST") {
00348             double cost = traj_planner_.absJointConfigurationDist(start_joint_, tmp_ik[i - 1]);
00349             new_weights(i, 0) = cost;
00350             new_weights(0, i) = new_weights(i, 0);
00351         } else if (dist_measure_ == "TIME") {
00352             double cost = traj_planner_.jointConfigurationMinTravelTime(start_joint_, tmp_ik[i - 1]);
00353             new_weights(i, 0) = cost;
00354             new_weights(0, i) = new_weights(i, 0);
00355         } else {
00356             ROS_ERROR("JointGTSPSolver::transformGraphToGTSP Unknown TSP version");
00357         }
00358     }
00359 
00360     new_weights.block(1, 1, weights.rows(), weights.cols()) = weights.block(0, 0, weights.rows(), weights.cols());
00361 }
 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