feat:给solver添加中文注释
							parent
							
								
									9bf19d5ff3
								
							
						
					
					
						commit
						3c4963d289
					
				|  | @ -7,99 +7,234 @@ | |||
| 
 | ||||
| namespace oh_my_loam { | ||||
| 
 | ||||
| // ============================================================================
 | ||||
| //                        数据结构定义
 | ||||
| // ============================================================================
 | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 点-直线匹配对数据结构 | ||||
|  * | ||||
|  * 包含一个待优化的点和对应的直线。直线由直线上任意两个点定义。 | ||||
|  */ | ||||
| struct PointLinePair { | ||||
|   TPoint pt; | ||||
|   TPoint pt;  // 待优化的点
 | ||||
| 
 | ||||
|   // 内部结构体,用于描述直线
 | ||||
|   struct Line { | ||||
|     TPoint pt1, pt2; | ||||
|     TPoint pt1, pt2;  // 定义直线的两个点
 | ||||
| 
 | ||||
|     // 默认构造函数
 | ||||
|     Line() = default; | ||||
| 
 | ||||
|     // 构造函数,根据传入的两个点构造直线
 | ||||
|     Line(const TPoint &pt1, const TPoint &pt2) : pt1(pt1), pt2(pt2) {} | ||||
|   }; | ||||
|   Line line; | ||||
| 
 | ||||
|   Line line;  // 与点对应的直线
 | ||||
| 
 | ||||
|   // 构造函数,根据点和直线结构体构造匹配对
 | ||||
|   PointLinePair(const TPoint &pt, const Line &line) : pt(pt), line(line) {} | ||||
| 
 | ||||
|   // 构造函数,根据点和直线上的两个点构造匹配对
 | ||||
|   PointLinePair(const TPoint &pt, const TPoint &pt1, const TPoint &pt2) | ||||
|       : pt(pt), line(pt1, pt2) {} | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 点-平面对匹配对数据结构 | ||||
|  * | ||||
|  * 包含一个待优化的点和对应的平面。平面由平面内任意三个点确定。 | ||||
|  */ | ||||
| struct PointPlanePair { | ||||
|   TPoint pt; | ||||
|   TPoint pt;  // 待优化的点
 | ||||
| 
 | ||||
|   // 内部结构体,用于描述平面
 | ||||
|   struct Plane { | ||||
|     TPoint pt1, pt2, pt3; | ||||
|     TPoint pt1, pt2, pt3;  // 定义平面的三个点
 | ||||
| 
 | ||||
|     // 默认构造函数
 | ||||
|     Plane() = default; | ||||
| 
 | ||||
|     // 构造函数,根据三个点构造平面
 | ||||
|     Plane(const TPoint &pt1, const TPoint &pt2, const TPoint &pt3) | ||||
|         : pt1(pt1), pt2(pt2), pt3(pt3) {} | ||||
|   }; | ||||
|   Plane plane; | ||||
| 
 | ||||
|   Plane plane;  // 与点对应的平面
 | ||||
| 
 | ||||
|   // 构造函数,根据点和平面结构体构造匹配对
 | ||||
|   PointPlanePair(const TPoint &pt, const Plane &plane) : pt(pt), plane(plane) {} | ||||
| 
 | ||||
|   // 构造函数,根据点和平面上的三个点构造匹配对
 | ||||
|   PointPlanePair(const TPoint &pt, const TPoint &pt1, const TPoint &pt2, | ||||
|                  const TPoint &pt3) | ||||
|       : pt(pt), plane(pt1, pt2, pt3) {} | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 带系数的点-直线匹配对数据结构 | ||||
|  * | ||||
|  * 包含一个待优化的点和对应的直线系数,系数存储在 6×1 的向量中, | ||||
|  * 前 3 个元素表示直线上一个点,后 3 个元素表示直线方向向量。 | ||||
|  */ | ||||
| struct PointLineCoeffPair { | ||||
|   TPoint pt; | ||||
|   Eigen::Matrix<double, 6, 1> line_coeff; | ||||
|   TPoint pt;  // 待优化的点
 | ||||
|   Eigen::Matrix<double, 6, 1> line_coeff;  // 直线系数(6维向量)
 | ||||
| 
 | ||||
|   // 构造函数,根据点和直线系数构造匹配对
 | ||||
|   PointLineCoeffPair(const TPoint &pt, | ||||
|                      const Eigen::Matrix<double, 6, 1> &line_coeff) | ||||
|       : pt(pt), line_coeff(line_coeff) {} | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 带系数的点-平面对匹配对数据结构 | ||||
|  * | ||||
|  * 包含一个待优化的点和对应的平面系数,系数存储在 4 维向量中, | ||||
|  * 通常表示平面方程 ax+by+cz+d=0 的系数。 | ||||
|  */ | ||||
| struct PointPlaneCoeffPair { | ||||
|   TPoint pt; | ||||
|   Eigen::Vector4d plane_coeff; | ||||
|   TPoint pt;  // 待优化的点
 | ||||
|   Eigen::Vector4d plane_coeff;  // 平面系数(4维向量)
 | ||||
| 
 | ||||
|   // 构造函数,根据点和平面系数构造匹配对
 | ||||
|   PointPlaneCoeffPair(const TPoint &pt, const Eigen::Vector4d &plane_coeff) | ||||
|       : pt(pt), plane_coeff(plane_coeff) {} | ||||
| }; | ||||
| 
 | ||||
| // ============================================================================
 | ||||
| //                        成本函数定义
 | ||||
| // ============================================================================
 | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 点-直线代价函数 | ||||
|  * | ||||
|  * 使用自动微分方式计算代价,用于衡量待优化点到直线的距离误差, | ||||
|  * 误差由构成直线的两个点确定。 | ||||
|  */ | ||||
| class PointLineCostFunction { | ||||
|  public: | ||||
|   // 构造函数,传入匹配对和时间因子
 | ||||
|   PointLineCostFunction(const PointLinePair &pair, double time) | ||||
|       : pair_(pair), time_(time){}; | ||||
|       : pair_(pair), time_(time) {}; | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief 重载函数调用操作符 | ||||
|    * | ||||
|    * 模板化实现,用于 Ceres 自动微分,计算当前参数下的残差。 | ||||
|    * | ||||
|    * @param r_quat 旋转部分参数(四元数,长度为4) | ||||
|    * @param t_vec 平移部分参数(向量,长度为3) | ||||
|    * @param residual 输出残差数组(3个元素) | ||||
|    * @return true 表示计算成功 | ||||
|    */ | ||||
|   template <typename T> | ||||
|   bool operator()(const T *const r_quat, const T *const t_vec, | ||||
|                   T *residual) const; | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief 静态创建函数 | ||||
|    * | ||||
|    * 创建一个自动微分类型的 Ceres 成本函数,并传入当前匹配对和时间因子。 | ||||
|    * | ||||
|    * @param pair 点-直线匹配对 | ||||
|    * @param time 时间因子,用于时间插值(运动补偿) | ||||
|    * @return ceres::CostFunction* 创建的成本函数指针 | ||||
|    */ | ||||
|   static ceres::CostFunction *Create(const PointLinePair &pair, double time) { | ||||
|     return new ceres::AutoDiffCostFunction<PointLineCostFunction, 3, 4, 3>( | ||||
|         new PointLineCostFunction(pair, time)); | ||||
|   } | ||||
| 
 | ||||
|  private: | ||||
|   PointLinePair pair_; | ||||
|   double time_; | ||||
|   PointLinePair pair_;  // 当前匹配对
 | ||||
|   double time_;         // 时间因子
 | ||||
| 
 | ||||
|   // 禁止拷贝构造函数和赋值操作(宏定义,确保对象不可复制)
 | ||||
|   DISALLOW_COPY_AND_ASSIGN(PointLineCostFunction) | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 点-平面代价函数 | ||||
|  * | ||||
|  * 使用自动微分方式计算代价,用于衡量待优化点到平面的距离误差, | ||||
|  * 平面由平面内的三个点确定。 | ||||
|  */ | ||||
| class PointPlaneCostFunction { | ||||
|  public: | ||||
|   // 构造函数,传入匹配对和时间因子
 | ||||
|   PointPlaneCostFunction(const PointPlanePair &pair, double time) | ||||
|       : pair_(pair), time_(time){}; | ||||
|       : pair_(pair), time_(time) {}; | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief 重载函数调用操作符 | ||||
|    * | ||||
|    * 模板化实现,用于计算当前参数下的残差(标量残差)。 | ||||
|    * | ||||
|    * @param r_quat 旋转四元数参数(长度为4) | ||||
|    * @param t_vec 平移向量参数(长度为3) | ||||
|    * @param residual 输出残差(单个元素) | ||||
|    * @return true 表示计算成功 | ||||
|    */ | ||||
|   template <typename T> | ||||
|   bool operator()(const T *const r_quat, const T *const t_vec, | ||||
|                   T *residual) const; | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief 静态创建函数 | ||||
|    * | ||||
|    * 创建一个自动微分类型的成本函数,用于点-平面匹配。 | ||||
|    * | ||||
|    * @param pair 点-平面对匹配对 | ||||
|    * @param time 时间因子 | ||||
|    * @return ceres::CostFunction* 成本函数指针 | ||||
|    */ | ||||
|   static ceres::CostFunction *Create(const PointPlanePair &pair, double time) { | ||||
|     return new ceres::AutoDiffCostFunction<PointPlaneCostFunction, 1, 4, 3>( | ||||
|         new PointPlaneCostFunction(pair, time)); | ||||
|   } | ||||
| 
 | ||||
|  private: | ||||
|   PointPlanePair pair_; | ||||
|   double time_; | ||||
|   PointPlanePair pair_;  // 当前匹配对
 | ||||
|   double time_;          // 时间因子
 | ||||
| 
 | ||||
|   DISALLOW_COPY_AND_ASSIGN(PointPlaneCostFunction) | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 带系数的点-直线代价函数 | ||||
|  * | ||||
|  * 用于含有额外直线系数信息的匹配对,计算待优化点到直线的距离误差。 | ||||
|  */ | ||||
| class PointLineCoeffCostFunction { | ||||
|  public: | ||||
|   // 构造函数,传入匹配对和时间因子
 | ||||
|   PointLineCoeffCostFunction(const PointLineCoeffPair &pair, double time) | ||||
|       : pair_(pair), time_(time){}; | ||||
|       : pair_(pair), time_(time) {}; | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief 重载函数调用操作符 | ||||
|    * | ||||
|    * 模板化实现,计算当前参数下的残差(3维向量残差)。 | ||||
|    * | ||||
|    * @param r_quat 旋转参数(四元数,长度为4) | ||||
|    * @param t_vec 平移参数(向量,长度为3) | ||||
|    * @param residual 输出残差(3个元素) | ||||
|    * @return true 表示计算成功 | ||||
|    */ | ||||
|   template <typename T> | ||||
|   bool operator()(const T *const r_quat, const T *const t_vec, | ||||
|                   T *residual) const; | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief 静态创建函数 | ||||
|    * | ||||
|    * 创建自动微分类型的成本函数,用于带系数的点-直线匹配。 | ||||
|    * | ||||
|    * @param pair 带系数的点-直线匹配对 | ||||
|    * @param time 时间因子 | ||||
|    * @return ceres::CostFunction* 成本函数指针 | ||||
|    */ | ||||
|   static ceres::CostFunction *Create(const PointLineCoeffPair &pair, | ||||
|                                      double time) { | ||||
|     return new ceres::AutoDiffCostFunction<PointLineCoeffCostFunction, 1, 4, 3>( | ||||
|  | @ -107,20 +242,46 @@ class PointLineCoeffCostFunction { | |||
|   } | ||||
| 
 | ||||
|  private: | ||||
|   PointLineCoeffPair pair_; | ||||
|   double time_; | ||||
|   PointLineCoeffPair pair_;  // 当前匹配对(含直线系数)
 | ||||
|   double time_;              // 时间因子
 | ||||
| 
 | ||||
|   DISALLOW_COPY_AND_ASSIGN(PointLineCoeffCostFunction) | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 带系数的点-平面代价函数 | ||||
|  * | ||||
|  * 用于含有额外平面系数信息的匹配对,计算待优化点到平面的距离误差。 | ||||
|  */ | ||||
| class PointPlaneCoeffCostFunction { | ||||
|  public: | ||||
|   // 构造函数,传入匹配对和时间因子
 | ||||
|   PointPlaneCoeffCostFunction(const PointPlaneCoeffPair &pair, double time) | ||||
|       : pair_(pair), time_(time){}; | ||||
|       : pair_(pair), time_(time) {}; | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief 重载函数调用操作符 | ||||
|    * | ||||
|    * 模板化实现,计算当前参数下的残差(标量残差)。 | ||||
|    * | ||||
|    * @param r_quat 旋转参数(四元数,长度为4) | ||||
|    * @param t_vec 平移参数(向量,长度为3) | ||||
|    * @param residual 输出残差(单个元素) | ||||
|    * @return true 表示计算成功 | ||||
|    */ | ||||
|   template <typename T> | ||||
|   bool operator()(const T *const r_quat, const T *const t_vec, | ||||
|                   T *residual) const; | ||||
| 
 | ||||
|   /**
 | ||||
|    * @brief 静态创建函数 | ||||
|    * | ||||
|    * 创建自动微分类型的成本函数,用于带系数的点-平面匹配。 | ||||
|    * | ||||
|    * @param pair 带系数的点-平面对匹配对 | ||||
|    * @param time 时间因子 | ||||
|    * @return ceres::CostFunction* 成本函数指针 | ||||
|    */ | ||||
|   static ceres::CostFunction *Create(const PointPlaneCoeffPair &pair, | ||||
|                                      double time) { | ||||
|     return new ceres::AutoDiffCostFunction<PointPlaneCoeffCostFunction, 1, 4, | ||||
|  | @ -129,78 +290,144 @@ class PointPlaneCoeffCostFunction { | |||
|   } | ||||
| 
 | ||||
|  private: | ||||
|   PointPlaneCoeffPair pair_; | ||||
|   double time_; | ||||
|   PointPlaneCoeffPair pair_;  // 当前匹配对(含平面系数)
 | ||||
|   double time_;               // 时间因子
 | ||||
| 
 | ||||
|   DISALLOW_COPY_AND_ASSIGN(PointPlaneCoeffCostFunction) | ||||
| }; | ||||
| 
 | ||||
| // ============================================================================
 | ||||
| //                        成本函数实现(模板函数)
 | ||||
| // ============================================================================
 | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 点-直线代价函数的模板实现 | ||||
|  * | ||||
|  * 对于待优化的点,先通过当前位姿(旋转和平移)对其进行变换, | ||||
|  * 然后计算变换后的点到直线(由两个点确定)的距离误差, | ||||
|  * 此误差以三维残差的形式返回(利用交叉乘积计算三角形面积后除以直线基底长度)。 | ||||
|  * | ||||
|  * @tparam T 数值类型模板参数(如 float 或 double) | ||||
|  * @param r_quat 旋转参数(四元数,长度为4) | ||||
|  * @param t_vec 平移参数(向量,长度为3) | ||||
|  * @param residual 输出残差数组(3个元素) | ||||
|  * @return true 表示计算成功 | ||||
|  */ | ||||
| template <typename T> | ||||
| bool PointLineCostFunction::operator()(const T *const r_quat, | ||||
|                                        const T *const t_vec, | ||||
|                                        T *residual) const { | ||||
|   // 提取匹配对中的点和直线上的两个点
 | ||||
|   const auto &pt = pair_.pt, &pt1 = pair_.line.pt1, &pt2 = pair_.line.pt2; | ||||
|   // 将点转换为 Eigen 向量(3维)
 | ||||
|   Eigen::Matrix<T, 3, 1> p(T(pt.x), T(pt.y), T(pt.z)); | ||||
|   Eigen::Matrix<T, 3, 1> p1(T(pt1.x), T(pt1.y), T(pt1.z)); | ||||
|   Eigen::Matrix<T, 3, 1> p2(T(pt2.x), T(pt2.y), T(pt2.z)); | ||||
| 
 | ||||
|   // 根据输入的旋转参数构造四元数,注意:Ceres中四元数存储顺序可能为 [x,y,z,w]
 | ||||
|   Eigen::Quaternion<T> r(r_quat[3], r_quat[0], r_quat[1], r_quat[2]); | ||||
|   // 构造平移向量
 | ||||
|   Eigen::Matrix<T, 3, 1> t(t_vec[0], t_vec[1], t_vec[2]); | ||||
|   if (time_ <= 1.0 - 1.0e-6) { | ||||
|   // 如果时间因子小于 1,则对旋转和平移进行插值(运动补偿)
 | ||||
|   if (time_ <= T(1.0) - T(1.0e-6)) { | ||||
|     r = Eigen::Quaternion<T>::Identity().slerp(T(time_), r); | ||||
|     t = T(time_) * t; | ||||
|   } | ||||
|   // 计算变换后的点位置
 | ||||
|   Eigen::Matrix<T, 3, 1> p0 = r * p + t; | ||||
| 
 | ||||
|   // norm of cross product: triangle area x 2
 | ||||
|   Eigen::Matrix<T, 3, 1> area = (p0 - p1).cross(p0 - p2) * 0.5; | ||||
|   // 利用交叉乘积计算三角形面积(面积 = 0.5 * |(p0-p1) x (p0-p2)|)
 | ||||
|   Eigen::Matrix<T, 3, 1> area = (p0 - p1).cross(p0 - p2) * T(0.5); | ||||
|   // 计算直线基底的长度(两点之间的距离)
 | ||||
|   T base_length = (p2 - p1).norm(); | ||||
|   // 将面积除以基底长度,即可得到点到直线的距离(与三角形高等价)
 | ||||
|   // 注意:这里残差为3维,分别保存了每个坐标轴上的误差(也可看作向量形式)
 | ||||
|   residual[0] = area[0] / base_length; | ||||
|   residual[1] = area[1] / base_length; | ||||
|   residual[2] = area[2] / base_length; | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 点-平面代价函数的模板实现 | ||||
|  * | ||||
|  * 对于待优化的点,通过当前位姿对其进行变换, | ||||
|  * 然后计算变换后的点到平面(由三个点确定)的距离, | ||||
|  * 平面法向量由三个点计算得到,残差为点到平面的距离(标量)。 | ||||
|  * | ||||
|  * @tparam T 数值类型模板参数 | ||||
|  * @param r_quat 旋转参数(长度为4的四元数) | ||||
|  * @param t_vec 平移参数(3维向量) | ||||
|  * @param residual 输出残差(单个元素) | ||||
|  * @return true 表示计算成功 | ||||
|  */ | ||||
| template <typename T> | ||||
| bool PointPlaneCostFunction::operator()(const T *const r_quat, | ||||
|                                         const T *const t_vec, | ||||
|                                         T *residual) const { | ||||
|   // 提取匹配对中的点和平面上三个点
 | ||||
|   const auto &pt = pair_.pt, &pt1 = pair_.plane.pt1, &pt2 = pair_.plane.pt2, | ||||
|              &pt3 = pair_.plane.pt3; | ||||
|   // 将各点转换为 Eigen 向量
 | ||||
|   Eigen::Matrix<T, 3, 1> p(T(pt.x), T(pt.y), T(pt.z)); | ||||
|   Eigen::Matrix<T, 3, 1> p1(T(pt1.x), T(pt1.y), T(pt1.z)); | ||||
|   Eigen::Matrix<T, 3, 1> p2(T(pt2.x), T(pt2.y), T(pt2.z)); | ||||
|   Eigen::Matrix<T, 3, 1> p3(T(pt3.x), T(pt3.y), T(pt3.z)); | ||||
| 
 | ||||
|   // 构造旋转四元数和平移向量
 | ||||
|   Eigen::Quaternion<T> r(r_quat[3], r_quat[0], r_quat[1], r_quat[2]); | ||||
|   Eigen::Matrix<T, 3, 1> t(t_vec[0], t_vec[1], t_vec[2]); | ||||
|   if (time_ <= 1.0 - 1.0e-6) { | ||||
|   // 进行运动补偿插值
 | ||||
|   if (time_ <= T(1.0) - T(1.0e-6)) { | ||||
|     r = Eigen::Quaternion<T>::Identity().slerp(T(time_), r); | ||||
|     t = T(time_) * t; | ||||
|   } | ||||
|   // 计算变换后的点位置
 | ||||
|   Eigen::Matrix<T, 3, 1> p0 = r * p + t; | ||||
| 
 | ||||
|   // 计算平面法向量:由平面内两个向量叉乘后归一化得到
 | ||||
|   Eigen::Matrix<T, 3, 1> normal = (p2 - p1).cross(p3 - p1).normalized(); | ||||
|   // 计算点到平面的距离(点与平面上一点连线与法向量的内积)
 | ||||
|   residual[0] = (p0 - p1).dot(normal); | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 带系数的点-直线代价函数的模板实现 | ||||
|  * | ||||
|  * 使用额外的直线系数信息,将系数向量分为两部分:前 3 个元素为直线上某一点, | ||||
|  * 后 3 个元素为直线方向。对待优化的点进行变换后,计算其到直线的距离误差, | ||||
|  * 该误差以3维残差输出(利用叉积计算)。 | ||||
|  * | ||||
|  * @tparam T 数值类型模板参数 | ||||
|  * @param r_quat 旋转参数(四元数,长度为4) | ||||
|  * @param t_vec 平移参数(向量,长度为3) | ||||
|  * @param residual 输出残差(3个元素) | ||||
|  * @return true 表示计算成功 | ||||
|  */ | ||||
| template <typename T> | ||||
| bool PointLineCoeffCostFunction::operator()(const T *const r_quat, | ||||
|                                             const T *const t_vec, | ||||
|                                             T *residual) const { | ||||
|   // 将待优化点转换为 Eigen 向量
 | ||||
|   Eigen::Matrix<T, 3, 1> p(T(pair_.pt.x), T(pair_.pt.y), T(pair_.pt.z)); | ||||
|   // 将直线系数转换为模板类型,并分解为直线上的一点 p1 和方向向量 dir
 | ||||
|   Eigen::Matrix<T, 6, 1> coeff = pair_.line_coeff.template cast<T>(); | ||||
|   Eigen::Matrix<T, 3, 1> p1 = coeff.topRows(3); | ||||
|   Eigen::Matrix<T, 3, 1> dir = coeff.bottomRows(3); | ||||
| 
 | ||||
|   // 构造旋转和平移参数
 | ||||
|   Eigen::Quaternion<T> r(r_quat[3], r_quat[0], r_quat[1], r_quat[2]); | ||||
|   Eigen::Matrix<T, 3, 1> t(t_vec[0], t_vec[1], t_vec[2]); | ||||
|   if (time_ <= 1.0 - 1.0e-6) { | ||||
|   // 如果时间因子小于1,则进行插值
 | ||||
|   if (time_ <= T(1.0) - T(1.0e-6)) { | ||||
|     r = Eigen::Quaternion<T>::Identity().slerp(T(time_), r); | ||||
|     t = T(time_) * t; | ||||
|   } | ||||
|   // 计算变换后的点位置
 | ||||
|   Eigen::Matrix<T, 3, 1> p0 = r * p + t; | ||||
| 
 | ||||
|   // 计算待优化点到直线的距离误差:计算 (p0-p1) 与直线方向的叉积
 | ||||
|   Eigen::Matrix<T, 3, 1> cross = (p0 - p1).cross(dir); | ||||
|   residual[0] = cross[0]; | ||||
|   residual[1] = cross[1]; | ||||
|  | @ -208,21 +435,39 @@ bool PointLineCoeffCostFunction::operator()(const T *const r_quat, | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 带系数的点-平面代价函数的模板实现 | ||||
|  * | ||||
|  * 利用传入的平面系数(4维向量,表示平面方程 ax+by+cz+d=0), | ||||
|  * 对待优化的点进行变换后计算其到平面的距离残差,残差为标量形式。 | ||||
|  * | ||||
|  * @tparam T 数值类型模板参数 | ||||
|  * @param r_quat 旋转参数(四元数,长度为4) | ||||
|  * @param t_vec 平移参数(向量,长度为3) | ||||
|  * @param residual 输出残差(单个标量) | ||||
|  * @return true 表示计算成功 | ||||
|  */ | ||||
| template <typename T> | ||||
| bool PointPlaneCoeffCostFunction::operator()(const T *const r_quat, | ||||
|                                              const T *const t_vec, | ||||
|                                              T *residual) const { | ||||
|   // 将待优化点转换为 Eigen 向量
 | ||||
|   Eigen::Matrix<T, 3, 1> p(T(pair_.pt.x), T(pair_.pt.y), T(pair_.pt.z)); | ||||
|   // 将平面系数转换为模板类型的 4 维向量
 | ||||
|   Eigen::Matrix<T, 4, 1> coeff = pair_.plane_coeff.template cast<T>(); | ||||
| 
 | ||||
|   // 构造旋转四元数和平移向量
 | ||||
|   Eigen::Quaternion<T> r(r_quat[3], r_quat[0], r_quat[1], r_quat[2]); | ||||
|   Eigen::Matrix<T, 3, 1> t(t_vec[0], t_vec[1], t_vec[2]); | ||||
|   if (time_ <= 1.0 - 1.0e-6) { | ||||
|   // 对时间因子小于1的情况进行插值
 | ||||
|   if (time_ <= T(1.0) - T(1.0e-6)) { | ||||
|     r = Eigen::Quaternion<T>::Identity().slerp(T(time_), r); | ||||
|     t = T(time_) * t; | ||||
|   } | ||||
|   // 计算变换后的点位置
 | ||||
|   Eigen::Matrix<T, 3, 1> p0 = r * p + t; | ||||
| 
 | ||||
|   // 计算点到平面的距离残差:将点 p0 代入平面方程,得到 ax+by+cz+d
 | ||||
|   residual[0] = coeff.topRows(3).transpose() * p0; | ||||
|   residual[0] += coeff(3); | ||||
|   return true; | ||||
|  |  | |||
|  | @ -8,58 +8,138 @@ | |||
| 
 | ||||
| namespace oh_my_loam { | ||||
| 
 | ||||
| // 定义一个局部变量,表示 Huber 损失的尺度参数
 | ||||
| namespace { | ||||
| double kHuberLossScale = 0.1; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief PoseSolver 构造函数 | ||||
|  * | ||||
|  * 初始化位姿求解器,传入初始位姿(包括旋转和位移),并将其复制到内部参数数组中。 | ||||
|  * 同时为 Ceres 问题添加参数块,其中旋转部分使用 Eigen 四元数参数化, | ||||
|  * 并设置 Huber 损失函数用于鲁棒优化。 | ||||
|  * | ||||
|  * @param pose 初始位姿(类型为 common::Pose3d),包含旋转(四元数)和位移向量 | ||||
|  */ | ||||
| PoseSolver::PoseSolver(const common::Pose3d &pose) { | ||||
|   // 将输入位姿的旋转部分(四元数的系数)复制到内部数组 r_quat_ 中,四元数有 4 个元素
 | ||||
|   std::copy_n(pose.r_quat().coeffs().data(), 4, r_quat_); | ||||
|   // 将输入位姿的平移向量复制到内部数组 t_vec_ 中,平移向量有 3 个元素
 | ||||
|   std::copy_n(pose.t_vec().data(), 3, t_vec_); | ||||
|   // 创建一个 Ceres 的 Huber 损失函数对象,参数 kHuberLossScale 控制损失函数的尺度
 | ||||
|   loss_function_ = new ceres::HuberLoss(kHuberLossScale); | ||||
|   problem_.AddParameterBlock(r_quat_, 4, | ||||
|                              new ceres::EigenQuaternionParameterization()); | ||||
|   // 向问题中添加旋转参数块,使用 Eigen 四元数参数化以确保单位四元数的约束
 | ||||
|   problem_.AddParameterBlock(r_quat_, 4, new ceres::EigenQuaternionParameterization()); | ||||
|   // 向问题中添加平移参数块(3个自由度)
 | ||||
|   problem_.AddParameterBlock(t_vec_, 3); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief Solve 求解器入口函数 | ||||
|  * | ||||
|  * 利用 Ceres 求解器求解当前的位姿优化问题。设定线性求解器类型、最大迭代次数等参数, | ||||
|  * 求解后更新内部的旋转和平移参数,同时将最新位姿保存到 pose 输出参数中。 | ||||
|  * | ||||
|  * @param max_iter_num 最大迭代次数 | ||||
|  * @param verbose 是否输出详细日志信息 | ||||
|  * @param pose 求解后得到的最新位姿(输出参数) | ||||
|  * @return bool 如果优化收敛则返回 true,否则返回 false | ||||
|  */ | ||||
| bool PoseSolver::Solve(int max_iter_num, bool verbose, | ||||
|                        common::Pose3d *const pose) { | ||||
|   // 配置 Ceres 求解选项
 | ||||
|   ceres::Solver::Options options; | ||||
|   options.linear_solver_type = ceres::DENSE_QR; | ||||
|   options.max_num_iterations = max_iter_num; | ||||
|   options.minimizer_progress_to_stdout = false; | ||||
|   ceres::Solver::Summary summary; | ||||
|   options.linear_solver_type = ceres::DENSE_QR;  // 使用密集 QR 分解作为线性求解器
 | ||||
|   options.max_num_iterations = max_iter_num;       // 最大迭代次数
 | ||||
|   options.minimizer_progress_to_stdout = false;    // 是否将求解进度输出到标准输出
 | ||||
|   ceres::Solver::Summary summary;                  // 用于存储求解过程和结果的摘要信息
 | ||||
|   // 调用 Ceres 求解器求解问题
 | ||||
|   ceres::Solve(options, &problem_, &summary); | ||||
|   // 如果 verbose 为 true,则输出求解摘要报告
 | ||||
|   AINFO_IF(verbose) << summary.BriefReport(); | ||||
|   // 如果 pose 非空,则将当前求解得到的旋转和平移参数构造为 common::Pose3d 对象输出
 | ||||
|   if (pose) *pose = common::Pose3d(r_quat_, t_vec_); | ||||
|   // 返回求解是否收敛的状态(Ceres 的 termination_type 为 CONVERGENCE 表示收敛)
 | ||||
|   return summary.termination_type == ceres::CONVERGENCE; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 添加点-直线匹配项 | ||||
|  * | ||||
|  * 根据输入的点-直线匹配对 pair 以及时间参数 time, | ||||
|  * 构造一个对应的代价函数(CostFunction),并将其加入到 Ceres 优化问题中。 | ||||
|  * | ||||
|  * @param pair 点-直线匹配对,包含原始点和匹配直线上的两个点 | ||||
|  * @param time 时间参数,用于对匹配代价进行时间权重调整 | ||||
|  */ | ||||
| void PoseSolver::AddPointLinePair(const PointLinePair &pair, double time) { | ||||
|   // 通过静态工厂函数创建点-直线匹配的代价函数
 | ||||
|   ceres::CostFunction *cost_function = | ||||
|       PointLineCostFunction::Create(pair, time); | ||||
|   // 将代价函数添加到问题中,设置损失函数(Huber 损失)和待优化参数(旋转和平移)
 | ||||
|   problem_.AddResidualBlock(cost_function, loss_function_, r_quat_, t_vec_); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 添加点-平面对匹配项 | ||||
|  * | ||||
|  * 根据输入的点-平面对匹配 pair 以及时间参数 time, | ||||
|  * 构造一个对应的代价函数(CostFunction),并将其加入到 Ceres 优化问题中。 | ||||
|  * | ||||
|  * @param pair 点-平面对匹配对,包含原始点和匹配平面上的三个点 | ||||
|  * @param time 时间参数,用于对匹配代价进行时间权重调整 | ||||
|  */ | ||||
| void PoseSolver::AddPointPlanePair(const PointPlanePair &pair, double time) { | ||||
|   // 创建点-平面对代价函数
 | ||||
|   ceres::CostFunction *cost_function = | ||||
|       PointPlaneCostFunction::Create(pair, time); | ||||
|   // 添加残差块到优化问题中,待优化参数为旋转和平移
 | ||||
|   problem_.AddResidualBlock(cost_function, loss_function_, r_quat_, t_vec_); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 添加带有系数信息的点-直线匹配项 | ||||
|  * | ||||
|  * 针对带有额外系数信息的点-直线匹配对,构造对应的代价函数,并加入优化问题中。 | ||||
|  * | ||||
|  * @param pair 点-直线匹配对(含系数信息) | ||||
|  * @param time 时间参数 | ||||
|  */ | ||||
| void PoseSolver::AddPointLineCoeffPair(const PointLineCoeffPair &pair, | ||||
|                                        double time) { | ||||
|   // 通过工厂函数创建带系数的点-直线代价函数
 | ||||
|   ceres::CostFunction *cost_function = | ||||
|       PointLineCoeffCostFunction::Create(pair, time); | ||||
|   // 将代价函数加入到问题中
 | ||||
|   problem_.AddResidualBlock(cost_function, loss_function_, r_quat_, t_vec_); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 添加带有系数信息的点-平面对匹配项 | ||||
|  * | ||||
|  * 针对带有额外系数信息的点-平面对匹配对,构造对应的代价函数,并加入优化问题中。 | ||||
|  * | ||||
|  * @param pair 点-平面对匹配对(含系数信息) | ||||
|  * @param time 时间参数 | ||||
|  */ | ||||
| void PoseSolver::AddPointPlaneCoeffPair(const PointPlaneCoeffPair &pair, | ||||
|                                         double time) { | ||||
|   // 创建带系数的点-平面代价函数
 | ||||
|   ceres::CostFunction *cost_function = | ||||
|       PointPlaneCoeffCostFunction::Create(pair, time); | ||||
|   // 将代价函数添加到 Ceres 问题中,优化参数为旋转和平移
 | ||||
|   problem_.AddResidualBlock(cost_function, loss_function_, r_quat_, t_vec_); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 获取当前求解的位姿 | ||||
|  * | ||||
|  * 根据内部存储的旋转和平移参数构造一个 common::Pose3d 对象, | ||||
|  * 用于返回当前的位姿估计结果。 | ||||
|  * | ||||
|  * @return common::Pose3d 当前位姿 | ||||
|  */ | ||||
| common::Pose3d PoseSolver::GetPose() const { | ||||
|   return common::Pose3d(r_quat_, t_vec_); | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue