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