VINS-FUSION 优化-IMU预积分因子(二)

VINS-FUSION 优化-IMU预积分因子(一)完成了IMU预积分及对于优化变量的全部雅克比矩阵的推导,本文结合VINS-FUSION源码,完成优化-IMU预积分因子的使用。

一、IMU预积分因子雅克比

VINS-FUSION源码中将优化变量分组如下:

(p_{b_{i}}^{w}, q_{b_{i}}^{w}), (v_{i}^{w}, b_{i}^{a}, b_{i}^{g}),(p_{b_{j}}^{w}, q_{b_{j}}^{w}), (v_{j}^{w}, b_{j}^{a}, b_{j}^{g})

1.对i时刻优化变量的雅可比

jacobians[0] = \begin{vmatrix} \frac{\partial r}{\partial p_{b_{i}}^{w}} & \frac{\partial r}{\partial q_{b_{i}}^{w}} \end{vmatrix} = \begin{vmatrix} \frac{\partial r_{p}}{\partial p_{b_{i}}^{w}} & \frac{\partial r_{p}}{\partial q_{b_{i}}^{w}}\\ \frac{\partial r_{q}}{\partial p_{b_{i}}^{w}} & \frac{\partial r_{q}}{\partial q_{b_{i}}^{w}}\\ \frac{\partial r_{v}}{\partial p_{b_{i}}^{w}} & \frac{\partial r_{v}}{\partial q_{b_{i}}^{w}}\\ \frac{\partial r_{b_{a}}}{\partial p_{b_{i}}^{w}} & \frac{\partial r_{b_{a}}}{\partial q_{b_{i}}^{w}}\\ \frac{\partial r_{b_{g}}}{\partial p_{b_{i}}^{w}} & \frac{\partial r_{b_{g}}}{\partial q_{b_{i}}^{w}}\\ \end{vmatrix}

                        =\begin{vmatrix} -q_{wb_{i}}^* & \frac{1}{2} \begin{vmatrix} q_{wb_{i}}^* (p_{wb_{j}} - p_{wb_{i}} - v_{i}^{w}\Delta t + \frac{1}{2}g^w\Delta t^2) \end{vmatrix} _{\times }\\ 0 & -\begin{vmatrix} (q_{wb_{j}}^* \bigotimes q_{wb_{i}}) \end{vmatrix}_{L}\begin{vmatrix} (q_{b_{i}b_{j}}) \end{vmatrix}_{R}\\ 0 & \begin{vmatrix} q_{wb_{i}}^*(v_{j}^{w} - v_{i}^{w} + g^w\Delta t) \end{vmatrix}_{\times }\\ 0 & 0\\ 0 & 0 \end{vmatrix}

jacobians[1] = \begin{vmatrix} \frac{\partial r}{\partial v_{i}^{w}} & \frac{\partial r}{\partial b_{i}^{a}} & \frac{\partial r}{\partial b_{i}^{g}} \end{vmatrix} = \begin{vmatrix} \frac{\partial r_{p}}{\partial v_{i}^{w}} & \frac{\partial r_{p}}{\partial b_{i}^{a}} & \frac{\partial r_{p}}{\partial b_{i}^{g}} \\ \frac{\partial r_{q}}{\partial v_{i}^{w}} & \frac{\partial r_{q}}{\partial b_{i}^{a}}& \frac{\partial r_{q}}{\partial b_{i}^{g}} \\ \frac{\partial r_{v}}{\partial v_{i}^{w}} & \frac{\partial r_{v}}{\partial b_{i}^{a}} & \frac{\partial r_{v}}{\partial b_{i}^{g}} \\ \frac{\partial r_{b_{a}}}{\partial v_{i}^{w}} & \frac{\partial r_{b_{a}}}{\partial b_{i}^{a}} &\frac{\partial r_{b_{a}}}{\partial b_{i}^{g}}\\ \frac{\partial r_{b_{g}}}{\partial v_{i}^{w}} & \frac{\partial r_{b_{g}}}{\partial b_{i}^{a}}& \frac{\partial r_{b_{g}}}{\partial b_{i}^{g}}\\ \end{vmatrix}

                        =\begin{vmatrix} -q_{wb_{i}}^*\Delta t & - J_{b_{i}^{a}}^{\alpha} & - J_{b_{i}^{g}}^{\alpha}\\ 0 & 0 & - (q_{wb_{j}}^*\bigotimes q_{wb_{i}} \bigotimes q_{b_{i}b_{j}})_{L} J_{b_{i}^{g}}^{\alpha}\\ -q_{wb_{i}}^* & -J_{b_{i}^{a}}^{\beta} & -J_{b_{i}^{g}}^{\beta}\\ 0 & -I & 0\\ 0 & 0& -I \end{vmatrix}

2.对j时刻优化变量的雅可比

jacobians[2] = \begin{vmatrix} \frac{\partial r}{\partial p_{b_{j}}^{w}} & \frac{\partial r}{\partial q_{b_{j}}^{w}} \end{vmatrix} = \begin{vmatrix} \frac{\partial r_{p}}{\partial p_{b_{j}}^{w}} & \frac{\partial r_{p}}{\partial q_{b_{j}}^{w}}\\ \frac{\partial r_{q}}{\partial p_{b_{j}}^{w}} & \frac{\partial r_{q}}{\partial q_{b_{j}}^{w}}\\ \frac{\partial r_{v}}{\partial p_{b_{j}}^{w}} & \frac{\partial r_{v}}{\partial q_{b_{j}}^{w}}\\ \frac{\partial r_{b_{a}}}{\partial p_{b_{j}}^{w}} & \frac{\partial r_{b_{a}}}{\partial q_{b_{j}}^{w}}\\ \frac{\partial r_{b_{g}}}{\partial p_{b_{j}}^{w}} & \frac{\partial r_{b_{g}}}{\partial q_{b_{j}}^{w}}\\ \end{vmatrix}

                        = \begin{vmatrix} q_{wb_{i}}^* & 0\\ 0& \begin{vmatrix} (q_{b_{i}b_{j}}^{*} \bigotimes q_{wb_{i}}^* \bigotimes q_{wb_{j}}) \end{vmatrix}_{L}\\ 0 & 0\\ 0 & 0\\ 0 & 0 \end{vmatrix}

jacobians[3] = \begin{vmatrix} \frac{\partial r}{\partial v_{j}^{w}} & \frac{\partial r}{\partial b_{j}^{a}} & \frac{\partial r}{\partial b_{j}^{g}} \end{vmatrix} = \begin{vmatrix} \frac{\partial r_{p}}{\partial v_{j}^{w}} & \frac{\partial r_{p}}{\partial b_{j}^{a}} & \frac{\partial r_{p}}{\partial b_{j}^{g}} \\ \frac{\partial r_{q}}{\partial v_{j}^{w}} & \frac{\partial r_{q}}{\partial b_{j}^{a}}& \frac{\partial r_{q}}{\partial b_{j}^{g}} \\ \frac{\partial r_{v}}{\partial v_{j}^{w}} & \frac{\partial r_{v}}{\partial b_{j}^{a}} & \frac{\partial r_{v}}{\partial b_{j}^{g}} \\ \frac{\partial r_{b_{a}}}{\partial v_{j}^{w}} & \frac{\partial r_{b_{a}}}{\partial b_{j}^{a}} &\frac{\partial r_{b_{a}}}{\partial b_{j}^{g}}\\ \frac{\partial r_{b_{g}}}{\partial v_{j}^{w}} & \frac{\partial r_{b_{g}}}{\partial b_{j}^{a}}& \frac{\partial r_{b_{g}}}{\partial b_{j}^{g}}\\ \end{vmatrix}

                ​​​​​​​        =\begin{vmatrix} 0 & 0& 0\\ 0 & 0& 0\\ q_{wb_{i}}^* & 0& 0\\ 0 & I& 0\\ 0 & 0& I \end{vmatrix}

二、IMU预积分因子源码

class IMUFactor : public ceres::SizedCostFunction<15, 7, 9, 7, 9> {
   public:
    IMUFactor() = delete;
    IMUFactor(IntegrationBase* _pre_integration):pre_integration(_pre_integration) {}

    virtual bool Evaluate(double const *const *parameters, double *residuals, double **jacobians) const {

        Eigen::Vector3d Pi(parameters[0][0], parameters[0][1], parameters[0][2]);
        Eigen::Quaterniond Qi(parameters[0][6], parameters[0][3], parameters[0][4], parameters[0][5]);

        Eigen::Vector3d Vi(parameters[1][0], parameters[1][1], parameters[1][2]);
        Eigen::Vector3d Bai(parameters[1][3], parameters[1][4], parameters[1][5]);
        Eigen::Vector3d Bgi(parameters[1][6], parameters[1][7], parameters[1][8]);

        Eigen::Vector3d Pj(parameters[2][0], parameters[2][1], parameters[2][2]);
        Eigen::Quaterniond Qj(parameters[2][6], parameters[2][3], parameters[2][4], parameters[2][5]);

        Eigen::Vector3d Vj(parameters[3][0], parameters[3][1], parameters[3][2]);
        Eigen::Vector3d Baj(parameters[3][3], parameters[3][4], parameters[3][5]);
        Eigen::Vector3d Bgj(parameters[3][6], parameters[3][7], parameters[3][8]);

        Eigen::Map<Eigen::Matrix<double, 15, 1>> residual(residuals);
        residual = pre_integration->evaluate(Pi, Qi, Vi, Bai, Bgi,
                                            Pj, Qj, Vj, Baj, Bgj);

        Eigen::Matrix<double, 15, 15> sqrt_info = Eigen::LLT<Eigen::Matrix<double, 15, 15>>(pre_integration->covariance.inverse()).matrixL().transpose();
        //sqrt_info.setIdentity();
        residual = sqrt_info * residual;

        if (jacobians) {
            double sum_dt = pre_integration->sum_dt;
            Eigen::Matrix3d dp_dba = pre_integration->jacobian.template block<3, 3>(O_P, O_BA);
            Eigen::Matrix3d dp_dbg = pre_integration->jacobian.template block<3, 3>(O_P, O_BG);

            Eigen::Matrix3d dq_dbg = pre_integration->jacobian.template block<3, 3>(O_R, O_BG);

            Eigen::Matrix3d dv_dba = pre_integration->jacobian.template block<3, 3>(O_V, O_BA);
            Eigen::Matrix3d dv_dbg = pre_integration->jacobian.template block<3, 3>(O_V, O_BG);

            if (pre_integration->jacobian.maxCoeff() > 1e8 || pre_integration->jacobian.minCoeff() < -1e8)
            {
                LOG(WARNING) << ("numerical unstable in preintegration");

                //std::cout << pre_integration->jacobian << std::endl;
                // ROS_BREAK();
            }

            if (jacobians[0])
            {
                Eigen::Map<Eigen::Matrix<double, 15, 7, Eigen::RowMajor>> jacobian_pose_i(jacobians[0]);
                jacobian_pose_i.setZero();

                jacobian_pose_i.block<3, 3>(O_P, O_P) = -Qi.inverse().toRotationMatrix();
                jacobian_pose_i.block<3, 3>(O_P, O_R) = Utility::skewSymmetric(Qi.inverse() * (0.5 * G * sum_dt * sum_dt + Pj - Pi - Vi * sum_dt));

#if 0
            jacobian_pose_i.block<3, 3>(O_R, O_R) = -(Qj.inverse() * Qi).toRotationMatrix();
#else
                Eigen::Quaterniond corrected_delta_q = pre_integration->delta_q * Utility::deltaQ(dq_dbg * (Bgi - pre_integration->linearized_bg));
                jacobian_pose_i.block<3, 3>(O_R, O_R) = -(Utility::Qleft(Qj.inverse() * Qi) * Utility::Qright(corrected_delta_q)).bottomRightCorner<3, 3>();
#endif

                jacobian_pose_i.block<3, 3>(O_V, O_R) = Utility::skewSymmetric(Qi.inverse() * (G * sum_dt + Vj - Vi));

                jacobian_pose_i = sqrt_info * jacobian_pose_i;

                if (jacobian_pose_i.maxCoeff() > 1e8 || jacobian_pose_i.minCoeff() < -1e8)
                {
                    LOG(WARNING) << ("numerical unstable in preintegration");
                    //std::cout << sqrt_info << std::endl;
                    //ROS_BREAK();
                }
            }
            if (jacobians[1])
            {
                Eigen::Map<Eigen::Matrix<double, 15, 9, Eigen::RowMajor>> jacobian_speedbias_i(jacobians[1]);
                jacobian_speedbias_i.setZero();
                jacobian_speedbias_i.block<3, 3>(O_P, O_V - O_V) = -Qi.inverse().toRotationMatrix() * sum_dt;
                jacobian_speedbias_i.block<3, 3>(O_P, O_BA - O_V) = -dp_dba;
                jacobian_speedbias_i.block<3, 3>(O_P, O_BG - O_V) = -dp_dbg;

                #if 0
                jacobian_speedbias_i.block<3, 3>(O_R, O_BG - O_V) = -dq_dbg;
                #else
                //Eigen::Quaterniond corrected_delta_q = pre_integration->delta_q * Utility::deltaQ(dq_dbg * (Bgi - pre_integration->linearized_bg));
                //jacobian_speedbias_i.block<3, 3>(O_R, O_BG - O_V) = -Utility::Qleft(Qj.inverse() * Qi * corrected_delta_q).bottomRightCorner<3, 3>() * dq_dbg;
                jacobian_speedbias_i.block<3, 3>(O_R, O_BG - O_V) = -Utility::Qleft(Qj.inverse() * Qi * pre_integration->delta_q).bottomRightCorner<3, 3>() * dq_dbg;
                #endif

                jacobian_speedbias_i.block<3, 3>(O_V, O_V - O_V) = -Qi.inverse().toRotationMatrix();
                jacobian_speedbias_i.block<3, 3>(O_V, O_BA - O_V) = -dv_dba;
                jacobian_speedbias_i.block<3, 3>(O_V, O_BG - O_V) = -dv_dbg;

                jacobian_speedbias_i.block<3, 3>(O_BA, O_BA - O_V) = -Eigen::Matrix3d::Identity();

                jacobian_speedbias_i.block<3, 3>(O_BG, O_BG - O_V) = -Eigen::Matrix3d::Identity();

                jacobian_speedbias_i = sqrt_info * jacobian_speedbias_i;

                //ROS_ASSERT(fabs(jacobian_speedbias_i.maxCoeff()) < 1e8);
                //ROS_ASSERT(fabs(jacobian_speedbias_i.minCoeff()) < 1e8);
            }
            if (jacobians[2])
            {
                Eigen::Map<Eigen::Matrix<double, 15, 7, Eigen::RowMajor>> jacobian_pose_j(jacobians[2]);
                jacobian_pose_j.setZero();

                jacobian_pose_j.block<3, 3>(O_P, O_P) = Qi.inverse().toRotationMatrix();

#if 0
                jacobian_pose_j.block<3, 3>(O_R, O_R) = Eigen::Matrix3d::Identity();
#else
                Eigen::Quaterniond corrected_delta_q = pre_integration->delta_q * Utility::deltaQ(dq_dbg * (Bgi - pre_integration->linearized_bg));
                jacobian_pose_j.block<3, 3>(O_R, O_R) = Utility::Qleft(corrected_delta_q.inverse() * Qi.inverse() * Qj).bottomRightCorner<3, 3>();
#endif

                jacobian_pose_j = sqrt_info * jacobian_pose_j;

                //ROS_ASSERT(fabs(jacobian_pose_j.maxCoeff()) < 1e8);
                //ROS_ASSERT(fabs(jacobian_pose_j.minCoeff()) < 1e8);
            }
            if (jacobians[3])
            {
                Eigen::Map<Eigen::Matrix<double, 15, 9, Eigen::RowMajor>> jacobian_speedbias_j(jacobians[3]);
                jacobian_speedbias_j.setZero();

                jacobian_speedbias_j.block<3, 3>(O_V, O_V - O_V) = Qi.inverse().toRotationMatrix();

                jacobian_speedbias_j.block<3, 3>(O_BA, O_BA - O_V) = Eigen::Matrix3d::Identity();

                jacobian_speedbias_j.block<3, 3>(O_BG, O_BG - O_V) = Eigen::Matrix3d::Identity();

                jacobian_speedbias_j = sqrt_info * jacobian_speedbias_j;

                //ROS_ASSERT(fabs(jacobian_speedbias_j.maxCoeff()) < 1e8);
                //ROS_ASSERT(fabs(jacobian_speedbias_j.minCoeff()) < 1e8);
            }
        }

        return true;
    }

    //bool Evaluate_Direct(double const *const *parameters, Eigen::Matrix<double, 15, 1> &residuals, Eigen::Matrix<double, 15, 30> &jacobians);

    //void checkCorrection();
    //void checkTransition();
    //void checkJacobian(double **parameters);
    IntegrationBase* pre_integration;

};

源码使用ceres解析求导:

1.构建一个继承自ceres::SizedCostFunction的类

class IMUFactor : public ceres::SizedCostFunction<15, 7, 9, 7, 9>

参数分别表示为:残差维度15,优化参数(p_{b_{i}}^{w}, q_{b_{i}}^{w})维度,优化参数(v_{i}^{w}, b_{i}^{a}, b_{i}^{g})维度,优化参数(p_{b_{j}}^{w}, q_{b_{j}}^{w})维度,优化参数(v_{j}^{w}, b_{j}^{a}, b_{j}^{g})维度。

2.重载纯虚函数

virtual bool Evaluate(double const *const *parameters, double *residuals, double **jacobians)

根据输入优化参数块,实现残差和雅克比矩阵的计算。

其中:

(1)Pi,Qi表示i帧位姿,对应(p_{b_{i}}^{w}, q_{b_{i}}^{w})

(2)Vi,Bai,Bgi表示i帧速度、加速度bias、加速度bias,对应(v_{i}^{w}, b_{i}^{a}, b_{i}^{g})

(3)Pj,Qj表示i帧位姿,对应(p_{b_{j}}^{w}, q_{b_{j}}^{w})

(4)Vj,Baj,Bgj表示i帧速度、加速度bias、加速度bias,对应(v_{j}^{w}, b_{j}^{a}, b_{j}^{g})

雅可比矩阵J_{b_{i}^{a}}^{\alpha },J_{b_{i}^{g}}^{\alpha },J_{b_{i}^{a}}^{\beta},J_{b_{i}^{g}}^{\beta},J_{b_{i}^{g}}^{q}是在预积分中实现。

3.残差求解evaluate
Eigen::Matrix<double, 15, 1> evaluate(
	const Eigen::Vector3d &Pi, const Eigen::Quaterniond &Qi, const Eigen::Vector3d &Vi, const Eigen::Vector3d &Bai, const Eigen::Vector3d &Bgi,
	const Eigen::Vector3d &Pj, const Eigen::Quaterniond &Qj, const Eigen::Vector3d &Vj, const Eigen::Vector3d &Baj, const Eigen::Vector3d &Bgj) {
	/// NOTE: xxx

	Eigen::Matrix<double, 15, 1> residuals;

	Eigen::Matrix3d dp_dba = jacobian.block<3, 3>(O_P, O_BA);
	Eigen::Matrix3d dp_dbg = jacobian.block<3, 3>(O_P, O_BG);

	Eigen::Matrix3d dq_dbg = jacobian.block<3, 3>(O_R, O_BG);

	Eigen::Matrix3d dv_dba = jacobian.block<3, 3>(O_V, O_BA);
	Eigen::Matrix3d dv_dbg = jacobian.block<3, 3>(O_V, O_BG);

	Eigen::Vector3d dba = Bai - linearized_ba;
	Eigen::Vector3d dbg = Bgi - linearized_bg;

	Eigen::Quaterniond corrected_delta_q = delta_q * Utility::deltaQ(dq_dbg * dbg);
	Eigen::Vector3d corrected_delta_v = delta_v + dv_dba * dba + dv_dbg * dbg;
	Eigen::Vector3d corrected_delta_p = delta_p + dp_dba * dba + dp_dbg * dbg;

	residuals.block<3, 1>(O_P, 0) = Qi.inverse() * (0.5 * G * sum_dt * sum_dt + Pj - Pi - Vi * sum_dt) - corrected_delta_p;
	residuals.block<3, 1>(O_R, 0) = 2 * (corrected_delta_q.inverse() * (Qi.inverse() * Qj)).vec();
	residuals.block<3, 1>(O_V, 0) = Qi.inverse() * (G * sum_dt + Vj - Vi) - corrected_delta_v;
	residuals.block<3, 1>(O_BA, 0) = Baj - Bai;
	residuals.block<3, 1>(O_BG, 0) = Bgj - Bgi;
	return residuals;
}

jacobians组成如下:

注:待优化变量如上,但实际求雅可比矩阵是用的优化变量的误差量(扰动量)。

故:dp_dba表示残差p对ba的雅可比矩阵,对应jacobians第0行9列,dp_dbg、dq_dbg、dv_dba、dv_dbg如图就很好理解了。

4.雅克比矩阵

雅克比矩阵对应小节一中IMU预积分因子雅克比公式。

5.方差矩阵

代码中sqrt_info表示信息矩阵,等于方差的逆矩阵,如下:

Eigen::Matrix<double, 15, 15> sqrt_info = Eigen::LLT<Eigen::Matrix<double, 15, 15>>(pre_integration->covariance.inverse()).matrixL().transpose();

​​​​​​​

三、参考

1.VINS-Mono: A Robust and Versatile Monocular Visual-Inertial State Estimator

2.Online Temporal Calibration for Monocular Visual-Inertial Systems

3.https://github.com/HKUST-Aerial-Robotics/VINS-Fusion

4.多传感器融合定位-基于图优化的建图方法

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值