边缘化(marginalization )和稀疏化(sparsification)---ceres-solver

来源:互联网 发布:饥荒mac版mod 编辑:程序博客网 时间:2024/06/05 19:37

我拿港科技沈老师的VINS中的BA优化来阐述ceres-solver怎么做边缘化和稀疏化.

代码如下:

void Estimator::optimization(){    ceres::Problem problem;    ceres::LossFunction *loss_function;    //loss_function = new ceres::HuberLoss(1.0);    loss_function = new ceres::CauchyLoss(1.0);
//添加需要优化的变量(camera的pose,imu的biases)    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);    }
//添加camera和IMU的坐标变换的变量    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");    }    TicToc t_whole, t_prepare;
//把要优化的变量转成数组的形式    vector2double();//添加上一次边缘化的parameter blocks    if (last_marginalization_info)    {        // construct new marginlization_factor        MarginalizationFactor *marginalization_factor = new MarginalizationFactor(last_marginalization_info);        problem.AddResidualBlock(marginalization_factor, NULL,                                 last_marginalization_parameter_blocks);    }//添加当前sliding window中的优化变量    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]);    }    int f_m_cnt = 0;    int feature_index = -1;    for (auto &it_per_id : f_manager.feature)//遍历sliding window的帧数    {        it_per_id.used_num = it_per_id.feature_per_frame.size();//每一帧图像feature的个数        if (!(it_per_id.used_num >= 2 && it_per_id.start_frame < WINDOW_SIZE - 2))            continue;         ++feature_index;        int imu_i = it_per_id.start_frame, imu_j = imu_i - 1;                Vector3d pts_i = it_per_id.feature_per_frame[0].point;        for (auto &it_per_frame : it_per_id.feature_per_frame)//遍历每一帧图像所有features        {            imu_j++;            if (imu_i == imu_j)            {                continue;            }            Vector3d pts_j = it_per_frame.point;            ProjectionFactor *f = new ProjectionFactor(pts_i, pts_j);            problem.AddResidualBlock(f, loss_function, para_Pose[imu_i], para_Pose[imu_j], para_Ex_Pose[0], para_Feature[feature_index]);            f_m_cnt++;        }    }    relocalize = false;    //loop close factor//闭环检测,闭环这里就不说了    if(LOOP_CLOSURE)    {        int loop_constraint_num = 0;        for (int k = 0; k < (int)retrive_data_vector.size(); k++)        {                for(int i = 0; i < WINDOW_SIZE; i++)            {                if(retrive_data_vector[k].header == Headers[i].stamp.toSec())                {                    relocalize = true;                    ceres::LocalParameterization *local_parameterization = new PoseLocalParameterization();                    problem.AddParameterBlock(retrive_data_vector[k].loop_pose, SIZE_POSE, local_parameterization);                    loop_window_index = i;                    loop_constraint_num++;                    int retrive_feature_index = 0;                    int feature_index = -1;                    for (auto &it_per_id : f_manager.feature)                    {                        it_per_id.used_num = it_per_id.feature_per_frame.size();                        if (!(it_per_id.used_num >= 2 && it_per_id.start_frame < WINDOW_SIZE - 2))                            continue;                        ++feature_index;                        int start = it_per_id.start_frame;                        if(start <= i)                        {                               while(retrive_data_vector[k].features_ids[retrive_feature_index] < it_per_id.feature_id)                            {                                retrive_feature_index++;                            }                            if(retrive_data_vector[k].features_ids[retrive_feature_index] == it_per_id.feature_id)                            {                                Vector3d pts_j = Vector3d(retrive_data_vector[k].measurements[retrive_feature_index].x, retrive_data_vector[k].measurements[retrive_feature_index].y, 1.0);                                Vector3d pts_i = it_per_id.feature_per_frame[0].point;                                                                ProjectionFactor *f = new ProjectionFactor(pts_i, pts_j);                                problem.AddResidualBlock(f, loss_function, para_Pose[start], retrive_data_vector[k].loop_pose, para_Ex_Pose[0], para_Feature[feature_index]);                                                            retrive_feature_index++;                            }                             }                    }                                            }            }        }        ROS_DEBUG("loop constraint num: %d", loop_constraint_num);    }    ROS_DEBUG("visual measurement count: %d", f_m_cnt);    ROS_DEBUG("prepare for ceres: %f", t_prepare.toc());    ceres::Solver::Options options;    options.linear_solver_type = ceres::DENSE_SCHUR;//线性求解类型 为什么是Dense schur?    //options.num_threads = 2;    options.trust_region_strategy_type = ceres::DOGLEG;//信頼域类型    options.max_num_iterations = NUM_ITERATIONS;    //options.use_explicit_schur_complement = true;//选择schur    //options.minimizer_progress_to_stdout = true;    //options.use_nonmonotonic_steps = true;    if (marginalization_flag == MARGIN_OLD)        options.max_solver_time_in_seconds = SOLVER_TIME * 4.0 / 5.0;    else        options.max_solver_time_in_seconds = SOLVER_TIME;    TicToc t_solver;    ceres::Solver::Summary summary;    ceres::Solve(options, &problem, &summary);    //cout << summary.BriefReport() << endl;    ROS_DEBUG("Iterations : %d", static_cast<int>(summary.iterations.size()));    ROS_DEBUG("solver costs: %f", t_solver.toc());    // relative info between two loop frame
   if(LOOP_CLOSURE && relocalize)//计算闭环后的相对位姿    {         for (int k = 0; k < (int)retrive_data_vector.size(); k++)        {            for(int i = 0; i< WINDOW_SIZE; i++)            {                if(retrive_data_vector[k].header == Headers[i].stamp.toSec())                {                    retrive_data_vector[k].relative_pose = true;                    Matrix3d Rs_i = Quaterniond(para_Pose[i][6], para_Pose[i][3], para_Pose[i][4], para_Pose[i][5]).normalized().toRotationMatrix();                    Vector3d Ps_i = Vector3d(para_Pose[i][0], para_Pose[i][1], para_Pose[i][2]);                    Quaterniond Qs_loop;                    Qs_loop = Quaterniond(retrive_data_vector[k].loop_pose[6],  retrive_data_vector[k].loop_pose[3],  retrive_data_vector[k].loop_pose[4],  retrive_data_vector[k].loop_pose[5]).normalized().toRotationMatrix();                    Matrix3d Rs_loop = Qs_loop.toRotationMatrix();                    Vector3d Ps_loop = Vector3d( retrive_data_vector[k].loop_pose[0],  retrive_data_vector[k].loop_pose[1],  retrive_data_vector[k].loop_pose[2]);                    retrive_data_vector[k].relative_t = Rs_loop.transpose() * (Ps_i - Ps_loop);                    retrive_data_vector[k].relative_q = Rs_loop.transpose() * Rs_i;                    retrive_data_vector[k].relative_yaw = Utility::normalizeAngle(Utility::R2ypr(Rs_i).x() - Utility::R2ypr(Rs_loop).x());                    if (abs(retrive_data_vector[k].relative_yaw) > 30.0 || retrive_data_vector[k].relative_t.norm() > 20.0)                        retrive_data_vector[k].relative_pose = false;                                        }            }         }     }    double2vector();//边缘化操作    TicToc t_whole_marginalization;
//沈老师这里边缘化有两个策略,如果在sliding window中第二近的frame是关键帧则丢弃sliding window中最老的帧、否则丢弃该帧。无论丢弃哪一帧,都需要边缘化。    if (marginalization_flag == MARGIN_OLD)//丢弃老的一帧。    {        MarginalizationInfo *marginalization_info = new MarginalizationInfo();        vector2double();        if (last_marginalization_info)        {            vector<int> drop_set;            for (int i = 0; i < static_cast<int>(last_marginalization_parameter_blocks.size()); i++)            {                if (last_marginalization_parameter_blocks[i] == para_Pose[0] ||                    last_marginalization_parameter_blocks[i] == para_SpeedBias[0])                    drop_set.push_back(i);            }            // construct new marginlization_factor            MarginalizationFactor *marginalization_factor = new MarginalizationFactor(last_marginalization_info);            ResidualBlockInfo *residual_block_info = new ResidualBlockInfo(marginalization_factor, NULL,                                                                           last_marginalization_parameter_blocks,                                                                           drop_set);            marginalization_info->addResidualBlockInfo(residual_block_info);//添加上一次边缘化的变量        }        {            if (pre_integrations[1]->sum_dt < 10.0)            {                IMUFactor* imu_factor = new IMUFactor(pre_integrations[1]);                ResidualBlockInfo *residual_block_info = new ResidualBlockInfo(imu_factor, NULL,                                                                           vector<double *>{para_Pose[0], para_SpeedBias[0], para_Pose[1], para_SpeedBias[1]},                                                                           vector<int>{0, 1});                marginalization_info->addResidualBlockInfo(residual_block_info);//添加优化变量            }        }        {            int feature_index = -1;            for (auto &it_per_id : f_manager.feature)            {                it_per_id.used_num = it_per_id.feature_per_frame.size();                if (!(it_per_id.used_num >= 2 && it_per_id.start_frame < WINDOW_SIZE - 2))                    continue;                ++feature_index;                int imu_i = it_per_id.start_frame, imu_j = imu_i - 1;                if (imu_i != 0)                    continue;                Vector3d pts_i = it_per_id.feature_per_frame[0].point;                for (auto &it_per_frame : it_per_id.feature_per_frame)                {                    imu_j++;                    if (imu_i == imu_j)                        continue;                    Vector3d pts_j = it_per_frame.point;                    ProjectionFactor *f = new ProjectionFactor(pts_i, pts_j);                    ResidualBlockInfo *residual_block_info = new ResidualBlockInfo(f, loss_function,                                                                                   vector<double *>{para_Pose[imu_i], para_Pose[imu_j], para_Ex_Pose[0], para_Feature[feature_index]},                                                                                   vector<int>{0, 3});                    marginalization_info->addResidualBlockInfo(residual_block_info);//添加优化变量                }            }        }        TicToc t_pre_margin;        marginalization_info->preMarginalize();        ROS_DEBUG("pre marginalization %f ms", t_pre_margin.toc());                TicToc t_margin;        marginalization_info->marginalize();        ROS_DEBUG("marginalization %f ms", t_margin.toc());        std::unordered_map<long, double *> addr_shift;        for (int i = 1; i <= WINDOW_SIZE; i++)        {            addr_shift[reinterpret_cast<long>(para_Pose[i])] = para_Pose[i - 1];            addr_shift[reinterpret_cast<long>(para_SpeedBias[i])] = para_SpeedBias[i - 1];        }        for (int i = 0; i < NUM_OF_CAM; i++)            addr_shift[reinterpret_cast<long>(para_Ex_Pose[i])] = para_Ex_Pose[i];        vector<double *> parameter_blocks = marginalization_info->getParameterBlocks(addr_shift);        if (last_marginalization_info)            delete last_marginalization_info;        last_marginalization_info = marginalization_info;        last_marginalization_parameter_blocks = parameter_blocks;            }    else    {        if (last_marginalization_info &&            std::count(std::begin(last_marginalization_parameter_blocks), std::end(last_marginalization_parameter_blocks), para_Pose[WINDOW_SIZE - 1]))        {            MarginalizationInfo *marginalization_info = new MarginalizationInfo();            vector2double();            if (last_marginalization_info)            {                vector<int> drop_set;                for (int i = 0; i < static_cast<int>(last_marginalization_parameter_blocks.size()); i++)                {                    ROS_ASSERT(last_marginalization_parameter_blocks[i] != para_SpeedBias[WINDOW_SIZE - 1]);                    if (last_marginalization_parameter_blocks[i] == para_Pose[WINDOW_SIZE - 1])                        drop_set.push_back(i);                }                // construct new marginlization_factor                MarginalizationFactor *marginalization_factor = new MarginalizationFactor(last_marginalization_info);                ResidualBlockInfo *residual_block_info = new ResidualBlockInfo(marginalization_factor, NULL,                                                                               last_marginalization_parameter_blocks,                                                                               drop_set);                marginalization_info->addResidualBlockInfo(residual_block_info);            }            TicToc t_pre_margin;            ROS_DEBUG("begin marginalization");            marginalization_info->preMarginalize();            ROS_DEBUG("end pre marginalization, %f ms", t_pre_margin.toc());            TicToc t_margin;            ROS_DEBUG("begin marginalization");            marginalization_info->marginalize();            ROS_DEBUG("end marginalization, %f ms", t_margin.toc());                        std::unordered_map<long, double *> addr_shift;            for (int i = 0; i <= WINDOW_SIZE; i++)            {                if (i == WINDOW_SIZE - 1)                    continue;                else if (i == WINDOW_SIZE)                {                    addr_shift[reinterpret_cast<long>(para_Pose[i])] = para_Pose[i - 1];                    addr_shift[reinterpret_cast<long>(para_SpeedBias[i])] = para_SpeedBias[i - 1];                }                else                {                    addr_shift[reinterpret_cast<long>(para_Pose[i])] = para_Pose[i];                    addr_shift[reinterpret_cast<long>(para_SpeedBias[i])] = para_SpeedBias[i];                }            }            for (int i = 0; i < NUM_OF_CAM; i++)                addr_shift[reinterpret_cast<long>(para_Ex_Pose[i])] = para_Ex_Pose[i];            vector<double *> parameter_blocks = marginalization_info->getParameterBlocks(addr_shift);            if (last_marginalization_info)                delete last_marginalization_info;            last_marginalization_info = marginalization_info;            last_marginalization_parameter_blocks = parameter_blocks;                    }    }    ROS_DEBUG("whole marginalization costs: %f", t_whole_marginalization.toc());        ROS_DEBUG("whole time for ceres: %f", t_whole.toc());}


原创粉丝点击