zoukankan      html  css  js  c++  java
  • ceres关于图优化问题

    ceres关于图优化问题

      首先是图的节点,一般为位姿;再者,边代表节点与节点之间的相对变换(旋转和平移),一般是真实测量的数据,如里程计、激光雷达数据、imu数据等。如下图,三角形代表位姿、边代表测量数据;虚线代表回环检测的约束边。

    
    #include <fstream>
    #include <iostream>
    #include <map>
    #include <string>
    #include <vector>
    
    #include "angle_local_parameterization.h"
    #include "ceres/ceres.h"
    #include "common/read_g2o.h"
    #include "gflags/gflags.h"
    #include "glog/logging.h"
    #include "pose_graph_2d_error_term.h"
    #include "types.h"
    
    DEFINE_string(input, "", "The pose graph definition filename in g2o format.");
    
    namespace ceres {
    namespace examples {
    namespace {
    
    // Constructs the nonlinear least squares optimization problem from the pose
    // graph constraints.
    void BuildOptimizationProblem(const std::vector<Constraint2d>& constraints,
                                  std::map<int, Pose2d>* poses,
                                  ceres::Problem* problem) {
      CHECK(poses != NULL);
      CHECK(problem != NULL);
      if (constraints.empty()) {
        LOG(INFO) << "No constraints, no problem to optimize.";
        return;
      }
    
      ceres::LossFunction* loss_function = NULL;
      ceres::LocalParameterization* angle_local_parameterization =
          AngleLocalParameterization::Create();  //创建参数项
    
      for (std::vector<Constraint2d>::const_iterator constraints_iter =
               constraints.begin();
           constraints_iter != constraints.end();
           ++constraints_iter) 
      {
        const Constraint2d& constraint = *constraints_iter;
    
        std::map<int, Pose2d>::iterator pose_begin_iter =
            poses->find(constraint.id_begin);
        CHECK(pose_begin_iter != poses->end())
            << "Pose with ID: " << constraint.id_begin << " not found.";
        std::map<int, Pose2d>::iterator pose_end_iter =
            poses->find(constraint.id_end);
        CHECK(pose_end_iter != poses->end())
            << "Pose with ID: " << constraint.id_end << " not found.";
    
        const Eigen::Matrix3d sqrt_information =
            constraint.information.llt().matrixL();
        // Ceres will take ownership of the pointer.
        ceres::CostFunction* cost_function = PoseGraph2dErrorTerm::Create(
            constraint.x, constraint.y, constraint.yaw_radians, sqrt_information);  //传参进去
        problem->AddResidualBlock(cost_function,
                                  loss_function,
                                  &pose_begin_iter->second.x,
                                  &pose_begin_iter->second.y,
                                  &pose_begin_iter->second.yaw_radians,
                                  &pose_end_iter->second.x,
                                  &pose_end_iter->second.y,
                                  &pose_end_iter->second.yaw_radians);  //添加残差项  传入优化变量
    
        problem->SetParameterization(&pose_begin_iter->second.yaw_radians,
                                     angle_local_parameterization);
        problem->SetParameterization(&pose_end_iter->second.yaw_radians,
                                     angle_local_parameterization);
      }
    
      // The pose graph optimization problem has three DOFs that are not fully
      // constrained. This is typically referred to as gauge freedom. You can apply
      // a rigid body transformation to all the nodes and the optimization problem
      // will still have the exact same cost. The Levenberg-Marquardt algorithm has
      // internal damping which mitigate this issue, but it is better to properly
      // constrain the gauge freedom. This can be done by setting one of the poses
      // as constant so the optimizer cannot change it.
      std::map<int, Pose2d>::iterator pose_start_iter = poses->begin();
      CHECK(pose_start_iter != poses->end()) << "There are no poses.";
      problem->SetParameterBlockConstant(&pose_start_iter->second.x);
      problem->SetParameterBlockConstant(&pose_start_iter->second.y);
      problem->SetParameterBlockConstant(&pose_start_iter->second.yaw_radians);
    }
    
    // Returns true if the solve was successful.
    bool SolveOptimizationProblem(ceres::Problem* problem) {
      CHECK(problem != NULL);
    
      ceres::Solver::Options options;
      options.max_num_iterations = 100;
      options.linear_solver_type = ceres::SPARSE_NORMAL_CHOLESKY;
    
      ceres::Solver::Summary summary;
      ceres::Solve(options, problem, &summary);
    
      std::cout << summary.FullReport() << '
    ';
    
      return summary.IsSolutionUsable();
    }
    
    // Output the poses to the file with format: ID x y yaw_radians.
    bool OutputPoses(const std::string& filename,
                     const std::map<int, Pose2d>& poses) {
      std::fstream outfile;
      outfile.open(filename.c_str(), std::istream::out);
      if (!outfile) {
        std::cerr << "Error opening the file: " << filename << '
    ';
        return false;
      }
      for (std::map<int, Pose2d>::const_iterator poses_iter = poses.begin();
           poses_iter != poses.end();
           ++poses_iter) {
        const std::map<int, Pose2d>::value_type& pair = *poses_iter;
        outfile << pair.first << " " << pair.second.x << " " << pair.second.y << ' '
                << pair.second.yaw_radians << '
    ';
      }
      return true;
    }
    
    }  // namespace
    }  // namespace examples
    }  // namespace ceres
    
    int main(int argc, char** argv) {
      google::InitGoogleLogging(argv[0]);
      GFLAGS_NAMESPACE::ParseCommandLineFlags(&argc, &argv, true);
    
      CHECK(FLAGS_input != "") << "Need to specify the filename to read.";
    
      std::map<int, ceres::examples::Pose2d> poses;
      std::vector<ceres::examples::Constraint2d> constraints;
    
      CHECK(ceres::examples::ReadG2oFile(FLAGS_input, &poses, &constraints))
          << "Error reading the file: " << FLAGS_input;
    
      std::cout << "Number of poses: " << poses.size() << '
    ';
      std::cout << "Number of constraints: " << constraints.size() << '
    ';
    
      CHECK(ceres::examples::OutputPoses("poses_original.txt", poses))
          << "Error outputting to poses_original.txt";
    
      ceres::Problem problem;
      ceres::examples::BuildOptimizationProblem(constraints, &poses, &problem);
    
      CHECK(ceres::examples::SolveOptimizationProblem(&problem))
          << "The solve was not successful, exiting.";
    
      CHECK(ceres::examples::OutputPoses("poses_optimized.txt", poses))
          << "Error outputting to poses_original.txt";
    
      return 0;
    }
  • 相关阅读:
    lianjie
    分享页(把末尾的JS函数换成这个)
    面试题:Java回形数组
    Keycloak暴力检测和OTP验证
    Mybatis 使用Spring boot AOP +自定义注解+PageHelper实现分页
    基于Keycloak权限管理服务的架构
    如何访问被Keycloak保护的后端API
    KeyCloak实战|Vue项目集成Keycloak
    LeetCode|788. Rotated Digits
    LeetCode|413. Arithmetic Slices
  • 原文地址:https://www.cnblogs.com/lovebay/p/14903917.html
Copyright © 2011-2022 走看看