VINS-Mono源码分析4— vins_estimator3(非线性优化)

VINS-Mono源码分析4— vins_estimator3


初始化成功完成后,程序就进入了如下所示的代码中,

if(result)
{
   
    solver_flag = NON_LINEAR;
    solveOdometry();
    slideWindow();
    f_manager.removeFailures();
    ROS_INFO("Initialization finish!");
    last_R = Rs[WINDOW_SIZE];
    last_P = Ps[WINDOW_SIZE];
    last_R0 = Rs[0];
    last_P0 = Ps[0];
    
}

solver_flag的状态置为NON_LINEAR后,就会执行后端非线性优化solveOdometry()函数和滑窗处理slideWindow()函数,并且删除特征点管理器f_manager中深度为负值的特征点,最后记录last_R、last_P、last_R0last_P0

接下来详细分析一下solveOdometry()函数,

void Estimator::solveOdometry()
{
   
    if (frame_count < WINDOW_SIZE)
        return;
    if (solver_flag == NON_LINEAR)
    {
   
        TicToc t_tri;
        f_manager.triangulate(Ps, tic, ric);
        ROS_DEBUG("triangulation costs %f", t_tri.toc());
        optimization();
    }
}

triangulate()函数在《VINS-Mono源码分析3— vins_estimator2》中已经分析过了,这里不再赘述了,不过要强调一下,这里再次调用此函数的目的是更新特征点的深度到世界坐标系下的图像帧中。接下来分析optimization()函数

ceres::Problem problem;
ceres::LossFunction *loss_function;
//loss_function = new ceres::HuberLoss(1.0);
loss_function = new ceres::CauchyLoss(1.0);

构建ceres库优化问题,定义损失函数为柯西核函数,

for (int i = 0; i < WINDOW_SIZE + 1; i++)
{
   
    ceres::LocalParameterization *local_parameterization = new PoseLocalParameterization();
    problem.AddParameterBlock(para_Pose[i], SIZE_POSE, local_parameterization);
    problem.AddParameterBlock(para_SpeedBias[i], SIZE_SPEEDBIAS); 
}
for (int i = 0; i < NUM_OF_CAM; i++)
{
   
    ceres::LocalParameterization *local_parameterization = new PoseLocalParameterization();
    problem.AddParameterBlock(para_Ex_Pose[i], SIZE_POSE, local_parameterization);
    //这里在默认情况下是执行的
    if (!ESTIMATE_EXTRINSIC)
    {
   
        ROS_DEBUG("fix extinsic param");
        problem.SetParameterBlockConstant(para_Ex_Pose[i]);
    }
    else
        ROS_DEBUG("estimate extinsic param");
}

添加参数块,包括滑窗内所有帧的位姿、IMU的速度和加计陀螺偏置信息以及IMU-相机间的外参位姿,并将IMU-相机间的外参位姿设为固定参数块。

if (ESTIMATE_TD)
{
   
    problem.AddParameterBlock(para_Td[0], 1);
}

这段代码默认不执行。

vector2double();
void Estimator::vector2double()
{
   
    ......
    VectorXd dep = f_manager.getDepthVector();
    for (int i = 0; i < f_manager.getFeatureCount(); i++)
        para_Feature[i][0] = dep(i);
    if (ESTIMATE_TD)
        para_Td[0][0] = td;
}

这段代码就是给para_Pose、para_SpeedBiaspara_Ex_Pose赋值,最重要的是得到逆深度para_Feature。其实这里我一直不太明白,按理说应该先给para_Pose、para_SpeedBiaspara_Ex_Pose赋值,然后再添加参数块才对,但不知为何这样写程序也能正常执行?

if (last_marginalization_info)
{
   
    MarginalizationFactor *marginalization_factor = new MarginalizationFactor(last_marginalization_info);
    problem.AddResidualBlock(marginalization_factor, NULL,
                             last_marginalization_parameter_blocks);
}

定义边缘化残差信息,添加边缘化残差块,注意边缘化在优化过程中只是起到了一个约束的作用。关于边缘化这部分专门写了一篇博客《VINS-Mono源码分析5— vins_estimator4》来介绍,这里就不多讲了。

for (int i = 0; i < WINDOW_SIZE; i++)
{
   
    int j = i + 1;
    //个人感觉这句代码意义不大
    if (pre_integrations[j]->sum_dt > 10.0)
        continue;
    IMUFactor* imu_factor = new IMUFactor(pre_integrations[j]);
    problem.AddResidualBlock(imu_factor, NULL, para_Pose[i], para_SpeedBias[i], para_Pose[j], para_SpeedBias[j]);
}

定义IMU残差信息,添加IMU残差块。这部分具体实现代码在factor文件夹下的IMU_factor.h文件中,

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
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值