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
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());
00045 for (unsigned int i = 0; i < traj.size(); ++i) {
00046 traj[i] = traj[i] - 1;
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
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
00062 int local_edge_nb = -1;
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]);
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]);
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
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) {
00113 for (unsigned int j = 0; j < coll_free_ik[i].size(); ++j) {
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
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
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_;
00132
00133 float sum_assigned_weights = 0;
00134 int curr_edge_index = 0;
00135
00136
00137 for (int i = 0; i < n_nodes; ++i) {
00138
00139 int local_edge_nb = -1;
00140
00141 for (int j = 0; j < n_nodes; ++j) {
00142
00143
00144 if (adj_bool(i, j) == 1) {
00145
00146 local_edge_nb++;
00147
00148 int n2_start = 0;
00149 if (j != 0) {
00150 n2_start = row_cumsum[j - 1];
00151 }
00152
00153
00154 for (unsigned int k = 0; k < coll_free_ik[i][local_edge_nb].size(); ++k) {
00155
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
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
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
00217
00218 for (int i = 0; i < n_multinodes; ++i) {
00219
00220
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
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
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
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
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
00312
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);
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 }