Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "landmark.h"
00010 #include "misc2.h"
00011
00012 #ifdef DO_FEATURE_OPTIMIZATION
00013
00014 #include "graph_manager.h"
00015
00016 #include "g2o/types/slam3d/parameter_camera.h"
00017
00018
00019
00020
00021 #include <utility>
00022 using namespace std;
00023
00024
00025
00026 MatchingResult removeStrangeMatches(const MatchingResult& match_result){
00027
00028
00029 map<int,int> good_inlier;
00030 for (uint i=0; i<match_result.inlier_matches.size(); ++i){
00031 cv::DMatch m = match_result.inlier_matches[i];
00032 good_inlier[m.trainIdx] = m.queryIdx;
00033 }
00034
00035
00036 map<int,int> final_inlier;
00037 for (map<int,int>::iterator it = good_inlier.begin(); it != good_inlier.end(); ++it){
00038 final_inlier[it->second] = it->first;
00039 }
00040
00041
00042 MatchingResult cleaned; cleaned.inlier_matches.reserve(good_inlier.size());
00043 for (map<int,int>::iterator it = final_inlier.begin(); it != final_inlier.end(); ++it){
00044 cv::DMatch m;
00045 m.trainIdx = it->second; m.queryIdx=it->first;
00046 cleaned.inlier_matches.push_back(m);
00047 }
00048
00049 ROS_INFO("Cleaning: removed %zu matches from %zu", match_result.inlier_matches.size()-good_inlier.size(), match_result.inlier_matches.size() );
00050
00051 return cleaned;
00052
00053
00054
00055 }
00056
00057
00058
00059 void GraphManager::removeFeaturesFromGraph(){
00060
00061
00062
00063
00064
00065 for (uint i=0; i<landmarks.size(); ++i){
00066 if (landmarks[i].g2o_vertex){
00067 optimizer_->removeVertex(landmarks[i].g2o_vertex);
00068 landmarks[i].g2o_vertex = NULL;
00069 }
00070
00071 }
00072
00073 for (EdgeSet_it it = cam_lm_edges.begin(); it != cam_lm_edges.end(); ++it){
00074 optimizer_->removeEdge(*it);
00075 }
00076
00077 }
00078
00079
00080 void GraphManager::printLandmarkStatistic(){
00081
00082 float mean_obs_cnt = 0;
00083 uint lm_cnt = landmarks.size();
00084 if (lm_cnt == 0) return;
00085
00086 for (uint i=0; i<lm_cnt; ++i){
00087 Landmark *lm = &landmarks[i];
00088
00089 mean_obs_cnt += (lm->observations.size()*1.0/lm_cnt);
00090 }
00091
00092 ROS_WARN("%i Landmarks with mean of %.2f observations", lm_cnt, mean_obs_cnt);
00093 }
00094
00095
00096
00097 void GraphManager::updateLandmarkInGraph(Landmark* lm){
00098
00099
00100
00101 if (!lm->g2o_vertex){
00102 int node_id = lm->observations.begin()->first;
00103 int feature_id = lm->observations.begin()->second;
00104 Node *n = graph_[node_id];
00105 g2o::VertexSE3* v1 = dynamic_cast<g2o::VertexSE3*>(optimizer_->vertex(n->vertex_id_ ));
00106
00107 assert(v1);
00108 assert(int(n->feature_locations_3d_.size()) > feature_id);
00109
00110 Eigen::Vector4f pos_relative = n->feature_locations_3d_[feature_id];
00111 if(isnan(pos_relative(2))){
00112 pos_relative(2) = 1.0;
00113 return;
00114 }
00115 Eigen::Vector3d pos_absolute = v1->estimate()*Eigen::Vector3d(pos_relative[0],pos_relative[1],pos_relative[2]);
00116
00117 lm->g2o_vertex = new LM_vertex_type();
00118 lm->g2o_vertex->setId(next_vertex_id++);
00119 lm->g2o_vertex->setFixed(false);
00120 lm->g2o_vertex->setEstimate(pos_absolute);
00121
00122 optimizer_->addVertex(lm->g2o_vertex);
00123 landmark_vertices.insert(lm->g2o_vertex);
00124 }
00125
00126
00127 if (lm->observations.size()>0){
00128
00129 for (std::map<int,int>::iterator it=lm->observations.begin(); it != lm->observations.end(); ++it){
00130 int node_id = it->first;
00131 int kpt = it->second;
00132
00133
00134
00135
00136 if (graph_.find(node_id) == graph_.end()){
00137 ROS_INFO("Trying to create projection to node %i which is not in the graph!", node_id);
00138 continue;
00139 }
00140
00141 Node * node = graph_[node_id];
00142 g2o::VertexSE3* v1 = dynamic_cast<g2o::VertexSE3*>(optimizer_->vertex(node->vertex_id_));
00143
00144
00145 assert(node->feature_locations_3d_.size() == node->feature_locations_2d_.size());
00146 assert(kpt < int(node->feature_locations_2d_.size()));
00147
00148
00149 Proj_edge_type* projectionEdge = new Proj_edge_type();
00150 cv::KeyPoint kp = node->feature_locations_2d_[kpt];
00151 Eigen::Vector4f pos_relative = node->feature_locations_3d_[kpt];
00152 if(!isnan(pos_relative(2))){
00153 projectionEdge->setMeasurement(Eigen::Vector3d(kp.pt.x,kp.pt.y,pos_relative[2]));
00154 Eigen::Matrix3d info_mat = point_information_matrix(pos_relative[2]);
00155 projectionEdge->setInformation(info_mat);
00156 } else {
00157 continue;
00158 projectionEdge->setMeasurement(Eigen::Vector3d(kp.pt.x,kp.pt.y,1.0));
00159 Eigen::Matrix3d info_mat = point_information_matrix(1e12);
00160 projectionEdge->setInformation(info_mat);
00161 }
00162 projectionEdge->setParameterId(0,0);
00163 projectionEdge->vertices()[0] = v1;
00164 projectionEdge->vertices()[1] = lm->g2o_vertex;
00165
00166
00167
00168
00169
00170
00171
00172
00173 optimizer_->addEdge(projectionEdge);
00174 lm->g2o_vertex->setFixed(false);
00175 cam_lm_edges.insert(projectionEdge);
00176
00177
00178 }
00179
00180
00181
00182 }
00183 }
00184
00185 void GraphManager::updateProjectionEdges(){
00186
00187
00188 for (uint i=0; i<landmarks.size(); ++i){
00189 Landmark *lm = &landmarks[i];
00190 updateLandmarkInGraph(lm);
00191
00192 }
00193
00194 ROS_WARN("Updated all Landmarks!");
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 }
00207
00208
00209
00210 void GraphManager::updateLandmarks(const MatchingResult& match_result, Node* old_node, Node* new_node){
00211
00212
00213
00214 assert(old_node && new_node);
00215 assert(int(old_node->id_) == match_result.edge.id1);
00216 assert(int(new_node->id_) == match_result.edge.id2);
00217
00218 MatchingResult cleaned = removeStrangeMatches(match_result);
00219
00220 for (uint i=0; i<cleaned.inlier_matches.size(); ++i)
00221 {
00222 cv::DMatch m = cleaned.inlier_matches[i];
00223
00224 std::map<int, int>::iterator it_old, it_new;
00225
00226 int lm_id_old = -1;
00227 int lm_id_new = -1;
00228
00229
00230
00231
00232
00233 it_old = old_node->kpt_to_landmark.find(m.trainIdx);
00234 if (it_old != old_node->kpt_to_landmark.end())
00235 lm_id_old = it_old->second;
00236
00237 it_new = new_node->kpt_to_landmark.find(m.queryIdx);
00238 if (it_new != new_node->kpt_to_landmark.end())
00239 lm_id_new = it_new->second;
00240
00241
00242
00243
00244
00245 if (lm_id_old == -1 && lm_id_new == -1){
00246
00247
00248
00249
00250
00251 Landmark lm;
00252 lm.id = next_landmark_id++;
00253
00254
00255
00256
00257
00258 lm.observations[old_node->id_] = m.trainIdx;
00259 lm.observations[new_node->id_] = m.queryIdx;
00260
00261
00262
00263 assert(lm.observations.size() == 2);
00264
00265
00266 old_node->kpt_to_landmark[m.trainIdx] = lm.id;
00267 new_node->kpt_to_landmark[m.queryIdx] = lm.id;
00268
00269
00270
00271
00272
00273
00274
00275 landmarks.push_back(lm);
00276 continue;
00277 }
00278
00279
00280 if (lm_id_old > -1 && lm_id_new == -1){
00281
00282 Landmark* lm = &landmarks[lm_id_old];
00283
00284 lm->observations[new_node->id_] = m.queryIdx;
00285
00286 new_node->kpt_to_landmark[m.queryIdx] = lm->id;
00287
00288 continue;
00289 }
00290
00291
00292 if (lm_id_old == -1 && lm_id_new > -1){
00293
00294 Landmark* lm = &landmarks[lm_id_new];
00295
00296 lm->observations[old_node->id_] = m.trainIdx;
00297
00298 old_node->kpt_to_landmark[m.trainIdx] = lm->id;
00299
00300 continue;
00301 }
00302
00303 assert(lm_id_old > -1 && lm_id_new > -1);
00304
00305
00306
00307 if (lm_id_new == lm_id_new){
00308
00309
00310
00311
00312
00313
00314 continue;
00315 }
00316
00317
00318
00319
00320
00321
00322 Landmark *lm_1 = &landmarks[lm_id_old];
00323 Landmark *lm_2 = &landmarks[lm_id_new];
00324
00325
00326 if (lm_1->observations.size() >= lm_2->observations.size()){
00327 mergeLandmarks(lm_1, lm_2);
00328 landmarks.erase(landmarks.begin()+lm_id_new);
00329 }else{
00330 mergeLandmarks(lm_2, lm_1);
00331 landmarks.erase(landmarks.begin()+lm_id_old);
00332 }
00333
00334 }
00335
00336 }
00337
00338
00339
00340
00341 void GraphManager::mergeLandmarks( Landmark *lm_1, Landmark *lm_del){
00342
00343 ROS_INFO("Merging lm %i (%zu pts) into lm %i (%zu pts)", lm_1->id, lm_1->observations.size(),lm_del->id, lm_del->observations.size());
00344
00345 int new_lm_id = lm_1->id;
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 for (std::map<int,int>::iterator it = lm_del->observations.begin(); it != lm_del->observations.end(); ++it){
00359 Node *n = graph_[it->first];
00360 int kpt = it->second;
00361
00362
00363
00364
00365
00366 n->kpt_to_landmark[kpt] = new_lm_id;
00367
00368
00369
00370 lm_1->observations[n->id_] = kpt;
00371
00372 }
00373
00374
00375
00376
00377
00378
00379 }
00380 #endif
00381