Lidar_imu自动标定源码阅读(四)——optimize部分

源码阅读,能力有限,如有某处理解错误,请指出,谢谢。

optimize.hpp:主要是利用ceres完成非线性优化,但是在这个cpp中只有代价函数的构造和残差的定义,以及使用自动求导,没有针对一个具体的问题展开求解

残差定义:residual=normal/transform-average

使用 Ceres Solver 求解非线性优化问题,主要包括以下几部分:

  • 【STEP 1】构建优化问题(ceres::Problem)
  • 【STEP 2】构建代价函数(ceres::CostFunction) 或残差(residual)
  • 【STEP 3】配置代价函数和损失函数(ceres::Problem::AddResidualBlock):通过 AddResidualBlock 添加代价函数(cost function)、损失函数(loss function) 和待优化状态量
  • 【STEP 4】配置求解器(ceres::Solver::Options)
  • 【STEP 5】运行求解器(ceres::Solve(options, &problem, &summary))
#pragma once

#include "ceres/ceres.h"
#include "ceres/rotation.h"
#include <eigen3/Eigen/Dense>
#include <math.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>

定义BalmVoxelEnergy1类,实现的功能:构造一个代价函数,定义残差,利用ceres的自动求导
struct BalmVoxelEnergy1 {
  //构造函数,传入参数,并完成传递
  BalmVoxelEnergy1(const Eigen::Vector3d &current_laser_point,
                   const Eigen::Vector3d &point_average,
                   const Eigen::Vector3d &normal,
                   const Eigen::Matrix4d &imu_tran)
      : current_laser_point_(current_laser_point),
        point_average_(point_average), normal_(normal), imu_tran_(imu_tran) {}
  //析构函数
  ~BalmVoxelEnergy1() {}

  //ceres代价函数需要用模板构造仿函数实现
  template <typename T>
  bool operator()(const T *const q, const T *const t, T *residual) const {
    T cur_p[3];
    cur_p[0] = T(current_laser_point_(0));
    cur_p[1] = T(current_laser_point_(1));
    cur_p[2] = T(current_laser_point_(2));
    T world_p[3];
    //给出旋转向量q,由cur_p得到world_p
    ceres::QuaternionRotatePoint(q, cur_p, world_p);
    // ceres::AngleAxisRotatePoint(q, cur_p, world_p);
    //加上平移向量,得到完整的世界坐标系下的坐标
    world_p[0] += t[0];
    world_p[1] += t[1];
    // world_p[2] += t[2];
    T tran_p[3];

    // n * (p - p_aver)
    //定义一个残差
    tran_p[0] = imu_tran_(0, 0) * world_p[0] + imu_tran_(0, 1) * world_p[1] +
                imu_tran_(0, 2) * world_p[2] + imu_tran_(0, 3) -
                point_average_[0];
    tran_p[1] = imu_tran_(1, 0) * world_p[0] + imu_tran_(1, 1) * world_p[1] +
                imu_tran_(1, 2) * world_p[2] + imu_tran_(1, 3) -
                point_average_[1];
    tran_p[2] = imu_tran_(2, 0) * world_p[0] + imu_tran_(2, 1) * world_p[1] +
                imu_tran_(2, 2) * world_p[2] + imu_tran_(2, 3) -
                point_average_[2];

    residual[0] = normal_[0] * tran_p[0] + normal_[1] * tran_p[1] +
                  normal_[2] * tran_p[2];

    return true;
  }

  static ceres::CostFunction *Create(const Eigen::Vector3d &current_laser_point,
                                     const Eigen::Vector3d &point_average,
                                     const Eigen::Vector3d &normal,
                                     const Eigen::Matrix4d &imu_tran) {
    //使用自动求导,将之前的代价函数结构体传入,第一个1是输出维度,即残差的维度,第二个是输入维度,即待寻优参数x的维度
    auto cost_function =
        new ceres::AutoDiffCostFunction<BalmVoxelEnergy1, 1, 4, 3>(
            new BalmVoxelEnergy1(current_laser_point, point_average, normal,
                                 imu_tran));
    return cost_function;
  }

  const Eigen::Vector3d current_laser_point_;
  const Eigen::Vector3d point_average_;
  const Eigen::Vector3d normal_;
  const Eigen::Matrix4d imu_tran_;
};

定义BalmVoxelEnergy2类,实现的功能:构造一个代价函数,定义残差,利用ceres的自动求导
struct BalmVoxelEnergy2 {
  //构造函数,传入参数,并完成传递
  BalmVoxelEnergy2(const Eigen::Vector3d &current_laser_point,
                   const Eigen::Vector3d &point_average,
                   const Eigen::Vector3d &normal,
                   const Eigen::Matrix4d &imu_tran,
                   const Eigen::Matrix4d &imu_tran_orig)
      : current_laser_point_(current_laser_point),
        point_average_(point_average), normal_(normal), imu_tran_(imu_tran),
        imu_tran_orig_(imu_tran_orig) {}
  //析构函数
  ~BalmVoxelEnergy2() {}

  //ceres代价函数需要用模板构造仿函数实现
  template <typename T>
  bool operator()(const T *const q, const T *const t, T *residual) const {
    T cur_p[3];
    cur_p[0] = T(current_laser_point_(0));
    cur_p[1] = T(current_laser_point_(1));
    cur_p[2] = T(current_laser_point_(2));
    T world_p[3];
    //给出旋转向量q,由cur_p得到world_p
    ceres::QuaternionRotatePoint(q, cur_p, world_p);
    // ceres::AngleAxisRotatePoint(q, cur_p, world_p);
    world_p[0] += t[0];
    world_p[1] += t[1];
    // world_p[2] += t[2];
    T tran_p[3];

    // transform point average and surface normal变换点平均和曲面法线
    T tran_point_aver[3];//变换点平均值
    T tran_normal[3];//变换正常值
    T orig_point_aver[3];//原始点平均值
    T orig_normal[3];原始正常值
    orig_point_aver[0] = T(point_average_(0));
    orig_point_aver[1] = T(point_average_(1));
    orig_point_aver[2] = T(point_average_(2));
    orig_normal[0] = T(normal_(0));
    orig_normal[1] = T(normal_(1));
    orig_normal[2] = T(normal_(2));
    //给出旋转向量q,由orig_point_aver得到tran_point_aver
    ceres::QuaternionRotatePoint(q, orig_point_aver, tran_point_aver);
    tran_point_aver[0] += t[0];
    tran_point_aver[1] += t[1];
    // tran_point_aver[2] += t[2];
    //给出旋转向量q,由orig_normal得到tran_normal
    ceres::QuaternionRotatePoint(q, orig_normal, tran_normal);
    // imu pose
    T imu_point_aver[3];//imu点平均值
    T imu_normal[3];//imu正常值
    imu_point_aver[0] = imu_tran_orig_(0, 0) * tran_point_aver[0] +
                        imu_tran_orig_(0, 1) * tran_point_aver[1] +
                        imu_tran_orig_(0, 2) * tran_point_aver[2] +
                        imu_tran_orig_(0, 3);
    imu_point_aver[1] = imu_tran_orig_(1, 0) * tran_point_aver[0] +
                        imu_tran_orig_(1, 1) * tran_point_aver[1] +
                        imu_tran_orig_(1, 2) * tran_point_aver[2] +
                        imu_tran_orig_(1, 3);
    imu_point_aver[2] = imu_tran_orig_(2, 0) * tran_point_aver[0] +
                        imu_tran_orig_(2, 1) * tran_point_aver[1] +
                        imu_tran_orig_(2, 2) * tran_point_aver[2] +
                        imu_tran_orig_(2, 3);

    imu_normal[0] = imu_tran_orig_(0, 0) * tran_normal[0] +
                    imu_tran_orig_(0, 1) * tran_normal[1] +
                    imu_tran_orig_(0, 2) * tran_normal[2];
    imu_normal[1] = imu_tran_orig_(1, 0) * tran_normal[0] +
                    imu_tran_orig_(1, 1) * tran_normal[1] +
                    imu_tran_orig_(1, 2) * tran_normal[2];
    imu_normal[2] = imu_tran_orig_(2, 0) * tran_normal[0] +
                    imu_tran_orig_(2, 1) * tran_normal[1] +
                    imu_tran_orig_(2, 2) * tran_normal[2];

    // n * (p - p_aver)定义一个残差
    tran_p[0] = imu_tran_(0, 0) * world_p[0] + imu_tran_(0, 1) * world_p[1] +
                imu_tran_(0, 2) * world_p[2] + imu_tran_(0, 3) -
                imu_point_aver[0];
    tran_p[1] = imu_tran_(1, 0) * world_p[0] + imu_tran_(1, 1) * world_p[1] +
                imu_tran_(1, 2) * world_p[2] + imu_tran_(1, 3) -
                imu_point_aver[1];
    tran_p[2] = imu_tran_(2, 0) * world_p[0] + imu_tran_(2, 1) * world_p[1] +
                imu_tran_(2, 2) * world_p[2] + imu_tran_(2, 3) -
                imu_point_aver[2];

    residual[0] = imu_normal[0] * tran_p[0] + imu_normal[1] * tran_p[1] +
                  imu_normal[2] * tran_p[2];

    return true;
  }

  static ceres::CostFunction *Create(const Eigen::Vector3d &current_laser_point,
                                     const Eigen::Vector3d &point_average,
                                     const Eigen::Vector3d &normal,
                                     const Eigen::Matrix4d &imu_tran,
                                     const Eigen::Matrix4d &imu_tran_orig) {
    //使用自动求导,将之前的代价函数结构体传入,第一个1是输出维度,即残差的维度,第二4个是输入维度,即待寻优参数x的维度
    auto cost_function =
        new ceres::AutoDiffCostFunction<BalmVoxelEnergy2, 1, 4, 3>(
            new BalmVoxelEnergy2(current_laser_point, point_average, normal,
                                 imu_tran, imu_tran_orig));
    return cost_function;
  }

  const Eigen::Vector3d current_laser_point_;
  const Eigen::Vector3d point_average_;
  const Eigen::Vector3d normal_;
  const Eigen::Matrix4d imu_tran_;
  const Eigen::Matrix4d imu_tran_orig_;
};

定义BalmVoxelEnergy2_NOT类,实现的功能:构造一个代价函数,定义残差,利用ceres的自动求导
struct BalmVoxelEnergy2_NOT {
  //构造函数,传入参数,并完成传递
  BalmVoxelEnergy2_NOT(const Eigen::Vector3d &current_laser_point,
                       const Eigen::Vector3d &point_average,
                       const Eigen::Vector3d &normal,
                       const Eigen::Matrix4d &imu_tran,
                       const Eigen::Matrix4d &imu_tran_orig)
      : current_laser_point_(current_laser_point),
        point_average_(point_average), normal_(normal), imu_tran_(imu_tran),
        imu_tran_orig_(imu_tran_orig) {}
  //析构函数
  ~BalmVoxelEnergy2_NOT() {}

  //ceres代价函数需要用模板构造仿函数实现
  template <typename T> bool operator()(const T *const q, T *residual) const {
    T cur_p[3];
    cur_p[0] = T(current_laser_point_(0));
    cur_p[1] = T(current_laser_point_(1));
    cur_p[2] = T(current_laser_point_(2));
    T world_p[3];
    ceres::QuaternionRotatePoint(q, cur_p, world_p);
    // ceres::AngleAxisRotatePoint(q, cur_p, world_p);
    T tran_p[3];

    // transform point average and surface normal变换点平均和曲面法线
    T tran_point_aver[3];//变换点平均值
    T tran_normal[3];//变换正常
    T orig_point_aver[3];//原始点平均值
    T orig_normal[3];//原始正常
    orig_point_aver[0] = T(point_average_(0));
    orig_point_aver[1] = T(point_average_(1));
    orig_point_aver[2] = T(point_average_(2));
    orig_normal[0] = T(normal_(0));
    orig_normal[1] = T(normal_(1));
    orig_normal[2] = T(normal_(2));
    //给出旋转向量q,由orig_point_aver得到tran_point_aver
    ceres::QuaternionRotatePoint(q, orig_point_aver, tran_point_aver);
    //给出旋转向量q,由orig_normal得到tran_normal
    ceres::QuaternionRotatePoint(q, orig_normal, tran_normal);
    // imu pose
    T imu_point_aver[3];//imu点平均值
    T imu_normal[3];//imu正常值
    
    imu_point_aver[0] = imu_tran_orig_(0, 0) * tran_point_aver[0] +
                        imu_tran_orig_(0, 1) * tran_point_aver[1] +
                        imu_tran_orig_(0, 2) * tran_point_aver[2] +
                        imu_tran_orig_(0, 3);
    imu_point_aver[1] = imu_tran_orig_(1, 0) * tran_point_aver[0] +
                        imu_tran_orig_(1, 1) * tran_point_aver[1] +
                        imu_tran_orig_(1, 2) * tran_point_aver[2] +
                        imu_tran_orig_(1, 3);
    imu_point_aver[2] = imu_tran_orig_(2, 0) * tran_point_aver[0] +
                        imu_tran_orig_(2, 1) * tran_point_aver[1] +
                        imu_tran_orig_(2, 2) * tran_point_aver[2] +
                        imu_tran_orig_(2, 3);

    imu_normal[0] = imu_tran_orig_(0, 0) * tran_normal[0] +
                    imu_tran_orig_(0, 1) * tran_normal[1] +
                    imu_tran_orig_(0, 2) * tran_normal[2];
    imu_normal[1] = imu_tran_orig_(1, 0) * tran_normal[0] +
                    imu_tran_orig_(1, 1) * tran_normal[1] +
                    imu_tran_orig_(1, 2) * tran_normal[2];
    imu_normal[2] = imu_tran_orig_(2, 0) * tran_normal[0] +
                    imu_tran_orig_(2, 1) * tran_normal[1] +
                    imu_tran_orig_(2, 2) * tran_normal[2];

    // n * (p - p_aver)定义残差
    tran_p[0] = imu_tran_(0, 0) * world_p[0] + imu_tran_(0, 1) * world_p[1] +
                imu_tran_(0, 2) * world_p[2] + imu_tran_(0, 3) -
                imu_point_aver[0];
    tran_p[1] = imu_tran_(1, 0) * world_p[0] + imu_tran_(1, 1) * world_p[1] +
                imu_tran_(1, 2) * world_p[2] + imu_tran_(1, 3) -
                imu_point_aver[1];
    tran_p[2] = imu_tran_(2, 0) * world_p[0] + imu_tran_(2, 1) * world_p[1] +
                imu_tran_(2, 2) * world_p[2] + imu_tran_(2, 3) -
                imu_point_aver[2];

    residual[0] = imu_normal[0] * tran_p[0] + imu_normal[1] * tran_p[1] +
                  imu_normal[2] * tran_p[2];

    return true;
  }

  static ceres::CostFunction *Create(const Eigen::Vector3d &current_laser_point,
                                     const Eigen::Vector3d &point_average,
                                     const Eigen::Vector3d &normal,
                                     const Eigen::Matrix4d &imu_tran,
                                     const Eigen::Matrix4d &imu_tran_orig) {
    //使用自动求导,将之前的代价函数结构体传入,第一个1是输出维度,即残差的维度,第二个是输入维度,即待寻优参数x的维度
    auto cost_function =
        new ceres::AutoDiffCostFunction<BalmVoxelEnergy2_NOT, 1, 4>(
            new BalmVoxelEnergy2_NOT(current_laser_point, point_average, normal,
                                     imu_tran, imu_tran_orig));
    return cost_function;
  }

  const Eigen::Vector3d current_laser_point_;
  const Eigen::Vector3d point_average_;
  const Eigen::Vector3d normal_;
  const Eigen::Matrix4d imu_tran_;
  const Eigen::Matrix4d imu_tran_orig_;
};

定义BalmVoxelEnergy3类,实现的功能:构造一个代价函数,定义残差,利用ceres的自动求导
struct BalmVoxelEnergy3 {
  //构造函数,传入参数,完成赋值
  BalmVoxelEnergy3(
      const Eigen::Vector3d &cur_laser_point,
      const Eigen::Matrix4d &cur_imu_tran,
      const std::vector<std::vector<Eigen::Vector3d> *> &orig_laser_points,
      const std::vector<pcl::PointXYZINormal> &ap_centor_origns,
      const std::vector<Eigen::Matrix4d> &imu_trans)
      : cur_laser_point_(cur_laser_point), cur_imu_tran_(cur_imu_tran),
        orig_laser_points_(orig_laser_points),
        ap_centor_origns_(ap_centor_origns), imu_trans_(imu_trans) {}
  //析构函数
  ~BalmVoxelEnergy3() {}
  //ceres代价函数需要用利用模板构建仿函数实现
  template <typename T>
  bool operator()(const T *const q, const T *const t, T *residual) const {
    T real_window_size = T(0);//实际窗口大小
    T overall_point_aver[3] = {T(0), T(0), T(0)};//全部点平均
    T overall_normal[3] = {T(0), T(0), T(0)};//全部正常
    // transform point average and surface normal变换点平均和曲面法线
    //遍历每个原始激光雷达点数据
    for (int i = 0; i < orig_laser_points_.size(); i++) {
      if (orig_laser_points_[i]->size() <= 0)
        continue;
      real_window_size += T(1);
      // int asize = current_laser_points_[i] -> size();
      T tran_point_aver[3];//变换点平均值
      T tran_normal[3];//变换正常
      T orig_point_aver[3];//原始点平均值
      T orig_normal[3];//原始正常
      orig_point_aver[0] = T(ap_centor_origns_[i].x);
      orig_point_aver[1] = T(ap_centor_origns_[i].y);
      orig_point_aver[2] = T(ap_centor_origns_[i].z);
      orig_normal[0] = T(ap_centor_origns_[i].normal_x);
      orig_normal[1] = T(ap_centor_origns_[i].normal_y);
      orig_normal[2] = T(ap_centor_origns_[i].normal_z);
      //给出旋转向量q,由orig_point_aver得到tran_point_aver
      ceres::QuaternionRotatePoint(q, orig_point_aver, tran_point_aver);
      tran_point_aver[0] += t[0];
      tran_point_aver[1] += t[1];
      // tran_point_aver[2] += t[2];
      //给出旋转向量q,由orig_normal得到tran_normal
      ceres::QuaternionRotatePoint(q, orig_normal, tran_normal);
      Eigen::Matrix4d imu_tran_orign = imu_trans_[i];

      // imu pose
      T imu_point_aver[3];//imu点平均值
      T imu_normal[3];//imu正常
      imu_point_aver[0] = imu_tran_orign(0, 0) * tran_point_aver[0] +
                          imu_tran_orign(0, 1) * tran_point_aver[1] +
                          imu_tran_orign(0, 2) * tran_point_aver[2] +
                          imu_tran_orign(0, 3);
      imu_point_aver[1] = imu_tran_orign(1, 0) * tran_point_aver[0] +
                          imu_tran_orign(1, 1) * tran_point_aver[1] +
                          imu_tran_orign(1, 2) * tran_point_aver[2] +
                          imu_tran_orign(1, 3);
      imu_point_aver[2] = imu_tran_orign(2, 0) * tran_point_aver[0] +
                          imu_tran_orign(2, 1) * tran_point_aver[1] +
                          imu_tran_orign(2, 2) * tran_point_aver[2] +
                          imu_tran_orign(2, 3);

      imu_normal[0] = imu_tran_orign(0, 0) * tran_normal[0] +
                      imu_tran_orign(0, 1) * tran_normal[1] +
                      imu_tran_orign(0, 2) * tran_normal[2];
      imu_normal[1] = imu_tran_orign(1, 0) * tran_normal[0] +
                      imu_tran_orign(1, 1) * tran_normal[1] +
                      imu_tran_orign(1, 2) * tran_normal[2];
      imu_normal[2] = imu_tran_orign(2, 0) * tran_normal[0] +
                      imu_tran_orign(2, 1) * tran_normal[1] +
                      imu_tran_orign(2, 2) * tran_normal[2];
      // add to overall point average
      overall_point_aver[0] += imu_point_aver[0];
      overall_point_aver[1] += imu_point_aver[1];
      overall_point_aver[2] += imu_point_aver[2];
      overall_normal[0] += imu_normal[0];
      overall_normal[1] += imu_normal[1];
      overall_normal[2] += imu_normal[2];
    }
    //得到全部激光雷达点云数据的均值
    overall_point_aver[0] /= real_window_size;
    overall_point_aver[1] /= real_window_size;
    overall_point_aver[2] /= real_window_size;
    overall_normal[0] /= real_window_size;
    overall_normal[1] /= real_window_size;
    overall_normal[2] /= real_window_size;

    // add residuals
    T cur_p[3];
    cur_p[0] = T(cur_laser_point_(0));
    cur_p[1] = T(cur_laser_point_(1));
    cur_p[2] = T(cur_laser_point_(2));
    T world_p[3];
    //给出旋转四元数q,由cur_p得到world_p
    ceres::QuaternionRotatePoint(q, cur_p, world_p);
    // ceres::AngleAxisRotatePoint(q, cur_p, world_p);
    world_p[0] += t[0];
    world_p[1] += t[1];
    // world_p[2] += t[2];
    T tran_p[3];

    // n * (p - p_aver)定义残差
    tran_p[0] = cur_imu_tran_(0, 0) * world_p[0] +
                cur_imu_tran_(0, 1) * world_p[1] +
                cur_imu_tran_(0, 2) * world_p[2] + cur_imu_tran_(0, 3) -
                overall_point_aver[0];
    tran_p[1] = cur_imu_tran_(1, 0) * world_p[0] +
                cur_imu_tran_(1, 1) * world_p[1] +
                cur_imu_tran_(1, 2) * world_p[2] + cur_imu_tran_(1, 3) -
                overall_point_aver[1];
    tran_p[2] = cur_imu_tran_(2, 0) * world_p[0] +
                cur_imu_tran_(2, 1) * world_p[1] +
                cur_imu_tran_(2, 2) * world_p[2] + cur_imu_tran_(2, 3) -
                overall_point_aver[2];

    residual[0] = overall_normal[0] * tran_p[0] +
                  overall_normal[1] * tran_p[1] + overall_normal[2] * tran_p[2];
    return true;
  }

  static ceres::CostFunction *
  Create(const Eigen::Vector3d &cur_laser_point,
         const Eigen::Matrix4d &cur_imu_tran,
         const std::vector<std::vector<Eigen::Vector3d> *> &orig_laser_points,
         const std::vector<pcl::PointXYZINormal> &ap_centor_origns,
         const std::vector<Eigen::Matrix4d> &imu_trans) {
    //使用自动求导,将之前的代价函数结构体传入,第一个1是输出维度,即残差的维度,第二个是输入维度,即待寻优参数x的维度
    auto cost_function =
        new ceres::AutoDiffCostFunction<BalmVoxelEnergy3, 1, 4, 3>(
            new BalmVoxelEnergy3(cur_laser_point, cur_imu_tran,
                                 orig_laser_points, ap_centor_origns,
                                 imu_trans));
    // cost_function.SetNumResiduals(point_size);
    return cost_function;
  }

  const Eigen::Vector3d cur_laser_point_;
  const Eigen::Matrix4d cur_imu_tran_;
  const std::vector<std::vector<Eigen::Vector3d> *> orig_laser_points_;
  const std::vector<pcl::PointXYZINormal> ap_centor_origns_;
  const std::vector<Eigen::Matrix4d> imu_trans_;
};

struct BalmVoxelTransEnergy {
  //构造函数,传递参数,完成赋值
  BalmVoxelTransEnergy(const Eigen::Vector3d &current_laser_point,
                       const Eigen::Vector3d &point_average,
                       const Eigen::Vector3d &normal,
                       const Eigen::Matrix4d &imu_tran,
                       const Eigen::Matrix4d &imu_tran_orig,
                       const Eigen::Matrix4d &refined_calib_mat)
      : current_laser_point_(current_laser_point),
        point_average_(point_average), normal_(normal), imu_tran_(imu_tran),
        imu_tran_orig_(imu_tran_orig), refined_calib_mat_(refined_calib_mat) {}
  //析构函数
  ~BalmVoxelTransEnergy() {}
  //ceres构造代价函数需要借助模板搭建仿函数实现
  template <typename T> bool operator()(const T *const t, T *residual) const {
    T cur_p[3];
    cur_p[0] = T(current_laser_point_(0));
    cur_p[1] = T(current_laser_point_(1));
    cur_p[2] = T(current_laser_point_(2));
    T world_p[3];
    world_p[0] = refined_calib_mat_(0, 0) * cur_p[0] +
                 refined_calib_mat_(0, 1) * cur_p[1] +
                 refined_calib_mat_(0, 2) * cur_p[2] + refined_calib_mat_(0, 3);
    world_p[1] = refined_calib_mat_(1, 0) * cur_p[0] +
                 refined_calib_mat_(1, 1) * cur_p[1] +
                 refined_calib_mat_(1, 2) * cur_p[2] + refined_calib_mat_(1, 3);
    world_p[2] = refined_calib_mat_(2, 0) * cur_p[0] +
                 refined_calib_mat_(2, 1) * cur_p[1] +
                 refined_calib_mat_(2, 2) * cur_p[2] + t[2];
    T tran_p[3];

    // transform point average and surface normal变换点平均和曲面法线
    T tran_point_aver[3];//变换点平均
    T tran_normal[3];//变换正常
    T orig_point_aver[3];//原始点平均
    T orig_normal[3];//原始正常
    orig_point_aver[0] = T(point_average_(0));
    orig_point_aver[1] = T(point_average_(1));
    orig_point_aver[2] = T(point_average_(2));
    orig_normal[0] = T(normal_(0));
    orig_normal[1] = T(normal_(1));
    orig_normal[2] = T(normal_(2));
    tran_point_aver[0] = refined_calib_mat_(0, 0) * orig_point_aver[0] +
                         refined_calib_mat_(0, 1) * orig_point_aver[1] +
                         refined_calib_mat_(0, 2) * orig_point_aver[2] +
                         refined_calib_mat_(0, 3);
    tran_point_aver[1] = refined_calib_mat_(1, 0) * orig_point_aver[0] +
                         refined_calib_mat_(1, 1) * orig_point_aver[1] +
                         refined_calib_mat_(1, 2) * orig_point_aver[2] +
                         refined_calib_mat_(1, 3);
    tran_point_aver[2] = refined_calib_mat_(2, 0) * orig_point_aver[0] +
                         refined_calib_mat_(2, 1) * orig_point_aver[1] +
                         refined_calib_mat_(2, 2) * orig_point_aver[2] + t[2];
    tran_normal[0] = refined_calib_mat_(0, 0) * orig_normal[0] +
                     refined_calib_mat_(0, 1) * orig_normal[1] +
                     refined_calib_mat_(0, 2) * orig_normal[2];
    tran_normal[1] = refined_calib_mat_(1, 0) * orig_normal[0] +
                     refined_calib_mat_(1, 1) * orig_normal[1] +
                     refined_calib_mat_(1, 2) * orig_normal[2];
    tran_normal[2] = refined_calib_mat_(2, 0) * orig_normal[0] +
                     refined_calib_mat_(2, 1) * orig_normal[1] +
                     refined_calib_mat_(2, 2) * orig_normal[2];
    // imu pose
    T imu_point_aver[3];//imu点平均
    T imu_normal[3];//imu正常
    imu_point_aver[0] = imu_tran_orig_(0, 0) * tran_point_aver[0] +
                        imu_tran_orig_(0, 1) * tran_point_aver[1] +
                        imu_tran_orig_(0, 2) * tran_point_aver[2] +
                        imu_tran_orig_(0, 3);
    imu_point_aver[1] = imu_tran_orig_(1, 0) * tran_point_aver[0] +
                        imu_tran_orig_(1, 1) * tran_point_aver[1] +
                        imu_tran_orig_(1, 2) * tran_point_aver[2] +
                        imu_tran_orig_(1, 3);
    imu_point_aver[2] = imu_tran_orig_(2, 0) * tran_point_aver[0] +
                        imu_tran_orig_(2, 1) * tran_point_aver[1] +
                        imu_tran_orig_(2, 2) * tran_point_aver[2] +
                        imu_tran_orig_(2, 3);

    imu_normal[0] = imu_tran_orig_(0, 0) * tran_normal[0] +
                    imu_tran_orig_(0, 1) * tran_normal[1] +
                    imu_tran_orig_(0, 2) * tran_normal[2];
    imu_normal[1] = imu_tran_orig_(1, 0) * tran_normal[0] +
                    imu_tran_orig_(1, 1) * tran_normal[1] +
                    imu_tran_orig_(1, 2) * tran_normal[2];
    imu_normal[2] = imu_tran_orig_(2, 0) * tran_normal[0] +
                    imu_tran_orig_(2, 1) * tran_normal[1] +
                    imu_tran_orig_(2, 2) * tran_normal[2];

    // n * (p - p_aver)定义残差
    tran_p[0] = imu_tran_(0, 0) * world_p[0] + imu_tran_(0, 1) * world_p[1] +
                imu_tran_(0, 2) * world_p[2] + imu_tran_(0, 3) -
                imu_point_aver[0];
    tran_p[1] = imu_tran_(1, 0) * world_p[0] + imu_tran_(1, 1) * world_p[1] +
                imu_tran_(1, 2) * world_p[2] + imu_tran_(1, 3) -
                imu_point_aver[1];
    tran_p[2] = imu_tran_(2, 0) * world_p[0] + imu_tran_(2, 1) * world_p[1] +
                imu_tran_(2, 2) * world_p[2] + imu_tran_(2, 3) -
                imu_point_aver[2];

    residual[0] = imu_normal[0] * tran_p[0] + imu_normal[1] * tran_p[1] +
                  imu_normal[2] * tran_p[2];

    return true;
  }

  static ceres::CostFunction *Create(const Eigen::Vector3d &current_laser_point,
                                     const Eigen::Vector3d &point_average,
                                     const Eigen::Vector3d &normal,
                                     const Eigen::Matrix4d &imu_tran,
                                     const Eigen::Matrix4d &imu_tran_orig,
                                     const Eigen::Matrix4d &refined_calib_mat) {
    //使用自动求导,将之前的代价函数结构体传入,第一个1是输出维度,即残差的维度,第二个是输入维度,即待寻优参数x的维度
    auto cost_function =
        new ceres::AutoDiffCostFunction<BalmVoxelTransEnergy, 1, 3>(
            new BalmVoxelTransEnergy(current_laser_point, point_average, normal,
                                     imu_tran, imu_tran_orig,
                                     refined_calib_mat));
    return cost_function;
  }

  const Eigen::Vector3d current_laser_point_;
  const Eigen::Vector3d point_average_;
  const Eigen::Vector3d normal_;
  const Eigen::Matrix4d imu_tran_;
  const Eigen::Matrix4d imu_tran_orig_;
  const Eigen::Matrix4d refined_calib_mat_;
};

参考连接:

参考系列2:优化库——ceres(一)快速概览_贵在坚持,不忘初心的博客-CSDN博客_ceres库1 ???? ceres快速概览基本概念对于任何一个优化问题,我们首先需要对问题进行建模,之后采用合适的优化方法,进行求解。在求解的过程中,往往需要进行梯度下降求取最优,这里涉及了导数计算。所以在代码中使用Ceres进行优化时,需要包含基本内容:建模、优化、求导方法。1.1 ????问题建模和求解1.1.1 问题建模对于形如 下 问题来说:​​这样便完成了一个优化问题的建模 !在写代码时,我们构建问题之后需要先定义代价函数,定义时需要指明求导方式,之后将残差块加入到https://blog.csdn.net/hltt3838/article/details/119774758?ops_request_misc=&request_id=&biz_id=102&utm_term=%20%20%20%20auto%20cost_function%20=%20%20%20%20%20%20&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-119774758.142%5Ev41%5Econtrol,185%5Ev2%5Econtrol&spm=1018.2226.3001.4187

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值