diff --git a/include/imu/factor/factor_imu.h b/include/imu/factor/factor_imu.h index 9e752656f10de383513a406538da1f399c2ec1a7..49f5043359eaa42042c6e7ffd899781735472867 100644 --- a/include/imu/factor/factor_imu.h +++ b/include/imu/factor/factor_imu.h @@ -36,7 +36,7 @@ namespace wolf { WOLF_PTR_TYPEDEFS(FactorImu); //class -class FactorImu : public FactorAutodiff<FactorImu, 15, 3, 4, 3, 6, 3, 4, 3, 6> +class FactorImu : public FactorAutodiff<FactorImu, 9, 3, 4, 3, 6, 3, 4, 3> { public: FactorImu(const FeatureImuPtr& _ftr_ptr, @@ -61,7 +61,6 @@ class FactorImu : public FactorAutodiff<FactorImu, 15, 3, 4, 3, 6, 3, 4, 3, 6> const T* const _p2, const T* const _o2, const T* const _v2, - const T* const _b2, T* _res) const; /** \brief Estimation error given the states in the wolf tree @@ -95,8 +94,6 @@ class FactorImu : public FactorAutodiff<FactorImu, 15, 3, 4, 3, 6, 3, 4, 3, 6> const Eigen::MatrixBase<D1> & _p2, const Eigen::QuaternionBase<D2> & _q2, const Eigen::MatrixBase<D1> & _v2, - const Eigen::MatrixBase<D1> & _ab2, - const Eigen::MatrixBase<D1> & _wb2, Eigen::MatrixBase<D3> & _res) const; /** Function expectation(...) @@ -150,23 +147,7 @@ class FactorImu : public FactorAutodiff<FactorImu, 15, 3, 4, 3, 6, 3, 4, 3, 6> /// Metrics const double dt_; ///< delta-time and delta-time-squared between keyframes - const double ab_rate_stdev_, wb_rate_stdev_; //stdev for standard_deviation (= sqrt(variance)) - /** bias covariance and bias residuals - * - * continuous bias covariance matrix for accelerometer would then be A_r = diag(ab_stdev_^2, ab_stdev_^2, ab_stdev_^2) - * To compute bias residuals, we will need to do (sqrt(A_r)).inverse() * ab_error - * - * In our case, we introduce time 'distance' in the computation of this residual (SEE FORSTER17), thus we have to use the discret covariance matrix - * discrete bias covariance matrix for accelerometer : A_r_dt = dt_ * A_r - * taking the square root for bias residuals : sqrt_A_r_dt = sqrt(dt_ * A_r) = sqrt(dt_) * sqrt(A_r) - * then with the inverse : sqrt_A_r_dt_inv = (sqrt(dt_ * A_r)).inverse() = (1/sqrt(dt_)) * sqrt(A_r).inverse() - * - * same logic for gyroscope bias - */ - const Eigen::Matrix3d sqrt_A_r_dt_inv; - const Eigen::Matrix3d sqrt_W_r_dt_inv; - public: EIGEN_MAKE_ALIGNED_OPERATOR_NEW; }; @@ -177,8 +158,8 @@ inline FactorImu::FactorImu(const FeatureImuPtr& _ftr_ptr, const CaptureImuPtr& _cap_origin_ptr, const ProcessorBasePtr& _processor_ptr, bool _apply_loss_function, - FactorStatus _status) : - FactorAutodiff<FactorImu, 15, 3, 4, 3, 6, 3, 4, 3, 6>( // ... + FactorStatus _status) : + FactorAutodiff<FactorImu, 9, 3, 4, 3, 6, 3, 4, 3>( // ... "FactorImu", TOP_MOTION, _ftr_ptr, @@ -195,8 +176,7 @@ inline FactorImu::FactorImu(const FeatureImuPtr& _ftr_ptr, _cap_origin_ptr->getSensorIntrinsic(), _ftr_ptr->getFrame()->getP(), _ftr_ptr->getFrame()->getO(), - _ftr_ptr->getFrame()->getV(), - _ftr_ptr->getCapture()->getSensorIntrinsic()), + _ftr_ptr->getFrame()->getV()), processor_imu_(std::static_pointer_cast<ProcessorImu>(_processor_ptr)), dp_preint_(_ftr_ptr->getMeasurement().head<3>()), // dp, dv, dq at preintegration time dq_preint_(_ftr_ptr->getMeasurement().data()+3), @@ -208,11 +188,7 @@ inline FactorImu::FactorImu(const FeatureImuPtr& _ftr_ptr, dDp_dwb_(_ftr_ptr->getJacobianBias().block(0,3,3,3)), dDv_dwb_(_ftr_ptr->getJacobianBias().block(6,3,3,3)), dDq_dwb_(_ftr_ptr->getJacobianBias().block(3,3,3,3)), - dt_(_ftr_ptr->getFrame()->getTimeStamp() - _cap_origin_ptr->getTimeStamp()), - ab_rate_stdev_(std::static_pointer_cast<SensorImu>(_ftr_ptr->getCapture()->getSensor())->getAbRateStdev()), - wb_rate_stdev_(std::static_pointer_cast<SensorImu>(_ftr_ptr->getCapture()->getSensor())->getWbRateStdev()), - sqrt_A_r_dt_inv((Eigen::Matrix3d::Identity() * ab_rate_stdev_ * sqrt(dt_)).inverse()), - sqrt_W_r_dt_inv((Eigen::Matrix3d::Identity() * wb_rate_stdev_ * sqrt(dt_)).inverse()) + dt_(_ftr_ptr->getFrame()->getTimeStamp() - _cap_origin_ptr->getTimeStamp()) { // } @@ -225,7 +201,6 @@ inline bool FactorImu::operator ()(const T* const _p1, const T* const _p2, const T* const _q2, const T* const _v2, - const T* const _b2, T* _res) const { using namespace Eigen; @@ -240,12 +215,10 @@ inline bool FactorImu::operator ()(const T* const _p1, Map<const Matrix<T,3,1> > p2(_p2); Map<const Quaternion<T> > q2(_q2); Map<const Matrix<T,3,1> > v2(_v2); - Map<const Matrix<T,3,1> > ab2(_b2); - Map<const Matrix<T,3,1> > wb2(_b2 + 3); Map<Matrix<T,15,1> > res(_res); - residual(p1, q1, v1, ab1, wb1, p2, q2, v2, ab2, wb2, res); + residual(p1, q1, v1, ab1, wb1, p2, q2, v2, res); return true; } @@ -264,7 +237,7 @@ Eigen::Vector9d FactorImu::error() Eigen::Vector9d delta_step; delta_step.head<3>() = dDp_dab_ * (acc_bias - acc_bias_preint_ ) + dDp_dwb_ * (gyro_bias - gyro_bias_preint_); - delta_step.segment<3>(3) = dDq_dwb_ * (gyro_bias - gyro_bias_preint_); + delta_step.segment<3>(3) = dDq_dwb_ * (gyro_bias - gyro_bias_preint_); delta_step.tail<3>() = dDv_dab_ * (acc_bias - acc_bias_preint_ ) + dDv_dwb_ * (gyro_bias - gyro_bias_preint_); Eigen::VectorXd delta_corr = imu::plus(delta_preint, delta_step); @@ -283,8 +256,6 @@ inline bool FactorImu::residual(const Eigen::MatrixBase<D1> & _p1, const Eigen::MatrixBase<D1> & _p2, const Eigen::QuaternionBase<D2> & _q2, const Eigen::MatrixBase<D1> & _v2, - const Eigen::MatrixBase<D1> & _ab2, - const Eigen::MatrixBase<D1> & _wb2, Eigen::MatrixBase<D3> & _res) const { @@ -405,13 +376,6 @@ inline bool FactorImu::residual(const Eigen::MatrixBase<D1> & _p1, #endif - // Errors between biases - Eigen::Matrix<T,3,1> ab_error(_ab1 - _ab2); // KF1.bias - KF2.bias - Eigen::Matrix<T,3,1> wb_error(_wb1 - _wb2); - - // 4. Residuals are the weighted errors - _res.segment(9,3) = sqrt_A_r_dt_inv.cast<T>() * ab_error; - _res.tail(3) = sqrt_W_r_dt_inv.cast<T>() * wb_error; ////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// PRINT VALUES /////////////////////////////////// diff --git a/include/imu/processor/processor_imu.h b/include/imu/processor/processor_imu.h index 1c03c1b41371b0fdbc412fdb3391c063c7f90c5c..0fb04fd3fe13363407da78b03d3b9bb7d05a081e 100644 --- a/include/imu/processor/processor_imu.h +++ b/include/imu/processor/processor_imu.h @@ -22,9 +22,12 @@ #ifndef PROCESSOR_IMU_H #define PROCESSOR_IMU_H -// Wolf +// Wolf Imu +#include "imu/sensor/sensor_imu.h" #include "imu/capture/capture_imu.h" #include "imu/feature/feature_imu.h" +// Wolf core + #include <core/processor/processor_motion.h> namespace wolf { @@ -82,7 +85,7 @@ class ProcessorImu : public ProcessorMotion{ ProcessorImu(ParamsProcessorImuPtr _params_motion_Imu); ~ProcessorImu() override; WOLF_PROCESSOR_CREATE(ProcessorImu, ParamsProcessorImu); - void configure(SensorBasePtr _sensor) override { }; + void configure(SensorBasePtr _sensor) override; void preProcess() override; @@ -147,8 +150,10 @@ class ProcessorImu : public ProcessorMotion{ bool recomputeStates() const; protected: - ParamsProcessorImuPtr params_motion_Imu_; - std::list<FactorBasePtr> bootstrap_factor_list_; ///< List of all IMU factors created while IMU is bootstrapping + ParamsProcessorImuPtr params_motion_Imu_; + std::list<FactorBasePtr> bootstrap_factor_list_; ///< List of all IMU factors created while IMU is bootstrapping + SensorImuPtr sensor_imu_; + Matrix6d imu_drift_cov_; }; } diff --git a/src/processor/processor_imu.cpp b/src/processor/processor_imu.cpp index b0b5c56497cadc61f0c83e0735be58952dc2dabe..45fcac1a5296a2a6edab149140fc57e7b9d4998e 100644 --- a/src/processor/processor_imu.cpp +++ b/src/processor/processor_imu.cpp @@ -26,6 +26,7 @@ // wolf #include <core/state_block/state_composite.h> +#include <core/factor/factor_block_difference.h> namespace wolf { @@ -106,25 +107,77 @@ void ProcessorImu::setCalibration (const CaptureBasePtr _capture, const VectorXd _capture->getSensorIntrinsic()->setState(_calibration); } +void ProcessorImu::configure(SensorBasePtr _sensor) +{ + sensor_imu_ = std::static_pointer_cast<SensorImu>(_sensor); + + auto acc_drift_std = sensor_imu_->getAbRateStdev(); + auto gyro_drift_std = sensor_imu_->getAbRateStdev(); + + ArrayXd imu_drift_sigmas(6); + imu_drift_sigmas << acc_drift_std, acc_drift_std, acc_drift_std, gyro_drift_std, gyro_drift_std, gyro_drift_std; + imu_drift_cov_ = imu_drift_sigmas.square().matrix().asDiagonal(); + +} void ProcessorImu::emplaceFeaturesAndFactors(CaptureBasePtr _capture_origin, CaptureMotionPtr _capture_own) { - auto feature = FeatureBase::emplace<FeatureImu>(_capture_own, - _capture_own->getBuffer().back().delta_integr_, - _capture_own->getBuffer().back().delta_integr_cov_ + unmeasured_perturbation_cov_, - _capture_own->getCalibrationPreint(), - _capture_own->getBuffer().back().jacobian_calib_); + // 1. Feature and factor Imu + //--------------------------- + + auto ftr_imu = FeatureBase::emplace<FeatureImu>( + _capture_own, _capture_own->getBuffer().back().delta_integr_, + _capture_own->getBuffer().back().delta_integr_cov_ + unmeasured_perturbation_cov_, + _capture_own->getCalibrationPreint(), _capture_own->getBuffer().back().jacobian_calib_); CaptureImuPtr cap_imu = std::static_pointer_cast<CaptureImu>(_capture_origin); - FeatureImuPtr ftr_imu = std::static_pointer_cast<FeatureImu>(feature); - auto fac_imu = FactorBase::emplace<FactorImu>(feature, ftr_imu, cap_imu, shared_from_this(), params_->apply_loss_function); + auto fac_imu = + FactorBase::emplace<FactorImu>(ftr_imu, ftr_imu, cap_imu, shared_from_this(), params_->apply_loss_function); - if (bootstrapping_) + if (bootstrapping_) { fac_imu->setStatus(FAC_INACTIVE); bootstrap_factor_list_.push_back(fac_imu); } + // 2. Feature and factor bias -- IMU bias drift for acc and gyro + //--------------------------------------------------------------- + // - This factor only if IMU biases are Dynamic (check sensor->isStateBlockDynamic('I')) + // - feature has zero measurement size 6, with the cov of the bias drift size 6x6 + // - factor relates bias(last capture) and bias(origin capture) + if (getSensor()->isStateBlockDynamic('I')) + { + const auto& sb_imubias_own = _capture_own->getStateBlock('I'); + const auto& sb_imubias_origin = _capture_origin->getStateBlock('I'); + if (sb_imubias_own != sb_imubias_origin) // make sure it's two different state blocks! -- just in case + { + auto dt = _capture_own->getTimeStamp() - _capture_origin->getTimeStamp(); + auto ftr_bias = + FeatureBase::emplace<FeatureBase>(_capture_own, "FeatureBase", + Vector6d::Zero(), // mean IMU drift is zero + imu_drift_cov_ * dt); // IMU drift cov specified in continuous time + auto fac_bias = + FactorBase::emplace<FactorBlockDifference>(ftr_bias, ftr_bias, + sb_imubias_own, // IMU bias block at t=own + sb_imubias_origin, // IMU bias block at t=origin + nullptr, // frame other + _capture_origin, // origin capture + nullptr, // feature other + nullptr, // landmark other + 0, // take all of first state block + -1, // take all of first state block + 0, // take all of first second block + -1, // take all of first second block + shared_from_this(), // this processor + params_->apply_loss_function); // loss function + + if (bootstrapping_) + { + fac_bias->setStatus(FAC_INACTIVE); + bootstrap_factor_list_.push_back(fac_bias); + } + } + } } void ProcessorImu::computeCurrentDelta(const Eigen::VectorXd& _data,