diff --git a/include/core/factor/factor_block_difference.h b/include/core/factor/factor_block_difference.h
index 8fd52090ba8b012fecb3484c3659d0e37e3b9ed7..22ec994a4338e9ff15e5b7457ae5aafce52e9f0e 100644
--- a/include/core/factor/factor_block_difference.h
+++ b/include/core/factor/factor_block_difference.h
@@ -63,13 +63,17 @@ class FactorBlockDifference : public FactorAnalytic
             sb2_constrained_start_(_start_idx2),
             sb2_constrained_size_(_size2 == -1 ? sb2_size_ : _size2)
         {
+            // Check if constrained portion is in the stateblock vector range 
             assert(sb1_constrained_size_+sb1_constrained_start_ <= sb1_size_);
             assert(sb2_constrained_size_+sb2_constrained_start_ <= sb2_size_);
             assert(sb1_constrained_size_ == sb2_constrained_size_);
 
-            // precompute Jacobian (Identity)
-            J1_ = Eigen::MatrixXd::Identity(sb1_constrained_size_, sb1_size_);
-            J2_ = Eigen::MatrixXd::Identity(sb2_constrained_size_, sb2_size_);
+            // precompute Jacobian (Identity with zero columns if the stateblock part is not constrained)
+            J1_ = Eigen::MatrixXd::Zero(sb1_constrained_size_,sb1_size_);
+            J1_.middleCols(sb1_constrained_start_,sb1_constrained_size_) = - Eigen::MatrixXd::Identity(sb1_constrained_size_,sb1_constrained_size_);
+
+            J2_ = Eigen::MatrixXd::Zero(sb2_constrained_size_,sb2_size_);
+            J2_.middleCols(sb2_constrained_start_,sb1_constrained_size_) =   Eigen::MatrixXd::Identity(sb2_constrained_size_,sb2_constrained_size_);
         }
 
         virtual ~FactorBlockDifference() = default;
@@ -119,12 +123,16 @@ class FactorBlockDifference : public FactorAnalytic
 
 inline Eigen::VectorXd FactorBlockDifference::evaluateResiduals(const std::vector<Eigen::Map<const Eigen::VectorXd> >& _st_vector) const
 {
+    // Check measurement and cov sizes 
     assert(_st_vector.size() == 2 && "Wrong number of state blocks!");
-    assert(_st_vector[0].size() >= getMeasurement().size() && "Wrong StateBlock size");
-    assert(_st_vector[1].size() >= getMeasurement().size() && "Wrong StateBlock size");
+    assert(getMeasurement().size() == getMeasurementCovariance().cols());
+    assert(getMeasurement().size() == getMeasurementCovariance().rows());
+    assert(getMeasurement().size() == sb1_constrained_size_);
+    assert(getMeasurement().size() == sb2_constrained_size_);
 
     // residual: meas -> measurement of the difference between partial stateblocks
-    return getMeasurementSquareRootInformationUpper() * ((_st_vector[1] - _st_vector[0]) - getMeasurement());
+    return getMeasurementSquareRootInformationUpper() * ((_st_vector[1].segment(sb1_constrained_start_, sb1_constrained_size_) 
+                                                        - _st_vector[0].segment(sb2_constrained_start_, sb2_constrained_size_)) - getMeasurement());
 }
 
 inline void FactorBlockDifference::evaluateJacobians(const std::vector<Eigen::Map<const Eigen::VectorXd> >& _st_vector,
@@ -140,13 +148,8 @@ inline void FactorBlockDifference::evaluateJacobians(const std::vector<Eigen::Ma
     assert(_st_vector[1].size() >= getMeasurement().size() && "StateBlock size and measurement size should match");
 
     // normalized jacobian
-    if (_compute_jacobian.front()){
-        _jacobians[0] = getMeasurementSquareRootInformationUpper() * J1_;
-        _jacobians[1] = getMeasurementSquareRootInformationUpper() * J2_;
-    }
-    else {
-        // TODO?
-    }
+    _jacobians[0] = getMeasurementSquareRootInformationUpper() * J1_;
+    _jacobians[1] = getMeasurementSquareRootInformationUpper() * J2_;
 }
 
 inline void FactorBlockDifference::evaluateJacobians(const std::vector<Eigen::Map<const Eigen::VectorXd>>& _st_vector,
@@ -162,10 +165,8 @@ inline void FactorBlockDifference::evaluateJacobians(const std::vector<Eigen::Ma
     assert(_st_vector[1].size() >= getMeasurement().size() && "StateBlock size and measurement size should match");
 
     // normalized jacobian
-    if (_compute_jacobian.front()){
-        _jacobians[0] = getMeasurementSquareRootInformationUpper() * J1_;
-        _jacobians[1] = getMeasurementSquareRootInformationUpper() * J2_;
-    }
+    _jacobians[0] = getMeasurementSquareRootInformationUpper() * J1_;
+    _jacobians[1] = getMeasurementSquareRootInformationUpper() * J2_;
 }
 
 inline void FactorBlockDifference::evaluatePureJacobians(std::vector<Eigen::MatrixXd>& jacobians) const
diff --git a/test/gtest_factor_block_difference.cpp b/test/gtest_factor_block_difference.cpp
index 0945b328de7d8094d49624aad6a89b0af5708788..4585edaab87c4a94d23712cdafe9a7856c04510a 100644
--- a/test/gtest_factor_block_difference.cpp
+++ b/test/gtest_factor_block_difference.cpp
@@ -76,8 +76,9 @@ TEST_F(FixtureFactorBlockDifference, EqualP)
     );
 
     // perturbate
-    KF1_->getP()->setState((Vector3d() << 1, 0, 0).finished());
-
+    KF0_->getP()->setState(Vector3d::Random());
+    KF1_->getP()->setState(Vector3d::Random());
+    
     std::string report = ceres_manager_->solve(SolverManager::ReportVerbosity::BRIEF);
 
     ASSERT_MATRIX_APPROX(KF1_->getP()->getState() - KF0_->getP()->getState(), zero3, 1e-8);
@@ -91,7 +92,8 @@ TEST_F(FixtureFactorBlockDifference, EqualV)
     );
 
     // perturbate
-    KF1_->getV()->setState((Vector3d() << 1, 0, 0).finished());
+    KF0_->getV()->setState(Vector3d::Random());
+    KF1_->getV()->setState(Vector3d::Random());
 
     std::string report = ceres_manager_->solve(SolverManager::ReportVerbosity::BRIEF);
 
@@ -103,18 +105,19 @@ TEST_F(FixtureFactorBlockDifference, EqualV)
 
 TEST_F(FixtureFactorBlockDifference, DiffP)
 {
-    Vector3d diffP = Vector3d::Random();
-    Feat_->setMeasurement(diffP);
+    Vector3d diff = Vector3d::Random();
+    Feat_->setMeasurement(diff);
     FactorBlockDifferencePtr Fac = FactorBase::emplace<FactorBlockDifference>(
         Feat_, KF0_->getP(), KF1_->getP()
     );
 
     // perturbate
-    KF1_->getP()->setState((Vector3d() << 1, 0, 0).finished());
+    KF0_->getP()->setState(Vector3d::Random());
+    KF1_->getP()->setState(Vector3d::Random());
 
     std::string report = ceres_manager_->solve(SolverManager::ReportVerbosity::BRIEF);
 
-    ASSERT_MATRIX_APPROX(KF1_->getP()->getState() - KF0_->getP()->getState(), diffP, 1e-8);
+    ASSERT_MATRIX_APPROX(KF1_->getP()->getState() - KF0_->getP()->getState(), diff, 1e-8);
 
 }
 
@@ -122,19 +125,89 @@ TEST_F(FixtureFactorBlockDifference, DiffP)
 
 TEST_F(FixtureFactorBlockDifference, DiffV)
 {
-    Vector3d diffV = Vector3d::Random();
-    Feat_->setMeasurement(diffV);
+    Vector3d diff = Vector3d::Random();
+    Feat_->setMeasurement(diff);
     FactorBlockDifferencePtr Fac = FactorBase::emplace<FactorBlockDifference>(
         Feat_, KF0_->getV(), KF1_->getV()
     );
 
     // perturbate
-    KF1_->getV()->setState((Vector3d() << 1, 0, 0).finished());
+    KF0_->getV()->setState(Vector3d::Random());
+    KF1_->getV()->setState(Vector3d::Random());
+
+    std::string report = ceres_manager_->solve(SolverManager::ReportVerbosity::BRIEF);
+
+    ASSERT_MATRIX_APPROX(KF1_->getV()->getState() - KF0_->getV()->getState(), diff, 1e-8);
+}
+
+
+TEST_F(FixtureFactorBlockDifference, DiffPx)
+{
+    // Vector3d diff = Vector3d::Random();
+    Vector1d diff; diff << 1;  // measurement still of the same size as the constrained state
+    Matrix1d cov_diff = 1e-4 * Matrix1d::Identity();  // measurement still of the same size as the constrained state
+    Feat_->setMeasurement(diff);
+    Feat_->setMeasurementCovariance(cov_diff);
+    FactorBlockDifferencePtr Fac = FactorBase::emplace<FactorBlockDifference>(
+        Feat_, KF0_->getP(), KF1_->getP(),
+        0, 1, 0, 1
+    );
+
+    // perturbate
+    KF0_->getP()->setState(Vector3d::Random());
+    KF1_->getP()->setState(Vector3d::Random());
+
+    std::string report = ceres_manager_->solve(SolverManager::ReportVerbosity::BRIEF);
+
+    ASSERT_MATRIX_APPROX(KF1_->getP()->getState().head<1>() - KF0_->getP()->getState().head<1>(), diff.head<1>(), 1e-8);
+}
+
+
+
+
+TEST_F(FixtureFactorBlockDifference, DiffPxy)
+{
+    // Vector3d diff = Vector3d::Random();
+    Vector2d diff; diff << 1, 2;  // measurement still of the same size as the constrained state
+    Matrix2d cov_diff = 1e-4 * Matrix2d::Identity();  // measurement still of the same size as the constrained state
+    Feat_->setMeasurement(diff);
+    Feat_->setMeasurementCovariance(cov_diff);
+    FactorBlockDifferencePtr Fac = FactorBase::emplace<FactorBlockDifference>(
+        Feat_, KF0_->getP(), KF1_->getP(),
+        0, 2, 0, 2
+    );
+
+    // perturbate
+    KF0_->getP()->setState(Vector3d::Random());
+    KF1_->getP()->setState(Vector3d::Random());
 
     std::string report = ceres_manager_->solve(SolverManager::ReportVerbosity::BRIEF);
 
-    ASSERT_MATRIX_APPROX(KF1_->getV()->getState() - KF0_->getV()->getState(), diffV, 1e-8);
+    ASSERT_MATRIX_APPROX(KF1_->getP()->getState().head<2>() - KF0_->getP()->getState().head<2>(), diff, 1e-8);
+}
+
+TEST_F(FixtureFactorBlockDifference, DiffPyz)
+{
+    // Vector3d diff = Vector3d::Random();
+    Vector2d diff; diff << 1, 2;  // measurement still of the same size as the constrained state
+    Matrix2d cov_diff = 1e-4 * Matrix2d::Identity();  // measurement still of the same size as the constrained state
+    Feat_->setMeasurement(diff);
+    Feat_->setMeasurementCovariance(cov_diff);
+    FactorBlockDifferencePtr Fac = FactorBase::emplace<FactorBlockDifference>(
+        Feat_, KF0_->getP(), KF1_->getP(),
+        1, 2, 1, 2
+    );
+
+    // perturbate
+    KF0_->getP()->setState(Vector3d::Random());
+    KF1_->getP()->setState(Vector3d::Random());
+
+    // problem_->print(4,true,true,true);
+    std::string report = ceres_manager_->solve(SolverManager::ReportVerbosity::BRIEF);
+    // std::cout << report << std::endl;
+    // problem_->print(4,true,true,true);
 
+    ASSERT_MATRIX_APPROX(KF1_->getP()->getState().segment<2>(1) - KF0_->getP()->getState().segment<2>(1), diff, 1e-8);
 }
 
 int main(int argc, char **argv)