Jafar
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
dataManagerOnePointRansac.impl.hpp
Go to the documentation of this file.
00001 
00008 #include "kernel/misc.hpp"
00009 
00010 #include "jmath/randomIntTmplt.hpp"
00011 #include "jmath/misc.hpp"
00012 
00013 
00014 #include "rtslam/dataManagerOnePointRansac.hpp"
00015 #include "rtslam/kalmanTools.hpp"
00016 
00017 #include "rtslam/rtSlam.hpp"
00018 #include "rtslam/observationAbstract.hpp"
00019 
00020 #include "rtslam/imageTools.hpp"
00021 
00022 #include <algorithm>
00023 
00024 /*
00025  * STATUS: working fine, use it
00026  * Buffered update is faster than iterative update, but it doesn't allow
00027  * active search, so we use a mixed approach
00028  */
00029 #define BUFFERED_UPDATE 1
00030 
00031 /*
00032  * STATUS: working fine, use it
00033  * The goal is to improve performance by not computing jacobians
00034  * and covariance matrix for observations that are not visible
00035  * (but we compute twice the mean for those that are visible)
00036  * It brings approx 2% speedup
00037  */
00038 #define PROJECT_MEAN_VISIBILITY 1
00039 
00040 /*
00041  * STATUS: testing purpose
00042  * apply quaternion constraints in the filter after each update
00043  */
00044 #define APPLY_CONSTRAINTS 0
00045 
00046 #if RELEVANCE_TEST && RELEVANCE_TEST_P
00047   #error "RELEVANCE_TEST and RELEVANCE_TEST_P are incompatible!"
00048 #endif
00049 
00050 namespace jafar {
00051   namespace rtslam {
00052 
00053     bool compare_lmk_uncertainty(landmark_ptr_t const & lmkPtr1, landmark_ptr_t const & lmkPtr2)
00054     {
00055       double uncert1 = lmkPtr1->uncertainty();
00056       double uncert2 = lmkPtr2->uncertainty();
00057       if (uncert1 < uncert2) return true; else
00058         if (uncert1 == uncert2) return (lmkPtr1->countObserved() > lmkPtr2->countObserved()); else
00059         return false;
00060     }
00061 
00062     bool compare_obs_uncertainty(observation_ptr_t const & obsPtr1, observation_ptr_t const & obsPtr2)
00063     {
00064       return compare_lmk_uncertainty(obsPtr1->landmarkPtr(), obsPtr2->landmarkPtr());
00065     }
00066 
00067     template<class RawSpec,class SensorSpec, class FeatureSpec, class RoiSpec, class FeatureManagerSpec, class DetectorSpec, class MatcherSpec>
00068     void DataManagerOnePointRansac<RawSpec,SensorSpec,FeatureSpec,RoiSpec,FeatureManagerSpec,DetectorSpec,MatcherSpec>::
00069     processKnown(raw_ptr_t data, double date_limit)
00070     {
00071       const unsigned min_as_update = 2;
00072       int n_updates_ransac = algorithmParams.n_updates_ransac;
00073       // adapt number of ransac updates for this frame
00074       double date_begin = kernel::Clock::getTime();
00075       double time_available = date_limit - date_begin;
00076       if (date_limit > 0)
00077       {
00078         if (prev_average_as_update_time < prev_average_ransac_update_time) prev_average_ransac_update_time = prev_average_as_update_time; // to prevent long ransac update to stick
00079         if (prev_average_ransac_update_time > 0 && prev_average_as_update_time > 0)
00080           n_updates_ransac = (time_available - min_as_update*prev_average_as_update_time) / prev_average_ransac_update_time;
00081         else if (prev_average_ransac_update_time > 0) // if no estimate for as time, use ransac time
00082           n_updates_ransac = (time_available / prev_average_ransac_update_time) - min_as_update;
00083         if (n_updates_ransac <= 0) n_updates_ransac = (time_available / prev_average_ransac_update_time);
00084         if (n_updates_ransac <= 0) n_updates_ransac = 1; // do at least one update!
00085         if ((unsigned)n_updates_ransac > algorithmParams.n_updates_ransac) n_updates_ransac = algorithmParams.n_updates_ransac;
00086       }
00087       double average_ransac_update_time = kernel::Clock::getTime();
00088 
00089       boost::shared_ptr<RawSpec> rawData = SPTR_CAST<RawSpec>(data);
00090       //###
00091       //### Init, collect visible observations
00092       //### 
00093       map_ptr_t mapPtr = sensorPtr()->robotPtr()->mapPtr();
00094       unsigned numObs = 0, numObsRansac = 0;
00095 
00096       projectAndCollectVisibleObs();
00097       if (n_updates_ransac <= 0) return; // here to build visibleList and clearFlags in case next manage or detect steps are made afterwards
00098 
00099       unsigned n_tries = algorithmParams.n_tries;
00100       if (obsVisibleList.size() < n_tries) n_tries = obsVisibleList.size();
00101 
00102       
00103       //###
00104       //### Create the different Ransac sets
00105       //### 
00106       unsigned current_try = 0;
00107       if (n_tries >= 2)
00108       while (current_try < n_tries)
00109       {
00110         // select random obs and match it
00111         observation_ptr_t obsBasePtr;
00112         getOneMatchedBaseObs(obsBasePtr, rawData);
00113         if (!obsBasePtr) break; // no more available matched obs
00114 
00115         // 1b. base obs is now matched
00116         ransac_set_ptr_t ransacSetPtr(new RansacSet);
00117         ransacSetList.push_back(ransacSetPtr);
00118         ransacSetPtr->obsBasePtr = obsBasePtr;
00119         ransacSetPtr->add_inlier(obsBasePtr);
00120 
00121         current_try ++;
00122         vec x_copy = updateMean(obsBasePtr);
00123 
00124         JFR_VVDEBUG("Ransac try " << current_try << " with base obs " << obsBasePtr->id());
00125 
00126         // for each other obs
00127         for(ObsList::iterator obsIter = obsVisibleList.begin(); obsIter != obsVisibleList.end(); obsIter++)
00128         {
00129           observation_ptr_t obsCurrentPtr = *obsIter;
00130           if (obsCurrentPtr == obsBasePtr) continue; // ignore the tested observation
00131 
00132           // project
00133           ransac_exp.resize(obsCurrentPtr->expectation.size(), false);
00134           projectFromMean(ransac_exp, obsCurrentPtr, x_copy);
00135 
00136           bool inlier = obsCurrentPtr->events.matched && 
00137                         isLowInnovationInlier(obsCurrentPtr, ransac_exp, matcher->params.lowInnov);
00138 
00139           if (!inlier)
00140           {
00141             matchWithExpectedInnovation(rawData, obsCurrentPtr, true);
00142 
00143             inlier = obsCurrentPtr->events.matched &&
00144                      isLowInnovationInlier(obsCurrentPtr, ransac_exp, matcher->params.lowInnov);
00145           }
00146           
00147           if (inlier)
00148           {
00149             // declare inlier
00150             ransacSetPtr->add_inlier(obsCurrentPtr);
00151             JFR_VVDEBUG("Obs " << obsCurrentPtr->id() << " is inlier (@" << obsCurrentPtr->measurement.x() << " exp " << obsCurrentPtr->expectation.x() << ")");
00152           }
00153           else{
00154             // declare pending
00155             ransacSetPtr->pendingObs.push_back(obsCurrentPtr);
00156             JFR_VVDEBUG("Obs " << obsCurrentPtr->id() << " is pending (@" << (obsCurrentPtr->events.matched ? (jblas::vec)obsCurrentPtr->measurement.x() : (jblas::vec)jblas::zero_vec(2) ) << " exp " << obsCurrentPtr->expectation.x() << ")");
00157           }
00158         } // for each other obs
00159       } // for i = 0:n_tries
00160 
00161       // TODO we should also store the measurement when building the sets,
00162       // and take the right one when using the best set
00163 
00164       //###
00165       //### Process the best Ransac set
00166       //### 
00167       ransac_set_ptr_t best_set;
00168       bool pending_buffered_update = false;
00169       if (ransacSetList.size() != 0)
00170       {
00171         // 1. select ransacSet.inliers.size() max
00172         for(RansacSetList::iterator rsIter = ransacSetList.begin(); rsIter != ransacSetList.end(); ++rsIter)
00173           if (!best_set || (*rsIter)->size() > best_set->size()) best_set = *rsIter;
00174 
00175         // if there are too many updates to do bufferized, randomly move out some of them
00176         // to pending, they may be processed in active search if really necessary
00177         while (best_set->size() > 1 && best_set->size() > (unsigned)n_updates_ransac)
00178         {
00179           int n = (rtslam::rand() % (best_set->size() - 1)) + 1; // keep the first one which is the base obs
00180           best_set->pendingObs.push_back(best_set->inlierObs[n]);
00181           kernel::fastErase(best_set->inlierObs, n);
00182         }
00183 
00184         if (best_set->size() > 1)
00185         {
00186           // 2. for each obs in inliers
00187           JFR_DEBUG_BEGIN(); JFR_DEBUG_SEND("Updating with Ransac:");
00188           #if RELEVANCE_TEST || RELEVANCE_TEST_P
00189           double innovation_relevance = 0.0;
00190           #endif
00191           for(ObsList::iterator obsIter = best_set->inlierObs.begin(); obsIter != best_set->inlierObs.end(); ++obsIter)
00192           {
00193             observation_ptr_t obsPtr = *obsIter;
00194 
00195             // restore measurements and innovation that were used for ransac
00196             obsPtr->measurement = best_set->inlierMeasurements.at(obsPtr->id());
00197             obsPtr->computeInnovation();
00198 
00199             // 2a. add obs to buffer for EKF update
00200             #if BUFFERED_UPDATE
00201             mapPtr->filterPtr->stackCorrection(obsPtr->innovation, obsPtr->INN_rsl, obsPtr->ia_rsl);
00202             #if RELEVANCE_TEST || RELEVANCE_TEST_P
00203             innovation_relevance += obsPtr->computeRelevance();
00204             #endif
00205             #else
00206             obsPtr->project(multi_hyps_);
00207             obsPtr->computeInnovation();
00208             #if RELEVANCE_TEST
00209             if (obsPtr->computeRelevance() > jmath::sqr(matcher->params.relevanceTh))
00210             #endif
00211             {
00212               #if RELEVANCE_TEST_P
00213               obsPtr->update(obsPtr->computeRelevance() > jmath::sqr(matcher->params.relevanceTh));
00214               #else
00215               obsPtr->update();
00216               #endif
00217               obsPtr->events.updated = true;
00218               #if APPLY_CONSTRAINTS
00219               sensorPtr()->robotPtr()->applyConstraints();
00220               #endif
00221             }
00222             #endif
00223           }
00224           bool do_update = false;
00225           #if BUFFERED_UPDATE
00226           // 3. perform buffered update
00227           #if RELEVANCE_TEST || RELEVANCE_TEST_P
00228           innovation_relevance /= best_set->inlierObs.size();
00229           #endif
00230           #if RELEVANCE_TEST
00231           if (innovation_relevance > jmath::sqr(matcher->params.relevanceTh))
00232           #endif
00233           {
00234             #if RELEVANCE_TEST_P
00235             mapPtr->filterPtr->correctAllStacked(mapPtr->ia_used_states(), innovation_relevance > jmath::sqr(matcher->params.relevanceTh));
00236             #else
00237             mapPtr->filterPtr->correctAllStacked(mapPtr->ia_used_states());
00238             #endif
00239             #if APPLY_CONSTRAINTS
00240             sensorPtr()->robotPtr()->applyConstraints();
00241             #endif
00242             do_update = true;
00243           }
00244           #if RELEVANCE_TEST
00245           else pending_buffered_update = true;
00246           #endif
00247           
00248           #endif
00249           
00250           for(ObsList::iterator obsIter = best_set->inlierObs.begin(); obsIter != best_set->inlierObs.end(); ++obsIter)
00251             if (do_update || (*obsIter)->events.updated)
00252             {
00253               // Add to tesselation grid for active search
00254               //featMan->addObs(obsPtr->expectation.x(), obsPtr);
00255               numObs++; numObsRansac++;
00256               (*obsIter)->events.updated = true;
00257               JFR_DEBUG_SEND(" " << (*obsIter)->id());
00258               //JFR_DEBUG_VSEND(" @"<<(*obsIter)->measurement.x());
00259             } else
00260             {
00261               // TODO do that better with an insignificant flag
00262               (*obsIter)->events.measured = false;
00263               (*obsIter)->events.matched = false;
00264             }
00265           JFR_DEBUG_END();
00266         }
00267       }
00268 
00269       double date_now = kernel::Clock::getTime(), date_prev, time_update;
00270       average_ransac_update_time = date_now - average_ransac_update_time;
00271       if (numObsRansac > 0) prev_average_ransac_update_time = average_ransac_update_time / numObsRansac;
00272       double average_as_update_time = date_now;
00273       bool stop_no_time = false;
00274 
00275       //###
00276       //### Process some other observations with Active Search
00277       //### 
00278       ObsList activeSearchList = ((ransacSetList.size() == 0) || (best_set->size() <= 1) ? obsVisibleList : best_set->pendingObs);
00279       // FIXME don't search again landmarks that failed as base
00280       
00281       JFR_DEBUG_BEGIN(); JFR_DEBUG_SEND("Updating with ActiveSearch:");
00282       for (unsigned i = 0; i < algorithmParams.n_recomp_gains && !stop_no_time; ++i)
00283       {
00284         // 4. for each obs in pending: retake algorithm from active search
00285         for(ObsList::iterator obsIter = activeSearchList.begin(); obsIter != activeSearchList.end(); ++obsIter)
00286         {
00287           observation_ptr_t obsPtr = *obsIter;
00288           // FIXME maybe don't clear events and don't rematch if already did, especially if didn't reestimate
00289           obsPtr->clearFlags();
00290           obsPtr->measurement.matchScore = 0;
00291 
00292           // 1a. project
00293           obsPtr->project(multi_hyps_);
00294 
00295           // 1b. check visibility
00296           obsPtr->predictVisibility();
00297 
00298           if (obsPtr->isVisible()) {
00299 
00300             // Add to tesselation grid for active search
00301             //featMan->addObs(obsPtr->expectation.x(), obsPtr);
00302             
00303             /*
00304             quicly check if expectation has some negative variance values,
00305             to ignore the observation and prevent from crashing
00306             (it means that the filter is corrupted and that we should stop
00307             everything anyway)
00308             */
00309             bool valid = true;
00310             for (unsigned i = 0; i < obsPtr->expectation.P().size1(); ++i)
00311               if (obsPtr->expectation.P()(i,i) < 0.0) { valid = false; break; }
00312 
00313             if (valid)
00314             {
00315               // predict information gain
00316               obsPtr->predictInfoGain();
00317 
00318               // add to sorted list of observations
00319               obsListSorted[obsPtr->expectation.infoGain] = obsIter;
00320             }
00321           } // visible obs
00322         } // for each obs
00323 
00324         // loop only the N_UPDATES most interesting obs, from largest info gain to smallest
00325         for (ObservationListSorted::reverse_iterator obsIter = obsListSorted.rbegin();
00326           obsIter != obsListSorted.rend() && !stop_no_time; ++obsIter)
00327         {
00328           if (i != algorithmParams.n_recomp_gains-1 && obsIter != obsListSorted.rbegin()) break;
00329           date_prev = kernel::Clock::getTime();
00330           observation_ptr_t obsPtr = *(obsIter->second);
00331 
00332           // 1a. re-project to get up-to-date means and Jacobians
00333           if (obsIter != obsListSorted.rbegin()) obsPtr->project(multi_hyps_); // otherwise already projected right before
00334 
00335           // 1b. re-check visibility, just in case re-projection caused this obs to be invisible
00336           obsPtr->predictVisibility();
00337           if (obsPtr->isVisible())
00338           {
00339             if (numObs < algorithmParams.n_updates_total)
00340             {
00341               matchWithExpectedInnovation(rawData, obsPtr, false); // FIXME maybe don't rematch if already matched ?
00342               if (obsPtr->events.matched
00343               #if RELEVANCE_TEST
00344                       && obsPtr->computeRelevance() > jmath::sqr(matcher->params.relevanceTh)
00345               #endif
00346                  ) {
00347                 #if RELEVANCE_TEST
00348                 if (pending_buffered_update)
00349                 {
00350                   mapPtr->filterPtr->correctAllStacked(mapPtr->ia_used_states());
00351                   pending_buffered_update = false;
00352                   #if APPLY_CONSTRAINTS
00353                   sensorPtr()->robotPtr()->applyConstraints();
00354                   #endif
00355                   // TODO mark as updated
00356                 }
00357                 #endif
00358                 obsPtr->markUpdated();
00359                 numObs++;
00360                 JFR_DEBUG_SEND(" " << obsPtr->id());
00361                 //JFR_DEBUG_VSEND(" @"<<obsPtr->measurement.x());
00362                 //                kernel::Chrono update_chrono;
00363                 #if RELEVANCE_TEST_P
00364                 obsPtr->update(obsPtr->computeRelevance() > jmath::sqr(matcher->params.relevanceTh));
00365                 #else
00366                 obsPtr->update();
00367                 #endif
00368                 #if APPLY_CONSTRAINTS
00369                 sensorPtr()->robotPtr()->applyConstraints();
00370                 #endif
00371                 //                total_update_time += update_chrono.elapsedMicrosecond();
00372               }
00373             } // number of observations
00374           } // obsPtr->isVisible()
00375 
00376 
00377           // check if we need to stop because we don't have enough time
00378           if (obsPtr->events.updated && date_limit > 0)
00379           {
00380             date_now = kernel::Clock::getTime();
00381             time_update = date_now - date_prev;
00382             if (date_now+time_update > date_limit) { stop_no_time = true; break; }
00383           }
00384 
00385         } // foreach observation
00386 
00387         if (i+1 != algorithmParams.n_recomp_gains && obsListSorted.rbegin() != obsListSorted.rend())
00388           kernel::fastErase(activeSearchList, obsListSorted.rbegin()->second);
00389         obsListSorted.clear(); // clear the list now or it will prevent the observation to be destroyed until next frame, and will still be displayed
00390       }
00391       JFR_DEBUG_END();
00392 
00393       if (pending_buffered_update) mapPtr->filterPtr->clearStack();
00394 
00395       average_as_update_time = kernel::Clock::getTime() - average_as_update_time;
00396       if (numObs > numObsRansac) prev_average_as_update_time = average_as_update_time / (numObs-numObsRansac);
00397 
00398       // check duplicates
00399       updateVisibleObs();
00400       for(size_t i = 0; i < featMan->projections.size(); ++i)
00401       {
00402         int nkilled = 0;
00403         for(size_t j1 = 0; j1 < featMan->projections[i].size(); ++j1)
00404           if (featMan->projections[i][j1]->events.updated)
00405             for(size_t j2 = j1+1; j2 < featMan->projections[i].size(); ++j2)
00406               if (featMan->projections[i][j2]->events.updated)
00407                 if (ublasExtra::prod_xt_P_x(featMan->projections[i][j1]->measurement.P() + featMan->projections[i][j2]->measurement.P(),
00408                                             featMan->projections[i][j1]->measurement.x() - featMan->projections[i][j2]->measurement.x()) <= 3)
00409                   {
00410                     if (featMan->projections[i][j1]->landmarkPtr()->killed != LandmarkAbstract::kNo) break;
00411                     if (featMan->projections[i][j2]->landmarkPtr()->killed != LandmarkAbstract::kNo) continue; // test now to avoid testing it systematically above
00412                     nkilled++;
00413                     if (compare_obs_uncertainty(featMan->projections[i][j2], featMan->projections[i][j1]))
00414                       { featMan->projections[i][j1]->landmarkPtr()->killed = LandmarkAbstract::kDuplicate; break; } else
00415                       { featMan->projections[i][j2]->landmarkPtr()->killed = LandmarkAbstract::kDuplicate; continue; }
00416                   }
00417 /*
00418         const size_t max_obs_per_cell = 3;
00419         if (featMan->projections[i].size()-nkilled > max_obs_per_cell)
00420         {
00421           std::sort(featMan->projections[i].begin(), featMan->projections[i].end(), compare_obs_uncertainty);
00422           size_t n_ok = 0;
00423           for(size_t j = 0; j < featMan->projections[i].size(); ++j)
00424             if (featMan->projections[i][j]->landmarkPtr()->killed == LandmarkAbstract::kNo)
00425             {
00426               n_ok++;
00427               if (n_ok > max_obs_per_cell) featMan->projections[i][j]->landmarkPtr()->killed = LandmarkAbstract::kCellOverflow;
00428             }
00429         }
00430 */
00431       }
00432 
00433 
00434       //###
00435       //### Update obs counters and some other stuff
00436       //### 
00437       clearCounters();
00438       for(ObservationList::iterator obsIter = observationList().begin(); obsIter != observationList().end();obsIter++)
00439       {
00440         observation_ptr_t obs = *obsIter;
00441         if (obs->events.visible) JFR_ASSERT(obs->events.predicted, "obs visible without previous steps");
00442         if (obs->events.measured) JFR_ASSERT(obs->events.visible && obs->events.predicted, "obs measured without previous steps");
00443         if (obs->events.matched) JFR_ASSERT(obs->events.measured && obs->events.visible && obs->events.predicted, "obs matched without previous steps");
00444         if (obs->events.updated) JFR_ASSERT(obs->events.matched && obs->events.measured && obs->events.visible && obs->events.predicted, "obs updated without previous steps");
00445         
00446         obs->updateDescriptor();
00447         #if VISIBILITY_MAP
00448         obs->updateVisibilityMap();
00449         #endif
00450         
00451         if (obs->events.measured) obs->updatable = obs->events.updated;
00452         if (not (obs->events.measured && !obs->events.matched && !obs->isDescriptorValid()))
00453         {
00454           if (obs->events.measured) { obs->counters.nSearch++; counters.measured++; }
00455           if (obs->events.matched) { obs->counters.nMatch++; counters.matched++; }
00456           if (obs->events.updated) { obs->counters.nInlier++; counters.updated++; }
00457         }
00458         
00459         if (obs->events.measured) obs->counters.nSearchSinceLastInlier++;
00460         if (obs->events.visible) { obs->counters.nFrameSinceLastVisible = 0; counters.visible++; }
00461         if (obs->events.updated) obs->counters.nSearchSinceLastInlier = 0;
00462       }
00463 
00464       // clear all sets to liberate shared pointers
00465       ransacSetList.clear();
00466       obsBaseList.clear();
00467       obsFailedList.clear();
00468     }
00469 
00470 
00471     template<class RawSpec,class SensorSpec, class FeatureSpec, class RoiSpec, class FeatureManagerSpec, class DetectorSpec, class MatcherSpec>
00472     void DataManagerOnePointRansac<RawSpec,SensorSpec,FeatureSpec,RoiSpec,FeatureManagerSpec,DetectorSpec,MatcherSpec>::
00473     detectNew(raw_ptr_t data)
00474     {
00475       boost::shared_ptr<RawSpec> rawData = SPTR_CAST<RawSpec>(data);      
00476       updateVisibleObs();
00477       obsVisibleList.clear();
00478       for(unsigned i = 0; i < algorithmParams.n_init; )
00479       if (mapManagerPtr()->mapSpaceForInit()) {
00480         //boost::shared_ptr<RawImage> rawDataSpec = SPTR_CAST<RawImage>(rawData);
00481         RoiSpec roi;
00482         if (featMan->getRoi(roi)) {
00483           // FIXME if we already have searched some part of this roi without finding anything, we should not search again
00484           // this should be done in featMan, as long as no renew has been done, it remembers the getRoi, and detects when it is not followed by a addObs
00485 
00486           boost::shared_ptr<FeatureSpec> featPtr;
00487           if (detector->detect(rawData, roi, featPtr))
00488           {
00489             // 2a. Create the lmk and associated obs object.
00490             observation_ptr_t obsPtr =
00491                 mapManagerPtr()->createNewLandmark(shared_from_this());
00492 
00493             // 2b. fill data for this obs
00494             obsPtr->counters.nSearch = 1;
00495             obsPtr->counters.nMatch = 1;
00496             obsPtr->counters.nInlier = 1;
00497             obsPtr->events.visible = true;
00498             obsPtr->events.predicted = false;
00499             obsPtr->events.measured = true;
00500             obsPtr->events.matched = false;
00501             obsPtr->markUpdated();
00502             obsPtr->measurement = featPtr->measurement;
00503 
00504             // 2c. compute and fill stochastic data for the landmark
00505             obsPtr->backProject();
00506 
00507             // 2d. Create lmk descriptor
00508             detector->fillDataObs(featPtr, obsPtr);
00509 
00510             // FIXME maybe adjust roi to prevent from detecting points too close to edge compared to descriptor size
00511             // it would be better if we could check that the descriptor cannot be build before adding the landmark to the map...
00512             if (obsPtr->updateDescriptor())
00513             {
00514               #if VISIBILITY_MAP
00515               obsPtr->updateVisibilityMap();
00516               #endif
00517               featMan->addObs(obsPtr->measurement.x(), obsPtr);
00518               counters.created++;
00519               
00520 //#ifndef JFR_NDEBUG
00521 #if 0
00522               // check that point is correlated very close from the source (because of interpolation, and to check bugs)
00523               obsPtr->project(multi_hyps_);
00524               if (obsPtr->predictAppearance())
00525               {
00526                 jblas::sym_mat P = jblas::identity_mat(obsPtr->expectation.size())*jmath::sqr(4.0);
00527                 RoiSpec roi(obsPtr->expectation.x(), P, 1.0);
00528                 obsPtr->searchSize = roi.count();
00529                 matcher->match(rawData, obsPtr->predictedAppearance, roi, obsPtr->measurement, obsPtr->observedAppearance);
00530                 JFR_ASSERT(ublas::norm_2(obsPtr->measurement.x()-obsPtr->expectation.x()) <= 0.01);
00531               }
00532 #endif
00533               
00534               ++i;
00535             } else
00536             {
00537               obsPtr->landmarkPtr()->mapManagerPtr()->unregisterLandmark(obsPtr->landmarkPtr());
00538               featMan->setFailed(roi);
00539             }
00540           } else // create&init
00541           {
00542             featMan->setFailed(roi);
00543           }
00544         } else break; // getRoi()
00545       } else break; // if space in map
00546     } // detect()
00547 
00548 #if 0
00549     template<class RawSpec,class SensorSpec, class FeatureSpec, class RoiSpec, class FeatureManagerSpec, class DetectorSpec, class MatcherSpec>
00550     void DataManagerOnePointRansac<RawSpec,SensorSpec,FeatureSpec,RoiSpec,FeatureManagerSpec,DetectorSpec,MatcherSpec>::
00551     process( boost::shared_ptr<RawAbstract> data )
00552     {
00553         boost::shared_ptr<RawSpec> dataSpec = SPTR_CAST<RawSpec>(data);
00554         // 1. Observe known landmarks.
00555         processKnownObs(dataSpec); // process known landmarks
00556         // 2. Initialize new landmark.
00557         detectNewObs(dataSpec);
00558     }
00559 #endif
00560 
00561     template<class RawSpec,class SensorSpec, class FeatureSpec, class RoiSpec, class FeatureManagerSpec, class DetectorSpec, class MatcherSpec>
00562     void DataManagerOnePointRansac<RawSpec,SensorSpec,FeatureSpec,RoiSpec,FeatureManagerSpec,DetectorSpec,MatcherSpec>::
00563     projectAndCollectVisibleObs()
00564     {
00565       obsVisibleList.clear();
00566 
00567       for(ObservationList::iterator obsIter = observationList().begin(); obsIter != observationList().end();obsIter++)
00568       {
00569         observation_ptr_t obsPtr = *obsIter;
00570 
00571         obsPtr->clearFlags();
00572         obsPtr->counters.nFrameSinceLastVisible++;
00573         obsPtr->measurement.matchScore = 0;
00574 
00575         #if PROJECT_MEAN_VISIBILITY
00576         obsPtr->projectMean();
00577         #else
00578         obsPtr->project(multi_hyps_);
00579         #endif
00580         
00581         if (obsPtr->predictVisibility())
00582         {
00583           bool add;
00584           #if VISIBILITY_MAP
00585           double visibility, viscertainty;
00586           obsPtr->landmark().visibilityMap.estimateVisibility(obsPtr, visibility, viscertainty);
00587           add = false;
00588           if (visibility > 0.75 && viscertainty > 0.75) add = true; else
00589           if (!obsPtr->landmark().converged)
00590             { if (visibility < 0.25) visibility = 0.25; }
00591           else
00592             { if (visibility < 0.1) visibility = 0.1; } // allow closing the loop! maybe look at neighbors
00593           if (viscertainty < 0.25) visibility = 0.25;
00594           if (rtslam::rand()%1024 < visibility*1024) add = true;
00595           #else
00596           add = true;
00597           #endif
00598           
00599           if (add)
00600             obsVisibleList.push_back(obsPtr);
00601           //else std::cout << __FILE__ << ":" << __LINE__ << " ignore lmk " << obsPtr->id() << std::endl;
00602         } // visible obs
00603       } // for each obs
00604       remainingObsCount = obsVisibleList.size();
00605     }
00606 
00607     template<class RawSpec,class SensorSpec, class FeatureSpec, class RoiSpec, class FeatureManagerSpec, class DetectorSpec, class MatcherSpec>
00608     void DataManagerOnePointRansac<RawSpec,SensorSpec,FeatureSpec,RoiSpec,FeatureManagerSpec,DetectorSpec,MatcherSpec>::
00609     updateVisibleObs()
00610     {
00611       featMan->renew();
00612 
00613       for(ObsList::iterator obsIter = obsVisibleList.begin(); obsIter != obsVisibleList.end();obsIter++)
00614       { // don't recompute visibility to save time
00615         observation_ptr_t obsPtr = *obsIter;
00616         bool add = false;
00617         
00618         if (obsPtr->events.updated) add = true; else
00619         if (mapManagerPtr()->isExclusive(obsPtr)) add = true;
00620         // TODO with visibility stuff
00621         
00622         if (add && !obsPtr->events.killed)
00623           featMan->addObs(obsPtr->expectation.x(), obsPtr); // don't reproject to save time
00624       } // for each visible obs
00625     }
00626 
00627 
00628     template<class RawSpec,class SensorSpec, class FeatureSpec, class RoiSpec, class FeatureManagerSpec, class DetectorSpec, class MatcherSpec>
00629     void DataManagerOnePointRansac<RawSpec,SensorSpec,FeatureSpec,RoiSpec,FeatureManagerSpec,DetectorSpec,MatcherSpec>::
00630     getOneMatchedBaseObs(observation_ptr_t & obsBasePtr, boost::shared_ptr<RawSpec> rawData)
00631     {
00632       bool matchedBase = false;
00633       while (!matchedBase) {
00634         // select one random obs
00635 //        obsBasePtr = selectOneRandomObs();
00636         if (remainingObsCount <= 0) { obsBasePtr.reset(); return; }
00637         int n = rtslam::rand()%remainingObsCount;
00638         obsBasePtr = obsVisibleList[n];
00639 
00640 // JFR_DEBUG("getOneMatchedBaseObs: trying obs " << obsBasePtr->id() << " already matched " << obsBasePtr->events.matched);
00641         // try to match (if not yet matched)
00642         if (!obsBasePtr->events.matched)
00643         {
00644           obsBasePtr->events.measured = true;
00645 
00646           #if PROJECT_MEAN_VISIBILITY
00647           obsBasePtr->project(multi_hyps_);
00648           #endif
00649 
00650           if (!matchWithExpectedInnovation(rawData, obsBasePtr))
00651             obsFailedList.push_back(obsBasePtr);
00652 
00653 // JFR_DEBUG("getOneMatchedBaseObs: obs " << obsBasePtr->id() << " matched " << obsBasePtr->events.matched << " at " << obsBasePtr->measurement.x() << " predicted at " << obsBasePtr->expectation.x() << " with score " << obsBasePtr->getMatchScore());
00654         }
00655         if (obsBasePtr->events.matched && obsBasePtr->hypotheses.size() == 0) // multi hyp lmks are inefficient for ransac
00656         {
00657           obsBasePtr->computeInnovation();
00658           obsBaseList.push_back(obsBasePtr);
00659           matchedBase = true;
00660         }
00661         
00662         --remainingObsCount;
00663         obsVisibleList[n] = obsVisibleList[remainingObsCount];
00664         obsVisibleList[remainingObsCount] = obsBasePtr;
00665       }
00666     }
00667 
00668 
00669     template<class RawSpec,class SensorSpec, class FeatureSpec, class RoiSpec, class FeatureManagerSpec, class DetectorSpec, class MatcherSpec>
00670     vec DataManagerOnePointRansac<RawSpec,SensorSpec,FeatureSpec,RoiSpec,FeatureManagerSpec,DetectorSpec,MatcherSpec>::
00671     updateMean(const observation_ptr_t & obsPtr)
00672     {
00673       // get map things
00674       vec x_copy = mapManagerPtr()->mapPtr()->x();
00675       ind_array ia_x = mapManagerPtr()->mapPtr()->ia_used_states();
00676       sym_mat &P = mapManagerPtr()->mapPtr()->P();
00677 
00678       // compute Kalman gain
00679       mat K(ia_x.size(), obsPtr->innovation.size());
00680       kalman::computeKalmanGain(P, ia_x, obsPtr->innovation, obsPtr->INN_rsl, obsPtr->ia_rsl, K);
00681 
00682       // perform state update to the mean, get temporary copy
00683       ublas::project(x_copy, ia_x) += ublas::prod(K, obsPtr->innovation.x());
00684 
00685       return x_copy;
00686     }
00687 
00688 
00689     template<class RawSpec,class SensorSpec, class FeatureSpec, class RoiSpec, class FeatureManagerSpec, class DetectorSpec, class MatcherSpec>
00690     void DataManagerOnePointRansac<RawSpec,SensorSpec,FeatureSpec,RoiSpec,FeatureManagerSpec,DetectorSpec,MatcherSpec>::
00691     projectFromMean(vec & exp, const observation_ptr_t & obsPtr, const vec & x)
00692     {
00693       vec nobs;
00694 
00695       // get global sensor pose
00696       vec7 robPose = ublas::project(x, obsPtr->sensorPtr()->robotPtr()->pose.ia());
00697       vec7 senPose = obsPtr->sensorPtr()->pose.x(); // may be in the filter or not, the Gaussian pose points to the right data in both cases
00698       vec7 senGlobPose = quaternion::composeFrames(robPose, senPose);
00699 
00700       // project landmark
00701       vec lmk = ublas::project(x, obsPtr->landmarkPtr()->state.ia());
00702       obsPtr->model->project_func(senGlobPose, lmk, exp, nobs);
00703 
00704       // (we should not modify obsPtr->expectation because it has already been computed with initial prediction and will be used for full/base search)
00705     }
00706 
00707 
00708     template<class RawSpec,class SensorSpec, class FeatureSpec, class RoiSpec, class FeatureManagerSpec, class DetectorSpec, class MatcherSpec>
00709     bool DataManagerOnePointRansac<RawSpec,SensorSpec,FeatureSpec,RoiSpec,FeatureManagerSpec,DetectorSpec,MatcherSpec>::
00710     isLowInnovationInlier(const observation_ptr_t & obsPtr, const vec & exp, double lowInnTh)
00711     {
00712       vec inn;
00713       obsPtr->computeInnovationMean(inn, obsPtr->measurement.x(), exp);
00714       return (ublas::norm_2(inn) < lowInnTh);
00715     }
00716 
00717 
00718     template<class RawSpec,class SensorSpec, class FeatureSpec, class RoiSpec, class FeatureManagerSpec, class DetectorSpec, class MatcherSpec>
00719     bool DataManagerOnePointRansac<RawSpec,SensorSpec,FeatureSpec,RoiSpec,FeatureManagerSpec,DetectorSpec,MatcherSpec>::
00720     matchWithExpectedInnovation(boost::shared_ptr<RawSpec> rawData,  observation_ptr_t obsPtr, bool lowInnov)
00721     {
00722       if (obsPtr->predictAppearance())
00723       {
00724         RoiSpec roi;
00725 
00726         bool global_matched = false;
00727         double global_score = 0.0;
00728         bool use_hypotheses = (obsPtr->hypotheses.size() != 0 && !lowInnov);
00729         int count = (use_hypotheses ? obsPtr->hypotheses.size() : 1);
00730         for(int i = 0; i < count; ++i)
00731         {
00732           // build ROI
00733           Expectation &exp = (use_hypotheses ? obsPtr->hypotheses[i].expectation : obsPtr->expectation);
00734           if (exp.x().size() == 2) // basically DsegMatcher handles it's own roi and having a size4 expectation the following roi computation fails, hence the test
00735           {
00736             if (lowInnov)
00737             {
00738               jblas::sym_mat P = jblas::identity_mat(obsPtr->expectation.size())*jmath::sqr(matcher->params.lowInnov);
00739               roi = RoiSpec(ransac_exp, P, 2.0);
00740             } else
00741             {
00742               if (ublasExtra::det(exp.P()) > 5*jmath::sqr(matcher->params.maxSearchSize/jmath::sqr(matcher->params.mahalanobisTh)))
00743                 return false; // if bigger than 5 times the max, then don't even try, it will be deleted anyway
00744               obsPtr->measurement.searchP = matcher->params.measVar*identity_mat(2);
00745               roi = RoiSpec(exp.x(), exp.P() + obsPtr->measurement.searchP, matcher->params.mahalanobisTh);
00746             }
00747             obsPtr->searchSize = roi.count();
00748             if (obsPtr->searchSize > matcher->params.maxSearchSize) roi.scale(sqrt(matcher->params.maxSearchSize/(double)obsPtr->searchSize));
00749           }
00750           else // Segment
00751           {
00752             // Rough approximation, this won't be used by Dseg Matcher, only by the simulator
00753             vec2 p1, p2;
00754             vec2 var1, var2;
00755             p1[0] = exp.x()[0]; p1[1] = exp.x()[1];
00756             p2[0] = exp.x()[2]; p2[1] = exp.x()[3];
00757             obsPtr->measurement.searchP = matcher->params.measVar*identity_mat(4);
00758             var1[0] = (exp.P()(0,0) + matcher->params.measVar) * matcher->params.mahalanobisTh;
00759             var1[1] = (exp.P()(1,1) + matcher->params.measVar) * matcher->params.mahalanobisTh;
00760             var2[0] = (exp.P()(2,2) + matcher->params.measVar) * matcher->params.mahalanobisTh;
00761             var2[1] = (exp.P()(3,3) + matcher->params.measVar) * matcher->params.mahalanobisTh;
00762 
00763             int basex = min(p1[0]-var1[0],p2[0]-var2[0]);
00764             int basey = min(p1[1]-var1[1],p2[1]-var2[1]);
00765             cv::Rect rect(
00766               basex, basey,
00767               max(p1[0]+var1[0],p2[0]+var2[0]) - basex,
00768               max(p1[1]+var1[1],p2[1]+var2[1]) - basey
00769             );
00770             roi = RoiSpec(rect);
00771           }
00772 
00773           // match
00774           Measurement measurement(obsPtr->measurement.size());
00775           matcher->match(rawData, obsPtr->predictedAppearance, roi, measurement, obsPtr->observedAppearance);
00776           obsPtr->events.measured = true;
00777 
00778           // FIXME maybe replace this condition by multi hyp ? or not because linearity and ambiguity are different criteria
00779           double threshold = (lowInnov || obsPtr->landmark().converged || sqrt(jmath::sqr(roi.w()) + jmath::sqr(roi.h())) < matcher->params.hi_limit)*count ?
00780             matcher->params.threshold : matcher->params.hi_threshold;
00781 
00782           bool matched = false;
00783           if (obsPtr->events.matched && lowInnov)
00784             { if (measurement.matchScore >= obsPtr->getMatchScore()-1e-6) matched = true; } else // FIXME couldn't we do that even for not lowInnov ? not supposed to happen ?
00785             { if (measurement.matchScore >= threshold) matched = true; }
00786           if (use_hypotheses && measurement.matchScore < global_score-1e-6) matched = false;
00787 
00788           if (matched)
00789           {
00790             #if PROJECT_MEAN_VISIBILITY
00791             if (lowInnov && !obsPtr->events.predicted) obsPtr->project(false);
00792             #endif
00793 
00794             if (use_hypotheses)
00795               matched = ObservationAbstract::compatibilityTest(measurement, exp, matcher->params.mahalanobisTh);
00796             else
00797               matched = ObservationAbstract::compatibilityTest(measurement, obsPtr->expectation, matcher->params.mahalanobisTh);
00798           }
00799 
00800           if (matched)
00801           {
00802             obsPtr->measurement = measurement;
00803             global_matched = true;
00804             global_score = measurement.matchScore;
00805           }
00806         }
00807         if (global_matched) obsPtr->events.matched = true;
00808         return global_matched;
00809       } else
00810         return false;
00811     }
00812 
00813 
00814     template<class RawSpec,class SensorSpec, class FeatureSpec, class RoiSpec, class FeatureManagerSpec, class DetectorSpec, class MatcherSpec>
00815     void DataManagerOnePointRansac<RawSpec,SensorSpec,FeatureSpec,RoiSpec,FeatureManagerSpec,DetectorSpec,MatcherSpec>::
00816     dump(raw_ptr_t data)
00817     {
00818       LoggableMatchings *lm = new LoggableMatchings(data->name() + ".obs");
00819       for(ObservationList::iterator obsIter = observationList().begin(); obsIter != observationList().end();obsIter++)
00820       {
00821         observation_ptr_t obsPtr = *obsIter;
00822                 if (obsPtr->events.updated) lm->addMatching(obsPtr->id(), obsPtr->measurement.x(0), obsPtr->measurement.x(1));
00823       }
00824             if (loggerTask) loggerTask->push(lm);
00825     }
00826 
00827 
00828     template<class RawSpec,class SensorSpec, class FeatureSpec, class RoiSpec, class FeatureManagerSpec, class DetectorSpec, class MatcherSpec>
00829     void DataManagerOnePointRansac<RawSpec,SensorSpec,FeatureSpec,RoiSpec,FeatureManagerSpec,DetectorSpec,MatcherSpec>::
00830 		writeLogHeader(kernel::DataLogger& log) const
00831     {
00832       log.writeComment("DataManager");
00833       log.writeLegendTokens("visible measured matched updated created killed");
00834     }
00835 
00836     template<class RawSpec,class SensorSpec, class FeatureSpec, class RoiSpec, class FeatureManagerSpec, class DetectorSpec, class MatcherSpec>
00837     void DataManagerOnePointRansac<RawSpec,SensorSpec,FeatureSpec,RoiSpec,FeatureManagerSpec,DetectorSpec,MatcherSpec>::
00838 		writeLogData(kernel::DataLogger& log) const
00839     {
00840       log.writeData(counters.visible);
00841       log.writeData(counters.measured);
00842       log.writeData(counters.matched);
00843       log.writeData(counters.updated);
00844       log.writeData(counters.created);
00845       log.writeData(counters.killed);
00846     }
00847 
00848 
00849 
00850   } // namespace ::rtslam
00851 } // namespace jafar::
00852 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on Wed Oct 15 2014 00:37:26 for Jafar by doxygen 1.7.6.1
LAAS-CNRS