diff --git a/include/laser/processor/processor_tracker_feature_polyline_2D.h b/include/laser/processor/processor_tracker_feature_polyline_2D.h index 56ccd7f01fce1ffd02cd535c8181ad4afacdb073..9ed7379c50cd0fe484e6b9e4970fd72f72bf4dab 100644 --- a/include/laser/processor/processor_tracker_feature_polyline_2D.h +++ b/include/laser/processor/processor_tracker_feature_polyline_2D.h @@ -67,6 +67,7 @@ class ProcessorTrackerFeaturePolyline2D : public ProcessorTrackerFeature FeatureBasePtrList untracked_features_incoming_, untracked_features_last_; LandmarkMatchPolyline2DMap landmark_match_map_; LandmarkPolyline2DPtrList modified_lmks_; + std::set<LandmarkBasePtr> new_landmarks_; std::list<LandmarkPolyline2DPtrList> merge_candidates_list_; Eigen::Matrix2s R_sensor_world_last_, R_world_sensor_last_; diff --git a/src/landmark/landmark_match_polyline_2D.cpp b/src/landmark/landmark_match_polyline_2D.cpp index add363ba36bf6a26c5191bfff801d867ff565ecb..0b2bb446741b79c23f5cc53ce731067fcdf37b02 100644 --- a/src/landmark/landmark_match_polyline_2D.cpp +++ b/src/landmark/landmark_match_polyline_2D.cpp @@ -45,7 +45,7 @@ bool LandmarkMatchPolyline2D::isDeprecated() const { assert(pl_landmark_ != nullptr); - return landmark_version_ != pl_landmark_->getVersion() || pl_landmark_->getMergedInLandmark() != nullptr; + return pl_landmark_->isRemoving() || landmark_version_ != pl_landmark_->getVersion() || pl_landmark_->getMergedInLandmark() != nullptr; } bool LandmarkMatchPolyline2D::isPartialFront() const diff --git a/src/landmark/landmark_polyline_2D.cpp b/src/landmark/landmark_polyline_2D.cpp index ce4164acecde747c6249961c06a4dbf1138880e9..eb1d75fb5944b2df43b42460413d8c8902bc83a3 100644 --- a/src/landmark/landmark_polyline_2D.cpp +++ b/src/landmark/landmark_polyline_2D.cpp @@ -1000,6 +1000,7 @@ void LandmarkPolyline2D::tryMergeLandmarks(LandmarkPolyline2DPtrList& _lmk_list, // 2 by 2 LandmarkPolyline2DPtr remaining_lmk = _lmk_list.front(); _lmk_list.pop_front(); + assert(!remaining_lmk->isRemoving()); LandmarkPolyline2DPtr lmk_1, lmk_2, merged_lmk; int remaining_from, remaining_to, merged_from, merged_to; diff --git a/src/processor/processor_tracker_feature_polyline_2D.cpp b/src/processor/processor_tracker_feature_polyline_2D.cpp index 4fea24612b2c726dcbf5bf05574210f155a26201..b4bcdabceafb59835fd6a7852acb6fb4b4e4d115 100644 --- a/src/processor/processor_tracker_feature_polyline_2D.cpp +++ b/src/processor/processor_tracker_feature_polyline_2D.cpp @@ -28,7 +28,7 @@ unsigned int ProcessorTrackerFeaturePolyline2D::trackFeatures(const FeatureBaseP FeatureBasePtrList& _features_out, FeatureMatchMap& _feature_correspondences) { - WOLF_DEBUG("PTFP ", getName(), "::trackFeatures ", _features_in.size()); + WOLF_DEBUG("PTFP ", getName(), "::trackFeatures ", _features_in.size()); if (_features_in.empty()) return 0; @@ -85,7 +85,7 @@ unsigned int ProcessorTrackerFeaturePolyline2D::trackFeatures(const FeatureBaseP if (!updateLandmarkMatch(landmark_match_map_[pl_last])) { // not successful update -> remove match and feature - //std::cout << "\t\t\tNot success: removing last feature " << pl_last->id() << " and removing landmark match\n"; + std::cout << "\t\t\tNot success: removing last feature " << pl_last->id() << " and removing landmark match\n"; landmark_match_map_.erase(pl_last); pl_last->remove(); continue; @@ -94,7 +94,7 @@ unsigned int ProcessorTrackerFeaturePolyline2D::trackFeatures(const FeatureBaseP // Landmark removed -> not valid match with landmark else if (pl_lmk->isRemoving()) { - //std::cout << "\t\t\tRemoved landmark, removing last feature " << pl_last->id() << " and removing landmark match\n"; + std::cout << "\t\t\tRemoved landmark " << pl_lmk->id() << " removing last feature " << pl_last->id() << " and removing landmark match\n"; landmark_match_map_.erase(pl_last); pl_last->remove(); continue; @@ -147,7 +147,7 @@ unsigned int ProcessorTrackerFeaturePolyline2D::trackFeatures(const FeatureBaseP ftr_it++; } - // WOLF_DEBUG(_feature_correspondences.size(), " features tracked"); + WOLF_DEBUG(_feature_correspondences.size(), " features tracked"); return _feature_correspondences.size(); } @@ -155,7 +155,7 @@ bool ProcessorTrackerFeaturePolyline2D::correctFeatureDrift(const FeatureBasePtr const FeatureBasePtr _last_feature, FeatureBasePtr _incoming_feature) { - WOLF_DEBUG("PTFP ", getName(), "::correctFeatureDrift: "); + WOLF_DEBUG("PTFP ", getName(), "::correctFeatureDrift: "); /** After finding a valid feature match last-incoming, we have to check that the concatenated match * incoming-landmark is also valid. @@ -183,14 +183,22 @@ bool ProcessorTrackerFeaturePolyline2D::correctFeatureDrift(const FeatureBasePtr // COMPLETE PARTIAL MATCH if (!tryCompletePartialMatch(lmk_inc_match)) { - WOLF_WARN("correctFeatureDrift: tryCompletePartialMatch didn't success"); + WOLF_WARN("correctFeatureDrift: tryCompletePartialMatch didn't success, removing..", "last ", last_ptr_->id(), " incoming ", incoming_ptr_->id(), " landmark ", pl_lmk->id()); + landmark_match_map_.erase(_incoming_feature); + return false; + } + + // FILTER OUT matches that does not pass check + if (!lmk_inc_match->check()) + { + WOLF_WARN("correctFeatureDrift: match didn't pass the check, removing..", "last ", last_ptr_->id(), " incoming ", incoming_ptr_->id(), " landmark ", pl_lmk->id()); landmark_match_map_.erase(_incoming_feature); return false; } // CORRECT DRIFT // feature landmark transformation - // WOLF_DEBUG("try update match..."); + WOLF_DEBUG("try update match..."); tryUpdateMatchTransformation(lmk_inc_match); // RETRY LANDMARK-MATCH IF TOO MUCH ERROR @@ -203,7 +211,7 @@ bool ProcessorTrackerFeaturePolyline2D::correctFeatureDrift(const FeatureBasePtr // not succeed if (lmk_matches.empty()) { - WOLF_WARN("correctFeatureDrift: tryMatchWithLandmark didn't success"); + WOLF_WARN("correctFeatureDrift: tryMatchWithLandmark didn't success, removing..", "last ", last_ptr_->id(), " incoming ", incoming_ptr_->id(), " landmark ", pl_lmk->id()); landmark_match_map_.erase(_incoming_feature); return false; } @@ -300,12 +308,12 @@ bool ProcessorTrackerFeaturePolyline2D::voteForKeyFrame() unsigned int ProcessorTrackerFeaturePolyline2D::processNew(const int& _max_features) { - // WOLF_DEBUG("PTFP ", getName(), "::processNew: "); + WOLF_DEBUG("PTFP ", getName(), "::processNew: "); // PT::processNew() ========================================================== unsigned int n = ProcessorTrackerFeature::processNew(_max_features); // implicit call to detectNewFeatures() and trackFeatures() - // WOLF_DEBUG("Processing ", n, " new last features"); + WOLF_DEBUG("Processing ", n, " new last features"); // prior transformations Eigen::Matrix3s T_sensor_world_last(Eigen::Matrix3s::Identity()); @@ -314,7 +322,6 @@ unsigned int ProcessorTrackerFeaturePolyline2D::processNew(const int& _max_featu // MATCH or EMPLACE LANDMARKS ========================================================== // For each new last feature: Either emplace a landmark or match with an existent landmark - LandmarkBasePtrList new_landmarks; for (auto ftr : new_features_last_) { // not matched feature @@ -327,7 +334,7 @@ unsigned int ProcessorTrackerFeaturePolyline2D::processNew(const int& _max_featu // SEARCH: Check matching with all existing landmarks for (auto lmk : getProblem()->getMap()->getLandmarkList()) // Check only polyline landmarks that hasn't been just emplaced - if (lmk->getType() == "POLYLINE 2D" && std::find(new_landmarks.begin(), new_landmarks.end(), lmk) == new_landmarks.end()) + if (lmk->getType() == "POLYLINE 2D" && new_landmarks_.count(lmk) == 0) // Store all matches consistent with T_sensor_world_last in best_lmk_matches sorted by difference from T_sensor_world_last tryMatchWithLandmark(best_lmk_matches, std::static_pointer_cast<LandmarkPolyline2D>(lmk), pl_ftr, T_sensor_world_last); @@ -358,9 +365,12 @@ unsigned int ProcessorTrackerFeaturePolyline2D::processNew(const int& _max_featu assert((new_lmk_match->computeSqDistArray() < Constants::EPS).all()); // Store in new_landmarks - new_landmarks.push_back(new_lmk_ptr); + new_landmarks_.insert(new_lmk_ptr); + // store match in map landmark_match_map_[pl_ftr] = new_lmk_match; + + WOLF_DEBUG("New landmark ", new_lmk_ptr->id(), " created. Matching with feature ", pl_ftr->id()); } // MATCH else @@ -417,7 +427,7 @@ unsigned int ProcessorTrackerFeaturePolyline2D::detectNewFeatures(const int& _ma const CaptureBasePtr& _capture, FeatureBasePtrList& _features_out) { - WOLF_DEBUG("PTFP ", getName(), "::detectNewFeatures (", untracked_features_last_.size(), " in untracked_features_last_)"); + WOLF_DEBUG("PTFP ", getName(), "::detectNewFeatures (", untracked_features_last_.size(), " in untracked_features_last_)"); // move all already created features (in preProcess()) _features_out = std::move(untracked_features_last_); @@ -437,59 +447,66 @@ unsigned int ProcessorTrackerFeaturePolyline2D::detectNewFeatures(const int& _ma void ProcessorTrackerFeaturePolyline2D::establishFactors() { - WOLF_DEBUG("PTFP ", getName(), "::establishFactors: "); + WOLF_DEBUG("PTFP ", getName(), "::establishFactors: "); unsigned int N_factors = 0; // Create a factor for each match in last features FeatureBasePtrList last_features = last_ptr_->getFeatureList(); for (auto ftr : last_features) { - // WOLF_DEBUG("\tLast feature: ", ftr->id()); assert(landmark_match_map_.count(ftr) && "feature without landmark match in last features"); auto lmk_match = landmark_match_map_[ftr]; auto pl_lmk = lmk_match->pl_landmark_; auto pl_ftr = lmk_match->pl_feature_; assert(pl_ftr->id() == ftr->id()); - // WOLF_DEBUG("\tLandmark: ", pl_lmk->id()); + WOLF_DEBUG("Establishing factors for last feature: ", ftr->id(), " and landmark ", pl_lmk->id()); - // LANDMARK CHANGED: update match - // WOLF_DEBUG("\tLandmark changed?"); + // DEPRECATED MATCH: update match if (lmk_match->isDeprecated()) { - WOLF_DEBUG("\tLandmark changed or was merged, trying to update..."); + WOLF_DEBUG("\tLandmark was changed, merged or removed, trying to update..."); // not successful update if (!updateLandmarkMatch(lmk_match)) { - WOLF_DEBUG("\tUpdate didn't succeess, removing feature..."); + WOLF_DEBUG("\tUpdate didn't success, removing feature..."); // remove from match map landmark_match_map_.erase(ftr); // remove feature ftr->remove(); continue; } + else // landmark could be merged into another one, update the pointer + pl_lmk = lmk_match->pl_landmark_; } - // LANDMARK REMOVED: remove match and feature - else - { - // WOLF_DEBUG("\tLandmark removed?"); - if (pl_lmk->isRemoving()) - { - WOLF_DEBUG("\tLandmark was removed, removing feature..."); - // remove from match map - landmark_match_map_.erase(ftr); - // remove feature - ftr->remove(); - continue; - } + // CHECK + if (!lmk_match->check()) + { + WOLF_DEBUG("\tMatch check not passed, removing feature..."); + // remove from match map + landmark_match_map_.erase(ftr); + // remove feature + ftr->remove(); + continue; } // MODIFY LANDMARK (only for not closed and not recently emplaced) // WOLF_DEBUG("\tModifying.."); - if (!pl_lmk->isClosed() && pl_lmk->getHits() > 0) - // If modified, add lmk to modified_lmks_ list + if (!pl_lmk->isClosed() && new_landmarks_.count(pl_lmk) == 0) + { + // If modified, add lmk to modified_lmks_ list if (modifyLandmarkAndMatch(lmk_match)) - modified_lmks_.push_back(pl_lmk); + modified_lmks_.push_back(pl_lmk); + + //std::cout << "after modifyLandmarkAndMatchlandmark " << pl_lmk->id() << (pl_lmk->isClosed() ? " is closed" : " is new") << " matched with feature " << ftr->id() << std::endl; + + assert(lmk_match->feature_from_id_ == 0 && "Landmark didn't grow properly"); + assert(lmk_match->feature_to_id_ == pl_ftr->getNPoints()-1 && "Landmark didn't grow properly"); + assert(pl_lmk->getNPoints() >= pl_ftr->getNPoints() && "Landmark didn't grow properly"); + assert(lmk_match->check() && "Landmark didn't grow properly"); + } + //else + // std::cout << "landmark " << pl_lmk->id() << (pl_lmk->isClosed() ? " is closed" : " is new") << " matched with feature " << ftr->id() << std::endl; // ESTABLISH FACTORS // WOLF_DEBUG("\tEstablishing factors.."); @@ -549,6 +566,7 @@ void ProcessorTrackerFeaturePolyline2D::establishFactors() //std::cout << "landmark last id:" << pl_lmk->getLastId() << std::endl; //std::cout << "landmark n points:" << pl_lmk->getNPoints() << std::endl; emplaceFactorPoint(pl_ftr, pl_lmk, ftr_point_id, lmk_point_id); + assert(pl_lmk->getHits() != 0); N_factors++; // std::cout << "factor added" << std::endl; } @@ -557,6 +575,7 @@ void ProcessorTrackerFeaturePolyline2D::establishFactors() if (ftr_point_id < pl_ftr->getNPoints()-1) lmk_point_id=pl_lmk->getNextValidId(lmk_point_id); } + WOLF_DEBUG("landmark ", pl_lmk->id(), " has now ", pl_lmk->getHits(), " hits"); } // std::cout << N_factors << " factors established" << std::endl; } @@ -623,7 +642,7 @@ LandmarkBasePtr ProcessorTrackerFeaturePolyline2D::emplaceLandmark(FeatureBasePt bool ProcessorTrackerFeaturePolyline2D::modifyLandmarkAndMatch(LandmarkMatchPolyline2DPtr& lmk_match) { - WOLF_DEBUG("PTFP ", getName(), "::modifyLandmarkAndMatch: "); + WOLF_DEBUG("PTFP ", getName(), "::modifyLandmarkAndMatch: "); //lmk_match->print(); auto pl_lmk = lmk_match->pl_landmark_; auto pl_ftr = lmk_match->pl_feature_; @@ -786,7 +805,7 @@ bool ProcessorTrackerFeaturePolyline2D::modifyLandmarkAndMatch(LandmarkMatchPoly //if (print) // lmk_match->print(); -// + // WOLF_ERROR_COND((lmk_match->computeSqDistArray() >= 0.5).any(), // "landmark not properly aligned with feature: ", // lmk_match->computeSqDistArray().transpose() ); @@ -797,7 +816,7 @@ bool ProcessorTrackerFeaturePolyline2D::modifyLandmarkAndMatch(LandmarkMatchPoly void ProcessorTrackerFeaturePolyline2D::advanceDerived() { - //WOLF_DEBUG("PTFP ", getName(), "::advanceDerived: "); + WOLF_DEBUG("PTFP ", getName(), "::advanceDerived: "); // remove landmark matches with last features if (last_ptr_ != nullptr) for (auto ftr : last_ptr_->getFeatureList()) @@ -821,12 +840,15 @@ void ProcessorTrackerFeaturePolyline2D::advanceDerived() //WOLF_DEBUG("PTF ", getName(), ": untracked_features_last_ has ", untracked_features_last_.size() , " features (prev. untracked_features_incoming_)"); //WOLF_DEBUG_COND(last_ptr_!= nullptr, "PTF ", getName(), ": ", last_ptr_->getFeatureList().size(), " in last_ptr_)"); + // clear new_landmarks_ + new_landmarks_.clear(); + ProcessorTrackerFeature::advanceDerived(); } void ProcessorTrackerFeaturePolyline2D::resetDerived() { - //WOLF_DEBUG("PTFP ", getName(), "::resetDerived: "); + WOLF_DEBUG("PTFP ", getName(), "::resetDerived: "); // remove landmark matches with last features if (last_ptr_ != nullptr) for (auto ftr : last_ptr_->getFeatureList()) @@ -850,6 +872,9 @@ void ProcessorTrackerFeaturePolyline2D::resetDerived() //WOLF_DEBUG("PTF ", getName(), ": untracked_features_last_ has ", untracked_features_last_.size() , " features (prev. untracked_features_incoming_)"); //WOLF_DEBUG_COND(last_ptr_!= nullptr, "PTF ", getName(), ": ", last_ptr_->getFeatureList().size(), " in last_ptr_)"); + // clear new_landmarks_ + new_landmarks_.clear(); + ProcessorTrackerFeature::resetDerived(); } @@ -883,10 +908,11 @@ void ProcessorTrackerFeaturePolyline2D::preProcess() void ProcessorTrackerFeaturePolyline2D::postProcess() { - //WOLF_DEBUG("PTFP ", getName(), "::postProcess: "); + WOLF_DEBUG("PTFP ", getName(), "::postProcess: "); // Try to close & classify modified landmarks while (!modified_lmks_.empty()) { + WOLF_DEBUG("classifying and closing modified landmarks"); auto lmk_ptr = modified_lmks_.front(); modified_lmks_.pop_front(); @@ -903,20 +929,30 @@ void ProcessorTrackerFeaturePolyline2D::postProcess() // Try to merge landmarks while (!merge_candidates_list_.empty()) { + WOLF_DEBUG("merging landmarks..."); // load next list of candidates LandmarkPolyline2DPtrList merge_candidates = std::move(merge_candidates_list_.front()); merge_candidates_list_.pop_front(); // change already merged lmks with the corresponding remaining lmk - for (auto&& lmk : merge_candidates) - if (lmk->getMergedInLandmark() != nullptr) - lmk = lmk->getMergedInLandmark(); + auto lmk_it = merge_candidates.begin(); + while (lmk_it != merge_candidates.end()) + { + if ((*lmk_it)->isRemoving()) + { + lmk_it = merge_candidates.erase(lmk_it); + continue; + } + if ((*lmk_it)->getMergedInLandmark() != nullptr) + (*lmk_it) = (*lmk_it)->getMergedInLandmark(); + lmk_it++; + } // remove repeated lmks merge_candidates.sort(); merge_candidates.unique(); - if (merge_candidates.size() == 1) + if (merge_candidates.size() < 2) continue; // Merge landmarks candidates and accumulate the correspondence of merged to the remaining ones @@ -1162,6 +1198,12 @@ bool ProcessorTrackerFeaturePolyline2D::updateLandmarkMatch(LandmarkMatchPolylin // merged: update the pl_lmk pointer if (pl_lmk->getMergedInLandmark() != nullptr) pl_lmk = pl_lmk->getMergedInLandmark(); + // removed: not valid match + else if (pl_lmk->isRemoving()) + { + WOLF_DEBUG("updateLandmarkMatch: landmark was removed, returning false"); + return false; + } // try match with _feat_ptr again LandmarkMatchPolyline2DScalarMap new_lmk_matches; @@ -1191,9 +1233,9 @@ LandmarkMatchPolyline2DPtr ProcessorTrackerFeaturePolyline2D::concatenateFeature //WOLF_DEBUG("LANDMARK-LAST MATCH:"); //lmk_match_last->print(); - WOLF_WARN_COND((lmk_match_last->computeSqDistArray() >= 0.5).any(), - "before concatenateFeatureLandmarkMatches too much error: ", - lmk_match_last->computeSqDistArray().transpose() ); + //WOLF_WARN_COND((lmk_match_last->computeSqDistArray() >= 0.5).any(), + // "before concatenateFeatureLandmarkMatches too much error: ", + // lmk_match_last->computeSqDistArray().transpose() ); //assert((lmk_match_last->computeSqDistArray() < 0.5).all()); auto lmk_match_incoming = std::make_shared<LandmarkMatchPolyline2D>(); @@ -1254,9 +1296,9 @@ LandmarkMatchPolyline2DPtr ProcessorTrackerFeaturePolyline2D::concatenateFeature //WOLF_DEBUG("LANDMARK-INCOMING MATCH:"); //lmk_match_incoming->print(); - WOLF_WARN_COND((lmk_match_incoming->computeSqDistArray() >= 0.5).any(), - "after concatenateFeatureLandmarkMatches too much error: ", - lmk_match_incoming->computeSqDistArray().transpose() ); + //WOLF_WARN_COND((lmk_match_incoming->computeSqDistArray() >= 0.5).any(), + // "after concatenateFeatureLandmarkMatches too much error: ", + // lmk_match_incoming->computeSqDistArray().transpose() ); //assert((lmk_match_incoming->computeSqDistArray() < 0.5).all()); return lmk_match_incoming; @@ -1284,9 +1326,9 @@ bool ProcessorTrackerFeaturePolyline2D::tryUpdateMatchTransformation(LandmarkMat // "\n\tUpdated pose:", // T2pose2D(lmk_match->T_feature_landmark_).transpose()); - WOLF_WARN_COND((lmk_match->computeSqDistArray() >= 0.5).any(), - "after tryUpdateMatchTransformation too much error: ", - lmk_match->computeSqDistArray().transpose() ); + //WOLF_WARN_COND((lmk_match->computeSqDistArray() >= 0.5).any(), + // "after tryUpdateMatchTransformation too much error: ", + // lmk_match->computeSqDistArray().transpose() ); return true; }