diff --git a/include/vision/processor/active_search.h b/include/vision/processor/active_search.h
index 56ce7004905d4374a7594604e31c7d5cd70043d7..fb79b623f37dff47aa24b98d162ae6da43c6de80 100644
--- a/include/vision/processor/active_search.h
+++ b/include/vision/processor/active_search.h
@@ -109,7 +109,7 @@ namespace wolf{
  * {
  *   obs->project();
  *   if (obs->isVisible())
- *     grid.hiCell(obs->expectation.x());   // add only visible landmarks
+ *     grid.hitCell(obs->pixel());   // add only visible landmarks
  * }
  *
  * // Then we process the selected observations
@@ -203,6 +203,7 @@ class ActiveSearchGrid {
 
         /**
          * \brief Add a projected pixel to the grid.
+         * If the cell is blocked, unblock and add.
          * \param _x the x-coordinate of the pixel to add.
          * \param _y the y-coordinate of the pixel to add.
          */
@@ -211,6 +212,7 @@ class ActiveSearchGrid {
 
         /**
          * \brief Add a projected pixel to the grid.
+         * If the cell is blocked, unblock and add.
          * \param _pix the pixel to add as an Eigen 2-vector with any Scalar type (can be a non-integer).
          */
         template<typename Scalar>
@@ -218,6 +220,7 @@ class ActiveSearchGrid {
 
         /**
          * \brief Add a projected pixel to the grid.
+         * If the cell is blocked, unblock and add.
          * \param _pix the pixel to add as a cv::KeyPoint.
          */
         void hitCell(const cv::KeyPoint& _pix);
@@ -229,6 +232,12 @@ class ActiveSearchGrid {
          */
         bool pickRoi(cv::Rect & _roi);
 
+        /**
+         * \brief Block a cell known to be empty in order to avoid searching again in it.
+         * \param _cell the cell where nothing was found
+         */
+        void blockCell(const Eigen::Vector2i & _cell);
+
         /**
          * \brief Call this after pickRoi if no point was found in the roi
          * in order to avoid searching again in it.
@@ -265,6 +274,17 @@ class ActiveSearchGrid {
          */
         bool pickEmptyCell(Eigen::Vector2i & _cell);
 
+        /**
+         * \brief Get the region of interest, reduced by a margin.
+         */
+        void cell2roi(const Eigen::Vector2i & _cell, cv::Rect& _roi);
+
+        /**
+         * \brief True if the cell is blocked
+         * \param _cell the queried cell
+         */
+        bool isCellBlocked(const Eigen::Vector2i& _cell);
+
 };
 
 inline void ActiveSearchGrid::clear()
@@ -297,8 +317,8 @@ inline void ActiveSearchGrid::hitCell(const Scalar _x, const Scalar _y)
     if (cell(0) < 0 || cell(1) < 0 || cell(0) >= grid_size_(0) || cell(1) >= grid_size_(1))
         return;
 
-    if (projections_count_(cell(0), cell(1)) == -1)
-        projections_count_(cell(0), cell(1)) = 0;
+    if (isCellBlocked(cell))
+        projections_count_(cell(0), cell(1)) = 0; // unblock cell: it becomes empty
 
     projections_count_(cell(0), cell(1))++;
 }
diff --git a/include/vision/processor/processor_visual_odometry.h b/include/vision/processor/processor_visual_odometry.h
index cce736b440362ce23ba4f04d28cd6ce788acb48d..aa006e1b905ac6b0957c7775730591fdaaf5957b 100644
--- a/include/vision/processor/processor_visual_odometry.h
+++ b/include/vision/processor/processor_visual_odometry.h
@@ -124,7 +124,7 @@ class ProcessorVisualOdometry : public ProcessorTracker
 {
     public:
         ProcessorVisualOdometry(ParamsProcessorVisualOdometryPtr _params_visual_odometry);
-        ~ProcessorVisualOdometry() override {};
+        virtual ~ProcessorVisualOdometry() override {};
 
         WOLF_PROCESSOR_CREATE(ProcessorVisualOdometry, ParamsProcessorVisualOdometry);
 
@@ -158,13 +158,16 @@ class ProcessorVisualOdometry : public ProcessorTracker
 
     public:
 
+        /**
+         * \brief Get params from sensor to finish processor setup
+         */
         void configure(SensorBasePtr _sensor) override;
 
-        /** Pre-process incoming Capture, see ProcessorTracker
+        /** \brief Pre-process incoming Capture, see ProcessorTracker
          */
         void preProcess() override;
 
-        /** Post-process, see ProcessorTracker
+        /** \brief Post-process, see ProcessorTracker
          */
         virtual void postProcess() override;
 
@@ -172,7 +175,8 @@ class ProcessorVisualOdometry : public ProcessorTracker
          */
         bool voteForKeyFrame() const override;
 
-        /** \brief Tracker function
+        /**
+         * \brief Tracker function
          * \return The number of successful tracks.
          *
          * see ProcessorTracker
@@ -180,19 +184,23 @@ class ProcessorVisualOdometry : public ProcessorTracker
         unsigned int processKnown() override;
 
 
-        /** \brief Process new Features or Landmarks
-         *
+        /**
+         * \brief Process new Features
+         * \param _max_features the maximum number of new feature tracks
+         * \return the number of new tracks
          */
         unsigned int processNew(const int& _max_features) override;
 
 
-        /**\brief Creates and adds factors from last_ to origin_
-         *
+        /**
+         * \brief Creates and adds factors from last_ to origin_
          */
         void establishFactors() override;
 
-        /**\brief Emplace a landmark corresponding to a track and initialize it with triangulation.
-         *
+        /**
+         * \brief Emplace a landmark corresponding to a track and initialize it with triangulation.
+         * \param _feature_ptr a pointer to the feature used to create the new landmark
+         * \return a pointer to the created landmark
          */
         LandmarkBasePtr emplaceLandmark(FeatureBasePtr _feature_ptr);
 
@@ -208,7 +216,13 @@ class ProcessorVisualOdometry : public ProcessorTracker
          */
         void resetDerived() override;
 
-        /** \brief Implementation of pyramidal KLT with openCV
+        /**
+         * \brief Implementation of pyramidal KLT with openCV
+         * \param img_prev previous image
+         * \param img_curr current image
+         * \param mwkps_prev keypoints in previous image
+         * \param mwkps_curr keypoints in current image, those tracked from the previous image
+         * \return a map with track associations
          */
         TracksMap kltTrack(const cv::Mat img_prev, const cv::Mat img_curr, const KeyPointsMap &mwkps_prev, KeyPointsMap &mwkps_curr);
 
diff --git a/src/processor/active_search.cpp b/src/processor/active_search.cpp
index 76abe9f868d315edc31cc09e953053dfe15027fd..e9006dfe617cac74802c11da0dcbf82d90524368 100644
--- a/src/processor/active_search.cpp
+++ b/src/processor/active_search.cpp
@@ -76,7 +76,8 @@ bool ActiveSearchGrid::pickEmptyCell(Eigen::Vector2i & _cell) {
         for (int j = 1; j < grid_size_(1) - 1; j++) {
             cell0(0) = i;
             cell0(1) = j;
-            if (projections_count_(i, j) == 0) {
+            if (projections_count_(i, j) == 0) // cell in empty AND not blocked
+            {
                 empty_cells_tile_tmp_(0,k) = i; //may be done in a better way
                 empty_cells_tile_tmp_(1,k) = j;
                 k++;
@@ -125,13 +126,23 @@ bool ActiveSearchGrid::pickRoi(cv::Rect & _roi) {
         return false;
 }
 
+void ActiveSearchGrid::blockCell(const cv::Rect & _cell)
+{
+    projections_count_(_cell(0), _cell(1)) = -1;
+}
+
 void ActiveSearchGrid::blockCell(const cv::Rect & _roi)
 {
     Eigen::Vector2i pix;
     pix(0) = _roi.x+_roi.width/2;
     pix(1) = _roi.y+_roi.height/2;
     Eigen::Vector2i cell = coords2cell(pix(0), pix(1));
-    projections_count_(cell(0), cell(1)) = -1;
+    blockCell(cell);
+}
+
+bool ActiveSearchGrid::isCellBlocked (const Eigen::Vector2i& _cell)
+{
+    return projections_count_(_cell(0), _cell(1)) < 0;
 }
 
 
diff --git a/src/processor/processor_visual_odometry.cpp b/src/processor/processor_visual_odometry.cpp
index c047f016a4fee58faa5e2a88bc9b8689693170e3..94459d620d11537a7db113963659fe96ada83a4a 100644
--- a/src/processor/processor_visual_odometry.cpp
+++ b/src/processor/processor_visual_odometry.cpp
@@ -76,6 +76,7 @@ TracksMap ProcessorVisualOdometry::mergeTracks(TracksMap tracks_prev_curr, Track
 
 void ProcessorVisualOdometry::preProcess()
 {
+
     auto t1 = std::chrono::system_clock::now();
     
     // Get Capture
@@ -137,7 +138,7 @@ void ProcessorVisualOdometry::preProcess()
         capture_image_incoming_->setTracksPrev(tracks_init);
 
         auto dt_preprocess = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - t1).count();
-        std::cout << "dt_preprocess (ms): " << dt_preprocess << std::endl;
+        WOLF_INFO( "dt_preprocess (ms): " , dt_preprocess );
 
         return;
     }
@@ -166,7 +167,9 @@ void ProcessorVisualOdometry::preProcess()
 
     // TracksMap between last and incoming
     // Input: ID of Wkp in last. Output: ID of the tracked Wkp in incoming.
+    WOLF_INFO( "Tracking " , mwkps_last.size(), " keypoints in last" );
     TracksMap tracks_last_incoming = kltTrack(img_last, img_incoming, mwkps_last, mwkps_incoming);
+    WOLF_INFO( "Tracked " , mwkps_incoming.size(), " keypoints to incoming" );
 
     // TracksMap between origin and last
     // Input: ID of Wkp in origin. Output: ID of the tracked Wkp in last.
@@ -175,6 +178,7 @@ void ProcessorVisualOdometry::preProcess()
     // Merge tracks to get TracksMap between origin and incoming
     // Input: ID of Wkp in origin. Output: ID of the tracked Wkp in incoming.
     TracksMap tracks_origin_incoming = mergeTracks(tracks_origin_last, tracks_last_incoming);
+    WOLF_INFO( "Merged " , tracks_last_incoming.size(), " tracks..." );
 
     // Outliers rejection with essential matrix
     cv::Mat E;
@@ -190,6 +194,7 @@ void ProcessorVisualOdometry::preProcess()
             }
         }
     }
+    WOLF_INFO( "Retained " , tracks_last_incoming_filtered.size(), " inliers..." );
 
     // Update captures
     capture_image_incoming_->addKeyPoints(mwkps_incoming);
@@ -204,10 +209,10 @@ void ProcessorVisualOdometry::preProcess()
     // detect new KeyPoints in last and track them to incoming
     ////////////////////////////////
     size_t n_tracks_origin = tracks_origin_incoming.size();
-    WOLF_TRACE("# of tracks: ", n_tracks_origin, "; min # of tracks: ", params_visual_odometry_->min_features_for_keyframe);
+    WOLF_INFO("# of tracks: ", n_tracks_origin, "; min # of tracks: ", params_visual_odometry_->min_features_for_keyframe);
     if (n_tracks_origin < params_visual_odometry_->min_features_for_keyframe){
 
-        WOLF_TRACE( "  Too Few Tracks" );
+        WOLF_INFO( "Too Few Tracks. Detecting more keypoints..." );
 
         // Erase all keypoints previously added to the cell grid
         cell_grid_.renew();
@@ -250,7 +255,6 @@ void ProcessorVisualOdometry::preProcess()
             }
         }
 
-
         WOLF_TRACE("Detected ", kps_last_new.size(), " new raw keypoints");
         
         // Create a map of wolf KeyPoints to track only the new ones
@@ -259,15 +263,16 @@ void ProcessorVisualOdometry::preProcess()
             WKeyPoint wkp(cvkp);
             mwkps_last_new[wkp.getId()] = wkp;
         }
-        WOLF_TRACE("Found ", mwkps_last_new.size(), " new keypoints");
+        WOLF_INFO("Found ", mwkps_last_new.size(), " keypoints in last that are new");
 
         TracksMap tracks_last_incoming_new = kltTrack(img_last, img_incoming, mwkps_last_new, mwkps_incoming_new);
+        WOLF_INFO("Tracked ", mwkps_incoming_new.size(), " new keypoints to incoming");
 
         // Outliers rejection with essential matrix
-        // tracks that are not geometrically consistent are removed from tracks_last_incoming_new 
-        cv::Mat E;
+        // tracks that are not geometrically consistent are removed from tracks_last_incoming_new
+//        cv::Mat E;
         filterWithEssential(mwkps_last_new, mwkps_incoming_new, tracks_last_incoming_new, E);
-        WOLF_TRACE("Tracked ", mwkps_incoming_new.size(), " new keypoints");
+        WOLF_INFO("Retained ", mwkps_incoming_new.size(), " inliers");
 
         // Concatenation of old tracks and new tracks
         // Only keep tracks until it reaches a max nb of tracks
@@ -281,7 +286,7 @@ void ProcessorVisualOdometry::preProcess()
             tracks_last_incoming_filtered[track.first] = track.second;
             count_new_tracks++;
         }
-        WOLF_TRACE("New total : ", tracks_last_incoming_filtered.size(), " tracks");
+        WOLF_INFO("New total : ", n_tracks_origin, " + ", mwkps_incoming_new.size(), " = ", tracks_last_incoming_filtered.size(), " tracks");
 
         // Update captures
         capture_image_last_->addKeyPoints(mwkps_last_new);
@@ -301,6 +306,7 @@ void ProcessorVisualOdometry::preProcess()
 
 unsigned int ProcessorVisualOdometry::processKnown()
 {
+
     auto t1 = std::chrono::system_clock::now();
     // Extend the process track matrix by using information stored in the incoming capture
 
@@ -317,7 +323,7 @@ unsigned int ProcessorVisualOdometry::processKnown()
         // otherwise we store the pair as a newly detected track (for processNew)
         TracksMap tracks_map_li = capture_image_incoming_->getTracksPrev();
         if (tracks_map_li.count(id_feat_last)){
-            // WOLF_TRACE("A corresponding track has been found for id_feat_last ", id_feat_last );
+            // WOLF_INFO("A corresponding track has been found for id_feat_last ", id_feat_last );
             auto kp_track_li = tracks_map_li.find(id_feat_last);
             // create a feature using the corresponding WKeyPoint contained in incoming (hence the "second")
             auto feat_inco = FeatureBase::emplace<FeaturePointImage>(
@@ -333,7 +339,7 @@ unsigned int ProcessorVisualOdometry::processKnown()
         }
     }
     auto dt_processKnown = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - t1).count();
-    std::cout << "dt_processKnown (ms): " << dt_processKnown << std::endl;
+    WOLF_INFO( "dt_processKnown (ms): " , dt_processKnown );
 
     // return number of successful tracks until incoming
     return tracks_map_li_matched_.size();
@@ -373,7 +379,7 @@ unsigned int ProcessorVisualOdometry::processNew(const int& _max_features)
     }
 
     auto dt_processNew = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - t1).count();
-    std::cout << "dt_processNew (ms): " << dt_processNew << std::endl;
+    WOLF_INFO( "dt_processNew (ms): " , dt_processNew );
 
     return counter_new_tracks;
 }
@@ -392,12 +398,21 @@ void ProcessorVisualOdometry::establishFactors()
     //        For bookkeeping, define the landmark id as the track id.
 
     std::list<FeatureBasePtr> tracks_snapshot_last = track_matrix_.snapshotAsList(last_ptr_);
-    for (auto feat: tracks_snapshot_last){
+
+    if(tracks_snapshot_last.empty())
+    {
+        WOLF_WARN("Trying to establish factors but no features exist in last Capture!");
+        return;
+    }
+
+    for (auto feat: tracks_snapshot_last)
+    {
         auto feat_pi = std::static_pointer_cast<FeaturePointImage>(feat);
 
         // verify if a landmark is associated to this track (BAD implementation)
         LandmarkBasePtr associated_lmk = nullptr;
-        for (auto lmk: getProblem()->getMap()->getLandmarkList()){
+        for (auto lmk: getProblem()->getMap()->getLandmarkList())
+        {
             if (lmk->id() == feat_pi->trackId()){
                 associated_lmk = lmk;
             }
@@ -423,6 +438,7 @@ void ProcessorVisualOdometry::establishFactors()
         }
     }
 
+    return;
 }
 
 LandmarkBasePtr ProcessorVisualOdometry::emplaceLandmark(FeatureBasePtr _feat)
@@ -476,6 +492,7 @@ void ProcessorVisualOdometry::postProcess()
 
 bool ProcessorVisualOdometry::voteForKeyFrame() const
 {
+
     // If the last capture was repopulated in preProcess, it means that the number of tracks fell
     // below a threshold in the current incoming track and that, as a consequence, last capture keypoints
     // was repopulated. In this case, the processor needs to create a new Keyframe whatever happens.
@@ -488,6 +505,7 @@ bool ProcessorVisualOdometry::voteForKeyFrame() const
     vote = vote || incoming_ptr_->getFeatureList().size() < params_visual_odometry_->min_features_for_keyframe;
 
     std::cout << "vote " << vote << std::endl;
+
     return vote;
 }
 
@@ -513,6 +531,8 @@ void ProcessorVisualOdometry::setParams(const ParamsProcessorVisualOdometryPtr _
 
 TracksMap ProcessorVisualOdometry::kltTrack(const cv::Mat _img_prev, const cv::Mat _img_curr, const KeyPointsMap &_mwkps_prev, KeyPointsMap &_mwkps_curr)
 {
+    if (_mwkps_prev.empty()) return TracksMap();
+
     TracksMap tracks_prev_curr;
 
     // Create cv point list for tracking, we initialize optical flow with previous keypoints
@@ -529,6 +549,8 @@ TracksMap ProcessorVisualOdometry::kltTrack(const cv::Mat _img_prev, const cv::M
     std::vector<uchar> status;
     std::vector<float> err;
 
+
+
     // Process one way: previous->current with current init with previous
     ParamsProcessorVisualOdometry::KltParams prms = params_visual_odometry_->klt_params_;
     cv::calcOpticalFlowPyrLK(
@@ -579,6 +601,7 @@ TracksMap ProcessorVisualOdometry::kltTrack(const cv::Mat _img_prev, const cv::M
 
 bool ProcessorVisualOdometry::filterWithEssential(const KeyPointsMap _mwkps_prev, const KeyPointsMap _mwkps_curr, TracksMap &_tracks_prev_curr, cv::Mat &_E)
 {
+
     // We need to build lists of pt2f for openCV function
     std::vector<cv::Point2f> p2f_prev, p2f_curr;
     std::vector<size_t> all_indices;
@@ -606,6 +629,7 @@ bool ProcessorVisualOdometry::filterWithEssential(const KeyPointsMap _mwkps_prev
             _tracks_prev_curr.erase(all_indices.at(k));
         }
     }
+
     return true;
 }