diff --git a/include/core/processor/processor_motion.h b/include/core/processor/processor_motion.h
index 6a0f15a90885f5438c18c2cf01ed714c488ba599..b590ff73fa5724f30908ebe134524826d6c376b3 100644
--- a/include/core/processor/processor_motion.h
+++ b/include/core/processor/processor_motion.h
@@ -12,6 +12,7 @@
 #include "core/capture/capture_motion.h"
 #include "core/processor/processor_base.h"
 #include "core/processor/is_motion.h"
+#include "core/factor/factor_block_difference.h"
 #include "core/common/time_stamp.h"
 #include "core/utils/params_server.h"
 
@@ -457,6 +458,12 @@ class ProcessorMotion : public ProcessorBase, public IsMotion
          */
         virtual FactorBasePtr emplaceFactor(FeatureBasePtr _feature_motion, CaptureBasePtr _capture_origin) = 0;
 
+        /** \brief emplace a factor accounting for the drift of calibration/intrinsics parameters
+        * \param  _cap_motion: capture containing an origin capture, the factor will be created between biases at 
+        * _cap_motion time and its origin capture time
+        */
+        virtual void emplaceCalibrationDriftFactor(CaptureMotionPtr _cap_motion);
+
         virtual void setCalibration(const CaptureBasePtr _capture, const VectorXd& _calibration) = 0;
 
         Motion motionZero(const TimeStamp& _ts) const;
diff --git a/include/core/sensor/sensor_base.h b/include/core/sensor/sensor_base.h
index b1572a010a6594473b51aceb949f5b21c26e8eb6..1f457b1838b4475fccbf796d99ebf6daedae636d 100644
--- a/include/core/sensor/sensor_base.h
+++ b/include/core/sensor/sensor_base.h
@@ -103,6 +103,7 @@ class SensorBase : public NodeBase, public HasStateBlocks, public std::enable_sh
     protected:
         Eigen::VectorXd noise_std_; // std of sensor noise
         Eigen::MatrixXd noise_cov_; // cov matrix of noise
+        Eigen::MatrixXd calib_drift_cov_; // cov matrix of calibration drift in continuous time (in [parameter unit]^2/s)
 
         void setProblem(ProblemPtr _problem) override final;
 
@@ -233,6 +234,8 @@ class SensorBase : public NodeBase, public HasStateBlocks, public std::enable_sh
 
         SizeEigen getCalibSize() const;
         Eigen::VectorXd getCalibration() const;
+        Eigen::MatrixXd getCalibrationDriftCov() const;
+        void setCalibrationDriftCov(const Eigen::MatrixXd & _calib_drift_cov);
 
         void setNoiseStd(const Eigen::VectorXd & _noise_std);
         void setNoiseCov(const Eigen::MatrixXd & _noise_std);
diff --git a/include/core/sensor/sensor_diff_drive.h b/include/core/sensor/sensor_diff_drive.h
index 8238139c3a2bf85238a9d4bacc7ac02994e987dd..05180f90df967ce5ba12665f7d693198f442e2b7 100644
--- a/include/core/sensor/sensor_diff_drive.h
+++ b/include/core/sensor/sensor_diff_drive.h
@@ -25,6 +25,11 @@ struct ParamsSensorDiffDrive : public ParamsSensorBase
     Eigen::Vector3d prior_cov_diag;
     double          ticks_cov_factor;
 
+    // drift standard deviation
+    double radius_left_rate_stdev = 1;
+    double radius_right_rate_stdev = 1;
+    double wheel_separation_rate_stdev = 1;
+
     ParamsSensorDiffDrive() = default;
     ParamsSensorDiffDrive(std::string _unique_name, const wolf::ParamsServer& _server)
       : ParamsSensorBase(_unique_name, _server)
@@ -36,17 +41,25 @@ struct ParamsSensorDiffDrive : public ParamsSensorBase
         set_intrinsics_prior       = _server.getParam<bool>(prefix + _unique_name + "/set_intrinsics_prior");
         prior_cov_diag             = _server.getParam<Eigen::Vector3d>(prefix + _unique_name + "/prior_cov_diag");
         ticks_cov_factor           = _server.getParam<double>(prefix + _unique_name + "/ticks_cov_factor");
+
+        radius_left_rate_stdev       = _server.getParam<double>(prefix + _unique_name + "/radius_left_rate_stdev");
+        radius_right_rate_stdev      = _server.getParam<double>(prefix + _unique_name + "/radius_right_rate_stdev");
+        wheel_separation_rate_stdev  = _server.getParam<double>(prefix + _unique_name + "/wheel_separation_rate_stdev");
+
     }
     std::string print() const
     {
-        return "\n" + ParamsSensorBase::print()                                           + "\n"
+        return "\n" + ParamsSensorBase::print()                                         + "\n"
         + "radius_left: "                   + std::to_string(radius_left)               + "\n"
         + "radius_right: "                  + std::to_string(radius_right)              + "\n"
         + "wheel_separation: "              + std::to_string(wheel_separation)          + "\n"
         + "ticks_per_wheel_revolution: "    + std::to_string(ticks_per_wheel_revolution)+ "\n"
         + "set_intrinsics_prior: "          + std::to_string(set_intrinsics_prior)      + "\n"
         + "prior_cov_diag:  to_string not implemented yet! \n"
-        + "ticks_cov_factor: "              + std::to_string(ticks_cov_factor)          + "\n";
+        + "ticks_cov_factor: "              + std::to_string(ticks_cov_factor)            + "\n";
+        + "radius_left_rate_stdev: "        + std::to_string(radius_left_rate_stdev)      + "\n";
+        + "radius_right_rate_stdev: "       + std::to_string(radius_right_rate_stdev)     + "\n";
+        + "wheel_separation_rate_stdev: "   + std::to_string(wheel_separation_rate_stdev) + "\n";
     }
 };
 
diff --git a/src/processor/processor_motion.cpp b/src/processor/processor_motion.cpp
index d18ae7c312f4e19a98ed1ae9522b2b06aad2fd41..5e35be115a93cdcf8543fcfcc59cc5c80ce552d1 100644
--- a/src/processor/processor_motion.cpp
+++ b/src/processor/processor_motion.cpp
@@ -86,6 +86,10 @@ void ProcessorMotion::mergeCaptures(CaptureMotionConstPtr cap_prev,
         // emplace new feature and factor
         auto new_feature = emplaceFeature(cap_target);
         emplaceFactor(new_feature, cap_prev->getOriginCapture());
+
+        // emplace calibration drift factor if sensor intrinsics are dynamic
+        if (getSensor()->hasStateBlock('I') and getSensor()->isStateBlockDynamic('I'))
+            emplaceCalibrationDriftFactor(cap_target);
     }
 }
 
@@ -272,6 +276,10 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
 
             // create motion factor and add it to the feature, and constrain to the other capture (origin)
             emplaceFactor(feature_new, capture_origin );
+            
+            // emplace calibration drift factor if sensor intrinsics are dynamic
+            if (getSensor()->hasStateBlock('I') and getSensor()->isStateBlockDynamic('I'))
+                emplaceCalibrationDriftFactor(capture_for_keyframe_callback);
 
             // modify existing feature and factor (if they exist in the existing capture)
             if (!capture_existing->getFeatureList().empty())
@@ -283,6 +291,10 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
                 auto new_feature_existing = emplaceFeature(capture_existing);
                 emplaceFactor(new_feature_existing, capture_for_keyframe_callback);
 
+                // emplace calibration drift factor if sensor intrinsics are dynamic
+                if (getSensor()->hasStateBlock('I') and getSensor()->isStateBlockDynamic('I'))
+                    emplaceCalibrationDriftFactor(capture_existing);
+
 //                auto feature_existing = capture_existing->getFeatureList().back(); // there is only one feature!
 //
 //                // Modify existing feature --------
@@ -367,6 +379,10 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
             // create motion factor and add it to the feature, and constrain to the other capture (origin)
             emplaceFactor(feature_for_keyframe_callback, capture_origin );
 
+            // emplace calibration drift factor if sensor intrinsics are dynamic
+            if (getSensor()->hasStateBlock('I') and getSensor()->isStateBlockDynamic('I'))
+                emplaceCalibrationDriftFactor(capture_for_keyframe_callback);            
+
             // reset processor origin
             origin_ptr_ = capture_for_keyframe_callback;
 
@@ -427,7 +443,11 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
         auto key_feature    = emplaceFeature(last_ptr_);
 
         // create motion factor and link it to parent feature and other frame (which is origin's frame)
-        auto factor         = emplaceFactor(key_feature, origin_ptr_);
+        emplaceFactor(key_feature, origin_ptr_);
+
+        // emplace calibration drift factor if sensor intrinsics are dynamic
+        if (getSensor()->hasStateBlock('I') and getSensor()->isStateBlockDynamic('I'))
+            emplaceCalibrationDriftFactor(last_ptr_);  
 
         // create a new frame
         auto frame_new      = FrameBase::createNonKeyFrame<FrameBase>(getTimeStamp(),
@@ -439,8 +459,8 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr)
                                              key_frame->getTimeStamp(),
                                              Eigen::VectorXd::Zero(data_size_),
                                              getSensor()->getNoiseCov(),
-                                             getCalibration(last_ptr_),
-                                             getCalibration(last_ptr_),
+                                             getCalibration(origin_ptr_),
+                                             getCalibration(origin_ptr_),
                                              last_ptr_);
         // reset the new buffer
         capture_new->getBuffer().push_back( motionZero(key_frame->getTimeStamp()) ) ;
@@ -942,6 +962,27 @@ PackKeyFramePtr ProcessorMotion::computeProcessingStep()
     return nullptr;
 }
 
+void ProcessorMotion::emplaceCalibrationDriftFactor(CaptureMotionPtr _cap_motion){
+    MatrixXd cov_continuous = getSensor()->getCalibrationDriftCov();
+    if (cov_continuous.size() == 0){
+        WOLF_TRACE("SensorBase calib_drift_cov_ not initialized")
+    }
+    else {
+        CaptureBasePtr cap_origin = _cap_motion->getOriginCapture();
+        double dt_drift = _cap_motion->getTimeStamp() - cap_origin->getTimeStamp();
+        // covariance resulting from the integration of a continuous white gaussian
+        Eigen::MatrixXd cov_drift = cov_continuous * dt_drift;  
+        Eigen::VectorXd zero_drift(getSensor()->getCalibSize()); zero_drift.setZero(); 
+        FeatureBasePtr feat_diff = FeatureBase::emplace<FeatureBase>(_cap_motion, "ComBiasDrift", zero_drift, cov_drift, 
+                                                                     FeatureBase::UncertaintyType::UNCERTAINTY_IS_COVARIANCE);
+        StateBlockPtr sb_pbc1 = cap_origin->getSensorIntrinsic();
+        StateBlockPtr sb_pbc2 = _cap_motion->getSensorIntrinsic();
+        FactorBlockDifferencePtr Fac = FactorBase::emplace<FactorBlockDifference>(
+                feat_diff, feat_diff, sb_pbc1, sb_pbc2, nullptr, cap_origin
+        );
+    }
+}
+
 bool ProcessorMotion::storeKeyFrame(FrameBasePtr _frame_ptr)
 {
   return true;
diff --git a/src/sensor/sensor_base.cpp b/src/sensor/sensor_base.cpp
index 82fbe684558bd9791763b70c0bbedab68514b8f0..a4792242079212faa7aeb119a602f828b98942c2 100644
--- a/src/sensor/sensor_base.cpp
+++ b/src/sensor/sensor_base.cpp
@@ -23,7 +23,8 @@ SensorBase::SensorBase(const std::string& _type,
         calib_size_(0),
         sensor_id_(++sensor_id_count_), // simple ID factory
         noise_std_(_noise_size),
-        noise_cov_(_noise_size, _noise_size)
+        noise_cov_(_noise_size, _noise_size),
+        calib_drift_cov_(Matrix<double,0,0>())
 {
     assert((_p_ptr or not _p_dyn) and "Trying to set dynamic position state block without providing a position state block. It is required anyway.");
     assert((_o_ptr or not _o_dyn) and "Trying to set dynamic orientation state block without providing an orientation state block. It is required anyway.");
@@ -214,6 +215,17 @@ void SensorBase::setNoiseCov(const Eigen::MatrixXd& _noise_cov) {
     noise_cov_ = _noise_cov;
 }
 
+Eigen::MatrixXd SensorBase::getCalibrationDriftCov() const
+{
+    return calib_drift_cov_;
+}
+
+void SensorBase::setCalibrationDriftCov(const Eigen::MatrixXd & _calib_drift_cov)
+{
+    calib_drift_cov_.resize(_calib_drift_cov.rows(), _calib_drift_cov.cols());
+    calib_drift_cov_ = _calib_drift_cov;
+}
+
 CaptureBasePtr SensorBase::lastCapture(void) const
 {
     // we search for the most recent Capture of this sensor which belongs to a KeyFrame
diff --git a/src/sensor/sensor_diff_drive.cpp b/src/sensor/sensor_diff_drive.cpp
index afdc43e02a8085feb99c4ae0ac1a9a4cdefe2162..258231e70b0456459e60684cc0dfe7d60e429acb 100644
--- a/src/sensor/sensor_diff_drive.cpp
+++ b/src/sensor/sensor_diff_drive.cpp
@@ -32,7 +32,11 @@ SensorDiffDrive::SensorDiffDrive(const Eigen::VectorXd& _extrinsics,
     Eigen::Vector2d noise_sigma; noise_sigma << sigma_rev, sigma_rev;
 
     setNoiseStd(noise_sigma);
-   
+
+    // initialize continuous calibration drift covariance
+    Vector3d std_vec_drift; std_vec_drift << params_diff_drive_->radius_left_rate_stdev, params_diff_drive_->radius_right_rate_stdev, params_diff_drive_->wheel_separation_rate_stdev;
+    Matrix3d cov = std_vec_drift.array().square().matrix().asDiagonal();
+    setCalibrationDriftCov(cov);
 }
 
 SensorDiffDrive::~SensorDiffDrive()