diff --git a/include/core/math/SE2.h b/include/core/math/SE2.h
index 95631a8a6fb82ac22595b64d3e1d5b4fe7849cb4..c3ca6dd59bad3d7a110724eaebb5f4a9a470ab42 100644
--- a/include/core/math/SE2.h
+++ b/include/core/math/SE2.h
@@ -320,6 +320,13 @@ inline void compose(const VectorComposite& _x1,
     _c['O'] = Matrix1d( pi2pi(a1 + a2) ) ;
 }
 
+inline VectorComposite compose(const VectorComposite& x1, const VectorComposite& x2)
+{
+    VectorComposite c("PO", {2,1});
+    compose(x1.at('P'), x1.at('O'), x2.at('P'), x2.at('O'), c['P'], c['O']);
+    return c;
+}
+
 inline void compose(const VectorComposite& _x1,
              const VectorComposite& _x2,
              VectorComposite& _c,
diff --git a/include/core/processor/processor_tracker_feature_landmark_external.h b/include/core/processor/processor_tracker_feature_landmark_external.h
index 578181788acdc0b74cf938d8e1b2e4dd0ce27d55..8444bbb381872cb3c9e54b2e90c591dca9bbb530 100644
--- a/include/core/processor/processor_tracker_feature_landmark_external.h
+++ b/include/core/processor/processor_tracker_feature_landmark_external.h
@@ -32,16 +32,18 @@ WOLF_STRUCT_PTR_TYPEDEFS(ParamsProcessorTrackerFeatureLandmarkExternal);
 
 struct ParamsProcessorTrackerFeatureLandmarkExternal : public ParamsProcessorTrackerFeature
 {
-    unsigned int filter_track_length_th;  ///< length of the track necessary to consider the detection
     double filter_quality_th;             ///< min quality to consider the detection
+    double filter_dist_th;                ///< for considering tracked detection: distance threshold to previous detection
+    unsigned int filter_track_length_th;  ///< length of the track necessary to consider the detection
 
     ParamsProcessorTrackerFeatureLandmarkExternal() = default;
     ParamsProcessorTrackerFeatureLandmarkExternal(std::string _unique_name,
                                        const wolf::ParamsServer & _server):
         ParamsProcessorTrackerFeature(_unique_name, _server)
     {
-        filter_track_length_th  = _server.getParam<unsigned int>(prefix + _unique_name + "/filter_track_length_th");
         filter_quality_th       = _server.getParam<double>      (prefix + _unique_name + "/filter_quality_th");
+        filter_dist_th          = _server.getParam<double>      (prefix + _unique_name + "/filter_dist_th");
+        filter_track_length_th  = _server.getParam<unsigned int>(prefix + _unique_name + "/filter_track_length_th");
     }
 };
 
@@ -142,6 +144,12 @@ class ProcessorTrackerFeatureLandmarkExternal : public ProcessorTrackerFeature
 
         void advanceDerived() override;
         void resetDerived() override;
+
+        double detectionDistance(FeatureBasePtr _ftr1,
+                                 FeatureBasePtr _ftr2,
+                                 const VectorComposite& _pose1,
+                                 const VectorComposite& _pose2,
+                                 const VectorComposite& _pose_sen) const;
 };
 
 inline ProcessorTrackerFeatureLandmarkExternal::ProcessorTrackerFeatureLandmarkExternal(ParamsProcessorTrackerFeatureLandmarkExternalPtr _params_tfle) :
diff --git a/include/core/processor/processor_tracker_landmark.h b/include/core/processor/processor_tracker_landmark.h
index bbccccf950aa02f499d215a21f5488a724330435..ab109ffdbf4302cfeb517be5e184ae3499d77fa2 100644
--- a/include/core/processor/processor_tracker_landmark.h
+++ b/include/core/processor/processor_tracker_landmark.h
@@ -88,7 +88,7 @@ WOLF_PTR_TYPEDEFS(ProcessorTrackerLandmark);
  *     - createLandmark() : creates a Landmark using a new Feature                  <=== IMPLEMENT
  *     - findLandmarks() : find the new Landmarks again in \b incoming              <=== IMPLEMENT
  *   - establishFactors() : which calls the pure virtual:
- *     - createFactor() : create a Feature-Landmark factor of the correct derived type <=== IMPLEMENT
+ *     - emplaceFactor() : create a Feature-Landmark factor of the correct derived type <=== IMPLEMENT
  *
  * Should you need extra functionality for your derived types, you can overload these two methods,
  *
diff --git a/src/processor/processor_tracker_feature_landmark_external.cpp b/src/processor/processor_tracker_feature_landmark_external.cpp
index e2dd598eab84c8036035c626a73d10c49a2b5f63..be4ff3be06b1c9a59a767b6aab7ce8c1511ec6b9 100644
--- a/src/processor/processor_tracker_feature_landmark_external.cpp
+++ b/src/processor/processor_tracker_feature_landmark_external.cpp
@@ -31,6 +31,8 @@
 #include "core/state_block/state_block_derived.h"
 #include "core/state_block/state_quaternion.h"
 #include "core/state_block/state_angle.h"
+#include "core/math/SE2.h"
+#include "core/math/SE3.h"
 
 using namespace Eigen;
 
@@ -46,14 +48,24 @@ void ProcessorTrackerFeatureLandmarkExternal::preProcess()
         throw std::runtime_error("ProcessorTrackerFeatureLandmarkExternal::preProcess incoming_ptr_ should be of type 'CaptureLandmarksExternal'");
 
     auto landmark_detections = cap_landmarks->getDetections();
+    std::set<int> ids;
     for (auto detection : landmark_detections)
     {
+        WOLF_WARN_COND(ids.count(detection.id), "ProcessorTrackerFeatureLandmarkExternal::preProcess: detection with repeated id, discarding...");
+
+        if (detection.quality < params_tfle_->filter_quality_th
+            or ids.count(detection.id))
+            continue;
+
         FeatureBasePtr ftr = FeatureBase::emplace<FeatureBase>(cap_landmarks,
                                                                "FeatureLandmarkExternal",
                                                                detection.measure,
                                                                detection.covariance);
         ftr->setLandmarkId(detection.id);
 
+        if (detection.id != -1 and detection.id != 0)
+            ids.insert(detection.id);
+
         detections_incoming_.push_back(ftr);
     }
 }
@@ -65,16 +77,25 @@ unsigned int ProcessorTrackerFeatureLandmarkExternal::trackFeatures(const Featur
 {
     WOLF_INFO("tracking " , _features_in.size() , " features...");
 
+    if (_features_in.empty())
+        return 0;
+
     if (_capture != last_ptr_ and _capture != incoming_ptr_)
         throw std::runtime_error("ProcessorTrackerFeatureLandmarkExternal::trackFeatures unknown capture");
 
     FeatureBasePtrList& landmark_detections = (_capture == last_ptr_ ? detections_last_ : detections_incoming_);
 
+    assert(not _features_in.front() and not _features_in.front()->getCapture());
+    auto pose_sen = getSensor()->getState("PO");
+    auto pose_in  = getProblem()->getState(_features_in.front()->getCapture()->getTimeStamp(), "PO");
+    auto pose_out = getProblem()->getState(_capture->getTimeStamp(), "PO");
+
     for (auto feat_in : _features_in)
     {
         for (auto feat_candidate : landmark_detections)
         {
-            if (feat_candidate->landmarkId() == feat_in->landmarkId())
+            if (feat_candidate->landmarkId() == feat_in->landmarkId() and 
+                detectionDistance(feat_in, feat_candidate, pose_in, pose_out, pose_sen) < params_tfle_->filter_dist_th)
             {
                 _features_out.push_back(feat_candidate);
                 _feature_correspondences[_features_out.back()] = std::make_shared<FeatureMatch>(FeatureMatch({feat_in,0}));
@@ -87,6 +108,41 @@ unsigned int ProcessorTrackerFeatureLandmarkExternal::trackFeatures(const Featur
     return _features_out.size();
 }
 
+double ProcessorTrackerFeatureLandmarkExternal::detectionDistance(FeatureBasePtr _ftr1,
+                                                                  FeatureBasePtr _ftr2,
+                                                                  const VectorComposite& _pose1,
+                                                                  const VectorComposite& _pose2,
+                                                                  const VectorComposite& _pose_sen) const
+{
+    // Any not available info of poses, assume identity
+    if (not _pose1.includesStructure("PO") or not _pose2.includesStructure("PO") or not _pose_sen.includesStructure("PO"))
+    {
+        if (getProblem()->getDim() == 2)
+            return (_ftr1->getMeasurement().head<2>() - _ftr2->getMeasurement().head<2>()).norm();
+        else
+            return (_ftr1->getMeasurement().head<3>() - _ftr2->getMeasurement().head<3>()).norm();
+    }
+    else
+    {
+        if (getProblem()->getDim() == 2)
+        {
+            auto pose_s1 = SE2::compose(_pose1, _pose_sen);
+            auto pose_s2 = SE2::compose(_pose2, _pose_sen);
+            auto p1 = pose_s1.at('P') + Eigen::Rotation2Dd(pose_s1.at('O')(0)) * _ftr1->getMeasurement().head<2>();
+            auto p2 = pose_s2.at('P') + Eigen::Rotation2Dd(pose_s2.at('O')(0)) * _ftr2->getMeasurement().head<2>();
+            return (p1-p2).norm();
+        }
+        else
+        {
+            auto pose_s1 = SE3::compose(_pose1, _pose_sen);
+            auto pose_s2 = SE3::compose(_pose2, _pose_sen);
+            auto p1 = pose_s1.at('P') + Eigen::Quaterniond(Eigen::Vector4d(pose_s1.at('O'))) * _ftr1->getMeasurement().head<3>();
+            auto p2 = pose_s2.at('P') + Eigen::Quaterniond(Eigen::Vector4d(pose_s2.at('O'))) * _ftr2->getMeasurement().head<3>();
+            return (p1-p2).norm();
+        }
+    }
+}
+
 bool ProcessorTrackerFeatureLandmarkExternal::voteForKeyFrame() const
 {
     WOLF_INFO("Nbr. of active feature tracks: " , incoming_ptr_->getFeatureList().size() );
@@ -131,6 +187,20 @@ FactorBasePtr ProcessorTrackerFeatureLandmarkExternal::emplaceFactor(FeatureBase
     assert(getProblem());
     assert(getProblem()->getMap());
 
+    // Check track length
+    if (params_tfle_->filter_track_length_th > 1)
+    {
+        auto snapshot = track_matrix_.snapshot(_feature_ptr->getCapture());
+        const auto& it = std::find_if(snapshot.begin(), snapshot.end(),
+                                      [_feature_ptr](const std::pair<SizeStd, FeatureBasePtr>& pair)
+                                      {
+                                        return pair.second == _feature_ptr;
+                                      });
+        assert(it != snapshot.end());
+        if (track_matrix_.track(it->first).size() < params_tfle_->filter_track_length_th)
+            return nullptr;
+    }
+
     // Get landmark
     LandmarkBasePtr lmk = getProblem()->getMap()->getLandmark(_feature_ptr->landmarkId());
     
@@ -155,11 +225,11 @@ FactorBasePtr ProcessorTrackerFeatureLandmarkExternal::emplaceFactor(FeatureBase
         }
 
         // emplace factor
-        return FactorBase::emplace<FactorRelativePose2dWithExtrinsics>(_feature_ptr, 
-                                                                       _feature_ptr,
-                                                                       lmk,
-                                                                       shared_from_this(),
-                                                                       params_tfle_->apply_loss_function);
+        return FactorBase::emplace<FactorRelativePosition2dWithExtrinsics>(_feature_ptr, 
+                                                                           _feature_ptr,
+                                                                           lmk,
+                                                                           shared_from_this(),
+                                                                           params_tfle_->apply_loss_function);
     }
     // 2D - Relative Pose
     else if (getProblem()->getDim() == 2 and _feature_ptr->getMeasurement().size() == 3)